//*****************************************************************************************************
//*** Author:     Ruediger von Creytz     ruediger.creytz@globalbit.net                             ***
//*** Copyright:  globalBIT, LLC          http://www.globalbit.net                                  ***
//*** Version:    20080709                                                                          ***
//*****************************************************************************************************


//*****************************************************************************************************
//*** Implement following lines into the head of your template: ***************************************
//*****************************************************************************************************
/*

<script src="JS/dropdown.js" type="text/javascript"></script>

*/
//*****************************************************************************************************
//*** Implement following lines into the very end of your template's body: ****************************
//*****************************************************************************************************
/*

<script type="text/javascript">
  <!--
    selectToListbox('ACTUAL_SELECTBOX_ID');
  //-->
</script>

*/
//*****************************************************************************************************
//*****************************************************************************************************

var listboxBgColor = "#ffffff";
var listboxBorderColor = "#999999";
var listboxButtonBgColor = "#dddddd";
var listboxButtonImage = "arrow_down_16x16.gif";
var listboxColor = "#000000";
var listboxCursor = '';
var listboxFocusedBgColor = "#0a246a";
var listboxFocusedColor = "#ffffff";
var listboxFocusedID = "";
var listboxFocusedNum = "";
var listboxFontFamily = "sans-serif";
var listboxFontSize = 12;
var listboxHeight = 18;
var listboxMouseover = false;
var listboxTimer = false;
var listboxScrollTimer = false;
var listboxes = new Array();

if(window.event) {
  listboxCursor = 'hand';
}
else {
  listboxCursor = 'pointer';
}

//*****************************************************************************************************

/**
 * Avoids doing the browser's default actions.
 * @param event The event to avoid.
 * @return FALSE.
 */
function getFalseListbox(event) {
  if(event.preventDefault)
    event.preventDefault();
  if(event.returnValue)
    event.returnValue = false;
  return false;
}

//*****************************************************************************************************

/**
 * Returns the focused listbox entry.
 * @param id ID of the listbox to make sure the program is working on the correct one.
 * @return Number of the focused listbox entry or NULL.
 */
function getFocusedListbox(id) {
  if(getListbox(id) == null)
    return null;
  if(listboxFocusedID == id)
    return listboxFocusedNum;
  else
    return null;
}

//*****************************************************************************************************

/**
 * Returns all parameters for one listbox in an array.
 * @param id ID of the listbox.
 * @return An array with all parameters of one listbox or NULL.
 */ 
function getListbox(id) {
  if(id == null || id == "")
    return null;
  for(var i=0; i<listboxes.length; i++) {
    if(listboxes[i][0] == id)
      return listboxes[i];
  }
  return null;
}

//*****************************************************************************************************

/**
 * Returns the key for the selected value.
 * @param id ID of the listbox.
 * @return The key for the selected value or an empty string.
 */
function getListboxSelectedKey(id) {
  var listbox = getListbox(id);
  if(listbox == null)
    return null;
  var value = document.getElementById(id + '-value').value;
  for(var i=0; i<listbox[1].length; i++) {
    if(listbox[1][i][1] == value)
      return listbox[1][i][0];
  }
  return "";
}

//*****************************************************************************************************

/**
 * Returns the selected value.
 * @param id ID of the listbox.
 * @return The selected value.
 */
function getListboxSelectedValue(id) {
  var listbox = getListbox(id);
  if(listbox == null)
    return null;
  var value = document.getElementById(id + '-value').value;
  while(value.charAt(0) == ' ')
    value = value.substring(1, value.length);
  while(value.charAt(value.length-1) == ' ')
    value = value.substring(0, value.length-1);
  while(value.indexOf('  ') >= 0)
    value = value.replace(/\ \ /g, ' ');
  for(var i=0; i<listbox[1].length; i++) {
    if(listbox[1][i][1].toLowerCase() == value.toLowerCase())
      return listbox[1][i][1];
  }
  return value;
}

//*****************************************************************************************************

