Note: After saving, changes may not occur immediately. Click here to learn how to bypass your browser's cache.
  • Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (Cmd-R on a Mac)
  • Google Chrome: Press Ctrl-Shift-R (Cmd-Shift-R on a Mac)
  • Internet Explorer: Hold Ctrl while clicking Refresh, or press Ctrl-F5
  • Opera: Clear the cache in Tools → Preferences

For details and instructions about other browsers, see Wikipedia:Bypass your cache.

/*
 * Does a lookup two previous Page:* from the current, extract the rh from
 * its content, insert it in the header after trying to increase the rh page
 * number. See the FIXME comment(s) for caveats.
 *
 * Originally at User:Phe/Running header.js
 *
 * To use this script, add the following to your .js:
 *	 importScript('User:Inductiveload/Roman numerals.js');
 *	 importScript('User:Inductiveload/Running header.js');
 */

(function($, mw) {

  "use strict";

  // Roman numeral functions 
  // From http://blog.stevenlevithan.com/archives/javascript-roman-numeral-converter

  function int_to_roman(num) {
    if (Number(num) === 0) {
      return false;
    }

    var digits = String(Number(num)).split(""),
      key = ["", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM",
        "", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC",
        "", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"
      ],
      roman = "",
      i = 3;

    while (i--) {
      roman = (key[+digits.pop() + (i * 10)] || "") + roman;
    }

    return Array(+digits.join("") + 1).join("M") + roman;
  }

  function roman_to_int(in_str) {
    var str = in_str.toUpperCase(),
      validator =
      /^M*(?:D?C{0,3}|C[MD])(?:L?X{0,3}|X[CL])(?:V?I{0,3}|I[XV])$/,
      token = /[MDLV]|C[MD]?|X[CL]?|I[XV]?/g,
      key = {
        M: 1000,
        CM: 900,
        D: 500,
        CD: 400,
        C: 100,
        XC: 90,
        L: 50,
        XL: 40,
        X: 10,
        IX: 9,
        V: 5,
        IV: 4,
        I: 1
      },
      num = 0,
      m;
    if (!(str && validator.test(str)))
      return false;
    while ((m = token.exec(str)))
      num += key[m[0]];
    return num;
  }

  var RunningHeaderAutoComplete = function() {
    this.offsets = [2, 4, 1, -2]; //offsets to try, in order
    this.offset = 0;
  };

  RunningHeaderAutoComplete.prototype.increment_arabic = function(rh) {

    try {
      // now attempt to increment the number
      var r = new RegExp(
        "^(.*[\\|][\\[\\( ]*)(\\d+)([\\]\\)\\. ]*[\\|}].*)$");
      var regex_res = r.exec(rh);

      var page = Number(r.exec(rh)[2]) + 2;
      rh = regex_res[1] + String(page) + regex_res[3];

      this.add_rh(rh);

      return true;
    } catch (err) {
      return false;
    }
  };

  RunningHeaderAutoComplete.prototype.increment_roman = function(rh) {
    try {
      // now attempt to increment a roman numeral

      var r = new RegExp(
        "^(.*[\\|] *)([ivxlcm]+|[IVXLCM]+)(\\.? *[\\|}].*)$");
      var regex_res = r.exec(rh);

      var numeral = regex_res[2];

      var lower_case = false;
      if (numeral.charCodeAt(0) > 96 && numeral.charCodeAt(0) < 123) {
        lower_case = true;
      }


      var number = roman_to_int(numeral) + 2;

      numeral = int_to_roman(number);

      if (lower_case) {
        numeral = numeral.toLowerCase();
      }

      //insert the numeral back into the RH
      rh = regex_res[1] + numeral + regex_res[3];

      this.add_rh(rh);

      return true;
    } catch (err) {
      return false;
    }
  };

  RunningHeaderAutoComplete.prototype.add_rh = function(rh) {

    var r = new RegExp(/^\s*$/);

    if (r.test(this.header.value)) {
      this.header.value = rh;
    } else {
      this.header.value = rh + '\n' + this.header.value;
    }
  };

  RunningHeaderAutoComplete.prototype.fill_rh = function(data) {

    if (this.header && !data.query.pages["-1"]) {
      for (var ids in data.query.pages) {
        var content = data.query.pages[ids].revisions[0]['*'];
        var r = new RegExp("{" +
          "{([Rr]h|[Rr]unning header|[[Rr]unningHeader) *\\|.*}}");
        var match = r.exec(content);

        if (match) {
          // FIXME: needs to be tweaked, actually works only if the first
          // rh parameters consisting of only digits or roman numerals is the one to increment
          var rh = match[0];

          //try to increment the number
          var success = this.increment_arabic(rh);

          if (!success) { //we failed to get a number, see if there is a roman numeral
            success = this.increment_roman(rh);
          }

          if (!success) {
            //we didn't find a number to increment
            //set equal to the previous page's header, the user needs to edit by hand
            this.add_rh(rh);
          }

          if ($("prp_header").css('display') == 'none') {
            pr_toggle_visibility();
          }
        } else { //go back and try the next offset
          this.offset = this.offset + 1;
          if (this.offset < this.offsets.length) {
            this.try_offset();
          } else { //none of them have an RH, we failed!
            break;
          }
        }

        break;
      }
    }
  };

  RunningHeaderAutoComplete.prototype.set_running_header = function() {
    this.header = document.getElementsByName('wpHeaderTextbox')[0];

    if (!this.header) {
      return;
    }

    //remove existing RH
    this.header.value = this.header.value.replace(
      /{{([Rr]h|[Rr]unning ?[Hh]eader) *\|.*}}\n?/, '');

    this.try_offset();
  };

  RunningHeaderAutoComplete.prototype.try_offset = function() {

    var rhac = this;

    var r = new RegExp("(\\d+)$");
    var page = Number(r.exec(mw.config.get("wgPageName"))[1]) - this.offsets[
      this.offset];
    var pagename = mw.config.get("wgPageName").replace(/\d+$/g, page);

    mw.loader.using(['mediawiki.util']).then(function() {
      $.ajax({
        type: "GET",
        url: mw.util.wikiScript('api'),
        data: {
          'action': 'query',
          'prop': 'revisions',
          'rvprop': 'content',
          'titles': pagename,
          'format': 'json'
        },
        dataType: 'json',
        success: function(jsondata) {
          rhac.fill_rh(jsondata);
        }
      });
    });
  };

  var RunningHeaderAutoCompleteInstance = new RunningHeaderAutoComplete();

  /**
   * TemplateScript adds configurable templates and scripts to the sidebar, and adds an example regex editor.
   * @see https://meta.wikimedia.org/wiki/TemplateScript
   * @update-token [[File:pathoschild/templatescript.js]]
   */
  $.ajax(
    '//tools-static.wmflabs.org/meta/scripts/pathoschild.templatescript.js', {
      dataType: 'script',
      cache: true
    }).then(function() {
    pathoschild.TemplateScript.add([{
      name: 'Running header',
      script: function() {
        RunningHeaderAutoCompleteInstance.set_running_header();
      },
      forNamespaces: 'page'
    }]);
  });

}(jQuery, mediaWiki));