Multi-Select Transfers Using MooTools 1.2

While I was a Zone Leader for DZone's AJAX, CSS, and PHP Zones, DZone's Rick Ross asked me to contact Jeremy Martin with regard to a hot blog post he created: Easy Multi Select Transfer with jQuery. Both Rick and I were impressed with Jeremy's script and asked him to repost on DZone.

Fast forward five months later, I decided that I simply had to create a MooTools script that would accomplish the same goal. I mean, if Jeremy's going to port the Kwicks effect to jQuery, why can't I take one back for the Moo team? In the end, the MooTools code looks very much like jQuery's code.

The HTML

<div class="holder">
	<select multiple="multiple" id="select1" name="select1[]">
		<option value="1">Option 1</option>
		<option value="2">Option 2</option>
		<option value="3">Option 3</option>
		<option value="4">Option 4</option>
	</select>
	<a href="javascript:;" id="add">add >></a>
</div>
<div class="holder">
	<select multiple="multiple" id="select2" name="select2[]">
		<option value="5">Option 5</option>
		<option value="6">Option 6</option>
	</select>
	<a href="javascript:;" id="remove"><< remove</a>
</div>

The MooTools JavaScript

window.addEvent('domready', function() {
	$('add').addEvent('click', function() {
		$('select1').getSelected().each(function(el) {
			el.inject($('select2'));
		});
	});
	$('remove').addEvent('click', function() {
		$('select2').getSelected().each(function(el) {
			el.inject($('select1'));
		});
	});
});

All we need to do is move the selected <option> elements to the other select list.

Note that the PHP $_POST variable receives the values correctly. Very practical and functional!


