MediaWiki:Gadget-thor.js

Aus Stupidedia, der sinnfreien Enzyklopädie!
Wechseln zu: Navigation, Suche

Wichtig: Nach dem Speichern musst Du deinem Browser sagen, dass er die neue Version laden soll: Mozilla/Firefox: Strg-Shift-R, IE: Strg-F5, Safari: Cmd-Shift-R, Konqueror: F5.

/**
 * Thor – Script zum vereinfachten Erteilen von offiziellen Auszeichnungen
 * Autor: [[Benutzer:Phorgo]]
 * Lizenz: GNU FDL
 *
 * Verwendete Dateien:
 * [[Datei:GThor-autoprotect.png]]
 * [[Datei:GThor-autoprotect-selected.png]]
 * [[Datei:GThor-null.png]]
 * [[Datei:GThor-null-selected.png]]
 * [[Datei:GThor-gelungen.png]]
 * [[Datei:GThor-gelungen-selected.png]]
 * [[Datei:GThor-hammer.png]]
 * [[Datei:GThor-hammer-selected.png]]
 * [[Datei:GThor-goldpokal.png]]
 * [[Datei:GThor-goldpokal-selected.png]]
 * [[Datei:Rauch.jpg]]
 *
 * <nowiki>
 */

gThor.votePages = {
    gh: 'Stupidedia:Ausgezeichnete_Artikel/Wahllokal', // Gelungen und Hammer
    gp: 'Kategorie_Diskussion:Stupidedia:Goldpokal/Wahllokal' // Goldpokal
};

gThor.init = function() {
    if ( mw.config.get( 'wgPageName' ) === gThor.votePages.gh || ( mw.config.get( 'wgPageName' ) === gThor.votePages.gp && global.groups.sysop ) ) {
        var link = $( '<a href="#" class="gThor-link">Thor</a>' ).click( gThor.onClick );
        $( 'h2 span.mw-editsection a' ).before( link, '&nbsp;|&nbsp;' );
    }
};

gThor.onClick = function( e ) {
    e.preventDefault();

    var h2 = $( this ).closest( 'h2' );
    var section = h2.find( 'a[href*="&action=edit&section="]' ).attr( 'href' ).replace( /.+&action=edit&section=(\d+).*/, '$1' );

    var container = $( '#gThor-window' );
    // Keine Fenster vorhanden, also neues öffnen
    if ( container.length === 0 ) {
        gThor.openWindow( h2, section );
    }
    // Fenster ist auf und behandelt diesen Abschnitt, also schließen
    else if ( container.find( 'input[name="section"]' ).val() === section ) {
        gThor.closeWindow();
    }
    // Es gibt bereits ein Fenster, aber das behandelt einen anderen Abschnitt, somit schließen und neues öffnen
    else {
        gThor.closeWindow( h2, section );
    }
};

