<!-- You'd need to set up something different for touch devices though -->
<h1>Drag and drop example </h1>
<div class="wrap">
<div id="phrase">
<label for="inp1">Enter a row A - H</label>
<input type="text" id="inp1" placeholder="Enter Row">
<label for="inp2">Enter a column 1 - 12</label>
<input id="inp2" type="number" min="1" max="12" pattern="[0-9] placeholder="Enter Column">
<button id="calculate">Calculate</button>
<p class="target">The cell number is <b id="cellnum">?</b></p>
<button id="move-text" type="button">Move Text Content!</button>
<!-- remove whitespace from inside div html and then we can use :empty in css to change background -->
<div data-id='1'><span class='words' data-id='1'>H1 text</span></div>
<div data-id='2'><span class='words' data-id='2'>H2 text</span></div>
<div data-id='3'><span class='words' data-id='3'>H3 text</span></div>
<div data-id='4'><span class='words' data-id='4'>H4 text</span></div>
<div data-id='5'><span class='words' data-id='5'>H5 text</span></div>
<div data-id='6'><span class='words' data-id='6'>H6 text</span></div>
<div data-id='7'><span class='words' data-id='7'>G1 text</span></div>
<div data-id='8'><span class='words' data-id='8'>G2 text</span></div>
<div data-id='9'><span class='words' data-id='9'>G3 text</span></div>
<div data-id='10'><span class='words' data-id='10'>G4 text</span></div>
</div>
<div id="drop-em" class="grid">
<div class="item">
<div class="content"></div><!-- must have no spaces inside .content -->
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
<div class="item">
<div class="content"></div>
</div>
</div>
</div>
/* see improved version here :
https://codepen.io/rpg2019/pen/ZEZpwZB
*/
html {
box-sizing: border-box;
}
*,
*:before,
*:after {
box-sizing: inherit;
}
body {
counter-reset: columnCount 1 alphaCount cellCount;
}
h1 {
text-align: center;
}
.wrap {
display: flex;
gap: 2rem;
position:relative;
padding-left:220px;
}
.grid {
margin: auto;
display: grid;
flex: 1 0 0;
grid-template-columns: repeat(12, 1fr);
padding-top: 1.5rem;
}
.item {
position: relative;
background-color: #f9f9f9;
border: 1px solid grey;
aspect-ratio: 1/1;
counter-increment: columnCount;
min-width: 0;
transition: background 1s ease;
}
.item:nth-of-type(12n + 1) {
counter-increment: alphaCount;
}
.item:nth-of-type(12n + 1)::before {
content: counter(alphaCount, upper-alpha);
position: absolute;
display: flex;
align-items: center;
top: 0;
bottom: 0;
left: -1.75rem;
color: red;
pointer-events: none;
}
.item:nth-of-type(n + 13)::after {
display: none;
}
.item::after {
content: counter(columnCount);
position: absolute;
left: 0;
right: 0;
text-align: center;
top: -1.75rem;
color: red;
pointer-events: none;
}
.content {
display: flex;
flex-direction: column;
justify-content: center;
width: 100%;
height: 100%;
overflow: auto;
color: #000;
padding: 1rem;
word-wrap: break-word;
counter-increment: cellCount;
}
.words {
cursor: move;
transition: padding 0.5s ease;
}
.content:has(.ui-draggable-dragging) {
overflow: visible;
}
.ui-droppable-active .content {
overflow: visible;
}
.words.ui-draggable-dragging {
background: blue;
padding: 5px 10px;
border-radius: 6px;
z-index: 999;
color: #fff;
display: block;
width: 50px;
height: 50px;
overflow: hidden;
}
#phrase {
position:absolute;
left:0;
top:0;
bottom:0;
color: #fff;
width:150px;
overflow:auto;
z-index: 2;
display: flex;
flex-direction: column;
margin:1rem 0 .5rem;
}
#phrase > div {
margin: 0 0 10px;
width:150px;
padding: 5px 10px;
background: #007bff;
border: 2px solid #007bff;
border-radius: 6px;
color: #fff;
}
#phrase > div:empty {
background: #fff;
border-style: dashed;
padding: 0px 25px;
min-height: 30px;
}
.moved {
animation: fade 3s ease;
}
@keyframes fade {
0% {
opacity: 0;
}
50% {
opacity: 1;
background: red;
}
}
.item .content::before {
content: counter(cellCount);
position: absolute;
top: 2px;
left: 2px;
font-size: smaller;
color: #666;
border-radius: 50%;
border: 1px solid red;
background: white;
width: 1.2rem;
height: 1, 2rem;
display: grid;
place-items: center;
}
#move-text.disabled{
cursor:none;
pointer-events:none;
opacity:0.5;
}
#phrase:has(.ui-droppable-active){
overflow:visible;
}
input,
button,
label,
p.target {
display: block;
margin: 0 0 0.4rem;
color:#000;
}
p.target {margin:0 0 1rem}
/* see improved version here :
https://codepen.io/rpg2019/pen/ZEZpwZB
*/
/*
Requires jquery + UI
https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js
https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js
*/
$(".words").draggable({
revert: function (event, ui) {
var bRevertingPhrase = this.closest("#drop-em");
if (!bRevertingPhrase.length) {
var phraseID = $(this).data("id");
var phraseHomeID = $(this).parent().data("id");
//If the child and parent ids don't match, we move the child to the correct parent
if (phraseID !== phraseHomeID) {
var correctCell = $("#phrase").find("div[data-id='" + phraseID + "']");
correctCell.prepend(this);
}
}
return !event;
}
});
$("#drop-em > div").droppable({
drop: function (ev, ui) {
$(ui.draggable)
.detach()
.css({ top: 0, left: 0 })
.appendTo($(this).find(".content:empty"));
$("#move-text").addClass("disabled");
}
});
$("#phrase > div").droppable({
drop: function (ev, ui) {
$(ui.draggable).detach().css({ top: 0, left: 0 }).prependTo(this);
}
});
const myButton = document.querySelector("#move-text");
myButton.addEventListener(
"click",
() => {
fill();
},
{
once: true
}
);
var reOrder = [];
function fill() {
const cells = document.querySelectorAll("#phrase > div > span");
var newLoc = "";
const celLength = cells.length;
var myIndex = 0;
myButton.classList.add("disabled");
cells.forEach((cell, index) => {
newLoc = document.querySelector(
".item:nth-child(" + reOrder[myIndex + startPos-1] + ") .content "
);
newLoc.append(cell);
newLoc.classList.add("moved");
if (index + startPos-1 === 95){
startPos = 0;
myIndex = 0;
}
myIndex ++;
});
}
function reArrange() {
var limit1 = 85;
var limit2 = 91;
for (let loop = 0; loop < 8; loop++) {
for (let i = 0; i < 6; i++) {
reOrder.push(limit1 + i);
}
limit1 = limit1 - 12;
}
for (let loop = 0; loop < 8; loop++) {
for (let j = 0; j < 6; j++) {
reOrder.push(limit2 + j);
}
limit2 = limit2 - 12;
}
}
reArrange();
/* get cell number */
const myRow = document.querySelector("#inp1");
const myCol = document.querySelector("#inp2");
var startPos = 1;
const myCalculateButton = document.querySelector("#calculate");
const myAnswer = document.querySelector("#cellnum");
myCalculateButton.addEventListener("click", () => {
var rowNumber = myRow.value.toUpperCase();
var colNumber = myCol.value;
var result = 0;
switch (rowNumber) {
case "A":
rowNumber = 42;
break;
case "B":
rowNumber = 36;
break;
case "C":
rowNumber = 30;
break;
case "D":
rowNumber = 24;
break;
case "E":
rowNumber = 18;
break;
case "F":
rowNumber = 12;
break;
case "G":
rowNumber = 6;
break;
case "H":
rowNumber = 0;
break;
}
if (colNumber < 7) {
result = rowNumber + parseInt(colNumber);
} else {
result = rowNumber + 42 + parseInt(colNumber);
}
myAnswer.innerHTML = result;
startPos= result;
});
This Pen doesn't use any external CSS resources.