Select multiple options without ctrl click

I am looking to idiot proof certain aspects of my admin interface. I would like the user to be able to select various options from a multi select box by simply clicking the options instead of ctrl-click. There may be multiple select boxes on the page that require this functionality.,

Thanks :slight_smile:

I think you will have to loop through all select boxes with a “multiple” attribute and attach an onchange event listener to each. Create an array for each select box (perhaps storing them all in an object) containing all the options and whether each is selected or not. Then whenever the select box changes, check which was clicked and if it’s in the array, remove it. If not, add it. Then loop through the options and for each one make the relevant option selected (because if it’s not in the array it doesn’t need to be selected).

Does anyone know of a pre-made script? Javascript is not my forte. Thanks for the help.

It works in Firefox and should work in all other browsers too, though I’m not sure about IE because I can’t remember where it chokes regarding hasAttribute or removeAttribute. I’d be grateful if you could test it for me in IE because I’ve broken mine. There’s also a nasty flicker when you click on any of the options, you’ll see what I mean. Will try and deal with that later.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
  <title>Badger</title>
  <meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
  <meta name="generator" content="Crimson Editor" />
  <link rel="stylesheet" type="text/css" href="" />
  <script type="text/javascript">
    function init() {
      if (arguments.callee.done) return;
      arguments.callee.done = true;
      if (khtmltimer) clearInterval(khtmltimer);
      var s = document.getElementsByTagName('select');
      for (var i = 0; i < s.length; i++) {
        if (s[i].hasAttribute('multiple')) {
          s[i].onclick = updateSelect;
        }
      }
    }
    function updateSelect(e) {
      var opts = this.getElementsByTagName('option'), t, o;
      if (e) {
        e.preventDefault();
        t = e.target;
      }
      else if (window.event) {
        window.event.returnValue = false;
        t = window.event.srcElement;
      }
      else return;
      t = e.target || window.event.srcElement;
      if (t.getAttribute('class') == 'selected') t.removeAttribute('class');
      else t.setAttribute('class', 'selected');
      for (var i = 0, j = opts.length; i < j; i++) {
        if (opts[i].hasAttribute('class')) opts[i].selected = true;
        else opts[i].selected = false;
      }
    }
         
    if (document.addEventListener) document.addEventListener("DOMContentLoaded", init, false);
    /*@cc_on @*/
    /*@if (@_win32)
        document.write("<script id=__ie_onload defer src=javascript:void(0)><\\/script>");
        var script = document.getElementById('__ie_onload');
        script.onreadystatechange = function() {
            if (this.readyState == 'complete') {
                init();
            }
        };
    /*@end @*/
    if (/KHTML/i.test(navigator.userAgent)) {
        var khtmltimer = setInterval(function() {
            if (/loaded|complete/.test(document.readyState)) {
                init();
            }
        }, 10);
    }
    window.onload = init;
  </script>
</head>

<body>
  <div id="a">
    <select name="x" multiple="multiple">
    <option value="xa">Badger</option>
    <option value="xb">Badger</option>
    <option value="xc">Badger</option>
    <option value="xd">Badger</option>
    <option value="xe">Badger</option>
    <option value="xf">Badger</option>
    <option value="xg">Badger</option>
    <option value="xh">Badger</option>
    <option value="xi">Badger</option>
    </select>
  </div>
</body>
</html>

It works fine on firefox as you mentioned but IE doesn’t support hasAttribute/setAttribute at all.

Thanks.

That’s true for hasAttribute, but IE does support setAttribute, just not entirely well.

This should work in IE now:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html>
<head>
  <title>Badger</title>
  <script type="text/javascript">
    function init() {        
      var s = document.getElementsByTagName('select');
      for (var i = 0; i < s.length; i++) {
        if (s[i].multiple) {
          s[i].onclick = updateSelect;
        }
      }
    }
    function updateSelect(e) {
      var opts = this.getElementsByTagName('option'), t, o;
      if (e) {
        e.preventDefault();
        t = e.target;
      }
      else if (window.event) {
        window.event.returnValue = false;
        t = window.event.srcElement;
      }
      else return;
      t = e.target || window.event.srcElement;
      if (t.className == 'selected') t.className = '';
      else t.className = 'selected';
      for (var i = 0, j = opts.length; i < j; i++) {
        if (opts[i].className == 'selected') opts[i].selected = true;
        else opts[i].selected = false;
      }
    }
    window.onload = init;
  </script>
</head>

<body>
    <select name="x" multiple="multiple">
    <option value="xa">Badger</option>
    <option value="xb">Badger</option>
    <option value="xc">Badger</option>
    <option value="xd">Badger</option>
    <option value="xe">Badger</option>
    <option value="xf">Badger</option>
    <option value="xg">Badger</option>
    <option value="xh">Badger</option>
    <option value="xi">Badger</option>
    </select>
</body>
</html>

The only caveat is that with this simple script you can’t give the <option>s class attributes, but I think that’s normally fairly unusual.

That works fine in FF, but IE7 still will not select multiple.

Well, I found out that IE doesn’t support onclick events on <option> elements and that when you use the event on a <select> it gets the srcElement wrong anyway.

I found this: http://www.mattkruse.com/temp/easier-multi-select.html - it does what you want, but it uses inline event handlers, so I added to it to work for any <select> with a multiple attribute. It works in IE.

var multiSelect = {};
    function init() {      
      var s = document.getElementsByTagName('select');
      for (var i = 0; i < s.length; i++) {
        if (s[i].multiple) {
          var n = s[i].name;
          multiSelect[n] = [];
          for (var j = 0; j < s[i].options.length; j++) {
            multiSelect[n][j] = s[i].options[j].selected;
          }
          s[i].onchange = changeMultiSelect;
        }
      }
    }
    function changeMultiSelect() {
      var n = this.name;
      for (var i=0; i < this.options.length; i++) {
        if (this.options[i].selected) {
          multiSelect[n][i] = !multiSelect[n][i];
        }
        this.options[i].selected = multiSelect[n][i];
      }
    }
    window.onload = init;