User:Atelaes/TabbedLanguages.js

Note – after saving, you may have to bypass your browser’s cache to see the changes.

  • Mozilla / Firefox / Safari: hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (Command-R on a Macintosh);
  • Konqueror and Chrome: click Reload or press F5;
  • Opera: clear the cache in Tools → Preferences;
  • Internet Explorer: hold Ctrl while clicking Refresh, or press Ctrl-F5.

var tabbedLanguages = [];
var tabLangSectionNums = {};
var tabLangTOC = {};

/*
 * Modelled after function described at http://robertnyman.com/2005/11/07/the-ultimate-getelementsbyclassname/
 */

if (document.getElementsByClassName == undefined) {
  function homeBrewElementsByClassName(className) {
    var child;
    var results = [];
    var allChildren = this.getElementsByTagName('*');
    for (var a=0; a<allChildren.length; a++) {
      child = allChildren[a];
      childClass = child.className;
      regexTest = new RegExp('(^|\\s)' + className + '(\\s|$)');
      if (regexTest.test(childClass)) {
        results.push(child);
        }
      }
    return results;
    }
    Document.prototype.getElementsByClassName = homeBrewElementsByClassName;
    Element.prototype.getElementsByClassName = homeBrewElementsByClassName;
  }

/*
 *Taken from https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Array/indexOf
 */  

if (!Array.prototype.indexOf)
{
  Array.prototype.indexOf = function(elt /*, from*/)
  {
    var len = this.length >>> 0;

    var from = Number(arguments[1]) || 0;
    from = (from < 0)
         ? Math.ceil(from)
         : Math.floor(from);
    if (from < 0)
      from += len;

    for (; from < len; from++)
    {
      if (from in this &&
          this[from] === elt)
        return from;
    }
    return -1;
  };
} 
  