/**
 * Returns the number of the first occurence of an entry's value begining with FIRSTCHAR.
 * @param id ID of the listbox.
 * @param firstchar First character of an entry's value to look for.
 * @return Number of a found entry or NULL.
 */
function getListboxNumByFirstValueChar(id, firstChar) {
  var listbox = getListbox(id);
  if(listbox == null)
    return null;
  for(var i=0; i<listbox[1].length; i++) {
    var value = listbox[1][i][1].toLowerCase();
    if(value.length > 0 && value.charAt(0) == firstChar)
      return i;
  }
  return null;
}

//*****************************************************************************************************

/**
 * Returns the number of the selected entry.
 * @param id ID of the listbox.
 * @return Number of the selected entry or '0'.
 */
function getListboxSelectedNum(id) {
  var listbox = getListbox(id);
  if(listbox == null)
    return null;
  var value = document.getElementById(id + '-value').value;
  for(var i=0; i<listbox[1].length; i++) {
    if(listbox[1][i][1] == value)
      return i;
  }
  return 0;
}

//*****************************************************************************************************

/**
 * Hides the listbox entries.
 * @param id ID of the listbox.
 */
function hideListbox(id) {
  if(getListbox(id) == null)
    return;
  var theDiv = document.getElementById(id);
  theDiv.style.display = "none";
  theDiv.style.visibility = "hidden";
  unsetFocusedListbox(id);
}

//*****************************************************************************************************

/**
 * For the event ONBLUR.
 * @param id ID of the listbox.
 * @return TRUE if possible otherwise FALSE.
 */
function onblurListbox(id) {
  if(getListbox(id) == null)
    return false;
  listboxTimer = window.setTimeout("onblurListboxDelayed('" + id + "', false)", 5);
  return true;
}

//*****************************************************************************************************

/**
 * To do delayed by event ONBLUR.
 * @param id ID of the listbox.
 * @param returnKey FALSE if mouse must be over an entry for setting the entry as selected.
 */
function onblurListboxDelayed(id, returnKey) {
  if(getListbox(id) == null)
    return;
  if(getFocusedListbox(id) == null || (!returnKey && !listboxMouseover))
    hideListbox(id);
  else
    setListbox(id, getFocusedListbox(id));
  listboxMouseover = false;
}

//*****************************************************************************************************

/**
 * For the event ONCHANGE of the text input field.
 * @param id ID of the listbox.
 */
function onchangeListbox(id) {
  if(getListbox(id) == null)
    return;
  document.getElementById(id + '-value').value = getListboxSelectedValue(id);
  document.getElementById(id + '-key').value = getListboxSelectedKey(id);
}

//*****************************************************************************************************

/**
 * For the event ONKEYDOWN of the text input field.
 * @param event The browser event.
 * @param id ID of the listbox.
 * @return FALSE.
 */
