"use strict";
// 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, $ */
(function ajaxEditIife() {
window.AjaxEdit = {};
window.AjaxEdit.scriptLink = "";
if (mw.config.get("wgSiteName") !== "Wiktionary")
window.AjaxEdit.scriptLink += "wikt:";
if (mw.config.get("wgContentLanguage") !== "en")
window.AjaxEdit.scriptLink += "en:";
window.AjaxEdit.scriptLink += "MediaWiki:Gadget-AjaxEdit.js";
var $document = $(document);
window.AjaxEdit.FireEvents = function() {
// fire page load events like the 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("This AjaxEdit edit box is already open.");
return;
} else {
ajaxEditAnchor.hasEditBox = true;
}
var elements = {};
var _query = new mw.Uri($(ajaxEditAnchor)
.parent()
.find("a")
.attr("href")).query,
title = _query.title,
section = _query.section;
section = section.replace("T-", ""); //transclusions...
var hdr = $(ajaxEditAnchor).parent().parent();
var sectionName = hdr.children(":header").first().text();
if (window.tabbedLanguages && !hdr.is(":header")) {
sectionName = window.tabbedLanguages;
}
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 ;
}
var minorEdit = checkboxAndLabel("ajaxedit-minor-edit-checkbox", "Minor edit");
elements.minorEditCheckbox = minorEdit, elements.minorEditLabel = minorEdit;
elements.saveButton = $("<button/>")
.text("Save")
.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();
$("#mw-content-text").html(newHtml.parse.text);
$("#catlinks").replaceWith(newHtml.parse.categorieshtml);
window.AjaxEdit.FireEvents();
mw.loader.moduleRegistry.state = "registered";
//mw.loader.moduleRegistry.version="generate-unique-guid-here";
mw.loader.moduleRegistry.script = undefined;
mw.loader.using("site", function () {});
window.AjaxEdit.Submain();
});
});
})
.css("margin-left", "3px");
elements.cancelButton = $('<button/>')
.text("Cancel")
.click(function () {
$("#ajaxedit-wrapper").remove();
ajaxEditAnchor.hasEditBox = false;
});
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", "Live preview");
elements.livePreviewCheckbox = livePreview, elements.livePreviewLabel = livePreview;
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);
}
});
};
/*
* 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(
/\$(*)/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(
"Your edit summary template (window.AjaxEditSummary) contains an unknown variable name. Variable name: "
+ name + ". Choose from summary, scriptlink, sectionname, sectionlink."
);
return "";
}
}
});
if (!usedSummary) {
mw.notify(
"Your edit summary template (window.AjaxEditSummary) doesn't use the edit summary you supplied, so your edit summary will be appended to the template: "
+ window.AjaxEditSummary);
finalSummary += " " + summary;
}
} else {
finalSummary = "/* " + sectionName + " */ " + summary + " (using ])";
}
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("successful");
} else if (response && response.error) {
mw.notify('Error: API returned error code "' + response.error.code + '": ' + response.error.info);
}
return response;
}).fail(function (xhr) {
mw.notify('Error: Request failed.');
$('#ajaxedit-wrapper *').attr('disabled', false);
});
};
window.AjaxEdit.Submain = function()
{
$(".mw-body-content .mw-editsection > .mw-editsection-bracket:contains(']')").each (function(){
var btn = $('<a/>').text("Ædit").on("click", function() { window.AjaxEdit.Click(this) });
$(this).before(", ").before(btn);
});
};
window.AjaxEdit.Main = function()
{
$(".mw-editsection > .mw-editsection-bracket:contains(']')").each (function(){
var btn = $('<a/>').text("Ædit").on("click", function() { window.AjaxEdit.Click(this) });
$(this).before(", ").before(btn);
});
};
if (mw.config.get('wgAction') == "view")
$(window.AjaxEdit.Main);
})();