HEX
Server: nginx/1.28.1
System: Linux VM-0-12-opencloudos 6.6.117-45.oc9.x86_64 #1 SMP Thu Dec 4 10:26:39 CST 2025 x86_64
User: www (1000)
PHP: 7.4.33
Disabled: passthru,exec,system,putenv,chroot,chgrp,chown,shell_exec,popen,proc_open,pcntl_exec,ini_alter,ini_restore,dl,openlog,syslog,readlink,symlink,popepassthru,pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,imap_open,apache_setenv
Upload Files
File: /www/wwwroot/www.waciwang.com/wp-content/themes/miragev-main/assets/lib/ui/light-tip.js
/**
 * @LightTip.js
 * @author popeyesailorman(yangfan)
 * @version
 * @Created: 20-05-15
 * @edit: 20-05-15
 */

class LightTip extends HTMLElement {
    static get observedAttributes () {
        return ['open'];
    }

    constructor () {
        super();

        if (arguments.length) {
            LightTip.custom.apply(this, arguments);
        }
    }

    get type () {
        return this.getAttribute('type');
    }

    get time () {
        let strTime = this.getAttribute('time');
        if (!isNaN(strTime) && !isNaN(parseFloat(strTime))) {
            return Number(strTime);
        }

        return 3000;
    }

    set type (value) {
        this.setAttribute('type', value);
    }

    set time (value) {
        this.setAttribute('time', value);
    }

    get open () {
        return this.hasAttribute('open');
    }

    set open (value) {
        this.toggleAttribute('open', value);
    }

    connectedCallback () {
        // 自定义元素设置 tabIndex=0 代表改元素可聚焦,并可通过键盘导航来聚焦到该元素
        this.setAttribute('tabIndex', 0);
        this.setAttribute('role', 'tooltip');

        if (!this.closeMode) {
            this.closeMode = 'hide';
        }

        // 点击组件本身或按键盘 esc/enter 键即可关闭组件
        this.addEventListener('click', () => {
            // 移除元素
            this[this.closeMode]();
        });

        // 全局事件
        this.dispatchEvent(new CustomEvent('connected', {
            detail: {
                type: 'ui-lighttip'
            }
        }));

        this.isConnectedCallback = true;
    }

    attributeChangedCallback (name, oldValue, newValue) {
        // 让按钮或者之前的触发元素重新获取焦点,便于继续操作
        if (name == 'open' && typeof oldValue !== typeof newValue) {
            if (typeof newValue === 'string') {
                clearTimeout(this.timer);
                this.timer = setTimeout(() => {
                    // 标志量,是否是因为时间到关闭
                    this.isTimeHide = true;
                    // 关闭提示
                    this[this.closeMode]();
                    this.position();
                }, this.time);

                this.setAttribute('data-tid', this.timer);
                this.classList.add('ESC');

                // 组件的 z-index 层级计算
                this.zIndex();

                // 组件的定位,不同的提示位置不重叠
                this.position();
            } else {
                this.classList.remove('ESC');
            }
            this.tabIndex();

            this.isTimeHide = null;
        }
    }

    zIndex () {
        // 只对<body>子元素进行层级最大化计算处理,这里lighttip默认的z-index值是19
        var numZIndexNew = 19;
        this.parentElement && [...this.parentElement.childNodes].forEach(function (eleChild) {
            if (eleChild.nodeType != 1) {
                return;
            }
            var objStyleChild = window.getComputedStyle(eleChild);
            var numZIndexChild = objStyleChild.zIndex * 1;
            if (numZIndexChild && objStyleChild.display != 'none') {
                numZIndexNew = Math.max(numZIndexChild + 1, numZIndexNew);
            }
        });
        this.style.zIndex = numZIndexNew;
    }

