iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 16
1
自我挑戰組

30天找回寫程式手感計劃!!!系列 第 16

Day16 - 雖然很久沒有國際賽事,還是要用 JavaScript 關心一下小戴的 World Rankings!─ addEventListener 篇

  • 分享至 

  • xImage
  •  

對不起,在下小的我要用小戴女神撐過 2 天了QQ
小戴對不起(#

正片開始

本日主題:事件監聽

昨天初步用 JavaScript 控制了網頁元素,
今天要來更進階的 addEventListener 事件監聽,
這就是像如果滑鼠 hover 過去或點下元件要做什麼事。

昨天只有列出世界女單前 25 名與小戴現在分數差距,
如果我想要知道世界女單前 25 名各國選手各有幾個要怎麼辦呢?

先弄出下拉式選單,並增加元素監聽

這邊我們先在 html 寫出下拉式選單:

<select name="" id="optionSelected">
    <option value="1">1. 世界女單前 25 名與小戴現在分數差距</option>
    <option value="2">2. 世界女單前 25 名人數 (by國家)</option>
</select>

https://ithelp.ithome.com.tw/upload/images/20200922/20129873liQAKKx5qS.png

然後我們為下拉式選單增加 addEventListener
我們的最終目標是根據點擊的下拉式選單的選項(值)下面要顯示不同內容。
一開始我們先監聽這個元件的點擊事件,
所以我們就可以在 JavaScript 寫:

const optionElement = document.getElementById("optionSelected");
optionElement.addEventListener("click",contentShow); // 當下拉式選單被點擊時,要執行什麼函數
function countryShow(){
    console.log("有被點擊到");
}

https://ithelp.ithome.com.tw/upload/images/20200922/201298730poxLF2q0k.png
看來有做出我們想要的樣子~~~

取得點擊的下拉式選單的值

JavaScript 中有一個可以取得觸發事件當下物件的值 event.target.value
有興趣的可以 console.log(event) 出來看看,裡面有很多東西可以研究XD
本日就先暫時不介紹。

function contentShow(event){
    console.log("有被點擊到");
    console.log(`所點擊的值為: ${event.target.value}`);
}

https://ithelp.ithome.com.tw/upload/images/20200922/20129873z0k6VHEnCG.png

要怎麼取出不同國家的選手有多少

除了事件監聽,
本日還有一個大難題要解決,
我們要怎麼從 25 個女單選手中 distinct 出 國家與人數對照呢?
這邊我之前有試過要自己寫,寫不出來,
於是只好網路搜尋大大的解法了,下面有稍微註解一下。
不過這邊稍微講一下,
大概做法是將國家存成陣列的 index 值,
然後每次拿到一個國家都去搜尋 陣列[國家] 存不存在,
不存在就將 Count 設為 1,存在就將 Count +1。

function findLand(inputArray){
    let obj = []; //虛擬存不同的國家字串
    let objAll = []; //存國家字串跟出現次數

    for ( let i=0; i < inputArray.length; i++){
        // distinct出不同國家
        if ( !obj[inputArray[i].Land] ){
            obj[inputArray[i].Land] = 1;
            objAll.push({Country:inputArray[i].Land,Count:obj[inputArray[i].Land]});
        }
        else{
            //存國家跟次數
            for (var j=0; j < objAll.length; j++){
                if( objAll[j].Country === inputArray[i].Land ){
                    objAll[j].Count += 1;
                }
            }
        }
    }
    return objAll;
}

然後我們要驗證這個函數會不會 work,
所以這樣寫:

let countryCount = findLand(players);
for ( let i=0; i<countryCount.length; i++){
    console.log(`${countryCount[i].Country} 有 ${countryCount[i].Count}`);
}

https://ithelp.ithome.com.tw/upload/images/20200922/20129873MmQq6yZFpa.png

看起來有成功 distinct 出不同國家及數量,
這個函數真的滿好用的,
我自己用很多次XD

根據 event.target.value 值的不同,要顯示不同結果

這邊是本日最後一個關卡了,
其實不難,讓我們勇敢的上吧XD

根據值不同要做不同事,
有一個好用的東西叫 switch case,(應該幾乎所有程式語言都有這個東西)

讓我們先用 JavaScript 寫一下:

switch(event.target.value){
    case 1:
        console.log(" 1 有被點擊到");
        break;
    case 2:
        console.log(" 2 有被點擊到");
        break;
    default:
        console.log("default");
        break;
}

嗯?為什麼一直走到 default 的邏輯?
https://ithelp.ithome.com.tw/upload/images/20200922/20129873hmpMV9WeOs.png

該不會是 type 不一樣吧!
讓我們看看 event.target.value 的 type 是什麼吧!

console.log(`event.target.value 的 type 是 ${typeof(event.target.value)}`);

https://ithelp.ithome.com.tw/upload/images/20200922/20129873dUqyu0YbQa.png
抓到了!switch 比的值是數字,
event.target.value 是 string 型態,
所以前面要用 parseInt 轉換成整數。

switch(parseInt(event.target.value)){
    case 1:
        console.log(" 1 有被點擊到!");
        break;
    case 2:
        console.log(" 2 有被點擊到!");
        break;
    default:
        console.log("default");
        break;
}

https://ithelp.ithome.com.tw/upload/images/20200922/20129873dKKLrsoSev.png
耶,正常比對了,
那我們繼續往下寫吧。

function contentShow(event){
    // console.log(`所點擊的值為: ${event.target.value}`);
    // console.log(`event.target.value 的 type 是 ${typeof(event.target.value)}`);
    switch(parseInt(event.target.value)){
        case 1:
            // console.log(" 1 有被點擊到!");
            tableHTMLStr = `<tr><th>名次</th><th>選手</th><th>差距(分)</th></tr>`; // 表格標頭
            for ( let i=1; i<players.length; i++){ // 要從第 2 個開始,因為小戴自己是基準
                // 其實可以合成 1 行,拆 2 行只是方便閱讀
                tableHTMLStr += `<tr><td>${players[i].Rank}</td><td>${players[i].Speler}</td>`;
                tableHTMLStr += `<td>${players[0].Punten - players[i].Punten}</td></tr>`;
            }
            break;
        case 2:
            // console.log(" 2 有被點擊到!");
            tableHTMLStr = `<tr><th>國家</th><th>選手數</th></tr>`; // 表格標頭
            for ( let i=0; i<countryCount.length; i++){
                tableHTMLStr += `<tr><td>${countryCount[i].Country}</td><td>${countryCount[i].Count}</td></tr>`;
            }
            break;
        default:
            console.log("default");
            break;
    }
    tableElement.innerHTML = tableHTMLStr;
}

https://ithelp.ithome.com.tw/upload/images/20200922/201298738TlzotTlRW.png
https://ithelp.ithome.com.tw/upload/images/20200922/20129873D8drTHSq5D.png
耶!本日打完收工!

[後記]

其實本日的 addEventListener("click")
有更好的做法是 addEventListener("change")
偵測值的改變才去做,而不是 click 到就要做,
但今天是複習 addEventListener 的感覺,
還是先用起手式 click 開始XD

[本日程式碼]

Codepen


上一篇
Day15 - 雖然很久沒有國際賽事,還是要用 JavaScript 關心一下小戴的 World Rankings!─ getElementById 篇
下一篇
Day17 - Open Data x JavaScript x JSON
系列文
30天找回寫程式手感計劃!!!36
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言