//

////
// ==UserScript==
// @name           doNachsichtungen
// @namespace      ParaDox
// @description    doNachsichtungen
//
// @include        http://de.wikipedia.org/*
// ==/UserScript==
//
//// runtime lineoffset = 183

function _ADD_EVENT_LISTENER() {} // DUMMY
window.addEventListener('load', function(event) {

    var scriptVersion    = '11.12.2009 19:05';
    var goBackHours      = (0.00 * 24) + 1.00 // 0.10 == 6 Minuten
    var calcOffsetDate   = true;            // errechne neuen offset für GM_setValue('offsetDate', YYYYMMDDHHmmSS)
    var autoOffsetDate   = true;            // automatically increase GM_setValue('offsetDate') if needed
    var limit            = '25';            // '&limit=' + limit

    var selectMaxItems   = 5;               // MAX-Anzahl LI-Elemente ==> Anzahl SichtungsDiffs öffnen
    var doInterval       = true;            // Wenn false, dann werden diffFenster nicht geladen in function loadDiffs()

    var displayVisited   = false;           // LI-row: white (or green #E8FFE8)
    var displayUnVisited = true;            // LI-row: blue #E8E8FF (yellow #FFFFDD are loaded now and allways displayed)
    var historyExtra     = 0;               // zusätzlich history-zeilen älter als letzte gesichtet version
    var alertIfBewertet  = false;           // Extra-Dialog-Warnung wenn Artikel mit WP-Bewertung "exzellent" oder "lesenswert"
    var hideSelectForm   = true;            // Formular ausblenden in "Spezial:Seiten_mit_ungesichteten_Versionen"

    ////
    // SEHR WICHTIG: Linkfarbe des Browsers bzw. WP-Skins
    var notVisitedColor  = 'rgb(0, 43, 184)';
    var beenVisitedColor = 'rgb(90, 54, 150)'; // 11.12.2009: Wird gleich weiter unten im Script neu ermittelt und "überschrieben";
    ////

    /* ===================================================================================== */

    if ( false ) {
        // Quasi permanenter Offset. Vermutlich muss var "calcOffsetDate" und/oder var "autoOffsetDate"
        // false sein damit das funktioniert ;-P
        GM_setValue('offsetDate', '20091211004500');
    }
    var triggerScriptURL = 'http://de.wikipedia.org/w/index.php?title=Spezial:Seiten_mit_ungesichteten_Versionen&greasemonkey=donachsichungen&limit=1';

    //// 11.12.2009: fraglich ob 'backwards' noch funktioniert
    var direction        = 'forwards';      // 'backwards' or 'forwards': stepping through <ul><li>
    ////

    //// am 26.09.2009 erhöht weil "var numObserverStr" fehlerhaft arbeitete (mag am schellerem FF3.5 gelegen haben?)
    var delayLoadDiff    = 3;               // nach dem Laden von Diff1 n Sekunden warten (bis 26.09.2009 default 1)
    var delayLoadDiff2   = 5;               // nach dem Laden ab  Diff2 n Sekunden warten (bis 26.09.2009 default 3)
    ////

    var dateLOC               = new Date();
    var timezoneOffset        = dateLOC.getTimezoneOffset() * 60 * 1000; // millisekunden
    var strangeTimezoneOffset = 2 * timezoneOffset; // millisekunden
    var body;
    var temp, tmp0, tmp1, i;
    var intervalTimer_id1, intervalTimer_id2;
    var intervalDauer, intervalCount, intervalStart;
    var urlArr         = new Array();
    var numObserverArr = new Array();
    var nextDiff, lastDiff, diffReady;              // interval vars
    var pattern;
    var rowAnchors;
    var bodyContentStr;
    var linkColorsObj = new Object();

    /* ===================================================================================== */
    function $(id) {
        return document.getElementById(id);
    }

    /* ===================================================================================== */
    function $$(pTag, pParent) {
        if ( pParent ) {
            return pParent.getElementsByTagName(pTag);
        } else {
            return document.getElementsByTagName(pTag);
        }
    }

    /* ===================================================================================== */
    function getUrlWithCallback(url, cb) {
      GM_xmlhttpRequest({
        method: "GET",
         url: url,
         onload: function(xhr) { cb(xhr.responseText); }
      });
    }

    /* ===================================================================================== */
    function removeNode(element) {
        element.parentNode.removeChild(element);
    }

    /* ===================================================================================== */
    function insertNodeAfter(newNode, node) {
      return node.parentNode.insertBefore(newNode, node.nextSibling);
    }

    /* ===================================================================================== */
    function y2k(number) {
        return (number < 1000) ? number + 1900 : number;
    }

    /* ===================================================================================== */
    function getStyle(pNode, pProperty) {
        // getComputedStyle(): http://www.codingforums.com/archive/index.php?t-19008.html
        // sytax for pProperty is 'backgroundColor' and not 'background-color'
        return document.defaultView.getComputedStyle(pNode, null).getPropertyValue(pProperty);
    }

    /* ===================================================================================== */
    function uniDate(pStr) { // "tt. Monat Jahr"
        // diese func aus "sectionage.user.js" kopiert am 06.08.2008
        //alert('function uniDate(pStr)=['+pStr+']');
        var result = '';
        var a = pStr.match( /(^\d{1,2})\. (.{3}).+?(\d{4}$)/ );
        //GM_log( 'donachsichtungen.user.js: [' + String(a).replace(/,/g,'\n') + ']' );
        if ( a != null ) {
            var m = 'Jan Feb Mär Apr Mai Jun Jul Aug Sep Okt Nov Dez';
                m = m.indexOf(a[2]);
                m = '01  02  03  04  05  06  07  08  09  10  11  12 '.substr(m,2)
            var t = ('00' + a[1]).substr(-2);
            var j = a[3];
            var result = j + '-' + m + '-' + t; // "jjjj-mm-tt"
        }
        //GM_log( 'donachsichtungen.user.js: [' + result + ']' );
        return result;
    }

    /* ===================================================================================== */
    function getOffsetDays() {
        var temp;
        temp = GM_getValue('offsetDate', '(offsetDate??)');
        temp = new Date( Number(temp.substr(0,4)), Number(temp.substr(4,2)-1), Number(temp.substr(6,2)),
                    Number(temp.substr(8,2)), Number(temp.substr(10,2)), Number(temp.substr(12,2)) );
        temp = ( (Number(dateLOC) + timezoneOffset - Number(temp) ) / 1000 / 60 / 60 / 24
                    ).toFixed(2);
        return temp;
    }

    /* ===================================================================================== */
    function calcLoadOffsetDate() {
        if ( calcOffsetDate ) {
            // getTimezoneOffset() sind negative Minuten relativ zu (-120=CEST) (-60=CET)
            var offsetTime = strangeTimezoneOffset - (goBackHours * 60 * 60 * 1000);

            var dateUTC = new Date(
                Date.UTC(
                    y2k(dateLOC.getYear()), dateLOC.getMonth(), dateLOC.getDate(),
                    dateLOC.getHours(),dateLOC.getMinutes(),dateLOC.getSeconds()
                    ) + offsetTime
                );

            var ano = String(dateUTC.getFullYear());
            var mon = ( '0' + String(dateUTC.getMonth()+1) ).substr(-2);
            var tag = ( '0' + String(dateUTC.getDate())    ).substr(-2);
            var hh  = ( '0' + String(dateUTC.getHours())   ).substr(-2);
            var mm  = ( '0' + String(dateUTC.getMinutes()) ).substr(-2);
            var ss  = ( '0' + String(dateUTC.getSeconds()) ).substr(-2);

            GM_setValue('offsetDate', ano + mon + tag + hh + mm + ss);
        }
        return GM_getValue('offsetDate', '(offsetDate??)');
    }

    /* ===================================================================================== */
    function loadSpezialNachsichtungen(pOffsetURL) {
        GM_setValue('observers', '');
        GM_getValue('observers', '');
        document.location.href = 'http://de.wikipedia.org/w/index.php?title='
            + 'Spezial:Seiten_mit_ungesichteten_Versionen&offset=' + pOffsetURL + '&limit=' + limit;
    }

    /* ===================================================================================== */
    function processURL(p_aNode) {
        var resultArr, i;
        // p_aNode is second aNode in liNode
        var nodeClone1 = p_aNode.cloneNode(true);
        p_aNode.parentNode.appendChild(nodeClone1);
        var nodeClone2 = p_aNode.cloneNode(true);
        p_aNode.parentNode.appendChild(nodeClone2);
        var nodeClone3 = p_aNode.cloneNode(true);
        p_aNode.parentNode.appendChild(nodeClone3);
        rowAnchors = p_aNode.parentNode.getElementsByTagName('a');
        for ( i=2; i<5; i++ ) {
            rowAnchors[i].innerHTML = ' ' + rowAnchors[i].innerHTML + String(i);
            rowAnchors[i].style.display = 'none';
        }

        ////
        // URL-FIX,  weil firefox die url sonst nicht als besucht merkt
        // Version 1+ (andere Versionen gelöscht 28.09.2008 01:52)
        var a = rowAnchors[1];
        var u = a.href;
        var t = a.title;
/*
        if ( t.indexOf('.') >= 0 ) {
            // Punkt in Lemma Problem
            s = u.replace(/(^.+?title=)(.+?)(&diff=.*$)/, '$2');
            var r1 = RegExp.$1;
            var r3 = RegExp.$3;
            t = s.replace(/\./, '%2E');
            u = r1 + t + r3;
            //alert('[' + a.href + ']\n[' + t + ']\n[' + u + ']');
        }
*/
        if ( t.indexOf('(') >= 0 ) {
            // ersetze '%28' und '%29' in url mit '(' und ')'
            var s = t.replace(/^.*\((.+?)\).*$/, '$1');
            ////
            // neu/überarb 09.10.2008 09:00: /Siehe unten Ausnahmen mit einem Punkt im Lemma: Schlecht für var pattern
            pattern = new RegExp('%28' + s.replace(/\./g, '\.') + '%29');
            ////
            u = u.replace(pattern, '(' + s + ')');
            //alert(a.href + '\n' + t + '\n' + s + '\n' + u);
        }
        rowAnchors[2].href = rowAnchors[1].href.replace(/&diffonly=0$/, '&diffonly=1'); // schnelleres Laden ohne ganzen Artikel
        rowAnchors[3].href = u;
        rowAnchors[4].href = u.replace(/&diffonly=0$/, '&diffonly=1'); // schnelleres Laden ohne ganzen Artikel
        ////

        var visited_URL_num = 0;
        for ( i=1; i<5; i++ ) {
            var linkColorStr = getStyle(rowAnchors[i], 'color');
            if ( linkColorStr == beenVisitedColor ) {
                visited_URL_num = i;
                if ( linkColorsObj[linkColorStr] == null ) linkColorsObj[linkColorStr] = 0;
                linkColorsObj[linkColorStr]++;
                break;
            }
        }
        if ( t.indexOf('.') >= 0 ) { // dann ist ein Punkt im Lemma, was blöderweise mit beenVisitedColor nicht geht
            visited_URL_num += 0.1;
        }
        rowAnchors[4].innerHTML += ' (visited_URL = ' + String(visited_URL_num) + ')'
            // + ' ' + getStyle(rowAnchors[1], 'color') + getStyle(rowAnchors[2], 'color')
            ;

        resultArr = [ rowAnchors[4].href, visited_URL_num ];
        return resultArr;
    }

    /* ===================================================================================== */
    function loadDiffs() {
        var tempArr, visited_URL_num, urlStr;
        $('contentSub').innerHTML = '<div id="contentSubDiv" style="font-size:12px; line-height:16px; color:black"></div>';

        var uLists = document.getElementById('bodyContent').getElementsByTagName('ul');
        if ( uLists.length < 1 ) {
            $('contentSubDiv').innerHTML = 'ABBRUCH – <b>donachsichtungen.user.js</b>'
                + ' – keine Liste vorhanden';
            return; // EXIT
        } else {
            var listRows = uLists[0].getElementsByTagName('li');
            if ( listRows == null ) {
                alert('EXIT donachsichtungen.user.js: listRows eq null');
                return; // EXIT
            } else {
                uLists[0].style.display = 'none';
                var countDiffs = 0;
                //GM_log(von + ' ' + bis);
                //GM_log('listRows eq ' + String(listRows.length));
                if ( direction == 'backwards' ) {
                    var idxFirst = listRows.length - 1;
                    var idxLast  = 0;
                    var idxLI    = idxFirst;
                    var idxStep  = -1;
                } else {
                    // direction == 'forwards'
                    var idxFirst = 0;
                    var idxLast  = listRows.length - 1;
                    var idxLI    = idxFirst;
                    var idxStep  = 1;
                }
                var idxMin = Math.min(idxFirst,idxLast)
                var idxMax = Math.max(idxFirst,idxLast)
                GM_setValue('nextDiff', 0);
                GM_setValue('lastDiff', 0);
                /*
                    alert( direction + ' idxLI=' + String(idxLI)
                    + ' idxFirst=' + String(idxFirst) + ' '
                    + ' idxLast=' + String(idxLast) + ' '
                    + String(idxLI >= idxFirst) + ' ' + String(idxLI <= idxLast) );
                */
                var lastUnmarked = -1;
                while ( (idxLI >= idxMin) && (idxLI <= idxMax) && (countDiffs < selectMaxItems) ) {
                    //GM_log('idxLI=' + String(idxLI));
                    var thisLiRow      = listRows[idxLI];
                    var beingRevuedStr = '';
                    try {
                        beingRevuedStr = thisLiRow.lastChild.firstChild.nodeValue; // empty or "(wird überprüft)"
                        // thisLiRow.lastChild.firstChild.nodeValue += 'TEST-A';
                    } catch (e) {
                        ;
                    }
                    if ( beingRevuedStr != '' ) {
                        var numObserverStr = '<b style="text-decoration:blink">' + beingRevuedStr + '</b>'
                            + thisLiRow.lastChild.previousSibling.nodeValue;
                            // thisLiRow.lastChild.previousSibling.nodeValue += 'TEST-B';
                    } else {
                        var numObserverStr = thisLiRow.lastChild.nodeValue;
                        // thisLiRow.lastChild.nodeValue += 'TEST-C';
                    }
                    rowAnchors = thisLiRow.getElementsByTagName('a');
                    tempArr         = processURL(rowAnchors[1]);
                    urlStr          = tempArr[0];
                    visited_URL_num = tempArr[1];
                    //GM_log('all: idxLI=' + String(idxLI) + ' countDiffs=' + String(countDiffs) + ' ' + String(visited_URL_num) + ' ' + urlStr)
                    if ( visited_URL_num == 0 ) {
                        countDiffs++;
                        //GM_log('NV: idxLI=' + String(idxLI) + ' countDiffs=' + String(countDiffs));
                        urlArr[countDiffs]         = urlStr;
                        numObserverArr[countDiffs] = numObserverStr;
                        //alert(numObserverArr[countDiffs]);
                        thisLiRow.style.backgroundColor = '#FFFFDD';
                        temp = String(idxLI + 1) + ' von ' + String(listRows.length) +  ' ... ' + thisLiRow.innerHTML;
                        thisLiRow.innerHTML = temp;
                        lastUnmarked = idxLI;
                    } else {
                        // beenVisitedColor
                        //GM_log('BV: idxLI=' + String(idxLI) + ' countDiffs=' + String(countDiffs));
                        thisLiRow.style.backgroundColor = '#E8FFE8';
                        if ( !displayVisited ) {
                            thisLiRow.style.display = 'none';
                        }
                    }
                    //GM_log(String(idxLI) + ' linkFarbe=' + linkFarbe + ' ' + rowAnchors[1].href);
                    idxLI    += idxStep;
                }
                var notVisitedYet = 0;
                while ( (idxLI >= idxMin) && (idxLI <= idxMax) ) {
                    thisLiRow  = listRows[idxLI];
                    rowAnchors = thisLiRow.getElementsByTagName('a');
                    tempArr         = processURL(rowAnchors[1]);
                    urlStr          = tempArr[0];
                    visited_URL_num = tempArr[1];
                    if ( visited_URL_num == 0 ) {
                        notVisitedYet++;
                        thisLiRow.style.backgroundColor = '#E8E8FF';
                        if ( !displayUnVisited ) {
                            thisLiRow.style.display = 'none';
                        }
                    } else {
                        // beenVisitedColor
                        thisLiRow.style.backgroundColor = 'white';
                        if ( !displayVisited ) {
                            thisLiRow.style.display = 'none';
                        }
                    }
                    idxLI += idxStep;
                }
                /*
                // folgendes ist schlecht, denn anschließende dynamische DOM-Veränderungen gehen dann nicht mehr!
                body = document.getElementsByTagName('BODY')[0];
                body.innerHTML = body.innerHTML.replace(/<\/h1>/, '</h1>' + ...
                */
                var lastUnmarked_offsetDate = expandOffset(GM_getValue('offsetDate', '(offsetDate??)'));
                if ( lastUnmarked >= 0 ) {
                    // then display offset after "lastUnmarked offsetDate=" with red background and bold
                    lastUnmarked_offsetDate = '<b style="background-color:#FCC">' + lastUnmarked_offsetDate + '</b>';
                }
                $('contentSubDiv').innerHTML = 'notVisitedYet = <b>'
                    + String(notVisitedYet) + '</b> of ' + String(listRows.length)
                    + ' (' + ( notVisitedYet/listRows.length*100 ).toFixed(1) + ' %)'
                    + ' — goBackHours=' + goBackHours.toFixed(1) + ' (' + ((goBackHours/24)+0.005).toFixed(2) + ' Tage)'
                    + ' — lastUnmarked offsetDate='  + lastUnmarked_offsetDate
                    ;
                uLists[0].style.display = 'block';
            }
            if ( autoOffsetDate || (notVisitedYet < 1) ) { // !???!: countDiffs < Number(limit)
                function _AUTO_OFFSET() {} // DUMMY
                // mark lemma-background of last-LI red
                if ( lastUnmarked >= 0 ) {
                    //alert(lastUnmarked);
                    var lastLI = listRows[lastUnmarked];
                } else {
                    var lastLI = uLists[0].lastChild;
                }
                var lemmaA = lastLI.getElementsByTagName('A')[0];
                lemmaA.style.backgroundColor = '#FCC';
                var diffA  = lastLI.getElementsByTagName('A')[1];
                var articleUrlName = diffA.href.replace(/^.+?\?title\=(.+?)&.+?$/, '$1');
                var lastMarkedRev  = diffA.href.replace(/^.+?&oldid\=(.+?)&.+?$/, '$1');
                var revisionsHREF  = 'http://de.wikipedia.org/w/api.php'
                    + '?action=query&prop=revisions&rvprop=ids|timestamp|user'
                    + '&rvlimit=500'  // default 500 stimmt nicht, vermutlich wenn '&rvendid=' benutzt wird
                    + '&format=xml' // or 'xmlfm' for debug
                    + '&rvendid=' + lastMarkedRev // stop on this revid
                    + '&titles=' + articleUrlName;
                //GM_openInTab(revisionsHREF);
                getUrlWithCallback(revisionsHREF, setNewOffsetDate);
            }
            if ( doInterval && (countDiffs > 0) ) {
                /*
                GM_log( String(urlArr).replace(/,/g,',\n') + '\n========\n\n'
                    +   String(numObserverArr).replace(/,/g,',\n')
                    );
                */
                function _INTERVAL_1_START() {} // DUMMY
                GM_setValue('lastDiff', countDiffs);
                GM_setValue('nextDiff', 1);
                GM_setValue('diffReady', true);
                intervalDauer = new Date();
                intervalCount = 0;
                intervalStart = new Date();
                var newText, newColor;
                intervalTimer_id1 = setInterval( function() {
                    intervalCount++;
                    diffReady = GM_getValue('diffReady', true);
                    nextDiff  = GM_getValue('nextDiff', 0);

                    // display interval dauer
                    if ( diffReady && (intervalCount > 0) ) {
                        temp = new Date();
                        intervalDauer = Number(temp - intervalDauer);
                        newColor = '#FFFFCC';
                        if ( intervalDauer < 2000 ) {
                            intervalReady = true;
                            newColor = '#E3FFE3';
                        }
                        newText = '[C=' + String(intervalCount)
                            + '_D=' + String(intervalDauer)
                            //+ '_' + String(diffReady)
                            + '_N=' + String(nextDiff) + '] ';
                            ;
                    } else {
                        intervalReady = false;
                        if ( $('searchInput').value.substr(0, 7) != '[bussy] ' ) {
                            newText  = '[bussy] ';
                        } else {
                            newText  = '';
                        }
                        newColor = '#FFE8E8';
                    }
                    $('searchInput').value = newText + $('searchInput').value;
                    $('bodyContent').style.backgroundColor = newColor;
                    //

                    if ( $('ParaDoxView') ) {
                        // display interval count
                        temp = $('ParaDoxView');
                        temp.value = String(Number(temp.value) + 1);
                        // display delayLoadDiff
                        $('ParaDoxLoad').value = String(delayLoadDiff);
                        // get and display nextDiff
                        $('ParaDoxExtra').value = String(nextDiff);;
                    }
                    //
                    if ( (delayLoadDiff > 0) && (nextDiff > 1) ) {
                        delayLoadDiff--;
                    } else {
                        delayLoadDiff = delayLoadDiff2;
                        lastDiff  = GM_getValue('lastDiff', 0);
                        if ( (nextDiff <= lastDiff) && diffReady && intervalReady ) {
                            intervalCount = 0;
                            GM_setValue('observers', numObserverArr[nextDiff]);
                            GM_setValue('diffReady', false);
                            GM_openInTab(urlArr[nextDiff]);
                            GM_setValue('nextDiff', ++nextDiff);
                            if ( nextDiff > lastDiff ) {
                                window.clearInterval(intervalTimer_id1);
                                temp = new Date();
                                temp = (Number(temp - intervalStart) / 1000).toFixed(1);
                                $('searchInput').value  = '[Dauer: ' + temp + ' Sek] ' + $('searchInput').value;
                                $('bodyContent').style.backgroundColor = '#E3E3FF';
                            }
                        }
                    }
                    intervalDauer = new Date();
                },1000);
                function _INTERVAL_1_ENDE() {} // DUMMY

            } // END if/else ( countDiffs < 1 )
        }
    } // function loadDiffs()

    /* ===================================================================================== */
    function setNewOffsetDate(pApiResult) {
        //alert('API-Result:\n\n' + pApiResult);
        //<rev revid="51724508" user="84.146.99.227" anon="" timestamp="2008-10-11T14:28:20Z"/>
        var revLinesArr = pApiResult.match(/<rev revid.+?\/>/g);
        //alert(String(revLinesArr));
        var revString = revLinesArr[revLinesArr.length - 2]; // vorletztes ArrayElement
        var timestamp = revString.replace(/^.+?timestamp="(.+?)Z".+?$/g, '$1');
        var offsetStr = timestamp.replace(/-/g, '');
        offsetStr = offsetStr.replace(/T/g, '');
        offsetStr = offsetStr.replace(/:/g, '');
        //alert(revString + '\n' + timestamp + '\n' + offsetStr);
        var newOffsetStr = expandOffset(offsetStr);
        if ( offsetStr != GM_getValue('offsetDate', '') ) {
            // then display offset after "autoOffsetDate=" with red background and bold
            newOffsetStr = '<b style="background-color:#FCC">' + newOffsetStr + '</b>';
        }
        GM_setValue('offsetDate', offsetStr);
        GM_getValue('offsetDate', '');
        $('contentSubDiv').innerHTML += ' <span style="white-space:nowrap">— autoOffsetDate=' + newOffsetStr + '</span>';
        var temp = '';
        for ( key in linkColorsObj ) {
            temp += '[' + key + ' Count=' + linkColorsObj[key] + ']';
            //temp += linkColorsObj[key];
        }
        if ( temp != '' ) $('contentSubDiv').innerHTML += ' <span style="white-space:nowrap">— ' + temp + '</span>';
    }

    /* ===================================================================================== */
    function showHistory(pHistoryHTML) {
        //alert('The first 2048 chars from the HTML of the page:\n\n' + pHistoryHTML.substr(0,2048));
        var ulPosAnf = pHistoryHTML.indexOf('<ul id="pagehistory">');
        var ulPosEnd = pHistoryHTML.substr(ulPosAnf).indexOf('</ul>') + ulPosAnf + 5;
        var ulHTML   = pHistoryHTML.substring(ulPosAnf, ulPosEnd);
        //GM_log(ulPosAnf);
        //GM_log(ulPosEnd);
        //GM_log(ulHTML);
        ////
        // neu 18.10.2008 12:30: !???! scheinbar nötig, wenn $('fr-rating-controls') (vllt. $('mw-reviewform') ?) fehlt
        $('contentSub').style.display = 'block';
        ////
        $('insertedHistory').innerHTML = ulHTML;

        setTimeout( function() {
            // datum der ersten Ent-Sichtung ist in letztem LI-Element
            temp = $('pagehistory').lastChild.previousSibling.innerHTML;
            // get "tt. Monat Jahr"
            temp = temp.replace(/^.+?>(\d\d:\d\d), (\d{1,2}\.) (.{3}).+?(\d{4})<\/a>.+?$/, '$1 $2 $3 $4');
            // change to "JJJJ-MM-TT HH:MM"
            temp = ( uniDate(temp.substr(6)) + ' ' + temp.substr(0,5) );
            // calc age in days
            temp = new Date( Number(temp.substr(0,4)), Number(temp.substr(5,2)-1), Number(temp.substr(8,2)),
                        Number(temp.substr(11,2)), Number(temp.substr(14,2)), 0 );
            temp = ( (Number(dateLOC) - Number(temp) ) / 1000 / 60 / 60 / 24
                        ).toFixed(2);
            $('tageAlt').innerHTML += ' • HISTORY=' + temp;
        },0);

    }

    /* ===================================================================================== */
    function showCategories(pApiResult) {
        //alert('API-Result:\n\n' + pApiResult);
        var catLinesArr = pApiResult.match(/<cl ns="14" title=".+?" \/>/g);
        var catString   = String(catLinesArr);
        //GM_log('A:' + catString);
        catString = catString.replace(/<cl ns="14" title="/g, '');
        catString = catString.replace(/" \/>,/g,              ' &mdash ');
        catString = catString.replace(/" \/>/g,               '');
        //GM_log('B:' + catString);
        checkIf_bewerteteSeite(catString);
    }

    /* ===================================================================================== */
    function checkIf_bewerteteSeite(pCatString) {
        if ( $('mw-reviewform') ) {
            //alert('mw-reviewform');
            var appendToTag = '</form>';
        } else {
            var appendToTag = '</h1>';
        }
        ////
        // Erkennen und behandeln von "Kategorie:Wikipedia:Bewertete Seite"-Unterkategorien
        // var isBewerteteSeite wird true
        var unterKatArr = new Array( 'Kategorie:Wikipedia:Exzellent',
            'Kategorie:Wikipedia:Exzellent Gesprochene Artikel',
            'Kategorie:Wikipedia:Exzellentes Bild',
            'Kategorie:Wikipedia:Informativ',
            'Kategorie:Wikipedia:Lesenswert' );
        //alert(unterKatArr);
        var isBewerteteSeite = false;
        for ( i=0; i<unterKatArr.length; i++ ) {
            if ( pCatString.indexOf(unterKatArr[i]) >= 0 ) {
                isBewerteteSeite = true;
                break
            }
        }
        var styleBewerteteSeite1 = '';
        var styleBewerteteSeite2 = '';
        if ( isBewerteteSeite ) {
            styleBewerteteSeite1 = '<span style="text-decoration:blink; background-color:#FFFF88">';
            styleBewerteteSeite2 = '</span>';
        }
        ////

        temp = GM_getValue('observers', '(observers??)');
        var observers = '<span style="color:#BB0000">'
            + temp + '</span>';
        if ( temp.indexOf('(EMPTY)') < 0 ) {
            GM_setValue('observers', temp + '(EMPTY)');
        } else {
            //alert('"(EMPTY)" sollte nur einmal da sein, ist aber:\n' + observers);
            // 04.10.2008 08:27: nasty workaroud!
            temp = temp.replace(/\(EMPTY\)/g, '');
            GM_setValue('observers', temp + '(EMPTY)');
        }
        GM_getValue('observers', '');

        if ( !$('wikEdDiffButton') ) {
            pattern = new RegExp(appendToTag);
            body = document.getElementsByTagName('BODY')[0];
            body.innerHTML = body.innerHTML.replace(pattern, appendToTag
                + '<div style="background-color:#EEEEFF; padding:0 3pt 3pt 3pt">'
                + observers + ' <b>'
                + styleBewerteteSeite1 + pCatString + styleBewerteteSeite2
                + '</b></div>'
                );
        } else {
            if ( !$('insertData') ) {
                ; // alert('id="insertData" fehlt, vermutlich wegen URL: diffonly=0');
            } else {
                $('insertData').innerHTML = observers
                    + ' <b>' + styleBewerteteSeite1 + pCatString + styleBewerteteSeite2 + '</b>';
            }
        }

        if ( isBewerteteSeite && alertIfBewertet ) {
            alert('ist bewertete Seite: Siehe Kategorien');
        }
    }

    /* ===================================================================================== */
    function expandOffset(pOffset) {
        return pOffset.substr(0,4) + '-' + pOffset.substr(4,2) + '-' + pOffset.substr(6,2)
            +'_'+ pOffset.substr(8,2) + ":" + pOffset.substr(10,2) + "'" + pOffset.substr(12);
    }

    /* ===================================================================================== */
    /* ===================================================================================== */
    function main() {
        if ( !calcOffsetDate ) {
            goBackHours = getOffsetDays() * 24;
        }

        documentURL = document.location.href;
        if ( documentURL == triggerScriptURL ) {
            $$('body')[0].innerHTML = '<h1 style="margin-left:2em;">donachsichtungen.user.js<br />wurde gestartet...</h1>';
            loadSpezialNachsichtungen(calcLoadOffsetDate());
            return; // EXIT
        }

        if ( $('bodyContent') ) {
            if ( $('bodyContent').innerHTML.indexOf('Unterschiede zwischen der markierten und der aktuellen Version ansehen') > 0 ) {
                // Link in normalem Diff ändern, damit beim Anwenden das History per diesem Script geladen wird
                //alert('29.09.2008 15:35:59');
                $('bodyContent').innerHTML = $('bodyContent').innerHTML.replace(/diffonly=1"/, 'diffonly=1"');
            } else if ( document.location.href == 'http://de.wikipedia.org/wiki/Spezial:Seiten_mit_ungesichteten_Versionen' ) {
                // neu 02.10.2008 17:08: !???! fraglich
                $('bodyContent').innerHTML = $('bodyContent').innerHTML.replace(/diffonly=0"/g, 'diffonly=1"');
            }
        }
        if ( $('mw-difftostable') ) {
            $('mw-difftostable').style.display = 'none';
            //GM_addStyle('.diff-context { display:none }');
            GM_addStyle('.diff-context { font:9px/12px Verdana,Arial,Sans-serif !important}');
        }

        //temp = documentURL; // wahrscheinlich schrott zeile
        if ( documentURL.substr(-11) == '&diffonly=1' ) { // neu 28.09.2008 10:52
            ////
            // datum/alter der aktuellen Version ermitteln/anzeigen

            // rechte Spalte
            temp = $('mw-diff-ntitle1').innerHTML;
            // get "tt. Monat Jahr"
            temp = temp.replace(/^.+?Version vom (\d{1,2}\.) (.{3}).+?(\d{4}), (\d\d:\d\d).+?$/, '$1 $2 $3 $4');
            // change to "JJJJ-MM-TT HH:MM"
            tmp0 = RegExp.$4; // RegExp.$4 is changed in uniDate()
            temp = ( uniDate(RegExp.$1 + ' ' + RegExp.$2 + ' ' + RegExp.$3) + ' ' + tmp0 );
            // calc age in days
            temp = new Date( Number(temp.substr(0,4)), Number(temp.substr(5,2)-1), Number(temp.substr(8,2)),
                            Number(temp.substr(11,2)), Number(temp.substr(14,2)), 0 );
            var tageAltR = ( (Number(dateLOC) - Number(temp) ) / 1000 / 60 / 60 / 24
                            ).toFixed(2);

            // linke Spalte: "Version vom 15. Mai 2009, 23:09 Uhr"
            temp = $('mw-diff-otitle1').innerHTML;
            // get "tt. Monat Jahr"
            temp = temp.replace(/^.+?Version vom (\d{1,2}\.) (.{3}).+?(\d{4}), (\d\d:\d\d).+?$/, '$1 $2 $3 $4');
            //GM_log( 'donachsichtungen.user.js A: [' + RegExp.$1 + '][' + RegExp.$2 + '][' + RegExp.$3 + '][' + RegExp.$4 + ']' );
            // change to "JJJJ-MM-TT HH:MM"
            tmp0 = RegExp.$4; // RegExp.$4 is changed in uniDate()
            temp = ( uniDate(RegExp.$1 + ' ' + RegExp.$2 + ' ' + RegExp.$3) + ' ' + tmp0 );
            //GM_log( 'donachsichtungen.user.js B: [' + temp + ']' );
            // calc age in days
            temp = new Date( Number(temp.substr(0,4)), Number(temp.substr(5,2)-1), Number(temp.substr(8,2)),
                            Number(temp.substr(11,2)), Number(temp.substr(14,2)), 0 );
            //GM_log( 'donachsichtungen.user.js C: ' + temp.toLocaleString() );
            var tageAltL = ( (Number(dateLOC) - Number(temp) ) / 1000 / 60 / 60 / 24
                            ).toFixed(2);
            ////

            ////
            // insert links: LOAD_DIFF+ARTICLE • <s>HISTORY</s> • <s>RELOAD</s> "jump to wikDiff-Button"
            var spanContainer = document.createElement('span');
            var spanHTML2 = ' <a href="'
                + documentURL.substr(0, documentURL.length - 1) + '0'
                + '" title="load this diff with complete article content"'
                + '>LOAD_DIFF+ARTICLE</a>'
                //+ ' • <a href="#insertedHistory"><b>HISTORY</b></a>'
                //+ ' — <a href="#' + documentURL + '">RELOAD</a>'
                + ' — <a href="#wikEdDiffButton">wikDiff</a>'
                + ' — <span id="tageAlt" style="color:#B00">Tage alt LINKS=' + tageAltL
                + ' • RECHTS=' + tageAltR + '</span>';
            if ( $('fr-rating-controls') ) {
                var spanHTML1    = '<span style="font-size:124%">';
                var spanLocation = 'fr-rating-controls';
            } else {
                var spanHTML1    = ' <span style="font-size:100%">';
                var spanLocation = 'contentSub';
            }
            spanContainer.innerHTML = spanHTML1 + spanHTML2 + '</span>'
                + '<span id="insertData" style="display:block;'
                + ' background-color:#EEEEFF; padding:3pt 3pt 3pt 3pt;'
                + ' font-size:120%;'
                + '"></span>'
                + '<div id="insertedHistory" style="font-family:Verdana,Arial,Sans-serif"></div>';
            $(spanLocation).appendChild(spanContainer);
            ////

            ////
            // get and display categories
            var articleUrlName = document.location.href.replace(/^.+?\?title\=(.+?)&.+?$/, '$1');
            //alert('articleUrlName=[' + articleUrlName + ']');
            var categoriesHREF = 'http://de.wikipedia.org/w/api.php?action=query&prop=categories'
                + '&format=xml' // or 'xmlfm' for debug
                + '&titles=' + articleUrlName;
            getUrlWithCallback(categoriesHREF, showCategories);
            ////

            bodyContentStr = $('bodyContent').innerHTML;
            var includedVersionsStrPos = bodyContentStr.indexOf('Der Versionsvergleich bezieht ');
            if ( includedVersionsStrPos >= 0 ) {
                var includedVersionsNum = Number(bodyContentStr.substr(includedVersionsStrPos+30,2)); // 2 weil wohl kaum mehr als 99 wahrscheinlich
                if ( typeof includedVersionsNum != 'number') alert('doNachsichtungen.user.js:\n var includedVersionsNum is not a number');

                ////
                // get and display history
                var historyHREF = $('ca-history').getElementsByTagName('a')[0].href;
                historyHREF += '&limit=' + String(includedVersionsNum + 1 + historyExtra);
                getUrlWithCallback(historyHREF, showHistory);
                ////

            }
        }

        if ( document.getElementById('mw-difftostable') ) { // ab 27.09.2008 03:20

            // Wahrscheinlich Sichtungs-Diff: ab 23.09.2008:
            // Folgender Code geht bei aktivierter Einstellung
            //    "Verschiedenes: Zeige beim Versionsvergleich nur die Unterschiede, nicht die vollständige Seite"
            // bei normalen Diff (ohne '&diffonly=0') nicht, weil dann keine Kats in der Seite enthalten sind.

            ////
            // Kategorien an Seiten-Anfang kopieren
            ////
            if ( $('mw-normal-catlinks') ) {
                var catLinks_innerHTML = document.getElementById('mw-normal-catlinks').innerHTML;
                checkIf_bewerteteSeite(catLinks_innerHTML);
            }

            if ( $('bodyContent').innerHTML.indexOf('title="Spezial:Beiträge/84.158.') > 0 ) {
                $('wikEdDiffWrapper').style.backgroundColor = 'red';
            }

            function _INTERVAL_2_START() {} // DUMMY
            intervalTimer_id2 = setInterval( function() {
                if ( $('ParaDoxView') ) {
                    // display interval count
                    temp = $('ParaDoxView');
                    temp.value = String(Number(temp.value) + 1);
                }
                if ( document.title == 'Aktion beendet' ) {
                    window.clearInterval(intervalTimer_id2);
                    temp = $('mw-js-message').innerHTML.indexOf('wurde erfolgreich als gesichtet markiert');
                    //alert(temp);
                    if ( temp > 0 ) {
                        $('mw-js-message').style.backgroundColor = '#EEFFEE';
                        document.title = 'OK';
                    } else {
                        $('mw-js-message').style.backgroundColor = '#FFEEEE';
                        document.title = 'FEHLER';
                        //alert('WURDE NICHT MARKIERT');
                    }
                }
            },1000);
            function _INTERVAL_2_ENDE() {} // DUMMY

        }

        ////
        // page loading finished: set diffReady = true;
        ////
        if ( !GM_getValue('diffReady', false) ) {
            GM_setValue('diffReady', true);
            document.title = String(GM_getValue('nextDiff', 0) - 1) + ' ' + document.title;
        }

        ////
        // eventually load diff-tabs/-windows
        ////

        temp = 'http://de.wikipedia.org/w/index.php?title=Spezial:Seiten_mit_ungesichteten_Versionen&offset=';
        if ( documentURL.substr(0,temp.length) == temp ) {
            ////
            // neu 12.10.2008: SEITEN-TITEL ändern + anzeigen
            var docOffset = expandOffset( String( Number(documentURL.substr(temp.length, 14)) ) );
            var docTitle  = 'Special:OldReviewedPages [this URL offset: ' + docOffset + ']';
            document.title = docTitle;
            document.getElementsByTagName('H1')[0].innerHTML = '<span style="font-size:82%">'
                + document.title.replace(/\[/,' <small>[')
                + ' [<a id="ParaDox_load_next_link" href="' + triggerScriptURL + '"'
                + ' title="donachsichtungen.user.js: erneut ausführen">'
                + '<b style="background-color:#FFFFBB">load next</b></a>]'
                + '</small></span>';
            beenVisitedColor = getStyle($('ParaDox_load_next_link'),'color');
            ////

            if ( hideSelectForm ) $$('form', $('bodyContent'))[0].style.display = 'none';
            loadDiffs();
        } else {
            // if namespace=0 category=Wikipedia:Löschkandidat
                temp = 'http://de.wikipedia.org/w/index.php?'
                    + 'title=Spezial:Seiten_mit_ungesichteten_Versionen&namespace=0&category=Wikipedia:L%F6schkandidat';
                if ( documentURL == temp ) {
                    alert('donachsichtungen.user.js:\nnamespace=0 category=Wikipedia:Löschkandidat');
                    loadDiffs();
            // else
                } else if (
                       (documentURL == 'file:///F:/Eigene%20Dateien/WikiPedia/-%20GREASEMONKEY/ParaDox/WatchlistLastTime.html')
                    || (documentURL == 'file:///F:/Eigene%20Dateien/WikiPedia/-%20GREASEMONKEY/ParaDox/WatchlistNoUpdate.html')
                    ) {
                    document.getElementsByTagName('H1')[0].innerHTML += ' [<small>'
                    + String(getOffsetDays()) + ' Tage für doNachsichtungen</small>]';
                }
            //
        }
    } // END function main()

    function _ONLOAD() {} // DUMMY
    main();
}, false); // window.addEventListener('load', function(event) {
//