gThor.openWindow = function( h2, section ) {
    var radio, label;
    var article = extractTitle( h2.find( 'span.mw-headline a' ).attr( 'href' ) ).replace( /_/g, ' ' );

    // Tabelle
    var table = $( '<table id="gThor-table" class="valign-top" />' )
            .append( '<tr id="gThor-articleRow"><th>Artikel:</th><td /></tr>' ) // Artikel
            .append( '<tr id="gThor-awardRow"><th>Auszeichnung:</th><td /></tr>' ) // Auszeichnung
            .append( '<tr id="gThor-commentRow"><th>Kommentar:</th><td /></tr>' ) // Kommentar
            .append( '<tr id="gThor-buttonRow"><th>&nbsp;</th><td /></tr>' ) // Buttons
            .append( '<tr id="gThor-messageRow"><td colspan="2" /></tr>' ); // Ausgabe

    // Artikelzeile
    var url = mw.util.wikiGetlink( article );
    var articleLink = $( '<a target="_blank" />' ).attr( 'href', url ).text( article );
    var historyLink = $( '<a target="_blank">Versionen</a>' ).attr( 'href', url + '?action=history' );
    var logLink = $( '<a target="_blank">Logbücher</a>' ).attr( 'href', mw.util.wikiGetlink( 'Spezial:Logbuch' ) + '?page=' + encodeURIComponent( article ) );
    // Reihenfolge: Artikel ( Versionen | Logbücher )
    table.find( '#gThor-articleRow td' ).append( articleLink, ' (', historyLink, ' | ', logLink, ')' );

    // Radiobuttons für die Auszeichnung
    var awardCol = table.find( '#gThor-awardRow td' );
    // Öffentliches Wahllokal
    if ( mw.config.get( 'wgPageName' ) === gThor.votePages.gh ) {
        // Keine Auszeichnung
        radio = $( '<input type="radio" name="award" value="null" id="gThor-award-null" class="gThor-boxInput" />' );
        label = $( '<label for="gThor-award-null">Keine Auszeichnung</label>' );
        awardCol.append( radio, ' ', label, '<br />' );
        // Gelungen
        radio = $( '<input type="radio" name="award" value="gelungen" id="gThor-award-gelungen" class="gThor-boxInput" />' );
        label = $( '<label for="gThor-award-gelungen">Gelungener Artikel</label>' );
        awardCol.append( radio, ' ', label, '<br />' );
    }
    // Hammer
    radio = $( '<input type="radio" name="award" value="hammer" id="gThor-award-hammer" class="gThor-boxInput" />' );
    label = $( '<label for="gThor-award-hammer">Absoluter Hammer</label>' );
    awardCol.append( radio, ' ', label );
    // Diktatorenwahllokal
    if ( mw.config.get( 'wgPageName' ) === gThor.votePages.gp ) {
        // Goldpokal
        radio = $( '<input type="radio" name="award" value="goldpokal" id="gThor-award-goldpokal" class="gThor-boxInput" />' );
        label = $( '<label for="gThor-award-goldpokal">Goldpokal</label>' );
        awardCol.append( '<br />', radio, ' ', label );
    }

    // Kommentarzeile
    var commentLine = $( '<input type="text" name="comment" value="" maxlength="255" />' );
    table.find( '#gThor-commentRow td' ).append( commentLine );

    // Seitenschutz automatisch ändern oder nicht
    var checkbox = $( '<input type="checkbox" name="autoprotect" checked="checked" id="gThor-autoprotect" class="gThor-boxInput" />' );
    label = $( '<label for="gThor-autoprotect" />' );
    // Automatisch anpassen für Diktatoren
    if ( global.groups.sysop ) {
        label.text( 'Seitenschutz automatisch anpassen' );
    }
    // Für Funktionäre wird in ihrem Namen eine Anfrage im Userportal gestellt
    else {
        label.text( 'Seitenschutzänderung im Userportal anfragen' );
    }
    table.find( '#gThor-commentRow' ).after( '<tr id="gThor-protectRow"><th>&nbsp;</th><td /></tr>' );
    table.find( '#gThor-protectRow td' ).append( checkbox, ' ', label );

    // Buttons
    var submitButton = $( '<input type="submit" value="Übernehmen" />' );
    var resetButton = $( '<input type="reset" value="Zurücksetzen" />' );
    var closeButton = $( '<input type="button" value="Schließen" />' ).click( gThor.closeWindow );
    table.find( '#gThor-buttonRow td' ).append( submitButton, ' ', resetButton, ' ', closeButton );

    // IE-Workaround, da CSS-Pseudoklasse :checked in älteren Versionen nicht vorhanden
    table.find( '.gThor-boxInput' ).on( 'change', gThor.refreshBoxInputs );

    // Versteckte Felder
    var articleField = $( '<input type="hidden" name="article" />' ).val( article );
    var sectionField = $( '<input type="hidden" name="section" />' ).val( section );

    // Formular erstellen
    var form = $( '<form action="javascript:rein_damit();" id="gThor-form" />' )
            .append( table, articleField, sectionField ) // Tabelle und versteckte Felder anhängen
            .bind( 'reset', gThor.resetForm ) // Bei Reset die Inputboxen überprüfen
            .bind( 'submit', gThor.submitForm ); // Funktion bei Bestätigung

    // Fristverlängerungsformular erstellen
    var periodBtn = $( '<button type="submit">Frist um eine Woche verlängern</button>' );
    var formPeriod = $( '<form action="javascript:rein_damit();" id="gThor-formPeriod" />' )
            .append( periodBtn, articleField.clone(), sectionField.clone() )
            .bind( 'submit', gThor.submitPeriod );

    // Fenster erstellen
    var container = $( '<div id="gThor-window" />' )
            .append( form, formPeriod ) // Formulare anhängen
            .appendTo( 'body' ) // Ans body-Element anhängen
            .autoCenter() // Zentrieren
            .draggable( { cancel: '#gThor-form' } ) // Verschiebbar machen
            .hide() // Verstecken
            .fadeIn( 'fast' ); // Mit Effekt einblenden

    gThor.refreshBoxInputs();
}