    // 定位处理
    position () {
        var elesOpen = [...document.querySelectorAll('ui-lighttip[open]:not([type="loading"])')];
        // 基于 data-tid 排序
        var elesOpenSort = elesOpen.sort(function (eleA, eleB) {
            return (eleA.getAttribute('data-tid') || 0) - (eleB.getAttribute('data-tid') || 0);
        });
        // 确定提示内容
        var objMatchText = {};
        var numIndex = -1;

        elesOpenSort.forEach((ele) => {
            let strText = ele.textContent;
            if (typeof objMatchText[strText] == 'undefined') {
                numIndex++;
                objMatchText[strText] = numIndex;
            }
            ele.style.setProperty('--ui-sort-index', objMatchText[strText]);
        });
    }

    // 新的元素层级总是最高
    tabIndex () {
        var eleContainer = this;
        var eleLastActive = LightTip.lastActiveElement;
        if (this.open == true) {
            var eleActiveElement = document.activeElement;
            
            // 键盘索引起始位置定位在提示元素上
            if (eleActiveElement && !eleActiveElement.closest('[keepfocus]')) {
                if (eleContainer !== eleActiveElement) {
                    LightTip.lastActiveElement = eleActiveElement;
                }
                
                eleContainer.focus();
            }
        } else if (eleLastActive && !eleLastActive.matches('body')) {
            // 获取焦点但不会定位
            eleLastActive.focus({
                preventScroll: true
            });
            // 如果不是键盘关闭提示,而是点击的话,之前的焦点元素失焦
            // 这里实现有问题,如果是时间到了自动关闭的话,这里不应该失焦
            if (!window.isKeyEvent && !this.isTimeHide) {
                eleLastActive.blur();
            }
            LightTip.lastActiveElement = null;
        }
        return this;
    }

    // success
    static success (text, time = 3000) {
        return this.custom(text, 'success', time);
    }
    // error
    static error (text, time = 3000) {
        return this.custom(text, 'error', time);
    }
    // normal
    static normal (text, time = 3000) {
        return this.custom(text, 'normal', time);
    }
    // loading
    static loading (text) {
        text = text || '正在加载中...';
        return this.custom(text, 'loading');
    }
    // 调用方法处理
    static custom (text = '', type, time) {
        // 如果是静态方法执行
        // 创建ui-lighttip自定义元素
        if (!this.matches || !this.matches('ui-lighttip')) {
            return LightTip.custom.apply(document.createElement('ui-lighttip'), arguments);
        }

        if (typeof text == 'object') {
            type = text;
            text = '';
        }

        if (typeof text != 'string') {
            return this;
        }

        this.closeMode = 'remove';

        // 如果传入的类型是object形式
        if (type && typeof type === 'object') {
            LightTip.custom.call(this, text, type.type, type.time);
            return;
        }
        // 如果type的类型是number,则赋值给time
        if (typeof type === 'number') {
            LightTip.custom.call(this, text, time, type);
            return;
        }

        if (type == 'loading') {
            if (!text) {
                text = '正在加载中...';
            }
            time = 999999;
        }

        if (time) {
            this.time = time;
        }
        if (type) {
            this.type = type;
        }

        this.innerHTML = text;
        // 提高无障碍
        if (type == 'success') {
            this.setAttribute('aria-lable', '操作成功');
        } else if (type == 'error') {
            this.setAttribute('aria-lable', '操作失败');
        }

        // append内存中创建的ui-lighttip元素
        if (!this.parentElement) {
            document.body.appendChild(this);

            this.dispatchEvent(new CustomEvent('DOMContentLoaded'));
        }

        this.show();

        return this;
    }
    remove () {
        if (this.parentElement) {
            this.parentElement.removeChild(this);
        }
        this.open = false;
    }
    show () {
        if (this.time > 0) {
            this.open = true;
        }
    }
    hide () {
        this.open = false;
    }
}

if (!customElements.get('ui-lighttip')) {
    customElements.define('ui-lighttip', LightTip);
}

// 将该方法定义为 window 全局使用的方法
window.LightTip = LightTip;

export default LightTip;