[js] 阻止中键关闭任何页签或钉住的页签

效果是避免不小心中键点击页签从而关闭文档。

JS 代码片段:

注意:开头有个变量,为 true 时阻止所有页签的中键,为 false 时阻止钉住页签的中键

2.0 版本(更简洁,性能更好):

// 阻止中键关闭任何页签或钉住的页签 2.0 JS片段
// author by JeffreyChen https://ld246.com/article/1728321288261
(function() {
    const applyToAllTabs = true; // true: 阻止所有页签 | false: 仅阻止钉住页签
    const targetSelector = applyToAllTabs 
        ? '.layout-tab-bar:not(.layout-tab-bar--readonly) .item' 
        : '.layout-tab-bar:not(.layout-tab-bar--readonly) .item--pin';

    document.addEventListener('mousedown', function(event) {
        if (event.button !== 1) return; // 仅处理中键点击
      
        const targetElement = event.target.closest(targetSelector);
        if (!targetElement) return;
      
        // 阻止默认行为和事件传播
        event.preventDefault();
        event.stopPropagation();
    }, true); // 使用捕获阶段确保早期拦截
})();

1.0 版本:

// 阻止中键关闭任何页签或钉住的页签 1.0 JS片段
// author by JeffreyChen https://ld246.com/article/1728321288261
(function() {
    const applyToAllTabs = true; // 变量:为 true 时阻止所有页签的中键,为 false 时阻止钉住页签的中键
    const targetSelector = applyToAllTabs 
        ? '#layouts .layout__center div:not(.fn__none) > .layout-tab-bar:not(.layout-tab-bar--readonly) .item' 
        : '#layouts .layout__center div:not(.fn__none) > .layout-tab-bar:not(.layout-tab-bar--readonly) .item--pin';

    const targetContainer = document.querySelector('#layouts');
    const observerConfig = { childList: true, subtree: true };

    function handleClick(event) {
        if (event.button !== 1) return;

        const targetElement = event.target.closest(targetSelector);
        if (!targetElement) return;

        event.preventDefault();
        event.stopPropagation();
    }

    function attachListener(element) {
        if (!element.dataset.listenerAttached) {
            element.addEventListener('mousedown', handleClick, true);
            element.dataset.listenerAttached = 'true';
        }
    }

    function detachListener(element) {
        if (element.dataset.listenerAttached) {
            element.removeEventListener('mousedown', handleClick, true);
            delete element.dataset.listenerAttached;
        }
    }

    function checkAndSetupListeners() {
        const elements = document.querySelectorAll('#layouts .layout__center div:not(.fn__none) > .layout-tab-bar:not(.layout-tab-bar--readonly)');
        elements.forEach(attachListener);
    }

    const observer = new MutationObserver(mutations => {
        mutations.forEach(mutation => {
            // Check for added nodes
            mutation.addedNodes.forEach(node => {
                if (node.matches && node.matches('.layout-tab-bar:not(.layout-tab-bar--readonly)')) {
                    attachListener(node);
                } else if (node.querySelectorAll) {
                    node.querySelectorAll('.layout-tab-bar:not(.layout-tab-bar--readonly)').forEach(attachListener);
                }
            });

            // Check for removed nodes
            mutation.removedNodes.forEach(node => {
                if (node.matches && node.matches('.layout-tab-bar:not(.layout-tab-bar--readonly)')) {
                    detachListener(node);
                } else if (node.querySelectorAll) {
                    node.querySelectorAll('.layout-tab-bar:not(.layout-tab-bar--readonly)').forEach(detachListener);
                }
            });
        });
    });

    observer.observe(targetContainer, observerConfig);

    // 初始化时设置监听
    checkAndSetupListeners();
})();

其他相关

[css] 显示钉住文档名并在页签右下角添加一个钉子图标

打赏 30 积分后可见
30 积分 • 2 打赏
  • 思源笔记

    思源笔记是一款隐私优先的个人知识管理系统,支持完全离线使用,同时也支持端到端加密同步。

    融合块、大纲和双向链接,重构你的思维。

    28446 引用 • 119778 回帖
  • 代码片段

    代码片段分为 CSS 与 JS 两种代码,添加在 [设置 - 外观 - 代码片段] 中,这些代码会在思源笔记加载时自动执行,用于改善笔记的样式或功能。

    用户在该标签下分享代码片段时需在帖子标题前添加 [css] [js] 用于区分代码片段类型。

    285 引用 • 1985 回帖
2 操作
JeffreyChen 在 2025-09-19 10:32:15 更新了该帖
JeffreyChen 在 2024-10-08 20:57:16 更新了该帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...
JeffreyChen
目前作为思源笔记的半个客服、测试、开发、评审,在爱发电接受捐赠:https://afdian.com/a/JeffreyChen