JSFiddle - React, Tailwind, and code Playground

by Michael Prosser

HTML

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<select multiple id="userlist">
    <option data-value="kevin bagley" value="1005479">Kevin Bagley</option>
    <option data-value="doe bill" value="1005172">Doe Bill</option>
    <option data-value="frank byers" value="2">Frank Byers</option>
    <option data-value="glenn dickey" value="1565">Glenn Dickey</option>
    <option data-value="angie fjeldheim" value="1005602">Angie Fjeldheim</option>
    <option data-value="mimi lam" value="1005413">Mimi Lam</option>
    <option data-value="mike law" value="1000064">Mike Law</option>
    <option data-value="nick mitchell" value="1005220">Nick Mitchell</option>
    <option data-value="scott rysdon" value="1826">Scott Rysdon</option>
    <option data-value="laura schmidt" value="1005557">Laura Schmidt</option>
    <option data-value="john sewell" value="1005618">John Sewell</option>
    <option data-value="scott sorrows" value="1005501">Scott Sorrows</option>
</select>

CSS

body {
  font-family: helvetica, serif;
  font-size: 13px;
}

select {
  width: 232px;
  padding: 6px;
  border-radius: 5px;
  border: solid 1px #999;
  font-size: 12px;
  height: 200px;
}

select[multiple] option {
  background-color: #fff;
  color: #000;
  background-image: none;
  background-repeat: no-repeat;
  padding: 6px;
  padding-left: 25px;
  background-size: auto 60%;
  background-position: 5px 5px;
  border-bottom: solid 1px #ebebeb;
  transition: all 0.4s;
}

select[multiple] option:checked {
  background-color: #e7f9e1 !important;
  background-image: url(https://agrisphere-portal.com/live/images/success_small.png);
}

select.selection-segregation.disable-events {
  pointer-events: none;
  overflow: hidden;
}

select[multiple].selection-segregation option.move-hide {
  height: 10px;
  opacity: 0.2;
}

select.selection-segregation>optgroup.selected-options-group:empty {
  display: none;
}

select.selection-segregation>optgroup>option:first-child {
  margin-top: 5px;
}

select.selection-segregation>optgroup>option:last-child {
  margin-bottom: 5px;
}

JavaScript

function enableSelectionSegregation(targetElements,availableLabel,selectedLabel){

	targetElements.each(function(){
  
    var outputElement = $(this);

    outputElement.addClass('selection-segregation');
    
    outputElement.addClass('disabled-events');
    
    outputElement.html('<optgroup label="' + availableLabel + '">' + outputElement.html() + '</optgroup>');
    
    outputElement.prepend('<optgroup label="' + selectedLabel + '" class="selected-options-group"></optgroup>');

    // index caching

    outputElement.find('option').each(function(index) {

      $(this).attr('data-selection-index', index);

    });

    outputElement.find('option').mousedown(function(e) {

      e.preventDefault();

      var scroll = outputElement.scrollTop();

      var cached_this = $(this);

      outputElement.addClass('disable-events');

      cached_this.prop('selected', !cached_this.prop('selected'));

      cached_this.addClass('move-hide');

      setTimeout(function() {

        if (cached_this.prop('selected')) {

          var detached = cached_this.detach();

          var eq = parseInt(cached_this.attr('data-selection-index'));

          var appended = false;

          // check if the current selections are all higher indexes than new selection

          var greater = true;

          outputElement.find('optgroup[label="' + selectedLabel + '"]>option').each(function() {

            var itemIndex = parseInt($(this).attr('data-selection-index'));

            if (itemIndex < eq) {

              greater = false;

            }


          });

          if (outputElement.find('optgroup[label="' + selectedLabel + '"]>option').length == 0) {

            outputElement.find('optgroup[label="' + selectedLabel + '"]').prepend(detached);

            appended = true;

          } else if (greater) {

            outputElement.find('optgroup[label="' + selectedLabel + '"]').prepend(detached);

            appended = true;

          } else {

           ...