Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Reorder multiple <select> fields in a web page

0.00/5 (No votes)
15 Nov 2005 1  
An article on how to reorder a select field in multiple mode and submit the data to the server.

Introduction

This script aims to extend the functionality of the standard <select> field in web pages. Sometimes, we need to order elements in a list. Such functionality extension may be useful, for example, in CMS when you need an interface to order and reorder some elements.

Background

I started to work on a new CMS project for my client and searched for a script to reorder <select> elements. I found many scripts, but none of them does what I expect and what I need. As you know, the difference between programmers and normal people is that when programmers need something, they sit and script. So I wrote this script...

Why use THIS script?

  1. First of all, this script supports the multiple="multiple" attribute of the sorted <select> field. You can move up, down, to top, or to bottom even a complex multiple selection. Read more in "About multiple selections";
  2. Another advantage of this script is that it does not copy values of the <select> in to a hidden field, but submit the whole field as an array to the server. Note that the name of the <select> field must contain [] at the end. For example, if the name of the field should be "files", use: name="files[]";
  3. Some browsers support different colors, fonts, styles and background colors for different elements of the <select> field - MSIE and Firefox. This script supports not only reordering texts and values, but also reorders the layout of the <select> field by changing colors, background colors, ID and class name attributes of the moved elements;
  4. Also, when using viceversa() and listsort() functions, the script remembers which element is selected and which is not;
  5. At last, the script is tested under MSIE, Netscape 6 and 7, Opera 6 and 7, and Firefox 0.8.# and 0.9.#.

Functions

There are six basic functions to order elements:

  • top(object);

    Moves selected items in the <select> field to the top;

  • up(object);

    Moves selected items in the <select> field one step upper;

  • down(object);

    Moves selected items in the <select> field one step lower;

  • bottom(object);

    Moves selected items in the <select> field to the bottom;

  • NEW! viceversa(object, onlyselected);

    Reorders all or only selected items in the <select> field in backorder;

  • NEW! swap(object);

    Swaps the first and the last selected items in the <select> field;

  • listsort(object, criteria, parameter, parameter);

    Sorts all items in the <select> field by a criteria.

Also, there are additional functions:

  • selectall(object);

    Selects all items in the <select> field before submitting the <form>;

  • selectnone(object);

    Unselects all items in the <select> field;

  • mousewheel(object);

    Moves selected items in the <select> field up or down by scrolling the mouse wheel.

  • additem(object, value, text, index, id, className, color, backgroundColor, selected);

    Adds a new item with specified parameters to the existing <select> field;

  • removeitem(object, index);

    Removes item from the <select> field;

Calling the functions

You can create buttons for each function using this code:

<input type="button" value="Top" onclick="top(object);" 
             title="Move to top" />

Or you can use any page object with the onclick="function();" event. Don't use the <button> tag to create such buttons, because in some browsers, this type of buttons submits the form! Also, if using <img>, don't use the onclick="function();" event inside the image, but put the image in to an anchor tag:

<a href="#" onclick="top(object); return false;">
    <img src="..." border="0" />
</a>

Never use href="javascript:". Later, I plan to submit an article on "Why we have never used href="javascript:"".

Another good idea is to use the mouse wheel to call the script. Unfortunately, it may be done only under the MSIE browser because of the onmousewheel="" event:

<select ... onmousewheel="mousewheel(this);">

If you use server side, you need to submit all elements in the <select> field. This is because we added the selectall(); function which can be used with the onsubmit="" event.

<form ... onsubmit="selectall('object'); return true;">

NEW! The new added function selectnone(); may be used with the ondblclick="" event. This way it is possible to unselect elements:

<select ... ondblclick="selectnone(this);">

Function parameters

Note that when calling any function of the script, as a first parameter, you have to set the <select> object. It means you have to send an instance to the object or just send the ID of the object:

f(object);
// or

f("id"); // when sending ID quote it!

The listsort(object, by, numeric, caseSensitive); function accepts four parameters, but the last three are optional.

  • Required, object is an instance to the <select> field object or its ID;
  • Optional, by - integer. Sets the sort criteria. Acceptable values:
    • 0- order by the element text.

      Default value when the parameter is not set or wrong;

    • 1- order by the element value attribute;
    • 2- order by the element color;
    • 3- order by the element background color;
    • 4- order by the element class name;
    • 5- order by the element ID attribute value;
  • Optional, numeric - boolean. If true, sorts by numeric values. For example, 2 is before 10;
  • Optional, caseSensitive - boolean. If true, sorts by case sensitive values. For example, a is before Z;

