俗話說的好,一天一蘋果,醫生遠離我
一天一 JS,What the f*ck JavaScript?
small steps every day - 記錄著新手村日記
shift
對另一個打勾,中間的選項會自動勾起來shift
」勾選,若畫面上已有打勾,則此次和上次打勾的選項中間都要自動打勾<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Hold Shift to Check Multiple Checkboxes</title>
</head>
<body>
<style>
html {
font-family: sans-serif;
background: #ffc600;
}
.inbox {
max-width: 400px;
margin: 50px auto;
background: white;
border-radius: 5px;
box-shadow: 10px 10px 0 rgba(0,0,0,0.1);
}
.item {
display: flex;
align-items: center;
border-bottom: 1px solid #F1F1F1;
}
.item:last-child {
border-bottom: 0;
}
input:checked + p {
background: #F9F9F9;
text-decoration: line-through;
}
input[type="checkbox"] {
margin: 20px;
}
p {
margin: 0;
padding: 20px;
transition: background 0.2s;
flex: 1;
font-family:'helvetica neue';
font-size: 20px;
font-weight: 200;
border-left: 1px solid #D1E2FF;
}
</style>
<!--
The following is a common layout you would see in an email client.
When a user clicks a checkbox, holds Shift, and then clicks another checkbox a few rows down, all the checkboxes inbetween those two checkboxes should be checked.
-->
<div class="inbox">
<div class="item">
<input type="checkbox">
<p>This is an inbox layout.</p>
</div>
<div class="item">
<input type="checkbox">
<p>Check one item</p>
</div>
<div class="item">
<input type="checkbox">
<p>Hold down your Shift key</p>
</div>
<div class="item">
<input type="checkbox">
<p>Check a lower item</p>
</div>
<div class="item">
<input type="checkbox">
<p>Everything in between should also be set to checked</p>
</div>
<div class="item">
<input type="checkbox">
<p>Try to do it without any libraries</p>
</div>
<div class="item">
<input type="checkbox">
<p>Just regular JavaScript</p>
</div>
<div class="item">
<input type="checkbox">
<p>Good Luck!</p>
</div>
<div class="item">
<input type="checkbox">
<p>Don't forget to tweet your result!</p>
</div>
</div>
<script>
</script>
</body>
</html>
首先,透過 querySelectorAll
抓出 type="checkbox"
,為了方便之後可以使用 foreach
迴圈讀出每項checkbox,因此再將它轉為陣列 Array.from
,如果被點擊的話,觸發 clickHandler
這個方法印出 MouseEvent
可以操作的項目,然後來看看裡面有什麼...
<script>
const checkboxes = Array.from(document.querySelectorAll('.inbox input[type="checkbox"]'));
checkboxes.forEach(function(input){
input.addEventListener("click", clickHandler);
})
function clickHandler(env){
console.log(env);
}
</script>
根據題目要求,我們要執行的是按住 Shift 按鈕觸發功能,在上方程式碼的 env
變數中,印出來的觸發事件如下,可以看到 shiftKey: false
這個事件物件,勾起來是 true
,反之
// MouseEvent {isTrusted: true, screenX: 287, screenY: 265, clientX: 316, clientY: 80, …}
// altKey: false
// bubbles: true
// button: 0
// buttons: 0
// cancelBubble: false
// cancelable: true
// clientX: 316
// clientY: 80
// -------------------略--------------------
// screenX: 287
// screenY: 265
// shiftKey: false
// sourceCapabilities: InputDeviceCapabilities {firesTouchEvents: true}
// srcElement: input
// target: input
// timeStamp: 1173.464999999851
// toElement: input
// type: "click"
// view: Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, parent: Window, …}
// which: 1
// x: 316
// y: 80
// __proto__: MouseEvent
不過要先要紀錄我們點到的 checkbox 是陣列中的第幾個,透過 indexOf
算出並記於變數 firstCheck
中
<script>
const checkboxes = Array.from(document.querySelectorAll('.inbox input[type="checkbox"]'));
checkboxes.forEach(function(input){
input.addEventListener("click", clickHandler);
})
function clickHandler(env){
// console.log(env);
firstCheck = checkboxes.indexOf(this)
console.log(firstCheck);
}
</script>
變數 firstCheck
代表紀錄使用者一開始點的 Checkbox,先宣告一開始是空值,如果使用者點下 Checkbox,就記錄下剛剛抓的陣列第幾個,反之為 null
<script>
const checkboxes = Array.from(document.querySelectorAll('.inbox input[type="checkbox"]'));
checkboxes.forEach(function(input){
input.addEventListener("click", clickHandler);
})
let firstCheck = null;
function clickHandler(env){
// console.log(env);
if (this.checked) {
firstCheck = checkboxes.indexOf(this);
} else {
firstCheck = null;
}
}
</script>
當有 ShiftKey 並且 firstCheck 不是空值的話,可以抓到使用者第二個按下的按鈕,並且透過 slice
將點擊的兩個按鈕排列 Math.min / Math.max
,在將全部打勾的讀出來設定為打勾勾
<script>
const checkboxes = Array.from(document.querySelectorAll('.inbox input[type="checkbox"]'));
checkboxes.forEach(function(input){
input.addEventListener("click", clickHandler);
})
let firstCheck = null;
function clickHandler(env){
if (this.checked) {
if (env.shiftKey && firstCheck !== null) {
let secondCheck = checkboxes.indexOf(this);
checkboxes
.slice(
Math.min(secondCheck, firstCheck),
Math.max(secondCheck, firstCheck)
)
.forEach(input => (input.checked = true));
}
firstCheck = checkboxes.indexOf(this);
} else {
firstCheck = null;
}
}
</script>
就大功告成啦!
<script>
const checkboxes = Array.from(document.querySelectorAll('.inbox input[type="checkbox"]'));
checkboxes.forEach(function(input){
input.addEventListener("click", clickHandler);
})
let firstCheck = null;
function clickHandler(env){
if (this.checked) {
if (env.shiftKey && firstCheck !== null) {
let secondCheck = checkboxes.indexOf(this);
checkboxes
.slice(
Math.min(secondCheck, firstCheck),
Math.max(secondCheck, firstCheck)
)
.forEach(input => (input.checked = true));
}
firstCheck = checkboxes.indexOf(this);
} else {
firstCheck = null;
}
}
</script>
本刊同步於個人網站:http://chestertang.site/
本次範例程式碼原作者來源:https://tinyurl.com/yavm5f5n