MULTI SORTABLE MULTI SCROLL

This is a simple Twitter Bootstrap 3 template. You can fork it to get a ready to use Bootstrap 3 fiddle.

HTML

<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css">
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.5.2/jquery.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.11.2/jquery-ui.min.js"></script>
<div class="phase-scroll">
  <ul class="phases row">
  </ul>
</div>

CSS

/* Latest compiled and minified CSS included as External Resource*/


/* Optional theme */

@import url('//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap-theme.min.css');
body {
  margin: 10px;
}

.phase-scroll {
  width: 100%;
  overflow: auto;
}

h2 {
  cursor: move;
  background: #ccc;
  margin: 0;
  padding: 5px;
}

.phases {
  white-space: nowrap;
}

.phase {
  display: inline-block;
  vertical-align: top;
  width: 120px;
  margin: 0 10px;
  border: 1px solid #222;
}

.phase-block {
  max-height: 340px;
  overflow: auto;
}

.item {
  border: 1px solid #ccc;
  padding: 5px;
}

.item.alt1 {
  height: 50px;
}

.item.alt2 {
  height: 60px;
}

.item.alt3 {
  height: 70px;
}

JavaScript

/* Latest compiled and minified JavaScript included as External Resource */
jQuery(function($) {
  var activePhaseBlock;
  var keepScrolling = false;
  var $phases = $('.phases');
  var classes = ['', 'alt1', 'alt2', 'alt3'];
  for (var i = 0; i < 10; i++) {
    var $phase = $('<li />').addClass('phase').append('<h2>+</h2>');
    var $block = $('<div/>').addClass('phase-block');

    for (var j = 0; j < 20; j++) {
      var $item = $('<div/>').text(i + '_Item' + j).addClass('item').addClass(classes[Math.floor(Math.random() * classes.length)]);
      $block.append($item);
    }

    $phase.append($block);
    $phases.append($phase);
  }

  $('.phases').sortable({
    handle: 'h2',
    scroll: true
  });

  $('.phase-block').sortable({
    scroll: true,
    connectWith: '.phase-block',
    appendTo: '.phase-scroll',
    helper: 'clone',
    sort: function(event, ui) {
      if (ui.offset.top >= activePhaseBlock.height() + (90 - ui.item.height() > 0 ? 65 - ui.item.height() : 10))
        activePhaseBlock.scrollTop(activePhaseBlock.scrollTop() + ui.item.height());
      else if (ui.offset.top <= 0 + (ui.item.height() > 25 ? 20 : 40))
        activePhaseBlock.scrollTop(activePhaseBlock.scrollTop() - ui.item.height());
    },
    over: function(event, ui) {
      activePhaseBlock = $(this);
    }
  });
});