MediaWiki:Common.js: Difference between revisions

From Citizendium
Jump to navigation Jump to search
imported>ZachPruckowski
(fix the URLs Greg missed... (two index.php references removed))
(updating Google Analytics tag number)
 
(48 intermediate revisions by 6 users not shown)
Line 1: Line 1:
/** Tooltips and access keys ***************************************************
/* <nowiki> */
  *
  *  Ported straight from Wikipedia, substituted 'Citizendium' for both 'Wikipedia'
  *  and 'Wikimedia'--probably a lot of stuff is broken here
  *  Description: Adds tooltips and access keys to links part of the MediaWiki
  *              interface.
  *  Maintainers (on Wikipedia): [[User:Gwicke|Gwicke]]?, [[User:Simetrical|Simetrical]]?, [[User:Ruud Koot|Ruud Koot]]
  */
ta = new Object();
ta["n-mainpage"]            = new Array("z","Visit the main page");
ta["n-Main-page"]          = new Array("z","Visit the main page");
ta["n-Featured-content"]    = new Array("","Featured content — the best of Citizendium");
ta["n-help"]                = new Array("","The place to find out about Citizendium");
ta["n-contact"]            = new Array("","How to contact Citizendium");
ta["n-sitesupport"]        = new Array("","Help keep Citizendium running");
ta["t-print"]              = new Array("","Printable version of this page");
ta["t-permalink"]          = new Array("","Permanent link to this version of the page");
ta["t-cite"]                = new Array("","Cite this Citizendium article");
ta["ca-nstab-project"]      = new Array("c","View the project page");
ta["n-Contents"]            = new Array("","Guides to browsing Citizendium");


  /** Import module *************************************************************
  /** Import module *************************************************************
   *
   *
   *  Description: Includes a raw wiki page as javascript or CSS,  
   *  Description: Includes a raw wiki page as javascript or CSS, used for including user made modules.
  *              used for including user made modules.
   *   
   *  Maintainers: [[User:AzaToth]]
  *  Doesn't work in WebKit or IE7...
   */
   */
importedScripts = {}; // object keeping track of included scripts, so a script ain't included twice
var loadedScripts = {}; // included-scripts tracker
function importScript( page ) {
function importScript(page) {
    if( importedScripts[page] ) {
var url = wgScript + '?title=' + encodeURIComponent(page.replace(/ /g,'_')).replace(/%2F/ig,'/').replace(/%3A/ig,':') + '&action=raw&ctype=text/javascript';
        return;
    }
if (loadedScripts[url]) return null;
    importedScripts[page] = true;
loadedScripts[url] = true;
    var url = wgScriptPath
            + '/wiki?title='
var s = document.createElement('script');
            + encodeURIComponent( page.replace( ' ', '_' ) )
s.setAttribute('src',url);
            + '&action=raw&ctype=text/javascript';
s.setAttribute('type','text/javascript');
    var scriptElem = document.createElement( 'script' );
document.getElementsByTagName('head')[0].appendChild(s);
    scriptElem.setAttribute( 'src' , url );
}
    scriptElem.setAttribute( 'type' , 'text/javascript' );
 
    document.getElementsByTagName( 'head' )[0].appendChild( scriptElem );
}
   
   
  function importStylesheet( page ) {
  function importStylesheet( page ) {
Line 54: Line 32:
     document.getElementsByTagName( 'head' )[0].appendChild( styleElem );
     document.getElementsByTagName( 'head' )[0].appendChild( styleElem );
  }
  }
/* Import more specific scripts if necessary */
//if (wgAction == 'edit' || wgAction == 'submit')
//    importScript("MediaWiki:Common.js/edit.js");
//if (wgPageName == 'Special:Upload')
//    importScript("MediaWiki:Common.js/upload.js");
/** Extra toolbar options ******************************************************
  *
  *  Description: UNDOCUMENTED
  *  Maintainers:
  */
/* To disable this script, add    mwCustomEditButtons = [];    to [[Special:Mypage/Pinkwich5.js]] */
function imageButons(){
if (wgAction == 'edit' || wgAction == 'submit') {
/* Make the Image insertion button use the CZ image template */
mwEditButtons[5].speedTip = 'Image';
mwEditButtons[5].tagOpen = '{{Image|';
mwEditButtons[5].tagClose = '|right|250px|Image Caption}}';
/* Add extra image buttons */
if (mwCustomEditButtons) {
mwCustomEditButtons[mwCustomEditButtons.length] = {
"imageFile": "http://upload.wikimedia.org/wikipedia/en/c/c8/Button_redirect.png",
"speedTip": "Redirect",
"tagOpen": "#REDIRECT [[",
"tagClose": "]]",
"sampleText": "Insert text"};
mwCustomEditButtons[mwCustomEditButtons.length] = {
"imageFile": "http://upload.wikimedia.org/wikipedia/en/c/c9/Button_strike.png",
"speedTip": "Strike",
"tagOpen": "<s>",
"tagClose": "</s>",
"sampleText": "Strike-through text"};
mwCustomEditButtons[mwCustomEditButtons.length] = {
"imageFile": "http://upload.wikimedia.org/wikipedia/en/1/13/Button_enter.png",
"speedTip": "Line break",
"tagOpen": "<br />",
"tagClose": "",
"sampleText": ""};
mwCustomEditButtons[mwCustomEditButtons.length] = {
"imageFile": "http://upload.wikimedia.org/wikipedia/en/8/80/Button_upper_letter.png",
"speedTip": "Superscript",
"tagOpen": "<sup>",
"tagClose": "</sup>",
"sampleText": "Superscript text"};
mwCustomEditButtons[mwCustomEditButtons.length] = {
"imageFile": "http://upload.wikimedia.org/wikipedia/en/7/70/Button_lower_letter.png",
"speedTip": "Subscript",
"tagOpen": "<sub>",
"tagClose": "</sub>",
"sampleText": "Subscript text"};
mwCustomEditButtons[mwCustomEditButtons.length] = {
"imageFile": "http://upload.wikimedia.org/wikipedia/en/5/58/Button_small.png",
"speedTip": "Small",
"tagOpen": "<small>",
"tagClose": "</small>",
"sampleText": "Small Text"};
mwCustomEditButtons[mwCustomEditButtons.length] = {
"imageFile": "http://upload.wikimedia.org/wikipedia/en/6/60/Button_insert_table.png",
"speedTip": "Insert a table",
"tagOpen": '{| class="wikitable"\n|-\n',
"tagClose": "\n|}",
"sampleText": "! header 1\n! header 2\n! header 3\n|-\n| row 1, cell 1\n| row 1, cell 2\n| row 1, cell 3\n|-\n| row 2, cell 1\n| row 2, cell 2\n| row 2, cell 3"};
mwCustomEditButtons[mwCustomEditButtons.length] = {
"imageFile": "http://upload.wikimedia.org/wikipedia/commons/7/79/Button_reflink.png",
"speedTip": "Insert a reference",
"tagOpen": "<ref>",
"tagClose": "</ref>",
"sampleText": "Insert footnote text here"};
}
}
}
addOnloadHook(imageButons);
/** Upload Wizard ***************************************************
*
*  Adds many enhancements to the upload form
*
*  Maintainer : [[User:Caesar Schinas]]
*/
function uploadForm() {
if ((wgPageName == 'Special:Upload') && (wgUserLanguage != 'basic')) {
if ((document.getElementById('wpUploadDescription').value == '') && document.getElementById('preload')) {
document.getElementById('wpUploadDescription').value = document.getElementById('preload').innerHTML;
document.getElementById('preload').parentNode.innerHTML = 'Fill in all the details you know:';
}
if (wgUserLanguage == 'replace') {
document.getElementById('wpDestFile').parentNode.parentNode.style.display = 'none';
document.getElementById('wpUploadDescription').setAttribute('rows','5');
}
if ((document.getElementById('wpUploadDescription').value.indexOf('{{Image_Details') != -1) && (wgUserLanguage != 'advanced')) {
/* get an array of licences */
var license = document.getElementById('wpLicense');
var licenses = Array();
for (var i in license.childNodes) {
if (license.childNodes[i].nodeName == 'OPTION' && license.childNodes[i].value != '') {
licenses.push(license.childNodes[i].value);
}
}
/* if there is only one licence available select it and hide the input */
if (licenses.length == 1) {
license.value = licenses[0];
licenseSelectorCheck();
license.style.display = 'none';
}
/* Create individual fields for the image details */
var labels = {
'description' : 'Image description:',
'author' : 'Creator name:',
'copyright' : 'Copyright holder:',
'source' : 'Source:',
'date-created' : 'Date created:',
'pub-country' : 'Publication country:',
'notes' : 'Notes:',
'versions' : 'Other versions:'
};
var sig = '~~'+'~';
var summary = document.getElementById('wpUploadDescription');
var table = summary.parentNode.parentNode.parentNode;
var next = summary.parentNode.parentNode.nextSibling;
var args = Array();
if (summary.value.indexOf('Details|') != -1)
args = summary.value.substring(summary.value.indexOf('Details|')+8,summary.value.indexOf('\n')).split('|');
var details = summary.value.substring(summary.value.indexOf('\n|')+2,summary.value.indexOf('\n}}')).split('\n|');
for (var i in details) {
details[i] = details[i].split('=');
}
for (var i in details) {
var tr = document.createElement('tr');
var td1 = document.createElement('td');
var td2 = document.createElement('td');
tr.appendChild(td1);
tr.appendChild(td2);
td1.setAttribute('class','mw-label');
td2.setAttribute('class','mw-input');
td1.style.width = '12em';
// added by dnessett on 3/12/2010 to increase visible region for Notes
if ((details[i][0].replace(/^\s+|\s+$/g,'')) == 'notes') {
var textarea = document.createElement('textarea');
textarea.setAttribute('wrap','virtual');
textarea.setAttribute('id',details[i][0].replace(/^\s+|\s+$/g,''));
textarea.setAttribute('name',details[i][0].replace(/^\s+|\s+$/g,''));
textarea.setAttribute('value',details[i][1].replace(/^\s+|\s+$/g,''));
textarea.setAttribute('rows','5');
td2.appendChild(textarea);
textarea.style.width = '90%';
} else {
var input = document.createElement('input');
input.setAttribute('type','text');
input.setAttribute('id',details[i][0].replace(/^\s+|\s+$/g,''));
input.setAttribute('name',details[i][0].replace(/^\s+|\s+$/g,''));
input.setAttribute('value',details[i][1].replace(/^\s+|\s+$/g,''));
td2.appendChild(input);
input.style.width = '90%';
}
var label = document.createElement('label');
label.setAttribute('for',details[i][0].replace(/^\s+|\s+$/g,''));
label.appendChild(document.createTextNode(labels[details[i][0].replace(/^\s+|\s+$/g,'')]));
td1.appendChild(label);
table.insertBefore(tr,next);
if ((details[i][0].replace(/^\s+|\s+$/g,'')) == 'author' && (details[i][1].replace(/^\s+|\s+$/g,'') == sig)) tr.style.display = 'none';
}
summary.parentNode.parentNode.style.display = 'none';
var septr = document.createElement('tr');
var septd = document.createElement('td');
septr.appendChild(septd);
septd.appendChild(document.createElement('br'));
table.insertBefore(septr,summary.parentNode.parentNode);
document.getElementById('mw-upload-form').onsubmit = function(){
var temp = '{{Image_Details';
for (i in args) {
temp += '|' + args[i];
}
for (i in details) {
temp += '\n|' + details[i][0] + '= ' + document.getElementById(details[i][0].replace(/^\s+|\s+$/g,'')).value;
}
temp += '\n}}';
summary.value = temp;
if (license.value == '') {
alert('Please select a licence!');
return false;
}
}
}
}
}
addOnloadHook(uploadForm);
function uploadReplaceLink () {
if (wgNamespaceNumber == 6) {
var a = document.getElementsByTagName('a');
for (var i in a) {
if (a[i].getAttribute('href') && a[i].getAttribute('href').indexOf('wpDestFile') != -1)
a[i].setAttribute('href', a[i].getAttribute('href') + '&uselang=replace');
}
}
}
addOnloadHook(uploadReplaceLink);
/** Credit Line Editor ***************************************************
*
*  Creates a simple form for editing credit lines.
*
*  Maintainer : [[User:Caesar Schinas]]
*/
function creditEdit() {
  if ((wgPageName.indexOf('/credit') != -1) && (wgAction == 'edit')) {
var text = document.getElementById('wpTextbox1').value;
if (text.indexOf('{{creditline') == -1) return false;
var args = text.substring(text.indexOf('|')+1,text.indexOf('}}')).split('|');
var bodycontent = document.getElementById('bodycontent');
bodycontent.setAttribute('id','bodycontent-old');
bodycontent.style.display = 'none';
var div = document.createElement('div');
bodycontent.parentNode.appendChild(div);
div.setAttribute('id','bodycontent');
div.innerHTML = "\
<table>\n\
  <tr>\n\
<th style='text-align:right; padding-right:1em;'>\n\
  <label for='licence'>Licence Type</label>\n\
</th>\n\
<td>\n\
  <select id='licence' name='licence' style='width:25em;'>\n\
<option value='C'>C - Copyright, used by permission</option>\n\
<option value='CC'>CC - Creative Commons</option>\n\
<option value='GNU'>GNU</option>\n\
<option value='PD'>PD - Public Domain</option>\n\
<option value='other' selected='selected'>Other (please only enter letters)</option>\n\
  </select>\n\
  <input type='text' id='licence-other' name='imagetype-other' />\n\
</td>\n\
  </tr>\n\
  <tr>\n\
<th style='text-align:right; padding-right:1em;'>\n\
  <label for='imagetype'>Image Type</label>\n\
</th>\n\
<td>\n\
  <select id='imagetype' name='imagetype' style='width:25em;'>\n\
<option value='Image'>Image</option>\n\
<option value='Photo'>Photo</option>\n\
<option value='Diagram'>Diagram</option>\n\
<option value='Drawing'>Drawing</option>\n\
<option value='Painting'>Painting</option>\n\
<option value='Artwork'>Artwork</option>\n\
<option value='other' selected='selected'>Other</option>\n\
  </select>\n\
  <input type='text' id='imagetype-other' name='imagetype-other' />\n\
</td>\n\
  </tr>\n\
  <tr>\n\
<th style='text-align:right; padding-right:1em;'>\n\
  <label for='author'>Author</label>\n\
</th>\n\
<td>\n\
  <input type='text' id='author' name='author' style='width:25em;' />\n\
</td>\n\
  </tr>\n\
  <tr>\n\
<th>\n\
</th>\n\
<td>\n\
  <input type='button' id='save' value='Save Credit Line' />\n\
</td>\n\
  </tr>\n\
</table>\n\
";
// set form field values
if (args[0] && args[0] != 'licence') {
  document.getElementById('licence-other').value = args[0];
  for (var i=0; i<4; i++) {
if (args[0].toUpperCase() == Array('CC','GNU','PD','C')[i]) {
document.getElementById('licence').value = args[0].toUpperCase();
document.getElementById('licence-other').style.display = 'none';
}
  }
} else {
  document.getElementById('licence').value = 'C';
  document.getElementById('licence-other').style.display = 'none';
}
if (args[1] && args[1] != 'imagetype') {
  document.getElementById('imagetype-other').value = args[1];
  for (var i=0; i<6; i++) {
if (args[1].toLowerCase() == Array('Image','Photo','Diagram','Drawing','Painting','Artwork')[i].toLowerCase()) {
document.getElementById('imagetype').value = Array('Image','Photo','Diagram','Drawing','Painting','Artwork')[i];
document.getElementById('imagetype-other').style.display = 'none';
}
  }
} else {
  document.getElementById('imagetype').value = 'Image';
  document.getElementById('imagetype-other').style.display = 'none';
}
if (args[2] && args[2] != 'author')
  document.getElementById('author').value = args[2];
// onchange handlers for selects
document.getElementById('licence').onchange = function() {
  if (document.getElementById('licence').value == 'other')
document.getElementById('licence-other').style.display = 'inline';
  else
document.getElementById('licence-other').style.display = 'none';
}
document.getElementById('imagetype').onchange = function() {
  if (document.getElementById('imagetype').value == 'other')
document.getElementById('imagetype-other').style.display = 'inline';
  else
document.getElementById('imagetype-other').style.display = 'none';
}
// save the credit line
document.getElementById('save').onclick = function() {
  var value = '{{creditline';
 
  if (document.getElementById('licence').value != 'other')
value += '|' + document.getElementById('licence').value;
  else if (document.getElementById('licence-other').value != '')
value += '|' + document.getElementById('licence-other').value;
 
  if (document.getElementById('imagetype').value != 'Image' || document.getElementById('author').value != '') {
if (document.getElementById('imagetype').value != 'other')
value += '|' + document.getElementById('imagetype').value;
else if (document.getElementById('imagetype-other').value != '')
value += '|' + document.getElementById('imagetype-other').value;
if (document.getElementById('author').value != '')
value += '|' + document.getElementById('author').value;
  }
 
  value += '}}';
 
  document.getElementById('wpTextbox1').value = value;
  document.getElementById('editform').submit();
}
  }
}
addOnloadHook(creditEdit);


  /* Test if an element has a certain class **************************************
  /* Test if an element has a certain class **************************************
Line 68: Line 425:
  })();
  })();


/** Internet Explorer bug fix **************************************************
  *
  *  Description: UNDOCUMENTED
  *  Maintainers: [[User:Tom-]]?
  */
if (window.showModalDialog && document.compatMode && document.compatMode == "CSS1Compat")
{
  var oldWidth;
  var docEl = document.documentElement;
  function fixIEScroll()
  {
    if (!oldWidth || docEl.clientWidth > oldWidth)
      doFixIEScroll();
    else
      setTimeout(doFixIEScroll, 1);
 
    oldWidth = docEl.clientWidth;
  }
  function doFixIEScroll() {
    docEl.style.overflowX = (docEl.scrollWidth - docEl.clientWidth < 4) ? "hidden" : "";
  }
  document.attachEvent("onreadystatechange", fixIEScroll);
  attachEvent("onresize", fixIEScroll);
}


/** Interwiki links to featured articles ***************************************
 
  *
  *  Description: Highlights interwiki links to featured articles (or
  *              equivalents) by changing the bullet before the interwiki link
  *              into a star.
  *  Maintainers: [[User:R. Koot]]
  */
