Fandom Developers Wiki
Advertisement

Note: After publishing, you may have to bypass your browser's cache to see the changes.

  • Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
  • Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
  • Internet Explorer / Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5
  • Opera: Press Ctrl-F5.
/**
 * module (Info)Widgets
 * documentation at: https://dev.wikia.com/wiki/InfoWidgets
 * used files: [[File:Facebook throbber.gif]]
 * © Peter Coester, 2012
 * 
 */

var Widgets = function () {
    
    var widgets = [];
    var lastUpdate = false;
    
    var my = {
        
        // preconfigurations:
        
        activeTalks: function () {
            return {
                type: 'api',
                params: {
                    action: 'query',
                    format: 'json',
                    list: 'recentchanges',
                    rctype: 'new|edit',
                    rclimit: 40,
                    rcshow: '!redirect',
                    rcprop: 'title',
                    rcnamespace: '1|3|5|7|9|11|13|15|110|111|401|500|501|502|503'
            }};
        },
        
        contribs: function () {
            return {
                fallback: 'Special:UserLogin',
                type: 'api',
                params: {
                    action: 'query',
                    format: 'json',
                    list: 'usercontribs',
                    uclimit: 40,
                    ucuser: window.wgUserName !== undefined && wgUserName ? encodeURIComponent(wgUserName) : '',
                    ucprop: 'title'
            }};
        },
        
        newPages: function () {
            return {
                type: 'api',
                params: {
                    action: 'query',
                    format: 'json',
                    list: 'recentchanges',
                    rctype: 'new',
                    rclimit: 20,
                    rcshow: '!redirect',
                    rcprop: 'title',
                    rcnamespace: 0
            }};
        },

        newFiles: function () {
            return {
                type: 'api',
                params: {
                    action: 'query',
                    format: 'json',
                    list: 'recentchanges',
                    rclimit: 20,
                    rcshow: '!redirect',
                    rcprop: 'title',
                    rcnamespace: 6
            }};
        },
        
        recentChanges: function () {
            return {
                type: 'api',
                params: {
                    action: 'query',
                    format: 'json',
                    list: 'recentchanges',
                    rctype: 'edit',
                    rclimit: 50,
                    rcshow: '!redirect',
                    rcprop: 'title'
            }};
        },
        
        stubs: function () {
            return {
                type: 'api',
                params: {
                    action: 'query',
                    format: 'json',
                    list: 'categorymembers',
                    cmtitle: 'Category:Article_stubs',
                    cmlimit: 10,
                    cmsort: 'timestamp'
            }};
        },
        
        watchlist: function () {
            return {
                fallback: 'Special:UserLogin',
                type: 'api',
                params: {
                    action: 'query',
                    format: 'json',
                    list: 'watchlist',
                    wlprop: 'title'
            }};
        },
        
        wantedPages : function () {
            return {
                traversal: 'entry title',
                type: 'rss',
                params: {
                    title: 'Special:WantedPages',
                    feed: 'atom',
                    limit: 20,
                    offset: 0
            }};
        },
        
        // main public functions:
        
        add: function (widget) {
            if (!widget.selector) throw new Error('no selector for container provided');
            widget.container = $(widget.selector);
            if (!widget.container.length) throw new Error('widget container cannot be found');
            if (!widget.params) throw new Error('no query parameters provided');
            if (undefined === widget.type) widget.type = 'api';
            switch (widget.type) {
                case 'api':
                    widget.dataType = widget.params.format = 'json';
                    if (undefined === widget.traversal) {
                        widget.traversal = [widget.params.action, widget.params.list, 'title'];
                    }
                    widget.extract = jsonExtract;
                    widget.url = '/api.php';
                break;
                case 'rss':
                    widget.dataType = 'xml';
                    if (undefined === widget.traversal) throw new Error('no traversal specified');
                    widget.extract = xmlExtract;
                    widget.url = '/index.php';
                break;
                default: throw new Error('unknown widget type');
            }
            if (undefined === widget.fallback)   widget.fallback = '';
            if (undefined === widget.active)     widget.active = true;
            if (undefined === widget.maxResults) widget.maxResults = 10;
            if (!$.isFunction(widget.format))   widget.format = format;
            if (!$.isFunction(widget.preload))  widget.preload = preload;
            if (!$.isFunction(widget.postload)) widget.postload = postload;
            if (!$.isFunction(widget.error))    widget.error = function () {};
            widgets.push(widget);
        },
        
        interval: false,
        
        start: function () {
            cycleThroughWidgets();
            $(window).focus(function () { cycleThroughWidgets(); } );
            $(window).blur (function () { 
                if (Widgets.interval) window.clearInterval(Widgets.interval);
                Widgets.interval = false;
            });
        },
        
        restart : function () {
            if (Widgets.interval) window.clearInterval(Widgets.interval);
            Widgets.interval = false;
            lastUpdate = false;
            cycleThroughWidgets();
        }
    };
    
    function ajaxQuery (current) {
        current.container.empty();
        current.preload(current.container);
        $.ajax({
            type: 'GET',
            data: current.params,
            async: true,
            cache: false,
            error: current.error,
            complete: function () {
                current.postload(current.container);
            },
            url: current.url,
            dataType: current.dataType,
            success: function (response, textStatus, jqXHR) {
                var results = current.extract(response, current.traversal);
                if (!results.length) results.push(current.fallback);
                current.container.append(current.format(results, current.maxResults));
            }
        });
    }

    function cycleThroughWidgets () {
        if (lastUpdate && Date.now() - lastUpdate < 61000) return;
        lastUpdate = Date.now();
        if (!Widgets.interval) {
            Widgets.interval = window.setInterval(
            function () {
                cycleThroughWidgets();
            }, 20000 );
        }
        for (var i = 0; i < widgets.length; i++) {
            if (!widgets[i].active) continue;
            ajaxQuery(widgets[i]);
        }
    }
    
    function format (titles, maxResults) {
        var html = '';
        var doublettes = [];
        for (var i = 0; i < titles.length && doublettes.length <= maxResults; i++) {
            if (-1 == $.inArray(titles[i], doublettes)) {
                doublettes.push(titles[i]);
                html += '<li><a href="'+mw.util.getUrl(titles[i])+'">'+titles[i]+'</a></li>';
            }
        }
        return html.length ? '<ul>'+html+'</ul>' : '';
    }
    
    function preload (container) {
        container.css({
            backgroundImage: 'url(https://images.wikia.nocookie.net/dev/images/8/82/Facebook_throbber.gif)',
            backgroundRepeat: 'no-repeat',
            backgroundPosition: 'center'
        });
    }
    
    function postload (container) {
        container.css( {backgroundImage: 'none'} );
    }
    
    function jsonExtract (response, traversal) {
        var prop = traversal[traversal.length - 1];
        var results = [];
        for (var i = 0, t = response; i < traversal.length - 1; i++) {
            if (undefined === t[traversal[i]]) return []; //throw new Error(traversal[i] + ' not found');
            t = t[traversal[i]];
        }
        for (i = 0; i < t.length; i++) {
            if (undefined === t[i][prop]) return []; //throw new Error(prop + ' not found');
            results.push(t[i][prop]);
        }
        return results;
    }
    
    function xmlExtract (response, traversal)
    {
        var results = [];
        var nodes = $(response).find(traversal);
        for (var i = 0; i < nodes.length; i++) {
            results.push(nodes[i].firstChild.nodeValue);
        }
        return results;
    }
    
    return my;

}();

$(function () {
    if ($.isFunction(window.widgetsLoaded)) {
        window.widgetsLoaded();
        Widgets.start();
    }
});
Advertisement