[jQuery] 透過jQueryUI 實現輸入框的自動完成

透過jQueryUI 實現輸入框的自動完成

4年沒碰前端了,遇到了需求還是得跳下去改...


1.先確認這次的需求

  • User輸入框輸入時必須出現自動完成的選項,給User選擇
  • 自動完成的資料來源來自後端API,且會依照User當下輸入的值做查詢
  • API有訪問頻率的限制
  • User上下選擇選項時不可以更改輸入框的內容,按下enter時才可更改
  • User按下enter選定選項後,停止跳出自動完成選單
  • 自動完成的選項不需要過濾User輸入的內容,API拿到什麼就列出什麼
  • User上下選擇選項時,不可刷新清單

2.以上是陸續被反映的問題跟需求...有的是連貫的因果關係,不過還是一併列出

3.直接貼出程式碼,一一確認需求

// ctrl: $("#text")
function autocomplete(ctrl) {
    // 先定義方法,後面才會用到
    let oldKeyword;
    let newVar = function () {
        // 每次進入時檢查是否有改變值,若無則直接離開不做事
        const keyword = ctrl.val();
        if (keyword === oldKeyword)
        {
            return;
        }
        // 紀錄這次新的值
        oldKeyword = keyword;
        
        // 向後端API取得資料
        $.ajax({
            type: 'POST',
            url: "Autocomplete.aspx", //WebForm...
            data: {method: "get", keyword: keyword},
            datatype: "json",
            success: (response) => {
                const items = JSON.parse(response);
                // 需求之一,不要過濾內容
                ctrl.autocomplete("option", "source", function (request, response) {
                    response(items);
                });
                // 前面更新source後,jQuery-ui只有在觸發改變時才會跳出自動完成選單,這邊直接強制他做一次查詢,跳出選單
                ctrl.autocomplete("search");
            },
            error: (ex, a, b) => {
                console.log(b)
            },
        });
    };

    let interval;
    // 當User聚焦在輸入框,加入timer每一段時間更新一次清單
    // 若用keydown之類的觸發,會超過API的訪問頻率
    ctrl.focus(() => {
        // 先初始化輸入框的自動完成
        ctrl.autocomplete({
            source: [],
            // 只要有輸入一個字就允許跳出選單
            minLength: 1,
            // 當User選到其中一個選項(enter或是滑鼠點擊)時,把timer拔掉
            select: function (event, ui) {
                clearInterval(interval);
            },
            // 當User上下移動選項時,不改變輸入框的內容
            focus: function(event, ui){
                event.preventDefault();
            }
        });
        // 設定一個timer,每兩秒去更新一次選單
        interval = setInterval(() => {
            newVar();
        }, 2000);
    });

    // User離開聚焦後,把timer拔掉
    ctrl.focusout(() => {
        clearInterval(interval)
    });
}

4.說明都寫在程式碼內了,快樂結束XD


以上絕對不是最好也不是0 Bug的寫法,但是應付目前的需求是足夠的...

歡迎大大們提供建議改善這段程式碼 XD


官方文件 https://api.jqueryui.com/autocomplete/#option-source