function LinkFA()
{
    if ( document.getElementById( "p-lang" ) ) {
        var InterwikiLinks = document.getElementById( "p-lang" ).getElementsByTagName( "li" );
        for ( var i = 0; i < InterwikiLinks.length; i++ ) {
            if ( document.getElementById( InterwikiLinks[i].className + "-fa" ) ) {
                InterwikiLinks[i].className += " FA"
                InterwikiLinks[i].title = "This is a featured article in another language.";
            }
        }
    }
}
   
   
addOnloadHook( LinkFA );


  /** Collapsible tables *********************************************************
  /** Collapsible tables *********************************************************
Line 200: Line 508:
     }
     }
  }
  }
  addOnloadHook( createCollapseButtons );
  addOnloadHook( createCollapseButtons );


/** Dynamic Navigation Bars (experimental) *************************************
  *
  *  Description: See [[Citizendium:NavFrame]].
  *  Maintainers: UNMAINTAINED
  */
  // set up the words in your language
  var NavigationBarHide = '[' + collapseCaption + ']';
  var NavigationBarShow = '[' + expandCaption + ']';
 
  // set up max count of Navigation Bars on page,
  // if there are more, all will be hidden
  // NavigationBarShowDefault = 0; // all bars will be hidden
  // NavigationBarShowDefault = 1; // on pages with more than 1 bar all bars will be hidden
  var NavigationBarShowDefault = autoCollapse;
 
 
  // shows and hides content and picture (if available) of navigation bars
  // Parameters:
  //    indexNavigationBar: the index of navigation bar to be toggled
  function toggleNavigationBar(indexNavigationBar)
  {
    var NavToggle = document.getElementById("NavToggle" + indexNavigationBar);
    var NavFrame = document.getElementById("NavFrame" + indexNavigationBar);
 
    if (!NavFrame || !NavToggle) {
        return false;
    }
 
    // if shown now
    if (NavToggle.firstChild.data == NavigationBarHide) {
        for (
                var NavChild = NavFrame.firstChild;
                NavChild != null;
                NavChild = NavChild.nextSibling
            ) {
            if ( hasClass( NavChild, 'NavPic' ) ) {
                NavChild.style.display = 'none';
            }
            if ( hasClass( NavChild, 'NavContent') ) {
                NavChild.style.display = 'none';
            }
        }
    NavToggle.firstChild.data = NavigationBarShow;
 
    // if hidden now
    } else if (NavToggle.firstChild.data == NavigationBarShow) {
        for (
                var NavChild = NavFrame.firstChild;
                NavChild != null;
                NavChild = NavChild.nextSibling
            ) {
            if (hasClass(NavChild, 'NavPic')) {
                NavChild.style.display = 'block';
            }
            if (hasClass(NavChild, 'NavContent')) {
                NavChild.style.display = 'block';
            }
        }
    NavToggle.firstChild.data = NavigationBarHide;
    }
  }
 
  // adds show/hide-button to navigation bars
  function createNavigationBarToggleButton()
  {
    var indexNavigationBar = 0;
    // iterate over all < div >-elements
    var divs = document.getElementsByTagName("div");
    for(
            var i=0;
            NavFrame = divs[i];
            i++
        ) {
        // if found a navigation bar
        if (hasClass(NavFrame, "NavFrame")) {
 
            indexNavigationBar++;
            var NavToggle = document.createElement("a");
            NavToggle.className = 'NavToggle';
            NavToggle.setAttribute('id', 'NavToggle' + indexNavigationBar);
            NavToggle.setAttribute('href', 'javascript:toggleNavigationBar(' + indexNavigationBar + ');');
           
            var NavToggleText = document.createTextNode(NavigationBarHide);
            NavToggle.appendChild(NavToggleText);
            // Find the NavHead and attach the toggle link (Must be this complicated because Moz's firstChild handling is borked)
            for(
              var j=0;
              j < NavFrame.childNodes.length;
              j++
            ) {
              if (hasClass(NavFrame.childNodes[j], "NavHead")) {
                NavFrame.childNodes[j].appendChild(NavToggle);
              }
            }
            NavFrame.setAttribute('id', 'NavFrame' + indexNavigationBar);
        }
    }
    // if more Navigation Bars found than Default: hide all
    if (NavigationBarShowDefault < indexNavigationBar) {
        for(
                var i=1;
                i<=indexNavigationBar;
                i++
        ) {
            toggleNavigationBar(i);
        }
    }
 
  }
 
  addOnloadHook( createNavigationBarToggleButton );
/** Main Page layout fixes *********************************************************
  *
  *  Description:        Various layout fixes for the main page, including an
  *                      additional link to the complete list of languages available
  *                      and the renaming of the 'Article' to to 'Main Page'.
  *  Maintainers:        [[User:AzaToth]], [[User:R. Koot]]
  */
function mainPageRenameNamespaceTab() {
    try {
        var Node = document.getElementById( 'ca-nstab-main' ).firstChild;
        if ( Node.textContent ) {      // Per DOM Level 3
            Node.textContent = 'Main Page';
        } else if ( Node.innerText ) { // IE doesn't handle .textContent
            Node.innerText = 'Main Page';
        } else {                      // Fallback
            Node.replaceChild( Node.firstChild, document.createTextNode( 'Main Page' ) );
        }
    } catch(e) {
        // bailing out!
    }
}
function mainPageAppendCompleteListLink() {
    try {
        var node = document.getElementById( "p-lang" )
                            .getElementsByTagName('div')[0]
                            .getElementsByTagName('ul')[0];
        var aNode = document.createElement( 'a' );
        var liNode = document.createElement( 'li' );
        aNode.appendChild( document.createTextNode( 'Complete list' ) );
        aNode.setAttribute( 'href' , 'http://meta.citizendium.org/wiki/List_of_Citizendiums' );
        liNode.appendChild( aNode );
        liNode.className = 'interwiki-completelist';
        node.appendChild( liNode );
      } catch(e) {
        // lets just ignore what's happened
        return;
    }
}
if ( wgTitle == 'Main Page' && ( wgNamespaceNumber == 0 || wgNamespaceNumber == 1 ) ) {
        addOnloadHook( mainPageRenameNamespaceTab );
}
if ( wgTitle == 'Main Page' && wgNamespaceNumber == 0 ) {
        addOnloadHook( mainPageAppendCompleteListLink );
}
/** Extra toolbar options ****************************************************** <nowiki>
  *
  *  Description: UNDOCUMENTED
  *  Maintainers: [[User:MarkS]]?, [[User:Voice of All]], [[User:R. Koot]]
  */
//This is a modified copy of a script by User:MarkS for extra features added by User:Voice of All.
// This is based on the original code on Citizendium:Tools/Editing tools
// To disable this script, add <code>mwCustomEditButtons = [];<code> to [[Special:Mypage/monobook.js]]
if (mwCustomEditButtons) {
  mwCustomEditButtons[mwCustomEditButtons.length] = {
    "imageFile": "http://upload.citizendium.org/Citizendium/en/c/c8/Button_redirect.png",
    "speedTip": "Redirect",
    "tagOpen": "#REDIRECT [[",
    "tagClose": "]]",
    "sampleText": "Insert text"};
  mwCustomEditButtons[mwCustomEditButtons.length] = {
    "imageFile": "http://upload.citizendium.org/Citizendium/en/c/c9/Button_strike.png",
    "speedTip": "Strike",
    "tagOpen": "<s>",
    "tagClose": "</s>",
    "sampleText": "Strike-through text"};
  mwCustomEditButtons[mwCustomEditButtons.length] = {
    "imageFile": "http://upload.citizendium.org/Citizendium/en/1/13/Button_enter.png",
    "speedTip": "Line break",
    "tagOpen": "<br />",
    "tagClose": "",
    "sampleText": ""};
  mwCustomEditButtons[mwCustomEditButtons.length] = {
    "imageFile": "http://upload.citizendium.org/Citizendium/en/8/80/Button_upper_letter.png",
    "speedTip": "Superscript",
    "tagOpen": "<sup>",
    "tagClose": "</sup>",
    "sampleText": "Superscript text"};
  mwCustomEditButtons[mwCustomEditButtons.length] = {
    "imageFile": "http://upload.citizendium.org/Citizendium/en/7/70/Button_lower_letter.png",
    "speedTip": "Subscript",
    "tagOpen": "<sub>",
    "tagClose": "</sub>",
    "sampleText": "Subscript text"};
  mwCustomEditButtons[mwCustomEditButtons.length] = {
    "imageFile": "http://upload.citizendium.org/Citizendium/en/5/58/Button_small.png",
    "speedTip": "Small",
    "tagOpen": "<small>",
    "tagClose": "</small>",
    "sampleText": "Small Text"};
  mwCustomEditButtons[mwCustomEditButtons.length] = {
    "imageFile": "http://upload.citizendium.org/Citizendium/en/3/34/Button_hide_comment.png",
    "speedTip": "Insert hidden Comment",
    "tagOpen": "<!-- ",
    "tagClose": " -->",
    "sampleText": "Comment"};
  mwCustomEditButtons[mwCustomEditButtons.length] = {
    "imageFile": "http://upload.citizendium.org/Citizendium/en/1/12/Button_gallery.png",
    "speedTip": "Insert a picture gallery",
    "tagOpen": "\n<gallery>\n",
    "tagClose": "\n</gallery>",
    "sampleText": "Image:Example.jpg|Caption1\nImage:Example.jpg|Caption2"};
  mwCustomEditButtons[mwCustomEditButtons.length] = {
    "imageFile": "http://upload.citizendium.org/Citizendium/en/f/fd/Button_blockquote.png",
    "speedTip": "Insert block of quoted text",
    "tagOpen": "<blockquote>\n",
    "tagClose": "\n</blockquote>",
    "sampleText": "Block quote"};
  mwCustomEditButtons[mwCustomEditButtons.length] = {
    "imageFile": "http://upload.citizendium.org/Citizendium/en/6/60/Button_insert_table.png",
    "speedTip": "Insert a table",
    "tagOpen": '{| class="wikitable"\n|-\n',
    "tagClose": "\n|}",
    "sampleText": "! header 1\n! header 2\n! header 3\n|-\n| row 1, cell 1\n| row 1, cell 2\n| row 1, cell 3\n|-\n| row 2, cell 1\n| row 2, cell 2\n| row 2, cell 3"};
}
/*</nowiki>*/
/** pageview counter ***********************************************************
  *
  *  Description: Please talk to de:User:LeonWeber before changing anything or
  *              if there are any issues with that.
  *  Maintainers: [[:de:User:LeonWeber]]?
  */
 
  // this should be adjusted to a good value.
  // BE CAREFUL, you will break zedler if it's too low!
  // And then DaB. will kill Leon :-(
  var disable_counter = 0;
  var counter_factor = 6000;
 
  function pgcounter_setup()
  {
  if(disable_counter == 0)
  {
  var url = window.location.href;
  if(Math.floor(Math.random()*counter_factor)==42)  // the probability thing
  {
  if(wgIsArticle==true || wgArticleId==0) // do not count history pages etc.
  {
  var pgcountNs = wgCanonicalNamespace;
  if(wgCanonicalNamespace=="")
  {
  pgcountNs = "0";
  }
  var cnt_url = "http://pgcount.citizendium.de/index.png?ns=" + pgcountNs + "&title=" + encodeURI(wgTitle) + "&factor=" + counter_factor +"&wiki=enwiki";
  var img = new Image();
  img.src = cnt_url;
  }
  }
  }
  }
  // Do not use aOnloadFunctions[aOnloadFunctions.length] = pgcounter_setup;, some browsers don't like that.
  pgcounter_setup();
/** "Technical restrictions" title fix *****************************************
*
* Description:
* Maintainers: User:Interiot, User:Mets501, User:Freakofnurture
*/
//
// For pages that have something like Template:Lowercase, replace the title, but only if it is cut-and-pasteable as a valid wikilink.
// (for instance iPod's title is updated. But [[C#]] is not an equivalent
// wikilink, so [[C Sharp]] doesn't have its main title changed)
// Likewise for users who have selected the U.K. date format ("1 March") the 
// titles of day-of-the-year articles will appear in that style. Users with any
// other date setting are not affected.
//
// The function looks for a banner like this:
// &lt;div id="RealTitleBanner"&gt;  ... &lt;span id="RealTitle"&gt;title&lt;/span&gt; ... &lt;/div&gt;
// An element with id=DisableRealTitle disables the function.
//
var disableRealTitle = 0; // users can set disableRealTitle = 1 locally to disable.
if (wgIsArticle) { // don't display the RealTitle when editing, since it is apparently inconsistent (doesn't show when editing sections, doesn't show when not previewing)
  addOnloadHook(function() {
    try {
        var realTitleBanner = document.getElementById("RealTitleBanner");
        if (realTitleBanner && !document.getElementById("DisableRealTitle") && !disableRealTitle ) {
            var realTitle = document.getElementById("RealTitle");
            if (realTitle) {
                var realTitleHTML = realTitle.innerHTML;
                realTitleText = pickUpText(realTitle);
                var isPasteable = 0;
                //var containsHTML = /</.test(realTitleHTML);    // contains ANY HTML
                var containsTooMuchHTML = /</.test( realTitleHTML.replace(/<\/?(sub|sup|small|big)>/gi, "") ); // contains HTML that will be ignored when cut-n-pasted as a wikilink
                // calculate whether the title is pasteable
                var verifyTitle = realTitleText.replace(/^ +/, "");      // trim left spaces
                verifyTitle = verifyTitle.charAt(0).toUpperCase() + verifyTitle.substring(1, verifyTitle.length);    // uppercase first character
                // if the namespace prefix is there, remove it on our verification copy. If it isn't there, add it to the original realValue copy.
                if (wgNamespaceNumber != 0) {
                    if (wgCanonicalNamespace == verifyTitle.substr(0, wgCanonicalNamespace.length).replace(/ /g, "_") && verifyTitle.charAt(wgCanonicalNamespace.length) == ":") {
                        verifyTitle = verifyTitle.substr(wgCanonicalNamespace.length + 1);
                    } else {
                        realTitleText = wgCanonicalNamespace.replace(/_/g, " ") + ":" + realTitleText;
                        realTitleHTML = wgCanonicalNamespace.replace(/_/g, " ") + ":" + realTitleHTML;
                    }
                }
                // verify whether wgTitle matches
                verifyTitle = verifyTitle.replace(/[\s_]+/g, " ");      // underscores and multiple spaces to single spaces
                verifyTitle = verifyTitle.replace(/^\s+/, "").replace(/\s+$/, "");        // trim left and right spaces
                verifyTitle = verifyTitle.charAt(0).toUpperCase() + verifyTitle.substring(1, verifyTitle.length);    // uppercase first character
                if ( (verifyTitle == wgTitle) || (verifyTitle == wgTitle.replace(/^(.+)?(January|February|March|April|May|June|July|August|September|October|November|December)\s+([12]?[0-9]|3[0123])([^\d].*)?$/g, "$1$3 $2$4") )) isPasteable = 1;
                var h1 = document.getElementsByTagName("h1")[0];
                if (h1 && isPasteable) {
                    h1.innerHTML = containsTooMuchHTML ? realTitleText : realTitleHTML;
                    if (!containsTooMuchHTML)
                        realTitleBanner.style.display = "none";
                }
                document.title = realTitleText + " - Citizendium, the free encyclopedia";
            }
        }
    } catch (e) {
        /* Something went wrong. */
    }
  });
}
// similar to innerHTML, but only returns the text portions of the insides, excludes HTML
function pickUpText(aParentElement) {
var str = "";
function pickUpTextInternal(aElement) {
  var child = aElement.firstChild;
  while (child) {
  if (child.nodeType == 1)    // ELEMENT_NODE
    pickUpTextInternal(child);
  else if (child.nodeType == 3)  // TEXT_NODE
    str += child.nodeValue;
  child = child.nextSibling;
  }
}
  pickUpTextInternal(aParentElement);
  return str;
}
//fix edit summary prompt for undo
//this code fixes the fact that the undo function combined with the "no edit summary prompter" causes problems if leaving the
//edit summary unchanged
//this was added by [[User:Deskana]], code by [[User:Tra]]
addOnloadHook(function () {
  if (document.location.search.indexOf("undo=") != -1
  && document.getElementsByName('wpAutoSummary')[0]) {
    document.getElementsByName('wpAutoSummary')[0].value='';
  }
})


  /** Add dismiss button to watchlist-message *************************************
  /** Add dismiss button to watchlist-message *************************************
Line 638: Line 565:
  }
  }


  /** Main Page deletion image *******************************************************
 
  *
 
  Description: If the Main Page does not exist (i.e., it's been deleted) then insert an image
// MediaWiki JavaScript support functions
  *              instead of showing the "page does not exist" text.
 
  *  Created by: [[User:Mark]], with invaluable help from [[User:Pathoschild]]
var clientPC = navigator.userAgent.toLowerCase(); // Get client info
  */
var is_gecko = ((clientPC.indexOf('gecko')!=-1) && (clientPC.indexOf('spoofer')==-1)
                && (clientPC.indexOf('khtml') == -1) && (clientPC.indexOf('netscape/7.0')==-1));
var is_safari = ((clientPC.indexOf('applewebkit')!=-1) && (clientPC.indexOf('spoofer')==-1));
var is_khtml = (navigator.vendor == 'KDE' || ( document.childNodes && !document.all && !navigator.taintEnabled ));
// For accesskeys
var is_ff2_win = (clientPC.indexOf('firefox/2')!=-1 || clientPC.indexOf('minefield/3')!=-1) && clientPC.indexOf('windows')!=-1;
var is_ff2_x11 = (clientPC.indexOf('firefox/2')!=-1 || clientPC.indexOf('minefield/3')!=-1) && clientPC.indexOf('x11')!=-1;
if (clientPC.indexOf('opera') != -1) {
var is_opera = true;
var is_opera_preseven = (window.opera && !document.childNodes);
var is_opera_seven = (window.opera && document.childNodes);
var is_opera_95 = (clientPC.search(/opera\/(9.[5-9]|[1-9][0-9])/)!=-1);
}
 
// Global external objects used by this script.
/*extern ta, stylepath, skin */
 
