JSFiddle - React, Tailwind, and code Playground
by stevea
HTML
<div id='box1' class='box'></div>
<div id='box2' class='box'></div>
<div id='box3' class='box'></div>
<div id='box4' class='box'></div>
<div id='group'></div>
CSS
.box {
position: absolute;
width: 100px;
height: 100px;
background: black;
z-index: 100 /* keep boxes above group so we can select them */
}
#box1 {
left:10px;
top: 15px;
}
#box2 {
left:150px;
top:25px;
}
#box3 {
left:300px;
top:35px;
}
#box4 {
left:450px;
top:45px;
}
#group {
width: 100%;
height: 100%;
z-index: -1;
position: absolute;
}
JavaScript
$('.box').draggable();
$('.box').click(function(){
var this$=$(this);
var group$ = $('#group'); // short hand for ease
var top;
var left;
if(!this$.hasClass('clicked')){
this$.addClass('clicked'); // not clicked yet, mark clicked to join group
this.style.opacity = '0.3'; // dim to show box is now in group
this$.draggable('disable'); // disable box's own draggable
if(group$.children().length <= 0){ // if no group members yet, this is first
group$.draggable().css({ // make group box draggable
top: '0px', // position at top left
left: '0px'
});
}
/*
Add group offset to this box offset
*/
top = parseInt(group$.css('top').replace('px','')) + // group's top +
parseInt(this$.css('top').replace('px','')); // box's top
left = parseInt(group$.css('left').replace('px','')) + // group's left +
parseInt(this$.css('left').replace('px','')); // box's left
this$.css({
top: top,
left: left
})
group$.append(this$); // move box inside of group container
}
else { // clicking a clicked element. Move from group container back to body
this$.removeClass('clicked');
this.style.opacity = '1.0'; // bring back full color
this$.draggable('enable'); // let box be draggable again on its own
/*
Add group offset to box offset
*/
top = parseInt(group$.css('top').replace('px','')) + // group's top +
parseInt(this$.css('top').replace('px','')); // box's top
left = parseInt(group$.css('left').replace('px','')) + // group's left +
parseInt(this$.css('left').replace('px','')); // box's left
...