function onkeydownListbox(event, id) {
  var listbox = getListbox(id);
  if(listbox == null)
    return false;
  listboxTimer = false;
  var theNum = null;
  var theKeyCode;
  if(window.captureEvents)
    theKeyCode = event.which;
  else
    theKeyCode = event.keyCode;
  switch(theKeyCode) {
    case 13:   //return
      if(!listboxScrollTimer) {
        if(document.addEventListener) {
          document.addEventListener("keydown", getFalseListbox, false);
          document.addEventListener("keypress", getFalseListbox, false);
          document.addEventListener("keyup", getFalseListbox, false);
        }
        if(document.attachEvent)
          document.attachEvent("onkeydown", getFalseListbox);
        listboxScrollTimer = window.setTimeout("scrollTopListBox('"
        + window.document.documentElement.scrollTop + "')", 10);
        if(getFocusedListbox(id) == null)
          toggleListbox(id);
        else
          onblurListboxDelayed(id, true);
      }
      break;
    case 16:   //shift
      break;
    case 27:   //esc
      hideListbox(id);
      break;
    case 32:   //space
      break;
    case 38:   //arrow up
      if(!listboxScrollTimer) {
        if(document.addEventListener) {
          document.addEventListener("keydown", getFalseListbox, false);
          document.addEventListener("keypress", getFalseListbox, false);
          document.addEventListener("keyup", getFalseListbox, false);
        }
        if(document.attachEvent)
          document.attachEvent("onkeydown", getFalseListbox);
        listboxScrollTimer = window.setTimeout("scrollTopListBox('"
        + window.document.documentElement.scrollTop + "')", 10);
        if(getFocusedListbox(id) == null)
          toggleListbox(id);
        else {
          listboxFocusedNum--;
          if(listboxFocusedNum < 0)
            listboxFocusedNum++;
          onmouseoverListbox(id, listboxFocusedNum);
        }
      }
      break;
    case 40:   //arrow down
      if(!listboxScrollTimer) {
        if(document.addEventListener) {
          document.addEventListener("keydown", getFalseListbox, false);
          document.addEventListener("keypress", getFalseListbox, false);
          document.addEventListener("keyup", getFalseListbox, false);
        }
        if(document.attachEvent)
          document.attachEvent("onkeydown", getFalseListbox);
        listboxScrollTimer = window.setTimeout("scrollTopListBox('"
        + window.document.documentElement.scrollTop + "')", 10);
        if(getFocusedListbox(id) == null)
          toggleListbox(id);
        else {
          listboxFocusedNum++;
          if(listboxFocusedNum >= listbox[1].length)
            listboxFocusedNum--;
          onmouseoverListbox(id, listboxFocusedNum);
        }
      }
      break;
    case 65:   //a
      if(theNum == null)
        theNum = getListboxNumByFirstValueChar(id, "a");
    case 66:   //b
      if(theNum == null)
        theNum = getListboxNumByFirstValueChar(id, "b");
    case 67:   //c
      if(theNum == null)
        theNum = getListboxNumByFirstValueChar(id, "c");
    case 68:   //d
      if(theNum == null)
        theNum = getListboxNumByFirstValueChar(id, "d");
    case 69:   //e
      if(theNum == null)
        theNum = getListboxNumByFirstValueChar(id, "e");
    case 70:   //f
      if(theNum == null)
        theNum = getListboxNumByFirstValueChar(id, "f");
    case 71:   //g
      if(theNum == null)
        theNum = getListboxNumByFirstValueChar(id, "g");
    case 72:   //h
      if(theNum == null)
        theNum = getListboxNumByFirstValueChar(id, "h");
    case 73:   //i
      if(theNum == null)
        theNum = getListboxNumByFirstValueChar(id, "i");
    case 74:   //j
      if(theNum == null)
        theNum = getListboxNumByFirstValueChar(id, "j");
    case 75:   //k
      if(theNum == null)
        theNum = getListboxNumByFirstValueChar(id, "k");
    case 76:   //l
      if(theNum == null)
        theNum = getListboxNumByFirstValueChar(id, "l");
    case 77:   //m
      if(theNum == null)
        theNum = getListboxNumByFirstValueChar(id, "m");
    case 78:   //n
      if(theNum == null)
        theNum = getListboxNumByFirstValueChar(id, "n");
    case 79:   //o
      if(theNum == null)
        theNum = getListboxNumByFirstValueChar(id, "o");
    case 80:   //p
      if(theNum == null)
        theNum = getListboxNumByFirstValueChar(id, "p");
    case 81:   //q
      if(theNum == null)
        theNum = getListboxNumByFirstValueChar(id, "q");
    case 82:   //r
      if(theNum == null)
        theNum = getListboxNumByFirstValueChar(id, "r");
    case 83:   //s
      if(theNum == null)
        theNum = getListboxNumByFirstValueChar(id, "s");
    case 84:   //t
      if(theNum == null)
        theNum = getListboxNumByFirstValueChar(id, "t");
    case 85:   //u
      if(theNum == null)
        theNum = getListboxNumByFirstValueChar(id, "u");
    case 86:   //v
      if(theNum == null)
        theNum = getListboxNumByFirstValueChar(id, "v");
    case 87:   //w
      if(theNum == null)
        theNum = getListboxNumByFirstValueChar(id, "w");
    case 88:   //x
      if(theNum == null)
        theNum = getListboxNumByFirstValueChar(id, "x");
    case 89:   //y
      if(theNum == null)
        theNum = getListboxNumByFirstValueChar(id, "y");
    case 90:   //z
      if(theNum == null)
        theNum = getListboxNumByFirstValueChar(id, "z");
  }
  if(theNum != null)
    onmouseoverListbox(id, theNum);
  return false;
}

