進階的 Javascript 分享

分享常見的 Javascript 副程式,索引:

個案1:掛號網站驗證碼OCR結果錯誤的改善方法

掛號網站站的驗證碼是 5位的數字,就是5個整數,部份的數字會誤判為英文,例如:數字 9 判斷為英文 g, 數字 0 判斷為英文 o,解法是先判斷驗證碼是否為正整數:

function isInteger(value) {
    return /^-?\d+$/.test(value);
}

更多進階數字判斷:
https://stackoverflow.max-everyday.com/2024/03/javascript-isnumeric/


個案2:自動登入帳密,並延遲按下送出按鈕

let user_id = "your-account";
let user_password = "your-password";
let login_delay_interval = 3000;
$("#account_selector").val(user_id);
$("#password_selector").val(user_password);
setTimeout(() => {
    $("#submit_selecotor").click();
}, login_delay_interval);

由於慢慢登入就可以了,所以增加了 setTimeout 進行延遲,操作起來會更像真的人。


個案3:cityline 是否正在查詢座位

const loadingoverlay = $(".loadingoverlay");
const loading_display = loadingoverlay.css("display");
let able_to_work = true;
if (loading_display && loading_display == "flex") {
    able_to_work = false;
}

able_to_work == true, 就是可以按下訂位,反之就是正在查詢座位。


個案4:關鍵字比對需「全部符合」

當輸入的關鍵字使用了空格” “, 例如:”12/01 16:45″, 代表應該要同時符合”12/01” 而且也要出現 “16:45”

// AND logic
if (area_keyword.indexOf(" ") > 0) {
    keyword_control_symbol = true;
    const keyword_array = area_keyword.split(" ");
    let contain = true;
    for (var j = 0; j < keyword_array.length; j++) {
        if (keyword_array[j] == "") continue;
        if (html_text.indexOf(keyword_array[j]) == -1) {
            contain = false;
            break;
        }
    }
    if (contain) {
        // 全部都符合
    }
}

個案5:用關鍵字移除不要的區塊內容

下面這幾行就可以把所有 div.ticket-unit 中不要的關鍵字的區塊,使用 .remove() 進行移除,當然也可以用 .hide() 藏起來就好了。

var exclude_keyword_array = ["輪椅", "身障", "身心障礙", "Restricted View", "Wheelchair", "燈柱遮蔽", "視線不完整"];
for (let i = 0; i < exclude_keyword_array.length; i++) {
    $("#target_selector").each(function() {
        let html_text = $(this).text();
        if (html_text.indexOf(exclude_keyword_array[i]) > -1) {
            $(this).remove();
        }
    });
}


個案6:設定張數為指定張數或最大可以支援張數

以下的範例是每 100ms 設定張數的 select tag 為指定的 option, 當無符合的 option 時,就讓最後一個 option 為選取狀態。在按下送出按鈕(#autoMode)之前,延遲 100ms 之後才觸發 button 的 click() 事件。

let ticket_number=2;
function ticketmaster_assign_ticket_number(ticket_number) {
    let is_ticket_number_assign = false;
    let ticket_options = $("#ticket_price_selector select:first option");
    if (ticket_options.length > 1) {
        const first_option = ticket_options.first();
        if (ticket_number > 0 && first_option.prop('selected') && first_option.prop('value') == '0') {
            ticket_options.each(function() {
                if ($(this).val() == ticket_number) {
                    $(this).prop('selected', true);
                    is_ticket_number_assign = true;
                    return false;
                }
            });
            if (!is_ticket_number_assign) {
                ticket_options.last().prop('selected', true);
                is_ticket_number_assign = true;
            }
            if (is_ticket_number_assign) {
                // PS: click too fast will be detected.
                setTimeout(() => {
                    $("#autoMode").click();
                }, 100);
            }
        }
    }
    return is_ticket_number_assign;
}
setInterval(() =>
{
    ticketmaster_assign_ticket_number(ticket_number);
}, 100);

第二種的寫法, 針對同一個畫面中還有多個價位的 select tag:

var ticket_number = 2;
var exclude_keyword_array = [];
var price_keyword_array = [];

function ticketmaster_ticketPriceList_clean_exclude(exclude_keyword_array) {
    for (let i = 0; i < exclude_keyword_array.length; i++) {
        $("#ticket_price_selector > tbody > tr").each(function() {
            let html_text = $(this).text();
            //console.log("html:"+html_text);
            if (html_text.indexOf(exclude_keyword_array[i]) > -1) {
                $(this).remove();
            }
        });
    }
}

function ticketmaster_ticketPriceList_ticket_number(price_keyword_array, ticket_number) {
    let is_ticket_number_assign = false;

    let target_row = null;
    let all_row = $("#ticket_price_selector > tbody > tr");
    if (all_row.length > 0) {
        if (all_row.length == 1) {
            // single select.
            target_row = all_row;
        } else {
            // multi select.
            all_row.each(function() {
                let is_match_keyword = false;
                if (price_keyword_array.length) {
                    let html_text = $(this).text();
                    for (let i = 0; i < price_keyword_array.length; i++) {
                        if (price_keyword_array[i].indexOf(" ") > -1) {
                            // TODO: muti keywords with AND logic.
                        } else {
                            if (html_text.indexOf(price_keyword_array[i]) > -1) {
                                is_match_keyword = true;
                                target_row = $(this);
                                break;
                            }
                        }
                    }
                } else {
                    if (all_row.index(this) == 0) {
                        is_match_keyword = true;
                        target_row = $(this);
                    }
                }
                //console.log("is_match_keyword:"+is_match_keyword);
                if (is_match_keyword) {
                    return;
                }
            });
        }

        let ticket_options = target_row.find("option");
        if (ticket_options.length) {
            const first_option = ticket_options.first();

            if (ticket_number > 0 && first_option.prop('selected') && first_option.prop('value') == '0') {
                ticket_options.each(function() {
                    if ($(this).val() == ticket_number) {
                        $(this).prop('selected', true);
                        is_ticket_number_assign = true;
                        return false;
                    }
                });
            }
            if (!is_ticket_number_assign) {
                ticket_options.last().prop('selected', true);
            }
        }
    }
    return is_ticket_number_assign;
}

ticketmaster_ticketPriceList_clean_exclude(exclude_keyword_array);
ticketmaster_ticketPriceList_ticket_number(price_keyword_array, ticket_number);