MediaWiki:Common.js:修订间差异

来自SS唯基
跳到导航 跳到搜索
无编辑摘要
无编辑摘要
第110行: 第110行:


/////// Toggle Content
/////// Toggle Content
if(true) {
function cssSanitizer(cssStr) {
    const cssSanitizer = (cssStr) => {
  let result = "";
         let result = "";
  if (typeof cssStr === "string") {
         if (typeof cssStr === "string") {
    result = cssStr;
             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`] = "";
          }
         }
         }
        result = result.replace(RegExp(decodeURIComponent("%3C!--"), "g"), "");
      }
        result = result.replace(RegExp(decodeURIComponent("-%3E"), "g"), "");
    });
        result = result.replace(/\/\//g, "");
  return result;
        result = result.replace(/url/g, "");
}
        result = result.replace(/&/g, "");
function getEntries(obj) {
        result = result.replace(/pointer-event/g, ";");
  return Object.entries(obj).filter(
        result = result.replace(/display\s*:\s*none\s*!\s*important/g, "display: none");
    ([k, n]) => !/@(?:on|off|input)$/.test(k) && !/['"<>\\/]/.test(n)
        return result;
  );
    }
}
    const uuidv4 = () => {
function triggerChangeHandler($ele) {
        let result = "";
  $ele.each((_, ele) => {
        while (result === "" || $(`#${result}, [name="${result}"]`).length > 0) {
    $(ele).triggerHandler("change", [true]);
            result = ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c =>
  });
                (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
}
            );
const textToggleDisplayStyle = {};
        }
$(".textToggleDisplayStyle").each((_, ele) => {
        return result;
  const dataset = datasetParser(ele).data;
    };
  getEntries(dataset).forEach(([id, style]) => {
    const datasetParser = (ele) => {
    textToggleDisplayStyle[id] = style;
        const result = {
  });
            config: {},
});
            data: {},
$(".textToggleDisplay")
        };
  .each((_, ele) => {
        Object.entries(ele.dataset).filter(([n, m]) => n.startsWith("key-") && !/['"<>\\/]/.test(m)).forEach(([__key, _key]) => {
    if (ele.dataset.id in textToggleDisplayStyle) {
            const value = ele.dataset[`value-${__key.substring(4)}`];
      $(ele).attr(
            if (_key.length > 0 && value.length > 0) {
        "style",
                const isConfig = _key.startsWith("@");
        cssSanitizer(textToggleDisplayStyle[ele.dataset.id])
                const key = isConfig ? _key.substring(1) : _key;
      );
                const base = result[isConfig ? "config" : "data"];
    }
                base[key] = value;
  })
                if (/@o(?:n|ff)$/.test(_key)) {
  .addClass("hidden");
                    const id = _key.replace(/@o(?:n|ff)$/, "");
$(".textToggleDisplayButtons").each((_, ele) => {
                    if (!(id in base)) {
  const self = $(ele);
                        base[id] = value;
  const parsedDataset = datasetParser(ele);
                    }
  const ifRadio =
                } else if (_key.endsWith("@input")) {
    "radio" in parsedDataset.config && parsedDataset.config.radio.length > 0;
                    base[_key] = value;
  const ifForceNoCancel =
                    const id = _key.replace(/@input$/, "");
    "forceNoCancel" in parsedDataset.config &&
                    if (!(id in base)) {
    parsedDataset.config.forceNoCancel.length > 0;
                        base[id] = "";
  const ifReverse =
                    }
    "reverse" in parsedDataset.config &&
                } else {
    parsedDataset.config.reverse.length > 0;
                    if (!(`${key}@on` in base)) {
  const name = uuidv4();
                        base[`${key}@on`] = value;
  let hasDefault = false;
                    }
  self.children("span[data-key]").each((_, e) => {
                    if (!(`${key}@off` in base)) {
    if (/['"<>\\/]/.test(e.dataset.key)) {
                        base[`${key}@off`] = value;
      e.remove();
                    }
      return;
                    if (!(`${key}@input` in base)) {
    }
                        base[`${key}@input`] = "";
    const $e = $(e);
                    }
    const input = $("<input/>");
                }
    input
            }
      .attr({
        });
        "data-id": e.dataset.key,
        return result;
        type: ifRadio ? "radio" : "checkbox",
    };
      })
    const getEntries = (obj) => Object.entries(obj).filter(([k, n]) => !/@(?:on|off|input)$/.test(k) && !/['"<>\\/]/.test(n));
      .addClass(
    const triggerChangeHandler = ($ele) => {
        ifReverse
        $ele.each((_, ele) => {
          ? "textToggleDisplayButtonInputReverse"
            $(ele).triggerHandler("change", [true]);
          : "textToggleDisplayButtonInput"
        });
      );
    };
    if (ifRadio) {
    const textToggleDisplayStyle = {};
      input.attr("name", name);
    $(".textToggleDisplayStyle").each((_, ele) => {
    }
        const dataset = datasetParser(ele).data;
    const label = $("<label/>");
        getEntries(dataset).forEach(([id, style]) => {
    $e.children().appendTo(label);
            textToggleDisplayStyle[id] = style;
    label
        });
      .prepend(input)
    });
      .appendTo(e)
    $(".textToggleDisplay").each((_, ele) => {
      .attr("data-id", e.dataset.key)
        if (ele.dataset.id in textToggleDisplayStyle) {
      .addClass("textToggleDisplayButtonLabel");
            $(ele).attr("style", cssSanitizer(textToggleDisplayStyle[ele.dataset.id]));
    $e.find("*").each((_, e) => {
        }
      e.addEventListener(
    }).addClass("hidden");
        "click",
    $(".textToggleDisplayButtons").each((_, ele) => {
        (evt) => {
        const self = $(ele);
          evt.stopImmediatePropagation();
        const parsedDataset = datasetParser(ele);
          evt.stopPropagation();
        const ifRadio = "radio" in parsedDataset.config && parsedDataset.config.radio.length > 0;
          if (!$(evt.target).is(input)) {
        const ifForceNoCancel = "forceNoCancel" in parsedDataset.config && parsedDataset.config.forceNoCancel.length > 0;
            evt.preventDefault();
        const ifReverse = "reverse" in parsedDataset.config && parsedDataset.config.reverse.length > 0;
            if (ifRadio ? !input.prop("checked") : true) {
        const name = uuidv4();
              input.prop("checked", !input.prop("checked")).trigger("change");
        let hasDefault = false;
            }
        self.children("span[data-key]").each((_, e) => {
          }
            if (/['"<>\\/]/.test(e.dataset.key)) {
        },
                e.remove();
        {
                return;
          capture: true,
            }
        }
            const $e = $(e);
      );
            const input = $("<input/>");
    });
            input.attr({
    if (e.dataset.key === parsedDataset.config.default) {
                "data-id": e.dataset.key,
      input.prop("checked", true);
                type: ifRadio ? "radio" : "checkbox",
      hasDefault = true;
            }).addClass(ifReverse ? "textToggleDisplayButtonInputReverse" : "textToggleDisplayButtonInput");
    }
            if (ifRadio) {
  });
                input.attr("name", name);
  if (ifRadio && (!hasDefault || !ifForceNoCancel)) {
            }
    const input = $("<input/>");
            const label = $("<label/>");
    const inputId = uuidv4();
            $e.children().appendTo(label);
    input
            label.prepend(input).appendTo(e).attr("data-id", e.dataset.key).addClass("textToggleDisplayButtonLabel");
      .attr({
            $e.find("*").each((_, e) => {
        "data-id": "",
                e.addEventListener("click", (evt) => {
        "data-radio-cancel": "true",
                    evt.stopImmediatePropagation();
        id: inputId,
                    evt.stopPropagation();
        name,
                    if (!$(evt.target).is(input)) {
        type: "radio",
                        evt.preventDefault();
      })
                        if (ifRadio ? !input.prop("checked") : true) {
      .addClass(
                            input.prop("checked", !input.prop("checked")).trigger("change");
        ifReverse
                        }
          ? "textToggleDisplayButtonInputReverse"
                    }
          : "textToggleDisplayButtonInput"
                }, {
      )
                    capture: true,
      .css({
                });
        "margin-left": "0",
            });
        "margin-right": "0",
            if (e.dataset.key === parsedDataset.config.default) {
        width: "0",
                input.prop("checked", true);
      });
                hasDefault = true;
    const label = $("<label/>");
            }
    const span = $("<span/>");
        });
    span.text("取消选择");
        if (ifRadio && (!hasDefault || !ifForceNoCancel)) {
    label
            const input = $("<input/>");
      .attr({
            const inputId = uuidv4();
        "data-id": "",
            input.attr({
        for: inputId,
                "data-id": "",
      })
                "data-radio-cancel": "true",
      .addClass("textToggleDisplayButtonLabel cancelButton");
                id: inputId,
    self.append(label.append(input).append(span));
                name,
    if (!hasDefault) {
                type: "radio",
      input.prop("checked", true);
            }).addClass(ifReverse ? "textToggleDisplayButtonInputReverse" : "textToggleDisplayButtonInput").css({
    }
                "margin-left": "0",
  }
                "margin-right": "0",
});
                width: "0",
$(".textToggleDisplayButtonsStyle").each((_, ele) => {
            });
  const parsedDataset = datasetParser(ele);
            const label = $("<label/>");
  $(".textToggleDisplayButtonLabel.cancelButton").attr({
            const span = $("<span/>");
    "data-style-off": parsedDataset.config["cancel@off"] || "",
            span.text("取消选择");
    "data-style-on": parsedDataset.config["cancel@on"] || "",
            label.attr({
  });
                "data-id": "",
  $(".textToggleDisplayButtonLabel.cancelButton > input").attr(
                "for": inputId,
    "style",
            }).addClass("textToggleDisplayButtonLabel cancelButton");
    cssSanitizer(parsedDataset.config["cancel@input"])
            self.append(label.append(input).append(span));
  );
            if (!hasDefault) {
  getEntries(parsedDataset.data).forEach(([id]) => {
                input.prop("checked", true);
    $(`.textToggleDisplayButtonLabel[data-id="${id}"]`)
            }
      .attr({
        }
        "data-style-off": parsedDataset.data[`${id}@off`] || "",
    });
        "data-style-on": parsedDataset.data[`${id}@on`] || "",
    $(".textToggleDisplayButtonsStyle").each((_, ele) => {
      })
        const parsedDataset = datasetParser(ele);
      .children("input")
        $(".textToggleDisplayButtonLabel.cancelButton").attr({
      .attr("style", cssSanitizer(parsedDataset.data[`${id}@input`]));
            "data-style-off": parsedDataset.config["cancel@off"] || "",
  });
            "data-style-on": parsedDataset.config["cancel@on"] || "",
});
        });
triggerChangeHandler(
        $(".textToggleDisplayButtonLabel.cancelButton > input").attr("style", cssSanitizer(parsedDataset.config["cancel@input"]));
  $(".textToggleDisplayButtonInput").on(
        getEntries(parsedDataset.data).forEach(([id]) => {
    "change",
            $(`.textToggleDisplayButtonLabel[data-id="${id}"]`).attr({
    ({ target }, fromTriggerHandler = false) => {
                "data-style-off": parsedDataset.data[`${id}@off`] || "",
      const {
                "data-style-on": parsedDataset.data[`${id}@on`] || "",
        dataset: { id },
            }).children("input").attr("style", cssSanitizer(parsedDataset.data[`${id}@input`]));
        checked,
        });
      } = target;
    });
      const textToggleDisplayTarget = $(`.textToggleDisplay[data-id="${id}"]`);
    triggerChangeHandler($(".textToggleDisplayButtonInput").on("change", ({
      const {
        target,
        config: { toggleClass },
    }, fromTriggerHandler = false) => {
      } = datasetParser($(target).closest(".textToggleDisplayButtons")[0]);
        const {
      const toggleClassName =
            dataset: {
        typeof toggleClass === "string" && toggleClass.length > 0
                id,
          ? toggleClass
            },
          : "hidden";
            checked,
      if (toggleClassName !== "hidden") {
        } = target;
        textToggleDisplayTarget.removeClass("hidden");
        const textToggleDisplayTarget = $(`.textToggleDisplay[data-id="${id}"]`);
      }
        const { config: { toggleClass } } = datasetParser($(target).closest(".textToggleDisplayButtons")[0]);
      textToggleDisplayTarget[checked ? "removeClass" : "addClass"](
        const toggleClassName = typeof toggleClass === "string" && toggleClass.length > 0 ? toggleClass : "hidden";
        toggleClassName
        if (toggleClassName !== "hidden") {
      )[checked ? "addClass" : "removeClass"]("textToggleDisplay-on");
            textToggleDisplayTarget.removeClass("hidden");
      textToggleDisplayTarget
        }
        .prev(".textToggleDisplay")
        textToggleDisplayTarget[checked ? "removeClass" : "addClass"](toggleClassName)[checked ? "addClass" : "removeClass"]("textToggleDisplay-on");
        [checked ? "addClass" : "removeClass"]("textToggleDisplay-before-on");
        textToggleDisplayTarget.prev(".textToggleDisplay")[checked ? "addClass" : "removeClass"]("textToggleDisplay-before-on");
      textToggleDisplayTarget
        textToggleDisplayTarget.next(".textToggleDisplay")[checked ? "addClass" : "removeClass"]("textToggleDisplay-after-on");
        .next(".textToggleDisplay")
        const self = $(target);
        [checked ? "addClass" : "removeClass"]("textToggleDisplay-after-on");
        const label = self.closest(".textToggleDisplayButtonLabel");
      const self = $(target);
        const span = label.children(".on");
      const label = self.closest(".textToggleDisplayButtonLabel");
        label[checked ? "addClass" : "removeClass"]("on").attr("style", cssSanitizer(label.attr(checked ? "data-style-on" : "data-style-off")));
      const span = label.children(".on");
        if (checked) {
      label[checked ? "addClass" : "removeClass"]("on").attr(
            span.attr("style", cssSanitizer(textToggleDisplayStyle[id]));
        "style",
        } else {
        cssSanitizer(label.attr(checked ? "data-style-on" : "data-style-off"))
            span.removeAttr("style");
      );
        }
      if (checked) {
        const labelContainer = label.closest("span[data-order][data-key]");
        span.attr("style", cssSanitizer(textToggleDisplayStyle[id]));
        labelContainer.prev("span[data-order][data-key]").children(".textToggleDisplayButtonLabel").last()[checked ? "addClass" : "removeClass"]("before-on");
      } else {
        labelContainer.next("span[data-order][data-key]").children(".textToggleDisplayButtonLabel").first()[checked ? "addClass" : "removeClass"]("after-on");
        span.removeAttr("style");
        if (!fromTriggerHandler) {
      }
            triggerChangeHandler(self.closest(".textToggleDisplayButtons").find("input").not(target));
      const labelContainer = label.closest("span[data-order][data-key]");
        }
      labelContainer
    }));
        .prev("span[data-order][data-key]")
    triggerChangeHandler($(".textToggleDisplayButtonInputReverse").on("change", ({
        .children(".textToggleDisplayButtonLabel")
        target,
        .last()
    }, fromTriggerHandler = false) => {
        [checked ? "addClass" : "removeClass"]("before-on");
        const {
      labelContainer
            dataset: {
        .next("span[data-order][data-key]")
                id,
        .children(".textToggleDisplayButtonLabel")
                radioCancel,
        .first()
            },
        [checked ? "addClass" : "removeClass"]("after-on");
            checked,
      if (!fromTriggerHandler) {
        } = target;
        triggerChangeHandler(
        const isRadioCancel = (radioCancel || "").length > 0;
          self.closest(".textToggleDisplayButtons").find("input").not(target)
        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}"]`);
triggerChangeHandler(
            const { config: { toggleClass } } = datasetParser($(target).closest(".textToggleDisplayButtons")[0]);
  $(".textToggleDisplayButtonInputReverse").on(
            const toggleClassName = typeof toggleClass === "string" && toggleClass.length > 0 ? toggleClass : "hidden";
    "change",
            if (toggleClassName !== "hidden") {
    ({ target }, fromTriggerHandler = false) => {
                textToggleDisplayTarget.removeClass("hidden");
      const {
            }
        dataset: { id, radioCancel },
            textToggleDisplayTarget[checked ? "addClass" : "removeClass"](toggleClassName)[checked ? "removeClass" : "addClass"]("textToggleDisplay-on");
        checked,
            textToggleDisplayTarget.prev(".textToggleDisplay")[checked ? "removeClass" : "addClass"]("textToggleDisplay-before-on");
      } = target;
            textToggleDisplayTarget.next(".textToggleDisplay")[checked ? "removeClass" : "addClass"]("textToggleDisplay-after-on");
      const isRadioCancel = (radioCancel || "").length > 0;
            const span = label.children("span");
      const self = $(target);
            label[checked ? "removeClass" : "addClass"]("on").attr("style", cssSanitizer(label.attr(checked ? "data-style-off" : "data-style-on")));
      const label = self.closest(".textToggleDisplayButtonLabel");
            if (checked) {
      if (isRadioCancel) {
                span.removeAttr(".on");
        label[checked ? "addClass" : "removeClass"]("on").attr(
            } else {
          "style",
                span.attr("style", cssSanitizer(textToggleDisplayStyle[id]));
          cssSanitizer(label.attr(checked ? "data-style-on" : "data-style-off"))
            }
        );
        }
      } else {
        const labelContainer = label.closest("span[data-order][data-key]");
        const textToggleDisplayTarget = $(
        labelContainer.prev("span[data-order][data-key]").children(".textToggleDisplayButtonLabel").last()[checked ? "addClass" : "removeClass"]("before-on");
          `.textToggleDisplay[data-id="${id}"]`
        labelContainer.next("span[data-order][data-key]").children(".textToggleDisplayButtonLabel").first()[checked ? "addClass" : "removeClass"]("after-on");
        );
        if (!fromTriggerHandler) {
        const {
            triggerChangeHandler(self.closest(".textToggleDisplayButtons").find("input").not(target));
          config: { toggleClass },
        }
        } = datasetParser($(target).closest(".textToggleDisplayButtons")[0]);
    }));
        const toggleClassName =
    $(window).on("beforeunload", () => {
          typeof toggleClass === "string" && toggleClass.length > 0
        $(".textToggleDisplayButtons input[type=checkbox]").prop("checked", false);
            ? 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);
});
///////结束////////