//*****************************************************************************************************

/**
 * For the event ONMOUSEOUT.
 * @param id ID of the listbox.
 * @param num Number of the focused entry.
 * @return TRUE.
 */
function onmouseoutListbox(id, num) {
  if(getListbox(id) == null)
    return true;
  listboxMouseover = false;
  return true;
}

//*****************************************************************************************************

/**
 * For the event ONMOUSEOVER.
 * @param id ID of the listbox.
 * @param num Number of the focused entry.
 * @return TRUE.
 */
function onmouseoverListbox(id, num) {
  listboxTimer = false;
  if(getListbox(id) == null)
    return true;
  unsetFocusedListbox(id);
  if(getFocusedListbox(id) != "")
    onmouseoutListbox(id, getFocusedListbox(id));
  var theOption = document.getElementById(id+"-option"+num);
  theOption.style.backgroundColor = listboxFocusedBgColor;
  theOption.style.color = listboxFocusedColor;
  setFocusedListbox(id, num);
  listboxMouseover = true;
  return true;
}

//*****************************************************************************************************

/**
 * Opens the entries for the listbox under text input field and button.
 * @param id ID of the listbox.
 */
function openListboxDown(id) {
  var theBox = document.getElementById(id+"-box");
  var theDiv = document.getElementById(id);
  var theTab = document.getElementById(id+"-tab");
  theDiv.style.display = "block";
  if(theTab.style.borderTopWidth == "1px") {
    theTab.style.borderTopWidth = "0px";
    theTab.style.borderBottomWidth = "1px";
    if(window.event) {
      theDiv.style.top = theDiv.offsetTop + theBox.offsetHeight + theDiv.offsetHeight;
    }
    else
      theDiv.style.top = (theDiv.offsetTop + theBox.offsetHeight + theDiv.offsetHeight) + 'px';
  }
  theDiv.style.visibility = 'visible';
}

//*****************************************************************************************************

/**
 * Opens the entries for the listbox over text input field and button.
 * @param id ID of the listbox.
 */
function openListboxUp(id) {
  var theBox = document.getElementById(id+"-box");
  var theDiv = document.getElementById(id);
  var theTab = document.getElementById(id+"-tab");
  theDiv.style.display = "block";
  if(theTab.style.borderBottomWidth != "0px") {
    theTab.style.borderTopWidth = "1px";
    theTab.style.borderBottomWidth = "0px";
    if(window.event)
      theDiv.style.top = theDiv.offsetTop - theBox.offsetHeight - theDiv.offsetHeight;
    else
      theDiv.style.top = (theDiv.offsetTop - theBox.offsetHeight - theDiv.offsetHeight) + 'px';
  }
  theDiv.style.visibility = 'visible';
}

//*****************************************************************************************************

/**
 * Avoids the default scrolling of the browser.
 * @param scroll
 */
function scrollTopListBox(scroll) {
  window.document.documentElement.scrollTop = scroll;
  if(document.removeEventListener) {
    document.removeEventListener("keydown", getFalseListbox, false);
    document.removeEventListener("keypress", getFalseListbox, false);
    document.removeEventListener("keyup", getFalseListbox, false);
  }
  if(document.detachEvent)
    document.detachEvent("onkeydown", getFalseListbox);
  listboxScrollTimer = false;
}

//*****************************************************************************************************

/**
 * Builds the HTML-code for a new listbox and replaces a select box with it.
 * @param id ID of select box and new listbox.
 * @param width Width of the select box in px as number.
 */
