JSFiddle - React, Tailwind, and code Playground
HTML
<div>
<select id="sel">
<option value="p1">Profile 1</option>
<option value="p2">Profile 2</option>
<option value="p3">Profile 3</option>
</select>
</div>
<div class='wrapper'>
<div class='head'>
<div>Mon</div>
<div>Tue</div>
<div>Wed</div>
<div>Thu</div>
<div>Fri</div>
<div>Sat</div>
<div>Sun</div>
</div>
<div>
<div class='pre'>
<div>00:00</div>
<div>00:30</div>
<div>01:00</div>
<div>01:30</div>
<div>02:00</div>
<div>02:30</div>
<div>03:00</div>
<div>03:30</div>
<div>04:00</div>
<div>04:30</div>
<div>05:00</div>
<div>05:30</div>
<div>06:00</div>
<div>06:30</div>
<div>07:00</div>
</div>
<div class='table'>
<div class='row'>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
<div class='row'>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
<div class='row'>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
<div class='row'>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
<div class='row'>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
<div class='row'>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
<div class='row'>
<div></div>
<div></div>
...
CSS
body {
margin: 0;
padding: 0;
}
.head {
font-size: 0;
margin-left: 32px;
}
.head > div {
font-size: 12px;
display: inline-block;
width: 25px;
margin: 0 2px;
text-align: center;
}
.pre {
display: inline-block;
font-size: 0;
vertical-align: top;
width: 32px;
margin-top: -8px;
}
.pre > div {
height: 25px;
margin: 2px 0;
font-size: 12px;
display: inline-block;
}
.table {
display: inline-block;
}
.wrapper {
display: inline-block;
position: relative;
}
.row {
font-size: 0;
}
.row > div {
display: inline-block;
border: 1px solid black;
margin: 1px;
width: 25px;
height: 25px;
}
.p1 {
background: green;
}
.p2 {
background: blue;
}
.p3 {
background: orange;
}
.selected {
background: grey;
}
JavaScript
const table = document.querySelector('.table');
const rows = document.querySelectorAll('.row');
const sqSize = 28;
let selValue = 'p1';
let didMouseMove = false;
let startRow;
let startCol;
const cb = (e) => {
didMouseMove = true;
const x = e.clientX - table.offsetLeft;
const y = e.clientY - table.offsetTop;
const row = Math.round(y / sqSize);
const col = Math.round(x / sqSize);
for(let i=0; i < rows.length; i++) {
for(let j=0; j < rows[i].children.length; j++) {
if((j >= (startCol-1) && j <= (col-1) && i >= (startRow-1) && i < (row-1))) {
rows[i].children[j].classList.add('selected');
} else if((j > (startCol-1)) && (j <= (col-1)) && (i < (startRow-1))) {
rows[i].children[j].classList.add('selected');
} else if((j < (col-1) && (j >= (startCol-1)) && (i >= (row-1)))) {
rows[i].children[j].classList.add('selected');
} else {
rows[i].children[j].classList.remove('selected');
}
}
}
}
table.addEventListener('mousedown', (e) => {
startRow = Math.round((e.clientY - table.offsetTop) / sqSize);
startCol = Math.round((e.clientX - table.offsetLeft) / sqSize);
table.addEventListener('mousemove', cb);
});
table.addEventListener('mouseup', (e) => {
const x = table.querySelectorAll('.selected');
for (let i = 0; i < x.length; i++) {
x[i].className = selValue;
}
if(!didMouseMove && !e.target.classList.contains('row')) {
e.target.classList.toggle(selValue);
}
didMouseMove = false;
table.removeEventListener('mousemove', cb);
});
document.getElementById('sel').addEventListener('change', (e) => {
selValue = e.target.value;
});