User:Cookai1205/js/Gadget-AjaxEdit.js

维基百科,自由的百科全书

注意:保存之后,你必须清除浏览器缓存才能看到做出的更改。Google ChromeFirefoxMicrosoft EdgeSafari:按住⇧ Shift键并单击工具栏的“刷新”按钮。参阅Help:绕过浏览器缓存以获取更多帮助。

"use strict";
// from https://zh.wiktionary.org/w/index.php?title=MediaWiki:Gadget-AjaxEdit.js&oldid=7441434
// Description         : With a new button "Ædit" one can edit specific sections without reloading the whole page. 
//                       Supports TabbedLanguages gadget
// Dependencies: mediawiki.util, mediawiki.Uri, mediawiki.user, mediawiki.api
/* jshint maxerr:1048576, strict:true, undef:true, latedef:true, sub:true, esversion:5, esnext:false */
/* global mw, $ */


mw.loader.using( 'ext.gadget.HanAssist' ).then( ( require ) => {
	const { conv } = require( 'ext.gadget.HanAssist' );
    (function ajaxEditIife() {
		window.AjaxEdit = {};
		
		window.AjaxEdit.scriptLink = "";
		if (mw.config.get("wgSiteName") !== "Wikipedia")
			window.AjaxEdit.scriptLink += "w:";
		if (mw.config.get("wgContentLanguage") !== "zh")
			window.AjaxEdit.scriptLink += "zh:";
		window.AjaxEdit.scriptLink += "User:Cookai1205/js/Gadget-AjaxEdit.js";
		
		var $document = $(document);
		window.AjaxEdit.FireEvents = function() {
			// fire page load events like the [quotations ▼] thing
			// see https://github.com/wikimedia/mediawiki/blob/master/resources/src/mediawiki.action/mediawiki.action.edit.preview.js
			mw.hook("wikipage.content").fire($document);
			mw.hook("wikipage.categories").fire($document);
		};
		
		window.AjaxEdit.Click = function (ajaxEditAnchor) {
			if (ajaxEditAnchor.hasEditBox) {
				mw.notify(conv( { hans: "该AjaxEdit编辑框已打开", hant: "該AjaxEdit編輯框已打開。" } ));
				return;
			}
	
			var elements = {};
			var _query = new mw.Uri($(ajaxEditAnchor)
					.parent()
					.find("a[href*='action=edit']")
					.attr("href")).query,
			    title = _query.title,
			    section = _query.section;
		
			section = section.replace("T-", ""); //transclusions...
			var hdr = $(ajaxEditAnchor).parent().parent();
			var h2Parent = hdr.parent();
			if (h2Parent.hasClass("mw-heading")) {
				hdr = h2Parent;
			}
			var sectionName = hdr.children(".mw-headline").first().text();
			if (window.tabbedLanguages && !hdr.is(":header")) {
				sectionName = window.tabbedLanguages[window.currentLanguageTab];
			}
		
			var data = { action: 'raw', title: title, section: section };
			$.get(mw.util.wikiScript('index'), data).then(function (wikitext) {
				var rowHeight = Math.min(15, 1 + wikitext.split("\n").length);
				elements.textarea = $("<textarea/>")
				.attr({ rows: rowHeight })
				.addClass("mw-editfont-monospace")
				.text(wikitext);
				
				elements.textareaSummary = $("<input/>")
				.attr({
					type: "text",
					maxlength: 500,
					spellcheck: true,
					name: "wpSummary",
				})
				.keydown(event, function() {
					if (event.keyCode == 13) { // on enter
						elements.saveButton.click();
					}
				});
				
				function checkboxAndLabel(id, text) {
					var checkbox = $("<input/>")
					.attr({
						"id": id,
						"type": "checkbox",
					});
					var label = $("<label/>")
					.attr("for", id)
					.text(text);
					return [checkbox, label];
				}
				
				var minorEdit = checkboxAndLabel("ajaxedit-minor-edit-checkbox", conv( { hans: "小编辑", hant: "小編輯" } ));
				elements.minorEditCheckbox = minorEdit[0], elements.minorEditLabel = minorEdit[1];
				
				elements.saveButton = $("<button/>")
				.text("保存")
				.click(function () {
					elements.textarea.attr('disabled', true);
					elements.textareaSummary.attr('disabled', true);
					
					window.AjaxEdit.Save(section, sectionName, elements.textarea.val(), title, elements.textareaSummary.val(), elements.minorEditCheckbox.prop("checked"))
					.then(function (apiSaveResponse) {
						if (apiSaveResponse.error) return; //if abusefilter was triggered
						new mw.Api().get({page: mw.config.get("wgPageName"), action: "parse", prop: "text|categorieshtml"})
						.then(function (newHtml) {
							$("#ajaxedit-wrapper").remove();
							ajaxEditAnchor.hasEditBox = false;
							$("#mw-content-text").html(newHtml.parse.text["*"]);
							$("#catlinks").replaceWith(newHtml.parse.categorieshtml["*"]);
							
							window.AjaxEdit.FireEvents();
		
							mw.loader.moduleRegistry["site"].state = "registered";
							//mw.loader.moduleRegistry["site"].version="generate-unique-guid-here";
							mw.loader.moduleRegistry["site"].script = undefined;
							mw.loader.using("site", function () {});
		
							window.AjaxEdit.Submain();
						});
					});
				})
				.css("margin-left", "3px");
				
				elements.cancelButton = $('<button/>')
				.text("取消")
				.click(function () {
					$("#ajaxedit-wrapper").remove();
					ajaxEditAnchor.hasEditBox = false;
				})
				.css("margin-left", "3px");
				elements.previewDiv = $("<div/>")
				.css({
					"border-style": "solid", "border-width": "1px 1px 1px 4px",
					"border-radius": "0.33em", "border-color": "#a3d3ff",
				})
				.hide();
				
				function timestamp() {
					return new Date().toISOString();
				}
		
				var previousText;
				var previousTextTimestamp = timestamp();
				function loadPreview() {
					var newText = elements.textarea.val();
					var textTimestamp = timestamp();
					if (!previousText || previousText != newText) {
						new mw.Api()
						.parse(
							newText,
							{ title: mw.config.get("wgPageName"), pst: "true", preview: "true", sectionpreview: "true", disableeditsection: "true" }
						)
						.done(function (html) {
							if (textTimestamp > previousTextTimestamp) {
								elements.previewDiv.html(html);
								window.AjaxEdit.FireEvents();
								previousTextTimestamp = textTimestamp;
							}
						});
					}
					previousText = newText;
				}
				
				var livePreview = checkboxAndLabel("ajaxedit-live-preview-checkbox", conv( { hans: "实时预览", hant: "實時預覽" } ));
				elements.livePreviewCheckbox = livePreview[0], elements.livePreviewLabel = livePreview[1];
				elements.livePreviewCheckbox.on("change", function () {
					if ($(this).prop("checked")) {
						elements.previewDiv.show("slow");
						loadPreview();
						this.previewIntervalId = setInterval(loadPreview, 500);
					} else {
						clearInterval(this.previewIntervalId);
						elements.previewDiv.hide("fast");
						elements.previewDiv.empty();
					}
				});
		
				var wrapper = $("<div/>")
				.attr("id", "ajaxedit-wrapper")
				.css({ width: "auto", "margin": 0, "overflow": "hidden" })
				.append(elements.textarea)
				.append(elements.textareaSummary)
				.append(elements.saveButton)
				.append(elements.livePreviewCheckbox)
				.append(elements.livePreviewLabel)
				.append(elements.minorEditCheckbox)
				.append(elements.minorEditLabel)
				.append(elements.cancelButton)
				.append(elements.previewDiv);
		
				//tabbed languages support
				if ($(ajaxEditAnchor).is("#tabstable .editlangsection a")) {
					$(".languageContainer:not(:hidden)")
					.first()
					.prepend(wrapper);
				} else {
					hdr.after(wrapper);
				}
				
				ajaxEditAnchor.hasEditBox = true;
			});
		};
		
		/*
		 * Define edit summary template with window.AjaxEditSummary. For instance:
		 window.AjaxEditSummary = "Æ $sectionlink $summary";
		 */
		window.AjaxEdit.Save = function (sectionID, sectionName, sectionText, title, summary, minorEdit) {
			var finalSummary;
			if (typeof window.AjaxEditSummary === "string") {
				var usedSummary = false;
				finalSummary = window.AjaxEditSummary.replace(
					/\$([a-zA-Z_][a-zA-Z0-9_]*)/g,
					function(fullMatch, name) {
						switch (name) {
							case "summary": {
								usedSummary = true;
								return summary;
							}
							case "scriptlink": return window.AjaxEdit.scriptLink;
							case "sectionname": return sectionText;
							case "sectionlink": return "/* " + sectionName + " */";
							default: {
								mw.notify(
									conv( {
										hans: "您的编辑摘要模板(window.AjaxEditSummary)含有未知变量名:"
										+ name + "。请使用summary、scriptlink、sectionname、sectionlink。",
										hant: "您的編輯摘要模板(window.AjaxEditSummary)含有未知變數名:"
										+ name + "。請使用summary、scriptlink、sectionname、sectionlink。"
									} )
								);
								return "";
							}
						}
					});
				if (!usedSummary) {
					mw.notify(
						conv( {
							hans: "您的编辑摘要模板(window.AjaxEditSummary)不会使用您提供的编辑摘要,因此您的编辑摘要将后接于模板:"
							+ window.AjaxEditSummary,
							hant: "您的編輯摘要模板(window.AjaxEditSummary)不會使用您提供的編輯摘要,因此您的編輯摘要將後接於模板:"
							+ window.AjaxEditSummary
						} )
					);
					finalSummary += " " + summary;
				}
			} else {
				finalSummary = "/* " + sectionName + " */ " + summary + "(via [[" + window.AjaxEdit.scriptLink + "|AjaxEdit]])";
			}
			var data = {
				format: 'json',
				action: 'edit',
				title: title,
				section: sectionID,
				summary: finalSummary,
				text: sectionText,
				token: mw.user.tokens.get('csrfToken'),
				minor: minorEdit,
			};
			return new mw.Api().post(data).then(function (response) {
				if (response && response.edit && response.edit.result == 'Success') {
					mw.notify("成功");
				} else if (response && response.error) {
					mw.notify(conv( { hans: '错误:API返回错误代码“' + response.error.code + '”:' + response.error.info, hant: '錯誤:API返回錯誤碼「' + response.error.code + '」:' + response.error.info } ));
				}
				return response;
			}).fail(function (xhr) {
				mw.notify(conv( { hans: '错误:无法发送请求。', hant: '錯誤:無法發送請求。' } ));
				$('#ajaxedit-wrapper *').attr('disabled', false);
			});
		};
		
		window.AjaxEdit.Submain = function()
		{
			$(".mw-body-content .mw-editsection > .mw-editsection-bracket:contains(']')").each (function(){
				var btn = $('<a/>').addClass("Ajax-Edit-SectionBtn").text("Ædit").on("click", function() { window.AjaxEdit.Click(this) });
				$(this).before($("<span>").addClass("mw-editsection-divider").text(" | ")).before(btn);
			});
		};
		
		window.AjaxEdit.Main = function()
		{
			$(".mw-editsection > .mw-editsection-bracket:contains(']')").each (function(){
				var btn = $('<a/>').addClass("Ajax-Edit-SectionBtn").text("Ædit").on("click", function() { window.AjaxEdit.Click(this) });
				$(this).before($("<span>").addClass("mw-editsection-divider").text(" | ")).before(btn);
			});
		};
	
		if (mw.config.get('wgAction') == "view")
			$(window.AjaxEdit.Main);
	})();
} );