Jump to content

User:Unready/ui.refresh.js

From Wikipedia, the free encyclopedia
This is an old revision of this page, as edited by Unready (talk | contribs) at 01:01, 30 April 2015 (Version 1.2.1: Don't run if wgAction != view). The present address (URL) is a permanent link to this revision, which may differ significantly from the current revision.
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.
/*
 * 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
 *
 * License: CC-BY-SA
 *   http://creativecommons.org/licenses/by-sa/3.0/
 */

if ( mediaWiki.config.get( 'wgAction' ) !== 'view' )
{
  return;
}

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

  var g_self,
      g_selector,
      g_jqContent, g_jqInput, g_jqImg,
      g_interval = 120, // default refresh interval (seconds)
      g_hTimeout = -1;  // cannot run = -1; okay to run = 0; running > 0

  // 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 < 2592000 )) // 30 days
    {
      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,
        i;

    // strip off body tags
    // use search, because match could be too big for replace
    i = htmlString.search( /<\s*body[^>]*>/i );
    if ( i === -1 )
    {
      g_self.message = 'onDone :: unable to find html body';
      g_jqInput.prop( 'checked', false );
      return;
    }
    htmlString = htmlString.substr( i )
      .replace( /^<\s*body[^>]*>\s*/i, '' )
      .replace( /\s*<\s*\/html[^>]*>\s*$/i, '' )
      .replace( /\s*<\s*\/body[^>]*>\s*$/i, '' );
    // force it to parse
    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;
    // 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 );
  }

  // init g_self before document.ready
  //   in case document.ready executes immediately
  g_self =
  {
    interval : g_interval,
    message : 'Initializing',
    version : 'Version 1.2.1: 30 April 2015'
  };

  $( function main()
  {
    var jqSpan,
        i, done,
        selectors =
        [
          '.mw-changeslist', // only on RecentChanges & Watchlist ?
          '#mw-content-text' // universally usable ?
        ],
        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 =
        [
          '<span style="font-size: 40%; margin: 5px; vertical-align: middle;">',
          '<label for="ui-refresh-input" title="Enable auto-refresh"',
          ' style="border-bottom: 1px dotted;">Auto-refresh:</label>',
          '<input id="ui-refresh-input" type="checkbox"',
          ' style="vertical-align: middle;">',
          '<img src="' + uriData + '" alt="Refreshing page">',
          '</span>'
        ].join( '' );

    // 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.find( 'input' )
      .prop( 'checked', true )
      .click( onCheck );
    // throbber, initially hidden
    g_jqImg = jqSpan.find( 'img' )
      .hide();
    // add span to h1
    if ( $( '#firstHeading:visible' ).append( jqSpan ).length !== 1 )
    {
      g_self.message = 'main :: Problem with ( #firstHeading:visible )';
      g_jqInput.prop( 'checked', false )
        .prop( 'disabled', true );
      return;
    }
    // done with DOM
    g_hTimeout = window.setTimeout( onTick, getInterval() );
    g_self.message = 'OK';
  });

  return g_self;
}( jQuery ));