gThor.closeWindow = function( h2, section ) {
    $( '#gThor-window' ).fadeOut( 'fast', 'swing', function() {
        $( '#gThor-window' ).remove();
        if ( h2 && typeof section === 'string' ) {
            gThor.openWindow( h2, section );
        }
    } );
}

gThor.refreshBoxInputs = function() {
    $( '.gThor-boxInput' ).each( function() {
        var input = $( this );
        var checked = input.prop( 'checked' );
        if ( checked ) {
            input.addClass( 'gThor-checked' );
        }
        else {
            input.removeClass( 'gThor-checked' );
        }
    } );
}

// Formular zurücksetzen
gThor.resetForm = function() {
    $( '#gThor-form input:radio' ).removeClass( 'gThor-checked' );
    $( '#gThor-form input:checkbox' ).addClass( 'gThor-checked' );
    gThor.message();
}

// Formular wurde bestätigt, also aktuelle Seitenversion anfordern
gThor.submitForm = function() {
    var params = api.mergeParams( $( this ).serializeArray() );
    gThor.message();
    gThor.disableForm();

    // Formular ist beschädigt
    if ( params.article === undefined || params.section === undefined || params.comment === undefined ) {
        gThor.message( 'Das Formular ist beschädigt.', '#FF0000' );
        gThor.enableForm();
        return false;
    }

    var awards;
    
    if ( mw.config.get( 'wgPageName' ) === gThor.votePages.gh ) {
        awards = ['null', 'gelungen', 'hammer'];
    }
    else {
        awards = ['hammer', 'goldpokal'];
    }

    // Keine gültige Auszeichnung
    if ( $.inArray( params.award, awards ) === -1 ) {
        gThor.message( 'Du musst eine gültige Auszeichnung auswählen.', '#FF0000' );
        gThor.enableForm();
        return false;
    }

    gThor.message( 'Prüfe aktuelle Version der Abstimmungsseite …' );
    api.request( {
        action: 'query',
        prop: 'revisions',
        rvprop: 'ids|timestamp|content',
        pageids: mw.config.get( 'wgArticleId' ),
        rvsection: params.section
    }, gThor.copySection, params );

    return false;
}

