iT邦幫忙

2018 iT 邦幫忙鐵人賽
DAY 10
1

Day10-課題內容

今天我們將透過click事件中的shift屬性以及陣列的觀念,來做出選取多個項目的功能。在作者的範例中,當勾選其中一個欄位之後,按著Shift再勾選任一一個欄位,這之間的每個欄位都會被勾選起來。[1]
實作連結

進入課題

要完成今天的目標,我們要依序完成幾樣事情:

  1. 監聽選取事件。
  2. 取得勾選的位置。
  3. 同時按下shift與滑鼠時,此次到上次勾選之間的欄位都要被勾選。

步驟一

首先我們將每個勾選欄位都加上監聽click事件,且透過console.log(event),我們可以發現click事件中包含了一個屬性shiftKey。透過這個屬性我們就能得知按下滑鼠的同時,shift按鍵是否也被按下,因此不需再額外監聽鍵盤的事件:

//選取所有的input元素
let checkInput = document.querySelectorAll('input');
//透過forEach方法將每個input元素加上監聽事件
checkInput.forEach(function (input) {
    input.addEventListener('click', selectMany);
});

步驟二

將前面因選取所有input元素而產生的NodeList物件,利用Array.from()方法轉為陣列,我們就能透過事件觸發時的event.target加上array.indexOf()來取得勾選欄的index。

//將NodeList物件轉為陣列
let InputArray = Array.from(checkInput);
//指定初始的勾選位置為0
let lastOrder = 0;

function selectMany(e) {
    //取得事件觸發的元素
    var test = e.target;
    //取得事件觸發的元素位置
    var checkOrder = InputArray.indexOf(test);
    //如果事件中包含shiftKey,執行check()函式
    if (e.shiftKey === true) {
        checked(checkOrder);
    };
    //將這次的位置,指定為下次的起始位置
    lastOrder = checkOrder;
};

步驟三

我們已經指定好符合條件時的函示checked()並引入代表後來勾選位置的參數值checkOrder,雖然已得知前後兩次的勾選位置,但我們無法確定每次的後一定都大於前值。因此在我們執行勾選的函式中,需要先判斷兩者的大小關係,之後再由小至大將之間的元素都勾選起來,就能完成今天的課題:

function checked(checkOrder) {
    //當後面勾選的位置 > 前面勾選的位置
    if (checkOrder > lastOrder) {
        //利用for迴圈由小到大取出之間的每個元素
        for (i = lastOrder; i < checkOrder; i++) {
            //之間的每個input元素設為勾選
             checkInput[i].checked = true;
        };
    };
    //當前面勾選的位置 > 後面勾選的位置
    } else {
        for (i = checkOrder; i < lastOrder; i++) {
            checkInput[i].checked = true;
        };
    };
};

總結

今天也是透過將取得的資料轉為陣列,再透過陣列的相關方法,取得我們DOM上的元素結點並加以應用。可以看到實作上有許多會應用到陣列的地方,如果能熟悉各種陣列方法,之後在資料處理方面將能夠更加的靈活。以上是今天的方法與心得,感謝您的閱讀。

參考資料

  1. javascript30

上一篇
JS30-Day9-Dev Tools Domination
下一篇
JS30-Day11-Custom Video Player
系列文
新手也能懂的JS3030

尚未有邦友留言

立即登入留言