Select elements by dragging a box
by Génesis García Morilla
CSS
ul {
list-style-type: none;
display: flex;
flex-flow: row wrap;
}
li {
width: 80px;
height: 80px;
margin: 2px;
font-size: 2rem;
color: darkslategrey;
display: flex;
justify-content: center;
align-items: center;
user-select: none;
}
#box {
position: absolute;
left: 0;
top: 0;
border: 1px dotted darkslategrey;
}
.selected {
background: #FECA40;
}
JavaScript
document.querySelector('ul').innerHTML = [...Array(1000).keys()]
.reduce((sum, _, i) => sum + `<li>${i}</li>`, '')
// Select elements by dragging a box
let x0, y0
const $$li = document.querySelectorAll('li')
function is_inside(a, b, x, y) {
return a <= x && a >= x0 && b <= y && b >= y0
}
document.onmousedown = ({ pageX: x, pageY: y } = event) => {
x0 = x, y0 = y
$$li.forEach($li => $li.classList.remove('selected'))
let box = document.createElement('div')
box.id = 'box'
document.body.append(box)
box.style.left = `${x0}px`
box.style.top = `${y0}px`
document.onmousemove = ({ pageX: x, pageY: y } = event) => {
if (x0 > x) box.style.left = `${x}px`
if (y0 > y) box.style.top = `${y}px`
box.style.width = `${Math.abs(x - x0)}px`
box.style.height = `${Math.abs(y - y0)}px`
}
}
document.onmouseup = ({ pageX: x, pageY: y } = event) => {
document.querySelector('#box').remove()
document.onmousemove = null
// Swap variables to allow selections from all directions
if (x0 > x) [x0, x] = [x, x0]
if (y0 > y) [y0, y] = [y, y0]
if (x - x0 < 15 && y - y0 < 15) return
// Make selection at least as big as the element where it begins
let { left, top, width, height } =
document.elementFromPoint(x0 - scrollX, y0 - scrollY)
.getBoundingClientRect()
if (x - x0 < width) x0 = left + scrollX
if (y - y0 < height) y0 = top + scrollY
$$li.forEach($li => {
let { left: a, top: b, width: w, height: h } =
$li.getBoundingClientRect()
a += scrollX
b += scrollY
if ([[a, b], [a + w, b], [a, b + h], [a + w, b + w]]
.some(coo => is_inside(...coo, x, y)))
$li.classList.add('selected')
})
}