// Prüfen, ob die derzeit aufgerufene Version aktuell ist und dann den Abschnitt auf die Diskussionsseite des Artikels kopieren.
gThor.copySection = function( data, params, jqxhr ) {
    // Fehlercheck
    if ( gThor.isError( data, jqxhr, 'query' ) ) {
        return;
    }

    var page = api.makeArray( data )[0];

    // Seite gibt es nicht
    if ( page.missing === '' ) {
        gThor.message( 'Offenbar wurde diese Seite gelöscht, seit du sie aufgerufen hast.', '#FF0000' );
        gThor.enableForm();
        return;
    }

    var revision = page.revisions[0];

    // Version ist nicht mehr aktuell
    if ( revision.revid !== mw.config.get( 'wgCurRevisionId' ) ) {
        gThor.message( 'Offenbar wurde diese Seite bearbeitet, seit du sie aufgerufen hast. Du solltest die Abstimmung noch einmal überprüfen.', '#FF0000' );
        gThor.enableForm();
        return;
    }

    gThor.message( 'Kopiere Abstimmung auf Artikeldiskussionsseite …' );
    var text = revision['*'].replace(/^==(.*?)==\n\n(.*?)\<b class\=\"pMjoelnir-done\"\>Stichtag!\<\/b\> \| \}\}/, "== Abstimmung vom " + time.getText('$D.$M.$Y', null) + " ==");

    api.request( {
        action: 'edit',
        title: getTalkPageName(params.article),
        appendtext: "\n" + text,
        notminor: true,
        summary: '[[Hilfe:Helferlein/Thor|Thor]]: Beende Abstimmung über [[' + params.article + ']]',
        token: global.editToken
    }, gThor.cleanSection, params );

}


// Abschnitt löschen
gThor.cleanSection = function( data, params, jqxhr ) {
    // Fehlercheck
    if ( gThor.isError( data, jqxhr, 'edit' ) ) {
        return;
    }

    if ( data.edit.result !== 'Success' ) {
        gThor.message( 'Die Abstimmung konnte aus unbekannten Gründen nicht beendet werden.', '#FF0000' );
        gThor.enableForm();
        return;
    }

    gThor.message( 'Beende Abstimmung …' );
    switch( params.award ){
        case 'null':
            gThor.action = gThor.archive;
            break;
        default:
            gThor.action = gThor.getAwards;
    }
    api.request( {
        action: 'edit',
        pageid: mw.config.get( 'wgArticleId' ),
        text: '',
        section: params.section,
        notminor: true,
        summary: '[[Hilfe:Helferlein/Thor|Thor]]: Beende Abstimmung über [[' + params.article + ']]',
        token: global.editToken
    }, gThor.action, params );
}

gThor.archive = function( data, params, jqxhr ) {
    // Fehlercheck
    if ( gThor.isError( data, jqxhr, 'edit' ) ) {
        return;
    }

    if ( data.edit.result !== 'Success' ) {
        gThor.message( 'Die Abstimmung konnte aus unbekannten Gründen nicht beendet werden.', '#FF0000' );
        gThor.enableForm();
        return;
    }

    gThor.message( 'Abstimmung beendet.', '#00FF00' );
    gThor.message( 'Archiviere Artikel …' );
    api.request( {
        action: 'edit',
        title: 'Stupidedia:Ausgezeichnete_Artikel/Wahllokal/Archiv',
        appendtext: '\n* [[' + params.article + ']]: [{{fullurl:Stupidedia:Ausgezeichnete_Artikel/Wahllokal|oldid=' + mw.config.get( 'wgCurRevisionId' ) + '}}#' + mw.util.wikiUrlencode( params.article ).replace(/%/g, '.') + ' Abstimmung] (Wahl beendet am {{subst:#time:d.m.Y}})',
        summary: '[[Hilfe:Helferlein/Thor|Thor]]: Archiviere Artikel',
        token: global.editToken
    }, gThor.getAwards, params );
}

// Prüfen, ob die Bearbeitung erfolgreich war und die offizielle Auszeichnung des Artikels prüfen
gThor.getAwards = function( data, params, jqxhr ) {
    if( gThor.action === gThor.archive ){
        // Fehlercheck
        if ( gThor.isError( data, jqxhr, 'edit' ) ) {
            return;
        }

        if ( data.edit.result !== 'Success' ) {
            gThor.message( 'Der Artikel konnte aus unbekannten Gründen nicht archiviert werden.', '#FF0000' );
            gThor.enableForm();
            return;
        }

        gThor.message( 'Der Artikel wurde archiviert.', '#00FF00' );
    }else{
        // Fehlercheck
        if ( gThor.isError( data, jqxhr, 'edit' ) ) {
            return;
        }

        if ( data.edit.result !== 'Success' ) {
            gThor.message( 'Die Abstimmung konnte aus unbekannten Gründen nicht beendet werden.', '#FF0000' );
            gThor.enableForm();
            return;
        }

        gThor.message( 'Abstimmung beendet.', '#00FF00' );
    }

    gThor.message( 'Prüfe Auszeichnungen des Artikels …' );
    api.request( {
        action: 'query',
        prop: 'awards',
        titles: params.article,
        awprototypes: 'offiziell'
    }, gThor.getAnchor, params );
}

// Wenn die aktuelle offizielle Auszeichnung nicht dem angegebenen Wert entspricht, Änderung vorbereiten und Abschnittsanker anfordern
gThor.getAnchor = function( data, params, jqxhr ) {
    // Fehlercheck
    if ( gThor.isError( data, jqxhr, 'query' ) ) {
        return;
    }

    var page = api.makeArray( data )[0];

    // Seite gibt es nicht oder der Seitentitel ist ungültig
    if ( page.missing === '' || page.invalid === '' ) {
        gThor.message( 'Der fragliche Artikel existiert nicht.', '#FF0000' );
        gThor.enableForm();
        return;
    }

    var currentAward = 'null';
    if ( page.awards ) {
        currentAward = page.awards[0].value;
    }

    // Abbrechen, wenn die Seite bereits diese Auszeichnung hat.
    if ( currentAward === params.award ) {
        gThor.message( 'Der Artikel hat bereits diese Auszeichnung.', '#00FF00' );
        gThor.enableForm();
        return;
    }

    gThor.message( 'Rufe Anker für die Abstimmung ab …' );
    api.request( {
        action: 'parse',
        oldid: mw.config.get( 'wgCurRevisionId' ),
        prop: 'sections',
        section: params.section
    }, gThor.awardArticle, params );
}

// Anker einholen und Auszeichnung ändern
gThor.awardArticle = function( data, params, jqxhr ) {
    // Fehlercheck
    if ( gThor.isError( data, jqxhr, 'parse' ) ) {
        return;
    }

    var json = $.toJSON( {
        seite: mw.config.get( 'wgPageName' ).replace( /_/g, ' ' ),
        version: mw.config.get( 'wgCurRevisionId' ),
        anker: data.parse.sections[0].anchor
    } );

    gThor.message( 'Bearbeite Auszeichnung …' );
    api.request( {
        action: 'award',
        title: params.article,
        'prototype': 'offiziell',
        value: params.award,
        params: json,
        comment: params.comment,
        token: global.editToken
    }, gThor.getProtections, params );
};

// Seitenschutz abfragen
gThor.getProtections = function( data, params, jqxhr ) {
    // Fehlercheck
    if ( gThor.isError( data, jqxhr, 'award' ) ) {
        return;
    }

    if ( data.award.result ) {
        gThor.message( 'Der Artikel wurde erfolgreich ausgezeichnet.', '#00FF00' );
        gThor.enableForm();
    }
    else {
        gThor.message( 'Der Artikel konnte nicht ausgezeichnet werden.', '#FF0000' );
        gThor.enableForm();
        return;
    }

    if ( params.autoprotect ) {
        gThor.message( 'Frage Seitenschutzstatus ab …' );
        api.request( {
            action: 'query',
            prop: 'info',
            titles: params.article,
            inprop: 'protection'
        }, gThor.receiveProtections, params );
    }
};

gThor.receiveProtections = function( data, params, jqxhr ) {
    // Fehlercheck
    if ( gThor.isError( data, jqxhr, 'query' ) ) {
        return;
    }

    var page = api.makeArray( data )[0];

    // Seite gibt es nicht oder der Seitentitel ist ungültig
    if ( page.missing === '' || page.invalid === '' ) {
        gThor.message( 'Der fragliche Artikel existiert nicht.', '#FF0000' );
        gThor.enableForm();
        return;
    }

    var protections = {
        award: null,
        edit: null,
        move: null
    };
    if ( page.protection ) {
        $.each( page.protection, function() {
            protections[this.type] = this.level;
        } );
    }

    if ( (( params.award === 'null' || params.award === 'gelungen' || params.award === 'hammer')
            && protections.edit === 'autoconfirmed' )
            || ( params.award === 'goldpokal' // TODO
            && protections.edit === 'sysop'
            && protections.move === 'sysop' ) ) {
        gThor.message( 'Der Seitenschutzstatus muss nicht geändert werden.', '#00FF00' );
        gThor.enableForm();
        return;
    }

    var protection = '';
    var action = 'entsperren';
    if ( params.award === 'hammer' ) {
        protection = 'edit=autoconfirmed|move=autoconfirmed';
        action = 'sperren';
    }
    else if ( params.award === 'goldpokal' ) {
        protection = 'edit=sysop|move=sysop'; // TODO
        action = 'sperren';
    }
    var user = mw.config.get( 'wgUserName' );
    var text = '\n* Bitte den Artikel [[' + params.article + ']] ' + action + '. — [[Hilfe:Helferlein/Thor|Thor]] i. V. [[Benutzer:' + user + '|' + user + ']] ([[Benutzer Diskussion:' + user + '|Diskussion]]) ~~~~~';

    // Diktatoren können den Artikel direkt schützen
    if ( global.groups.sysop ) {
        gThor.message( 'Ändere Seitenschutzstatus …' );
        api.request( {
            action: 'protect',
            title: params.article,
            protections: protection,
            reason: '[[Hilfe:Helferlein/Thor|Thor]]: Ändere Seitenschutzstatus gemäß Wahl',
            token: global.editToken
        }, gThor.checkProtectSuccess );
    }
    // Funktionäre müssen eine demütige Anfrage bei den Diktatoren stellen
    else {
        gThor.message( 'Beantrage Seitenschutzstatusänderung im Userportal …' );
        api.request( {
            action: 'edit',
            title: 'Stupidedia Diskussion:Userportal',
            section: 2,
            appendtext: text,
            summary: '[[Hilfe:Helferlein/Thor|Thor]]: Anfrage für Seitenschutzstatusänderung',
            token: global.editToken
        }, gThor.checkRequestSuccess );
    }
}

gThor.checkProtectSuccess = function( data, params, jqxhr ) {
    // Fehlercheck
    if ( gThor.isError( data, jqxhr, 'protect' ) ) {
        return;
    }

    gThor.message( 'Der Seitenschutzstatus wurde geändert.', '#00FF00' );
    gThor.enableForm();
}

gThor.checkRequestSuccess = function( data, params, jqxhr ) {
    // Fehlercheck
    if ( gThor.isError( data, jqxhr, 'edit' ) ) {
        return;
    }

    if ( data.edit.result !== 'Success' ) {
        gThor.message( 'Die Anfrage konnte nicht gestellt werden.', '#FF0000' );
        gThor.enableForm();
    }
    else {
        gThor.message( 'Die Diktatur ist informiert.', '#00FF00' );
        gThor.enableForm();
    }
}

gThor.submitPeriod = function() {
    var params = api.mergeParams( $( this ).serializeArray() );
    gThor.message();
    gThor.disableForm();

    // Formular ist beschädigt
    if ( params.section === undefined ) {
        gThor.message( 'Das Formular ist beschädigt.', '#FF0000' );
        gThor.enableForm();
        return false;
    }

    gThor.message( 'Hole alte Abstimmungsfrist …' );
    api.request( {
        action: 'query',
        prop: 'revisions',
        rvprop: 'ids|content|timestamp',
        pageids: mw.config.get( 'wgArticleId' ),
        rvsection: params.section
    }, gThor.getPeriod, params );

    return false;
}

gThor.getPeriod = function( data, params, jqxhr ) {
    // Fehlercheck
    if ( gThor.isError( data, jqxhr, 'query' ) ) {
        return;
    }

    var page = api.makeArray( data )[0];

    // Seite gibt es nicht
    if ( page.missing === '' ) {
        gThor.message( 'Offenbar wurde diese Seite gelöscht, seit du sie aufgerufen hast.', '#FF0000' );
        gThor.enableForm();
        return;
    }

    var revision = page.revisions[0];

    // Version ist nicht mehr aktuell
    if ( revision.revid !== mw.config.get( 'wgCurRevisionId' ) ) {
        gThor.message( 'Offenbar wurde diese Seite bearbeitet, seit du sie aufgerufen hast. Du solltest die Abstimmung noch einmal überprüfen.', '#FF0000' );
        gThor.enableForm();
        return;
    }

    var pattern = /(\<p class=\"pMjoelnir-dueDate\".*? data-timestamp\=\")(\d*)(\"[\s\S]*?\– )([^\, ]*?, \d{2}.\d{2}.\d{4} \{\{\#ifexpr\: \{\{LOCALTIMESTAMP\}\} \>\= \d*)/;
    var text = revision['*'].replace( pattern, gThor.extendPeriod );

    gThor.message( 'Speichere neue Abstimmungsfrist …' );


    api.request( {
        action: 'edit',
        pageid: mw.config.get( 'wgArticleId' ),
        section: params.section,
        text: text,
        notminor: false,
        summary: '[[Hilfe:Helferlein/Thor|Thor]]: Verlängere Abstimmungsfrist für [[' + params.article + ']]',
        token: global.editToken
    }, gThor.periodExtended, params );

    return false;
}

gThor.extendPeriod = function (match, p1, p2, p3, p4, offset, string) {
    var newPeriod = parseInt(p2) + 604800000; // 24 * 60 * 60 * 1000 ms

    return p1 + newPeriod + p3 + time.getText('$W, $D.$M.$Y', newPeriod) + ' {{#ifexpr: {{LOCALTIMESTAMP}} >= ' + time.getWikiTimestamp(newPeriod);
}

gThor.periodExtended = function( data, params, jqxhr ) {
    // Fehlercheck
    if ( gThor.isError( data, jqxhr, 'edit' ) ) {
        return;
    }

    gThor.message( 'Die Frist wurde verlängert.', '#00FF00' );
    gThor.enableForm();
}

gThor.isError = function( data, jqxhr, prop ) {
    // Verbindungsfehler
    if ( jqxhr.status !== 200 ) {
        gThor.message( 'Verbindungsfehler ' + jqxhr.status.toString() + ': ' + jqxhr.statusText, '#FF0000' );
        gThor.enableForm();
        return true;
    }

    // API-Fehler
    if ( data.error ) {
        var errors = {
            badtoken: 'Das Bearbeitungstoken ist ungültig. Lade die Seite neu und versuch’s noch mal.',
            blocked: 'Du wurdest gesperrt.',
            permissiondenied: 'Zugriff verweigert!'
        };
        var text = errors[data.error.code] || 'API-Fehler ' + data.error.code + ': ' + data.error.info;
        gThor.message( text, '#FF0000' );
        gThor.enableForm();
        return true;
    }

    // Datenfehler
    if ( !data[prop] ) {
        gThor.message( 'Es ist ein Datenfehler aufgetreten. Die Operation kann nicht beendet werden, da die benötigten Informationen nicht übertragen wurden.', '#FF0000' );
        gThor.enableForm();
        return true;
    }

    // Kein Fehler, weitermachen
    return false;
}

gThor.message = function( text, color ) {
    if ( !text ) {
        $( '#gThor-messageRow' ).html( '<td colspan="2"></td>' ).hide();
        return;
    }
    if ( !color ) {
        color = '';
    }
    var line = $( '<div />' ).html( text ).css( 'color', color );
    $( '#gThor-messageRow' ).show().find( 'td' ).append( line );
}

gThor.disableForm = function() {
    $( '#gThor-form input, #gThor-formPeriod input' ).prop( 'disabled', true );
}

gThor.enableForm = function() {
    $( '#gThor-form input, #gThor-formPeriod input' ).prop( 'disabled', false );
}

execute( 'gThor.init' );

Linktipps: Faditiva und 3DPresso