// add any onload functions in this hook (please don't hard-code any events in the xhtml source)
var doneOnloadHook;
 
if (!window.onloadFuncts) {
var onloadFuncts = [];
}
 
function addOnloadHook(hookFunct) {
// Allows add-on scripts to add onload functions
onloadFuncts[onloadFuncts.length] = hookFunct;
}
 
function hookEvent(hookName, hookFunct) {
if (window.addEventListener) {
window.addEventListener(hookName, hookFunct, false);
} else if (window.attachEvent) {
window.attachEvent("on" + hookName, hookFunct);
}
}
 
// document.write special stylesheet links
if (typeof stylepath != 'undefined' && typeof skin != 'undefined') {
if (is_opera_preseven) {
document.write('<link rel="stylesheet" type="text/css" href="'+stylepath+'/'+skin+'/Opera6Fixes.css">');
} else if (is_opera_seven && !is_opera_95) {
document.write('<link rel="stylesheet" type="text/css" href="'+stylepath+'/'+skin+'/Opera7Fixes.css">');
} else if (is_opera_95) {
document.write('<link rel="stylesheet" type="text/css" href="'+stylepath+'/'+skin+'/Opera95Fixes.css">');
} else if (is_khtml) {
document.write('<link rel="stylesheet" type="text/css" href="'+stylepath+'/'+skin+'/KHTMLFixes.css">');
}
}
 
if (wgBreakFrames) {
// Un-trap us from framesets
if (window.top != window) {
window.top.location = window.location;
}
}
 
// for enhanced RecentChanges
function toggleVisibility(_levelId, _otherId, _linkId) {
var thisLevel = document.getElementById(_levelId);
var otherLevel = document.getElementById(_otherId);
var linkLevel = document.getElementById(_linkId);
if (thisLevel.style.display == 'none') {
thisLevel.style.display = 'block';
otherLevel.style.display = 'none';
linkLevel.style.display = 'inline';
} else {
thisLevel.style.display = 'none';
otherLevel.style.display = 'inline';
linkLevel.style.display = 'none';
}
}
 
function historyRadios(parent) {
var inputs = parent.getElementsByTagName('input');
var radios = [];
for (var i = 0; i < inputs.length; i++) {
if (inputs[i].name == "diff" || inputs[i].name == "oldid") {
radios[radios.length] = inputs[i];
}
}
return radios;
}
 
// check selection and tweak visibility/class onclick
function diffcheck() {
var dli = false; // the li where the diff radio is checked
var oli = false; // the li where the oldid radio is checked
var hf = document.getElementById('pagehistory');
if (!hf) {
return true;
}
var lis = hf.getElementsByTagName('li');
for (var i=0;i<lis.length;i++) {
var inputs = historyRadios(lis[i]);
if (inputs[1] && inputs[0]) {
if (inputs[1].checked || inputs[0].checked) { // this row has a checked radio button
if (inputs[1].checked && inputs[0].checked && inputs[0].value == inputs[1].value) {
return false;
}
if (oli) { // it's the second checked radio
if (inputs[1].checked) {
oli.className = "selected";
return false;
}
} else if (inputs[0].checked) {
return false;
}
if (inputs[0].checked) {
dli = lis[i];
}
if (!oli) {
inputs[0].style.visibility = 'hidden';
}
if (dli) {
inputs[1].style.visibility = 'hidden';
}
lis[i].className = "selected";
oli = lis[i];
} else { // no radio is checked in this row
if (!oli) {
inputs[0].style.visibility = 'hidden';
} else {
inputs[0].style.visibility = 'visible';
}
if (dli) {
inputs[1].style.visibility = 'hidden';
} else {
inputs[1].style.visibility = 'visible';
}
lis[i].className = "";
}
}
}
return true;
}
 
// page history stuff
// attach event handlers to the input elements on history page
function histrowinit() {
var hf = document.getElementById('pagehistory');
if (!hf) {
return;
}
var lis = hf.getElementsByTagName('li');
for (var i = 0; i < lis.length; i++) {
var inputs = historyRadios(lis[i]);
if (inputs[0] && inputs[1]) {
inputs[0].onclick = diffcheck;
inputs[1].onclick = diffcheck;
}
}
diffcheck();
}
 
// generate toc from prefs form, fold sections
// XXX: needs testing on IE/Mac and safari
// more comments to follow
function tabbedprefs() {
var prefform = document.getElementById('preferences');
if (!prefform || !document.createElement) {
return;
}
if (prefform.nodeName.toLowerCase() == 'a') {
return; // Occasional IE problem
}
prefform.className = prefform.className + 'jsprefs';
var sections = [];
var children = prefform.childNodes;
var seci = 0;
for (var i = 0; i < children.length; i++) {
if (children[i].nodeName.toLowerCase() == 'fieldset') {
children[i].id = 'prefsection-' + seci;
children[i].className = 'prefsection';
if (is_opera || is_khtml) {
children[i].className = 'prefsection operaprefsection';
}
var legends = children[i].getElementsByTagName('legend');
sections[seci] = {};
legends[0].className = 'mainLegend';
if (legends[0] && legends[0].firstChild.nodeValue) {
sections[seci].text = legends[0].firstChild.nodeValue;
} else {
sections[seci].text = '# ' + seci;
}
sections[seci].secid = children[i].id;
seci++;
if (sections.length != 1) {
children[i].style.display = 'none';
} else {
var selectedid = children[i].id;
}
}
}
var toc = document.createElement('ul');
toc.id = 'preftoc';
toc.selectedid = selectedid;
for (i = 0; i < sections.length; i++) {
var li = document.createElement('li');
if (i === 0) {
li.className = 'selected';
}
var a = document.createElement('a');
a.href = '#' + sections[i].secid;
a.onmousedown = a.onclick = uncoversection;
a.appendChild(document.createTextNode(sections[i].text));
a.secid = sections[i].secid;
li.appendChild(a);
toc.appendChild(li);
}
prefform.parentNode.insertBefore(toc, prefform.parentNode.childNodes[0]);
document.getElementById('prefsubmit').id = 'prefcontrol';
}
 
function uncoversection() {
var oldsecid = this.parentNode.parentNode.selectedid;
var newsec = document.getElementById(this.secid);
if (oldsecid != this.secid) {
var ul = document.getElementById('preftoc');
document.getElementById(oldsecid).style.display = 'none';
newsec.style.display = 'block';
ul.selectedid = this.secid;
var lis = ul.getElementsByTagName('li');
for (var i = 0; i< lis.length; i++) {
lis[i].className = '';
}
this.parentNode.className = 'selected';
}
return false;
}
 
// Timezone stuff
// tz in format [+-]HHMM
function checkTimezone(tz, msg) {
var localclock = new Date();
// returns negative offset from GMT in minutes
var tzRaw = localclock.getTimezoneOffset();
var tzHour = Math.floor( Math.abs(tzRaw) / 60);
var tzMin = Math.abs(tzRaw) % 60;
var tzString = ((tzRaw >= 0) ? "-" : "+") + ((tzHour < 10) ? "0" : "") + tzHour + ((tzMin < 10) ? "0" : "") + tzMin;
if (tz != tzString) {
var junk = msg.split('$1');
document.write(junk[0] + "UTC" + tzString + junk[1]);
}
}
 
function unhidetzbutton() {
var tzb = document.getElementById('guesstimezonebutton');
if (tzb) {
tzb.style.display = 'inline';
}
}
 
// in [-]HH:MM format...
// won't yet work with non-even tzs
function fetchTimezone() {
// FIXME: work around Safari bug
var localclock = new Date();
// returns negative offset from GMT in minutes
var tzRaw = localclock.getTimezoneOffset();
var tzHour = Math.floor( Math.abs(tzRaw) / 60);
var tzMin = Math.abs(tzRaw) % 60;
var tzString = ((tzRaw >= 0) ? "-" : "") + ((tzHour < 10) ? "0" : "") + tzHour +
":" + ((tzMin < 10) ? "0" : "") + tzMin;
return tzString;
}
 
function guessTimezone(box) {
document.getElementsByName("wpHourDiff")[0].value = fetchTimezone();
}
 
function showTocToggle() {
if (document.createTextNode) {
// Uses DOM calls to avoid document.write + XHTML issues
 
var linkHolder = document.getElementById('toctitle');
if (!linkHolder) {
return;
}
 
var outerSpan = document.createElement('span');
outerSpan.className = 'toctoggle';
 
var toggleLink = document.createElement('a');
toggleLink.id = 'togglelink';
toggleLink.className = 'internal';
toggleLink.href = 'javascript:toggleToc()';
toggleLink.appendChild(document.createTextNode(tocHideText));
 
outerSpan.appendChild(document.createTextNode('['));
outerSpan.appendChild(toggleLink);
outerSpan.appendChild(document.createTextNode(']'));
 
linkHolder.appendChild(document.createTextNode(' '));
linkHolder.appendChild(outerSpan);
 
var cookiePos = document.cookie.indexOf("hidetoc=");
if (cookiePos > -1 && document.cookie.charAt(cookiePos + 8) == 1) {
toggleToc();
}
}
}
 
function changeText(el, newText) {
// Safari work around
if (el.innerText) {
el.innerText = newText;
} else if (el.firstChild && el.firstChild.nodeValue) {
el.firstChild.nodeValue = newText;
}
}
 
function toggleToc() {
var toc = document.getElementById('toc').getElementsByTagName('ul')[0];
var toggleLink = document.getElementById('togglelink');
 
if (toc && toggleLink && toc.style.display == 'none') {
changeText(toggleLink, tocHideText);
toc.style.display = 'block';
document.cookie = "hidetoc=0";
} else {
changeText(toggleLink, tocShowText);
toc.style.display = 'none';
document.cookie = "hidetoc=1";
}
}
 
function escapeQuotes(text) {
var re = new RegExp("'","g");
text = text.replace(re,"\\'");
re = new RegExp("\\n","g");
text = text.replace(re,"\\n");
return escapeQuotesHTML(text);
}
 
function escapeQuotesHTML(text) {
var re = new RegExp('&',"g");
text = text.replace(re,"&amp;");
re = new RegExp('"',"g");
text = text.replace(re,"&quot;");
re = new RegExp('<',"g");
text = text.replace(re,"&lt;");
re = new RegExp('>',"g");
text = text.replace(re,"&gt;");
return text;
}
 
// apply tagOpen/tagClose to selection in textarea,
// use sampleText instead of selection if there is none
function insertTags(tagOpen, tagClose, sampleText) {
var txtarea;
if (document.editform) {
txtarea = document.editform.wpTextbox1;
} else {
// some alternate form? take the first one we can find
var areas = document.getElementsByTagName('textarea');
txtarea = areas[0];
}
var selText, isSample = false;
 
if (document.selection  && document.selection.createRange) { // IE/Opera
 
//save window scroll position
if (document.documentElement && document.documentElement.scrollTop)
var winScroll = document.documentElement.scrollTop
else if (document.body)
var winScroll = document.body.scrollTop;
//get current selection 
txtarea.focus();
var range = document.selection.createRange();
selText = range.text;
//insert tags
checkSelectedText();
range.text = tagOpen + selText + tagClose;
//mark sample text as selected
if (isSample && range.moveStart) {
if (window.opera)
tagClose = tagClose.replace(/\n/g,'');
range.moveStart('character', - tagClose.length - selText.length);
range.moveEnd('character', - tagClose.length);
}
range.select(); 
//restore window scroll position
if (document.documentElement && document.documentElement.scrollTop)
document.documentElement.scrollTop = winScroll
else if (document.body)
document.body.scrollTop = winScroll;
 
} else if (txtarea.selectionStart || txtarea.selectionStart == '0') { // Mozilla
 
//save textarea scroll position
var textScroll = txtarea.scrollTop;
//get current selection
txtarea.focus();
var startPos = txtarea.selectionStart;
var endPos = txtarea.selectionEnd;
selText = txtarea.value.substring(startPos, endPos);
//insert tags
checkSelectedText();
txtarea.value = txtarea.value.substring(0, startPos)
+ tagOpen + selText + tagClose
+ txtarea.value.substring(endPos, txtarea.value.length);
//set new selection
if (isSample) {
txtarea.selectionStart = startPos + tagOpen.length;
txtarea.selectionEnd = startPos + tagOpen.length + selText.length;
} else {
txtarea.selectionStart = startPos + tagOpen.length + selText.length + tagClose.length;
txtarea.selectionEnd = txtarea.selectionStart;
}
//restore textarea scroll position
txtarea.scrollTop = textScroll;
}
 
function checkSelectedText(){
if (!selText) {
selText = sampleText;
isSample = true;
} else if (selText.charAt(selText.length - 1) == ' ') { //exclude ending space char
selText = selText.substring(0, selText.length - 1);
tagClose += ' '
}
}
 
}
 
 
/**
* Set the accesskey prefix based on browser detection.
*/
var tooltipAccessKeyPrefix = 'alt-';
if (is_opera) {
tooltipAccessKeyPrefix = 'shift-esc-';
} else if (is_safari
  || navigator.userAgent.toLowerCase().indexOf('mac') != -1
  || navigator.userAgent.toLowerCase().indexOf('konqueror') != -1 ) {
tooltipAccessKeyPrefix = 'ctrl-';
} else if (is_ff2_x11 || is_ff2_win) {
tooltipAccessKeyPrefix = 'alt-shift-';
}
var tooltipAccessKeyRegexp = /\[(ctrl-)?(alt-)?(shift-)?(esc-)?.\]$/;
 
/**
* Add the appropriate prefix to the accesskey shown in the tooltip.
* If the nodeList parameter is given, only those nodes are updated;
* otherwise, all the nodes that will probably have accesskeys by
* default are updated.
*
* @param Array nodeList -- list of elements to update
*/
function updateTooltipAccessKeys( nodeList ) {
if ( !nodeList ) {
// skins without a "column-one" element don't seem to have links with accesskeys either
var columnOne = document.getElementById("column-one");
if ( columnOne )
updateTooltipAccessKeys( columnOne.getElementsByTagName("a") );
// these are rare enough that no such optimization is needed
updateTooltipAccessKeys( document.getElementsByTagName("input") );
updateTooltipAccessKeys( document.getElementsByTagName("label") );
return;
}
 
for ( var i = 0; i < nodeList.length; i++ ) {
var element = nodeList[i];
var tip = element.getAttribute("title");
var key = element.getAttribute("accesskey");
if ( key && tooltipAccessKeyRegexp.exec(tip) ) {
tip = tip.replace(tooltipAccessKeyRegexp,
  "["+tooltipAccessKeyPrefix+key+"]");
element.setAttribute("title", tip );
}
}
}
 
/**
* Add a link to one of the portlet menus on the page, including:
*
* p-cactions: Content actions (shown as tabs above the main content in Monobook)
* p-personal: Personal tools (shown at the top right of the page in Monobook)
* p-navigation: Navigation
* p-tb: Toolbox
*
* This function exists for the convenience of custom JS authors.  All
* but the first three parameters are optional, though providing at
* least an id and a tooltip is recommended.
*
* By default the new link will be added to the end of the list.  To
* add the link before a given existing item, pass the DOM node of
* that item (easily obtained with document.getElementById()) as the
* nextnode parameter; to add the link _after_ an existing item, pass
* the node's nextSibling instead.
*
* @param String portlet -- id of the target portlet ("p-cactions", "p-personal", "p-navigation" or "p-tb")
* @param String href -- link URL
* @param String text -- link text (will be automatically lowercased by CSS for p-cactions in Monobook)
* @param String id -- id of the new item, should be unique and preferably have the appropriate prefix ("ca-", "pt-", "n-" or "t-")
* @param String tooltip -- text to show when hovering over the link, without accesskey suffix
* @param String accesskey -- accesskey to activate this link (one character, try to avoid conflicts)
* @param Node nextnode -- the DOM node before which the new item should be added, should be another item in the same list
*
* @return Node -- the DOM node of the new item (an LI element) or null
*/
function addPortletLink(portlet, href, text, id, tooltip, accesskey, nextnode) {
var node = document.getElementById(portlet);
if ( !node ) return null;
node = node.getElementsByTagName( "ul" )[0];
if ( !node ) return null;
 
var link = document.createElement( "a" );
link.appendChild( document.createTextNode( text ) );
link.href = href;
 
var item = document.createElement( "li" );
item.appendChild( link );
if ( id ) item.id = id;
 
if ( accesskey ) {
link.setAttribute( "accesskey", accesskey );
tooltip += " ["+accesskey+"]";
}
if ( tooltip ) {
link.setAttribute( "title", tooltip );
}
if ( accesskey && tooltip ) {
updateTooltipAccessKeys( new Array( link ) );
}
 
if ( nextnode && nextnode.parentNode == node )
node.insertBefore( item, nextnode );
else
node.appendChild( item );  // IE compatibility (?)
 
return item;
}
 
 
/**
* Set up accesskeys/tooltips from the deprecated ta array.  If doId
* is specified, only set up for that id.  Note that this function is
* deprecated and will not be supported indefinitely -- use
* updateTooltipAccessKey() instead.
*
* @param mixed doId string or null
*/
function akeytt( doId ) {
// A lot of user scripts (and some of the code below) break if
// ta isn't defined, so we make sure it is.  Explictly using
// window.ta avoids a "ta is not defined" error.
if (!window.ta) window.ta = new Array;
 
// Make a local, possibly restricted, copy to avoid clobbering
// the original.
var ta;
if ( doId ) {
ta = [doId];
} else {
ta = window.ta;
}
 
// Now deal with evil deprecated ta
var watchCheckboxExists = document.getElementById( 'wpWatchthis' ) ? true : false;
for (var id in ta) {
var n = document.getElementById(id);
if (n) {
var a = null;
var ak = '';
// Are we putting accesskey in it
if (ta[id][0].length > 0) {
// Is this object a object? If not assume it's the next child.
 
if (n.nodeName.toLowerCase() == "a") {
a = n;
} else {
a = n.childNodes[0];
}
// Don't add an accesskey for the watch tab if the watch
// checkbox is also available.
if (a && ((id != 'ca-watch' && id != 'ca-unwatch') || !watchCheckboxExists)) {
a.accessKey = ta[id][0];
ak = ' ['+tooltipAccessKeyPrefix+ta[id][0]+']';
}
} else {
// We don't care what type the object is when assigning tooltip
a = n;
ak = '';
}
 
if (a) {
a.title = ta[id][1]+ak;
}
}
}
}
 