function makeLanguageTabs()
{
  if (wgNamespaceNumber == 0) {
    // Start by looking at all the L2 headers, which, in the main namespace, should all be languages.
    // Generate containers, placed immediately before the headers, 
    // and create a list of all the languages the page contains.
    // Also, remember the section numbers of the edit links, so we can recreate them after they're nuked.
    var languageContainer, languageContainers, li, languageLinks, toc;
    var EditSectionNumber = false;
    var language = false;
    var headerLanguageSection = false;
    var tabbedTOCPrefs = 'sectioned';  //Gotta find a way to institute a pref about that.
    var bodyContent = document.getElementById('bodyContent');
    for (var child = bodyContent.firstChild; child != null; child = child.nextSibling) {
      if (child.nodeName.toUpperCase() == 'H2') {
        EditSectionNumber = false;
        language = false;
        headerLanguageSection = false;
        var spans = child.getElementsByTagName('span');
        if (spans[1] && spans[1].className == 'mw-headline') {
          headerLanguageSection = spans[1];
          EditSectionNumber = spans[0].getElementsByTagName('a')[0].href.split('section=')[1];
          }
        else if (spans[0] && spans[0].className == 'mw-headline') {
          headerLanguageSection = spans[0];
          }
        if (headerLanguageSection) {  
          if (headerLanguageSection.getElementsByTagName('a').length > 0)  {
            language = headerLanguageSection.getElementsByTagName('a')[0].innerHTML;
            headerLanguageSection.innerHTML = '';
            }
          else {
            language = headerLanguageSection.innerHTML;
            headerLanguageSection.innerHTML = '';
            }
          }
        if (language) {
          tabbedLanguages.push(language);
          languageContainer = newNode('div', {'class' : 'languageContainer', 'id' : language + 'container'});
          bodyContent.insertBefore(languageContainer, child);
          if (EditSectionNumber) {
            tabLangSectionNums[language] = EditSectionNumber;
            }
          }
        }
      if (document.getElementById('toc')) {  
        toc = document.getElementById('toc');
        tocLangSections = toc.getElementsByClassName('toclevel-1');
        for (var c = 0; c < tocLangSections.length; c++) {
          if (tocLangSections[c].className.split('tocsection-')[1] == tabLangSectionNums[language]) {
            tabLangTOC[language] = tocLangSections[c];
            tocLangSections[c].parentNode.removeChild(tocLangSections[c]);
            }
          }
        }
      }
    if (document.getElementById('toc')) {
      var throwAway = VisibilityToggles.register('TOC',
        function show() {
          addCSSRule('#toc', 'display:table');
          },
        function hide() {
          addCSSRule('#toc', 'display:none');
          });
      }
      
    // Make the toggle.
    languageLinks = newNode('div', {'id' : 'languageLinks'});
    for (var b = 0; b < tabbedLanguages.length; b++) {
      language = tabbedLanguages[b];
      languageLink = newNode('a', language, {'href' : '#' + language});
      languageLinks.appendChild(newNode('span', languageLink, {'class' : 'unselectedTab'}));
      languageLinks.appendChild(newNode('wbr'));
      }
    // If there are section edit links, reproduce them, within a non-float container to make room.
    if (EditSectionNumber) {
      var LLEditSection = newNode('span', '[', newNode('a', 'edit', {'href' : 'emptyURL'}), ']', {'class' : 'editsection'});
      languageLinks.appendChild(newNode('span', LLEditSection, {'class' : 'LLeditContainer'}));
      }
    //Make the toggle so pretty that you want to walk over and buy it a drink.
    if (skin == 'vector') {
      addCSSRule('#languageLinks .unselectedTab', 'height:2.5em; padding:1.25em 0 .5em;\
      background-image:url("http://bits.wikimedia.org/skins-1.5/vector/images/tab-normal-fade.png?1"); \
      background-position:left bottom; background-repeat:repeat-x;');
      addCSSRule('#languageLinks .selectedTab', 'height:2.5em; padding:1.25em 0 .5em;');
      addCSSRule('#languageLinks .selectedTab a', 'cursor:pointer; color:#333333; height:2.5em; padding-left:0.4em; \
      padding-right:0.4em; line-height:3.1em; white-space:nowrap; padding-top:1.25em; padding-bottom:.5em; \
      background-image:url("http://bits.wikimedia.org/skins-1.5/vector/images/tab-break.png?1"); \
      background-position:right bottom; background-repeat:no-repeat;');
      addCSSRule('#languageLinks .unselectedTab a', 'cursor:pointer; color:#0645AD; height:2.5em; padding-left:0.4em; \
      padding-right:0.4em; line-height:3.1em; white-space:nowrap;  padding-top:1.25em; padding-bottom:.5em; \
      background-image:url("http://bits.wikimedia.org/skins-1.5/vector/images/tab-break.png?1"); \
      background-position:right bottom; background-repeat:no-repeat;');
      addCSSRule('.LLEditContainer', 'width : 3em;');
      }
    else {
      addCSSRule('#languageLinks .unselectedTab', 'line-height : 1.5em; display : inline; padding : 0 0.5em; \
      border : 1px solid #AAAAAA; background : #E8E8E8; white-space:nowrap;');
      addCSSRule('#languageLinks .selectedTab', 'line-height : 1.5em; display : inline; padding : 0 0.5em; \
      border : 1px solid #AAAAAA; border-bottom : none; background : white; white-space:nowrap');
      addCSSRule('#languageLinks a', 'color : #0645AD');
        }
      
    // Finally, stuff all the content into the appropriate language container.
    languageContainers = document.getElementsByClassName('languageContainer');
    var neighbor;
    for (var a = 0; a < languageContainers.length; a++) {
      languageContainer = languageContainers[a];
      if (a == 0) {
        bodyContent.insertBefore(languageLinks, languageContainer);
        }
      else {
        languageContainer.style.display = 'none';
        }
      while (true) {
        neighbor = languageContainer.nextSibling;
        if (!neighbor) {
          break;
          }
        else if (neighbor.className == 'languageContainer') {
          break;
          }
        else if (neighbor.className == 'printfooter' || neighbor.className == 'catlinks') {
          break;
          }
        else if (neighbor.nodeName.toUpperCase() == 'HR') {
          neighbor.parentNode.removeChild(neighbor);
          }
        else if (neighbor.nodeName.toUpperCase() == 'H2') {
          neighbor.parentNode.removeChild(neighbor);
          }
        else {
          languageContainer.appendChild(neighbor);
          }     
        }
      // Put a container in each for categories.  These will be populated later.  
      languageContainer.appendChild(newNode('div', newNode('text', languageContainer.id.split('container')[0] + ' categories: '), {'class' : 'catlinks'}));
      }
    // Now for category sorting, courtesy of Yair rand.
    var catDiv = document.getElementById('catlinks');
    var cats, catname;
    var catSections = catDiv.getElementsByTagName('div');
    for (var d=0; d<catSections.length; d++) {
      cats = catSections[d].getElementsByTagName('span');
      var langcurrent=0;
      while (cats.length > 0) {
        z=0;
        catname = cats[z].getElementsByTagName('a')[0].innerHTML;  
        while(catname.match(/derivations/)) {
          z+=1;
          catname = cats[z].getElementsByTagName('a')[0].innerHTML;
          }
        if(catname.match(new RegExp("^"+tabbedLanguages[langcurrent+1]))&&!catname.match(/letter\snames$/)&&!catname.match(/script\scharacters$/))
          {langcurrent+=1}
        var currentCatDiv = languageContainers[langcurrent].getElementsByClassName('catlinks')[0]
        if (currentCatDiv.lastChild.nodeName.toUpperCase() == 'SPAN') {
          currentCatDiv.appendChild(newNode('text', ' | '))
          }
        languageContainers[langcurrent].getElementsByClassName('catlinks')[0].appendChild(cats[0]);
        }
      }
    catDiv.parentNode.removeChild(catDiv);
    // If there's a location hash, the window may have scrolled down before we got a chance to reorganize everything.
    // If the destination was a sense id, switch to the right tab, and rescroll.
    // If it was simply a language, switch to the appropriate tab, and scroll back up.
    // If it was anything else (e.g. #Noun, #Etymology 1) , switch to the first tab, and try scrolling to it.
    // Note that the above method is not reliable, as the link author may have intended the "noun" of a different language.
    // However, it's unreliable anyway, even if tabbed languages does make it less reliable.
    if (window.location.hash != '') {
      var hash = decodeURI(window.location.hash).substr(1);
      if (hash.indexOf('-') > -1) {
        var destination = hash.split('-')[0].replace('_', ' ');
        toggleLanguageTabs(destination);
        window.location.hash = window.location.hash;
        }
      else if (tabbedLanguages.indexOf(hash.replace('_', ' ')) > -1) {
        var destination = hash.replace('_', ' ');
        toggleLanguageTabs(destination);
        if (window.scrollY) {
          window.scroll(0,0);
          }
        }
      else {
        toggleLanguageTabs(tabbedLanguages[0]);
        window.location.hash = window.location.hash;
        }
      }
    else {
      toggleLanguageTabs(tabbedLanguages[0]);
      }
    window.onhashchange = hashToggleLT;
    }
  }


