NMultiSelect – Et jQuery Plugin

NMultiSelect

UPDATE

This has become quite an old version, it’s good to get started, but to get the latest version, please take a look here: http://ndesoft.dk/category/web/js/nmultiselect-js/

Quick links

About NMultiSelect

Okay, I have been foolin’ around with javascripts again, i know, can’t help it. This time I have made me a jQuery plug-in. I chose jQuery because it’s so much easier to do cross browser compatible stuff with that framework, compared to time it will take for me to build it on my own.

The last 3/4 of a year, i have worked on and off with the Microsoft ASP.NET MVC framework, and found it quite likeable, in terms of development speed and possibilities in the markup and, in this case, JavaScript.

While working with the MVC framework, I have been looking for a nice, easy to implement method for a user to choose multiple values from a list. The good ol’ “hold ctrl while clicking”-method doesn’t quite do the job, so I decided to build my own control.

It’s, like most of the other stuff I’ve made, quite easy to use.

Seen from a user’s perspective, it’s simple, click or double click, select and click or what ever he or she feels like. For the developer, it’s also quite easy. A few lines of code, and you’re ready to go:

 

Getting started

First we need to include a few scripts:

<span class="kwrd">&lt;</span><span class="html">script</span> <span class="attr">type</span><span class="kwrd">="text/javascript"</span> <span class="attr">src</span><span class="kwrd">="https://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js"</span><span class="kwrd">&gt;&lt;/</span><span class="html">script</span><span class="kwrd">&gt;</span>

<span class="kwrd"> </span><span class="kwrd">&lt;</span><span class="html">script</span> <span class="attr">type</span><span class="kwrd">="text/javascript"</span> <span class="attr">src</span><span class="kwrd">="http://code.jdempster.com/jQuery.DisableTextSelect/jquery.disable.text.select.pack.js"</span><span class="kwrd">&gt;&lt;/</span><span class="html">script</span><span class="kwrd">&gt;</span>

<span class="kwrd"> </span><span class="kwrd">&lt;</span><span class="html">script</span> <span class="attr">type</span><span class="kwrd">="text/javascript"</span> <span class="attr">src</span><span class="kwrd">="http://nmultiselect.ndesoft.dk/scripts/jquery.nmultiselect.min.js"</span><span class="kwrd">&gt;&lt;/</span><span class="html">script</span><span class="kwrd">&gt;</span>

Where you wan’t to place your box, you just put a div:

<span class="kwrd">&lt;</span><span class="html">div</span> <span class="attr">id</span><span class="kwrd">="EmptySelectContainer"</span><span class="kwrd">&gt;&lt;/</span><span class="html">div</span><span class="kwrd">&gt;</span>

We wan’t to remember this ID for later…

To transform the div, to a multi select box, we will have to write the following piece of code:

$(document).ready(
    <span class="kwrd">function</span> () {
        <span class="kwrd">var</span> m1 = $(<span class="str">"#EmptySelectContainer"</span>).NMultiSelect(<span class="str">"mySelection"</span>);
    }
);