Comments

  1. Jeremy Martin

    Ha looks good… and only 4 lines longer! :p No but seriously, I think it’s time for a new library… how about MooQuery?

  2. david

    @Jeremy: Don’t tempt me to try to make it shorter!

  3. thomasd

    Sorry, but I had to do this!!! :)

    window.addEvent(‘domready’, function(){
    $(‘add’).addEvent(‘click’, function(){
    $(‘select1′).getSelected().inject($(‘select2′));
    });
    $(‘remove’).addEvent(‘click’, function(){
    $(‘select2′).getSelected().inject($(‘select1′));
    });
    });
    8 Lines

    or even shorter

    window.addEvent(‘domready’, function(){
    var move = function(from, to){$(from).getSelected().inject($(to));}
    $(‘add’).addEvent(‘click’, move.pass(['select1', 'select2']));
    $(‘remove’).addEvent(‘click’, move.pass(['select2', 'select1']));
    });
    5 Lines

    JS-Frameworks rock!!!

  4. david

    thomasd 1, David 0. Awesome work!

  5. Jeremy Martin

    Ok, I’ll admit the ternary usage is a little ridiculous here, but here’s 5 lines in jQuery:

    $().ready(function() {
      $(‘#add, #remove’).click(function() {
        $(‘option:selected’, $(this).is(‘#add’) ? $(‘#select1′) : $(‘#select2′)).remove().appendTo($(this).is(‘#add’) ? $(‘#select2′) : $(‘#select1′));
      });
    });

  6. thomasd

    This is what Jeremy’s very nice solution looks like in Mootools 1.2 (of course without the underscores :) ):

    window.addEvent(‘domready’, function(){
    __$$(‘#add, #remove’).addEvent(‘click’, function(){
    ____$(this.match(‘#add’)?’select1′:’select2′).getSelected().inject($(this.match(‘#remove’)?’select1′:’select2′));
    __});
    });

    Though I would prefer the other 5 lines solution, as in my opion it is much clearer and ‘move’ can be used for every pair of selects.

    @david:
    thank you very much for this blog, as it is a daily pleasure for me.
    I already use your Generic-Class, and some other ideas posted here.
    Greets from Austria

  7. Nate

    I have been working on the same kind of widget for the past week, using jquery. I had seen the one from Jeremy when it first came out, but it doesn’t do nearly enough for my purposes. Mine does the same basic things as yours, only it works on reset, keeps items sorted when adding and removing, handles preselected items, and only requires a user to create one select box with the class multiple, then the code creates the second box and all the buttons.

    I’d post the code, but it is a little over 100 lines, so it’s not exactly an easily readable snippet. If you are interested let me know and I’ll try to find a way to post it.

  8. david

    @Nate: Feel free to post a link to an example.

  9. Nate

    I’ll try to set something up when I get home.

  10. Nate

    I finally got around to posting it:

    http://www.suptin.com/selector.html

    If you view the source of the js file it will be a huge mess of stuff, and most of it is unrelated to the select transfer thing. Lines 4470 to 4552 contain the majority of the code related to the selector. The lines 4651 to 4654 are in an ready block that initializes the selectors.

    Everything is much more organized, when I’m working on it, but I grabbed the build rather than the src. Also the code for the selector would be quite a bit cleaner if I didn’t have to worry about IE 6/7.

  11. david

    @Nate: Great work. Thank you for posting it.

  12. Peter

    Hi David,

    I like this script. I’ll try and integrate it in a little project of mine.

    Otherwise, how does the code hightlighting on this blog work? I’ve been looking for a while and I think ones is pretty neat.
    Mind sharing a little info on it?

    Cheers,
    Peter

  13. Peter

    Me again…

    Answered my own question: you use wmd-editor.com

    Now I’ve got to figure how to input code

  14. James

    anyone know of a drag and drop version of this?

    Cheers.

  15. Ch@Sky

    Exellent David!! thnks a lot.

  16. sophy

    I need the same tutorial with mootools 1.11
    please help

  17. Paul

    Where should I look if I wanted a 3 box multi select? Basically The first box contains top level categories, then when you select one of those categories, the second box loads up (via ajax) all the sub categories, and then the user can choose to transfer one of the sub categories across to the third and empty box.

    Any ideas?

  18. alphanono

    Wow … great !

    But … an other chalange now ?

    There is a great plugin for jQuery not yet for mootools : http://code.google.com/p/jquery-asmselect/

  19. Scott

    Is it possible to limit the amount you can transfer into the second select.

  20. Ajans

    Thanks you too much, wonderful !

  21. Levis

    Thank you David for this.

    I’ve added a dblclick on the option if someone wants it:

    window.addEvent(‘domready’, function() {
    $(‘element_add’).addEvent(‘click’, function(){
    $(‘element1′).getSelected().inject($(‘element2′));
    });
    $(‘element_rem’).addEvent(‘click’, function(){
    $(‘element2′).getSelected().inject($(‘element1′));
    });
    $$([$('element1'), $('element2')]).each(function(ex){
    ex.getChildren().each(function(el){
    el.addEvent(‘dblclick’,function(){
    this.inject((this.getParent().get(‘id’)==’element1′ ? $(‘element2′) : $(‘element1′)));
    });
    });
    });
    });

  22. Timo

    Well i played with inject and swapping options between selectboxes way back in my online config editor.

    What i came up with is putting it into a Hash (for global closed namespace – no other reason) where i store some helper functions and simply dynamicly call it

    var APF = new Hash({
    swapSB: function(s,t){ $(s).getSelected().inject($(t)); }
    // alot more functions here …
    });

    and then call APF.swapSB(‘source’,'target’) onClick. This way you do not have to bind alot of events on domready but can use this where and when it’s needed. Basicly the way thomasd went using his move function on domready.

  23. Scott Boyde

    Hi

    Is it possible on form submit that you can select all options in the second list.

  24. Avinash

    Hi, David.

    Nice script.

    But how about the drag and drop version?

    Thanks..

  25. Alan

    Hi Dave,

    I was writing something for Joomla and it kind of fits with this. Different approach but uses same principle. However this method allows you to control the size (height, width) and format of the boxes containing the elements.

    window.addEvent('domready', function() {

    var elementsIs = $$('.options');
    for(z=0;z<elementsIs.length;z++){
    elementsIs[z].addEvent('click', function() {
    if(this.getParent().id=="select1"){
    this.inject($('select2'));
    }else{
    this.inject($('select1'));
    }
    });
    }

    You can control the boxes by using CSS for the various classes. Html is

    Option 1
    Option 2
    Option 3
    Option 4

     

    Option 5
    Option 6

    Bit tricker on the submit but simple enough with mootools and JSON. Simply parse the relevant part of the div ( in my case the innerHTML value) into an array and store as an object that can be simply decoded in php. I haven’t posted that here in the interests of keeping the reply short but if anyone is interested let me know and I’ll post it.

    Overall this is a bit more complex than your code but it allows you far more control of the list boxes and of the data inside them. It also removes the need for add and remove buttons since you just click on the option to move it across lists.
    Alan

  26. Tarek

    Is it doable to implement the “order” on the second list ?

  27. Tarek

    btw it will cause a problem on IE8+ using :

    version:”1.2.1″,build:”0d4845aab3d9a4fdee2f0d4a6dd59210e4b697cf”

    the error :
    Message: JScript object expected
    Line: 1
    Char: 91770
    Code: 0

  28. ginger

    Hi,

    Can I use the mootools code for this multi select transfer module for free?

    Thanks!

  29. pwell

    I use this:

    $(‘to’).adopt($(‘from’).getSelected());

  30. pwell

    I use this:


    $('to').adopt($('from').getSelected());

  31. nemoglobine

    Hy David, thx for your great experience

    When i send the form, only hilighted options are sent

    I tried this stuff on submit event but it seem to be done after the form submit … any ideas ???


    $('select2').getParent('form').addEvent('submit', function () {
    $('select2').getElements('option').each(function (el) {
    el.set('selected', 'selected');
    });
    });

    • nemoglobine

      It’s works …

      The problem was that i declared many submit events and the first one send the form by ajax before selecting all options. So i placed this code before the form submit and it works …

      I hope this will help someone (maybe Scott Boyde !)

  32. Thomas Freeman

    Great simple solution – especially with the double click option! Thanks for sharing this!
    Hoping it warms up for a nice Wisconsin Labor Day!

  33. pSoupre

    for those looking to add the element “pre-selected” then add this line …

    [CODE]el.setProperty(‘selected’, ‘selected’);[/CODE]

    like this…
    [CODE]
    $(‘add’).addEvent(‘click’, function() {
    $(‘select1′).getSelected().each(function(el) {
    el.inject($(‘select2′));
    el.setProperty(‘selected’, ‘selected’);
    });
    });
    [/CODE]
    $(‘remove’).addEvent(‘click’, function() {
    $(‘select2′).getSelected().each(function(el) {
    el.inject($(‘select1′));
    });
    });

  34. pSouper

    For those looking to add the element “pre-selected” then add this line …

    el.setProperty(‘selected’, ‘selected’);

    like this…

    $(‘add’).addEvent(‘click’, function() {
    $(‘select1′).getSelected().each(function(el) {
    el.inject($(‘select2′)); el.setProperty(‘selected’, ‘selected’);
    });
    });
    $(‘remove’).addEvent(‘click’, function() { $(‘select2′).getSelected().each(function(el) { el.inject($(‘select1′));
    });
    });


Be Heard!

Share your thoughts without being a jerk! And wrap your code in <code> tags, f00!

Name*:
Email*:
Website: