fluidmind
Star God: Fu Star God: Lu Star God: Shou

HTML Select Functions

These functions manipulate the options in HTML select elements.

FM.findOption(element, value)
Searches for an option with the specified value and returns its index
FM.addOption(element, text, value, before)
Add an option to a select list
FM.alterOptions(element, action, options)
Removes, selects, or deselects a list of options
FM.swapOptions(element, index1, index2)
Swaps the positions of two options in an HTML select element
FM.shiftOptionUp(element, option)
Shifts an option up one position
FM.shiftOptionDown(element, option)
Shifts an option down one position
FM.sortOptions(element, direction)
Sorts all of the options in an HTML select element

Multiple-Select Functions

FM.selectAllOptions(element)
Selects all of the options in the specified multiple-select element
FM.deselectAllOptions(element)
Deselects all of the options in the specified multiple-select element
FM.shiftSelectionsUp(element)
Shifts selected options in a multiple select field up one position
FM.shiftSelectionsDown(element)
Shifts selected options in a multiple select field down one position
FM.removeSelections(element)
Removes selected options from a multiple select field
FM.copySelections(fromElement, toElement)
Copies selected options in a multiple select field to another multiple select field
FM.moveSelections(fromElement, toElement)
Moves selected options in a multiple select field to another multiple select field

Example 1

Use the links and buttons below to experiment on the guinea pig menu. Just click on one of them, then pull down the menu to see how it was changed.

Remove 1st Three Options
Shift 'Option 7' Up
Shift 'Option 7' Down
Remove 'Option 7'

Label:
Value:
Before:

Example 2

This example demonstrates how to automatically select certain options within a multiple-select element.

Select All

Select First Three Options

Select All Even Options

Deselect All

Example 3

This example demonstrates all of the functions that manupulation the contents of multiple-select elements. The box on the left contains a sorted list of selections which can be moved to the end of the box on the right. The options in the right box can be moved into any order. If they are moved back to the left box they are placed back into alphabetical order. Finally, the left box can be sorted either ascending or descending.

Options   My Selections  

Code

You can copy and paste any and all of these functions, or just download them all in one file.

// Make sure the "FM" namespace object exists
if (typeof FM != 'object') {
    FM = new Object();
}
    
/**
 * Returns the index of the option with the specified value, or -1 if not found
 *
 * @param   element         The HTML select element to be sorted
 * @param   value           The option value to search for
 */
FM.findOption = function(element, value) {
    if (typeof element == 'string') { element = document.getElementById(element); }

    if(!(value == undefined)) {
        for (var i = 0; i < element.options.length; i++) {
            if (element.options[i].value == value) {
                return i;
            }
        }
    }

    return -1;
}


/**
 * Adds an option to a select element
 *
 * @author  Dan Delaney     http://fluidmind.org/
 * @param   element         The HTML select element to remove the options from
 * @param   label           The label text to appear in the menu option
 * @param   value           The value of the option element to add
 * @param   before          (Optional) The option to add this option before (either a numeric index or a value)
 */
FM.addOption = function(element, label, value, before) {
    if (label == undefined || label == '' || value == undefined || value == '') {
        return false;
    } else {
        if (typeof element == 'string') { element = document.getElementById(element); }

        if ( isNaN(parseInt(before)) ) {
            before = FM.findOption(element, before);
            if(before < 0) {
                before = element.options.length;
            }
        }

        // First, start an array with the new option and copy all options from the
        // "before" option to the end after it
        var options = new Array();
        options.push(new Option(label, value, false, false));
        for (var i = before; i < element.options.length; i++) {
            options.push(element.options[i]);
        }

        // Then put them back, including the new one
        for (var i = 0, j = before; i < options.length; i++, j++) {
            element.options[j] = 
                new Option(options[i].text, 
                           options[i].value, 
                           options[i].defaultSelected, 
                           options[i].selected);
        }
    }
} // addOption()



/**
 * Remove options in a multiple-select element, specified by numerical index
 *
 * After the first argument, put as many arguments as you like
 *
 * @author  Dan Delaney     http://fluidmind.org/
 * @param   element         The HTML select element to remove the options from
 * @param   action          The Action to perform. One of: remove, select, deselect
 * @param   options         (Multiple) Option indexes or values to perform the action on
 */
FM.alterOptions = function(element, action) {
    if (typeof element == 'string') { element = document.getElementById(element); }

    if (action == undefined || action != 'remove' && action != 'select' && action != 'deselect') {
        return false;
    } else if (arguments.length > 1) {
        // Put the indexes into an associative array
        var indexes = new Object();
        var values = new Object();
        for (var i = 2; i < arguments.length; i++) {
            if (isNaN(arguments[i])) {
                values['value_' + arguments[i]] = true;
            } else {
                indexes['index_' + arguments[i]] = true;
            }
        }

        // Step through the options backwards and alter them if they are in the list
        for (var i = element.options.length - 1; i >= 0; i--) {
            if (indexes.hasOwnProperty('index_' + i) || values.hasOwnProperty('value_' + element.options[i].value)) {
                switch (action) {
                    case 'remove':
                        element.options[i] = null;
                        break;
                    case 'select':
                        element.options[i].selected = true;
                        break;
                    case 'deselect':
                        element.options[i].selected = false;
                        break;
                }
            }
        }
    }
}  // alterOptions()