function setupRightClickEdit() {
if (document.getElementsByTagName) {
var spans = document.getElementsByTagName('span');
for (var i = 0; i < spans.length; i++) {
var el = spans[i];
if(el.className == 'editsection') {
addRightClickEditHandler(el);
}
}
}
}
 
function addRightClickEditHandler(el) {
for (var i = 0; i < el.childNodes.length; i++) {
var link = el.childNodes[i];
if (link.nodeType == 1 && link.nodeName.toLowerCase() == 'a') {
var editHref = link.getAttribute('href');
// find the enclosing (parent) header
var prev = el.parentNode;
if (prev && prev.nodeType == 1 &&
prev.nodeName.match(/^[Hh][1-6]$/)) {
prev.oncontextmenu = function(e) {
if (!e) { e = window.event; }
// e is now the event in all browsers
var targ;
if (e.target) { targ = e.target; }
else if (e.srcElement) { targ = e.srcElement; }
if (targ.nodeType == 3) { // defeat Safari bug
targ = targ.parentNode;
}
// targ is now the target element
 
// We don't want to deprive the noble reader of a context menu
// for the section edit link, do we?  (Might want to extend this
// to all <a>'s?)
if (targ.nodeName.toLowerCase() != 'a'
|| targ.parentNode.className != 'editsection') {
document.location = editHref;
return false;
}
return true;
};
}
}
}
}
 
var checkboxes;
var lastCheckbox;
 
function setupCheckboxShiftClick() {
checkboxes = [];
lastCheckbox = null;
var inputs = document.getElementsByTagName('input');
addCheckboxClickHandlers(inputs);
}
 
function addCheckboxClickHandlers(inputs, start) {
if ( !start) start = 0;
 
var finish = start + 250;
if ( finish > inputs.length )
finish = inputs.length;
 
for ( var i = start; i < finish; i++ ) {
var cb = inputs[i];
if ( !cb.type || cb.type.toLowerCase() != 'checkbox' )
continue;
var end = checkboxes.length;
checkboxes[end] = cb;
cb.index = end;
cb.onclick = checkboxClickHandler;
}
 
if ( finish < inputs.length ) {
setTimeout( function () {
addCheckboxClickHandlers(inputs, finish);
}, 200 );
}
}
 
function checkboxClickHandler(e) {
if (typeof e == 'undefined') {
e = window.event;
}
if ( !e.shiftKey || lastCheckbox === null ) {
lastCheckbox = this.index;
return true;
}
var endState = this.checked;
var start, finish;
if ( this.index < lastCheckbox ) {
start = this.index + 1;
finish = lastCheckbox;
} else {
start = lastCheckbox;
finish = this.index - 1;
}
for (var i = start; i <= finish; ++i ) {
checkboxes[i].checked = endState;
}
lastCheckbox = this.index;
return true;
}
 
function toggle_element_activation(ida,idb) {
if (!document.getElementById) {
return;
}
document.getElementById(ida).disabled=true;
document.getElementById(idb).disabled=false;
}
 
function toggle_element_check(ida,idb) {
if (!document.getElementById) {
return;
}
document.getElementById(ida).checked=true;
document.getElementById(idb).checked=false;
}
 
/**
* Restore the edit box scroll state following a preview operation,
* and set up a form submission handler to remember this state
*/
function scrollEditBox() {
var editBox = document.getElementById( 'wpTextbox1' );
var scrollTop = document.getElementById( 'wpScrolltop' );
var editForm = document.getElementById( 'editform' );
if( editBox && scrollTop ) {
if( scrollTop.value )
editBox.scrollTop = scrollTop.value;
addHandler( editForm, 'submit', function() {
document.getElementById( 'wpScrolltop' ).value = document.getElementById( 'wpTextbox1' ).scrollTop;
} );
}
}
hookEvent( 'load', scrollEditBox );
 
var allmessages_nodelist = false;
var allmessages_modified = false;
var allmessages_timeout = false;
var allmessages_running = false;
 
function allmessagesmodified() {
allmessages_modified = !allmessages_modified;
allmessagesfilter();
}
 
function allmessagesfilter() {
if ( allmessages_timeout )
window.clearTimeout( allmessages_timeout );
 
if ( !allmessages_running )
allmessages_timeout = window.setTimeout( 'allmessagesfilter_do();', 500 );
}
 
function allmessagesfilter_do() {
if ( !allmessages_nodelist )
return;
 
var text = document.getElementById('allmessagesinput').value;
var nodef = allmessages_modified;
 
allmessages_running = true;
 
for ( var name in allmessages_nodelist ) {
var nodes = allmessages_nodelist[name];
var display = ( name.indexOf( text ) == -1 ? 'none' : '' );
 
for ( var i = 0; i < nodes.length; i++)
nodes[i].style.display =
( nodes[i].className == "def" && nodef
  ? 'none' : display );
}
 
if ( text != document.getElementById('allmessagesinput').value ||
    nodef != allmessages_modified )
allmessagesfilter_do();  // repeat
 
allmessages_running = false;
}
 
function allmessagesfilter_init() {
if ( allmessages_nodelist )
return;
 
var nodelist = new Array();
var templist = new Array();
 
var table = document.getElementById('allmessagestable');
if ( !table ) return;
 
var rows = document.getElementsByTagName('tr');
for ( var i = 0; i < rows.length; i++ ) {
var id = rows[i].getAttribute('id')
if ( id && id.substring(0,16) != 'sp-allmessages-r' ) continue;
templist[ id ] = rows[i];
}
 
var spans = table.getElementsByTagName('span');
for ( var i = 0; i < spans.length; i++ ) {
var id = spans[i].getAttribute('id')
if ( id && id.substring(0,17) != 'sp-allmessages-i-' ) continue;
if ( !spans[i].firstChild || spans[i].firstChild.nodeType != 3 ) continue;
 
var nodes = new Array();
var row1 = templist[ id.replace('i', 'r1') ];
var row2 = templist[ id.replace('i', 'r2') ];
 
if ( row1 ) nodes[nodes.length] = row1;
if ( row2 ) nodes[nodes.length] = row2;
nodelist[ spans[i].firstChild.nodeValue ] = nodes;
}
 
var k = document.getElementById('allmessagesfilter');
if (k) { k.style.display = ''; }
 
allmessages_nodelist = nodelist;
}
 
hookEvent( "load", allmessagesfilter_init );
 
/*
Written by Jonathan Snook, http://www.snook.ca/jonathan
Add-ons by Robert Nyman, http://www.robertnyman.com
Author says "The credit comment is all it takes, no license. Go crazy with it!:-)"
From http://www.robertnyman.com/2005/11/07/the-ultimate-getelementsbyclassname/
*/
function getElementsByClassName(oElm, strTagName, oClassNames){
var arrElements = (strTagName == "*" && oElm.all)? oElm.all : oElm.getElementsByTagName(strTagName);
var arrReturnElements = new Array();
var arrRegExpClassNames = new Array();
if(typeof oClassNames == "object"){
for(var i=0; i<oClassNames.length; i++){
arrRegExpClassNames[arrRegExpClassNames.length] =
new RegExp("(^|\\s)" + oClassNames[i].replace(/\-/g, "\\-") + "(\\s|$)");
}
}
else{
arrRegExpClassNames[arrRegExpClassNames.length] =
new RegExp("(^|\\s)" + oClassNames.replace(/\-/g, "\\-") + "(\\s|$)");
}
var oElement;
var bMatchesAll;
for(var j=0; j<arrElements.length; j++){
oElement = arrElements[j];
bMatchesAll = true;
for(var k=0; k<arrRegExpClassNames.length; k++){
if(!arrRegExpClassNames[k].test(oElement.className)){
bMatchesAll = false;
break;
}
}
if(bMatchesAll){
arrReturnElements[arrReturnElements.length] = oElement;
}
}
return (arrReturnElements)
}
 
function redirectToFragment(fragment) {
var match = navigator.userAgent.match(/AppleWebKit\/(\d+)/);
if (match) {
var webKitVersion = parseInt(match[1]);
if (webKitVersion < 420) {
// Released Safari w/ WebKit 418.9.1 messes up horribly
// Nightlies of 420+ are ok
return;
}
}
if (is_gecko) {
// Mozilla needs to wait until after load, otherwise the window doesn't scroll
addOnloadHook(function () {
if (window.location.hash == "")
window.location.hash = fragment;
});
} else {
if (window.location.hash == "")
window.location.hash = fragment;
}
}
 
 
/*
* Table sorting script  by Joost de Valk, check it out at http://www.joostdevalk.nl/code/sortable-table/.
* Based on a script from http://www.kryogenix.org/code/browser/sorttable/.
* Distributed under the MIT license: http://www.kryogenix.org/code/browser/licence.html .
*
* Copyright (c) 1997-2006 Stuart Langridge, Joost de Valk.
*
* @todo don't break on colspans/rowspans (bug 8028)
* @todo language-specific digit grouping/decimals (bug 8063)
* @todo support all accepted date formats (bug 8226)
  */
 
var ts_image_path = stylepath+"/common/images/";
var ts_image_up = "sort_up.gif";
var ts_image_down = "sort_down.gif";
var ts_image_none = "sort_none.gif";
var ts_europeandate = wgContentLanguage != "en"; // The non-American-inclined can change to "true"
var ts_alternate_row_colors = true;
var SORT_COLUMN_INDEX;
 
function sortables_init() {
var idnum = 0;
// Find all tables with class sortable and make them sortable
var tables = getElementsByClassName(document, "table", "sortable");
for (var ti = 0; ti < tables.length ; ti++) {
if (!tables[ti].id) {
tables[ti].setAttribute('id','sortable_table_id_'+idnum);
++idnum;
}
ts_makeSortable(tables[ti]);
}
}
 
function ts_makeSortable(table) {
var firstRow;
if (table.rows && table.rows.length > 0) {
if (table.tHead && table.tHead.rows.length > 0) {
firstRow = table.tHead.rows[table.tHead.rows.length-1];
} else {
firstRow = table.rows[0];
}
}
if (!firstRow) return;
 
// We have a first row: assume it's the header, and make its contents clickable links
for (var i = 0; i < firstRow.cells.length; i++) {
var cell = firstRow.cells[i];
if ((" "+cell.className+" ").indexOf(" unsortable ") == -1) {
cell.innerHTML += '&nbsp;&nbsp;<a href="#" class="sortheader" onclick="ts_resortTable(this);return false;"><span class="sortarrow"><img src="'+ ts_image_path + ts_image_none + '" alt="&darr;"/></span></a>';
}
}
if (ts_alternate_row_colors) {
ts_alternate(table);
}
}
 
function ts_getInnerText(el) {
if (typeof el == "string") return el;
if (typeof el == "undefined") { return el };
if (el.textContent) return el.textContent; // not needed but it is faster
if (el.innerText) return el.innerText;    // IE doesn't have textContent
var str = "";
 
var cs = el.childNodes;
var l = cs.length;
for (var i = 0; i < l; i++) {
switch (cs[i].nodeType) {
case 1: //ELEMENT_NODE
str += ts_getInnerText(cs[i]);
break;
case 3: //TEXT_NODE
str += cs[i].nodeValue;
break;
}
}
return str;
}
 
function ts_resortTable(lnk) {
// get the span
var span = lnk.getElementsByTagName('span')[0];
 
var td = lnk.parentNode;
var tr = td.parentNode;
var column = td.cellIndex;
 
var table = tr.parentNode;
while (table && !(table.tagName && table.tagName.toLowerCase() == 'table'))
table = table.parentNode;
if (!table) return;
 
// Work out a type for the column
if (table.rows.length <= 1) return;
 
// Skip the first row if that's where the headings are
var rowStart = (table.tHead && table.tHead.rows.length > 0 ? 0 : 1);
 
var itm = "";
for (var i = rowStart; i < table.rows.length; i++) {
if (table.rows[i].cells.length > column) {
itm = ts_getInnerText(table.rows[i].cells[column]);
itm = itm.replace(/^[\s\xa0]+/, "").replace(/[\s\xa0]+$/, "");
if (itm != "") break;
}
}
 
sortfn = ts_sort_caseinsensitive;
if (itm.match(/^\d\d[\/. -][a-zA-Z]{3}[\/. -]\d\d\d\d$/))
sortfn = ts_sort_date;
if (itm.match(/^\d\d[\/.-]\d\d[\/.-]\d\d\d\d$/))
sortfn = ts_sort_date;
if (itm.match(/^\d\d[\/.-]\d\d[\/.-]\d\d$/))
sortfn = ts_sort_date;
if (itm.match(/^[\u00a3$\u20ac]/)) // pound dollar euro
sortfn = ts_sort_currency;
if (itm.match(/^[\d.,]+\%?$/))
sortfn = ts_sort_numeric;
 
var reverse = (span.getAttribute("sortdir") == 'down');
 
var newRows = new Array();
for (var j = rowStart; j < table.rows.length; j++) {
var row = table.rows[j];
var keyText = ts_getInnerText(row.cells[column]);
var oldIndex = (reverse ? -j : j);
 
newRows[newRows.length] = new Array(row, keyText, oldIndex);
}
 
newRows.sort(sortfn);
 
var arrowHTML;
if (reverse) {
arrowHTML = '<img src="'+ ts_image_path + ts_image_down + '" alt="&darr;"/>';
newRows.reverse();
span.setAttribute('sortdir','up');
} else {
arrowHTML = '<img src="'+ ts_image_path + ts_image_up + '" alt="&uarr;"/>';
span.setAttribute('sortdir','down');
}
 
// We appendChild rows that already exist to the tbody, so it moves them rather than creating new ones
// don't do sortbottom rows
for (var i = 0; i < newRows.length; i++) {
if ((" "+newRows[i][0].className+" ").indexOf(" sortbottom ") == -1)
table.tBodies[0].appendChild(newRows[i][0]);
}
// do sortbottom rows only
for (var i = 0; i < newRows.length; i++) {
if ((" "+newRows[i][0].className+" ").indexOf(" sortbottom ") != -1)
table.tBodies[0].appendChild(newRows[i][0]);
}
 
// Delete any other arrows there may be showing
var spans = getElementsByClassName(tr, "span", "sortarrow");
for (var i = 0; i < spans.length; i++) {
spans[i].innerHTML = '<img src="'+ ts_image_path + ts_image_none + '" alt="&darr;"/>';
}
span.innerHTML = arrowHTML;
 
ts_alternate(table);
}
 
function ts_dateToSortKey(date) {
// y2k notes: two digit years less than 50 are treated as 20XX, greater than 50 are treated as 19XX
if (date.length == 11) {
switch (date.substr(3,3).toLowerCase()) {
case "jan": var month = "01"; break;
case "feb": var month = "02"; break;
case "mar": var month = "03"; break;
case "apr": var month = "04"; break;
case "may": var month = "05"; break;
case "jun": var month = "06"; break;
case "jul": var month = "07"; break;
case "aug": var month = "08"; break;
case "sep": var month = "09"; break;
case "oct": var month = "10"; break;
case "nov": var month = "11"; break;
case "dec": var month = "12"; break;
// default: var month = "00";
}
return date.substr(7,4)+month+date.substr(0,2);
} else if (date.length == 10) {
if (ts_europeandate == false) {
return date.substr(6,4)+date.substr(0,2)+date.substr(3,2);
} else {
return date.substr(6,4)+date.substr(3,2)+date.substr(0,2);
}
} else if (date.length == 8) {
yr = date.substr(6,2);
if (parseInt(yr) < 50) {
yr = '20'+yr;
} else {
yr = '19'+yr;
}
if (ts_europeandate == true) {
return yr+date.substr(3,2)+date.substr(0,2);
} else {
return yr+date.substr(0,2)+date.substr(3,2);
}
}
return "00000000";
}
 
function ts_parseFloat(num) {
if (!num) return 0;
num = parseFloat(num.replace(/,/g, ""));
return (isNaN(num) ? 0 : num);
}
 
function ts_sort_date(a,b) {
var aa = ts_dateToSortKey(a[1]);
var bb = ts_dateToSortKey(b[1]);
return (aa < bb ? -1 : aa > bb ? 1 : a[2] - b[2]);
}
 
function ts_sort_currency(a,b) {
var aa = ts_parseFloat(a[1].replace(/[^0-9.]/g,''));
var bb = ts_parseFloat(b[1].replace(/[^0-9.]/g,''));
return (aa != bb ? aa - bb : a[2] - b[2]);
}
 
function ts_sort_numeric(a,b) {
var aa = ts_parseFloat(a[1]);
var bb = ts_parseFloat(b[1]);
return (aa != bb ? aa - bb : a[2] - b[2]);
}
 
function ts_sort_caseinsensitive(a,b) {
var aa = a[1].toLowerCase();
var bb = b[1].toLowerCase();
return (aa < bb ? -1 : aa > bb ? 1 : a[2] - b[2]);
}
 
function ts_sort_default(a,b) {
return (a[1] < b[1] ? -1 : a[1] > b[1] ? 1 : a[2] - b[2]);
}
 
function ts_alternate(table) {
// Take object table and get all it's tbodies.
var tableBodies = table.getElementsByTagName("tbody");
// Loop through these tbodies
for (var i = 0; i < tableBodies.length; i++) {
// Take the tbody, and get all it's rows
var tableRows = tableBodies[i].getElementsByTagName("tr");
// Loop through these rows
// Start at 1 because we want to leave the heading row untouched
for (var j = 0; j < tableRows.length; j++) {
// Check if j is even, and apply classes for both possible results
var oldClasses = tableRows[j].className.split(" ");
var newClassName = "";
for (var k = 0; k < oldClasses.length; k++) {
if (oldClasses[k] != "" && oldClasses[k] != "even" && oldClasses[k] != "odd")
newClassName += oldClasses[k] + " ";
}
tableRows[j].className = newClassName + (j % 2 == 0 ? "even" : "odd");
}
}
}
 
/*
* End of table sorting code
*/
   
   
function MainPageDeletedImage() {
  try {
   
   
    //If the article does not exist and it is the Main Page, proceed
/**
    if ( document.getElementById( "noarticletext" ) && wgTitle == 'Main Page' ) {
* Add a cute little box at the top of the screen to inform the user of
   
* something, replacing any preexisting message.
      // Insert a protected commons image at the end of the document explaining it.
*
      var contentbox = document.getElementById('content');
* @param String message HTML to be put inside the right div
      var newimg = document.createElement('img');
* @param String className  Used in adding a class; should be different for each
      newimg.setAttribute('src','http://upload.citizendium.org/Citizendium/commons/9/99/CitizendiumTechnical.png');
*  call to allow CSS/JS to hide different boxes.  null = no class used.
      contentbox.appendChild(newimg);
* @return Boolean      True on success, false on failure
*/
      // Hide the article-does-not-exist text
function jsMsg( message, className ) {
      var NoArticleMessage = document.getElementById('noarticletext');
if ( !document.getElementById ) {
      NoArticleMessage.style.display="none";
return false;
   
}
      // Hide the edit button
// We special-case skin structures provided by the software. Skins that
      var EditThisPageButton = document.getElementById('ca-edit');
// choose to abandon or significantly modify our formatting can just define
      EditThisPageButton.style.display="none";
// an mw-js-message div to start with.
    }
var messageDiv = document.getElementById( 'mw-js-message' );
  } catch(e) {
if ( !messageDiv ) {
      // In case it does not work, do nothing
messageDiv = document.createElement( 'div' );
      return;
if ( document.getElementById( 'column-content' )
  }
&& document.getElementById( 'content' ) ) {
  }
// MonoBook, presumably
document.getElementById( 'content' ).insertBefore(
addOnloadHook( MainPageDeletedImage );
messageDiv,
document.getElementById( 'content' ).firstChild
);
} else if ( document.getElementById('content')
&& document.getElementById( 'article' ) ) {
// Non-Monobook but still recognizable (old-style)
document.getElementById( 'article').insertBefore(
messageDiv,
document.getElementById( 'article' ).firstChild
);
} else {
return false;
}
}
 
messageDiv.setAttribute( 'id', 'mw-js-message' );
if( className ) {
messageDiv.setAttribute( 'class', 'mw-js-message-'+className );
}
messageDiv.innerHTML = message;
return true;
}
 
/**
* Inject a cute little progress spinner after the specified element
*
* @param element Element to inject after
* @param id Identifier string (for use with removeSpinner(), below)
*/
function injectSpinner( element, id ) {
var spinner = document.createElement( "img" );
spinner.id = "mw-spinner-" + id;
spinner.src = stylepath + "/common/images/spinner.gif";
spinner.alt = spinner.title = "...";
if( element.nextSibling ) {
element.parentNode.insertBefore( spinner, element.nextSibling );
} else {
element.parentNode.appendChild( spinner );
}
}
 
/**
  * Remove a progress spinner added with injectSpinner()
*
* @param id Identifier string
*/
function removeSpinner( id ) {
var spinner = document.getElementById( "mw-spinner-" + id );
if( spinner ) {
spinner.parentNode.removeChild( spinner );
}
}
 
 
/**
* Add an event handler to an element
*
* @param Element element Element to add handler to
* @param String attach Event to attach to
* @param callable handler Event handler callback
*/
function addHandler( element, attach, handler ) {
if( window.addEventListener ) {
element.addEventListener( attach, handler, false );
} else if( window.attachEvent ) {
element.attachEvent( 'on' + attach, handler );
}
}
 
/**
* Add a click event handler to an element
*
* @param Element element Element to add handler to
* @param callable handler Event handler callback
*/
function addClickHandler( element, handler ) {
addHandler( element, 'click', handler );
}
 
 
function runOnloadHook() {
// don't run anything below this for non-dom browsers
if (doneOnloadHook || !(document.getElementById && document.getElementsByTagName)) {
return;
}
 
// set this before running any hooks, since any errors below
// might cause the function to terminate prematurely
doneOnloadHook = true;
 
histrowinit();
unhidetzbutton();
//
// prefs.js calls addOnloadHook( tabbedprefs ), so the following call is redundant and causes the tabbedprefs toc to display twice.
//
// tabbedprefs();
updateTooltipAccessKeys( null );
akeytt( null );
scrollEditBox();
setupCheckboxShiftClick();
sortables_init();
 
// Run any added-on functions
for (var i = 0; i < onloadFuncts.length; i++) {
onloadFuncts[i]();
}
}
 
// Note: all skins should call runOnloadHook() at the end of html output, so the below should be redundant. It's there just in case.
hookEvent("load", runOnloadHook);
 
 
 
/**
  * Create Google Analytics instance for Citizendium
  */
function loadga() {
var c; (c = document.createElement("script")).src = "https://www.googletagmanager.com/gtag/js?id=G-W7ML9SNPXT";
document.head.appendChild(c);
 
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-W7ML9SNPXT');
}


/** MediaWiki media player *******************************************************
//Call prior function
  *
loadga();
  *  Description: A Java player for in-browser playback of media files.
  *  Created by: [[User:Gmaxwell]]
  */
document.write('<script type="text/javascript" src="'
            + 'http://en.Citizendium.org/wiki/Mediawiki:Citizendiumplayer.js'
            + '&action=raw&ctype=text/javascript&smaxage=86400"></script>');


/** Change Special:Search to use a drop-down menu *******************************************************
  *
  *  Description: Change Special:Search to use a drop-down menu, with the default being
  *              the internal MediaWiki engine
  *  Created and maintained by: [[User:Gracenotes]]
  */
if (wgPageName == "Special:Search") {
        var searchEngines = [];
        addOnloadHook(SpecialSearchEnhanced);
}
function SpecialSearchEnhanced() {
        var createOption = function(site, action, mainQ, addQ, addV) {
                var opt = document.createElement('option');
                opt.appendChild(document.createTextNode(site));
                searchEngines[searchEngines.length] = [action, mainQ, addQ, addV];
                return opt;
        }
        var searchForm = document.forms['search'];
        var selectBox = document.createElement('select');
        selectBox.id = 'searchEngine';
        searchForm.onsubmit = function() {
                var optSelected = searchEngines[document.getElementById('searchEngine').selectedIndex];
                searchForm.action = optSelected[0];
                searchForm.lsearchbox.name = optSelected[1];
                searchForm.title.value = optSelected[3];
                searchForm.title.name = optSelected[2];
        }
        selectBox.appendChild(createOption('MediaWiki search', wgScriptPath + '/index.php', 'search', 'title', 'Special:Search'));
        selectBox.appendChild(createOption('Google', 'http://www.google.com/search', 'q', 'sitesearch', 'en.Citizendium.org'));
        selectBox.appendChild(createOption('Yahoo', 'http://search.yahoo.com/search', 'p', 'vs', 'en.Citizendium.org'));
        selectBox.appendChild(createOption('Windows Live', 'http://search.live.com/results.aspx', 'q', 'q1', 'site:http://en.Citizendium.org'));
        selectBox.appendChild(createOption('Wikiwix', 'http://www.wikiwix.com/', 'action', 'lang', 'en'));
        selectBox.appendChild(createOption('Exalead', 'http://www.exalead.com/Citizendium/results', 'q', 'language', 'en'));
        searchForm.lsearchbox.style.marginLeft = '0px';
        var lStat = document.getElementById('loadStatus');
        lStat.parentNode.insertBefore(selectBox, lStat);
}


//Basic Hide/Show Function
/**
function hideshow( ElementID)
  * Modify link behavior to open in a new tab when contained in a span.newtab
{
  */
theElement = document.getElementById(ElementID);
function checklinks(){
theElement.style.display = (div.style.display=="none" ? "block" : "none"); //If "none", make it "block".  Else, set it to "none"
Array.from(document.getElementsByClassName("newtab")).forEach(function(obj){obj.getElementsByTagName("a")[0].target="_blank"});
}
}
//Call prior function
checklinks();
/* </nowiki> */

Latest revision as of 08:41, 30 January 2023

/* <nowiki> */

 /** Import module *************************************************************
  *
  *  Description: Includes a raw wiki page as javascript or CSS, used for including user made modules.
  *  
  *  Doesn't work in WebKit or IE7...
  */
var loadedScripts = {}; // included-scripts tracker
function importScript(page) {
	var url = wgScript + '?title=' + encodeURIComponent(page.replace(/ /g,'_')).replace(/%2F/ig,'/').replace(/%3A/ig,':') + '&action=raw&ctype=text/javascript';
	
	if (loadedScripts[url]) return null;
	loadedScripts[url] = true;
	
	var s = document.createElement('script');
	s.setAttribute('src',url);
	s.setAttribute('type','text/javascript');
	document.getElementsByTagName('head')[0].appendChild(s);
}

 
 function importStylesheet( page ) {
     var sheet = '@import "'
               + wgScriptPath
               + '/wiki?title='
               + encodeURIComponent( page.replace( ' ', '_' ) )
               + '&action=raw&ctype=text/css";'
     var styleElem = document.createElement( 'style' );
     styleElem.setAttribute( 'type' , 'text/css' );
     styleElem.appendChild( document.createTextNode( sheet ) );
     document.getElementsByTagName( 'head' )[0].appendChild( styleElem );
 }

/* Import more specific scripts if necessary */
//if (wgAction == 'edit' || wgAction == 'submit')
//    importScript("MediaWiki:Common.js/edit.js");
//if (wgPageName == 'Special:Upload')
//    importScript("MediaWiki:Common.js/upload.js");



/** Extra toolbar options ******************************************************
  *
  *  Description: UNDOCUMENTED
  *  Maintainers: 
  */

/* To disable this script, add    mwCustomEditButtons = [];    to [[Special:Mypage/Pinkwich5.js]] */

function imageButons(){
	if (wgAction == 'edit' || wgAction == 'submit') {
		/* Make the Image insertion button use the CZ image template */
		mwEditButtons[5].speedTip = 'Image';
		mwEditButtons[5].tagOpen	= '{{Image|';
		mwEditButtons[5].tagClose = '|right|250px|Image Caption}}';
		
		/* Add extra image buttons */
		if (mwCustomEditButtons) {
			mwCustomEditButtons[mwCustomEditButtons.length] = {
				"imageFile": "http://upload.wikimedia.org/wikipedia/en/c/c8/Button_redirect.png",
				"speedTip": "Redirect",
				"tagOpen": "#REDIRECT [[",
				"tagClose": "]]",
				"sampleText": "Insert text"};
		
			mwCustomEditButtons[mwCustomEditButtons.length] = {
				"imageFile": "http://upload.wikimedia.org/wikipedia/en/c/c9/Button_strike.png",
				"speedTip": "Strike",
				"tagOpen": "<s>",
				"tagClose": "</s>",
				"sampleText": "Strike-through text"};
		
			mwCustomEditButtons[mwCustomEditButtons.length] = {
				"imageFile": "http://upload.wikimedia.org/wikipedia/en/1/13/Button_enter.png",
				"speedTip": "Line break",
				"tagOpen": "<br />",
				"tagClose": "",
				"sampleText": ""};
		
			mwCustomEditButtons[mwCustomEditButtons.length] = {
				"imageFile": "http://upload.wikimedia.org/wikipedia/en/8/80/Button_upper_letter.png",
				"speedTip": "Superscript",
				"tagOpen": "<sup>",
				"tagClose": "</sup>",
				"sampleText": "Superscript text"};
		
			mwCustomEditButtons[mwCustomEditButtons.length] = {
				"imageFile": "http://upload.wikimedia.org/wikipedia/en/7/70/Button_lower_letter.png",
				"speedTip": "Subscript",
				"tagOpen": "<sub>",
				"tagClose": "</sub>",
				"sampleText": "Subscript text"};
		
			mwCustomEditButtons[mwCustomEditButtons.length] = {
				"imageFile": "http://upload.wikimedia.org/wikipedia/en/5/58/Button_small.png",
				"speedTip": "Small",
				"tagOpen": "<small>",
				"tagClose": "</small>",
				"sampleText": "Small Text"};
		
			mwCustomEditButtons[mwCustomEditButtons.length] = {
				"imageFile": "http://upload.wikimedia.org/wikipedia/en/6/60/Button_insert_table.png",
				"speedTip": "Insert a table",
				"tagOpen": '{| class="wikitable"\n|-\n',
				"tagClose": "\n|}",
				"sampleText": "! header 1\n! header 2\n! header 3\n|-\n| row 1, cell 1\n| row 1, cell 2\n| row 1, cell 3\n|-\n| row 2, cell 1\n| row 2, cell 2\n| row 2, cell 3"};
		
			mwCustomEditButtons[mwCustomEditButtons.length] = {
				"imageFile": "http://upload.wikimedia.org/wikipedia/commons/7/79/Button_reflink.png",
				"speedTip": "Insert a reference",
				"tagOpen": "<ref>",
				"tagClose": "</ref>",
				"sampleText": "Insert footnote text here"};
		}
	}
}
addOnloadHook(imageButons);


/** Upload Wizard ***************************************************
 *
 *  Adds many enhancements to the upload form
 *
 *  Maintainer : [[User:Caesar Schinas]]
 */

function uploadForm() {
	if ((wgPageName == 'Special:Upload') && (wgUserLanguage != 'basic')) {
		if ((document.getElementById('wpUploadDescription').value == '') && document.getElementById('preload')) {
			document.getElementById('wpUploadDescription').value = document.getElementById('preload').innerHTML;
			document.getElementById('preload').parentNode.innerHTML = 'Fill in all the details you know:';
		}
		if (wgUserLanguage == 'replace') {
			document.getElementById('wpDestFile').parentNode.parentNode.style.display = 'none';
			document.getElementById('wpUploadDescription').setAttribute('rows','5');
		}
		if ((document.getElementById('wpUploadDescription').value.indexOf('{{Image_Details') != -1) && (wgUserLanguage != 'advanced')) {
			/* get an array of licences */
			var license = document.getElementById('wpLicense');
			var licenses = Array();
			for (var i in license.childNodes) {
				if (license.childNodes[i].nodeName == 'OPTION' && license.childNodes[i].value != '') {
					licenses.push(license.childNodes[i].value);
				}
			}
			/* if there is only one licence available select it and hide the input */
			if (licenses.length == 1) {
				license.value = licenses[0];
				licenseSelectorCheck();
				license.style.display = 'none';
			}
			
			
			/* Create individual fields for the image details */
			
			var labels = {
				'description'	: 'Image description:',
				'author'		: 'Creator name:',
				'copyright'		: 'Copyright holder:',
				'source'		: 'Source:',
				'date-created'	: 'Date created:',
				'pub-country'	: 'Publication country:',
				'notes'			: 'Notes:',
				'versions'		: 'Other versions:'
			};
			var sig = '~~'+'~';
			
			var summary = document.getElementById('wpUploadDescription');
			var table = summary.parentNode.parentNode.parentNode;
			var next = summary.parentNode.parentNode.nextSibling;
			
			var args = Array();
			if (summary.value.indexOf('Details|') != -1)
				args = summary.value.substring(summary.value.indexOf('Details|')+8,summary.value.indexOf('\n')).split('|');
			
			var details = summary.value.substring(summary.value.indexOf('\n|')+2,summary.value.indexOf('\n}}')).split('\n|');
			for (var i in details) {
				details[i] = details[i].split('=');
			}
			for (var i in details) {
				var tr = document.createElement('tr');
				var td1 = document.createElement('td');
				var td2 = document.createElement('td');
				tr.appendChild(td1);
				tr.appendChild(td2);
				td1.setAttribute('class','mw-label');
				td2.setAttribute('class','mw-input');
				td1.style.width = '12em';

				// added by dnessett on 3/12/2010 to increase visible region for Notes
				if ((details[i][0].replace(/^\s+|\s+$/g,'')) == 'notes') {
					var textarea = document.createElement('textarea');
					textarea.setAttribute('wrap','virtual');
					textarea.setAttribute('id',details[i][0].replace(/^\s+|\s+$/g,''));
					textarea.setAttribute('name',details[i][0].replace(/^\s+|\s+$/g,''));
					textarea.setAttribute('value',details[i][1].replace(/^\s+|\s+$/g,''));
					textarea.setAttribute('rows','5');
					td2.appendChild(textarea);
					textarea.style.width = '90%';
				} else {
					var input = document.createElement('input');
					input.setAttribute('type','text');
					input.setAttribute('id',details[i][0].replace(/^\s+|\s+$/g,''));
					input.setAttribute('name',details[i][0].replace(/^\s+|\s+$/g,''));
					input.setAttribute('value',details[i][1].replace(/^\s+|\s+$/g,''));
					td2.appendChild(input);
					input.style.width = '90%';
				}
				
				var label = document.createElement('label');
				label.setAttribute('for',details[i][0].replace(/^\s+|\s+$/g,''));
				label.appendChild(document.createTextNode(labels[details[i][0].replace(/^\s+|\s+$/g,'')]));
				td1.appendChild(label);
				
				table.insertBefore(tr,next);
				
				if ((details[i][0].replace(/^\s+|\s+$/g,'')) == 'author' && (details[i][1].replace(/^\s+|\s+$/g,'') == sig)) tr.style.display = 'none';
			}
			summary.parentNode.parentNode.style.display = 'none';
			
			var septr = document.createElement('tr');
			var septd = document.createElement('td');
			septr.appendChild(septd);
			septd.appendChild(document.createElement('br'));
			table.insertBefore(septr,summary.parentNode.parentNode);
			
			document.getElementById('mw-upload-form').onsubmit = function(){
				var temp = '{{Image_Details';
				for (i in args) {
					temp += '|' + args[i];
				}
				for (i in details) {
					temp += '\n|' + details[i][0] + '= ' + document.getElementById(details[i][0].replace(/^\s+|\s+$/g,'')).value;
				}
				temp += '\n}}';
				summary.value = temp;
				
				if (license.value == '') {
					alert('Please select a licence!');
					return false;
				}
			}
		}
	}
}
addOnloadHook(uploadForm);

function uploadReplaceLink () {
	if (wgNamespaceNumber == 6) {
		var a = document.getElementsByTagName('a');
		for (var i in a) {
			if (a[i].getAttribute('href') && a[i].getAttribute('href').indexOf('wpDestFile') != -1)
				a[i].setAttribute('href', a[i].getAttribute('href') + '&uselang=replace');
		}
	}
}
addOnloadHook(uploadReplaceLink);


/** Credit Line Editor ***************************************************
 *
 *  Creates a simple form for editing credit lines.
 *
 *  Maintainer : [[User:Caesar Schinas]]
 */
function creditEdit() {
  if ((wgPageName.indexOf('/credit') != -1) && (wgAction == 'edit')) {
	var text = document.getElementById('wpTextbox1').value;
	if (text.indexOf('{{creditline') == -1) return false;
	var args = text.substring(text.indexOf('|')+1,text.indexOf('}}')).split('|');
	
	var bodycontent = document.getElementById('bodycontent');
	bodycontent.setAttribute('id','bodycontent-old');
	bodycontent.style.display = 'none';
	
	var div = document.createElement('div');
	bodycontent.parentNode.appendChild(div);
	div.setAttribute('id','bodycontent');
	
	div.innerHTML = "\
<table>\n\
  <tr>\n\
	<th style='text-align:right; padding-right:1em;'>\n\
	  <label for='licence'>Licence Type</label>\n\
	</th>\n\
	<td>\n\
	  <select id='licence' name='licence' style='width:25em;'>\n\
		<option value='C'>C - Copyright, used by permission</option>\n\
		<option value='CC'>CC - Creative Commons</option>\n\
		<option value='GNU'>GNU</option>\n\
		<option value='PD'>PD - Public Domain</option>\n\
		<option value='other' selected='selected'>Other (please only enter letters)</option>\n\
	  </select>\n\
	  <input type='text' id='licence-other' name='imagetype-other' />\n\
	</td>\n\
  </tr>\n\
  <tr>\n\
	<th style='text-align:right; padding-right:1em;'>\n\
	  <label for='imagetype'>Image Type</label>\n\
	</th>\n\
	<td>\n\
	  <select id='imagetype' name='imagetype' style='width:25em;'>\n\
		<option value='Image'>Image</option>\n\
		<option value='Photo'>Photo</option>\n\
		<option value='Diagram'>Diagram</option>\n\
		<option value='Drawing'>Drawing</option>\n\
		<option value='Painting'>Painting</option>\n\
		<option value='Artwork'>Artwork</option>\n\
		<option value='other' selected='selected'>Other</option>\n\
	  </select>\n\
	  <input type='text' id='imagetype-other' name='imagetype-other' />\n\
	</td>\n\
  </tr>\n\
  <tr>\n\
	<th style='text-align:right; padding-right:1em;'>\n\
	  <label for='author'>Author</label>\n\
	</th>\n\
	<td>\n\
	  <input type='text' id='author' name='author' style='width:25em;' />\n\
	</td>\n\
  </tr>\n\
  <tr>\n\
	<th>\n\
	</th>\n\
	<td>\n\
	  <input type='button' id='save' value='Save Credit Line' />\n\
	</td>\n\
  </tr>\n\
</table>\n\
";
	
	// set form field values
	
	if (args[0] && args[0] != 'licence') {
	  document.getElementById('licence-other').value = args[0];
	  for (var i=0; i<4; i++) {
		if (args[0].toUpperCase() == Array('CC','GNU','PD','C')[i]) {
			document.getElementById('licence').value = args[0].toUpperCase();
			document.getElementById('licence-other').style.display = 'none';
		}
	  }
	} else {
	  document.getElementById('licence').value = 'C';
	  document.getElementById('licence-other').style.display = 'none';
	}
	
	if (args[1] && args[1] != 'imagetype') {
	  document.getElementById('imagetype-other').value = args[1];
	  for (var i=0; i<6; i++) {
		if (args[1].toLowerCase() == Array('Image','Photo','Diagram','Drawing','Painting','Artwork')[i].toLowerCase()) {
			document.getElementById('imagetype').value = Array('Image','Photo','Diagram','Drawing','Painting','Artwork')[i];
			document.getElementById('imagetype-other').style.display = 'none';
		}
	  }
	} else {
	  document.getElementById('imagetype').value = 'Image';
	  document.getElementById('imagetype-other').style.display = 'none';
	}
	
	if (args[2] && args[2] != 'author')
	  document.getElementById('author').value = args[2];
	
	
	// onchange handlers for selects
	
	document.getElementById('licence').onchange = function() {
	  if (document.getElementById('licence').value == 'other')
		document.getElementById('licence-other').style.display = 'inline';
	  else
		document.getElementById('licence-other').style.display = 'none';
	}
	
	document.getElementById('imagetype').onchange = function() {
	  if (document.getElementById('imagetype').value == 'other')
		document.getElementById('imagetype-other').style.display = 'inline';
	  else
		document.getElementById('imagetype-other').style.display = 'none';
	}
	
	
	// save the credit line
	
	document.getElementById('save').onclick = function() {
	  var value = '{{creditline';
	  
	  if (document.getElementById('licence').value != 'other')
		value += '|' + document.getElementById('licence').value;
	  else if (document.getElementById('licence-other').value != '')
		value += '|' + document.getElementById('licence-other').value;
	  
	  if (document.getElementById('imagetype').value != 'Image' || document.getElementById('author').value != '') {
		if (document.getElementById('imagetype').value != 'other')
			value += '|' + document.getElementById('imagetype').value;
		else if (document.getElementById('imagetype-other').value != '')
			value += '|' + document.getElementById('imagetype-other').value;
		
		if (document.getElementById('author').value != '')
			value += '|' + document.getElementById('author').value;
	  }
	  
	  value += '}}';
	  
	  document.getElementById('wpTextbox1').value = value;
	  document.getElementById('editform').submit();
	}
  }
}
addOnloadHook(creditEdit);




 /* Test if an element has a certain class **************************************
  *
  * Description: Uses regular expressions and caching for better performance.
  * Maintainers: [[User:Mike Dillon]], [[User:R. Koot]], [[User:SG]]
  */
 
 var hasClass = (function () {
     var reCache = {};
     return function (element, className) {
         return (reCache[className] ? reCache[className] : (reCache[className] = new RegExp("(?:\\s|^)" + className + "(?:\\s|$)"))).test(element.className);
     };
 })();



 

 /** Collapsible tables *********************************************************
  *
  *  Description: Allows tables to be collapsed, showing only the header. See
  *               [[Citizendium:NavFrame]].
  *  Maintainers: [[User:R. Koot]]
  */
 
 var autoCollapse = 2;
 var collapseCaption = "hide";
 var expandCaption = "show";
 
 function collapseTable( tableIndex )
 {
     var Button = document.getElementById( "collapseButton" + tableIndex );
     var Table = document.getElementById( "collapsibleTable" + tableIndex );
 
     if ( !Table || !Button ) {
         return false;
     }
 
     var Rows = Table.getElementsByTagName( "tr" ); 
 
     if ( Button.firstChild.data == collapseCaption ) {
         for ( var i = 1; i < Rows.length; i++ ) {
             Rows[i].style.display = "none";
         }
         Button.firstChild.data = expandCaption;
     } else {
         for ( var i = 1; i < Rows.length; i++ ) {
             Rows[i].style.display = Rows[0].style.display;
         }
         Button.firstChild.data = collapseCaption;
     }
 }
 
 function createCollapseButtons()
 {
     var tableIndex = 0;
     var NavigationBoxes = new Object();
     var Tables = document.getElementsByTagName( "table" );
 
     for ( var i = 0; i < Tables.length; i++ ) {
         if ( hasClass( Tables[i], "collapsible" ) ) {
             NavigationBoxes[ tableIndex ] = Tables[i];
             Tables[i].setAttribute( "id", "collapsibleTable" + tableIndex );
 
             var Button     = document.createElement( "span" );
             var ButtonLink = document.createElement( "a" );
             var ButtonText = document.createTextNode( collapseCaption );
 
             Button.style.styleFloat = "right";
             Button.style.cssFloat = "right";
             Button.style.fontWeight = "normal";
             Button.style.textAlign = "right";
             Button.style.width = "6em";
 
             ButtonLink.setAttribute( "id", "collapseButton" + tableIndex );
             ButtonLink.setAttribute( "href", "javascript:collapseTable(" + tableIndex + ");" );
             ButtonLink.appendChild( ButtonText );
 
             Button.appendChild( document.createTextNode( "[" ) );
             Button.appendChild( ButtonLink );
             Button.appendChild( document.createTextNode( "]" ) );
 
             var Header = Tables[i].getElementsByTagName( "tr" )[0].getElementsByTagName( "th" )[0];
             /* only add button and increment count if there is a header row to work with */
             if (Header) {
                 Header.insertBefore( Button, Header.childNodes[0] );
                 tableIndex++;
             }
         }
     }
 
     for ( var i = 0;  i < tableIndex; i++ ) {
         if ( hasClass( NavigationBoxes[i], "collapsed" ) || ( tableIndex >= autoCollapse && hasClass( NavigationBoxes[i], "autocollapse" ) ) ) {
             collapseTable( i );
         }
     }
 }
 addOnloadHook( createCollapseButtons );


 /** Add dismiss button to watchlist-message *************************************
  *
  *  Description: Hide the watchlist message for one week.
  *  Maintainers: [[User:Ruud Koot|Ruud Koot]]
  */
 
 function addDismissButton() {
    var watchlistMessage = document.getElementById("watchlist-message");
    if ( watchlistMessage == null ) return;
 
    if ( document.cookie.indexOf( "hidewatchlistmessage=yes" ) != -1 ) {
        watchlistMessage.style.display = "none";
    }
 
    var Button     = document.createElement( "span" );
    var ButtonLink = document.createElement( "a" );
    var ButtonText = document.createTextNode( "dismiss" );
 
    ButtonLink.setAttribute( "id", "dismissButton" );
    ButtonLink.setAttribute( "href", "javascript:dismissWatchlistMessage();" );
    ButtonLink.setAttribute( "title", "Hide this message for one week" );
    ButtonLink.appendChild( ButtonText );
 
    Button.appendChild( document.createTextNode( "[" ) );
    Button.appendChild( ButtonLink );
    Button.appendChild( document.createTextNode( "]" ) );
 
    watchlistMessage.appendChild( Button );
 }
 
 function dismissWatchlistMessage() {
     var e = new Date();
     e.setTime( e.getTime() + (7*24*60*60*1000) );
     document.cookie = "hidewatchlistmessage=yes; expires=" + e.toGMTString() + "; path=/";
     var watchlistMessage = document.getElementById("watchlist-message");
     watchlistMessage.style.display = "none";
 }
 
 addOnloadHook( addDismissButton );

 /** Numeric sorting ***************************************************
  *
  *  Description: Fixes a bug (part of [[bugzilla:8115]])
  *  in http://svn.citizendium.org/viewvc/mediawiki/trunk/phase3/skins/common/wikibits.js
  *  regarding [[Help:Sorting|table sorting]]:
  *  it allows sorting of numbers with more than one comma (thousands separator).
  *  Maintainer: [[User:Patrick|Patrick]]
  */
 function ts_parseFloat(num) {
 	if (!num) return 0;
 	num = parseFloat(num.replace(/,/g, ""));
 	return (isNaN(num) ? 0 : num);
 }



// MediaWiki JavaScript support functions

var clientPC = navigator.userAgent.toLowerCase(); // Get client info
var is_gecko = ((clientPC.indexOf('gecko')!=-1) && (clientPC.indexOf('spoofer')==-1)
                && (clientPC.indexOf('khtml') == -1) && (clientPC.indexOf('netscape/7.0')==-1));
var is_safari = ((clientPC.indexOf('applewebkit')!=-1) && (clientPC.indexOf('spoofer')==-1));
var is_khtml = (navigator.vendor == 'KDE' || ( document.childNodes && !document.all && !navigator.taintEnabled ));
// For accesskeys
var is_ff2_win = (clientPC.indexOf('firefox/2')!=-1 || clientPC.indexOf('minefield/3')!=-1) && clientPC.indexOf('windows')!=-1;
var is_ff2_x11 = (clientPC.indexOf('firefox/2')!=-1 || clientPC.indexOf('minefield/3')!=-1) && clientPC.indexOf('x11')!=-1;
if (clientPC.indexOf('opera') != -1) {
	var is_opera = true;
	var is_opera_preseven = (window.opera && !document.childNodes);
	var is_opera_seven = (window.opera && document.childNodes);
	var is_opera_95 = (clientPC.search(/opera\/(9.[5-9]|[1-9][0-9])/)!=-1);
}

// Global external objects used by this script.
/*extern ta, stylepath, skin */

// add any onload functions in this hook (please don't hard-code any events in the xhtml source)
var doneOnloadHook;

if (!window.onloadFuncts) {
	var onloadFuncts = [];
}

function addOnloadHook(hookFunct) {
	// Allows add-on scripts to add onload functions
	onloadFuncts[onloadFuncts.length] = hookFunct;
}

function hookEvent(hookName, hookFunct) {
	if (window.addEventListener) {
		window.addEventListener(hookName, hookFunct, false);
	} else if (window.attachEvent) {
		window.attachEvent("on" + hookName, hookFunct);
	}
}

// document.write special stylesheet links
if (typeof stylepath != 'undefined' && typeof skin != 'undefined') {
	if (is_opera_preseven) {
		document.write('<link rel="stylesheet" type="text/css" href="'+stylepath+'/'+skin+'/Opera6Fixes.css">');
	} else if (is_opera_seven && !is_opera_95) {
		document.write('<link rel="stylesheet" type="text/css" href="'+stylepath+'/'+skin+'/Opera7Fixes.css">');
	} else if (is_opera_95) {
		document.write('<link rel="stylesheet" type="text/css" href="'+stylepath+'/'+skin+'/Opera95Fixes.css">');
	} else if (is_khtml) {
		document.write('<link rel="stylesheet" type="text/css" href="'+stylepath+'/'+skin+'/KHTMLFixes.css">');
	}
}

if (wgBreakFrames) {
	// Un-trap us from framesets
	if (window.top != window) {
		window.top.location = window.location;
	}
}

// for enhanced RecentChanges
function toggleVisibility(_levelId, _otherId, _linkId) {
	var thisLevel = document.getElementById(_levelId);
	var otherLevel = document.getElementById(_otherId);
	var linkLevel = document.getElementById(_linkId);
	if (thisLevel.style.display == 'none') {
		thisLevel.style.display = 'block';
		otherLevel.style.display = 'none';
		linkLevel.style.display = 'inline';
	} else {
		thisLevel.style.display = 'none';
		otherLevel.style.display = 'inline';
		linkLevel.style.display = 'none';
	}
}

function historyRadios(parent) {
	var inputs = parent.getElementsByTagName('input');
	var radios = [];
	for (var i = 0; i < inputs.length; i++) {
		if (inputs[i].name == "diff" || inputs[i].name == "oldid") {
			radios[radios.length] = inputs[i];
		}
	}
	return radios;
}

// check selection and tweak visibility/class onclick
function diffcheck() {
	var dli = false; // the li where the diff radio is checked
	var oli = false; // the li where the oldid radio is checked
	var hf = document.getElementById('pagehistory');
	if (!hf) {
		return true;
	}
	var lis = hf.getElementsByTagName('li');
	for (var i=0;i<lis.length;i++) {
		var inputs = historyRadios(lis[i]);
		if (inputs[1] && inputs[0]) {
			if (inputs[1].checked || inputs[0].checked) { // this row has a checked radio button
				if (inputs[1].checked && inputs[0].checked && inputs[0].value == inputs[1].value) {
					return false;
				}
				if (oli) { // it's the second checked radio
					if (inputs[1].checked) {
						oli.className = "selected";
						return false;
					}
				} else if (inputs[0].checked) {
					return false;
				}
				if (inputs[0].checked) {
					dli = lis[i];
				}
				if (!oli) {
					inputs[0].style.visibility = 'hidden';
				}
				if (dli) {
					inputs[1].style.visibility = 'hidden';
				}
				lis[i].className = "selected";
				oli = lis[i];
			}  else { // no radio is checked in this row
				if (!oli) {
					inputs[0].style.visibility = 'hidden';
				} else {
					inputs[0].style.visibility = 'visible';
				}
				if (dli) {
					inputs[1].style.visibility = 'hidden';
				} else {
					inputs[1].style.visibility = 'visible';
				}
				lis[i].className = "";
			}
		}
	}
	return true;
}

// page history stuff
// attach event handlers to the input elements on history page
function histrowinit() {
	var hf = document.getElementById('pagehistory');
	if (!hf) {
		return;
	}
	var lis = hf.getElementsByTagName('li');
	for (var i = 0; i < lis.length; i++) {
		var inputs = historyRadios(lis[i]);
		if (inputs[0] && inputs[1]) {
			inputs[0].onclick = diffcheck;
			inputs[1].onclick = diffcheck;
		}
	}
	diffcheck();
}

// generate toc from prefs form, fold sections
// XXX: needs testing on IE/Mac and safari
// more comments to follow
function tabbedprefs() {
	var prefform = document.getElementById('preferences');
	if (!prefform || !document.createElement) {
		return;
	}
	if (prefform.nodeName.toLowerCase() == 'a') {
		return; // Occasional IE problem
	}
	prefform.className = prefform.className + 'jsprefs';
	var sections = [];
	var children = prefform.childNodes;
	var seci = 0;
	for (var i = 0; i < children.length; i++) {
		if (children[i].nodeName.toLowerCase() == 'fieldset') {
			children[i].id = 'prefsection-' + seci;
			children[i].className = 'prefsection';
			if (is_opera || is_khtml) {
				children[i].className = 'prefsection operaprefsection';
			}
			var legends = children[i].getElementsByTagName('legend');
			sections[seci] = {};
			legends[0].className = 'mainLegend';
			if (legends[0] && legends[0].firstChild.nodeValue) {
				sections[seci].text = legends[0].firstChild.nodeValue;
			} else {
				sections[seci].text = '# ' + seci;
			}
			sections[seci].secid = children[i].id;
			seci++;
			if (sections.length != 1) {
				children[i].style.display = 'none';
			} else {
				var selectedid = children[i].id;
			}
		}
	}
	var toc = document.createElement('ul');
	toc.id = 'preftoc';
	toc.selectedid = selectedid;
	for (i = 0; i < sections.length; i++) {
		var li = document.createElement('li');
		if (i === 0) {
			li.className = 'selected';
		}
		var a = document.createElement('a');
		a.href = '#' + sections[i].secid;
		a.onmousedown = a.onclick = uncoversection;
		a.appendChild(document.createTextNode(sections[i].text));
		a.secid = sections[i].secid;
		li.appendChild(a);
		toc.appendChild(li);
	}
	prefform.parentNode.insertBefore(toc, prefform.parentNode.childNodes[0]);
	document.getElementById('prefsubmit').id = 'prefcontrol';
}

