MediaWiki:Common.js:修订间差异
外观
Willson-v-(留言 | 贡献) 无编辑摘要 |
Willson-v-(留言 | 贡献) 无编辑摘要 |
||
第110行: | 第110行: | ||
/////// Toggle Content | /////// Toggle Content | ||
if( | function cssSanitizer(cssStr) { | ||
let result = ""; | |||
if (typeof cssStr === "string") { | |||
if ( | result = cssStr; | ||
} | |||
result = result.replace(RegExp(decodeURIComponent("%3C!--"), "g"), ""); | |||
result = result.replace(RegExp(decodeURIComponent("-%3E"), "g"), ""); | |||
result = result.replace(/\/\//g, ""); | |||
result = result.replace(/url/g, ""); | |||
result = result.replace(/&/g, ""); | |||
result = result.replace(/pointer-event/g, ";"); | |||
result = result.replace( | |||
/display\s*:\s*none\s*!\s*important/g, | |||
"display: none" | |||
); | |||
return result; | |||
} | |||
function uuidv4() { | |||
let result = ""; | |||
while (result === "" || $(`#${result}, [name="${result}"]`).length > 0) { | |||
result = ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, (c) => | |||
( | |||
c ^ | |||
(crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4))) | |||
).toString(16) | |||
); | |||
} | |||
return result; | |||
} | |||
function datasetParser(ele) { | |||
const result = { | |||
config: {}, | |||
data: {}, | |||
}; | |||
Object.entries(ele.dataset) | |||
.filter(([n, m]) => n.startsWith("key-") && !/['"<>\\/]/.test(m)) | |||
.forEach(([__key, _key]) => { | |||
const value = ele.dataset[`value-${__key.substring(4)}`]; | |||
if (_key.length > 0 && value.length > 0) { | |||
const isConfig = _key.startsWith("@"); | |||
const key = isConfig ? _key.substring(1) : _key; | |||
const base = result[isConfig ? "config" : "data"]; | |||
base[key] = value; | |||
if (/@o(?:n|ff)$/.test(_key)) { | |||
const id = _key.replace(/@o(?:n|ff)$/, ""); | |||
if (!(id in base)) { | |||
base[id] = value; | |||
} | |||
} else if (_key.endsWith("@input")) { | |||
base[_key] = value; | |||
const id = _key.replace(/@input$/, ""); | |||
if (!(id in base)) { | |||
base[id] = ""; | |||
} | |||
} else { | |||
if (!(`${key}@on` in base)) { | |||
base[`${key}@on`] = value; | |||
} | |||
if (!(`${key}@off` in base)) { | |||
base[`${key}@off`] = value; | |||
} | |||
if (!(`${key}@input` in base)) { | |||
base[`${key}@input`] = ""; | |||
} | |||
} | } | ||
} | |||
}); | |||
return result; | |||
} | |||
function getEntries(obj) { | |||
return Object.entries(obj).filter( | |||
([k, n]) => !/@(?:on|off|input)$/.test(k) && !/['"<>\\/]/.test(n) | |||
); | |||
} | |||
function triggerChangeHandler($ele) { | |||
$ele.each((_, ele) => { | |||
$(ele).triggerHandler("change", [true]); | |||
}); | |||
} | |||
const textToggleDisplayStyle = {}; | |||
$(".textToggleDisplayStyle").each((_, ele) => { | |||
const dataset = datasetParser(ele).data; | |||
getEntries(dataset).forEach(([id, style]) => { | |||
textToggleDisplayStyle[id] = style; | |||
}); | |||
}); | |||
$(".textToggleDisplay") | |||
.each((_, ele) => { | |||
if (ele.dataset.id in textToggleDisplayStyle) { | |||
$(ele).attr( | |||
"style", | |||
cssSanitizer(textToggleDisplayStyle[ele.dataset.id]) | |||
); | |||
} | |||
}) | |||
.addClass("hidden"); | |||
$(".textToggleDisplayButtons").each((_, ele) => { | |||
const self = $(ele); | |||
const parsedDataset = datasetParser(ele); | |||
const ifRadio = | |||
"radio" in parsedDataset.config && parsedDataset.config.radio.length > 0; | |||
const ifForceNoCancel = | |||
"forceNoCancel" in parsedDataset.config && | |||
parsedDataset.config.forceNoCancel.length > 0; | |||
const ifReverse = | |||
"reverse" in parsedDataset.config && | |||
parsedDataset.config.reverse.length > 0; | |||
const name = uuidv4(); | |||
let hasDefault = false; | |||
self.children("span[data-key]").each((_, e) => { | |||
if (/['"<>\\/]/.test(e.dataset.key)) { | |||
e.remove(); | |||
return; | |||
} | |||
const $e = $(e); | |||
const input = $("<input/>"); | |||
input | |||
.attr({ | |||
"data-id": e.dataset.key, | |||
type: ifRadio ? "radio" : "checkbox", | |||
}) | |||
.addClass( | |||
ifReverse | |||
? "textToggleDisplayButtonInputReverse" | |||
: "textToggleDisplayButtonInput" | |||
); | |||
if (ifRadio) { | |||
input.attr("name", name); | |||
} | |||
const label = $("<label/>"); | |||
$e.children().appendTo(label); | |||
label | |||
.prepend(input) | |||
.appendTo(e) | |||
.attr("data-id", e.dataset.key) | |||
.addClass("textToggleDisplayButtonLabel"); | |||
$e.find("*").each((_, e) => { | |||
e.addEventListener( | |||
"click", | |||
(evt) => { | |||
evt.stopImmediatePropagation(); | |||
evt.stopPropagation(); | |||
if (!$(evt.target).is(input)) { | |||
evt.preventDefault(); | |||
if (ifRadio ? !input.prop("checked") : true) { | |||
input.prop("checked", !input.prop("checked")).trigger("change"); | |||
} | |||
} | |||
}, | |||
{ | |||
capture: true, | |||
} | |||
); | |||
}); | |||
if (e.dataset.key === parsedDataset.config.default) { | |||
input.prop("checked", true); | |||
hasDefault = true; | |||
} | |||
}); | |||
if (ifRadio && (!hasDefault || !ifForceNoCancel)) { | |||
const input = $("<input/>"); | |||
const inputId = uuidv4(); | |||
input | |||
.attr({ | |||
"data-id": "", | |||
"data-radio-cancel": "true", | |||
id: inputId, | |||
name, | |||
type: "radio", | |||
}) | |||
.addClass( | |||
ifReverse | |||
? "textToggleDisplayButtonInputReverse" | |||
: "textToggleDisplayButtonInput" | |||
) | |||
.css({ | |||
"margin-left": "0", | |||
"margin-right": "0", | |||
width: "0", | |||
}); | |||
const label = $("<label/>"); | |||
const span = $("<span/>"); | |||
span.text("取消选择"); | |||
label | |||
.attr({ | |||
"data-id": "", | |||
for: inputId, | |||
}) | |||
.addClass("textToggleDisplayButtonLabel cancelButton"); | |||
self.append(label.append(input).append(span)); | |||
if (!hasDefault) { | |||
input.prop("checked", true); | |||
} | |||
} | |||
}); | |||
$(".textToggleDisplayButtonsStyle").each((_, ele) => { | |||
const parsedDataset = datasetParser(ele); | |||
$(".textToggleDisplayButtonLabel.cancelButton").attr({ | |||
"data-style-off": parsedDataset.config["cancel@off"] || "", | |||
"data-style-on": parsedDataset.config["cancel@on"] || "", | |||
}); | |||
$(".textToggleDisplayButtonLabel.cancelButton > input").attr( | |||
"style", | |||
cssSanitizer(parsedDataset.config["cancel@input"]) | |||
); | |||
getEntries(parsedDataset.data).forEach(([id]) => { | |||
$(`.textToggleDisplayButtonLabel[data-id="${id}"]`) | |||
.attr({ | |||
"data-style-off": parsedDataset.data[`${id}@off`] || "", | |||
"data-style-on": parsedDataset.data[`${id}@on`] || "", | |||
}) | |||
.children("input") | |||
.attr("style", cssSanitizer(parsedDataset.data[`${id}@input`])); | |||
}); | |||
}); | |||
triggerChangeHandler( | |||
$(".textToggleDisplayButtonInput").on( | |||
"change", | |||
({ target }, fromTriggerHandler = false) => { | |||
const { | |||
dataset: { id }, | |||
checked, | |||
} = target; | |||
const textToggleDisplayTarget = $(`.textToggleDisplay[data-id="${id}"]`); | |||
const { | |||
config: { toggleClass }, | |||
} = datasetParser($(target).closest(".textToggleDisplayButtons")[0]); | |||
const toggleClassName = | |||
typeof toggleClass === "string" && toggleClass.length > 0 | |||
? toggleClass | |||
: "hidden"; | |||
if (toggleClassName !== "hidden") { | |||
textToggleDisplayTarget.removeClass("hidden"); | |||
} | |||
textToggleDisplayTarget[checked ? "removeClass" : "addClass"]( | |||
toggleClassName | |||
)[checked ? "addClass" : "removeClass"]("textToggleDisplay-on"); | |||
textToggleDisplayTarget | |||
.prev(".textToggleDisplay") | |||
[checked ? "addClass" : "removeClass"]("textToggleDisplay-before-on"); | |||
textToggleDisplayTarget | |||
.next(".textToggleDisplay") | |||
[checked ? "addClass" : "removeClass"]("textToggleDisplay-after-on"); | |||
const self = $(target); | |||
const label = self.closest(".textToggleDisplayButtonLabel"); | |||
const span = label.children(".on"); | |||
label[checked ? "addClass" : "removeClass"]("on").attr( | |||
"style", | |||
cssSanitizer(label.attr(checked ? "data-style-on" : "data-style-off")) | |||
); | |||
if (checked) { | |||
span.attr("style", cssSanitizer(textToggleDisplayStyle[id])); | |||
} else { | |||
span.removeAttr("style"); | |||
} | |||
const labelContainer = label.closest("span[data-order][data-key]"); | |||
labelContainer | |||
.prev("span[data-order][data-key]") | |||
.children(".textToggleDisplayButtonLabel") | |||
.last() | |||
[checked ? "addClass" : "removeClass"]("before-on"); | |||
labelContainer | |||
.next("span[data-order][data-key]") | |||
.children(".textToggleDisplayButtonLabel") | |||
.first() | |||
[checked ? "addClass" : "removeClass"]("after-on"); | |||
if (!fromTriggerHandler) { | |||
triggerChangeHandler( | |||
self.closest(".textToggleDisplayButtons").find("input").not(target) | |||
); | |||
} | |||
} | |||
) | |||
); | |||
triggerChangeHandler( | |||
$(".textToggleDisplayButtonInputReverse").on( | |||
"change", | |||
({ target }, fromTriggerHandler = false) => { | |||
const { | |||
dataset: { id, radioCancel }, | |||
checked, | |||
} = target; | |||
const isRadioCancel = (radioCancel || "").length > 0; | |||
const self = $(target); | |||
const label = self.closest(".textToggleDisplayButtonLabel"); | |||
if (isRadioCancel) { | |||
label[checked ? "addClass" : "removeClass"]("on").attr( | |||
"style", | |||
cssSanitizer(label.attr(checked ? "data-style-on" : "data-style-off")) | |||
); | |||
} else { | |||
const textToggleDisplayTarget = $( | |||
`.textToggleDisplay[data-id="${id}"]` | |||
); | |||
const { | |||
config: { toggleClass }, | |||
} = datasetParser($(target).closest(".textToggleDisplayButtons")[0]); | |||
const toggleClassName = | |||
typeof toggleClass === "string" && toggleClass.length > 0 | |||
? toggleClass | |||
: "hidden"; | |||
if (toggleClassName !== "hidden") { | |||
textToggleDisplayTarget.removeClass("hidden"); | |||
} | |||
textToggleDisplayTarget[checked ? "addClass" : "removeClass"]( | |||
toggleClassName | |||
)[checked ? "removeClass" : "addClass"]("textToggleDisplay-on"); | |||
textToggleDisplayTarget | |||
.prev(".textToggleDisplay") | |||
[checked ? "removeClass" : "addClass"]("textToggleDisplay-before-on"); | |||
textToggleDisplayTarget | |||
.next(".textToggleDisplay") | |||
[checked ? "removeClass" : "addClass"]("textToggleDisplay-after-on"); | |||
const span = label.children("span"); | |||
label[checked ? "removeClass" : "addClass"]("on").attr( | |||
"style", | |||
cssSanitizer(label.attr(checked ? "data-style-off" : "data-style-on")) | |||
); | |||
if (checked) { | |||
span.removeAttr(".on"); | |||
} else { | |||
span.attr("style", cssSanitizer(textToggleDisplayStyle[id])); | |||
} | |||
} | |||
const labelContainer = label.closest("span[data-order][data-key]"); | |||
labelContainer | |||
.prev("span[data-order][data-key]") | |||
.children(".textToggleDisplayButtonLabel") | |||
.last() | |||
[checked ? "addClass" : "removeClass"]("before-on"); | |||
labelContainer | |||
.next("span[data-order][data-key]") | |||
.children(".textToggleDisplayButtonLabel") | |||
.first() | |||
[checked ? "addClass" : "removeClass"]("after-on"); | |||
if (!fromTriggerHandler) { | |||
triggerChangeHandler( | |||
self.closest(".textToggleDisplayButtons").find("input").not(target) | |||
); | |||
} | |||
} | |||
) | |||
); | |||
$(window).on("beforeunload", () => { | |||
$(".textToggleDisplayButtons input[type=checkbox]").prop("checked", false); | |||
}); | |||
///////结束//////// | ///////结束//////// |
2022年5月4日 (三) 14:41的版本
/** * Collapsible tables ********************************************************* * * Description: Allows tables to be collapsed, showing only the header. See * [[Wikipedia:NavFrame]]. * Maintainers: [[User:R. Koot]] */ var autoCollapse = 2; var collapseCaption = '隐藏'; var expandCaption = '显示'; window.collapseTable = function ( tableIndex ) { var Button = document.getElementById( 'collapseButton' + tableIndex ); var Table = document.getElementById( 'collapsibleTable' + tableIndex ); if ( !Table || !Button ) { return false; } var Rows = Table.rows; var i; if ( Button.firstChild.data === collapseCaption ) { for ( i = 1; i < Rows.length; i++ ) { Rows[i].style.display = 'none'; } Button.firstChild.data = expandCaption; } else { for ( i = 1; i < Rows.length; i++ ) { Rows[i].style.display = Rows[0].style.display; } Button.firstChild.data = collapseCaption; } }; function createCollapseButtons() { var tableIndex = 0; var NavigationBoxes = {}; var Tables = document.getElementsByTagName( 'table' ); var i; function handleButtonLink( index, e ) { window.collapseTable( index ); e.preventDefault(); } for ( i = 0; i < Tables.length; i++ ) { if ( $( Tables[i] ).hasClass( 'collapsible' ) ) { /* only add button and increment count if there is a header row to work with */ var HeaderRow = Tables[i].getElementsByTagName( 'tr' )[0]; if ( !HeaderRow ) continue; var Header = HeaderRow.getElementsByTagName( 'th' )[0]; if ( !Header ) continue; NavigationBoxes[ tableIndex ] = Tables[i]; Tables[i].setAttribute( 'id', 'collapsibleTable' + tableIndex ); var Button = document.createElement( 'span' ); var ButtonLink = document.createElement( 'a' ); var ButtonText = document.createTextNode( collapseCaption ); Button.className = 'collapseButton'; /* Styles are declared in Common.css */ ButtonLink.style.color = Header.style.color; ButtonLink.setAttribute( 'id', 'collapseButton' + tableIndex ); ButtonLink.setAttribute( 'href', '#' ); $( ButtonLink ).on( 'click', $.proxy( handleButtonLink, ButtonLink, tableIndex ) ); ButtonLink.appendChild( ButtonText ); //Button.appendChild( document.createTextNode( '[' ) ); Button.appendChild( ButtonLink ); //Button.appendChild( document.createTextNode( ']' ) ); Header.insertBefore( Button, Header.firstChild ); tableIndex++; } } for ( i = 0; i < tableIndex; i++ ) { if ( $( NavigationBoxes[i] ).hasClass( 'collapsed' ) || ( tableIndex >= autoCollapse && $( NavigationBoxes[i] ).hasClass( 'autocollapse' ) ) ) { window.collapseTable( i ); } else if ( $( NavigationBoxes[i] ).hasClass ( 'innercollapse' ) ) { var element = NavigationBoxes[i]; while ((element = element.parentNode)) { if ( $( element ).hasClass( 'outercollapse' ) ) { window.collapseTable ( i ); break; } } } } } mw.hook( 'wikipage.content' ).add( createCollapseButtons ); /////分页tab/////// $(document).ready( function(){ $(".tab").each(function(indextabs) { $(this).click(function(e) { //所点击的同胞去除active $(this).siblings().removeClass("active"); //同一个div下的 .tab-c 去除active $(this).parent().siblings().find(".tab-c").removeClass("active"); $(this).toggleClass("active"); $(".tab-c") .eq(indextabs) .toggleClass("active"); }); }); }); /////// Toggle Content function cssSanitizer(cssStr) { let result = ""; if (typeof cssStr === "string") { result = cssStr; } result = result.replace(RegExp(decodeURIComponent("%3C!--"), "g"), ""); result = result.replace(RegExp(decodeURIComponent("-%3E"), "g"), ""); result = result.replace(/\/\//g, ""); result = result.replace(/url/g, ""); result = result.replace(/&/g, ""); result = result.replace(/pointer-event/g, ";"); result = result.replace( /display\s*:\s*none\s*!\s*important/g, "display: none" ); return result; } function uuidv4() { let result = ""; while (result === "" || $(`#${result}, [name="${result}"]`).length > 0) { result = ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, (c) => ( c ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4))) ).toString(16) ); } return result; } function datasetParser(ele) { const result = { config: {}, data: {}, }; Object.entries(ele.dataset) .filter(([n, m]) => n.startsWith("key-") && !/['"<>\\/]/.test(m)) .forEach(([__key, _key]) => { const value = ele.dataset[`value-${__key.substring(4)}`]; if (_key.length > 0 && value.length > 0) { const isConfig = _key.startsWith("@"); const key = isConfig ? _key.substring(1) : _key; const base = result[isConfig ? "config" : "data"]; base[key] = value; if (/@o(?:n|ff)$/.test(_key)) { const id = _key.replace(/@o(?:n|ff)$/, ""); if (!(id in base)) { base[id] = value; } } else if (_key.endsWith("@input")) { base[_key] = value; const id = _key.replace(/@input$/, ""); if (!(id in base)) { base[id] = ""; } } else { if (!(`${key}@on` in base)) { base[`${key}@on`] = value; } if (!(`${key}@off` in base)) { base[`${key}@off`] = value; } if (!(`${key}@input` in base)) { base[`${key}@input`] = ""; } } } }); return result; } function getEntries(obj) { return Object.entries(obj).filter( ([k, n]) => !/@(?:on|off|input)$/.test(k) && !/['"<>\\/]/.test(n) ); } function triggerChangeHandler($ele) { $ele.each((_, ele) => { $(ele).triggerHandler("change", [true]); }); } const textToggleDisplayStyle = {}; $(".textToggleDisplayStyle").each((_, ele) => { const dataset = datasetParser(ele).data; getEntries(dataset).forEach(([id, style]) => { textToggleDisplayStyle[id] = style; }); }); $(".textToggleDisplay") .each((_, ele) => { if (ele.dataset.id in textToggleDisplayStyle) { $(ele).attr( "style", cssSanitizer(textToggleDisplayStyle[ele.dataset.id]) ); } }) .addClass("hidden"); $(".textToggleDisplayButtons").each((_, ele) => { const self = $(ele); const parsedDataset = datasetParser(ele); const ifRadio = "radio" in parsedDataset.config && parsedDataset.config.radio.length > 0; const ifForceNoCancel = "forceNoCancel" in parsedDataset.config && parsedDataset.config.forceNoCancel.length > 0; const ifReverse = "reverse" in parsedDataset.config && parsedDataset.config.reverse.length > 0; const name = uuidv4(); let hasDefault = false; self.children("span[data-key]").each((_, e) => { if (/['"<>\\/]/.test(e.dataset.key)) { e.remove(); return; } const $e = $(e); const input = $("<input/>"); input .attr({ "data-id": e.dataset.key, type: ifRadio ? "radio" : "checkbox", }) .addClass( ifReverse ? "textToggleDisplayButtonInputReverse" : "textToggleDisplayButtonInput" ); if (ifRadio) { input.attr("name", name); } const label = $("<label/>"); $e.children().appendTo(label); label .prepend(input) .appendTo(e) .attr("data-id", e.dataset.key) .addClass("textToggleDisplayButtonLabel"); $e.find("*").each((_, e) => { e.addEventListener( "click", (evt) => { evt.stopImmediatePropagation(); evt.stopPropagation(); if (!$(evt.target).is(input)) { evt.preventDefault(); if (ifRadio ? !input.prop("checked") : true) { input.prop("checked", !input.prop("checked")).trigger("change"); } } }, { capture: true, } ); }); if (e.dataset.key === parsedDataset.config.default) { input.prop("checked", true); hasDefault = true; } }); if (ifRadio && (!hasDefault || !ifForceNoCancel)) { const input = $("<input/>"); const inputId = uuidv4(); input .attr({ "data-id": "", "data-radio-cancel": "true", id: inputId, name, type: "radio", }) .addClass( ifReverse ? "textToggleDisplayButtonInputReverse" : "textToggleDisplayButtonInput" ) .css({ "margin-left": "0", "margin-right": "0", width: "0", }); const label = $("<label/>"); const span = $("<span/>"); span.text("取消选择"); label .attr({ "data-id": "", for: inputId, }) .addClass("textToggleDisplayButtonLabel cancelButton"); self.append(label.append(input).append(span)); if (!hasDefault) { input.prop("checked", true); } } }); $(".textToggleDisplayButtonsStyle").each((_, ele) => { const parsedDataset = datasetParser(ele); $(".textToggleDisplayButtonLabel.cancelButton").attr({ "data-style-off": parsedDataset.config["cancel@off"] || "", "data-style-on": parsedDataset.config["cancel@on"] || "", }); $(".textToggleDisplayButtonLabel.cancelButton > input").attr( "style", cssSanitizer(parsedDataset.config["cancel@input"]) ); getEntries(parsedDataset.data).forEach(([id]) => { $(`.textToggleDisplayButtonLabel[data-id="${id}"]`) .attr({ "data-style-off": parsedDataset.data[`${id}@off`] || "", "data-style-on": parsedDataset.data[`${id}@on`] || "", }) .children("input") .attr("style", cssSanitizer(parsedDataset.data[`${id}@input`])); }); }); triggerChangeHandler( $(".textToggleDisplayButtonInput").on( "change", ({ target }, fromTriggerHandler = false) => { const { dataset: { id }, checked, } = target; const textToggleDisplayTarget = $(`.textToggleDisplay[data-id="${id}"]`); const { config: { toggleClass }, } = datasetParser($(target).closest(".textToggleDisplayButtons")[0]); const toggleClassName = typeof toggleClass === "string" && toggleClass.length > 0 ? toggleClass : "hidden"; if (toggleClassName !== "hidden") { textToggleDisplayTarget.removeClass("hidden"); } textToggleDisplayTarget[checked ? "removeClass" : "addClass"]( toggleClassName )[checked ? "addClass" : "removeClass"]("textToggleDisplay-on"); textToggleDisplayTarget .prev(".textToggleDisplay") [checked ? "addClass" : "removeClass"]("textToggleDisplay-before-on"); textToggleDisplayTarget .next(".textToggleDisplay") [checked ? "addClass" : "removeClass"]("textToggleDisplay-after-on"); const self = $(target); const label = self.closest(".textToggleDisplayButtonLabel"); const span = label.children(".on"); label[checked ? "addClass" : "removeClass"]("on").attr( "style", cssSanitizer(label.attr(checked ? "data-style-on" : "data-style-off")) ); if (checked) { span.attr("style", cssSanitizer(textToggleDisplayStyle[id])); } else { span.removeAttr("style"); } const labelContainer = label.closest("span[data-order][data-key]"); labelContainer .prev("span[data-order][data-key]") .children(".textToggleDisplayButtonLabel") .last() [checked ? "addClass" : "removeClass"]("before-on"); labelContainer .next("span[data-order][data-key]") .children(".textToggleDisplayButtonLabel") .first() [checked ? "addClass" : "removeClass"]("after-on"); if (!fromTriggerHandler) { triggerChangeHandler( self.closest(".textToggleDisplayButtons").find("input").not(target) ); } } ) ); triggerChangeHandler( $(".textToggleDisplayButtonInputReverse").on( "change", ({ target }, fromTriggerHandler = false) => { const { dataset: { id, radioCancel }, checked, } = target; const isRadioCancel = (radioCancel || "").length > 0; const self = $(target); const label = self.closest(".textToggleDisplayButtonLabel"); if (isRadioCancel) { label[checked ? "addClass" : "removeClass"]("on").attr( "style", cssSanitizer(label.attr(checked ? "data-style-on" : "data-style-off")) ); } else { const textToggleDisplayTarget = $( `.textToggleDisplay[data-id="${id}"]` ); const { config: { toggleClass }, } = datasetParser($(target).closest(".textToggleDisplayButtons")[0]); const toggleClassName = typeof toggleClass === "string" && toggleClass.length > 0 ? toggleClass : "hidden"; if (toggleClassName !== "hidden") { textToggleDisplayTarget.removeClass("hidden"); } textToggleDisplayTarget[checked ? "addClass" : "removeClass"]( toggleClassName )[checked ? "removeClass" : "addClass"]("textToggleDisplay-on"); textToggleDisplayTarget .prev(".textToggleDisplay") [checked ? "removeClass" : "addClass"]("textToggleDisplay-before-on"); textToggleDisplayTarget .next(".textToggleDisplay") [checked ? "removeClass" : "addClass"]("textToggleDisplay-after-on"); const span = label.children("span"); label[checked ? "removeClass" : "addClass"]("on").attr( "style", cssSanitizer(label.attr(checked ? "data-style-off" : "data-style-on")) ); if (checked) { span.removeAttr(".on"); } else { span.attr("style", cssSanitizer(textToggleDisplayStyle[id])); } } const labelContainer = label.closest("span[data-order][data-key]"); labelContainer .prev("span[data-order][data-key]") .children(".textToggleDisplayButtonLabel") .last() [checked ? "addClass" : "removeClass"]("before-on"); labelContainer .next("span[data-order][data-key]") .children(".textToggleDisplayButtonLabel") .first() [checked ? "addClass" : "removeClass"]("after-on"); if (!fromTriggerHandler) { triggerChangeHandler( self.closest(".textToggleDisplayButtons").find("input").not(target) ); } } ) ); $(window).on("beforeunload", () => { $(".textToggleDisplayButtons input[type=checkbox]").prop("checked", false); }); ///////结束////////