function selectToListbox(id, width) {
  if(id == null || id == "")
    return;
  var listbox = new Array();
  var oldSelect = document.getElementById(id);
  var theParent = oldSelect.parentNode;
  var theOptions = new Array();
  var theOption;
  var oldOptions = oldSelect.getElementsByTagName("option");
  var oldOption;
  var selectedValue = "";
  var selectedData = "";
  width = width + 4;
  listbox[0] = id;
  for(var i=0; i<oldOptions.length; i++) {
    oldOption = oldOptions[i];
    theOption = new Array();
    theOption[0] = oldOption.value;
    theOption[1] = oldOption.firstChild.data;
    theOption[2] = oldOption.selected;
    if(oldOption.selected) {
      selectedValue = oldOption.value;
      selectedData = oldOption.firstChild.data;
    }
    theOptions[theOptions.length] = theOption;
  }
  listbox[1] = theOptions;
  var htmlString = ''
  + '<table border="0" cellpadding="0" cellspacing="0"'
  +   ' style="border-spacing:0px;height:'+listboxHeight+'px;padding:0px">'
  +   '<tr>'
  +     '<td style="border-spacing:0px;height:'+listboxHeight+'px;overflow:visible;padding:0px">'
  +       '<table border="0"'
  +         ' cellpadding="0"'
  +         ' cellspacing="1"'
  +         ' id="'+id+'-box"'
  +         ' style="background-color:'+listboxBorderColor+';border-spacing:1px;padding:0px">'
  +         '<tr>'
  +           '<td style="background-color:'+listboxBgColor+';border-spacing:0px;'
  +             'height:'+(listboxHeight-2)+'px;padding:0px;vertical-align:middle">'
  +             '<div style="overflow:hidden;height:'+(listboxHeight-2)+'px">'
  +               '<input id="' + id + '-value"'
  +                 ' name="' + id + '-value"'
  +                 ' onchange="onchangeListbox(' + "'" + id + "'" +')"'
  +                 ' style="background-color:'+listboxBgColor+';border:0px;color:'+listboxColor+';'
  +                   'font-family:'+listboxFontFamily+';font-size:'+listboxFontSize+'px;'
  +                   'height:'+(listboxHeight-2)+'px;width:'+(width-listboxHeight-3)+'px"'
  +                 ' type="text"'
  +                 ' value="'+selectedData+'"/>'
  +             '</div>'
  +           '</td>'
  +           '<td style="background-color:'+listboxButtonBgColor+';border-spacing:0px;'
  +             'height:'+(listboxHeight-2)+'px;padding:0px">'
  +             '<div style="overflow:hidden;height:'+(listboxHeight-2)+'px;'
  +               'width:'+(listboxHeight-2)+'px">'
  +               '<input id="' + id + '-button"'
  +                 ' onblur="onblurListbox('+"'"+id+"'"+')"'
  +                 ' onclick="toggleListbox('+"'"+id+"'"+')"'
  +                 ' onkeydown="onkeydownListbox(event, ' + "'" + id + "'" +')"'
  +                 ' style="background-color:'+listboxButtonBgColor+';'
  +                   'background-image:url('+listboxButtonImage+');border:0px;border-spacing:0px;'
  +                   'cursor:'+listboxCursor+';'
  +                   'height:'+(listboxHeight-2)+'px;padding:0px;width:'+(listboxHeight-2)+'px"'
  +                 ' type="button"/>'
  +             '</div>'
  +           '</td>'
  +         '</tr>'
  +       '</table>'
  +       '<div id="' + id + '"'
  +         ' style="border-spacing:0px;display:none;padding:0px;position:absolute;'
  +           'visibility:hidden;z-index:90;width:'+(width+2)+'px"'
  +         ' onkeydown="onkeydownListbox(event, ' + "'" + id + "'" +')">'
  +         '<table border="0" cellpadding="0" cellspacing="0" id="' + id + '-tab"'
  +           ' style="background-color:'+listboxBorderColor+';'
  +             'border:1px solid '+listboxBorderColor+';border-spacing:0px;border-top-width:0px;'
  +             'padding:0px;width:'+width+'px">';
  for(var i=0; i<oldOptions.length; i++) {
    oldOption = oldOptions[i];
    htmlString += ''
    + '<tr>'
    +   '<td id="'+id+'-option'+i+'"'
    +     ' onclick="setListbox('+"'"+id+"'"+','+i+')"'
    +     ' onmouseover="onmouseoverListbox('+"'"+id+"'"+','+i+')"'
    +     ' onmouseout="onmouseoutListbox('+"'"+id+"'"+','+i+')"'
    +     ' style="background-color:'+listboxBgColor+';border-spacing:0px;'
    +       'font-family:'+listboxFontFamily+';font-size:'+listboxFontSize+'px;'
    +       'height:'+(listboxHeight-2)+'px;padding:0px 2px 0px 2px;vertical-align:middle">'
    +     oldOption.firstChild.data
    +   '</td>'
    + '</tr>';
  }
  htmlString += ''
  +         '</table>'
  +         '<input id="'+id+'-key" name="'+id+'" type="hidden" value="'+selectedValue+'"/>'
  +       '</div>'
  +     '</td>'
  +   '</tr>'
  + '</table>';
  theParent.innerHTML = htmlString;
  listboxes[listboxes.length] = listbox;
}

