User:Unready/ui.refresh.js

//__NOINDEX__ /* * Description: * Refresh page content periodically * * Version 1.0: 27 April 2015 *  Original version for Wikipedia use * Version 1.1: 28 April 2015 *  Use jQuery * Version 1.2: 29 April 2015 *  Dynamically determine selector *  Allow interval configuration * Version 1.3: 30 April 2015 *  Support action=history * Version 1.4: 3 May 2015 *  Add programmatic toggle * * License: CC-BY-SA *  http://creativecommons.org/licenses/by-sa/3.0/ */

((window.user = window.user || {}).ui = window.user.ui || {}).refresh = (function (mw, $) { 'use strict';

var g_self, g_selector, g_jqContent, g_jqInput, g_jqImg, g_jqLi, g_wAction = mw.config.get('wgAction'), g_interval = 120, // default refresh interval (seconds) g_hTimeout = -1; // cannot run = -1; okay to run = 0; running > 0

// process click events on radio buttons for action=history // mostly "borrowed" from MediaWiki 1.26wmf3 //  example: //  $._data( $('li > input[type="radio"]')[0] ).events.click[0].handler // it's not possible to attach the existing handler, because //  1. the existing handler cannot deal with //     changing the number of list items //  2. if the previous page had only one list item, //     there's no reference to the handler available function updateDiffRadios {   var li, inputs, oldidRadio, diffRadio, nextState = 'before';

if (!g_jqLi.length) {     return; }   g_jqLi.each(function    {      li = $(this);      inputs = li.find('input[type="radio"]');      oldidRadio = inputs.filter('[name="oldid"]').eq(0);      diffRadio = inputs.filter('[name="diff"]').eq(0);      li.removeClass('selected between before after');      if (!oldidRadio.length || !diffRadio.length)      {        return;      }      if (oldidRadio.prop('checked'))      {        li.addClass('selected after');        nextState = 'after';      }      else if (diffRadio.prop('checked'))      {        li.addClass('selected ' + nextState);        nextState = 'between';      }      else      {        li.addClass(nextState);      }    }); }

// get interval (sec) from module properties //  and convert it to msec function getInterval {   if ((typeof g_self.interval === 'number') &&      (g_self.interval > 0) &&      (g_self.interval < 604801 )) // 7 days + 1 sec {     g_interval = g_self.interval; }   else {     g_self.interval = g_interval; }   return g_interval * 1000; }

// process checkbox events function onCheck {   if (g_jqInput.prop('checked')) {     if (g_hTimeout === 0) { // schedule a tick g_jqImg.hide; // in case it was showing after an error g_hTimeout = window.setTimeout(onTick, getInterval); g_self.message = 'OK'; }   }    else {     if (g_hTimeout > 0) { // stop the scheduled tick window.clearTimeout(g_hTimeout); g_hTimeout = 0; g_self.message = 'Stopped'; }   }  }

// process Ajax done event function onDone(htmlString) {   var jqNewContent = $(htmlString).find(g_selector);

if (jqNewContent.length !== 1) {     g_self.message = 'onDone :: ' + jqNewContent.length + ' elements found for (' + g_selector + ')'; g_jqInput.prop('checked', false); return; }   // refresh content g_jqContent.replaceWith(jqNewContent); g_jqContent = jqNewContent; // for action=history ... if (g_wAction === 'history') { // ... attach click listeners and fake a click g_jqLi = g_jqContent.find('li'); g_jqLi.find('input[type="radio"]') .click(updateDiffRadios); updateDiffRadios; }   // go back to sleep g_jqImg.hide; g_hTimeout = window.setTimeout(onTick, getInterval); }

// process Ajax fail event function onFail(jqDummy, textStatus, errorThrown) {   g_self.message = 'onFail :: ' + textStatus + ' ' + errorThrown; g_jqInput.prop('checked', false); }

// handle timer events, function onTick {   g_hTimeout = 0; g_jqImg.show; // ajax defaults to window.location.href $.ajax({dataType: 'html'}) .done(onDone) .fail(onFail); }

// turn refresh on and off programmatically function toggle(state) {   if (!!g_jqInput &&      (typeof state === 'boolean') &&      (g_jqInput.prop('checked') !== state)) {     g_jqInput.click; } }

// init g_self before document.ready //  in case document.ready executes immediately g_self = {   interval : g_interval, message : 'Initializing', toggle : toggle, version : 'Version 1.4.1: 15 May 2015' };

$(function main {    var jqSpan, jqH1,        i, done,        actions =        [          'view',          'history'        ],        selectors =        [          '.mw-changeslist', // RecentChanges & Watchlist, all skins          '#pagehistory',    // action=history, all skins          '#mw-content-text' // all pages, all skins        ],        uriData =        [          'data:image/gif;base64,',          'R0lGODlhKwALAMIAAP///wAAAIKCggAAAP///////////////yH/C05FVFNDQVBF',          'Mi4wAwEAAAAh+QQFCgADACwAAAAAKwALAAADNDiyzPNQtRbhpHfWTCP/mgduYEl+',          'Z8mlGauG1ii+7bzadBejeL64sIfvAtQJR7yioHJsJQAAIfkEBQoAAgAsAAAAAAsA',          'CwAAAw0os8zaMMpJq70YPykSACH5BAUKAAEALAAAAAAbAAsAAAMtGLLM8TCMSalq',          'WERZ+8jY5nVgI45U6URoqmps+71n+8KQPKs1evejC2jzaAUSACH5BAEKAAEALBAA',          'AAAbAAsAAAMtGLLM8TCMSalqWERZ+8jY5nVgI45U6URoqmps+71n+8KQPKs1evej',          'C2jzaAUSADs='        ].join(''), htmlString = [         ' ',          'Auto-refresh: ', '', '', ' '       ].join('');

// allow listed actions, else deny done = false; for ( i = 0 ; (i < actions.length) && !done ; ++i ) {     done = (actions[i] === g_wAction); }   if (!done) {     g_self.message = 'main :: unsupported action : ' + g_wAction; return; }   // determine the "best" selector done = false; for ( i = 0 ; (i < selectors.length) && !done ; ++i ) {     g_selector = selectors[i]; g_jqContent = $(g_selector); done = (g_jqContent.length === 1); }   if (!done) {     g_self.message = 'main :: No suitable selector'; return; }   // span with all the new DOM elements jqSpan = $(htmlString); // checkbox checked, with handler g_jqInput = jqSpan.children('input') .prop('checked', true) .click(onCheck); // throbber, initially hidden g_jqImg = jqSpan.children('img') .hide; // add span to h1   jqH1 = $('h1:first:visible'); // Minerva made me do it    if (jqH1.length !== 1) {     g_self.message = 'main :: Problem with (h1:first:visible)'; g_jqInput = undefined; g_jqImg = undefined; return; }   jqH1.append(jqSpan); // done with DOM g_hTimeout = window.setTimeout(onTick, getInterval); g_self.message = 'OK'; });

return g_self; }(mediaWiki, jQuery));