function uncoversection() {
	var oldsecid = this.parentNode.parentNode.selectedid;
	var newsec = document.getElementById(this.secid);
	if (oldsecid != this.secid) {
		var ul = document.getElementById('preftoc');
		document.getElementById(oldsecid).style.display = 'none';
		newsec.style.display = 'block';
		ul.selectedid = this.secid;
		var lis = ul.getElementsByTagName('li');
		for (var i = 0; i< lis.length; i++) {
			lis[i].className = '';
		}
		this.parentNode.className = 'selected';
	}
	return false;
}

// Timezone stuff
// tz in format [+-]HHMM
function checkTimezone(tz, msg) {
	var localclock = new Date();
	// returns negative offset from GMT in minutes
	var tzRaw = localclock.getTimezoneOffset();
	var tzHour = Math.floor( Math.abs(tzRaw) / 60);
	var tzMin = Math.abs(tzRaw) % 60;
	var tzString = ((tzRaw >= 0) ? "-" : "+") + ((tzHour < 10) ? "0" : "") + tzHour + ((tzMin < 10) ? "0" : "") + tzMin;
	if (tz != tzString) {
		var junk = msg.split('$1');
		document.write(junk[0] + "UTC" + tzString + junk[1]);
	}
}

function unhidetzbutton() {
	var tzb = document.getElementById('guesstimezonebutton');
	if (tzb) {
		tzb.style.display = 'inline';
	}
}

// in [-]HH:MM format...
// won't yet work with non-even tzs
function fetchTimezone() {
	// FIXME: work around Safari bug
	var localclock = new Date();
	// returns negative offset from GMT in minutes
	var tzRaw = localclock.getTimezoneOffset();
	var tzHour = Math.floor( Math.abs(tzRaw) / 60);
	var tzMin = Math.abs(tzRaw) % 60;
	var tzString = ((tzRaw >= 0) ? "-" : "") + ((tzHour < 10) ? "0" : "") + tzHour +
		":" + ((tzMin < 10) ? "0" : "") + tzMin;
	return tzString;
}

function guessTimezone(box) {
	document.getElementsByName("wpHourDiff")[0].value = fetchTimezone();
}

function showTocToggle() {
	if (document.createTextNode) {
		// Uses DOM calls to avoid document.write + XHTML issues

		var linkHolder = document.getElementById('toctitle');
		if (!linkHolder) {
			return;
		}

		var outerSpan = document.createElement('span');
		outerSpan.className = 'toctoggle';

		var toggleLink = document.createElement('a');
		toggleLink.id = 'togglelink';
		toggleLink.className = 'internal';
		toggleLink.href = 'javascript:toggleToc()';
		toggleLink.appendChild(document.createTextNode(tocHideText));

		outerSpan.appendChild(document.createTextNode('['));
		outerSpan.appendChild(toggleLink);
		outerSpan.appendChild(document.createTextNode(']'));

		linkHolder.appendChild(document.createTextNode(' '));
		linkHolder.appendChild(outerSpan);

		var cookiePos = document.cookie.indexOf("hidetoc=");
		if (cookiePos > -1 && document.cookie.charAt(cookiePos + 8) == 1) {
			toggleToc();
		}
	}
}

function changeText(el, newText) {
	// Safari work around
	if (el.innerText) {
		el.innerText = newText;
	} else if (el.firstChild && el.firstChild.nodeValue) {
		el.firstChild.nodeValue = newText;
	}
}

function toggleToc() {
	var toc = document.getElementById('toc').getElementsByTagName('ul')[0];
	var toggleLink = document.getElementById('togglelink');

	if (toc && toggleLink && toc.style.display == 'none') {
		changeText(toggleLink, tocHideText);
		toc.style.display = 'block';
		document.cookie = "hidetoc=0";
	} else {
		changeText(toggleLink, tocShowText);
		toc.style.display = 'none';
		document.cookie = "hidetoc=1";
	}
}

function escapeQuotes(text) {
	var re = new RegExp("'","g");
	text = text.replace(re,"\\'");
	re = new RegExp("\\n","g");
	text = text.replace(re,"\\n");
	return escapeQuotesHTML(text);
}

function escapeQuotesHTML(text) {
	var re = new RegExp('&',"g");
	text = text.replace(re,"&amp;");
	re = new RegExp('"',"g");
	text = text.replace(re,"&quot;");
	re = new RegExp('<',"g");
	text = text.replace(re,"&lt;");
	re = new RegExp('>',"g");
	text = text.replace(re,"&gt;");
	return text;
}

// apply tagOpen/tagClose to selection in textarea,
// use sampleText instead of selection if there is none
function insertTags(tagOpen, tagClose, sampleText) {
	var txtarea;
	if (document.editform) {
		txtarea = document.editform.wpTextbox1;
	} else {
		// some alternate form? take the first one we can find
		var areas = document.getElementsByTagName('textarea');
		txtarea = areas[0];
	}
	var selText, isSample = false;

	if (document.selection  && document.selection.createRange) { // IE/Opera

		//save window scroll position
		if (document.documentElement && document.documentElement.scrollTop)
			var winScroll = document.documentElement.scrollTop
		else if (document.body)
			var winScroll = document.body.scrollTop;
		//get current selection  
		txtarea.focus();
		var range = document.selection.createRange();
		selText = range.text;
		//insert tags
		checkSelectedText();
		range.text = tagOpen + selText + tagClose;
		//mark sample text as selected
		if (isSample && range.moveStart) {
			if (window.opera)
				tagClose = tagClose.replace(/\n/g,'');
			range.moveStart('character', - tagClose.length - selText.length); 
			range.moveEnd('character', - tagClose.length); 
		}
		range.select();   
		//restore window scroll position
		if (document.documentElement && document.documentElement.scrollTop)
			document.documentElement.scrollTop = winScroll
		else if (document.body)
			document.body.scrollTop = winScroll;

	} else if (txtarea.selectionStart || txtarea.selectionStart == '0') { // Mozilla

		//save textarea scroll position
		var textScroll = txtarea.scrollTop;
		//get current selection
		txtarea.focus();
		var startPos = txtarea.selectionStart;
		var endPos = txtarea.selectionEnd;
		selText = txtarea.value.substring(startPos, endPos);
		//insert tags
		checkSelectedText();
		txtarea.value = txtarea.value.substring(0, startPos)
			+ tagOpen + selText + tagClose
			+ txtarea.value.substring(endPos, txtarea.value.length);
		//set new selection
		if (isSample) {
			txtarea.selectionStart = startPos + tagOpen.length;
			txtarea.selectionEnd = startPos + tagOpen.length + selText.length;
		} else {
			txtarea.selectionStart = startPos + tagOpen.length + selText.length + tagClose.length;
			txtarea.selectionEnd = txtarea.selectionStart;
		}
		//restore textarea scroll position
		txtarea.scrollTop = textScroll;
	} 

	function checkSelectedText(){
		if (!selText) {
			selText = sampleText;
			isSample = true;
		} else if (selText.charAt(selText.length - 1) == ' ') { //exclude ending space char
			selText = selText.substring(0, selText.length - 1);
			tagClose += ' '
		} 
	}

}


/**
 * Set the accesskey prefix based on browser detection.
 */
var tooltipAccessKeyPrefix = 'alt-';
if (is_opera) {
	tooltipAccessKeyPrefix = 'shift-esc-';
} else if (is_safari
	   || navigator.userAgent.toLowerCase().indexOf('mac') != -1
	   || navigator.userAgent.toLowerCase().indexOf('konqueror') != -1 ) {
	tooltipAccessKeyPrefix = 'ctrl-';
} else if (is_ff2_x11 || is_ff2_win) {
	tooltipAccessKeyPrefix = 'alt-shift-';
}
var tooltipAccessKeyRegexp = /\[(ctrl-)?(alt-)?(shift-)?(esc-)?.\]$/;

/**
 * Add the appropriate prefix to the accesskey shown in the tooltip.
 * If the nodeList parameter is given, only those nodes are updated;
 * otherwise, all the nodes that will probably have accesskeys by
 * default are updated.
 *
 * @param Array nodeList -- list of elements to update
 */
function updateTooltipAccessKeys( nodeList ) {
	if ( !nodeList ) {
		// skins without a "column-one" element don't seem to have links with accesskeys either
		var columnOne = document.getElementById("column-one");
		if ( columnOne )
			updateTooltipAccessKeys( columnOne.getElementsByTagName("a") );
		// these are rare enough that no such optimization is needed
		updateTooltipAccessKeys( document.getElementsByTagName("input") );
		updateTooltipAccessKeys( document.getElementsByTagName("label") );
		return;
	}

	for ( var i = 0; i < nodeList.length; i++ ) {
		var element = nodeList[i];
		var tip = element.getAttribute("title");
		var key = element.getAttribute("accesskey");
		if ( key && tooltipAccessKeyRegexp.exec(tip) ) {
			tip = tip.replace(tooltipAccessKeyRegexp,
					  "["+tooltipAccessKeyPrefix+key+"]");
			element.setAttribute("title", tip );
		}
	}
}

/**
 * Add a link to one of the portlet menus on the page, including:
 *
 * p-cactions: Content actions (shown as tabs above the main content in Monobook)
 * p-personal: Personal tools (shown at the top right of the page in Monobook)
 * p-navigation: Navigation
 * p-tb: Toolbox
 *
 * This function exists for the convenience of custom JS authors.  All
 * but the first three parameters are optional, though providing at
 * least an id and a tooltip is recommended.
 *
 * By default the new link will be added to the end of the list.  To
 * add the link before a given existing item, pass the DOM node of
 * that item (easily obtained with document.getElementById()) as the
 * nextnode parameter; to add the link _after_ an existing item, pass
 * the node's nextSibling instead.
 *
 * @param String portlet -- id of the target portlet ("p-cactions", "p-personal", "p-navigation" or "p-tb")
 * @param String href -- link URL
 * @param String text -- link text (will be automatically lowercased by CSS for p-cactions in Monobook)
 * @param String id -- id of the new item, should be unique and preferably have the appropriate prefix ("ca-", "pt-", "n-" or "t-")
 * @param String tooltip -- text to show when hovering over the link, without accesskey suffix
 * @param String accesskey -- accesskey to activate this link (one character, try to avoid conflicts)
 * @param Node nextnode -- the DOM node before which the new item should be added, should be another item in the same list
 *
 * @return Node -- the DOM node of the new item (an LI element) or null
 */
function addPortletLink(portlet, href, text, id, tooltip, accesskey, nextnode) {
	var node = document.getElementById(portlet);
	if ( !node ) return null;
	node = node.getElementsByTagName( "ul" )[0];
	if ( !node ) return null;

	var link = document.createElement( "a" );
	link.appendChild( document.createTextNode( text ) );
	link.href = href;

	var item = document.createElement( "li" );
	item.appendChild( link );
	if ( id ) item.id = id;

	if ( accesskey ) {
		link.setAttribute( "accesskey", accesskey );
		tooltip += " ["+accesskey+"]";
	}
	if ( tooltip ) {
		link.setAttribute( "title", tooltip );
	}
	if ( accesskey && tooltip ) {
		updateTooltipAccessKeys( new Array( link ) );
	}

	if ( nextnode && nextnode.parentNode == node )
		node.insertBefore( item, nextnode );
	else
		node.appendChild( item );  // IE compatibility (?)

	return item;
}


/**
 * Set up accesskeys/tooltips from the deprecated ta array.  If doId
 * is specified, only set up for that id.  Note that this function is
 * deprecated and will not be supported indefinitely -- use
 * updateTooltipAccessKey() instead.
 *
 * @param mixed doId string or null
 */
function akeytt( doId ) {
	// A lot of user scripts (and some of the code below) break if
	// ta isn't defined, so we make sure it is.  Explictly using
	// window.ta avoids a "ta is not defined" error.
	if (!window.ta) window.ta = new Array;

	// Make a local, possibly restricted, copy to avoid clobbering
	// the original.
	var ta;
	if ( doId ) {
		ta = [doId];
	} else {
		ta = window.ta;
	}

	// Now deal with evil deprecated ta
	var watchCheckboxExists = document.getElementById( 'wpWatchthis' ) ? true : false;
	for (var id in ta) {
		var n = document.getElementById(id);
		if (n) {
			var a = null;
			var ak = '';
			// Are we putting accesskey in it
			if (ta[id][0].length > 0) {
				// Is this object a object? If not assume it's the next child.

				if (n.nodeName.toLowerCase() == "a") {
					a = n;
				} else {
					a = n.childNodes[0];
				}
			 	// Don't add an accesskey for the watch tab if the watch
			 	// checkbox is also available.
				if (a && ((id != 'ca-watch' && id != 'ca-unwatch') || !watchCheckboxExists)) {
					a.accessKey = ta[id][0];
					ak = ' ['+tooltipAccessKeyPrefix+ta[id][0]+']';
				}
			} else {
				// We don't care what type the object is when assigning tooltip
				a = n;
				ak = '';
			}

			if (a) {
				a.title = ta[id][1]+ak;
			}
		}
	}
}

function setupRightClickEdit() {
	if (document.getElementsByTagName) {
		var spans = document.getElementsByTagName('span');
		for (var i = 0; i < spans.length; i++) {
			var el = spans[i];
			if(el.className == 'editsection') {
				addRightClickEditHandler(el);
			}
		}
	}
}

function addRightClickEditHandler(el) {
	for (var i = 0; i < el.childNodes.length; i++) {
		var link = el.childNodes[i];
		if (link.nodeType == 1 && link.nodeName.toLowerCase() == 'a') {
			var editHref = link.getAttribute('href');
			// find the enclosing (parent) header
			var prev = el.parentNode;
			if (prev && prev.nodeType == 1 &&
			prev.nodeName.match(/^[Hh][1-6]$/)) {
				prev.oncontextmenu = function(e) {
					if (!e) { e = window.event; }
					// e is now the event in all browsers
					var targ;
					if (e.target) { targ = e.target; }
					else if (e.srcElement) { targ = e.srcElement; }
					if (targ.nodeType == 3) { // defeat Safari bug
						targ = targ.parentNode;
					}
					// targ is now the target element

					// We don't want to deprive the noble reader of a context menu
					// for the section edit link, do we?  (Might want to extend this
					// to all <a>'s?)
					if (targ.nodeName.toLowerCase() != 'a'
					|| targ.parentNode.className != 'editsection') {
						document.location = editHref;
						return false;
					}
					return true;
				};
			}
		}
	}
}

var checkboxes;
var lastCheckbox;

function setupCheckboxShiftClick() {
	checkboxes = [];
	lastCheckbox = null;
	var inputs = document.getElementsByTagName('input');
	addCheckboxClickHandlers(inputs);
}

function addCheckboxClickHandlers(inputs, start) {
	if ( !start) start = 0;

	var finish = start + 250;
	if ( finish > inputs.length )
		finish = inputs.length;

	for ( var i = start; i < finish; i++ ) {
		var cb = inputs[i];
		if ( !cb.type || cb.type.toLowerCase() != 'checkbox' )
			continue;
		var end = checkboxes.length;
		checkboxes[end] = cb;
		cb.index = end;
		cb.onclick = checkboxClickHandler;
	}

	if ( finish < inputs.length ) {
		setTimeout( function () {
			addCheckboxClickHandlers(inputs, finish);
		}, 200 );
	}
}

function checkboxClickHandler(e) {
	if (typeof e == 'undefined') {
		e = window.event;
	}
	if ( !e.shiftKey || lastCheckbox === null ) {
		lastCheckbox = this.index;
		return true;
	}
	var endState = this.checked;
	var start, finish;
	if ( this.index < lastCheckbox ) {
		start = this.index + 1;
		finish = lastCheckbox;
	} else {
		start = lastCheckbox;
		finish = this.index - 1;
	}
	for (var i = start; i <= finish; ++i ) {
		checkboxes[i].checked = endState;
	}
	lastCheckbox = this.index;
	return true;
}

function toggle_element_activation(ida,idb) {
	if (!document.getElementById) {
		return;
	}
	document.getElementById(ida).disabled=true;
	document.getElementById(idb).disabled=false;
}

function toggle_element_check(ida,idb) {
	if (!document.getElementById) {
		return;
	}
	document.getElementById(ida).checked=true;
	document.getElementById(idb).checked=false;
}

/**
 * Restore the edit box scroll state following a preview operation,
 * and set up a form submission handler to remember this state
 */
function scrollEditBox() {
	var editBox = document.getElementById( 'wpTextbox1' );
	var scrollTop = document.getElementById( 'wpScrolltop' );
	var editForm = document.getElementById( 'editform' );
	if( editBox && scrollTop ) {
		if( scrollTop.value )
			editBox.scrollTop = scrollTop.value;
		addHandler( editForm, 'submit', function() {
			document.getElementById( 'wpScrolltop' ).value = document.getElementById( 'wpTextbox1' ).scrollTop; 
		} );
	}
}
hookEvent( 'load', scrollEditBox );

var allmessages_nodelist = false;
var allmessages_modified = false;
var allmessages_timeout = false;
var allmessages_running = false;

function allmessagesmodified() {
	allmessages_modified = !allmessages_modified;
	allmessagesfilter();
}

function allmessagesfilter() {
	if ( allmessages_timeout )
		window.clearTimeout( allmessages_timeout );

	if ( !allmessages_running )
		allmessages_timeout = window.setTimeout( 'allmessagesfilter_do();', 500 );
}

function allmessagesfilter_do() {
	if ( !allmessages_nodelist )
		return;

	var text = document.getElementById('allmessagesinput').value;
	var nodef = allmessages_modified;

	allmessages_running = true;

	for ( var name in allmessages_nodelist ) {
		var nodes = allmessages_nodelist[name];
		var display = ( name.indexOf( text ) == -1 ? 'none' : '' );

		for ( var i = 0; i < nodes.length; i++)
			nodes[i].style.display =
				( nodes[i].className == "def" && nodef
				  ? 'none' : display );
	}

	if ( text != document.getElementById('allmessagesinput').value ||
	     nodef != allmessages_modified )
		allmessagesfilter_do();  // repeat

	allmessages_running = false;
}

