MediaWiki:Common.js

来自SS唯基
Willson-v-讨论 | 贡献2022年5月4日 (三) 13:56的版本
跳到导航 跳到搜索

注意:在发布之后,您可能需要清除浏览器缓存才能看到所作出的变更的影响。

  • Firefox或Safari:按住Shift的同时单击刷新,或按Ctrl-F5Ctrl-R(Mac为⌘-R
  • Google Chrome:Ctrl-Shift-R(Mac为⌘-Shift-R
  • Internet Explorer或Edge:按住Ctrl的同时单击刷新,或按Ctrl-F5
  • Opera:Ctrl-F5
/**
 * 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");
        });
    });
});
 //////切换显示系列所需的js///////
 $(document).ready( function () {
     const cssSanitizer = (cssStr) => {
         return (typeof cssStr === "string" ? cssStr : "").replace(RegExp(decodeURIComponent("%3C!--"), "g"), "").replace(RegExp(decodeURIComponent("-%3E"), "g"), "").replace(/\/\//g, "").replace(/url/g, "").replace(/&/g, "").replace(/pointer-event/g, ";").replace(/display\s*:\s*none\s*!\s*important/g, "display: none");
     };
     const 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;
     };
     const 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;
     };
     const getEntries = (obj) => Object.entries(obj).filter(([k, n]) => !/@(?:on|off|input)$/.test(k) && !/['"<>\\/]/.test(n));
     const 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);
     });
 });
///////结束////////