/**
 * Swaps two options in an HTML select element
 *
 * @author  Dan Delaney     http://fluidmind.org/
 * @param   element         The HTML select element with the options to me moved
 * @param   index1          First index number of the options array to swap
 * @param   index2          Second index number of the options array to swap
 */
FM.swapOptions = function(element, index1, index2) {
    if (typeof element == 'string') { element = document.getElementById(element); }

    // Make sure the indexes are valid
    if (index1 != index2 &&
        index1 >= 0 && index1 < element.options.length &&
        index2 >= 0 && index2 < element.options.length) {

        // Save the selection state of all of the options because Opera
        // seems to forget them when we click the button
        var optionStates = new Array();
        for(i = 0; i < element.options.length; i++) {
            optionStates[i] = element.options[i].selected;
        }

        // Save the first option into a temporary variable
        var option = element.options[index1];

        // Copy the second option into the first option's place
        element.options[index1] =
            new Option(element.options[index2].text,
                       element.options[index2].value,
                       element.options[index2].defaultSelected,
                       element.options[index2].selected);

        // Copy the first option into the second option's place
        element.options[index2] = 
            new Option(option.text,
                       option.value,
                       option.defaultSelected,
                       option.selected);

        // Reset the selection states for Opera's benefit
        for(i = 0; i < element.options.length; i++) {
            element.options[i].selected = optionStates[i];
        }

        // Then select the ones we swapped, if they were selected before the swap
        element.options[index1].selected = optionStates[index2];
        element.options[index2].selected = optionStates[index1];
    }
} // swapOptions()


/**
 * Shifts an option (specified by index or value) in a select element up one position
 *
 * @author  Dan Delaney     http://fluidmind.org/
 * @param   element         The form select element with the options to me shifted
 * @param   option          The index or value of the option to be shifted up
 * @see     swapOptions
 */
FM.shiftOptionUp = function(element, option) {
    if (typeof element == 'string') { element = document.getElementById(element); }

    if (isNaN(option)) option = FM.findOption(element, option);

    // Only move it up if it's not the first option and it's not
    // below another selected option
    if (!isNaN(option) && option > 0 && option < element.options.length) {
        FM.swapOptions(element, option, option - 1);
    }
} // shiftOptionUp()


/**
 * Shifts an option (specified by index or value) in a select element down one position
 *
 * @author  Dan Delaney     http://fluidmind.org/
 * @param   element         The form select element with the options to me shifted
 * @param   option          The index or value of the option to be shifted up
 * @see     swapOptions
 */
FM.shiftOptionDown = function(element, option) {
    if (typeof element == 'string') { element = document.getElementById(element); }

    if (isNaN(option)) option = FM.findOption(element, option);

    // Only move it up if it's not the first option and it's not
    // below another selected option
    if (!isNaN(option) && option > 0 && option < (element.options.length - 1)) {
        FM.swapOptions(element, option, option + 1);
    }
} // shiftOptionDown()


/**
 * Sorts all of the options in a select element
 *
 * @author  Dan Delaney     http://fluidmind.org/
 * @param   element         The HTML select element to be sorted
 * @param   direction       The sort direction: 'asc' or 'desc' (optional)
 */
FM.sortOptions = function(element, direction) {
    if (typeof element == 'string') { element = document.getElementById(element); }

    // We have to put the whole options array into a new array, because
    // the options array doesn't support all of the Array methods (like sort)
    // Doesn't that suck?
    options = new Array();
    for (var i = 0; i < element.options.length; i++) {
        options.push(element.options[i]);
    }

    // Sort it with a function that uses the 'text' property of the Option object
    options.sort( function(a, b) {
            if (a.text.toLowerCase() < b.text.toLowerCase()) return -1;
            if (a.text.toLowerCase() > b.text.toLowerCase()) return 1;
            return 0;
        });

    // If asked to sort in descending, reverse it
    if(direction != undefined && direction.toLowerCase() == 'desc') {
        options.reverse();
    }

    // Now copy the array back into the options array
    for (var i = 0; i < options.length; i++) {
        element.options[i] = 
            new Option(options[i].text, 
                       options[i].value, 
                       options[i].defaultSelected, 
                       options[i].selected);
    }
} // sortOptions()


/**
 * Selects all of the options in a multiple-select element
 *
 * @author  Dan Delaney     http://fluidmind.org/
 * @param   element         The HTML select element to make the selection in
 */
