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);
}
});
});