DynamicTabs_gz

一个简易tabs标签页,只需创建该类的实例,按需传入配置即可在页面上创建

目前為 2024-11-15 提交的版本,檢視 最新版本

此腳本不應該直接安裝,它是一個供其他腳本使用的函式庫。欲使用本函式庫,請在腳本 metadata 寫上: // @require https://update.cn-greasyfork.org/scripts/517538/1484731/DynamicTabs_gz.js

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name        DynamicTabs_gz
// @namespace   http://tampermonkey.net/
// @license     Apache-2.0
// @version     0.1
// @author      byhgz
// @description 一个简易tabs标签页,只需创建该类的实例,按需传入配置即可在页面上创建
// @noframes
// ==/UserScript==

/**
 *
 * 一个简易Tabs标签页,只需创建该类的实例,按需传入配置即可在页面上创建
 *
 * @author byhgz
 */
class DynamicTabs_gz {
    #selector;
    #tabsConfig;
    #activeTabId;
    #options;

    /**
     *
     * @param selector{string} css选择器
     * @param tabsConfig {Array} 选项卡配置,参数为数组,数组每个对象为一个选项卡和对应的选项卡内容
     * @param options {Object} 其他选项,可设置自定义样式和事件处理类名
     */
    constructor(selector, tabsConfig, options = {}) {
        this.#selector = selector;       // 选项卡容器的选择器
        this.#tabsConfig = tabsConfig;   // 选项卡配置数组
        this.#activeTabId = tabsConfig[0].id; // 默认激活的第一个选项卡ID
        this.#options = options;         // 可选配置项,如自定义样式和事件处理函数

        // 初始化选项卡
        this.#init();
    }

    // 私有初始化方法
    #init() {
        const tabsContainer = document.querySelector(this.#selector);

        if (!tabsContainer) {
            throw new Error(`No element found matching the selector: ${this.#selector}`);
        }

        // 添加默认样式
        this.#addDefaultStyles();

        // 创建选项卡按钮
        this.#createButtons(tabsContainer);

        // 创建选项卡内容
        this.#createContents(tabsContainer);
    }

    // 私有添加默认样式的方法
    #addDefaultStyles() {
        const defaultClasses = {
            tabButton: 'dynamic-tab-button',
            tabButtonActive: 'dynamic-tab-button-active',
            tabContent: 'dynamic-tab-content',
            tabContentActive: 'dynamic-tab-content-active'
        };

        // 合并用户提供的类名
        const classes = {...defaultClasses, ...this.#options.classes};

        // 获取用户提供的样式或默认样式
        const backgroundColor = this.#options.backgroundColor || '#ccc';
        const borderColor = this.#options.borderColor || '#ccc';
        const textColor = this.#options.textColor || 'black';
        const fontWeight = this.#options.fontWeight || 'normal';
        const activeBackgroundColor = this.#options.activeBackgroundColor || '#007BFF';
        const activeTextColor = this.#options.activeTextColor || 'white';
        const contentBorderColor = this.#options.contentBorderColor || '#ccc';
        const contentBackgroundColor = this.#options.contentBackgroundColor || '#f9f9f9';

        const defaultStyle = `
                    .${classes.tabButton} {
                        padding: 10px 20px;
                        margin-right: 10px;
                        cursor: pointer;
                        border: 1px solid ${borderColor};
                        background-color: ${backgroundColor};
                        color: ${textColor};
                        font-weight: ${fontWeight};
                    }
                    .${classes.tabButton}.${classes.tabButtonActive} {
                        background-color: ${activeBackgroundColor};
                        color: ${activeTextColor};
                    }
                    .${classes.tabContent} {
                        margin-top: 20px;
                        padding: 20px;
                        border: 1px solid ${contentBorderColor};
                        background-color: ${contentBackgroundColor};
                        display: none;
                    }
                    .${classes.tabContent}.${classes.tabContentActive} {
                        display: block;
                    }
                `;

        // 如果提供了自定义样式,则覆盖默认样式
        const customStyle = this.#options.styles || '';

        const style = document.createElement('style');
        style.innerHTML = defaultStyle + customStyle;
        document.head.appendChild(style);
    }

    // 私有创建选项卡按钮的方法
    #createButtons(tabsContainer) {
        const buttonContainer = document.createElement('div');

        const classes = this.#options.classes || {};

        this.#tabsConfig.forEach(tab => {
            const button = document.createElement('button');
            button.className = `${classes.tabButton || 'dynamic-tab-button'}`;
            button.textContent = tab.title;
            button.dataset.tabId = tab.id;

            if (tab.id === this.#activeTabId) {
                button.classList.add(classes.tabButtonActive || 'dynamic-tab-button-active');
            }

            // 添加点击事件监听器
            button.addEventListener('click', () => {
                this.activateTab(tab.id);
                // 调用自定义的点击事件处理函数(如果存在)
                if (this.#options.onTabClick) {
                    this.#options.onTabClick(tab.id, tab.content);
                }
            });

            buttonContainer.appendChild(button);
        });

        tabsContainer.appendChild(buttonContainer);
    }

    // 私有创建选项卡内容的方法
    #createContents(tabsContainer) {
        const contentContainer = document.createElement('div');

        const classes = this.#options.classes || {};

        this.#tabsConfig.forEach(tab => {
            const contentDiv = document.createElement('div');
            contentDiv.className = `${classes.tabContent || 'dynamic-tab-content'}`;
            contentDiv.innerHTML = tab.content;
            contentDiv.id = `content-${tab.id}`;

            if (tab.id === this.#activeTabId) {
                contentDiv.classList.add(classes.tabContentActive || 'dynamic-tab-content-active');
            }

            contentContainer.appendChild(contentDiv);
        });

        tabsContainer.appendChild(contentContainer);
    }

    /**
     * 激活指定的选项卡
     * @param tabId {string} 选项卡id
     */
    activateTab(tabId) {
        const classes = this.#options.classes || {};

        // 更新按钮状态
        const buttons = document.querySelectorAll(`.${classes.tabButton || 'dynamic-tab-button'}`);
        buttons.forEach(button => {
            if (button.dataset.tabId === tabId) {
                button.classList.add(classes.tabButtonActive || 'dynamic-tab-button-active');
            } else {
                button.classList.remove(classes.tabButtonActive || 'dynamic-tab-button-active');
            }
        });

        // 更新内容状态
        const contents = document.querySelectorAll(`.${classes.tabContent || 'dynamic-tab-content'}`);
        contents.forEach(content => {
            if (content.id === `content-${tabId}`) {
                content.classList.add(classes.tabContentActive || 'dynamic-tab-content-active');
            } else {
                content.classList.remove(classes.tabContentActive || 'dynamic-tab-content-active');
            }
        });

        this.#activeTabId = tabId;
    }
}