Selecting multiple from an html select element without using ctrl key

You can save the Element.scrollTop and set it at the end.

$("select").mousedown(function(e){
    e.preventDefault();

    var select = this;
    var scroll = select .scrollTop;

    e.target.selected = !e.target.selected;

    setTimeout(function(){select.scrollTop = scroll;}, 0);

    $(select ).focus();
}).mousemove(function(e){e.preventDefault()});

http://jsfiddle.net/UziTech/cjjg68dr/114/


Tony's answer makes the select arrows buggy, as they work only if you hold the mouse down.

I've combined a few solutions into this, and it works fine at least in Chrome and FF:

// multiple select: selectable without Control
$('select[multiple] option').on('mousedown', function(e) {
    var $this = $(this),
        that = this,
        scroll = that.parentElement.scrollTop;

    e.preventDefault();
    $this.prop('selected', !$this.prop('selected'));

    setTimeout(function() {
        that.parentElement.scrollTop = scroll;
    }, 0);

    return false;
});

Here is a pure JS solution:

element.onmousedown= function(event) {
    //this == event.target
    event.preventDefault();
    var scroll_offset= this.parentElement.scrollTop;
    this.selected= !this.selected;
    this.parentElement.scrollTop= scroll_offset;
}
element.onmousemove= function(event) {
    event.preventDefault();
}

Look at the parent element(the select box) and record the vertical scroll offset before selecting/deselecting the option. Then reset it manually once you have performed the action.

The reasoning behind preventing default behavior for the mousemove event is because if you don't prevent it and you happen to click an option while moving the mouse, all options will become de-selected.


Here's a solution that appears to work in Chrome FF and IE. It's not terribly pretty because it flashes a little bit when clicking.

var vals = [];
$("select[multiple]").click(function(e){
        var scroll_offset= this.scrollTop;
      var newVals = $(this).val();
    if (newVals.length === 1) {
        var index = vals.indexOf(newVals[0])
        if (index > -1) {
        vals.splice(index, 1);
      } else {
        vals.push(newVals[0])
      }
      $(this).val(vals);
      this.scrollTop = scroll_offset;
    }
});

jsfiddle


For a pure js solution in chrome set the event listener on "onmouseup" instead. The event that resets the scroll to the first element is fired on the mouse up. So for example:

element.onmouseup = function(event) {
    event.preventDefault();
    var st = this.scrollTop;
    setTimeout(function () { element.scrollTop = st; }, 0);
};