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);