//*****************************************************************************************************

/**
 * Sets the focused listbox entry.
 * @param id ID of the listbox.
 * @param num Number of the focused listbox entry.
 */
function setFocusedListbox(id, num) {
  if(getListbox(id) == null || listboxTimer != false)
    return;
  listboxFocusedID = id;
  listboxFocusedNum = num;
}

//*****************************************************************************************************

/**
 * Sets the selected listbox entry.
 * @param id ID of the listbox.
 * @param num Number of the selected listbox entry.
 */
function setListbox(id, num) {
  var listbox = getListbox(id);
  if(listbox == null)
    return;
  document.getElementById(id + '-key').value = listbox[1][num][0];
  document.getElementById(id + '-value').value = listbox[1][num][1];
  hideListbox(id);
}

//*****************************************************************************************************

/**
 * Opens or closes the listbox entries.
 * @param id ID of the listbox.
 */
function toggleListbox(id) {
  if(getListbox(id) == null)
    return;
  var theBox = document.getElementById(id + '-box');
  var theDiv = document.getElementById(id);
  var theTab = document.getElementById(id + '-tab');
  if(theDiv.style.visibility!='visible') {
    theDiv.style.display = 'block';
    var theOffsetTop = theDiv.offsetTop - window.document.documentElement.scrollTop;
    var theWindowHeight;
    if(theTab.style.borderTopWidth == '1px')
      theOffsetTop += theBox.offsetHeight;
    else
      theOffsetTop -= theBox.offsetHeight
    if(document.documentElement)
      theWindowHeight = document.documentElement.clientHeight;
    else
      theWindowHeight = window.innerHeight;
    if((theOffsetTop * 2) <= theWindowHeight)
      openListboxDown(id);
    else
      openListboxUp(id);
    onmouseoverListbox(id, getListboxSelectedNum(id));
  }
  else
    hideListbox(id);
}

//*****************************************************************************************************

/**
 * Takes away the focus from the listbox.
 * @param id ID of the listbox to make sure the program is working on the correct one.
 */
function unsetFocusedListbox(id) {
  var listbox = getListbox(id);
  if(listbox == null)
    return;
  if(listboxFocusedID == id) {
    for(var i=0; i<listbox[1].length; i++) {
      var theOption = document.getElementById(id+'-option'+i);
      theOption.style.backgroundColor = listboxBgColor;
      theOption.style.color = listboxColor;
    }
    listboxFocusedID = "";
    listboxFocusedNum = "";
  }
  else
    hideListbox(listboxFocusedID);
}

//*****************************************************************************************************
