Hinweis: Leere nach dem Veröffentlichen den Browser-Cache, um die Änderungen sehen zu können.
- Firefox/Safari: Umschalttaste drücken und gleichzeitig Aktualisieren anklicken oder entweder Strg+F5 oder Strg+R (⌘+R auf dem Mac) drücken
- Google Chrome: Umschalttaste+Strg+R (⌘+Umschalttaste+R auf dem Mac) drücken
- Edge: Strg+F5 drücken oder Strg drücken und gleichzeitig Aktualisieren anklicken
//======================================================================
//## functions.js
/** finds an element in document by id */
function $(id) {
return document.getElementById(id);
}
/** add an OnLoad event handler */
function doOnLoad(callback) {
//.. gecko, safari, konqueror and standard
if (typeof window.addEventListener != 'undefined')
window.addEventListener('load', callback, false);
//.. opera 7
else if (typeof document.addEventListener != 'undefined')
document.addEventListener('load', callback, false);
//.. win/ie
else if (typeof window.attachEvent != 'undefined')
window.attachEvent('onload', callback);
// mac/ie5 and other crap fails here. on purpose.
}
//======================================================================
//## Page.js
//@depends functions.js
/** represents the current Page */
function Page() {
//------------------------------------------------------------------------------
//## public URL generation
/** compute an URL in action form which may have a title parameter */
this.actionURL = function(args) {
var url = this.wiki.site + this.wiki.actionPath;
return appendArgs(url, args);
}
/** compute an URL in the read form without a title parameter */
this.readURL = function(lemma, args, target) {
var url = this.wiki.site
+ this.wiki.readPath
+ encodeTitle(lemma)
+ (target ? "/" + encodeTitle(target) : "");
return appendArgs(url, args);
}
//------------------------------------------------------------------------------
//## url encoding and decoding
/** appends arguments to an url with "?" or "&" depending on context */
function appendArgs(url, args) {
var code = encodeArgs(args);
if (code == "") return url;
return url
+ (url.indexOf("?") == -1 ? "?" : "&")
+ code;
}
/** encodes an Object or Array into URL parameters. */
function encodeArgs(args) {
if (!args) return "";
var query = "";
for (arg in args) {
var key = encodeURIComponent(arg);
var raw = args[arg];
if (raw == null) continue;
var value = arg == "title" || arg == "target"
? encodeTitle(raw)
: encodeURIComponent(raw.toString());
query += "&" + key + "=" + value;
}
if (query == "") return "";
return query.substring(1);
}
/** convert URL-parameters into an Array. */
function decodeArgs(search) {
var out = new Object();
if (search == "") return out;
var split = search.split("&");
for (i=0; i<split.length; i++) {
var parts = split[i].split("=");
var key = decodeURIComponent(parts[0]);
var value = key == "title" || key == "target"
? decodeTitle(parts[1])
: decodeURIComponent(parts[1]);
out[key] = value;
}
return out;
}
/** encode a MediaWiki title into URL form */
function encodeTitle(title) {
return encodeURIComponent(title)
.replace(/%3[aA]/g, ":")
.replace(/%2[fF]/g, "/")
.replace(/ /g, "_");
}
/** decode a MediaWiki title from an URL */
function decodeTitle(title) {
return decodeURIComponent(title)
.replace(/_/g, " ");
}
//------------------------------------------------------------------------------
//## page info
function locationSite() {
return location.protocol + "//" + location.host
+ (location.port ? ":" + location.port : "");
}
function locationArgs() {
if (!location.search) return new Object();
return decodeArgs(location.search.substring(1))
}
function searchformAction(site) {
var search = $('searchform').action;
if (search.substring(0, site.length) == site) {
search = search.substring(site.length);
}
var match = /(.*\/)(.*):.*/(search);
return {
readPath: match[1],
specialNS: decodeTitle(match[2])
};
}
// readPath is needed later, but this.wiki is not accessible within an ordinary function :/
var site = locationSite();
var search = searchformAction(site);
var readPath = search.readPath;
var specialNS = search.specialNS;
var params = locationArgs();
function lemma() {
if (params.title) return params.title;
var split = location.pathname.split(readPath);
if (split.length < 2) return null;
return decodeTitle(split[1]);
}
function user() {
// ca-nstab-user ???
var userPage = $('pt-userpage');
if (userPage == null) return null;
var href = userPage.getElementsByTagName("a")[0].attributes.href.value;
var split = href.split(readPath);
if (split.length < 2) return null;
var full = decodeTitle(split[1]);
return full.split("/")[0];
}
function perma() {
var link = $('t-permalink');
if (!link) return null;
var a = link.getElementsByTagName("a")[0];
if (!a) return null;
return a.href;
// to get the oldid use this:
// .replace(/^.*&oldid=([0-9]+).*/, "$1");
}
//------------------------------------------------------------------------------
//## public info
this.lemma = lemma();
this.perma = perma();
this.user = user();
this.params = params;
this.wiki = {
site: site,
actionPath: "/w/index.php", //### generalize
readPath: readPath,
specialNS: specialNS,
}
}
//======================================================================
//## Ajax.js
/** ajax helper functions */
var Ajax = {
/** headers preset for POSTs */
urlEncoded: function(charset) { return {
"Content-Type": "application/x-www-form-urlencoded; charset=" + charset
}},
/** headers preset for POSTs */
multipartFormData: function(boundary, charset) { return {
"Content-Type": "multipart/form-data; boundary=" + boundary + "; charset=" + charset
}},
/** create a XMLHttpRequest with named parameters */
call: function(args) {
// create
var client = new XMLHttpRequest();
client.args = args;
// open
client.open(
args.method ? args.method : "GET",
args.url,
args.async ? args.async == true : true
);
// set headers
if (args.headers) {
for (var name in args.headers) {
client.setRequestHeader(name, args.headers[name]);
}
}
// handle state changes
client.onreadystatechange = function() {
if (args.state) args.state(client, args);
if (client.readyState != 4) return;
if (args.state4) args.state4(client, args);
}
// debug status
client.debug = function() {
return client.status + " " + client.statusText + "\n"
+ client.getAllResponseHeaders() + "\n\n"
+ client.responseText;
}
// and start
client.send(args.body ? args.body : null);
return client;
},
/** parses text into an XML dom */
parseXML: function(text) {
var parser = new DOMParser();
return parser.parseFromString(text, "text/xml");
},
/** encodes an Object or Array into URL parameters. */
encodeArgs: function(args) {
if (!args) return "";
var query = "";
for (arg in args) {
var key = encodeURIComponent(arg);
var raw = args[arg];
if (raw == null) continue;
var value = encodeURIComponent(raw.toString());
query += "&" + key + "=" + value;
}
if (query == "") return "";
return query.substring(1);
},
/** encodes form data as multipart/form-data */
encodeFormData: function(boundary, data) {
var out = "";
for (name in data) {
var raw = data[name];
if (raw == null) continue;
out += '--' + boundary + '\r\n';
out += 'Content-Disposition: form-data; name="' + name + '"\r\n\r\n';
out += raw.toString() + '\r\n';
}
out += '--' + boundary + '--';
return out;
},
}
//======================================================================
//## AjaxEditor.js
/** ajax functions for MediaWiki */
function AjaxEditor(page, progress) {
/** prepend a page with a given text */
this.prependText = function(title, text, summary) {
action(
{
title: title,
action: "edit",
section: 0
},
200,
"editform",
function(f) { return {
wpSection: f.wpSection.value,
wpStarttime: f.wpStarttime.value,
wpEdittime: f.wpEdittime.value,
wpScrolltop: f.wpScrolltop.value,
wpSummary: summary,
wpWatchthis: f.wpWatchthis.checked ? "1" : null,
wpMinoredit: f.wpMinoredit.checked ? "1" : null,
wpSave: f.wpSave.value,
wpEditToken: f.wpEditToken.value,
wpTextbox1: text + f.wpTextbox1.value,
}},
200,
progress
);
}
/** append a page with a given text */
this.appendText = function(title, text, summary) {
action(
{
title: title,
action: "edit",
section: "new"
},
200,
"editform",
function(f) { return {
wpSection: f.wpSection.value,
wpStarttime: f.wpStarttime.value,
wpEdittime: f.wpEdittime.value,
wpScrolltop: f.wpScrolltop.value,
wpSummary: summary,
wpWatchthis: f.wpWatchthis.checked ? "1" : null,
wpMinoredit: f.wpMinoredit.checked ? "1" : null,
wpSave: f.wpSave.value,
wpEditToken: f.wpEditToken.value,
wpTextbox1: f.wpTextbox1.value + text,
}},
200,
progress
);
}
/** delete a page */
this.deletePage = function(title, reason) {
action(
{
title: title,
action: "delete"
},
200,
"deleteconfirm",
function(f) { return {
wpReason: (reason == null ? ""
: reason != "" ? reason + " - "
: "") + f.wpReason.value,
wpConfirmB: f.wpConfirmB.value,
wpEditToken: f.wpEditToken.value,
}},
200,
progress
);
}
/** block a user */
this.blockUser = function(user, duration, reason) {
action(
{
title: page.wiki.specialNS + ":" + "Blockip",
target: user,
},
200,
"blockip",
function(f) { return {
wpBlockAddress: user, // title encode?
wpBlockReason: reason,
wpBlockExpiry: f.wpBlockExpiry.value,
wpBlockOther: duration,
wpEditToken: f.wpEditToken.value,
wpBlock: f.wpBlock.value,
}},
200,
progress
);
}
/** move a page */
this.movePage = function(oldTitle, newTitle, reason, withDisk) {
action(
{
title: page.wiki.specialNS + ":" + "Movepage",
target: oldTitle,
},
200,
"movepage",
function(f) { return {
wpOldTitle: oldTitle, // title encode?
wpNewTitle: newTitle, // title encode?
wpReason: reason,
wpMovetalk: withDisk ? "1" : null,
wpEditToken: f.wpEditToken.value,
wpMove: f.wpMove.value,
}},
200,
progress
);
}
//------------------------------------------------------------------------------
if (!progress) progress = null;
/**
* get a form, change it, post it.
*
* makeData gets form.elements to create a Map
* progress may have start(formName, url), execute(source),
* done(source) and error(source [, expectedStatus]) methods
*/
function action(
actionArgs, getStatus,
formName, makeData, postStatus,
progress) {
function phase1() {
var url = page.actionURL(actionArgs)
if (progress.start) progress.start(formName, url);
Ajax.call({
method: "GET", // default value, but needed in the messageAreaProgress :/
url: url,
state4: phase2,
});
}
function phase2(source) {
if (getStatus && source.status != getStatus) {
if (progress.error) { progress.error(source, getStatus); return; }
else throw "status unexpected: " + status + "\n" + client.debug();
}
if (progress.execute) progress.execute(source);
var doc = Ajax.parseXML(source.responseText);
var form = findForm(doc, formName);
if (form == null) {
if (progress.error) { progress.error(source, "form not found: " + formName); return; }
else throw "form not found: " + formName + "\n" + client.debug();
}
var data = makeData(form.elements);
// var boundary = "as908sfl3k45dshfasdfh"; //### BÄH!
Ajax.call({
method: "POST",
url: form.action,
headers: Ajax.urlEncoded("UTF-8"), // Ajax.multipartFormData(boundary, "UTF-8"),
body: Ajax.encodeArgs(data), // Ajax.encodeFormData(boundary, data),
state4: phase3,
});
}
function phase3(source) {
if (postStatus && source.status != postStatus) {
if (progress.error) { progress.error(source, postStatus); return; }
else throw "status unexpected: " + status + "\n" + client.debug();
}
if (progress.done) progress.done(source);
}
if (!progress) progress = {};
phase1();
}
/** finds a HTMLForm within an XMLDocument (!) */
function findForm(doc, name) {
// firefox does _not_ provide document.forms,
// but within the form we get proper HTMLInputElements
var forms = doc.getElementsByTagName("form");
for (var i=0; i<forms.length; i++) {
var form = forms[i];
if (elementName(form) == name) return form;
}
return null;
}
/** finds the name or id of an element */
function elementName(element) {
return element.name ? element.name
: element.id ? element.id
: null;
}
}
//======================================================================
//## MessageAreaProgress.js
/** uses a messageArea to display ajax progress */
function MessageAreaProgress() {
//------------------------------------------------------------------------------
//## Progress interface
this.start = function(formName, url) {
var ma = messageArea();
ma.display("form: " + formName
+ ", url: " + url);
ma.fade(6000);
}
this.execute = function(source) {
var ma = messageArea();
ma.display("method: " + source.args.method
+ ", status: " + source.status + " " + source.statusText
+ ", url: " + source.args.url);
ma.fade(6000);
}
this.done = function(source) {
var ma = messageArea();
ma.display("method: " + source.args.method
+ ", status: " + source.status + " " + source.statusText
+ ", url: " + source.args.url);
ma.fade(3000);
}
this.error = function(source, expectedStatus) {
var ma = messageArea();
ma.display("expected status: " + expectedStatus
+ ", received status: " + source.status + " " + source.statusText
+ ", url: " + source.args.url);
//ma.fade(12000);
}
//------------------------------------------------------------------------------
//## helper
function status(client) {
return client.status + " " + client.statusText;
}
/** returns an additional message area div */
function messageArea() {
var div = $('messageArea');
if (div) return div;
div = document.createElement("div");
div.id = 'messageArea';
div.className = "usermessage";
var bc = $('bodyContent');
bc.insertBefore(div, bc.firstChild);
/** display a text in the div */
div.display = function(text) {
div.textContent = text;
}
/** show the div for a minimum of 2 seconds */
div.fade = function(timeout) {
if (div.timer) clearTimeout(div.timer);
div.timer = setTimeout(
function() {
div.style.display = "none";
},
timeout
);
div.style.display = null;
}
return div;
}
}
//======================================================================
//## Bookmark.js
//@depends Page.js, AjaxEditor.js
/** manages a personal bookmarks page */
function Bookmark(page, editor) {
var PAGE = "bookmarks";
/** adds a bookmark on a user's bookmark page */
function add(remark) {
var lemma = page.lemma;
var mode = "perma";
var perma = page.perma;
if (!perma) {
var params = page.params;
var oldid = params["oldid"];
var target = params["target"];
if (oldid) {
var diff = params["diff"];
if (diff) {
if (diff == "prev") mode = "prev";
else if (diff == "next") mode = "next";
else mode = "diff";
perma = page.actionURL({ title: lemma, oldid: oldid, diff: diff});
}
else {
mode = "old";
perma = page.actionURL({ title: lemma, oldid: oldid});
}
}
else if (target) {
// for Special:Contributions
lemma += "/" + target;
}
}
var text = "*[[:" + lemma + "]]";
if (perma) text += " <small>[" + perma + " " + mode + "]</small>";
if (remark) text += " " + remark
text += "\n";
var title = page.user + "/" + PAGE;
editor.prependText(title, text, "");
return false;
}
// public
this.add = add;
this.page = PAGE;
this.full = page.readURL(page.user + "/" + PAGE);
}
//======================================================================
//## Template.js
//@depends Page.js, AjaxEditor.js
/** puts templates into the current page */
function Template(page, editor) {
/** puts an SLA template into the current article */
function sla(reason) {
var TEMPLATE = "löschen";
stamp(TEMPLATE, reason);
return false;
}
/** puts an LA template into the current article */
function la(reason) {
var TEMPLATE = "subst:Löschantrag";
var LISTPAGE = "Wikipedia:Löschkandidaten";
stamp(TEMPLATE, reason);
enlist(TEMPLATE, reason, LISTPAGE);
return false;
}
/** puts an QS template into the current article */
function qs(reason) {
var TEMPLATE = "subst:QS";
var LISTPAGE = "Wikipedia:Qualitätssicherung";
stamp(TEMPLATE, reason);
enlist(TEMPLATE, reason, LISTPAGE);
return false;
}
//------------------------------------------------------------------------------
//## helper
/** put template in the current page */
function stamp(template, reason) {
var r = renderer;
editor.prependText(
page.lemma,
r.get(r.template(template), r.sp, reason, r.sp, r.signature, r.lf, r.line, r.lf),
r.get(r.template(template), r.sp, reason)
);
}
/** list current page on a list page */
function enlist(template, reason, listPage) {
editor.appendText(
listPage + "/" + currentDate(),
r.get(r.lf, r.header(r.link(page.lemma)), r.lf, reason, r.sp, r.signature, r.lf),
r.get(r.link(page.lemma), r.sp, r.template(template), r.sp, reason)
);
}
/** returns the current date in the format the LKs are organized */
function currentDate() {
var months = [ "Januar", "Februar", "März", "April", "Mai", "Juni", "Juli",
"August", "September", "Oktober", "November", "Dezember" ];
var now = new Date();
var year = now.getYear();
if (year < 999) year += 1900;
return now.getDate() + ". " + months[now.getMonth()] + " " + year;
}
/** helps rendering mediawiki text */
var renderer = {
template: function(name) { return "{" + "{" + name + "}" + "}"; },
link: function(title) { return "[" + "[" + title + "]" + "]"; },
link2: function(title, label) { return "[" + "[" + title + "|" + label + "]" + "]"; },
header: function(text) { return "==" + text + "=="; },
signature: "-- " + "~~" + "~~",
line: "----",
sp: " ",
lf: "\n",
get: function() {
var out = "";
for (var i=0; i<arguments.length; i++) {
var arg = arguments[i];
while (arg.constructor == Function) {
arg = arg.apply(this);
}
out += arg.toString();
}
return out;
}
}
//------------------------------------------------------------------------------
// public
this.la = la;
this.sla = sla;
}
//======================================================================
//## init_public.js
//@depends functions.js, Page.js, Ajax.js, AjaxEditor.js
//@depends Bookmark.js, Template.js, doAction.css
/** onload hook */
function initialize() {
//------------------------------------------------------------------------------
//## ui building
/** adds a listitem to an ul and returns it */
function listItem(parent) {
var li = document.createElement("li");
parent.appendChild(li);
return li;
}
/** adds an actionlink to a list item and returns it */
function doAction(parent, func, label, query) {
var a = document.createElement("a");
a.textContent = label;
a.className = "actionLink";
a.onclick = function() {
var reason = prompt(query, "");
if (reason) func(reason);
else if (reason == "") func(reason);
return false;
};
parent.appendChild(a);
return a;
}
/** adds a page link to a list item and returns it */
function goPage(parent, url, label) {
var a = document.createElement("a");
a.href = url;
a.textContent =label;
parent.appendChild(a);
return a;
}
/** adds a space textNode to an list item and returns it */
function space(parent) {
var spc = document.createTextNode(" ");
parent.appendChild(spc);
return spc;
}
//------------------------------------------------------------------------------
//## setup
// setup objects
var page = new Page();
var progress = new MessageAreaProgress();
var editor = new AjaxEditor(page, progress);
var bookmark = new Bookmark(page, editor);
var template = new Template(page, editor);
// find toolbox
var toolbox = $('p-tb').getElementsByTagName("ul")[0];
// setup template UI
var line = listItem(toolbox);
doAction(line, template.qs, "QS", "SQ - Begründung?");
space(line);
doAction(line, template.la, "LA", "LA - Begründung?");
space(line);
doAction(line, template.sla, "SLA", "SLA - Begründung?");
// setup bookmarks UI
var line = listItem(toolbox);
goPage(line, bookmark.full, "bookmarks");
space(line);
doAction(line, bookmark.add, "add", "Bookmark - Kommentar?");
}
doOnLoad(initialize);