User:Gary/disambiguation navigator.js

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.
// Generated by CoffeeScript 2.1.1
(function() {
  /*
    DISAMBIGUATION NAVIGATOR
    Description: Makes navigation of disambiguation pages easier by associating
      each article with a keyboard key. Click on a key, such as "5", to click on
      the fifth article in a disambiguation page. Works with all numbers and
      letters on the keyboard.
  */
  var DisambiguationLinks;

  DisambiguationLinks = class DisambiguationLinks {
    static init() {
      var disambigBoxes, i, j, k, keys, letters, numbers, setIndexBox;
      disambigBoxes = $('#disambigbox');
      setIndexBox = $('#setindexbox');
      if ((!disambigBoxes.length && !setIndexBox.length) || window.mw.config.get('wgCanonicalNamespace') !== '' || window.mw.config.get('wgAction') !== 'view') {
        return false;
      }
      DisambiguationLinks.setCss();
      numbers = '1234567890';
      letters = 'abcdefghijklmnopqrstuvwxyz';
      // Loop through each disambiguation list item
      // Place either a number or letter next to each one
      DisambiguationLinks.setKeyForItems(letters);
      // 49 to 57, 48, 65 to 90
      keys = {};
      j = 0;
      k = 0;
      i = 49;
      while (i <= 57) {
        keys[i] = numbers.charAt(j);
        i++;
        j++;
      }
      keys[48] = numbers.charAt(j);
      i = 65;
      while (i <= 90) {
        keys[i] = letters.charAt(k);
        i++;
        k++;
      }
      // keys contains numbers and letters
      $.merge(keys, letters);
      return $('html').on('keydown', (event) => {
        if (!DisambiguationLinks.isModifierKey(event) && !DisambiguationLinks.isInInputField(event)) {
          DisambiguationLinks.goToDisambigLink(event, keys);
          return event.preventDefault();
        }
      });
    }

    static goToDisambigLink(e, keys) {
      var href, id;
      if (!keys[e.which]) {
        return false;
      }
      id = $('#disambig-link-' + keys[e.which]);
      href = id.attr('href');
      if (!href) {
        return false;
      }
      // Remove highlight from other links, then highlight the link's line
      $('.selected-disambig-link').removeClass('selected-disambig-link');
      id.closest('li').addClass('selected-disambig-link');
      // Go to the link
      return location.href = href;
    }

    static isInInputField(event) {
      if (['INPUT', 'TEXTAREA'].indexOf(event.target.nodeName) > -1) {
        return true;
      } else {
        return false;
      }
    }

    static isModifierKey(event) {
      if (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) {
        return true;
      } else {
        return false;
      }
    }

    static setCss() {
      return window.mw.util.addCSS('.disambig-link { color: #777; display: inline-block; width: 20px; } .catlinks .disambig-link { display: none; } .selected-disambig-link { background-color: #ff9; }');
    }

    static setKeyForItems(letters) {
      var charIndex, listIndex;
      listIndex = 1;
      charIndex = 0;
      return $('#bodyContent').find('li').each(function(index, element) {
        var article, links, styledLinks;
        article = $(element);
        // Don't use this LI if it's part of the TOC
        if (article.closest('#toc').length) {
          return true;
        }
        links = article.find('a');
        styledLinks = article.find('b > a, i > a, u > a');
        // There are no links in the current line.
        // The first link is wrapped in another tag.
        // The same as the above two but for styled links.
        if ((!links.length || links.first().parent()[0] !== article[0]) && (!styledLinks.length || styledLinks.first().parent().parent()[0] !== article[0])) {
          return true;
        }
        links.first().attr('id', 'disambig-link-' + listIndex);
        article.prepend('<span class="disambig-link">(' + listIndex + ')</span> ');
        // Increment index. Numbers from 1 to 0, then a to z. Covers 36 links.
        if (listIndex === 9) {
          listIndex = 0;
        } else if (listIndex === 0 || typeof listIndex === 'string') {
          listIndex = letters.charAt(charIndex);
          if (!listIndex) {
            return false;
          }
          charIndex++;
        } else {
          listIndex++;
        }
        if (listIndex === '') {
          return false;
        }
      });
    }

  };

  $(function() {
    return DisambiguationLinks.init();
  });

}).call(this);