﻿//
// File             : Select.js
// Author           : Johan Machielse
// Company          : Machielse Software
// Date             : 2007-11-20
// Version          : 1.00
// Description      : Wrapper class for the SELECT element.
//
// Attributes:
// 
// - ID
// - Object
// - MaximumOfItems
// - Numbering
//
// Functions:
//
// + GetSelectedIndex()
// + GetSelectedText()
// + GetSelectedValue()
// + GetIndexOfText()
// + GetIndexOfValue()
// + GetTextAtIndex()
// + GetValueAtIndex()
// + GetNumberOfItems()
//
// + SetMaximumNumberOfItems()
// + GetMaximumNumberOfItems()
// + SetNumbering()
// + GetNumbering()
//
// + Select()
// + SelectText()
// + SelectValue()
//
// + AddItem()
// + AddItemAtIndex()
//
// + RemoveSelectedItem()
// + RemoveItemAtIndex()
// + RemoveItemHavingValue()
// + RemoveItemHavingText()
// + Clear()
//
// + MoveItemUp() 
// + MoveItemDown()
//
// + SetItemTextAtIndex() not checked yet
// + SetItemTextHavingValue() not checked yet 
// + SetItemTextHavingText() not checked yet
// + SetItemValueAtIndex() not checked yet
// + SetItemValueHavingValue() not checked yet
// + SetItemValueHavingText() not checked yet
//
// - RemoveNumberingFromItem()
// - AddNumberingToItem()
// - Renumber()
// - RenumberAllItems()
//
// - SaveToHiddenField()
// - SaveSelectedItemToHiddenField()
//

