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'); 
    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
        
        this$.css({
      ...