iT邦幫忙

2021 iThome 鐵人賽

DAY 26
0
Modern Web

JavaScript 從 50% 開始,打造函式庫不是問題!系列 第 26

JS 26 - 進階版互動視窗!不只警告、確認和提示,還有導覽功能!

大家好!

我們今天要實作能和使用者互動的視窗。
我們進入今天的主題吧!


互動視窗

如果要和使用者互動,我們大多都會使用 alertconfirmprompt 等函式。
但是,必須要等使用者回應後,才能執行後續的動作。

因此,今天我們要實作能同時等待回應和執行動作的互動視窗。


程式碼

Felix.modal = function (method, p) {
    /* 如果 modal 存在則不執行 */
    if (Felix('#modal')[0]) return;
    let els = {};
    const modal = Felix('body').insert(`div#modal[data-method="${method}"]`);
    const container = Felix(modal).insert('article');
    /* 此處之後可不讀 */
    !function () {
        if (!p.title && method !== 'guide') return;
        var header = Felix(container).insert('header');
        if (method === 'guide') els.close = Felix(header).insert('div');
        if (p.heading) els.title = Felix(header).insert('h6', p.heading);
        if (method === 'guide') els.next = Felix(header).insert('a[data-customized]');
    }();
    !function () {
        p.heading = typeof p.heading === 'undefined' || p.heading;
        if (!p.title && !p.heading && p.message && method === 'prompt') return;
        var main = Felix(container).insert('div#modal-main');
        if (p.title) Felix(main).insert('div', p.title);
        if (p.message) Felix(main).insert('p', p.message);
        if (method !== 'prompt') return;
        els.input = Felix(main).insert('input' + p.inputbox);
    }();
    !function () {
        if (!method) return;
        var footer = Felix(container).insert('footer');
        if (method === 'guide') return;
        els.ok = Felix(footer).insert('button.positive[type="button"]', 'OK');
        if (method === 'alert') return;
        els.cancel = Felix(footer).insert('button.negative[type="button"]', 'Cancel');
    }();
    /* 此處之前可不讀 */
    return new Promise(function (resolve, reject) {
        var arr = [els.close, els.next, els.ok, els.cancel].filter(Boolean);
        arr.forEach(function (el) {
            el.addEventListener('click', clicked);
        });
        function clicked() {
            var that = this,
                check = method === 'prompt' ? els.input.validity.valid : true;
            if (!check && that === els.ok) return;
            arr.forEach(function (el) {
                el.removeEventListener('click', clicked);
            });
            modal.setAttribute('data-invisible', '');
            container.addEventListener('animationend', function () {
                if (that === els.ok || that === els.next)
                    resolve(method === 'prompt' ? els.input.value : true);
                else
                    reject(false);
                Felix(modal).remove();
            });
        }
    });
};

實測

Felix.modal('guide', {
    title: 'Hiya, Felix!'
});

直接觀看範例


差不多也到尾聲了。
如果對文章有任何疑問,也歡迎在下方提問和建議!
我是 Felix,我們明天再見!


上一篇
JS 25 - 舉一反三,擴充專屬於自己的函式庫!
下一篇
JS 27 - 平滑滾動,讓視窗不再是閃電俠!
系列文
JavaScript 從 50% 開始,打造函式庫不是問題!46

尚未有邦友留言

立即登入留言