SideBarButtonLibrary

SideBarButtonLibrary 是一个轻量级的 JavaScript 库,用于创建可展开和收起的侧边栏按钮容器,支持自定义吸附方向(左、右、上、下)、按钮排列方式(水平或垂直)以及样式,适用于快速构建侧边栏工具栏或导航菜单。

Version vom 23.01.2025. Aktuellste Version

Dieses Skript sollte nicht direkt installiert werden. Es handelt sich hier um eine Bibliothek für andere Skripte, welche über folgenden Befehl in den Metadaten eines Skriptes eingebunden wird // @require https://update.greatest.deepsurf.us/scripts/453745/1525524/SideBarButtonLibrary.js

// ==UserScript==
// @name         SideBarButtonLibrary
// @namespace    
// @version      2.0.0
// @description  SideBarButtonLibrary 是一个轻量级的 JavaScript 库,用于创建可展开和收起的侧边栏按钮容器,支持自定义吸附方向(左、右、上、下)、按钮排列方式(水平或垂直)以及样式,适用于快速构建侧边栏工具栏或导航菜单。
// @author       otc
// @match        *
// @license MIT
// ==/UserScript==

const SideBarButtonLibrary = (function() {
    // 默认配置
    const defaultConfig = {
        // 容器默认样式
        container: {
            width: '5px',               // 收起时宽度/高度
            expandedWidth: '150px',     // 展开时宽度
            backgroundColor: 'rgba(0, 0, 0, 0.1)',
            transition: 'width 0.3s ease',
            className: 'sidebar-button-container', // 默认类名
            position: 'left',           // 吸附位置:left/right/top/bottom
            flexDirection: 'column'     // 排列方向:row/column
        },
        // 按钮默认样式
        buttonStyles: {
            width: '140px',
            background: '#007bff',
            color: '#fff',
            borderRadius: '4px',
            fontSize: '14px',
            cursor: 'pointer',
            transition: 'background 0.2s ease',
            hoverBackground: '#0056b3', // 悬停背景颜色
            defaultBackground: '#007bff' // 默认背景颜色
        },
        // 删除按钮默认样式
        deleteButtonStyles: {
            right: '-30px',             // 收起时位置
            expandedRight: '10px',      // 展开时位置
            background: 'rgba(222, 55, 48, 0.8)',
            color: '#fff',
            borderRadius: '5px',
            cursor: 'pointer',
            transition: 'right 0.3s ease',
            padding: '5px 10px',        // 默认内边距
            fontSize: '14px',          // 默认字体大小
            border: 'none'             // 默认边框样式
        },
        // 动作延迟
        hoverDelay: 500,   // 悬停后展开延迟
        hideDelay: 1000    // 移出后收起延迟
    };

    // 私有函数:获取默认容器样式
    function getDefaultContainerStyles(config) {
        const baseStyles = {
            position: 'fixed',
            display: 'flex',
            justifyContent: 'center',
            alignItems: 'center',
            overflow: 'hidden',
            zIndex: 10000,
            backgroundColor: config.container.backgroundColor,
            transition: config.container.transition
        };

        // 根据吸附位置调整样式
        switch (config.container.position) {
            case 'left':
                baseStyles.left = '0';
                baseStyles.top = '0';
                baseStyles.height = '100%';
                baseStyles.width = config.container.width;
                break;
            case 'right':
                baseStyles.right = '0';
                baseStyles.top = '0';
                baseStyles.height = '100%';
                baseStyles.width = config.container.width;
                break;
            case 'top':
                baseStyles.top = '0';
                baseStyles.left = '0';
                baseStyles.width = '100%';
                baseStyles.height = config.container.width;
                break;
            case 'bottom':
                baseStyles.bottom = '0';
                baseStyles.left = '0';
                baseStyles.width = '100%';
                baseStyles.height = config.container.width;
                break;
        }

        return baseStyles;
    }

    // 私有函数:创建或获取容器
    function getOrCreateButtonContainer(config) {
        let container = document.querySelector(`.${config.container.className}`);
        if (!container) {
            container = document.createElement('div');
            container.className = config.container.className;

            const styles = getDefaultContainerStyles(config);
            for (const [key, value] of Object.entries(styles)) {
                container.style[key] = value;
            }

            // 设置按钮排列方向
            container.style.flexDirection = config.container.flexDirection;

            // 创建删除按钮
            const deleteButton = document.createElement('button');
            deleteButton.className = 'delete-button';
            deleteButton.innerHTML = '<span class="button-text">×</span>';
            deleteButton.style.position = 'absolute';

            // 根据吸附位置调整删除按钮的位置
            switch (config.container.position) {
                case 'left':
                case 'right':
                    deleteButton.style.top = '10px';
                    deleteButton.style.right = config.deleteButtonStyles.right;
                    break;
                case 'top':
                    deleteButton.style.right = '10px';
                    deleteButton.style.bottom = config.deleteButtonStyles.expandedRight;
                    break;
                case 'bottom':
                    deleteButton.style.right = '10px';
                    deleteButton.style.top = config.deleteButtonStyles.expandedRight;
                    break;
            }

            // 应用用户自定义的删除按钮样式
            const deleteStyles = { ...defaultConfig.deleteButtonStyles, ...config.deleteButtonStyles };
            for (const [key, value] of Object.entries(deleteStyles)) {
                deleteButton.style[key] = value;
            }

            deleteButton.addEventListener('click', () => {
                container.remove();
            });

            container.appendChild(deleteButton);

            // 鼠标悬停事件
            container.addEventListener('mouseenter', () => {
                clearTimeout(container.expandTimeout);
                clearTimeout(container.hideTimeout);

                container.expandTimeout = setTimeout(() => {
                    if (config.container.position === 'left' || config.container.position === 'right') {
                        container.style.width = config.container.expandedWidth;
                    } else {
                        container.style.height = config.container.expandedWidth;
                    }
                    deleteButton.style.right = config.deleteButtonStyles.expandedRight;
                    container.querySelectorAll('.button-text').forEach(text => {
                        text.style.opacity = 1;
                    });
                }, config.hoverDelay);
            });

            // 鼠标移出事件
            container.addEventListener('mouseleave', () => {
                clearTimeout(container.expandTimeout);

                container.hideTimeout = setTimeout(() => {
                    if (config.container.position === 'left' || config.container.position === 'right') {
                        container.style.width = config.container.width;
                    } else {
                        container.style.height = config.container.width;
                    }
                    deleteButton.style.right = config.deleteButtonStyles.right;
                    container.querySelectorAll('.button-text').forEach(text => {
                        text.style.opacity = 0;
                    });
                }, config.hideDelay);
            });

            document.body.appendChild(container);
        }
        return container;
    }

    // 公开接口:创建按钮
    function createButtons(buttons, config = {}) {
        const finalConfig = { ...defaultConfig, ...config };
        const container = getOrCreateButtonContainer(finalConfig);

        buttons.forEach((button, index) => {
            const buttonElement = document.createElement('button');
            buttonElement.innerHTML = `<span class="button-text">${button.name}</span>`;
            buttonElement.style.margin = '2px 0';
            buttonElement.style.width = finalConfig.buttonStyles.width;
            buttonElement.style.border = 'none';
            buttonElement.style.background = finalConfig.buttonStyles.defaultBackground;
            buttonElement.style.color = finalConfig.buttonStyles.color;
            buttonElement.style.borderRadius = finalConfig.buttonStyles.borderRadius;
            buttonElement.style.fontSize = finalConfig.buttonStyles.fontSize;
            buttonElement.style.cursor = finalConfig.buttonStyles.cursor;
            buttonElement.style.transition = finalConfig.buttonStyles.transition;

            const buttonText = buttonElement.querySelector('.button-text');
            buttonText.style.opacity = 0;
            buttonText.style.transition = 'opacity 0.3s ease';

            // 使用配置中的悬停和默认样式
            buttonElement.addEventListener('mouseover', () => {
                buttonElement.style.background = finalConfig.buttonStyles.hoverBackground;
            });
            buttonElement.addEventListener('mouseout', () => {
                buttonElement.style.background = finalConfig.buttonStyles.defaultBackground;
            });

            buttonElement.addEventListener('click', button.func);

            container.appendChild(buttonElement);
        });
    }

    // 暴露公共接口
    return {
        createButtons: createButtons
    };
})();

