С небольшой модификацией вы можете сделать это так:
<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='utf-8' />
<title></title>
<style>
#grid {
display: grid;
grid-template-columns: repeat(3, 50px);
grid-template-rows: repeat(2, 50px);
}
.cell {
display: flex;
justify-content: center;
align-items: center;
border: solid 1px #ccc;
}
.active {
background-color: #80aaff;
}
</style>
<script>
document.addEventListener('DOMContentLoaded',e=>{
const grid = document.getElementById('grid')
const cells= grid.querySelectorAll('div');
grid.addEventListener('click',function(e){
e.stopPropagation();
cells.forEach( cell=>{
cell.classList.remove('active')
});
event.target.classList.add('active');
if( event.ctrlKey ) {
Array.from(cells).some( cell=>{
cell.classList.add('active')
if( cell==event.target )return true;
})
}
});
});
</script>
</head>
<body>
<div id="grid">
<div class="cell">1</div>
<div class="cell">2</div>
<div class="cell">3</div>
<div class="cell">4</div>
<div class="cell">5</div>
<div class="cell">6</div>
</div>
</body>
</html>
document.addEventListener('DOMContentLoaded',e=>{
const grid = document.getElementById('grid')
const cells= grid.querySelectorAll('div');
grid.addEventListener('click',function(e){
e.stopPropagation();
cells.forEach( cell=>{
cell.classList.remove('active')
});
e.target.classList.add('active');
if( e.ctrlKey ) {
Array.from(cells).some( cell=>{
cell.classList.add('active')
if( cell==e.target )return true;
})
}
});
});
#grid {
display: grid;
grid-template-columns: repeat(3, 50px);
grid-template-rows: repeat(2, 50px);
}
.cell {
display: flex;
justify-content: center;
align-items: center;
border: solid 1px #ccc;
}
.active {
background-color: #80aaff;
}
<div id="grid">
<div class="cell">1</div>
<div class="cell">2</div>
<div class="cell">3</div>
<div class="cell">4</div>
<div class="cell">5</div>
<div class="cell">6</div>
</div>
Исходя из комментария о том, что это не работает задом наперед, я немного перефразировал оригинал, чтобы он работал в обоих направлениях выбора. В отредактированной версии используются атрибуты dataset
- в этом случае они назначаются как целые числа. Ведется запись о щелчке по начальной ячейке, и, если нажата клавиша ctrl
, выполняется простой расчет, чтобы определить, выбирает ли пользователь вперед или назад, что, в свою очередь, влияет на используемый l oop и, таким образом, на присвоение активный класс. Небольшая настройка CSS с использованием переменных была просто для удобства ...
<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='utf-8' />
<title></title>
<style>
:root{
--rows:2;
--cols:3;
--size:50px;
}
#grid {
display:grid;
grid-template-columns:repeat(var(--cols),var(--size));
grid-template-rows:repeat(var(--rows),var(--size));
width:calc(var(--size) * var(--cols));
}
.cell {
display: flex;
flex:1;
justify-content: center;
align-items: center;
border: solid 1px #ccc;
margin:1px;
cursor:pointer;
}
.active {
background-color: #80aaff;
}
</style>
<script>
document.addEventListener('DOMContentLoaded',e=>{
let range=[];
const grid = document.getElementById('grid')
const cells = grid.querySelectorAll('div');
const getcell=function(i){
return grid.querySelector('[data-index="'+i+'"]');
}
const clickhandler=function(e){
e.stopPropagation();
range.push( e.target );
/* clear cells of the "active" class */
cells.forEach( cell=>{
cell.classList.remove('active')
});
/* Assign the initially selected cell as "active" */
e.target.classList.add('active');
if( e.ctrlKey ) {
/* Is the user selecting forwards or backwards? */
if( range[0].dataset.index < e.target.dataset.index ){
for( let i=range[0].dataset.index; i < e.target.dataset.index; i++ )getcell(i).classList.add('active')
} else if( range[0].dataset.index == e.target.dataset.index ){
e.target.classList.add('active')
} else {
for( let i=range[0].dataset.index; i > e.target.dataset.index; i-- )getcell(i).classList.add('active')
}
range=[];
}
};
/* assign an integer index to each cell within parent */
cells.forEach( ( cell, index )=>{
cell.dataset.index = index + 1;
});
grid.addEventListener( 'click', clickhandler );
});
</script>
</head>
<body>
<div id="grid">
<div class="cell">1</div>
<div class="cell">2</div>
<div class="cell">3</div>
<div class="cell">4</div>
<div class="cell">5</div>
<div class="cell">6</div>
</div>
</body>
</html>
document.addEventListener('DOMContentLoaded',e=>{
let range=[];
const grid = document.getElementById('grid')
const cells = grid.querySelectorAll('div');
const getcell=function(i){
return grid.querySelector('[data-index="'+i+'"]');
}
const clickhandler=function(e){
e.stopPropagation();
range.push( e.target );
/* clear cells of the "active" class */
cells.forEach( cell=>{
cell.classList.remove('active')
});
/* Assign the initially selected cell as "active" */
e.target.classList.add('active');
if( e.ctrlKey ) {
/* Is the user selecting forwards or backwards? */
if( range[0].dataset.index < e.target.dataset.index ){
for( let i=range[0].dataset.index; i < e.target.dataset.index; i++ )getcell(i).classList.add('active')
} else if( range[0].dataset.index == e.target.dataset.index ){
e.target.classList.add('active')
} else {
for( let i=range[0].dataset.index; i > e.target.dataset.index; i-- )getcell(i).classList.add('active')
}
range=[];
}
};
/* assign an integer index to each cell within parent */
cells.forEach( ( cell, index )=>{
cell.dataset.index = index + 1;
});
grid.addEventListener( 'click', clickhandler );
});
:root{
--rows:2;
--cols:3;
--size:50px;
}
#grid {
display:grid;
grid-template-columns:repeat(var(--cols),var(--size));
grid-template-rows:repeat(var(--rows),var(--size));
width:calc(var(--size) * var(--cols));
}
.cell {
display: flex;
flex:1;
justify-content: center;
align-items: center;
border: solid 1px #ccc;
margin:1px;
cursor:pointer;
}
.active {
background-color: #80aaff;
}
<div id="grid">
<div class="cell">1</div>
<div class="cell">2</div>
<div class="cell">3</div>
<div class="cell">4</div>
<div class="cell">5</div>
<div class="cell">6</div>
</div>