;window.onload = (event) => {
// Setting up mousedown event
document.querySelector('table').addEventListener('mousedown',_onMouseDownTable, false)
};
/***
* Handling MouseDown event for the table
*/
function _onMouseDownTable(event){
// Checking if 'td' element...
if(
event.target &&
event.target.tagName.toLowerCase() === 'td'
){
const tObject = {Down: event.target};
// Adding event listener for marking cells
this.onmousemove = ((object, event) => {
if(
event.target &&
event.target.tagName.toLowerCase() === 'td'
){
object.Move = event.target
}
else{
delete object.Move
};
_markCells(object.Down, object.Move)
}).bind(null, tObject);
// Event listener for finishing cell marking
this.onmouseleave = this.onmouseup = ((object, event) => {
this.onmouseleave = this.onmousemove = this.onmouseup = null;
}).bind(null, tObject)
}
};
/***
* Marks cells between cell a and cell b
*/
function _markCells(a, b){
if(a && b){
// Finding parent table of cell a (usually same as b)
const tTable = a.closest('table');
// Clearing existing marks and border data
tTable.querySelectorAll('td.Marked, td[data-bounds-left], td[data-bounds-right], td[data-bounds-top], td[data-bounds-bottom]').forEach((td) => {
td.classList.remove('Marked');
delete td.dataset.boundsLeft;
delete td.dataset.boundsRight;
delete td.dataset.boundsTop;
delete td.dataset.boundsBottom
});
// Identifying the smallest (top/left) and largest coordinates
const
tMaxColumn = Math.max(Number(a.dataset.columnIndex), Number(b.dataset.columnIndex)),
tMaxRow = Math.max(Number(a.dataset.rowIndex), Number(b.dataset.rowIndex)),
tMinColumn = Math.min(Number(a.dataset.columnIndex), Number(b.dataset.columnIndex)),
tMinRow = Math.min(Number(a.dataset.rowIndex), Number(b.dataset.rowIndex));
// Marking all cells between Min and Max values
for(let row = tMinRow; row <= tMaxRow; row++){
for(let column = tMinColumn; column <= tMaxColumn; column++){
const tCell = tTable.querySelector(`td[data-row-index='${row}'][data-column-index='${column}']`);
if(tCell){
// Marking as left boundary if applicable
if(column === tMinColumn){
tCell.dataset.boundsLeft = true
};
// Marking as right boundary if applicable
if(column === tMaxColumn){
tCell.dataset.boundsRight = true
};
// Marking as top boundary if applicable
if(row === tMinRow){
tCell.dataset.boundsTop = true
};
// Marking as bottom boundary if applicable
if(row === tMaxRow){
tCell.dataset.boundsBottom = true
};
// Setting cell as marked
tCell.classList.add('Marked')
}
}
}
}
};
td{
border: 2px solid #000;
background-color: grey;
height: 25px;
width: 200px;
}
td.Marked{
background-color: #1e90ff
}
td.Marked[data-bounds-left]{
border-left-color: red
}
td.Marked[data-bounds-right]{
border-right-color: red
}
td.Marked[data-bounds-top]{
border-top-color: red
}
td.Marked[data-bounds-bottom]{
border-bottom-color: red
}
<table>
<tbody>
<tr>
<td data-column-index="0" data-row-index="0"></td>
<td data-column-index="1" data-row-index="0"></td>
<td data-column-index="2" data-row-index="0"></td>
<td data-column-index="3" data-row-index="0"></td>
<td data-column-index="4" data-row-index="0"></td>
</tr>
<tr>
<td data-column-index="0" data-row-index="1"></td>
<td data-column-index="1" data-row-index="1"></td>
<td data-column-index="2" data-row-index="1"></td>
<td data-column-index="3" data-row-index="1"></td>
<td data-column-index="4" data-row-index="1"></td>
</tr>
<tr>
<td data-column-index="0" data-row-index="2"></td>
<td data-column-index="1" data-row-index="2"></td>
<td data-column-index="2" data-row-index="2"></td>
<td data-column-index="3" data-row-index="2"></td>
<td data-column-index="4" data-row-index="2"></td>
</tr>
<tr>
<td data-column-index="0" data-row-index="3"></td>
<td data-column-index="1" data-row-index="3"></td>
<td data-column-index="2" data-row-index="3"></td>
<td data-column-index="3" data-row-index="3"></td>
<td data-column-index="4" data-row-index="3"></td>
</tr>
<tr>
<td data-column-index="0" data-row-index="4"></td>
<td data-column-index="1" data-row-index="4"></td>
<td data-column-index="2" data-row-index="4"></td>
<td data-column-index="3" data-row-index="4"></td>
<td data-column-index="4" data-row-index="4"></td>
</tr>
</tbody>
</table>