// 使用示例
// SideBarButtonLibrary.createButtons([
//     { name: 'Button 1', func: () => alert('Button 1 clicked') },
//     { name: 'Button 2', func: () => alert('Button 2 clicked') }
// ], {
//     container: {
//         width: '5px',               // 自定义收起宽度/高度
//         expandedWidth: '200px',     // 自定义展开宽度
//         backgroundColor: 'rgba(0, 0, 0, 0.2)', // 自定义背景颜色
//         className: 'my-custom-sidebar-container', // 自定义容器类名
//         position: 'top',            // 吸附到顶部
//         flexDirection: 'row'        // 按钮水平排列
//     },
//     buttonStyles: {
//         width: '180px',             // 自定义按钮宽度
//         background: '#ff5722',      // 自定义按钮默认背景
//         hoverBackground: '#cc4400', // 自定义按钮悬停背景
//         defaultBackground: '#ff5722' // 自定义按钮默认背景
//     },
//     deleteButtonStyles: {
//         right: '-40px',             // 自定义收起时删除按钮位置
//         expandedRight: '20px',      // 自定义展开时删除按钮位置
//         background: 'rgba(255, 0, 0, 0.8)', // 自定义删除按钮背景颜色
//         color: '#000'               // 自定义删除按钮字体颜色
//     },
//     hoverDelay: 300,                // 自定义悬停延迟
//     hideDelay: 800                  // 自定义隐藏延迟
// });