function hashToggleLT () 
{
  var destination = decodeURI(window.location.hash.substr(1)).replace('_', ' ');
  toggleLanguageTabs(destination);
  }

function toggleLanguageTabs(language)
{
  if (tabbedLanguages.indexOf(language) != -1) {
    var languageButtons = document.getElementById('languageLinks').getElementsByTagName('span');
    for (var b = 0; b < languageButtons.length; b++) {
      if (languageButtons[b].firstChild.innerHTML == language) {
        languageButtons[b].className = 'selectedTab';
        }
      else if (languageButtons[b].className == 'selectedTab') {
        languageButtons[b].className = 'unselectedTab';
        }
      }
    var languageContainers = document.getElementsByClassName('languageContainer');
    for (var a = 0; a < languageContainers.length; a++) {
      if (languageContainers[a].id.indexOf(language) != 0) {
        languageContainers[a].style.display = 'none';
        }
      else {
        languageContainers[a].style.display = 'block';
        }
      }
    if (document.getElementById('languageLinks').getElementsByClassName('editsection')[0] != undefined) {
      var editSection = document.getElementById('languageLinks').getElementsByClassName('editsection')[0];
      var editSectionHref = '/w/index.php?title=' + wgPageName + '&action=edit&section=' + tabLangSectionNums[language];
      editSection.getElementsByTagName('a')[0].href = editSectionHref;
      }
    if (document.getElementById('toc')) {
      var emptyTOC = document.getElementById('toc').getElementsByTagName('ul')[0];
      emptyTOC.innerHTML = '';
      emptyTOC.appendChild(tabLangTOC[language].cloneNode(true));
      }
    }  
  }

$( makeLanguageTabs );