Jump to content

User:Polygnotus/Scripts/Editwars.js

From Wikipedia, the free encyclopedia
Note: After saving, you have to bypass your browser's cache to see the changes. Google Chrome, Firefox, Microsoft Edge and Safari: Hold down the ⇧ Shift key and click the Reload toolbar button. For details and instructions about other browsers, see Wikipedia:Bypass your cache.
/**
 * Edit War Tracker - displays the top reverting pages from
 * [[User:PolygnotusBot/editwar]] in the sidebar.
 * Uses the Page Visibility API to refresh when the tab becomes visible.
 * Requires: [[User:Polygnotus/Helpers/Sidebar.js]]
 * Install: paste into [[Special:MyPage/common.js]]
 */
( function () {
    'use strict';

    if ( typeof document.hidden === 'undefined' ) {
        return;
    }

    var API_ENDPOINT = '/w/api.php';
    var SOURCE_PAGE  = 'User:PolygnotusBot/editwar';
    var helper;

    /* ------------------------------------------------------------------ */
    /*  Fetch                                                               */
    /* ------------------------------------------------------------------ */
    var fetchGeneration = 0;

    function fetchData() {
        var generation = ++fetchGeneration;

        helper.setHeadingLabel( 'Edit wars (…)' );

        var params = new URLSearchParams( {
            action:  'query',
            titles:  SOURCE_PAGE,
            prop:    'revisions',
            rvprop:  'content',
            rvslots: 'main',
            format:  'json',
            origin:  '*'
        } );

        var xhr = new XMLHttpRequest();
        xhr.open( 'GET', API_ENDPOINT + '?' + params.toString(), true );
        xhr.setRequestHeader( 'Api-User-Agent', 'EditWarTrackerUserscript/1.0 (common.js gadget)' );
        xhr.onreadystatechange = function () {
            if ( xhr.readyState !== 4 ) { return; }
            if ( generation !== fetchGeneration ) { return; }
            if ( xhr.status !== 200 ) {
                helper.setHeadingLabel( 'Edit wars (error)' );
                return;
            }
            try {
                var data  = JSON.parse( xhr.responseText );
                var pages = data.query && data.query.pages;
                if ( !pages ) { throw new Error( 'Bad response' ); }

                // The API returns pages keyed by page ID; grab the first one
                var pageId  = Object.keys( pages )[ 0 ];
                var content = pages[ pageId ].revisions[ 0 ].slots.main[ '*' ];

                // The page may wrap the JSON in <syntaxhighlight> or similar;
                // extract the first {...} block to be safe
                var match = content.match( /\{[\s\S]*\}/ );
                if ( !match ) { throw new Error( 'No JSON found' ); }

                var parsed = JSON.parse( match[ 0 ] );
                if ( !parsed.rows ) { throw new Error( 'Unexpected structure' ); }

                helper.markDataLoaded();
                renderRows( parsed.rows );
            } catch ( e ) {
                helper.setHeadingLabel( 'Edit wars (error)' );
            }
        };
        xhr.send( null );
    }

    /* ------------------------------------------------------------------ */
    /*  Page Visibility API                                                 */
    /* ------------------------------------------------------------------ */
    function attachVisibilityListener() {
        document.addEventListener( 'visibilitychange', function () {
            if ( !document.hidden ) {
                fetchData();
            }
        } );
    }

    /* ------------------------------------------------------------------ */
    /*  Render                                                              */
    /* ------------------------------------------------------------------ */
    function renderRows( rows ) {
        var ul = document.createElement( 'ul' );
        ul.className = 'vector-menu-content-list';

        if ( !rows || rows.length === 0 ) {
            var empty = document.createElement( 'li' );
            empty.className = 'mw-list-item';
            var emptySpan = document.createElement( 'span' );
            emptySpan.textContent = 'No results.';
            empty.appendChild( emptySpan );
            ul.appendChild( empty );
        } else {
            rows.forEach( function ( row ) {
                // row[0] = revert count, row[1] = page title with underscores
                var revertCount  = row[ 0 ];
                var rawTitle     = row[ 1 ];
                // MediaWiki titles use spaces internally; underscores are equivalent
                // but mw.util.getUrl handles either form correctly
                var displayTitle = rawTitle.replace( /_/g, ' ' );

                var li = document.createElement( 'li' );
                li.className = 'mw-list-item';

                var link = document.createElement( 'a' );
                link.href = mw.util.getUrl( rawTitle );

                var titleSpan = document.createElement( 'span' );
                titleSpan.textContent = displayTitle;
                link.appendChild( titleSpan );
                li.appendChild( link );

                var meta = document.createElement( 'div' );
                meta.style.fontSize = 'x-small';
                meta.style.color    = '#555';
                meta.textContent    = revertCount + ' reverts';
                li.appendChild( meta );

                ul.appendChild( li );
            } );
        }

        helper.replaceRows( ul );
        helper.setHeadingLabel( 'Edit wars' );
    }

    /* ------------------------------------------------------------------ */
    /*  Init                                                                */
    /* ------------------------------------------------------------------ */
    mw.loader.using( 'mediawiki.util' ).then( function () {
        mw.loader.getScript(
            'https://en.wikipedia.org/w/index.php?title=User:Polygnotus/Helpers/Sidebar.js&action=raw&ctype=text/javascript'
        ).then( function () {
            helper = window.SidebarHelper( {
                id         : 'p-editwar-tracker',
                storageKey : 'editWarTrackerCollapsed',
                heading    : 'Edit wars',
                btnClass   : 'editwar-collapse-btn',
                onExpand   : fetchData
            } );

            $( function () {
                renderRows( [] );
                if ( !helper.isCollapsed() ) {
                    fetchData();
                }
                attachVisibilityListener();
            } );

        }, function () {
            mw.log.error( 'Edit War Tracker: failed to load SidebarHelper.' );
        } );
    } );

}() );