[js 片段] 双击展开&展开全部_release_v1.0
功能介绍
- 双击节点展开/折叠 (DOUBLE_SWITCH 控制)
- 点击折叠按钮, 如果是从折叠到展开, 则自动展开所有子节点 (UNFOLD_ALL_SWITCH 控制)
(() => {
const CONFIG = {
DOUBLE_SWITCH : true,
DOUBLE_INTERVAL : 200,
UNFOLD_ALL_SWITCH : true,
UNFOLD_INTERVAL : 200,
};
const SESSION_ID = Date.now();
const CLICK_TYPE = {
INVALID: 0,
NODE : 1,
ARROW : 2,
BOOK : 3,
};
const utils = {
log(...args) {
console.log(`[${SESSION_ID}]:`, ...args);
},
sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
},
getTagName(element) {
return element?.tagName?.toLowerCase() || '';
}
};
class TreeHandler {
constructor() {
this.clickQueue = [];
this.isProcessing = false;
this.doubleClickFlag = false;
this.lastClickTime = 0;
}
getClickType(element) {
if (!element) return CLICK_TYPE.INVALID;
let target = element;
let tagName = utils.getTagName(target);
if (tagName === 'use') {
target = element.parentElement.parentElement;
} else if (tagName === 'svg') {
target = element.parentElement;
}
tagName = utils.getTagName(target);
if (tagName === 'ul') {
return CLICK_TYPE.INVALID;
}
else if (tagName === 'li' && target.getAttribute('data-path') === '/') {
return CLICK_TYPE.BOOK;
}
else if (tagName === 'li') {
return CLICK_TYPE.NODE;
}
else if (tagName === 'span') {
if (target.classList.contains('b3-list-item__toggle')) {
return CLICK_TYPE.ARROW;
}
else if (target.classList.contains('b3-list-item__text') &&
target.parentElement.getAttribute('data-path') === '/') {
return CLICK_TYPE.BOOK;
}
else if (target.classList.contains('b3-list-item__text')) {
return CLICK_TYPE.NODE;
}
}
return CLICK_TYPE.INVALID;
}
getArrowSpan(element) {
let target = element;
let tagName = utils.getTagName(target);
if (tagName === 'use') {
target = element.parentElement.parentElement;
} else if (tagName === 'svg') {
target = element.parentElement;
}
tagName = utils.getTagName(target);
if (tagName === 'span' && target.classList.contains('b3-list-item__toggle')) {
return target;
}
return null;
}
clickArrowButton(element) {
const li = utils.getTagName(element) === 'span' ?
element.parentElement : element;
if (utils.getTagName(li) !== 'li') return;
li.querySelector('span.b3-list-item__toggle:not(.fn__hidden)')?.click();
}
async unfoldChildNodes(element) {
const arrowSpan = this.getArrowSpan(element);
if (!arrowSpan) return;
if (!arrowSpan.querySelector('svg').classList.contains('b3-list-item__arrow--open')) {
return;
}
utils.log("点击了折叠按钮, 且是展开的", arrowSpan);
const childNodes = Array.from(arrowSpan.parentElement.nextElementSibling.children);
childNodes.forEach(node => {
node.querySelector('span.b3-list-item__toggle:not(.fn__hidden)')?.click();
});
}
async processClickQueue() {
if (this.isProcessing) return;
this.isProcessing = true;
while (this.clickQueue.length) {
const action = this.clickQueue.shift();
await action();
}
this.isProcessing = false;
}
handleClickEvent(event) {
const element = event.target;
const clickType = this.getClickType(element);
utils.log("点击了", clickType, element);
const currentTime = Date.now();
if (CONFIG.DOUBLE_SWITCH && currentTime - this.lastClickTime < CONFIG.DOUBLE_INTERVAL &&
clickType === CLICK_TYPE.NODE) {
utils.log("双击展开/折叠触发");
this.doubleClickFlag = true;
this.clickArrowButton(element);
}
this.lastClickTime = currentTime;
if (CONFIG.UNFOLD_ALL_SWITCH && clickType === CLICK_TYPE.ARROW) {
if (this.doubleClickFlag) {
this.doubleClickFlag = false;
return;
}
utils.log("点击折叠按钮处理", element);
this.clickQueue.push(async () => {
await utils.sleep(CONFIG.UNFOLD_INTERVAL);
await this.unfoldChildNodes(element);
});
this.processClickQueue();
}
}
}
let initInterval = setInterval(() => {
const treeContainer = document.querySelector('.sy__file>.fn__flex-1');
if (treeContainer) {
clearInterval(initInterval);
const handler = new TreeHandler();
treeContainer.addEventListener('click',
e => handler.handleClickEvent(e), true);
}
}, 200);
})();
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于