点击此处会biu~的随机导向一个高级条目哦 ><
|
H萌娘上月访问数据报告
查看“MediaWiki:AxUserMsg.js”的源代码
←
MediaWiki:AxUserMsg.js
跳到导航
跳到搜索
因为以下原因,您没有权限编辑本页:
此页面为本wiki上的软件提供界面文本,并受到保护以防止滥用。 如欲修改所有wiki的翻译,请访问
translatewiki.net
上的MediaWiki本地化项目。
您无权编辑此JavaScript页面,因为编辑此页面可能会影响所有访问者。
您可以查看和复制此页面的源代码。
//<nowiki> /** * https://commons.wikimedia.org/w/index.php?oldid=553484026 */ "use strict"; (async () => { if (window.AxUserMsg || !mw.config.get("wgUserGroups").includes("patroller") && !mw.config.get("wgUserGroups").includes("sysop")) { return; } class ClsUPC { constructor($userInputField, $outputField, stCallBack, callingObject, CBValidChange) { this.$userInputField = $userInputField; this.$outputField = $outputField; this.callingObject = callingObject; this.stCallBack = stCallBack; this.CBValidChange = CBValidChange; this.pendingCalls = 0; this.pendingSetTimeouts = 0; this.oldValue = ""; this.userNameExists = 2; const o = this; $userInputField.on("keyup", ( /* e*/) => { const tmpUNE = o.userNameExists; if (o.isValidIP($userInputField.val())) { o.setToIP(tmpUNE); } else { o.execApiCall(false, $userInputField.val()); } }); $userInputField.on("input", () => { $userInputField.keyup(); }); $userInputField.on("selected", () => { $userInputField.keyup(); }); } isValidIP(username) { if (mw.util.isIPv4Address(username)) { return true; } //IP v.4 return mw.util.isIPv6Address(username); //IP v.6 } setToIP(tmpUNE) { const o = this; o.userNameExists = -1; if ("function" === typeof o.CBValidChange && tmpUNE !== o.userNameExists) { o.$outputField.attr("src", o.callingObject.umImgUserIsIP); o.$outputField.attr("alt", "IP"); o.oldValue = o.callingObject.umCleanFileAndUser(o.$userInputField.val()); o.CBValidChange(o, o.callingObject); } } execApiCall(isTimeout, val) { if (isTimeout) { this.pendingSetTimeouts--; } if (this.oldValue !== this.callingObject.umCleanFileAndUser(val)) { if (this.pendingCalls > 0) { if (!this.pendingSetTimeouts) { this.pendingSetTimeouts++; const o = this; setTimeout(() => { o.execApiCall(true, o.$userInputField.val()); }, 1000); // do not use the old value, use the current instead } return; } const User = this.oldValue = this.callingObject.umCleanFileAndUser(val); const query = { action: "query", list: "allusers", aufrom: User, auto: User, }; this.callingObject.umCurrentUserQuery = this; this.pendingCalls++; this.callingObject.doAPICall(query, this.stCallBack); } } evalAPICall(result) { this.pendingCalls--; const uifval = this.$userInputField.val(); if (this.oldValue !== this.callingObject.umCleanFileAndUser(uifval)) { // Don't do anything if user updated the field in-between return; } if (this.isValidIP(uifval)) { return; } if ("object" === typeof result.query && "object" === typeof result.query.allusers) { const tmpUNE = this.userNameExists; if (!result.query.allusers.length) { this.$outputField.attr("src", this.callingObject.umImgUserNotExists); this.$outputField.attr("alt", "!! invalid !!"); this.userNameExists = false; } else { if (this.callingObject.umCleanFileAndUser(this.$userInputField.val()) === result.query.allusers[0].name) { this.$outputField.attr("src", this.callingObject.umImgUserExists); this.$outputField.attr("alt", "OK"); this.userNameExists = true; } else { if (!this.pendingSetTimeouts) { // Only overwrite if there is nothing pending this.$outputField.attr("src", this.callingObject.umImgUserUndefined); this.$outputField.attr("alt", "?"); this.userNameExists = 2; } } } if ("function" === typeof this.CBValidChange && tmpUNE !== this.userNameExists) { this.CBValidChange(this, this.callingObject); } } } } const umsg = window.AxUserMsg = { umInstall: () => { if ($("#t-AjaxUserMessage").length === 0) { const $LODLinkNode = $("#t-AjaxUserMessageLOD"); const $Href = $LODLinkNode.length ? $LODLinkNode.eq(0) : $(mw.util.addPortletLink("p-tb", "#", "警告用户", "t-AjaxUserMessage", "加载 UserMessages 小工具")); $Href.on("click", (e) => { e.preventDefault(); umsg.fireImmediately = false; umsg.umNotifyUser(); }); } }, umInstallOldLinks: () => { // written for Herby, who needs this for working on Commons umsg.umTemplate.forEach((ti, id) => { // Create portlet link const portletLink = mw.util.addPortletLink("p-tb", `#${id}`, ti[1], `t-gadgetUserMessage${id}`, ti[2]); // Bind click handler $(portletLink).on("click", (e) => { e.preventDefault(); window.AxUserMsgPreSelect = $(portletLink).find("a").attr("href").split("#")[1]; if (window.AxUserMsgFireAsYouClick) { const umType = umsg.umTemplate[umsg.umSelect][3]; if (!(umType & umsg.umFlagUQ) && !(umType & umsg.umFlagReq)) { umsg.fireImmediately = true; } else { umsg.fireImmediately = false; } } umsg.umNotifyUser(); }); }); }, umNotifyUser: () => { // mw.util.addCSS('a.new{color:#B00 !important;}'); ?? umsg.umUser = ""; umsg.editToken = ""; umsg.umDlgPresent = false; umsg.umExecuting = false; umsg.umPendingParser = 0; umsg.umPendingParserTimeouts = 0; umsg.umParserTimerID = 0; umsg.umDelay = window.AxUserMsgDelay || 100; umsg.umUserCache = {}; umsg.umFileCache = {}; umsg.umParserCache = {}; umsg.focusOwner = ""; umsg.umObtainEditToken(); umsg.umUser = mw.libs.commons.guessUser(); umsg.umDlg(); }, umFillSelect: (caller, o) => { const userstate = caller.userNameExists; o.umTemplate.forEach((currentTag, id) => { if ($(`#umOpt${id}`, o.$tagSelect).length === 0) { // check wether to add if (-1 === userstate && !(currentTag[3] & o.umFlagUM) || true === userstate && !(currentTag[3] & o.umFlagIP)) { o.$tagSelect.append(`<option id="umOpt${id}" value="${id}">${mw.html.escape(`${currentTag[1]} - ${currentTag[2]}`)}</option>`); return; } } else { // check wether to remove if (-1 === userstate && currentTag[3] & o.umFlagUM || true === userstate && currentTag[3] & o.umFlagIP) { $(`#umOpt${id}`, o.$tagSelect).remove(); return; } } }); if (-1 === userstate) { if (window.AxUserMsgPreSelectIP) { o.$tagSelect.val(window.AxUserMsgPreSelectIP); } } else { o.$tagSelect.val(umsg.umSelect); } o.umValidateInput(o); o.$tagSelect.change(); }, umDlg: () => { const $win = $(window); umsg.dlg = $("<div>").html('<div id="AjaxUmContainer"></div>').dialog({ modal: true, closeOnEscape: true, position: [Math.round(($win.width() - Math.min($win.width(), 850)) / 2), Math.round(($win.height() - Math.min($win.height(), 800)) / 2)], title: '警告用户 - <span class="mw-parser-output"><a href="//commons.wikimedia.org/wiki/MediaWiki_talk:Gadget-UserMessages.js" target="_blank" rel="nofollow noreferrer noopener" class="external text">去维基共享报告错误和建议</a> | <a href="https://zh.moegirl.org.cn/Help:UserMessages%E5%B0%8F%E5%B7%A5%E5%85%B7" target="_blank" class="external text">使用帮助</a></span>', height: Math.min($win.height(), 800), width: Math.min($win.width(), 850), buttons: { [umsg.i18n.submitButtonLabel]: () => { try { if (umsg.umIsValid) { umsg.umNotifyUserExecute(); } } catch (ex) { umsg.fail(ex); } }, [umsg.i18n.cancelButtonLabel]: function () { $(this).dialog("close"); console.info("[this.i18n.cancelButtonLabel]", this, umsg.dlg); }, }, close: function () { console.info("close", this, umsg.dlg); $(this).dialog("destroy"); $(this).remove(); umsg.umDlgPresent = false; }, open: function () { const $dlg = $(this); // 不可去除 $dlg.parents(".ui-dialog").css({ position: "fixed", top: `${Math.round(($win.height() - Math.min($win.height(), 800)) / 2)}px`, }); }, }); umsg.umDlgPresent = true; if (umsg.dlg) { const $AjaxUmContainer = $("#AjaxUmContainer"); $AjaxUmContainer.append(`<label for="umUser">${mw.html.escape(umsg.i18n.umFillInUser)}</label><br><input type="text" id="umUser" style="width: 95%;" value="${mw.html.escape(umsg.umUser)}"/>${umsg.umInitImgUserExists.replace("%ID%", "umUserExists")}<br><br>`); umsg.$tagSelect = $("<select>", { size: "1", id: "umTagToInsert", style: "width: 99%;", }); $AjaxUmContainer.append([ `<label for="umTagToInsert">${mw.html.escape(umsg.i18n.umSelectTag)}</label><br>`, umsg.$tagSelect, "<br><br>", `<span id="umMediaWrapper"><label for="umMedia">${mw.html.escape(umsg.i18n.umFillInMedia)}</label><br><input type="text" id="umMedia" style="width: 95%;" value="File:"/><br><br></span>`, `<span id="umP2Wrapper"><label for="umP2">${mw.html.escape(umsg.i18n.umFillInAdditional)}</label><br><input type="text" id="umP2" style="width: 95%;"/><br><br></span>`, `<span id="umP3Wrapper"><label for="umP3">${mw.html.escape(umsg.i18n.umFillInAdditional)}</label><br><input type="text" id="umP3" style="width: 95%;"/><br><br></span>`, `<span id="umRelatedUserWrapper"><label for="umRelatedUser">${mw.html.escape(umsg.i18n.umFillInRelUser)}</label><br><input type="text" id="umRelatedUser" style="width: 95%;" value="User:"/>${umsg.umInitImgUserExists.replace("%ID%", "umRelatedUserExists")}<br><br></span>`, `<span id="umSummaryWrapper"><label for="umSummary">${mw.html.escape(umsg.i18n.umFillInSummary)}</label><br><input type="text" id="umSummary" style="width: 95%;" value="摘要"/><br><br></span>`, `<label for="umAddText">${mw.html.escape(umsg.i18n.umAddText)}</label><br><textarea id="umAddText" style="width: 95%; height: 5em;">${mw.html.escape(window.AxUserMsgCustomText || "")}</textarea><br><br>`, ]); umsg.talkTag = ""; const $umMedia = $("#umMedia"), $umP2 = $("#umP2"), $umP3 = $("#umP3"), $umUser = $("#umUser"), $umRelatedUser = $("#umRelatedUser"), $umSummary = $("#umSummary"), $umAddText = $("#umAddText"); umsg.uUPC = new ClsUPC($umUser, $("#umUserExists"), "umUserExistsCB", umsg, umsg.umFillSelect); umsg.ouUPC = new ClsUPC($umRelatedUser, $("#umRelatedUserExists"), "umUserExistsCB", umsg, umsg.umUserValidChange); const submitButton = $(".ui-dialog-buttonpane button:first"); // guessing the related file thanks User:Platonides const guessFile = () => { let f = mw.util.getParamValue("title", document.referrer); if (f && /File:/.test(f)) { return f; } f = mw.util.getParamValue("page", document.referrer); if (f && /File:/.test(f)) { return f; } f = mw.util.getParamValue("target", document.referrer); if (f && /File:/.test(f)) { return f; } const m = document.referrer.match(/File:(.+)/); try { if (m) { if (/&.+=/.test(m[1])) { return `File:${decodeURI(m[1]).match(/^(.+)&/)[1]}`; } return `File:${m[1]}`; } } catch { } }; const umFile = guessFile(); if (umFile) { $umMedia.val(decodeURIComponent(umFile).replace(/_/g, " ")); } $umUser.on("keyup", (event) => { $umUser.val($umUser.val().replace(/<|>|\^/g, "")); }); $umUser.autocomplete({ minLength: 1, source: (request, callback) => { umsg.umSeekUsers(request, callback); }, close: () => { $umUser.triggerHandler("selected"); }, }); $umMedia.on("change", () => { umsg.umValidateInput(umsg); }); $umMedia.on("input", () => { $umMedia.val($umMedia.val().replace(/<|>|\^/g, "")); umsg.umValidateInput(umsg); }); $umMedia.on("keyup", (e) => { $umMedia.val($umMedia.val().replace(/<|>|\^/g, "")); }); $umMedia.autocomplete({ minLength: 1, source: (request, callback) => { umsg.umSeekFiles(request, callback); }, close: () => { $umMedia.triggerHandler("input"); }, }); $umRelatedUser.on("keyup", (event) => { $umRelatedUser.val($umRelatedUser.val().replace(/<|>|\^/g, "")); umsg.umValidateInput(umsg); }); $umRelatedUser.autocomplete({ minLength: 1, source: (request, callback) => { umsg.umSeekUsers(request, callback); }, close: () => { $umRelatedUser.triggerHandler("selected"); }, }); $umP2.on("change", () => { umsg.umValidateInput(umsg); }); $umP2.on("input", () => { umsg.umValidateInput(umsg); }); $umP3.on("change", () => { umsg.umValidateInput(umsg); }); $umP3.on("input", () => { umsg.umValidateInput(umsg); }); $umAddText.on("change", () => { umsg.umValidateInput(umsg); }); $umAddText.on("input", () => { umsg.umValidateInput(umsg); }); submitButton.focus(); $AjaxUmContainer.append(umsg.umInstPrevContainer.clone().text("即时预览为空")); umsg.$tagSelect.on("change", () => { const umType = umsg.umTemplate[$(umsg.$tagSelect).val()][3]; $umSummary.val(umsg.umTemplate[$("#umTagToInsert").val()][4] ? umsg.umTemplate[$("#umTagToInsert").val()][4] : `${umsg.umTemplate[$("#umTagToInsert").val()][2]}.`); umsg.umValidateInput(umsg); umsg.$tagSelect.combobox({ displaytext: umsg.$tagSelect.val() ? umsg.$tagSelect.children(":selected").text() : "", }); if (umType & umsg.umFlagP2) { $("#umP2Wrapper").show(); if (document.activeElement && $umUser.attr("id") !== document.activeElement.id) { $("#umP2").select(); } } else { $("#umP2Wrapper").hide(); } if (umType & umsg.umFlagP3) { $("#umP3Wrapper").show(); if (document.activeElement && $umUser.attr("id") !== document.activeElement.id) { $("#umP3").select(); } } else { $("#umP3Wrapper").hide(); } if (umType & umsg.umFlagMQ) { $("#umMediaWrapper").show(); if (document.activeElement && $umUser.attr("id") !== document.activeElement.id) { $("#umMedia").select(); } } else { $("#umMediaWrapper").hide(); } if (umType & umsg.umFlagUQ) { $("#umRelatedUserWrapper").show(); if (document.activeElement && $umUser.attr("id") !== document.activeElement.id) { $("#umMedia").select(); } } else { $("#umRelatedUserWrapper").hide(); } }); umsg.$tagSelect.val(umsg.umSelect); $("#umUser").keyup(); $("#umTagToInsert").combobox(); } }, umSeekUsers: (request, pCallback) => { const query = { action: "query", list: "allusers", auprefix: request.term.replace(/^(?:User):/, ""), }; umsg.doGetApiCall(query, "umSeekUsersCB", pCallback); }, umSeekUsersCB: (result, pCallback) => { const searchTerms = []; result.forEach((usi) => { searchTerms.push({ id: usi.userid, value: usi.name, }); }); if ("function" === typeof pCallback) { pCallback(searchTerms); } }, umSeekFiles: (request, pCallback) => { const query = { action: "query", list: "allimages", aiprefix: request.term.replace(/^(?:File|Image):/, ""), }; umsg.doGetApiCall(query, "umSeekFilesCB", pCallback); }, umSeekFilesCB: (result, pCallback) => { const searchTerms = []; result.forEach((fii) => { searchTerms.push({ id: fii.timestamp, value: `File:${fii.name}`, }); }); if ("function" === typeof pCallback) { pCallback(searchTerms); } }, umUserExistsCB: (result) => { umsg.umCurrentUserQuery.evalAPICall(result); }, umShowInfo: (info, o) => { $("#umInstantPreviewContainer").empty().html(`<p class="center"><img src="${o.umImgInfo}" width="64" height="64"/><br>${info}</p>`); }, umValidateInput: (o) => { umsg.umIsValid = true; const umType = umsg.umTemplate[$("#umTagToInsert").val()][3]; const submitButton = $(".ui-dialog-buttonpane button:first"); const validRelatedUser = () => { if (umType & o.umFlagUQ) { if (o.umCleanFileAndUser($("#umRelatedUser").val()).length < 1) { o.umShowInfo("未指定相关用户", o); return false; } if (!o.ouUPC.userNameExists) { o.umShowInfo("所指定的相关用户不存在", o); return false; } } return true; }; const validMedia = () => { if (umType & o.umFlagMQ) { if (o.umCleanFileAndUser($("#umMedia").val()).length < 5 && umType & o.umFlagReq) { o.umShowInfo("未指定文件,且强制检查已开启", o); return false; } } return true; }; const validUser = () => { if (o.umCleanFileAndUser($("#umUser").val()).length < 1) { o.umShowInfo("未指定用户", o); return false; } if (!o.uUPC.userNameExists) { o.umShowInfo("所指定的用户不存在", o); return false; } return true; }; umsg.umIsValid = umsg.umIsValid && validRelatedUser() && validMedia() && validUser(); if (umsg.umIsValid) { submitButton.removeClass("ui-state-disabled"); if (umType & umsg.umFlagMQ) { umsg.talkTag = `\n{{${umsg.umTemplate[$("#umTagToInsert").val()][0]}${umsg.umCleanFileAndUser($("#umMedia").val()) ? `|1=${umType & umsg.umFlagNS ? `File:${umsg.umCleanFileAndUser($("#umMedia").val())}` : $("#umMedia").val()}` : ""}`; } else if (umType & umsg.umFlagUQ) { umsg.talkTag = `\n{{${umsg.umTemplate[$("#umTagToInsert").val()][0]}|1=${umsg.umCleanFileAndUser($("#umRelatedUser").val())}`; } else { umsg.talkTag = `\n{{${umsg.umTemplate[$("#umTagToInsert").val()][0]}`; } let paramCount = (umType & umsg.umFlagUQ ? 1 : 0) + (umType & umsg.umFlagMQ ? 1 : 0); // cut of extra white space const sigText = "——~~~~"; if (umType & umsg.umFlagP2) { paramCount++; umsg.talkTag += `|${paramCount}=${$("#umP2").val()}`; } if (umType & umsg.umFlagP3) { paramCount++; umsg.talkTag += `|${paramCount}=${$("#umP3").val()}`; } umsg.talkTag += "}}"; if ("\n{{}}" === umsg.talkTag) { umsg.talkTag = "\n"; } umsg.talkTag += `\n${$("#umAddText").val().replace(/~{3,5}$/, "")}${sigText}\n`; umsg.umParseTemplate(false); // If the user wants the old behaviour back, we fire immediately if (umsg.fireImmediately) { umsg.umNotifyUserExecute(); } } else { submitButton.addClass("ui-state-disabled"); } }, umUserValidChange: (_, o) => { o.umValidateInput(o); }, umCleanFileAndUser: (input) => { let output = ""; if (input) { output = input.replace(/_/g, " ").replace(/File:/g, "").replace(/Image:/g, "").replace(/User:/g, "").replace(/^\s+|\s+$/g, ""); output = output.substring(0, 1).toUpperCase() + output.substring(1); } return output; }, umParseTemplate: (viaSetTimeout) => { if (window.AxUserMsgNoParse) { return; } if (viaSetTimeout) { umsg.umPendingParserTimeouts--; } if (umsg.umPendingParser > 0) { if (!umsg.umPendingParserTimeouts) { // call me later const o = umsg; umsg.umPendingParserTimeouts++; setTimeout(() => { o.umParseTemplate(true); }, 300); } return; } const maybeParse = () => { umsg.umPendingParser++; const action = { action: "parse", uselang: mw.config.get("wgUserLanguage"), redirects: true, prop: "text", pst: true, title: umsg.umUserTalkPrefix + $("#umUser").val(), text: umsg.talkTag, }; umsg.umDelay = Math.min(umsg.umDelay + 30, 1500); // Save server resources. umsg.doAPICall(action, "umParsedTemplate"); }; if (umsg.umParserTimerID) { clearTimeout(umsg.umParserTimerID); } umsg.umParserTimerID = setTimeout(maybeParse, umsg.umDelay); }, umParsedTemplate: (result) => { umsg.umPendingParser--; if ("object" === typeof result.parse && "object" === typeof result.parse.text && umsg.umDlgPresent && !umsg.umExecuting && umsg.umIsValid) { let $containerText = result.parse.text["*"].replace(" API", ` ${umsg.umCleanFileAndUser($("#umUser").val())}`).replace(">API", `>${umsg.umCleanFileAndUser($("#umUser").val())}`); $containerText = $($containerText); $(".editsection", $containerText).remove(); $("a", $containerText).attr("target", "_blank"); $("#umInstantPreviewContainer").empty().append($containerText).resizable({ alsoResize: "#AjaxUmContainer", }); } }, umObtainEditToken: () => { if (mw.user && mw.user.tokens) { umsg.editToken = mw.user.tokens.get("csrfToken"); } umsg.editToken = umsg.editToken || (mw.user.isAnon() ? "+\\" : ""); if (umsg.editToken) { return; } const query = { action: "query", prop: "info", intoken: "edit", titles: "FAQ", // Random title }; umsg.doAPICall(query, "umObtainEditTokenCB"); }, umObtainEditTokenCB: (result) => { const pages = result.query.pages; for (const id in pages) { // there should be only one, but we don't know its ID if (Object.hasOwnProperty.bind(pages)(id)) { umsg.editToken = pages[id].edittoken; } } }, umNotifyUserExecute: () => { if (umsg.umExecuting) { return; } umsg.pageName = umsg.umUserTalkPrefix + $("#umUser").val(); umsg.talkSummary = $("#umSummary").val(); umsg.appendTemplate(); }, appendTemplate: () => { const page = []; page.title = umsg.pageName; page.text = umsg.talkTag; page.editType = "appendtext"; page.redirect = true; if (window.AjaxDeleteWatchFile) { page.watchlist = "watch"; } umsg.umExecuting = true; $("#umInstantPreviewContainer").empty().html('<p class="center"><img src="https://img.moegirl.org.cn/common/d/d1/Windows_10_loading.gif"/></p>'); umsg.savePage(page, umsg.talkSummary, "umNotifyUserExecuteCB"); }, savePage: (page, summary, callback) => { const edit = { action: "edit", summary: summary, watchlist: page.watchlist || "preferences", title: page.title, }; if (page.redirect) { edit.redirect = ""; } edit[page.editType] = page.text; edit.token = umsg.editToken; umsg.doAPICall(edit, callback); }, umNotifyUserExecuteCB: (/* result*/) => { let encTitle = umsg.umUserTalkPrefix + $("#umUser").val(); encTitle = encodeURIComponent(encTitle.replace(/ /g, "_")).replace(/%2F/ig, "/").replace(/%3A/ig, ":"); const newLoc = mw.config.get("wgServer") + mw.config.get("wgArticlePath").replace("$1", encTitle); if (window.location.pathname === mw.config.get("wgArticlePath").replace("$1", encTitle)) { window.location.hash = "#footer"; window.location.reload(); } else { window.location.href = `${newLoc}#footer`; } umsg.umExecuting = false; }, doGetApiCall: (params, callback, pCallback) => { // Local Cache if (params.list) { if ("allusers" === params.list) { if (params.auprefix in umsg.umUserCache) { umsg[callback](umsg.umUserCache[params.auprefix], pCallback); return; } } else if ("allimages" === params.list) { if (params.aiprefix in umsg.umFileCache) { umsg[callback](umsg.umFileCache[params.aiprefix], pCallback); return; } } } params.format = "json"; $.ajax({ url: umsg.apiURL, cache: true, dataType: "json", data: params, type: "GET", async: true, success: (result) => { if (!result) { if ("function" === typeof pCallback) { pCallback(); } return; } try { if (params.list) { if ("allusers" === params.list) { // cache the result umsg.umUserCache[params.auprefix] = result.query.allusers; umsg[callback](result.query.allusers, pCallback); return; } } if (params.list) { if ("allimages" === params.list) { // cache the result umsg.umFileCache[params.aiprefix] = result.query.allimages; umsg[callback](result.query.allimages, pCallback); return; } } // This is a "must", the doc sais if ("function" === typeof pCallback) { pCallback(); } umsg[callback](result); } catch (e) { return umsg.fail(e); } }, error: () => { // This is a "must", the doc sais if ("function" === typeof pCallback) { pCallback(); } }, }); }, doAPICall: (params, callback) => { if (params.action) { if ("parse" === params.action) { if (params.text in umsg.umParserCache) { umsg[callback](umsg.umParserCache[params.text]); return; } } } params.format = "json"; $.ajax({ url: umsg.apiURL, cache: false, dataType: "json", data: params, type: "POST", success: (result, _, x) => { if (!result) { return umsg.fail(`API 响应为空:\n${x.responseText}`); } // In case we get the mysterious 231 unknown error, just try again if (result.error && result.error.info.includes("231")) { return setTimeout(() => { umsg.doAPICall(params, callback); }, 500); } if (result.error) { return umsg.fail(`API 请求返回失败结果 (${result.error.code}):${result.error.info}`); } if (result.edit && result.edit.spamblacklist) { return umsg.fail(`此次编辑因 ${result.edit.spamblacklist} 被列入黑名单而失败`); } if (params.action) { if ("parse" === params.action) { umsg.umParserCache[params.text] = result; } } try { umsg[callback](result); } catch (e) { return umsg.fail(e); } }, error: (x, status, error) => { return umsg.fail(`API 请求遭遇网络错误:状态码为 【${x.status}】,状态文本为 【${status}】,错误信息为 【${error}】`); }, }); }, fail: (_err) => { let err; if ("object" === typeof _err) { let stErr = `${mw.html.escape(_err.message)}<br>${_err.name}`; if (_err.lineNumber) { stErr += ` @line${_err.lineNumber}`; } if (_err.line) { stErr += ` @line${_err.line}`; } err = stErr; } else { err = mw.html.escape(_err.toString()); } if (umsg.umDlgPresent) { $("#umInstantPreviewContainer").empty().html(`<p class="center"><img src="${umsg.umImgErr}" width="64" height="64"/></p><br>小工具发生错误:<br>${mw.html.escape(err)}`); } else { mw.notify(`小工具发生错误:${err}`); } }, i18n: { umFillInUser: "被警告的用户:", umSelectTag: "警告类型:", umFillInMedia: "相关图片文件", umFillInAdditional: "用户违规的页面:", umFillInRelUser: "被警告的相关用户:", umFillInSummary: "编辑摘要:", umAddText: "额外补充的信息:", submitButtonLabel: "留言", cancelButtonLabel: "取消", }, umInstPrevContainer: $("<div>", { id: "umInstantPreviewContainer", style: "background-color:#EFD;min-height:250px;vertical-align:middle;", }), umInitImgUserExists: '<img id="%ID%" src="https://img.moegirl.org.cn/common/thumb/4/42/P_no.svg/20px-P_no.svg.png" alt="?"/>', umImgUserUndefined: "https://img.moegirl.org.cn/common/thumb/4/42/P_no.svg/20px-P_no.svg.png", umImgUserNotExists: "https://img.moegirl.org.cn/common/thumb/4/42/P_no.svg/20px-P_no.svg.png", umImgUserExists: "https://img.moegirl.org.cn/common/thumb/b/be/P_yes.svg/20px-P_yes.svg.png", umImgUserIsIP: "https://img.moegirl.org.cn/common/thumb/7/7e/OOjs_UI_icon_userAnonymous.svg/20px-OOjs_UI_icon_userAnonymous.svg.png", umImgErr: "https://img.moegirl.org.cn/common/7/7f/Dialog-error.svg", umImgWarn: "https://img.moegirl.org.cn/common/b/bc/Commons-emblem-issue.svg", umImgInfo: "https://img.moegirl.org.cn/common/2/28/Commons-emblem-notice.svg", umFlagMQ: 1, // Media Query umFlagUQ: 2, // Username Query umFlagReq: 4, // Required - must filled in umFlagNS: 8, // Add Namespace umFlagP2: 16, // add a universal parameter umFlagP3: 32, // add a universal parameter umFlagIP: 64, // Message for IP only umFlagUM: 128, // User message only umFlagReqMqNs: 13, // Combination of (umFlagReq | umFlagMQ | umFlagNS) umUserTalkPrefix: `${mw.config.get("wgFormattedNamespaces")[3]}:`, apiURL: mw.util.wikiScript("api"), }; /** * A custom widget built by composition of Autocomplete and Button. * You can either type something into the field to get filtered suggestions based on your input, * or use the button to get the full list of selections. * * The input is read from an existing select-element for progressive enhancement, * passed to Autocomplete with a customized source-option. * * Autor: someone from the jQuery UI-Team? * slightly altered **/ const initCombobox = ($) => { $.widget("ui.combobox", { // These options will be used as defaults options: { displaytext: "", emptyMessage: 42, passEnter: true, shutOff: window.AxUserMsgUseSelect, }, // Use the _setOption method to respond to changes to options _setOption: function (key, value, ...args) { if (this.options.shutOff) { return; } switch (key) { case "displaytext": this.input.val(value); break; case "passEnter": this.options.passEnter = value; break; } // In jQuery UI 1.8, you have to manually invoke the _setOption method from the base widget $.Widget.prototype._setOption.apply(this, [key, value, ...args]); }, _create: function () { if (this.options.shutOff) { return; } const self = this, select = this.element.hide(), selectWidth = select.width(), selectId = select.attr("id"), selected = select.children(":selected"), value = selected.val() ? selected.text() : "", ownId = `j${Math.floor(Math.random() * 10000000000)}`; let selectLabels, isOpen = false, valid = true; if (selectId) { selectLabels = $(`label[for="${selectId}"]`); } const portMessure = this.portMessure = $("<div>", { id: `${ownId}vp`, }).css({ position: "fixed", top: "0", height: "0", }); $("body").append(portMessure); const input = this.input = $("<input>", { id: ownId, }).insertAfter(select).val(value).autocomplete({ delay: 0, minLength: 0, source: (request, response) => { let i = 0; const matcher = new RegExp($.ui.autocomplete.escapeRegex(request.term), "i"); response(select.children("option").map((_, ele) => { if (i > (window.AxUserMsgMaxSelect || 20) && request.term) { return; } const text = $(ele).text(); if (ele.value && (!request.term || matcher.test(text))) { i++; return { label: text.replace( new RegExp( `(?![^&;]+;)(?!<[^<>]*)(${$.ui.autocomplete.escapeRegex(request.term) })(?![^<>]*>)(?![^&;]+;)`, "gi", ), "<b>$1</b>"), value: text, option: ele, }; } })); }, select: (event, ui) => { ui.item.option.selected = true; self._trigger("selected", event, { item: ui.item.option, }); select.triggerHandler("change"); }, change: function (_, ui) { setTimeout(() => { console.info("change", input, this, ui); }, 16); if (!ui.item) { const matcher = new RegExp(`^${$.ui.autocomplete.escapeRegex($(this).val())}$`, "i"); valid = false; select.children("option").each((_, ele) => { if ($(ele).text().match(matcher)) { ele.selected = valid = true; return false; } }); if (!valid) { // remove invalid value, as it didn't match anything $(this).val(""); input.data("autocomplete").term = ""; select.val(self.options.emptyMessage); select.triggerHandler("change"); return false; } select.triggerHandler("change"); } }, create: function () { const $this = $(this); // 不可去除 const t_top = $this.offset().top - portMessure.offset().top; $(".ui-autocomplete.ui-menu").css({ position: "fixed", overflow: "auto", "max-height": `${Math.round($(window).height() - t_top - $this.height() - 20)}px`, }); }, close: () => { setTimeout(() => { isOpen = false; }, 1); }, open: function () { setTimeout(() => { console.info("open", input, this); }, 16); isOpen = true; const _t = $(this), t_top = _t.offset().top - portMessure.offset().top; $(".ui-autocomplete.ui-menu").css({ position: "fixed", "max-height": `${Math.round($(window).height() - t_top - _t.height() - 20)}px`, }); }, }).addClass("ui-widget ui-widget-content ui-corner-left").css("width", `${selectWidth - 70}px`).on("click", () => { $(input).select(); }).on("keydown", (e) => { if (self.options.passEnter && 13 === e.which && !isOpen && valid) { const kup = $.Event("keyup"); kup.ctrlKey = false; kup.keyCode = kup.which = 13; select.triggerHandler(kup); } }); if (selectLabels) { selectLabels.attr("for", ownId); } input.data("autocomplete")._renderItem = (ul, item) => { return $("<li>").data("item.autocomplete", item).append(`<a>${item.label}</a>`).appendTo(ul); }; this.button = $("<button>", { tabIndex: -1, type: "button", text: " ", title: "Show All Items", style: "height:1.5em;padding:0!important;width:20px;margin:0!important;position:relative;top:-2px;", }).insertAfter(input).button({ icons: { primary: "ui-icon-triangle-1-s", }, text: false, }).removeClass("ui-corner-all").addClass("ui-corner-right ui-button-icon").on("click", () => { // close if already visible if (input.autocomplete("widget").is(":visible")) { input.autocomplete("close"); return; } // work around a bug (likely same cause as #5265) this.button.blur(); // pass empty string as value to search for, displaying all results input.autocomplete("search", ""); input.focus(); }); }, destroy: function () { if (this.options.shutOff) { return; } this.input.remove(); this.portMessure.remove(); this.button.remove(); this.element.show(); $.Widget.prototype.destroy.call(this); }, }); }; if ([-1, 2, 3].includes(mw.config.get("wgNamespaceNumber"))) { // alternative for jQuery UI autocomplete: jquery.suggestions // http://jqueryui.com/demos/autocomplete/ http://svn.wikimedia.org/viewvc/mediawiki/trunk/phase3/resources/jquery/jquery.suggestions.js?view=markup await mw.loader.using([ "ext.gadget.jquery.ui", "mediawiki.util", "mediawiki.user", "user.options", // for sig "ext.gadget.libUtil", "ext.gadget.libJQuery", ]); const builtinTemplate = [ /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! * Append new messages at the bottom. Otherwise pre-selection for users will break. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ // ['Template name', "Name in Sidebar", "Detailed text", Type/Prompt statement, 'Talk summary']; ["模板:预加载警告/繁简输入", "用户进行了错误的繁体输入", "用户在简体模式下输入繁体编辑条目", umsg.umFlagUM, "用户违反编辑规则警告", 0], ["模板:预加载警告/针对条目的评论违规", "用户针对条目的评论违规", "用户认为条目不客观,并嘲讽攻击本站或编辑者", umsg.umFlagUM, "用户违反评论规则警告", umsg.umFlagP2], ["模板:预加载警告/针对用户的评论违规", "用户回复其他用户的评论违规", "用户在评论区辱骂攻击其他用户", umsg.umFlagUM, "用户违反评论规则警告", umsg.umFlagP2], ["模板:预加载警告/忍耐是有限的", "对用户的忍耐已达极限", "用户进行了相当数量的违反编辑规范的操作", umsg.umFlagUM, "用户违反编辑规范警告", 0], ]; const placeholderTemplate = ["", "请选择警告类型", "其他类型", umsg.umFlagUM, " ", 0]; Object.defineProperties(umsg, { umTemplate: { get: () => { if (!Array.isArray(window.AxUserMsgCustomTemplate)) { window.AxUserMsgCustomTemplate = []; } const result = [ ...window.AxUserMsgUseBuiltinTemplate !== false ? builtinTemplate : [], ...window.AxUserMsgCustomTemplate, placeholderTemplate, ]; result.push = (...args) => window.AxUserMsgCustomTemplate.push(...args); return result; }, configurable: false, enumerable: true, }, umSelect: { get: () => { if (Number.isSafeInteger(window.AxUserMsgPreSelect) && window.AxUserMsgPreSelect >= 0 && window.AxUserMsgPreSelect < umsg.umTemplate.length) { return window.AxUserMsgPreSelect; } return umsg.umTemplate.indexOf(placeholderTemplate); }, configurable: false, enumerable: true, }, }); $(() => { initCombobox($); umsg.umInstall(); if (window.installOldLinks) { umsg.umInstallOldLinks(); } $(document).triggerHandler("scriptLoaded", ["AxUserMsg", umsg]); }); } })(); //</nowiki>
返回
MediaWiki:AxUserMsg.js
。
导航菜单
个人工具
中文
未登录
讨论
贡献
创建账号
登录
命名空间
消息
讨论
English
查看
阅读
查看源代码
查看历史
更多
搜索
导航
首页
随机页面
最新图片
最近更改
讨论版
所有日志
分类
色情
政治
人物
帮助
沙盒
创建新条目
请求创建条目
交流社群
WIKI指南
帮助
工具
链入页面
相关更改
特殊页面
页面信息