function Select( id )
{
    //constants
    var NUMBERING_NONE;
    var NUMBERING_NUMERICAL;
    
    //variables
    var ID;
    var Object;
    var MaximumOfItems;
    var Numbering;
    
    //initialisation
    this.NUMBERING_NONE = 0;
    this.NUMBERING_NUMERICAL = 1;
    
    this.ID = id;
    this.Object = document.getElementById( this.ID );
    this.MaximumOfItems = -1;
    this.Numbering = this.NUMBERING_NONE;
        
    //
    // Description:  
    //      Gets the index of the selected item (zero-based).
    // 
    // Returns:
    //      The index of the selected item or -1 when no item has been selected.
    // 
    this.GetSelectedIndex = function()
    {
        if ( this.Object == null ) return (-1);
        
        return ( this.Object.selectedIndex );
    }
    
    //
    // Description:  
    //      Gets the value of the selected item.
    // 
    // Returns:
    //      The value of the selected item.
    // 
    this.GetSelectedValue = function()
    {
        if ( this.Object == null ) return ("");
    
        index = this.GetSelectedIndex();
        
        if ( index != "-1" )
        {
            return ( this.Object.options[index].value );
        }
        else
        {
            return ( "" );
        }
    }
    
    //
    // Description:  
    //      Gets the text of the selected item.
    // 
    // Returns:
    //      The text of the selected item.
    // 
    this.GetSelectedText = function()
    {
        if ( this.Object == null ) return ("");
        
        index = this.GetSelectedIndex();
        
        if ( index != "-1" )
        {
            itemText = this.RemoveNumberingFromItem(this.Object.options[index].text);
            return ( itemText );
        }
        else
        {
            return ( "" );
        }
    }
    
    //
    // Description:  
    //      Get the index related to the text (name-value pair).
    // 
    // Parameters:
    //      text: The text to be searched.
    //
    // Return:
    //      Returns the index related to the searched text (name-value pair).
    //      When the text has not been found, the return value will equal -1.
    // 
    this.GetIndexOfText = function( text )
    {     
      if ( this.Object == null ) return (-1);
      
      for ( index = 0 ; index < this.GetNumberOfItems() ; index++ )
      {
        itemText = this.RemoveNumberingFromItem(this.Object.options[index].text);
        
        if ( itemText == text )
        {
            return (index);
            break;
        }
      }
      
      return (-1);
    }
    
    //
    // Description:  
    //      Get the index related to the value (name-value pair).
    // 
    // Parameters:
    //      text: The value to be searched.
    //
    // Return:
    //      Returns the index related to the searched value (name-value pair).
    //      When the value has not been found, the return value will equal -1.
    //
    this.GetIndexOfValue = function( value )
    { 
      if ( this.Object == null ) return (-1);
          
      for ( index = 0 ; index < this.GetNumberOfItems() ; index++ )
      {
        if ( this.Object.options[index].value == value )
        {
            return (index);
            break;
        }
      }
      return (-1);
    }
    
    //
    // Description:  
    //      Get the item's text at the specified index.
    // 
    // Parameters:
    //      index: The index of the item.
    //
    // Return:
    //      Returns the text of the item specified by the index.
    //
    this.GetTextAtIndex = function( index )
    {   
      if ( this.Object == null ) return ("");
        
      if ( (index >= 0) && (index < this.GetNumberOfItems()) )
      {
        return (this.RemoveNumberingFromItem(this.Object.options[index].text));
      }
      
      return ("");
    }
    
    //
    // Description:  
    //      Get the item's value at the specified index.
    // 
    // Parameters:
    //      index: The index of the item.
    //
    // Return:
    //      Returns the value of the item specified by the index.
    //
    this.GetValueAtIndex = function( index )
    {     
      if ( this.Object == null ) return ("");
      
      if ( (index >= 0) && (index < this.GetNumberOfItems()) )
      {
        return (this.Object.options[index].value);
      }
      
      return ("");
    }
    
    //
    // Description:  
    //      Gets the number of items.
    // 
    // Returns:
    //      The number of items.
    // 
    this.GetNumberOfItems = function()
    {
        if ( this.Object == null ) return (0);
        
        return (this.Object.length);  
    }
    
    //
    // Description:  
    //      Sets the maximum number of items that can be added.
    // 
    // Parameters:
    //      value: The maximum number of values that can be added.
    // 
    this.SetMaximumNumberOfItems = function( value )
    {       
        this.MaximumOfItems = value;  
    }
    
    //
    // Description:  
    //      Gets the maximum number of items that can be added.
    // 
    // Returns:
    //      The maximum number of values that can be added.
    // 
    this.GetMaximumNumberOfItems = function()
    {
        return (this.MaximumOfItems);
    }
    
    //
    // Description:  
    //      Sets the numbering of the items.
    // 
    // Parameters:
    //      numbering: The numbering to use.
    // 
    this.SetNumbering = function( numbering )
    {
        if ( (numbering >= this.NUMBERING_NONE) && (numbering <= this.NUMBERING_NUMERICAL) )
        {
            this.Numbering = numbering;
        }    
    }
    
    //
    // Description:  
    //      Gets the numbering of the items.
    // 
    // Returns:
    //      The used numbering.
    // 
    this.GetNumbering = function()
    {
        return (this.Numbering);  
    }
       
    //
    // Description:  
    //      Selects an item at the specified index.
    // 
    // Parameters:
    //      index: The index of the item to select (zero based index).
    //   
    this.Select = function( index )
    {
        if ( this.Object == null ) return;
        
        if ( (index >= 0) && (index < this.GetNumberOfItems()) )
        {
            this.Object.selectedIndex = index;
        }
    }
    
    //
    // Description:  
    //      Selects the item having a particular text.
    // 
    // Parameters:
    //      text: The text to select.
    //
    // Return:
    //      Returns true when the text has been selected otherwise false.
    //
    this.SelectText = function( text )
    {
      if ( this.Object == null ) return (false);
      
      for ( index = 0 ; index < this.GetNumberOfItems() ; index++ )
      {
        itemText = this.RemoveNumberingFromItem(this.Object.options[index].text);
        
        if ( itemText == text )
        {           
            this.Select( index );
            return (true);
            break;
        }
      }
      
      return (false);
    }
    
    //
    // Description:  
    //      Selects the item having a particular value.
    // 
    // Parameters:
    //      text: The value to select.
    //
    // Return:
    //      Returns true when the value has been selected otherwise false.
    //
    this.SelectValue = function( value )
    {
      if ( this.Object == null ) return (false);
           
      for ( index = 0 ; index < this.GetNumberOfItems() ; index++ )
      {
        if ( this.Object.options[index].value == value )
        {
            this.Select( index );
            return (true);
            break;
        }
      }
      
      return (false);
    }
    
    //
    // Description:  
    //      Adds a new item to the end.
    // 
    // Parameters:
    //      value: The value of the new item.
    //      text: The text of the new item.
    //
    this.AddItem = function( value, text )
    {
        if ( this.Object == null ) return;
        
        if ( (this.GetNumberOfItems() < this.GetMaximumNumberOfItems()) || (this.GetMaximumNumberOfItems() == -1) )
        {            
            itemText = this.AddNumberingToItem( text, this.Object.length );
            
            var option = document.createElement("option");
            option.text = itemText;
            option.value = value;
            
            this.Object.options.add(option, this.GetNumberOfItems());
        }
    }
    
    //
    // Description:  
    //      Adds a new item at the specified index.
    // 
    // Parameters:
    //      index: Index of the new item.
    //      value: The value of the new item.
    //      text: The text of the new item.
    //
    this.AddItemAtIndex = function( index, value, text )
    {
        if ( this.Object == null ) return;
        
        if ( (this.GetNumberOfItems() < this.GetMaximumNumberOfItems()) || (this.GetMaximumNumberOfItems() == -1) )
        {
            if ( (index >= 0) && (index <= this.GetNumberOfItems()) )
            {
                itemText = this.AddNumberingToItem( text, index );
                
                var option = document.createElement("option");
                option.text = itemText;
                option.value = value;
                        
                this.Object.options.add(option, index);
                
                //renumber all items
                if ( this.GetNumbering() != this.NUMBERING_NONE )
                {
                    for ( index = 0 ; index < this.GetNumberOfItems() ; index++ )
                    {
                        this.Object.options[index].text = this.Renumber( this.Object.options[index].text, index );
                    }      
                }
             }
        }
    }
    
    //
    // Description:  
    //      Removes the selected item.
    //
    this.RemoveSelectedItem = function()
    {
        if ( this.Object == null ) return;
        
        index = this.GetSelectedIndex();
        
        if ( index != "-1" )
        {
            this.Object.removeChild( this.Object.options[index] );
        }
    }
    
    //
    // Description:  
    //      Removes an item at the specified index.
    // 
    // Parameters:
    //      index: Index of the item to be removed.
    //
    this.RemoveItemAtIndex = function( index )
    {
        if ( this.Object == null ) return;
        
        if ( (index >= 0) && (index < this.GetNumberOfItems()) )
        {
            this.Object.removeChild( this.Object.options[index] );
        }  
    }
    
    //
    // Description:  
    //      Removes an item having the specified value.
    // 
    // Parameters:
    //      value: Value of the item to be removed.
    //
    this.RemoveItemHavingValue = function( value )
    {
        if ( this.Object == null ) return;
        
        for ( index = 0 ; index < this.GetNumberOfItems() ; index++ )
        {
            if ( this.Object.options[index].value == value )
            {
                this.RemoveItemAtIndex( index );
                break;
            }
        }
    }
    
    //
    // Description:  
    //      Removes an item having the specified text.
    // 
    // Parameters:
    //      text: Text of the item to be removed.
    //
    this.RemoveItemHavingText = function( text )
    {
        if ( this.Object == null ) return;
        
        for ( index = 0 ; index < this.GetNumberOfItems() ; index++ )
        {
            itemText = this.RemoveNumberingFromItem(this.Object.options[index].text);
            
            if ( itemText == text )
            {
                this.RemoveItemAtIndex( index );
                break;
            }
        }
    }
    
    //
    // Description:  
    //      Removes all items.
    //
    this.Clear = function()
    {
        if ( this.Object == null ) return;
        
        items = this.GetNumberOfItems();
        
        for ( index = 0 ; index < items ; index++ )
        {
           this.RemoveItemAtIndex(0); 
        }  
    }
    
    //
    // Description:  
    //      Moves an item up.
    //
    this.MoveItemUp = function()
    {
        if ( this.Object == null ) return;
        
        index = this.GetSelectedIndex();
        
        if ( index > 0 )
        {
            optionSelected = this.Object.options[index];
            optionChanged = this.Object.options[index - 1];
            
            selectedText = this.RemoveNumberingFromItem( optionSelected.text );
            selectedValue = optionSelected.value;
            
            changedText = this.RemoveNumberingFromItem( optionChanged.text );
            changedValue = optionChanged.value;
            
            optionChanged.text = this.AddNumberingToItem( selectedText, index - 1 );
            optionChanged.value = selectedValue; 
            
            optionSelected.text = this.AddNumberingToItem( changedText, index );
            optionSelected.value = changedValue;     
        }
    }
    
    //
    // Description:  
    //      Moves an item down.
    //
    this.MoveItemDown = function()
    {
        if ( this.Object == null ) return;
        
        index = this.GetSelectedIndex();
        
        if ( (index > 0) && (index < (this.GetNumberOfItems() - 1)) && (index != -1) )
        {
            optionSelected = this.Object.options[index];
            optionChanged = this.Object.options[index + 1];
            
            selectedText = this.RemoveNumberingFromItem( optionSelected.text );
            selectedValue = optionSelected.value;
            
            changedText = this.RemoveNumberingFromItem( optionChanged.text );
            changedValue = optionChanged.value;
            
            optionChanged.text = this.AddNumberingToItem( selectedText, index + 1 );
            optionChanged.value = selectedValue; 
            
            optionSelected.text = this.AddNumberingToItem( changedText, index );
            optionSelected.value = changedValue;     
        }
    }
   
    //
    // Description:  
    //      Returns the item's text whereof the numbering has been removed.
    // 
    // Parameters:
    //      text: Item's text inclusive the numbering.
    // 
    // Returns:
    //      Item's text without numbering.
    this.RemoveNumberingFromItem = function( text )
    {
        switch (this.Numbering)
        {
            case this.NUMBERING_NUMERICAL:
                indexOfDot = text.indexOf( "." );
                itemText = text.substring( indexOfDot + 2 );                
                return (itemText);
                break;
            default:
                return (text);
                break;
        } 
    }
    
    //
    // Description:  
    //      Returns the item's text where the numbering has been added.
    // 
    // Parameters:
    //      text: Item's text without numbering.
    //      position: Position of the item (zero-based).
    // 
    // Returns:
    //      Item's text with numbering.
    this.AddNumberingToItem = function( text, position )
    {
        switch (this.Numbering)
        {
            case this.NUMBERING_NUMERICAL:
                itemText = (parseInt(position,10) + 1) + ". " + text;
                return (itemText);
                break;
            default:
                return (text);
                break;
        } 
    }
    
    //
    // Description:  
    //      Renumbers the item's text related to it's changed position.
    // 
    // Parameters:
    //      text: Item's text with numbering that's not right.
    //      position: Position of the item (zero-based).
    // 
    // Returns:
    //      Item's text with right numbering.
    this.Renumber = function( text, position )
    {
        itemText = this.RemoveNumberingFromItem( text );
        itemText = this.AddNumberingToItem( itemText, position );
        
        return (itemText);
    }
    
    //
    // Description:  
    //      Renumbers all items.
    // 
    this.RenumberAllItems = function()
    {
        if ( this.Object == null ) return;
        
        if ( this.GetNumbering() != this.NUMBERING_NONE )
        {
            for ( index = 0 ; index < this.GetNumberOfItems() ; index++ )
            {
                this.Object.options[index].text = this.Renumber( this.Object.options[index].text, index );
            }      
        }
    }
    
    //
    // Description:  
    //      Sets the text of an item specified by the index.
    // 
    // Parameters:
    //      index: Index of the item to set the text.
    //      newText: The new text of the item.
    //
    this.SetItemTextAtIndex = function( index, newText )
    {
        if ( this.Object == null ) return;
        
        if ( (index >= 0) && (index < this.GetNumberOfItems()) )
        {
            this.Object.options[index].innerText = this.AddNumberingToItem( newText, index );
        }
    }
    
    //
    // Description:  
    //      Sets the text of an item having a specified value.
    // 
    // Parameters:
    //      value: Value of the item to set the text.
    //      newText: The new text of the item.
    //
    this.SetItemTextHavingValue = function( value, newText )
    {
        if ( this.Object == null ) return;
        
        for ( index = 0 ; index < this.GetNumberOfItems() ; index++ )
        {
            if ( this.Object.options[index].value == value )
            {
                this.Object.options[index].innerText = this.AddNumberingToItem( newText, index );
                break;
            }
        }
    }
    
    //
    // Description:  
    //      Sets the text of an item having a specified text.
    // 
    // Parameters:
    //      text: Text of the item to set the text.
    //      newText: The new text of the item.
    //
    this.SetItemTextHavingText = function( text, newText )
    {
        if ( this.Object == null ) return;
        
        for ( index = 0 ; index < this.GetNumberOfItems() ; index++ )
        {
            itemText = this.RemoveNumberingFromItem(this.Object.options[index].text);
            
            if ( itemText == text )
            {
                this.Object.options[index].innerText = this.AddNumberingToItem( newText, index );
                break;
            }
        }
    }
    
    //
    // Description:  
    //      Sets the value of an item specified by the index.
    // 
    // Parameters:
    //      index: Index of the item to set the value.
    //      newValue: The new value of the item.
    //
    this.SetItemValueAtIndex = function( index, newValue )
    {
        if ( this.Object == null ) return;
        
        if ( (index >= 0) && (index < this.GetNumberOfItems()) )
        {
            this.Object.options[index].value = newValue;
        }
    }
    
    //
    // Description:  
    //      Sets the value of an item having a specified value.
    // 
    // Parameters:
    //      value: Value of the item to set the value.
    //      newValue: The new value of the item.
    //
    this.SetItemValueHavingValue = function( value, newValue )
    {
        if ( this.Object == null ) return;
        
        for ( index = 0 ; index < this.GetNumberOfItems() ; index++ )
        {
            if ( this.Object.options[index].value == value )
            {
                this.Object.options[index].value = newValue;
                break;
            }
        }
    }
    
    //
    // Description:  
    //      Sets the value of an item having a specified text.
    // 
    // Parameters:
    //      text: Text of the item to set the value.
    //      newValue: The new value of the item.
    //
    this.SetItemValueHavingText = function( text, newValue )
    {
        if ( this.Object == null ) return;
        
        for ( index = 0 ; index < this.GetNumberOfItems() ; index++ )
        {
            itemText = this.RemoveNumberingFromItem(this.Object.options[index].text);
            
            if ( itemText == text )
            {
                this.Object.options[index].value = newValue;
                break;
            }
        }
    }
    
    //
    // Description:  
    //      Saves the contents of the select in a hidden field so that
    //      the server side code can read the items added/updated/deleted
    //      by JavaScript code.
    //      
    //      Format:
    //      elements=XXX
    //      value1=VVV
    //      text1=TTT
    //      ...
    //      valueX=VVV
    //      textX=TTT
    // 
    // Parameters:
    //      hiddenFieldID: The id of the hidden field. 
    //
    this.SaveToHiddenField = function( hiddenFieldID )
    {
        var hiddenField = document.getElementById( hiddenFieldID );
        hiddenFieldText = "";
        
        hiddenFieldText = "elements=" + this.GetNumberOfItems() + "\n";
        
        for ( index = 0 ; index < this.GetNumberOfItems() ; index++ )
        {
            value = "value" + (index + 1) + "=" + this.GetValueAtIndex(index) + "\n";
            text  = "text" + (index + 1) + "=" + this.GetTextAtIndex(index) + "\n";
            
            hiddenFieldText += (value + text);                  
        }    
        
        hiddenField.value = hiddenFieldText;    
    }
    
    //
    // Description:  
    //      Saves the selected item of the select in a hidden field so that
    //      the server side code can read the item selected
    //      by JavaScript code.
    //      
    //      Format:
    //      index=III
    //      value=VVV
    //      text=TTT
    // 
    // Parameters:
    //      hiddenFieldID: The id of the hidden field. 
    //
    this.SaveSelectedItemToHiddenField = function( hiddenFieldID )
    {
        var hiddenField = document.getElementById( hiddenFieldID );
        hiddenFieldText = "";
        
        indexString = "index=" + this.GetSelectedIndex() + "\n"; 
        valueString = "value=" + this.GetSelectedValue() + "\n";
        textString  = "text=" + this.GetSelectedText() + "\n";
        
        hiddenFieldText = indexString + valueString + textString;    
        
        hiddenField.value =  hiddenFieldText;   
    }
}