function allmessagesfilter_init() {
	if ( allmessages_nodelist )
		return;

	var nodelist = new Array();
	var templist = new Array();

	var table = document.getElementById('allmessagestable');
	if ( !table ) return;

	var rows = document.getElementsByTagName('tr');
	for ( var i = 0; i < rows.length; i++ ) {
		var id = rows[i].getAttribute('id')
		if ( id && id.substring(0,16) != 'sp-allmessages-r' ) continue;
		templist[ id ] = rows[i];
	}

	var spans = table.getElementsByTagName('span');
	for ( var i = 0; i < spans.length; i++ ) {
		var id = spans[i].getAttribute('id')
		if ( id && id.substring(0,17) != 'sp-allmessages-i-' ) continue;
		if ( !spans[i].firstChild || spans[i].firstChild.nodeType != 3 ) continue;

		var nodes = new Array();
		var row1 = templist[ id.replace('i', 'r1') ];
		var row2 = templist[ id.replace('i', 'r2') ];

		if ( row1 ) nodes[nodes.length] = row1;
		if ( row2 ) nodes[nodes.length] = row2;
		nodelist[ spans[i].firstChild.nodeValue ] = nodes;
	}

	var k = document.getElementById('allmessagesfilter');
	if (k) { k.style.display = ''; }

	allmessages_nodelist = nodelist;
}

hookEvent( "load", allmessagesfilter_init );

/*
	Written by Jonathan Snook, http://www.snook.ca/jonathan
	Add-ons by Robert Nyman, http://www.robertnyman.com
	Author says "The credit comment is all it takes, no license. Go crazy with it!:-)"
	From http://www.robertnyman.com/2005/11/07/the-ultimate-getelementsbyclassname/
*/
function getElementsByClassName(oElm, strTagName, oClassNames){
	var arrElements = (strTagName == "*" && oElm.all)? oElm.all : oElm.getElementsByTagName(strTagName);
	var arrReturnElements = new Array();
	var arrRegExpClassNames = new Array();
	if(typeof oClassNames == "object"){
		for(var i=0; i<oClassNames.length; i++){
			arrRegExpClassNames[arrRegExpClassNames.length] =
				new RegExp("(^|\\s)" + oClassNames[i].replace(/\-/g, "\\-") + "(\\s|$)");
		}
	}
	else{
		arrRegExpClassNames[arrRegExpClassNames.length] =
			new RegExp("(^|\\s)" + oClassNames.replace(/\-/g, "\\-") + "(\\s|$)");
	}
	var oElement;
	var bMatchesAll;
	for(var j=0; j<arrElements.length; j++){
		oElement = arrElements[j];
		bMatchesAll = true;
		for(var k=0; k<arrRegExpClassNames.length; k++){
			if(!arrRegExpClassNames[k].test(oElement.className)){
				bMatchesAll = false;
				break;
			}
		}
		if(bMatchesAll){
			arrReturnElements[arrReturnElements.length] = oElement;
		}
	}
	return (arrReturnElements)
}

function redirectToFragment(fragment) {
	var match = navigator.userAgent.match(/AppleWebKit\/(\d+)/);
	if (match) {
		var webKitVersion = parseInt(match[1]);
		if (webKitVersion < 420) {
			// Released Safari w/ WebKit 418.9.1 messes up horribly
			// Nightlies of 420+ are ok
			return;
		}
	}
	if (is_gecko) {
		// Mozilla needs to wait until after load, otherwise the window doesn't scroll
		addOnloadHook(function () {
			if (window.location.hash == "")
				window.location.hash = fragment;
		});
	} else {
		if (window.location.hash == "")
			window.location.hash = fragment;
	}
}


/*
 * Table sorting script  by Joost de Valk, check it out at http://www.joostdevalk.nl/code/sortable-table/.
 * Based on a script from http://www.kryogenix.org/code/browser/sorttable/.
 * Distributed under the MIT license: http://www.kryogenix.org/code/browser/licence.html .
 *
 * Copyright (c) 1997-2006 Stuart Langridge, Joost de Valk.
 *
 * @todo don't break on colspans/rowspans (bug 8028)
 * @todo language-specific digit grouping/decimals (bug 8063)
 * @todo support all accepted date formats (bug 8226)
 */

var ts_image_path = stylepath+"/common/images/";
var ts_image_up = "sort_up.gif";
var ts_image_down = "sort_down.gif";
var ts_image_none = "sort_none.gif";
var ts_europeandate = wgContentLanguage != "en"; // The non-American-inclined can change to "true"
var ts_alternate_row_colors = true;
var SORT_COLUMN_INDEX;

function sortables_init() {
	var idnum = 0;
	// Find all tables with class sortable and make them sortable
	var tables = getElementsByClassName(document, "table", "sortable");
	for (var ti = 0; ti < tables.length ; ti++) {
		if (!tables[ti].id) {
			tables[ti].setAttribute('id','sortable_table_id_'+idnum);
			++idnum;
		}
		ts_makeSortable(tables[ti]);
	}
}

function ts_makeSortable(table) {
	var firstRow;
	if (table.rows && table.rows.length > 0) {
		if (table.tHead && table.tHead.rows.length > 0) {
			firstRow = table.tHead.rows[table.tHead.rows.length-1];
		} else {
			firstRow = table.rows[0];
		}
	}
	if (!firstRow) return;

	// We have a first row: assume it's the header, and make its contents clickable links
	for (var i = 0; i < firstRow.cells.length; i++) {
		var cell = firstRow.cells[i];
		if ((" "+cell.className+" ").indexOf(" unsortable ") == -1) {
			cell.innerHTML += '&nbsp;&nbsp;<a href="#" class="sortheader" onclick="ts_resortTable(this);return false;"><span class="sortarrow"><img src="'+ ts_image_path + ts_image_none + '" alt="&darr;"/></span></a>';
		}
	}
	if (ts_alternate_row_colors) {
		ts_alternate(table);
	}
}

function ts_getInnerText(el) {
	if (typeof el == "string") return el;
	if (typeof el == "undefined") { return el };
	if (el.textContent) return el.textContent; // not needed but it is faster
	if (el.innerText) return el.innerText;     // IE doesn't have textContent
	var str = "";

	var cs = el.childNodes;
	var l = cs.length;
	for (var i = 0; i < l; i++) {
		switch (cs[i].nodeType) {
			case 1: //ELEMENT_NODE
				str += ts_getInnerText(cs[i]);
				break;
			case 3:	//TEXT_NODE
				str += cs[i].nodeValue;
				break;
		}
	}
	return str;
}

function ts_resortTable(lnk) {
	// get the span
	var span = lnk.getElementsByTagName('span')[0];

	var td = lnk.parentNode;
	var tr = td.parentNode;
	var column = td.cellIndex;

	var table = tr.parentNode;
	while (table && !(table.tagName && table.tagName.toLowerCase() == 'table'))
		table = table.parentNode;
	if (!table) return;

	// Work out a type for the column
	if (table.rows.length <= 1) return;

	// Skip the first row if that's where the headings are
	var rowStart = (table.tHead && table.tHead.rows.length > 0 ? 0 : 1);

	var itm = "";
	for (var i = rowStart; i < table.rows.length; i++) {
		if (table.rows[i].cells.length > column) {
			itm = ts_getInnerText(table.rows[i].cells[column]);
			itm = itm.replace(/^[\s\xa0]+/, "").replace(/[\s\xa0]+$/, "");
			if (itm != "") break;
		}
	}

	sortfn = ts_sort_caseinsensitive;
	if (itm.match(/^\d\d[\/. -][a-zA-Z]{3}[\/. -]\d\d\d\d$/))
		sortfn = ts_sort_date;
	if (itm.match(/^\d\d[\/.-]\d\d[\/.-]\d\d\d\d$/))
		sortfn = ts_sort_date;
	if (itm.match(/^\d\d[\/.-]\d\d[\/.-]\d\d$/))
		sortfn = ts_sort_date;
	if (itm.match(/^[\u00a3$\u20ac]/)) // pound dollar euro
		sortfn = ts_sort_currency;
	if (itm.match(/^[\d.,]+\%?$/))
		sortfn = ts_sort_numeric;

	var reverse = (span.getAttribute("sortdir") == 'down');

	var newRows = new Array();
	for (var j = rowStart; j < table.rows.length; j++) {
		var row = table.rows[j];
		var keyText = ts_getInnerText(row.cells[column]);
		var oldIndex = (reverse ? -j : j);

		newRows[newRows.length] = new Array(row, keyText, oldIndex);
	}

	newRows.sort(sortfn);

	var arrowHTML;
	if (reverse) {
			arrowHTML = '<img src="'+ ts_image_path + ts_image_down + '" alt="&darr;"/>';
			newRows.reverse();
			span.setAttribute('sortdir','up');
	} else {
			arrowHTML = '<img src="'+ ts_image_path + ts_image_up + '" alt="&uarr;"/>';
			span.setAttribute('sortdir','down');
	}

	// We appendChild rows that already exist to the tbody, so it moves them rather than creating new ones
	// don't do sortbottom rows
	for (var i = 0; i < newRows.length; i++) {
		if ((" "+newRows[i][0].className+" ").indexOf(" sortbottom ") == -1)
			table.tBodies[0].appendChild(newRows[i][0]);
	}
	// do sortbottom rows only
	for (var i = 0; i < newRows.length; i++) {
		if ((" "+newRows[i][0].className+" ").indexOf(" sortbottom ") != -1)
			table.tBodies[0].appendChild(newRows[i][0]);
	}

	// Delete any other arrows there may be showing
	var spans = getElementsByClassName(tr, "span", "sortarrow");
	for (var i = 0; i < spans.length; i++) {
		spans[i].innerHTML = '<img src="'+ ts_image_path + ts_image_none + '" alt="&darr;"/>';
	}
	span.innerHTML = arrowHTML;

	ts_alternate(table);		
}

function ts_dateToSortKey(date) {	
	// y2k notes: two digit years less than 50 are treated as 20XX, greater than 50 are treated as 19XX
	if (date.length == 11) {
		switch (date.substr(3,3).toLowerCase()) {
			case "jan": var month = "01"; break;
			case "feb": var month = "02"; break;
			case "mar": var month = "03"; break;
			case "apr": var month = "04"; break;
			case "may": var month = "05"; break;
			case "jun": var month = "06"; break;
			case "jul": var month = "07"; break;
			case "aug": var month = "08"; break;
			case "sep": var month = "09"; break;
			case "oct": var month = "10"; break;
			case "nov": var month = "11"; break;
			case "dec": var month = "12"; break;
			// default: var month = "00";
		}
		return date.substr(7,4)+month+date.substr(0,2);
	} else if (date.length == 10) {
		if (ts_europeandate == false) {
			return date.substr(6,4)+date.substr(0,2)+date.substr(3,2);
		} else {
			return date.substr(6,4)+date.substr(3,2)+date.substr(0,2);
		}
	} else if (date.length == 8) {
		yr = date.substr(6,2);
		if (parseInt(yr) < 50) { 
			yr = '20'+yr; 
		} else { 
			yr = '19'+yr; 
		}
		if (ts_europeandate == true) {
			return yr+date.substr(3,2)+date.substr(0,2);
		} else {
			return yr+date.substr(0,2)+date.substr(3,2);
		}
	}
	return "00000000";
}

function ts_parseFloat(num) {
	if (!num) return 0;
	num = parseFloat(num.replace(/,/g, ""));
	return (isNaN(num) ? 0 : num);
}

function ts_sort_date(a,b) {
	var aa = ts_dateToSortKey(a[1]);
	var bb = ts_dateToSortKey(b[1]);
	return (aa < bb ? -1 : aa > bb ? 1 : a[2] - b[2]);
}

function ts_sort_currency(a,b) {
	var aa = ts_parseFloat(a[1].replace(/[^0-9.]/g,''));
	var bb = ts_parseFloat(b[1].replace(/[^0-9.]/g,''));
	return (aa != bb ? aa - bb : a[2] - b[2]);
}

function ts_sort_numeric(a,b) {
	var aa = ts_parseFloat(a[1]);
	var bb = ts_parseFloat(b[1]);
	return (aa != bb ? aa - bb : a[2] - b[2]);
}

function ts_sort_caseinsensitive(a,b) {
	var aa = a[1].toLowerCase();
	var bb = b[1].toLowerCase();
	return (aa < bb ? -1 : aa > bb ? 1 : a[2] - b[2]);
}

function ts_sort_default(a,b) {
	return (a[1] < b[1] ? -1 : a[1] > b[1] ? 1 : a[2] - b[2]);
}

function ts_alternate(table) {
	// Take object table and get all it's tbodies.
	var tableBodies = table.getElementsByTagName("tbody");
	// Loop through these tbodies
	for (var i = 0; i < tableBodies.length; i++) {
		// Take the tbody, and get all it's rows
		var tableRows = tableBodies[i].getElementsByTagName("tr");
		// Loop through these rows
		// Start at 1 because we want to leave the heading row untouched
		for (var j = 0; j < tableRows.length; j++) {
			// Check if j is even, and apply classes for both possible results
			var oldClasses = tableRows[j].className.split(" ");
			var newClassName = "";
			for (var k = 0; k < oldClasses.length; k++) {
				if (oldClasses[k] != "" && oldClasses[k] != "even" && oldClasses[k] != "odd")
					newClassName += oldClasses[k] + " ";
			}
			tableRows[j].className = newClassName + (j % 2 == 0 ? "even" : "odd");
		}
	}
}

/*
 * End of table sorting code
 */
 
 
/**
 * Add a cute little box at the top of the screen to inform the user of
 * something, replacing any preexisting message.
 *
 * @param String message HTML to be put inside the right div
 * @param String className   Used in adding a class; should be different for each
 *   call to allow CSS/JS to hide different boxes.  null = no class used.
 * @return Boolean       True on success, false on failure
 */
function jsMsg( message, className ) {
	if ( !document.getElementById ) {
		return false;
	}
	// We special-case skin structures provided by the software.  Skins that
	// choose to abandon or significantly modify our formatting can just define
	// an mw-js-message div to start with.
	var messageDiv = document.getElementById( 'mw-js-message' );
	if ( !messageDiv ) {
		messageDiv = document.createElement( 'div' );
		if ( document.getElementById( 'column-content' )
		&& document.getElementById( 'content' ) ) {
			// MonoBook, presumably
			document.getElementById( 'content' ).insertBefore(
				messageDiv,
				document.getElementById( 'content' ).firstChild
			);
		} else if ( document.getElementById('content')
		&& document.getElementById( 'article' ) ) {
			// Non-Monobook but still recognizable (old-style)
			document.getElementById( 'article').insertBefore(
				messageDiv,
				document.getElementById( 'article' ).firstChild
			);
		} else {
			return false;
		}
	}

	messageDiv.setAttribute( 'id', 'mw-js-message' );
	if( className ) {
		messageDiv.setAttribute( 'class', 'mw-js-message-'+className );
	}
	messageDiv.innerHTML = message;
	return true;
}

/**
 * Inject a cute little progress spinner after the specified element
 *
 * @param element Element to inject after
 * @param id Identifier string (for use with removeSpinner(), below)
 */
function injectSpinner( element, id ) {
	var spinner = document.createElement( "img" );
	spinner.id = "mw-spinner-" + id;
	spinner.src = stylepath + "/common/images/spinner.gif";
	spinner.alt = spinner.title = "...";
	if( element.nextSibling ) {
		element.parentNode.insertBefore( spinner, element.nextSibling );
	} else {
		element.parentNode.appendChild( spinner );
	}
}

/**
 * Remove a progress spinner added with injectSpinner()
 *
 * @param id Identifier string
 */
function removeSpinner( id ) {
	var spinner = document.getElementById( "mw-spinner-" + id );
	if( spinner ) {
		spinner.parentNode.removeChild( spinner );
	}
}


/**
 * Add an event handler to an element
 *
 * @param Element element Element to add handler to
 * @param String attach Event to attach to
 * @param callable handler Event handler callback
 */
function addHandler( element, attach, handler ) {
	if( window.addEventListener ) {
		element.addEventListener( attach, handler, false );
	} else if( window.attachEvent ) {
		element.attachEvent( 'on' + attach, handler );
	}
}

/**
 * Add a click event handler to an element
 *
 * @param Element element Element to add handler to
 * @param callable handler Event handler callback
 */
function addClickHandler( element, handler ) {
	addHandler( element, 'click', handler );
}


function runOnloadHook() {
	// don't run anything below this for non-dom browsers
	if (doneOnloadHook || !(document.getElementById && document.getElementsByTagName)) {
		return;
	}

	// set this before running any hooks, since any errors below
	// might cause the function to terminate prematurely
	doneOnloadHook = true;

	histrowinit();
	unhidetzbutton();
//
//	prefs.js calls addOnloadHook( tabbedprefs ), so the following call is redundant and causes the tabbedprefs toc to display twice.
//
//	tabbedprefs();
	updateTooltipAccessKeys( null );
	akeytt( null );
	scrollEditBox();
	setupCheckboxShiftClick();
	sortables_init();

	// Run any added-on functions
	for (var i = 0; i < onloadFuncts.length; i++) {
		onloadFuncts[i]();
	}
}

// Note: all skins should call runOnloadHook() at the end of html output, so the below should be redundant. It's there just in case.
hookEvent("load", runOnloadHook);



/**
  * Create Google Analytics instance for Citizendium
 */
function loadga() {
	var c; (c = document.createElement("script")).src = "https://www.googletagmanager.com/gtag/js?id=G-W7ML9SNPXT";
	document.head.appendChild(c);

	window.dataLayer = window.dataLayer || [];
	function gtag(){dataLayer.push(arguments);}
	gtag('js', new Date());
	gtag('config', 'G-W7ML9SNPXT');
}

//Call prior function
loadga();


/**
  * Modify link behavior to open in a new tab when contained in a span.newtab
  */
function checklinks(){
	Array.from(document.getElementsByClassName("newtab")).forEach(function(obj){obj.getElementsByTagName("a")[0].target="_blank"});
}

//Call prior function
checklinks();


/* </nowiki> */