Files
server-configs/siyuan/temp/bazaar/package/01ff2z8/js/modules/bulletThreading.js

79 lines
2.9 KiB
JavaScript
Raw Normal View History

2026-02-13 22:24:27 +08:00
// ========================================
// 模块:列表子弹线功能
// ========================================
let bulletThreadingActive = false;
let selectionChangeHandler = null;
let btRafId = null;
let btLastItems = [];
// 初始化列表子弹线功能
export const initBulletThreading = () => {
if (bulletThreadingActive) return;
bulletThreadingActive = true;
const apply = () => {
btRafId = null;
const sel = window.getSelection();
if (!sel.rangeCount) {
// 清理上一次标记
btLastItems.forEach(node => {
node.classList.remove('en_item_bullet_actived', 'en_item_bullet_line');
node.style.removeProperty('--en-bullet-line-height');
});
btLastItems = [];
return;
}
const start = sel.getRangeAt(0).startContainer;
// 清理上一次标记(避免全局查询)
btLastItems.forEach(node => {
node.classList.remove('en_item_bullet_actived', 'en_item_bullet_line');
node.style.removeProperty('--en-bullet-line-height');
});
btLastItems = [];
const items = [];
for (let n = start; n && n !== document.body; n = n.parentElement) {
if (n.getAttribute?.('custom-f')) return; // 父级存在 custom-f 时直接终止
if (n.dataset?.type === 'NodeListItem') items.push(n);
}
if (items.length === 0) return;
for (let i = 0; i < items.length - 1; i++) {
const h = items[i].getBoundingClientRect().top - items[i + 1].getBoundingClientRect().top;
items[i].style.setProperty('--en-bullet-line-height', `${h}px`);
items[i].classList.add('en_item_bullet_line');
}
items.forEach(item => item.classList.add('en_item_bullet_actived'));
btLastItems = items.slice();
};
selectionChangeHandler = () => { if (!btRafId) btRafId = requestAnimationFrame(apply); };
document.addEventListener('selectionchange', selectionChangeHandler);
};
// 移除列表子弹线功能
export const removeBulletThreading = () => {
if (!bulletThreadingActive) return;
bulletThreadingActive = false;
if (btRafId) { cancelAnimationFrame(btRafId); btRafId = null; }
if (selectionChangeHandler) {
document.removeEventListener('selectionchange', selectionChangeHandler);
selectionChangeHandler = null;
}
// 清理剩余标记
btLastItems.forEach(node => {
node.classList.remove('en_item_bullet_actived', 'en_item_bullet_line');
node.style.removeProperty('--en-bullet-line-height');
});
btLastItems = [];
};
// 初始化列表子弹线模块
export const initBulletThreadingModule = () => {
window.initBulletThreading = initBulletThreading;
window.removeBulletThreading = removeBulletThreading;
window.cleanupBulletThreading = removeBulletThreading;
};