I have the following grid:
.grid {
display: grid;
grid-template-columns: 100px 100px 100px 100px 100px;
grid-template-rows: 50px 50px 50px 50px;
grid-gap: 10px;
&>* {
padding: 10px;
border: 1px solid black;
}
&>div:first-child {
border: none;
}
& .column-header {
background-color: lightgray;
}
& .row-header {
background-color: lightgray;
}
}
<div class="grid">
<div></div>
<div class="column-header">Col 1</div>
<div class="column-header">Col 2</div>
<div class="column-header">Col 3</div>
<div class="column-header">Col 4</div>
<div class="row-header">Row 1</div>
<div>Cell 1.1</div>
<div>Cell 2.1</div>
<div>Cell 3.1</div>
<div>Cell 4.1</div>
<div class="row-header">Row 2</div>
<div>Cell 1.2</div>
<div>Cell 2.2</div>
<div>Cell 3.2</div>
<div>Cell 4.2</div>
<div class="row-header">Row 3</div>
<div>Cell 1.3</div>
<div>Cell 2.3</div>
<div>Cell 3.3</div>
<div>Cell 4.3</div>
<div class="row-header">Row 4</div>
<div>Cell 1.4</div>
<div>Cell 2.4</div>
<div>Cell 3.4</div>
<div>Cell 4.4</div>
</div>
How to use Javascript drag and drop api to:
I have put together this example:
First, set the draggable
attribute to true
for all headers.
Then you need to handle each drag event. See HTMLElement: dragstart event.
Lastly, you need to swap rows/columns.
Here is a working example (of course, you need to adjust hardcoded values or make it dynamic for your application):
let dragSrcEl = null;
function handleDragStart(e) {
this.style.opacity = '0.4';
dragSrcEl = this;
e.dataTransfer.effectAllowed = 'move';
e.dataTransfer.setData('text/html', this.innerHTML);
}
function handleDragEnd() {
this.style.opacity = '1';
items.forEach(function(item) {
item.classList.remove('over');
});
}
function handleDragOver(e) {
if (e.preventDefault) {
e.preventDefault();
}
return false;
}
function handleDragEnter() {
this.classList.add('over');
}
function handleDragLeave() {
this.classList.remove('over');
}
function handleDrop(e) {
if (e.stopPropagation) {
e.stopPropagation();
}
if (dragSrcEl !== this) {
if (dragSrcEl.classList.contains('column-header') && this.classList.contains('column-header')) {
swapColumns(dragSrcEl, this);
} else if (dragSrcEl.classList.contains('row-header') && this.classList.contains('row-header')) {
swapRows(dragSrcEl, this);
}
}
return false;
}
function swapColumns(src, dest) {
const srcIndex = Array.from(src.parentNode.children).indexOf(src);
const destIndex = Array.from(dest.parentNode.children).indexOf(dest);
const grid = document.querySelector('.grid');
for (let i = 0; i < grid.children.length; i++) {
if (i % 5 === srcIndex) {
const temp = grid.children[i].innerHTML;
grid.children[i].innerHTML = grid.children[i + (destIndex - srcIndex)].innerHTML;
grid.children[i + (destIndex - srcIndex)].innerHTML = temp;
}
}
}
function swapRows(src, dest) {
const srcIndex = Array.from(src.parentNode.children).indexOf(src) / 5;
const destIndex = Array.from(dest.parentNode.children).indexOf(dest) / 5;
const grid = document.querySelector('.grid');
for (let i = 0; i < 5; i++) {
const temp = grid.children[srcIndex * 5 + i].innerHTML;
grid.children[srcIndex * 5 + i].innerHTML = grid.children[destIndex * 5 + i].innerHTML;
grid.children[destIndex * 5 + i].innerHTML = temp;
}
}
let items = document.querySelectorAll('.grid .column-header, .grid .row-header');
items.forEach(function(item) {
item.addEventListener('dragstart', handleDragStart);
item.addEventListener('dragover', handleDragOver);
item.addEventListener('dragenter', handleDragEnter);
item.addEventListener('dragleave', handleDragLeave);
item.addEventListener('dragend', handleDragEnd);
item.addEventListener('drop', handleDrop);
});
.grid {
display: grid;
grid-template-columns: 100px 100px 100px 100px 100px;
grid-template-rows: 50px 50px 50px 50px;
grid-gap: 10px;
}
.grid>* {
padding: 10px;
border: 1px solid black;
}
.grid>div:first-child {
border: none;
}
.column-header,
.row-header {
background-color: lightgray;
cursor: move;
}
<div class="grid">
<div></div>
<div class="column-header" draggable="true">Col 1</div>
<div class="column-header" draggable="true">Col 2</div>
<div class="column-header" draggable="true">Col 3</div>
<div class="column-header" draggable="true">Col 4</div>
<div class="row-header" draggable="true">Row 1</div>
<div>Cell 1.1</div>
<div>Cell 2.1</div>
<div>Cell 3.1</div>
<div>Cell 4.1</div>
<div class="row-header" draggable="true">Row 2</div>
<div>Cell 1.2</div>
<div>Cell 2.2</div>
<div>Cell 3.2</div>
<div>Cell 4.2</div>
<div class="row-header" draggable="true">Row 3</div>
<div>Cell 1.3</div>
<div>Cell 2.3</div>
<div>Cell 3.3</div>
<div>Cell 4.3</div>
<div class="row-header" draggable="true">Row 4</div>
<div>Cell 1.4</div>
<div>Cell 2.4</div>
<div>Cell 3.4</div>
<div>Cell 4.4</div>
</div>