The additem(object, text, value, index, id, className, color, backgroundColor, selected); function accepts nine parameters, but only the first and the second are required.

  • Required, object is an instance to the <select> field object or its ID;
  • Required, text - string. Sets the text of the new element;
  • Optional, value - string or integer. Sets the value of the new element;
  • Optional, index - integer. If set, determines in which position to add the new element. If not set or wrong, the new element is added at the end of the field. Index starts from 0 (zero) - the first element;
  • Optional, id - string or integer. Sets the ID of the new element. Be careful not to duplicate some ID!
  • Optional, className - string. Sets the CSS class of the new element;
  • Optional, color - string may be color name or HTML color value. Sets the color of the new element. See the known bugs!
  • Optional, backgroundColor - string may be color name or HTML color value. Sets the background color of the new element. See the known bugs!
  • Optional, selected - boolean. If true, the new added element will be selected by default.

The removeitem(object, index); function accepts two parameters, and only the first is required.

  • Required, object is an instance to the <select> field object or its ID;
  • Optional, index - integer or boolean:
    • If set as integer, determines which element to remove where 0 (zero) is the first element;
    • If set as negative integer, the last element is removed;
    • If set as positive integer greater than the element's amount, the last element is removed;
    • If set as boolean False, the last element is removed;
    • If not set or else, the last element is removed;
    • If set as boolean True, the selected element(s) is(are) removed. Note: if more than one element is selected, all selected elements will be removed.

The viceversa(object, onlyselected); from version 1.3, this function accepts two parameters, and only the first is required.

  • Required, object is an instance to the <select> field object or its ID;
  • Optional, onlyselected - boolean:
    • If set as true, only selected items are reordered in backorder (also if selection is not continuous). If only two elements are selected, works like the swap function;
    • If set as false or not set, all elements are reordered in backorder;

About multiple selections

Multiple selection means that users can select more than one element of the <select> field. To enable multiple selection, add multiple="multiple" and size="#" attributes.

Two types of multiple selections exist:

  • Simple (continuous) multiple selection may be done by pressing and holding down the Shift key while clicking to select. All elements between the first and the last clicked are selected;
  • Complex multiple selections may be done by pressing and holding down the Ctrl key while clicking to select. Only clicked elements are selected.

When moving up or down a complex multiple selection, two script behaviors are possible:

  • Default. When the upper or lower selected element goes to the top or bottom, the unselected elements inside the complex multiple selection moves to the opposite direction to decrement the space between selected elements until the complex selection looks like a simple one; or
  • When the upper or lower selected element goes to the top or bottom, it unselects and starts moving to the opposite direction until only one element is selected. So, the first of the selection goes last, and the last goes first;

If you need the second behavior, edit line 12 of up() and down() functions as follows:

// for up() function:

if (sel[i] != 0 && !obj[sel[i]-1].selected) {
if (sel[i] != 0) {
// for down() function:

if (sel[i] != obj.length-1 && !obj[sel[i]+1].selected) {

if (sel[i] != obj.length-1) {

The code

To use the script:

  1. Add inside the <head> section of your web page, a link to load the script file:
    <script type="text/javascript" src="sort.js"></script>

    Use the right location of the file in the src attribute, better relative;

  2. Create a form in your web page and add an onsubmit event to it:
    <form method="post" action="..." onsubmit="selectall('order');">
    ...
    </form>

    The selectall() function parameter is the ID attribute of the <select> field. Better use POST method, because of limitations of the GET method!

  3. Add a <select> field to your form:
    <select name="order[]" size="5" multiple="multiple" 
      id="order" onmousewheel="mousewheel(this);">
        <option value="1">One</option>
        <option value="2">Two</option>
    
        <option value="3">Three</option>
    </select>
  4. Optionally add the onmousewheel event to the <select> field;
  5. Add some buttons for ordering functions. Not necessary for all functions - for example, you can add only up() and down() functions:
    <input type="button" value="Move Up" onclick="up('order');" 
      title="Move up" />
    <input type="button" value="Move Down" onclick="down('order');" 
      title="Move down" />

    where the function parameter is the ID attribute of the <select> field.

  6. Debug to ensure everything is right. That's it!

Server side

Your server side script will receive an array variable containing the ordered values. For example, try this PHP code:


<?php
    var_dump($_POST["order"]);
?>

or ASP:

<%
For Each item In Request.Form()("order[]")
    Response.Write item & "<br />"
Next

%>

Example

Known bugs

A few bugs caused by some browsers' limitations:

  • Only MSIE and Firefox support formatting of elements;
  • Also, in other browsers, sort by color or background color doesn't work;
  • Only MSIE supports the onmousewheel event;

History

  • Version 1.1 [November 21, 2004]
    • Added function selectnone();
    • Added function additem();
    • Added function removeitem();
    • Some minor bug fixes.
  • Version 1.2 [September 8, 2005]
    • Bug fixed when adding element to the <SELECT> with selected elements;
    • Bug fixed in all functions when working with &nbsp; in element's text.
  • Version 1.3 [November 7, 2005]
    • Added function swap();
    • Advanced function viceversa(); now supports only selected parameter;
    • Some minor bug fixes.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here