|
@@ -0,0 +1,98 @@
|
|
|
+window.onload = function()
|
|
|
+{
|
|
|
+ let dragStart = null
|
|
|
+ let currentTargetChecked = null
|
|
|
+ let originalStates = []
|
|
|
+
|
|
|
+ const checkables = []
|
|
|
+ for (const element of document.getElementsByClassName("checkable"))
|
|
|
+ {
|
|
|
+ element.onmousedown = mouseDownHandler
|
|
|
+ element.onclick = function(e) { e.preventDefault() }
|
|
|
+ if(element.tagName == "INPUT")
|
|
|
+ checkables.push(element)
|
|
|
+ }
|
|
|
+
|
|
|
+ document.onmousemove = mouseMoveHandler
|
|
|
+ document.onmouseup = mouseUpHandler
|
|
|
+
|
|
|
+ function mouseDownHandler(e)
|
|
|
+ {
|
|
|
+ dragStart = {x: e.clientX, y: e.clientY}
|
|
|
+ let currentTarget
|
|
|
+ if (e.target.tagName == "INPUT")
|
|
|
+ {
|
|
|
+ currentTarget = e.target
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ currentTarget = e.target.parentNode.getElementsByTagName("input")[0]
|
|
|
+ }
|
|
|
+ currentTargetChecked = !currentTarget.checked
|
|
|
+ currentTarget.checked = currentTargetChecked
|
|
|
+
|
|
|
+ // save current state of all checkables
|
|
|
+ originalStates = []
|
|
|
+ for (let checkable of checkables)
|
|
|
+ originalStates.push(checkable.checked)
|
|
|
+ }
|
|
|
+ function mouseUpHandler(e)
|
|
|
+ {
|
|
|
+ if (!dragStart)
|
|
|
+ return
|
|
|
+ dragStart = null
|
|
|
+ let rectElement = document.getElementById("rect")
|
|
|
+ if (rectElement)
|
|
|
+ rectElement.parentNode.removeChild(rectElement)
|
|
|
+ }
|
|
|
+ function mouseMoveHandler(e)
|
|
|
+ {
|
|
|
+ if (!dragStart)
|
|
|
+ return
|
|
|
+
|
|
|
+ // get rectangle of dragged area
|
|
|
+ let rect = {
|
|
|
+ left: Math.min(dragStart.x, e.clientX),
|
|
|
+ top: Math.min(dragStart.y, e.clientY),
|
|
|
+ right: Math.max(dragStart.x, e.clientX),
|
|
|
+ bottom: Math.max(dragStart.y, e.clientY)
|
|
|
+ }
|
|
|
+ // draw rectangle
|
|
|
+ let rectElement = document.getElementById("rect")
|
|
|
+ if (!rectElement)
|
|
|
+ {
|
|
|
+ rectElement = document.createElement("div")
|
|
|
+ rectElement.id = "rect"
|
|
|
+ rectElement.style.position = "absolute"
|
|
|
+ rectElement.style.border = "1px solid black"
|
|
|
+ rectElement.style.zIndex = "100"
|
|
|
+ document.body.appendChild(rectElement)
|
|
|
+ }
|
|
|
+ rectElement.style.left = rect.left + "px"
|
|
|
+ rectElement.style.top = rect.top + "px"
|
|
|
+ rectElement.style.width = (rect.right - rect.left) + "px"
|
|
|
+ rectElement.style.height = (rect.bottom - rect.top) + "px"
|
|
|
+
|
|
|
+ // get all checkables in dragged area
|
|
|
+ for(let i = 0; i < checkables.length; i++)
|
|
|
+ {
|
|
|
+ let checkable = checkables[i]
|
|
|
+
|
|
|
+ let checkableRect = checkable.parentNode.getBoundingClientRect()
|
|
|
+ // check if checkable intersects the dragged area
|
|
|
+ if (checkableRect.left < rect.right &&
|
|
|
+ checkableRect.right > rect.left &&
|
|
|
+ checkableRect.top < rect.bottom &&
|
|
|
+ checkableRect.bottom > rect.top)
|
|
|
+ {
|
|
|
+ checkable.checked = currentTargetChecked
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ checkable.checked = originalStates[i]
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+}
|
|
|
+
|