What happens here is:

  1. $(document).ready – We will wait until the page is ready before doing anything.
  2. $(“#EmptySelectContainer”) – We select’s our div, using the ID from earlier. You can use any form of selectors here.
  3. NMultiSelect(“mySelection”) – Transform our div to a multi select box. The parameter (mySelection) is the name of the field getting posted to the server. In this case, we will be able to get our data using $_POST[“mySelection”] (using php, but more on that later.)

Now, we have transformed our div to a multi select box, but it’s a bit useless. Lets fill it with some values. To do so, use this function:

AddItemToList(value,text,selected).

The function AddItemToList, takes 3 parameters.

The first, is the value posted to the server. Usually an ID.

The second, is the text shown in the box.

The third, is a boolean value (not mandatory). If true, the item will be selected and visible in the right hand side box.

You can add as many items you want, Below is an example:

m1 = $(<span class="str">"#EmptySelectContainer"</span>).NMultiSelect(<span class="str">"mySelection"</span>);

m1.AddItemToList(<span class="str">"1-1"</span>,<span class="str">"Value 1"</span>,<span class="kwrd">false</span>);
m1.AddItemToList(<span class="str">"2-1"</span>,<span class="str">"Value 2"</span>,<span class="kwrd">false</span>);
m1.AddItemToList(<span class="str">"3-1"</span>,<span class="str">"Value 3"</span>,<span class="kwrd">true</span>);
m1.AddItemToList(<span class="str">"4-1"</span>,<span class="str">"Value 4"</span>,<span class="kwrd">true</span>);

Here we add 4 items to our box. Whereof the last two are pre-selected.

Now we have our items, it could be nice, to track how the user chooses, for statistics or calling AJAX methods or whatever. To do se, we can subscribe to the event:

SelectionChanged(code).

The parameter (code), is code that will be executed, when a user selects or deselects one or more items.

An example:

m1.SelectionChanged(<span class="kwrd">function</span>(data)
{
    <span class="rem">// Do stuff here.</span>
});

The function, or code, that is being executed, must take one parameter, (call it whatever you feel like, i would recommend “data”, because, that is what it is). This parameter contains two properties:

  • Items
    • Contains all elements we have added.
  • Selection
    • Contains all chosen elements.

The objects contained in the lists, has the following properties:

  • Text
  • Value
  • Selected

Full example

Bellow is a full example. You could also see nmultiselect live here.

<span class="kwrd">&lt;!</span><span class="html">DOCTYPE</span> <span class="attr">html</span> <span class="attr">PUBLIC</span> <span class="kwrd">"-//W3C//DTD XHTML 1.1//EN"</span> <span class="kwrd">"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"</span><span class="kwrd">&gt;</span>
<span class="kwrd">&lt;</span><span class="html">html</span> <span class="attr">xmlns</span><span class="kwrd">="http://www.w3.org/1999/xhtml"</span> <span class="attr">xml:lang</span><span class="kwrd">="da"</span><span class="kwrd">&gt;</span>
<span class="kwrd">&lt;</span><span class="html">head</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">title</span><span class="kwrd">&gt;</span>NMultiselect<span class="kwrd">&lt;/</span><span class="html">title</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">link</span> <span class="attr">rel</span><span class="kwrd">="stylesheet"</span> <span class="attr">type</span><span class="kwrd">="text/css"</span> <span class="attr">href</span><span class="kwrd">="/styles/style.css"</span><span class="kwrd">/&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">script</span> <span class="attr">type</span><span class="kwrd">="text/javascript"</span> <span class="attr">src</span><span class="kwrd">="https://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js"</span><span class="kwrd">&gt;&lt;/</span><span class="html">script</span><span class="kwrd">&gt;</span>
    &lt;script type=<span class="str">"text/javascript"</span> src=<span class="str">"/scripts/jquery.nmultiselect.min.js"</span>&gt;&lt;/script&gt;
    &lt;script&gt;
        <span class="kwrd">var</span> m1;
        <span class="kwrd">var</span> m2;

        $(document).ready(
            <span class="kwrd">function</span> () {
                m1 = $(<span class="str">"#EmptySelectContainer"</span>).NMultiSelect(<span class="str">"mySelection",<span class="kwrd">true</span></span>);

                m1.AddItemToList(<span class="str">"1-1"</span>,<span class="str">"Value 1"</span>,<span class="kwrd">false</span>);
                m1.AddItemToList(<span class="str">"2-1"</span>,<span class="str">"Value 2"</span>,<span class="kwrd">false</span>);
                m1.AddItemToList(<span class="str">"3-1"</span>,<span class="str">"Value 3"</span>,<span class="kwrd">true</span>);
                m1.AddItemToList(<span class="str">"4-1"</span>,<span class="str">"Value 4"</span>,<span class="kwrd">true</span>);

                m1.SelectionChanged(<span class="kwrd">function</span>(data)
                {
                    console.log(<span class="str">'List 1, selected values: '</span>+(data.Selection.length));
                });

                m2 = $(<span class="str">"#EmptySelectContainer2"</span>).NMultiSelect(<span class="str">"mySelection2"</span>);
                m2.AddItemToList(<span class="str">"1-2"</span>,<span class="str">"Value 1"</span>,<span class="kwrd">true</span>);
                m2.AddItemToList(<span class="str">"2-2"</span>,<span class="str">"Value 2"</span>,<span class="kwrd">false</span>);
                m2.AddItemToList(<span class="str">"3-2"</span>,<span class="str">"Value 3"</span>,<span class="kwrd">false</span>);
                m2.AddItemToList(<span class="str">"4-2"</span>,<span class="str">"Value 4"</span>,<span class="kwrd">true</span>);
                m2.AddItemToList(<span class="str">"5-2"</span>,<span class="str">"Value 5"</span>,<span class="kwrd">true</span>);
                m2.AddItemToList(<span class="str">"6-2"</span>,<span class="str">"Value 6"</span>,<span class="kwrd">true</span>);
                m2.AddItemToList(<span class="str">"7-2"</span>,<span class="str">"Value 7"</span>,<span class="kwrd">false</span>);
                m2.AddItemToList(<span class="str">"8-2"</span>,<span class="str">"Value 8"</span>,<span class="kwrd">false</span>);

                m2.SelectionChanged(<span class="kwrd">function</span>(data)
                {
                    console.log(<span class="str">'List 2, selected values: '</span>+(data.Selection.length));
                });
            }
        );
    <span class="kwrd">&lt;/</span><span class="html">script</span><span class="kwrd">&gt;</span>

<span class="kwrd">&lt;/</span><span class="html">head</span><span class="kwrd">&gt;</span>
<span class="kwrd">&lt;</span><span class="html">body</span><span class="kwrd">&gt;</span>
<span class="kwrd">&lt;</span><span class="html">form</span> <span class="attr">method</span><span class="kwrd">="get"</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">div</span> <span class="attr">id</span><span class="kwrd">="EmptySelectContainer"</span><span class="kwrd">&gt;&lt;/</span><span class="html">div</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">p</span><span class="kwrd">&gt;</span>hejsa<span class="kwrd">&lt;/</span><span class="html">p</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">div</span> <span class="attr">id</span><span class="kwrd">="EmptySelectContainer2"</span><span class="kwrd">&gt;</span>

    <span class="kwrd">&lt;/</span><span class="html">div</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">input</span> <span class="attr">type</span><span class="kwrd">="submit"</span> <span class="attr">value</span><span class="kwrd">="submit"</span><span class="kwrd">/&gt;</span>
    <span class="kwrd">&lt;/</span><span class="html">form</span><span class="kwrd">&gt;</span>
<span class="kwrd">&lt;/</span><span class="html">body</span><span class="kwrd">&gt;</span>
<span class="kwrd">&lt;/</span><span class="html">html</span><span class="kwrd">&gt;</span>

 

Serverside

So, what to do on the serverside to get the data?

Well, the name you apply in the NMultiSelect function above, is the name of the field getting posted to the server.

If we say, you use the ASP.NET MVC framework, your backend would look somewhat like this:

[HttpPost]
<span class="kwrd">public</span> <span class="kwrd">void</span> GiveMeData(<span class="kwrd">string</span> mySelection)
{
    <span class="rem">// Først splittes værdierne:</span>
    <span class="rem">// Ja, vi splitter på komma, i en fremtidig version kan dette ændres!</span>
    <span class="kwrd">string</span>[] mySelectionItems = mySelection.Split(<span class="str">','</span>);

    <span class="rem">// Gennemløb værdierne:</span>
    <span class="kwrd">foreach</span>(<span class="kwrd">string</span> itemId <span class="kwrd">in</span> mySelectionItems)
    {
        <span class="rem">// Du kan her behandle værdierne som du ønsker.</span>
    }
}

PHP

&lt;?php
    <span class="rem"># Få fat i værdierne:</span>
    $selection = $_POST[<span class="str">"mySelection"</span>];

    <span class="rem"># Split værdierne:</span>
    $values = explode(<span class="str">","</span>, $selection);

    <span class="rem"># Gennemløb værdierne:</span>
    <span class="kwrd">foreach</span> ($values as &amp;$value) {
            <span class="rem"># Gør med dataene hvad du vil.</span>
    }

    <span class="rem"># Husk at ryde op:</span>
    unset($value);

?&gt;

Reference

Heres a short reference of all the functions available:

NMultiSelect(name,[move]) Creates a new instance of the NMultiSelect-box on the first item in the applied jQuery object. See exampe above.Name: Name of the field that is posted to the server.

move: Not mandatory! If true, the items will be moved between the boxes, instead of just being copied to the right hand side box. Default is false.

AddSelection() Chooses all selected items in the left hand box.
AddAll() Chooses all items in the left hand box.
RemoveSelection() Removes selected items from the right hand side box.
RemoveAll() Removes all items from the right hand side box.
AddItemToList(value,text,[selected]) Adds an item to the box.value: Value the item should have.

text: Text of the item.

selected: Not mandatory, if true, the item is pre-selected.

SelectionChanged(code) Event you can subscribe. Is called each time a change in the chosen items occur.code: Code to be executed, when the event is fired. The code, must have a parameter, that accepts the same objects as data(‘values’) returns.
data(‘values’) Returns all added items, and all chosen items.More details about data(‘values’) below.

data(‘values’)

If you call data(‘values’), (it’s importent to include the ‘values’ part. This is a jQuery thingy!), you will get an object with two properties:

  • Items
  • Selection

Each of these properties contains a list of objects. Items – A list of all items we’ve added, and selection – A list of all chosen items. Each of these objects has the following properties:

  • Value
  • Text
  • Selected

In the Items-list, all values will be the ones, the item was created with.

In the Selection-list, the only difference would be, that the selected-property will be true.

Download

You can grap the code and an example here:

Download NMultiSelect 1.0

  • Zhahai

    Hi,

    Thanks for creating this module, it looks very useful!

    As a note for others, the unzipped example did not initially work, as it referenced the css file from /styles/ and I had unzipped in a subfolder beneath the domain root folder. When I changed the css reference to relative (from styles/ rather than /styles), it began working.

  • Hi, thanks for your comment… 🙂

    I think its one of those things getting missed when things goes way to fast. But thanks for the note.

    By the way, have you seen the newest version (1.5)? You can find it here: http://ndesoft.dk/2011/03/11/nmultiselect-v-1-5/

  • Flo

    Hi,

    thanks for this lovely module.
    I have a problem with getting all selected items’ texts. With a for-loop i iterate through data.Selection.length. With data.Selection[i].Text i wanted the displayed text for each item. But it’s always ‘undefined’. Any ideas?

    Thanks!

  • Hi,

    Sounds very odd, I will look into it and return with an answer.

    In the mean time, could you give me some info about your browser and maybe an example of your code?

  • @Flo

    I have made a fix, and put it into a new release, including some new features:

    http://ndesoft.dk/2011/04/26/nmultiselect-v-1-5-1/

  • Flo

    Hey,

    sry for my late answer. Thank you very much, now it works!
    I’m using firefox 4.0.1 on a Win7 64bit.
    This is my Code:

    [code]
    chooseWorkers = $(“#chooseWorkers”).NMultiSelect();

    chooseWorkers.SelectionChanged(function(data2){
    //iterate through all selected items and put the id and the name to 2 different input-fields(#newTicket_worker_id and #newTicket_worker)
    for(i = 0; i < data2.Selection.length; i++) {
    workerIds += data2.Selection[i].Value + ';';
    workers += data2.Selection[i].Text + ';';
    }
    $('#newTicket_worker_id').val(workerIds);
    $('#newTicket_worker').val(workers);

    workers = '';
    workerIds = '';
    });
    [/code]

  • Flo

    ah it deleted my php code … nvm, i’m adding multiple options in the 2nd line via php -> chooseWorkers.AddItemToList(“‘ . $userId . ‘”, “‘ . $userName . ‘”, false);

  • @Flo
    Hi, It’s OK I’ve been busy anyway so couldn’t reply on any comments anyway.

    It’s good to hear, that you’ve managed to get it to work, and thanks for the code example.

    Please let me now if you have any other questions or bug-reports.