Elastic Multiple Select List

Picture 6Following on from my previous post demonstrating my mooSelect class, today I needed to create something different, again with a multiple select list.

This time the brief was to make a standard multiple select list “expand” when it gets focus so as to prevent it from messing up the rest of the page whilst it is not being used.
By default, if a select list does not have a width defined via css, it will simply expand to fit the width of the longest option text.
This can cause problems when the items are excessively long.

My solution was to set a fixed width for the list via css and then use Mootools to detect the length of the longest option.
Then, when the user clicks on the list, it expands out to this width.

See Demo

mooElastic
As I am currently trying to get my head round mootools classes, I just had to do this by creating a class.
To make the class slightly more flexible, there are several options that can be set, possibly the most interesting of which is the possibility to define whether the select list should expand on “mouseover” or on “focus”.

Anyway, here is what I did:

The html:

<select id="mySelect" style="postion:relative;width:100px;" multiple size="8">
<option value="1">Option one</option>
<option value="2">Option two - longer</option>
<option value="3">Option three</option>
<option value="4">Option four</option>
<option value="5">Option five</option>
<option value="6">Option six - this one should define the length</option>
<option value="7">Option seven</option>
<option value="8">Option eight</option>
<option value="9">Option nine</option>
</select>

The javascript (mootools)

var mooElasticSelect = new Class({
  Implements: [Options],
    options: {
      initLength:'100',
      charWidth :'8',
      initMethod:'hover'
    },

  initialize: function(element,options){
    this.setOptions(options);
    this.selectBox		=	$(element);
    this.selectOptions	=	this.selectBox.getElements('option');
    this.build();
  },

  build: function(){
    //	wrap list in relative layer to flow "over" items
    var wrapper = new Element('div', {
      'styles': {
        'position': 'relative'
      }
    });
    wrapper.wraps(this.selectBox);

    //	find longest optin text value
    var optionLength=0;
    this.selectOptions.each(function(option) {
      lng=option.get('text').length;
      if(lng>optionLength) optionLength=lng;
    });
    var selectWidth=optionLength*this.options.charWidth;
    this.stretch(selectWidth);
  },

  stretch: function(lng){
    var initLength=this.options.initLength;
    this.selectBox.setStyle('cursor','pointer');
    if(this.options.initMethod=='focus'){
      this.selectBox.addEvents({
        'focus':function(){this.tween('width', ''+lng+'px');},
        'blur':	function(){this.tween('width', ''+initLength+'px');}
      })
    }else{
      this.selectBox.addEvents({
        'mouseover'	:function(){ this.tween('width', ''+lng+'px'); },
        'mouseout'	:function(){ this.tween('width', ''+initLength+'px');}
      });
    }
  }
});

//  initiate the class
window.addEvent('domready', function() {
  var sel =new mooElasticSelect('mySelect',{'charWidth':'6'});
});

Post to Twitter

chris@cbolson.com

There are 3 comments in this article:

  1. 17/02/2010Expanding Multiple Select List with Search Filter « Chris Bolson – I digress says:

    […] Elastic Multiple Select List Mootools Splash Screen […]

  2. 23/06/2010chandra sekhar says:

    I am trying to use above code but I am getting js error as “Class is undefined”. can you help me how to run sample in my system. I am beginner in javascript.

  3. 23/06/2010Chris says:

    Hi,
    Can you share an url? otherwise it is going to be impossible to help you.

Write a comment: