mirror of
https://github.com/bolucat/Archive.git
synced 2025-12-24 13:28:37 +08:00
Update On Wed Dec 10 19:41:24 CET 2025
This commit is contained in:
@@ -7,7 +7,7 @@ jobs:
|
||||
stale:
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/stale@v7.0.0
|
||||
- uses: actions/stale@v10
|
||||
with:
|
||||
stale-issue-message: "Stale Issue"
|
||||
stale-pr-message: "Stale PR"
|
||||
|
||||
@@ -206,9 +206,9 @@ function gen_outbound(flag, node, tag, proxy_table)
|
||||
local first = node.tcp_guise_http_path[1]
|
||||
return (first == "" or not first) and "/" or first
|
||||
end)() or "/",
|
||||
headers = {
|
||||
["User-Agent"] = node.tcp_guise_http_user_agent or nil
|
||||
},
|
||||
headers = node.tcp_guise_http_user_agent and {
|
||||
["User-Agent"] = node.tcp_guise_http_user_agent
|
||||
} or nil,
|
||||
idle_timeout = (node.http_h2_health_check == "1") and node.http_h2_read_idle_timeout or nil,
|
||||
ping_timeout = (node.http_h2_health_check == "1") and node.http_h2_health_check_timeout or nil,
|
||||
}
|
||||
@@ -220,9 +220,9 @@ function gen_outbound(flag, node, tag, proxy_table)
|
||||
type = "http",
|
||||
host = node.http_host or {},
|
||||
path = node.http_path or "/",
|
||||
headers = {
|
||||
["User-Agent"] = node.http_user_agent or nil
|
||||
},
|
||||
headers = node.http_user_agent and {
|
||||
["User-Agent"] = node.http_user_agent
|
||||
} or nil,
|
||||
idle_timeout = (node.http_h2_health_check == "1") and node.http_h2_read_idle_timeout or nil,
|
||||
ping_timeout = (node.http_h2_health_check == "1") and node.http_h2_health_check_timeout or nil,
|
||||
}
|
||||
@@ -233,10 +233,10 @@ function gen_outbound(flag, node, tag, proxy_table)
|
||||
v2ray_transport = {
|
||||
type = "ws",
|
||||
path = node.ws_path or "/",
|
||||
headers = {
|
||||
Host = node.ws_host or nil,
|
||||
["User-Agent"] = node.ws_user_agent or nil
|
||||
},
|
||||
headers = (node.ws_host or node.ws_user_agent) and {
|
||||
Host = node.ws_host,
|
||||
["User-Agent"] = node.ws_user_agent
|
||||
} or nil,
|
||||
max_early_data = tonumber(node.ws_maxEarlyData) or nil,
|
||||
early_data_header_name = (node.ws_earlyDataHeaderName) and node.ws_earlyDataHeaderName or nil --要与 Xray-core 兼容,请将其设置为 Sec-WebSocket-Protocol。它需要与服务器保持一致。
|
||||
}
|
||||
@@ -247,9 +247,9 @@ function gen_outbound(flag, node, tag, proxy_table)
|
||||
type = "httpupgrade",
|
||||
host = node.httpupgrade_host,
|
||||
path = node.httpupgrade_path or "/",
|
||||
headers = {
|
||||
["User-Agent"] = node.httpupgrade_user_agent or nil
|
||||
}
|
||||
headers = node.httpupgrade_user_agent and {
|
||||
["User-Agent"] = node.httpupgrade_user_agent
|
||||
} or nil
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
@@ -178,10 +178,10 @@ function gen_outbound(flag, node, tag, proxy_table)
|
||||
end
|
||||
return r
|
||||
end)() or {"/"},
|
||||
headers = {
|
||||
Host = node.tcp_guise_http_host or {},
|
||||
headers = (node.tcp_guise_http_host or node.tcp_guise_http_user_agent) and {
|
||||
Host = node.tcp_guise_http_host,
|
||||
["User-Agent"] = node.tcp_guise_http_user_agent and {node.tcp_guise_http_user_agent} or nil
|
||||
}
|
||||
} or nil
|
||||
} or nil
|
||||
}
|
||||
} or nil,
|
||||
@@ -201,10 +201,10 @@ function gen_outbound(flag, node, tag, proxy_table)
|
||||
} or nil,
|
||||
wsSettings = (node.transport == "ws") and {
|
||||
path = node.ws_path or "/",
|
||||
headers = {
|
||||
Host = node.ws_host or nil,
|
||||
["User-Agent"] = node.ws_user_agent or nil
|
||||
},
|
||||
headers = (node.ws_host or node.ws_user_agent) and {
|
||||
Host = node.ws_host,
|
||||
["User-Agent"] = node.ws_user_agent
|
||||
} or nil,
|
||||
maxEarlyData = tonumber(node.ws_maxEarlyData) or nil,
|
||||
earlyDataHeaderName = (node.ws_earlyDataHeaderName) and node.ws_earlyDataHeaderName or nil,
|
||||
heartbeatPeriod = tonumber(node.ws_heartbeatPeriod) or nil
|
||||
@@ -220,9 +220,9 @@ function gen_outbound(flag, node, tag, proxy_table)
|
||||
httpupgradeSettings = (node.transport == "httpupgrade") and {
|
||||
path = node.httpupgrade_path or "/",
|
||||
host = node.httpupgrade_host,
|
||||
headers = {
|
||||
["User-Agent"] = node.httpupgrade_user_agent or nil
|
||||
}
|
||||
headers = node.httpupgrade_user_agent and {
|
||||
["User-Agent"] = node.httpupgrade_user_agent
|
||||
} or nil
|
||||
} or nil,
|
||||
xhttpSettings = (node.transport == "xhttp") and {
|
||||
mode = node.xhttp_mode or "auto",
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
<%+cbi/valueheader%>
|
||||
<%
|
||||
-- Template Developers:
|
||||
-- - lwb1978
|
||||
-- Copyright: copyright(c)2025–2027
|
||||
-- Description: Passwall(2) UI template
|
||||
|
||||
local cbid = "cbid." .. self.config .. "." .. section .. "." .. self.option
|
||||
|
||||
-- 读取 MultiValue
|
||||
@@ -41,9 +46,62 @@ for _, item in ipairs(values) do
|
||||
end
|
||||
%>
|
||||
|
||||
<div id="<%=cbid%>" class="cbi-input-select" style="display:inline-block;">
|
||||
<!-- 搜索 -->
|
||||
<input type="text" id="<%=cbid%>.search" class="node_search_input cbi-input-text" placeholder="<%:Search nodes...%>"
|
||||
style="width:100%;padding:6px;margin-bottom:8px;border:1px solid #ccc;border-radius:4px;box-sizing:border-box;max-height:36px;" />
|
||||
<!-- 主容器 -->
|
||||
<div style="max-height:300px;overflow:auto;margin-bottom:8px;white-space:nowrap;">
|
||||
<ul class="cbi-multi" id="<%=cbid%>.node_list" style="padding:0 !important;margin:0 !important;width:100%;box-sizing:border-box;">
|
||||
<% for _, gname in ipairs(group_order) do %>
|
||||
<% local items = groups[gname] %>
|
||||
<li class="group-block" data-group="<%=gname%>" style="list-style:none;padding:0;margin:0 0 8px 0;">
|
||||
<!-- 组标题 -->
|
||||
<div class="group-title" style="cursor:pointer;padding:6px;background:#f0f0f0;border-radius:4px;margin-bottom:4px;display:flex;align-items:center;white-space:nowrap;">
|
||||
<span id="arrow-<%=self.option%>-<%=gname%>" class="mv-arrow-down-small"></span>
|
||||
<b style="margin-left:8px;"><%=gname%></b>
|
||||
<span id="group-count-<%=self.option%>-<%=gname%>" style="margin-left:8px;color:#007bff;">
|
||||
(0/<%=#items%>)
|
||||
</span>
|
||||
</div>
|
||||
<!-- 组内容 -->
|
||||
<ul id="group-<%=self.option%>-<%=gname%>" style="margin:0 0 8px 16px;padding:0;list-style:none;">
|
||||
|
||||
<% for _, item in ipairs(items) do %>
|
||||
<li data-node-name="<%=pcdata(item.label):lower()%>" title="<%=pcdata(item.label)%>" style="list-style:none;padding:0;margin:0;white-space:nowrap;text-align:left;">
|
||||
<div style="display:inline-flex;align-items:center;vertical-align:middle;">
|
||||
<input type="checkbox" class="cbi-input-checkbox" style="vertical-align:middle;margin:0;margin-right:6px;"
|
||||
<%= attr("id", cbid .. "." .. item.key) ..
|
||||
attr("name", cbid) ..
|
||||
attr("value", item.key) ..
|
||||
ifattr(selected[item.key], "checked", "checked")
|
||||
%> />
|
||||
<label for="<%=cbid .. "." .. item.key%>" style="vertical-align:middle;margin:0;padding:0;"><%=pcdata(item.label)%></label>
|
||||
</div>
|
||||
</li>
|
||||
<% end %>
|
||||
</ul>
|
||||
</li>
|
||||
<% end %>
|
||||
</ul>
|
||||
</div>
|
||||
<!-- 控制栏 -->
|
||||
<div style="margin-top:4px;display:flex;gap:4px;align-items:center;">
|
||||
<input class="btn cbi-button cbi-button-edit" type="button" onclick="mv_selectAll('<%=cbid%>','<%=self.option%>',true)" value="<%:Select all%>">
|
||||
<input class="btn cbi-button cbi-button-edit" type="button" onclick="mv_selectAll('<%=cbid%>','<%=self.option%>',false)" value="<%:DeSelect all%>">
|
||||
<span id="count-<%=self.option%>" style="color:#666;"></span>
|
||||
</div>
|
||||
</div>
|
||||
<%+cbi/valuefooter%>
|
||||
|
||||
<%
|
||||
-- 公共部分(只加载一次)
|
||||
if not _G.__NODES_MULTIVALUE_CSS_JS__ then
|
||||
_G.__NODES_MULTIVALUE_CSS_JS__ = true
|
||||
%>
|
||||
<style>
|
||||
/* 组标题的右箭头(折叠) */
|
||||
.lv-arrow-right {
|
||||
/* 组标题的右箭头 */
|
||||
.mv-arrow-right {
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-top: 4px solid transparent;
|
||||
@@ -52,9 +110,8 @@ end
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
/* 组标题的下箭头(展开) */
|
||||
.lv-arrow-down-small {
|
||||
/* 组标题的下箭头 */
|
||||
.mv-arrow-down-small {
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-left: 4px solid transparent;
|
||||
@@ -65,120 +122,67 @@ end
|
||||
}
|
||||
</style>
|
||||
|
||||
<div id="<%=cbid%>" class="cbi-input-select" style="display: inline-block;">
|
||||
<!-- 搜索 -->
|
||||
<input type="text"
|
||||
id="<%=cbid%>.search"
|
||||
class="node-search-input cbi-input-text"
|
||||
placeholder="<%:Search nodes...%>"
|
||||
oninput="filterGroups_<%=self.option%>(this.value)"
|
||||
style="width:100%;padding:6px;margin-bottom:8px;border:1px solid #ccc;border-radius:4px;box-sizing:border-box;max-height:36px;" />
|
||||
<!-- 主容器 -->
|
||||
<div style="max-height:300px; overflow:auto; margin-bottom:8px; white-space:nowrap;">
|
||||
<ul class="cbi-multi" id="<%=cbid%>.node_list" style="padding:0 !important;margin:0 !important;width:100%;box-sizing:border-box;">
|
||||
<% for _, gname in ipairs(group_order) do %>
|
||||
<% local items = groups[gname] %>
|
||||
<li class="group-block" data-group="<%=gname%>" style="list-style:none; padding:0; margin:0 0 8px 0;">
|
||||
<!-- 组标题 -->
|
||||
<div class="group-title"
|
||||
onclick="toggleGroup_<%=self.option%>('<%=gname%>')"
|
||||
style="cursor:pointer;padding:6px;background:#f0f0f0;border-radius:4px;margin-bottom:4px;display:flex;align-items:center;white-space:nowrap;">
|
||||
<span id="arrow-<%=self.option%>-<%=gname%>" class="lv-arrow-down-small"></span>
|
||||
<b style="margin-left:8px;"><%=gname%></b>
|
||||
<span id="group-count-<%=self.option%>-<%=gname%>" style="margin-left:8px;color:#007bff;">
|
||||
(0/<%=#items%>)
|
||||
</span>
|
||||
</div>
|
||||
<!-- 组内容(可折叠)-->
|
||||
<ul id="group-<%=self.option%>-<%=gname%>" style="margin:0 0 8px 16px; padding:0; list-style:none;">
|
||||
|
||||
<% for _, item in ipairs(items) do %>
|
||||
<li data-node-name="<%=pcdata(item.label):lower()%>" style="list-style:none;padding:0;margin:0;white-space:nowrap;" title="<%=pcdata(item.label)%>">
|
||||
<input
|
||||
type="checkbox"
|
||||
class="cbi-input-checkbox"
|
||||
style="vertical-align: middle; margin-right:6px;"
|
||||
<%= attr("id", cbid .. "." .. item.key) ..
|
||||
attr("name", cbid) ..
|
||||
attr("value", item.key) ..
|
||||
ifattr(selected[item.key], "checked", "checked")
|
||||
%> />
|
||||
<label for="<%=cbid .. "." .. item.key%>"><%=pcdata(item.label)%></label>
|
||||
</li>
|
||||
<% end %>
|
||||
</ul>
|
||||
</li>
|
||||
<% end %>
|
||||
</ul>
|
||||
</div>
|
||||
<!-- 控制栏 -->
|
||||
<div style="margin-top:4px;display:flex;gap:4px;align-items:center;">
|
||||
<input class="btn cbi-button cbi-button-edit" type="button" onclick="selectAll_<%=self.option%>(true)" value="<%:Select all%>">
|
||||
<input class="btn cbi-button cbi-button-edit" type="button" onclick="selectAll_<%=self.option%>(false)" value="<%:DeSelect all%>">
|
||||
<span id="count-<%=self.option%>" style="color:#666;"></span>
|
||||
</div>
|
||||
</div>
|
||||
<%+cbi/valuefooter%>
|
||||
|
||||
<script type="text/javascript">
|
||||
//<![CDATA[
|
||||
(function(){
|
||||
const cbid = "<%=cbid%>";
|
||||
const opt = "<%=self.option%>";
|
||||
const listId = cbid + ".node_list";
|
||||
|
||||
// 折叠组
|
||||
window["toggleGroup_" + opt] = function(g){
|
||||
const ul = document.getElementById("group-" + opt + "-" + g);
|
||||
const arrow = document.getElementById("arrow-" + opt + "-" + g);
|
||||
function mv_toggleGroup(opt, nodeList, searchInput, g) {
|
||||
const ul = nodeList.querySelector("#group-" + opt + "-" + g);
|
||||
const arrow = nodeList.querySelector("#arrow-" + opt + "-" + g);
|
||||
if (!ul) return;
|
||||
// 判断是否在搜索状态
|
||||
const keyword = document.getElementById(cbid + ".search").value.trim().toLowerCase();
|
||||
const keyword = searchInput.value.trim().toLowerCase();
|
||||
const isSearching = keyword.length > 0;
|
||||
// 搜索状态下,仅切换当前组,不处理其他组
|
||||
if (isSearching) {
|
||||
if (ul.style.display === "none") {
|
||||
ul.style.display = "";
|
||||
if (arrow) arrow.className = "lv-arrow-down-small";
|
||||
} else {
|
||||
ul.style.display = "none";
|
||||
if (arrow) arrow.className = "lv-arrow-right";
|
||||
}
|
||||
if (isSearching){
|
||||
ul.style.display = ul.style.display === "none" ? "block" : "none";
|
||||
if (arrow) arrow.className = ul.style.display === "none" ? "mv-arrow-right" : "mv-arrow-down-small";
|
||||
return;
|
||||
}
|
||||
// 非搜索模式:先折叠其他组
|
||||
const groups = document.querySelectorAll("[id='" + listId + "'] .group-block");
|
||||
groups.forEach(group=>{
|
||||
nodeList.querySelectorAll(".group-block").forEach(group=>{
|
||||
const gname = group.getAttribute("data-group");
|
||||
const gul = document.getElementById("group-" + opt + "-" + gname);
|
||||
const garrow = document.getElementById("arrow-" + opt + "-" + gname);
|
||||
if (gname !== g) {
|
||||
if (gul) gul.style.display = "none";
|
||||
if (garrow) arrow.className = "lv-arrow-right";
|
||||
if (garrow) garrow.className = "mv-arrow-right";
|
||||
}
|
||||
});
|
||||
document.getElementById(listId).parentNode.scrollTop = 0;
|
||||
nodeList.parentNode.scrollTop = 0;
|
||||
// 切换当前组
|
||||
if (ul.style.display === "none") {
|
||||
ul.style.display = "";
|
||||
if (arrow) arrow.className = "lv-arrow-down-small";
|
||||
} else {
|
||||
ul.style.display = "none";
|
||||
if (arrow) arrow.className = "lv-arrow-right";
|
||||
}
|
||||
ul.style.display = ul.style.display === "none" ? "block" : "none";
|
||||
if (arrow) arrow.className = ul.style.display === "none" ? "mv-arrow-right" : "mv-arrow-down-small";
|
||||
};
|
||||
|
||||
// 计数
|
||||
function mv_updateCount(opt, nodeList) {
|
||||
// 当前实例下的所有 checkbox
|
||||
const cbs = nodeList.querySelectorAll("input[type=checkbox]");
|
||||
let checked = 0;
|
||||
cbs.forEach(cb => { if(cb.checked) checked++; });
|
||||
// 更新总计
|
||||
const totalSpan = document.getElementById("count-" + opt);
|
||||
if (totalSpan) {
|
||||
totalSpan.innerHTML = "<%:Selected:%> <span style='color:red;'>" + checked + " / " + cbs.length + "</span>";
|
||||
}
|
||||
// 更新每个组计数
|
||||
nodeList.querySelectorAll(".group-block").forEach(group => {
|
||||
const gname = group.getAttribute("data-group");
|
||||
const groupCbs = group.querySelectorAll("li[data-node-name] input[type=checkbox]");
|
||||
let groupChecked = 0;
|
||||
groupCbs.forEach(cb => { if(cb.checked) groupChecked++; });
|
||||
const span = document.getElementById("group-count-" + opt + "-" + gname);
|
||||
if(span) span.textContent = "(" + groupChecked + "/" + groupCbs.length + ")";
|
||||
});
|
||||
}
|
||||
|
||||
// 搜索
|
||||
window["filterGroups_" + opt] = function(keyword){
|
||||
keyword = keyword.toLowerCase().trim();
|
||||
|
||||
const groups = document.querySelectorAll("[id='" + listId + "'] .group-block");
|
||||
|
||||
groups.forEach(group=>{
|
||||
function mv_filterGroups(keyword, opt, nodeList) {
|
||||
keyword = (keyword || "").toLowerCase().trim();
|
||||
nodeList.querySelectorAll(".group-block").forEach(group => {
|
||||
const items = group.querySelectorAll("li[data-node-name]");
|
||||
let matchCount = 0;
|
||||
|
||||
items.forEach(li=>{
|
||||
items.forEach(li => {
|
||||
const name = li.getAttribute("data-node-name");
|
||||
if (!keyword || name.indexOf(keyword) !== -1) {
|
||||
li.style.display = "";
|
||||
@@ -187,7 +191,7 @@ end
|
||||
li.style.display = "none";
|
||||
}
|
||||
});
|
||||
// 搜索时自动展开所有组
|
||||
// 搜索时自动展开组
|
||||
const gname = group.getAttribute("data-group");
|
||||
const ul = document.getElementById("group-" + opt + "-" + gname);
|
||||
const arrow = document.getElementById("arrow-" + opt + "-" + gname);
|
||||
@@ -196,88 +200,71 @@ end
|
||||
group.style.display = "none";
|
||||
} else {
|
||||
group.style.display = "";
|
||||
if (keyword) {
|
||||
if (keyword && ul && arrow) {
|
||||
ul.style.display = "";
|
||||
arrow.className = "lv-arrow-down-small";
|
||||
arrow.className = "mv-arrow-down-small";
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
updateCount();
|
||||
|
||||
mv_updateCount(opt, nodeList);
|
||||
// 清空搜索后恢复全部折叠
|
||||
if (!keyword) {
|
||||
const groups = document.querySelectorAll("[id='" + listId + "'] .group-block");
|
||||
groups.forEach(group=>{
|
||||
const gname = group.getAttribute("data-group");
|
||||
const ul = document.getElementById("group-" + opt + "-" + gname);
|
||||
const arrow = document.getElementById("arrow-" + opt + "-" + gname);
|
||||
if (ul) ul.style.display = "none";
|
||||
if (arrow) arrow.className = "lv-arrow-right";
|
||||
});
|
||||
mv_collapseAllGroups(opt, nodeList);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// 全选 / 全不选
|
||||
window["selectAll_" + opt] = function(flag){
|
||||
const cbs = document.querySelectorAll("[id='" + listId + "'] input[type=checkbox]");
|
||||
function mv_selectAll(cbid, opt, flag) {
|
||||
const nodeList = document.getElementById(cbid + ".node_list");
|
||||
const cbs = nodeList.querySelectorAll("input[type=checkbox]");
|
||||
cbs.forEach(cb=>{
|
||||
if (cb.offsetParent !== null) cb.checked = flag;
|
||||
});
|
||||
updateCount();
|
||||
mv_updateCount(opt, nodeList);
|
||||
};
|
||||
|
||||
// 计数
|
||||
function updateCount(){
|
||||
const cbs = document.querySelectorAll("[id='" + listId + "'] input[type=checkbox]");
|
||||
let checked = 0;
|
||||
cbs.forEach(cb=>{ if (cb.checked) checked++; });
|
||||
// 更新总计
|
||||
document.getElementById("count-" + opt).innerHTML =
|
||||
"<%:Selected:%> <span style='color:red;'>" + checked + " / " + cbs.length + "</span>";
|
||||
|
||||
// 更新每个组
|
||||
const groups = document.querySelectorAll("[id='" + listId + "'] .group-block");
|
||||
groups.forEach(group=>{
|
||||
const gname = group.getAttribute("data-group");
|
||||
const groupCbs = group.querySelectorAll("li[data-node-name] input[type=checkbox]");
|
||||
let groupChecked = 0;
|
||||
groupCbs.forEach(cb=>{ if(cb.checked) groupChecked++; });
|
||||
const span = document.getElementById("group-count-" + opt + "-" + gname);
|
||||
if(span) span.textContent = "(" + groupChecked + "/" + groupCbs.length + ")";
|
||||
});
|
||||
}
|
||||
|
||||
document.getElementById(listId)?.addEventListener("change", updateCount);
|
||||
|
||||
// 初始化折叠所有组和计数
|
||||
const initObserver = new MutationObserver(() => {
|
||||
const list = document.getElementById(listId);
|
||||
if (!list) return;
|
||||
|
||||
if (list.offsetParent === null) return;
|
||||
|
||||
if (list.dataset.initDone === "1") return;
|
||||
list.dataset.initDone = "1";
|
||||
|
||||
const groups = document.querySelectorAll("[id='" + listId + "'] .group-block");
|
||||
groups.forEach(group => {
|
||||
// 折叠所有组
|
||||
function mv_collapseAllGroups(opt, nodeList) {
|
||||
nodeList.querySelectorAll(".group-block").forEach(group => {
|
||||
const gname = group.getAttribute("data-group");
|
||||
const ul = document.getElementById("group-" + opt + "-" + gname);
|
||||
const arrow = document.getElementById("arrow-" + opt + "-" + gname);
|
||||
if (ul) ul.style.display = "none";
|
||||
if (arrow) arrow.className = "lv-arrow-right";
|
||||
if (arrow) arrow.className = "mv-arrow-right";
|
||||
});
|
||||
}
|
||||
//]]>
|
||||
</script>
|
||||
<% end %>
|
||||
|
||||
updateCount();
|
||||
<script type="text/javascript">
|
||||
//<![CDATA[
|
||||
(function(){
|
||||
const cbid = "<%=cbid%>";
|
||||
const opt = "<%=self.option%>";
|
||||
const searchInput = document.getElementById(cbid + ".search");
|
||||
const nodeList = document.getElementById(cbid + ".node_list");
|
||||
|
||||
nodeList.querySelectorAll(".group-title").forEach(title => {
|
||||
title.addEventListener("click", function() {
|
||||
const g = this.closest(".group-block")?.getAttribute("data-group");
|
||||
if (g) mv_toggleGroup(opt, nodeList, searchInput, g);
|
||||
});
|
||||
});
|
||||
|
||||
initObserver.observe(document.body, {
|
||||
attributes: true,
|
||||
subtree: true,
|
||||
attributeFilter: ["style", "class"]
|
||||
searchInput.addEventListener("input", function() {
|
||||
mv_filterGroups(this.value, opt, nodeList);
|
||||
})
|
||||
|
||||
// checkbox 改变时更新计数
|
||||
nodeList.addEventListener("change", () => {
|
||||
mv_updateCount(opt, nodeList);
|
||||
});
|
||||
|
||||
// 初始化折叠所有组和计数
|
||||
mv_collapseAllGroups(opt, nodeList)
|
||||
mv_updateCount(opt, nodeList);
|
||||
|
||||
})();
|
||||
//]]>
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user