FM.selectAllOptions = function(element) {
    if (typeof element == 'string') { element = document.getElementById(element); }

    // Then loop through the element's options and select all that
    // have keys in the new options associative array
    for (var i = 0; i < element.options.length; i++) {
        element.options[i].selected = true;
    }
}  // selectAllOptions()


/**
 * Deselects all of the options in a multiple-select element
 *
 * @author  Dan Delaney     http://fluidmind.org/
 * @param   element         The HTML select element to make the selection in
 */
FM.deselectAllOptions = function(element) {
    if (typeof element == 'string') { element = document.getElementById(element); }

    // Then loop through the element's options and select all that
    // have keys in the new options associative array
    for (var i = 0; i < element.options.length; i++) {
        element.options[i].selected = false;
    }
}  // deselectAllOptions()


/**
 * Shifts selected options in a multiple select element up one position
 *
 * @author  Dan Delaney     http://fluidmind.org/
 * @param   element         The form select element with the options to me moved
 * @see     swapOptions
 */
FM.shiftSelectionsUp = function(element) {
    if (typeof element == 'string') { element = document.getElementById(element); }

    // Make sure it's a multiple select element
    if (element.type == 'select-multiple') {
        // Step through the options and move the selected ones
        for (var i = 0; i < element.options.length; i++) {
            // Is the option selected?
            if (element.options[i].selected) {
                // Only swap it if it's not the first option and it's not
                // below another selected option
                if (i > 0 && element.options[i - 1].selected != true) {
                    FM.swapOptions(element, i, i - 1);
                }
            }
        } // for
    }
} // shiftSelectionsUp()


/**
 * Shifts selected options in a multiple select element down one position
 *
 * @author  Dan Delaney     http://fluidmind.org/
 * @param   element         The HTML select element with the options to me moved
 * @see     swapOptions
 */
FM.shiftSelectionsDown = function(element) {
    if (typeof element == 'string') { element = document.getElementById(element); }

    // Make sure it's a multiple select element
    if (element.type == 'select-multiple') {
        // Step through the options and move the selected ones
        for (var i = element.options.length - 1; i >= 0 ; i--) {
            // Is the option selected?
            if (element.options[i].selected) {
                // Only swap it if it's not the last option and it's not
                // above another selected option
                if (i < (element.options.length - 1) && !element.options[i + 1].selected) {
                    FM.swapOptions(element, i, i + 1);
                }
            }
        } // for
    }
} // shiftSelectionsDown()


/**
 * Removes selected options from a select element
 *
 * @author  Dan Delaney     http://fluidmind.org/
 * @param   element         The HTML select element to remove the options from
 */
FM.removeSelections = function(element) {
    if (typeof element == 'string') { element = document.getElementById(element); }

    if (element.type == 'select-multiple') {
        for (var i = element.options.length - 1; i >= 0; i--) {
            if (element.options[i].selected) {
                // Delete it from the source element
                element.options[i] = null;
            }
        }
    } else {
        element.options[element.selectedIndex] = null;
    }
} // removeSelections()


/**
 * Copies selected options in a multiple-select element to another multiple-select element.
 *
 * @author  Dan Delaney     http://fluidmind.org/
 * @param   fromElement     The HTML select element with the options to be copied
 * @param   toElement       The HTML select element to copy the options to
 */
FM.copySelections = function(fromElement, toElement) {
    if (typeof fromElement == 'string') fromElement = document.getElementById(fromElement);
    if (typeof toElement == 'string') toElement = document.getElementById(toElement);

    // Make sure both parameters are multiple select element
    if (fromElement.type == 'select-multiple' && toElement.type == 'select-multiple') {
        // Step through the options and move the selected ones
        for (var i = 0; i < fromElement.options.length; i++) {
            // Is the option selected?
            if (fromElement.options[i].selected) {
                // Copy it to the end of the destination element
                toElement.options[toElement.options.length] = 
                    new Option(fromElement.options[i].text, 
                               fromElement.options[i].value, 
                               fromElement.options[i].defaultSelected, 
                               fromElement.options[i].selected);
            }
        } // for
    }
} // copySelections()


/**
 * Moves selected options in a multiple-select element to another multiple-select element.
 *
 * @author  Dan Delaney     http://fluidmind.org/
 * @param   fromElement     The HTML select element with the options to be moved
 * @param   toElement       The HTML select element to move the options to
 * @see     copySelections
 * @see     removeSelections
 */
FM.moveSelections = function(fromElement, toElement) {
    if (typeof element == 'string') { element = document.getElementById(element); }

    // Make sure both parameters are multiple select elements
    if (fromElement.type == 'select-multiple' && toElement.type == 'select-multiple') {
        FM.copySelections(fromElement, toElement);
        FM.removeSelections(fromElement);
    }
} // moveSelections()