Difference between revisions of "MediaWiki:Common.js"

From OpenMedia
Jump to: navigation, search
m (fix markHiddenFormFields: select *all* inputs regardless of type)
 
(47 intermediate revisions by 3 users not shown)
Line 1: Line 1:
 +
/*global jQuery, $, mw, mw.config, console, importScript */
 +
/*jslint maxerr: 50, indent: 2 */
 
/* Any JavaScript here will be loaded for all users on every page load. */
 
/* Any JavaScript here will be loaded for all users on every page load. */
 
// <source lang="javascript">
 
// <source lang="javascript">
Line 5: Line 7:
 
// for authors see http://en.wikipedia.org/w/index.php?title=MediaWiki:Common.js&action=history
 
// for authors see http://en.wikipedia.org/w/index.php?title=MediaWiki:Common.js&action=history
 
// NEW: targetHighlighting (Hagedorn) and collapsibleTables (wikipedia) moved to jKey.js!
 
// NEW: targetHighlighting (Hagedorn) and collapsibleTables (wikipedia) moved to jKey.js!
 
+
/*
 
+
* @requires: MediaWiki:Mw-customcollapsible.js
/* Import more specific scripts if necessary */
+
* @requires: MediaWiki:Multilingual description.js
if (wgAction == "edit" || wgAction == "submit" || wgPageName == "Special:Upload") { //scripts specific to editing pages
+
* @requires: MediaWiki:Common.js/edit.js
 +
* @requires: MediaWiki:AddFileCommentByInputBoxExtension.js
 +
* @requires: MediaWiki:AddNewFileVersion.js
 +
* @requires: MediaWiki:Gadget-ImageAnnotator.js
 +
* @deprecated: MediaWiki:Edittools.js (is loaded by Gadget system MediaWiki:Gadget-Edittools.js)
 +
*/
 +
/* Import more specific scripts if necessary  
 +
if (mw.config.get("wgAction") === "edit" || mw.config.get("wgAction") === "submit" || mw.config.get("wgPageName") === "Special:Upload") { //scripts specific to editing pages
 
     importScript("MediaWiki:Common.js/edit.js");
 
     importScript("MediaWiki:Common.js/edit.js");
 
}
 
}
 +
*/
 +
/* define resource language dictionary as $.jI18n[lang-iso-code][resourceKey] for te first time */
 +
$.jI18n = {};
 +
 +
$.extend(true, $.jI18n, {
 +
  en: {
 +
    CollapseBox_captionCollapse :        "&nbsp;(show less)&nbsp;",
 +
    CollapseBox_captionExpand :          "&nbsp;(more...)&nbsp;",
 +
    CollapseBox_toolTipCollapse :        "(click to hide information below)",
 +
    CollapseBox_toolTipExpand :          "(click to show more information below)"
 +
    },
 +
  de: {
 +
    CollapseBox_captionCollapse :        "&nbsp;(weniger anzeigen)&nbsp;",
 +
    CollapseBox_captionExpand :          "&nbsp;(mehr...)&nbsp;",
 +
    CollapseBox_toolTipCollapse :        "(klicken um Zusatzinformationen zu verbergen)",
 +
    CollapseBox_toolTipExpand :          "(klicken um Zusatzinformationen anzuzeigen)"
 +
    }
 +
});
 +
 +
/*
 +
* Description: Get resource string (text, image URLs) for a given language, based on a string-key
 +
*  If no resource is defined in a given language for a resource key, the resource for "en" will be returned, if this is missing as well an error message.
 +
* resourceKey: key for the resource (string)
 +
*/
 +
$.resource = function (resourceKey) {
 +
    var lang = mw.config.get("wgUserLanguage").split("-")[0]; // language: "pt-BR", "de-formal", etc.
 +
    return ($.jI18n[lang] && $.jI18n[lang][resourceKey] ?
 +
      $.jI18n[lang][resourceKey] :
 +
      ($.jI18n.en[resourceKey]) ? $.jI18n.en[resourceKey] : "MISSING RESOURCE: no $.jI18n.en." + resourceKey + " defined.");
 +
  };
  
 +
// add a comment button to File namespace
 +
importScript("MediaWiki:AddFileCommentByInputBoxExtension.js");
 +
importScript("MediaWiki:AddNewFileVersion.js");
  
 
/* Scripts specific to Internet Explorer */
 
/* Scripts specific to Internet Explorer */
if (navigator.appName == "Microsoft Internet Explorer") {
+
if (navigator.appName === "Microsoft Internet Explorer") {
 
     /** Internet Explorer bug fix **************************************************
 
     /** Internet Explorer bug fix **************************************************
 
     *  Description: Fixes IE horizontal scrollbar bug
 
     *  Description: Fixes IE horizontal scrollbar bug
Line 22: Line 64:
 
     var docEl = document.documentElement;
 
     var docEl = document.documentElement;
  
     function fixIEScroll() {
+
     var fixIEScroll = function() {
         if (!oldWidth || docEl.clientWidth > oldWidth)
+
         if (!oldWidth || docEl.clientWidth > oldWidth) {
 
             doFixIEScroll();
 
             doFixIEScroll();
         else
+
         } else {
 
             setTimeout(doFixIEScroll, 1);
 
             setTimeout(doFixIEScroll, 1);
 +
        }
 
         oldWidth = docEl.clientWidth;
 
         oldWidth = docEl.clientWidth;
     }
+
     };
   
+
 
     function doFixIEScroll() {
+
     var doFixIEScroll = function () {
 
       docEl.style.overflowX = (docEl.scrollWidth - docEl.clientWidth < 4) ? "hidden" : "";
 
       docEl.style.overflowX = (docEl.scrollWidth - docEl.clientWidth < 4) ? "hidden" : "";
     }
+
     };
   
+
 
 
     document.attachEvent("onreadystatechange", fixIEScroll);
 
     document.attachEvent("onreadystatechange", fixIEScroll);
 
     document.attachEvent("onresize", fixIEScroll);
 
     document.attachEvent("onresize", fixIEScroll);
   
+
 
 
     // In print IE (7?) does not like line-height
 
     // In print IE (7?) does not like line-height
 
     appendCSS( '@media print { sup, sub, p, .documentDescription { line-height: normal; }}');
 
     appendCSS( '@media print { sup, sub, p, .documentDescription { line-height: normal; }}');
   
+
 
 
     //Import scripts specific to Internet Explorer 6
 
     //Import scripts specific to Internet Explorer 6
 
     // THIS IS A PNG transparency FIX, here commented out:
 
     // THIS IS A PNG transparency FIX, here commented out:
Line 54: Line 97:
 
  */
 
  */
 
// Not on Special pages, and only if viewing the page
 
// Not on Special pages, and only if viewing the page
if (wgNamespaceNumber != -1 && $.inArray(mw.config.get('wgAction'), ['view', 'purge']) != -1 ) {
+
if (mw.config.get("wgNamespaceNumber") != -1 && $.inArray(mw.config.get('wgAction'), ['view', 'purge']) != -1 ) {
if (typeof ImageAnnotator_disable == 'undefined' || !ImageAnnotator_disable) {
+
  if (typeof ImageAnnotator_disable === 'undefined' || !ImageAnnotator_disable) {
  // Don't even import it if it's disabled.
+
    // Don't even import it if it's disabled.
  importScript('MediaWiki:Gadget-ImageAnnotator.js');
+
    importScript('MediaWiki:Gadget-ImageAnnotator.js');
}
+
  }
 
}
 
}
  
/** Table sorting fixes
+
// Table sorting fixes
  *  Description: Disables code in table sorting routine to set classes on even/odd rows
+
// Disables code in table sorting routine to set classes on even/odd rows
  */
+
var ts_alternate_row_colors = false;
ts_alternate_row_colors = false;
+
  
 +
// helper function to escape jQuery IDs
 +
$.jqueryEscapeId = function (myid) {
 +
  if(myid.substr(0, 1) === "#"){
 +
    return myid.replace(/(:|\.)/g,'\\$1');
 +
  } else {
 +
    return '#' + myid.replace(/(:|\.)/g,'\\$1');
 +
  }
 +
}
  
 
/**
 
/**
  * sort event-tables according to column 3.
+
  * Footenote tooltips from <references>
 +
* @description Footnotes as unformatted tooltip - from it.wikipedia.org under same license
 +
* Note (2015-12-21 14:19:20): Use of "addOnloadHook" is deprecated. Use jQuery instead.
 +
* @returns {undefined}
 
  */
 
  */
function presort() {
+
function reference_footnote_tooltips() {
var table = document.getElementById("event-table");
+
  var sups = document.getElementsByTagName("sup");
if (table != null && table != 'undefined') {
+
  for (var i = sups.length - 1; i >= 0; i -= 1) {
  var sortLink = table.rows[0].cells[2].lastChild;
+
    var note_id = sups[i].childNodes[0].href;
           ts_resortTable(sortLink);
+
    if (note_id && (note_id.indexOf("#") !== -1)) {
 +
      note_id = document.getElementById(note_id.substr(note_id.indexOf("#")+1));
 +
      if (note_id) {
 +
        if (document.all) {
 +
          sups[i].title = note_id.innerText;
 +
          sups[i].childNodes[0].title = note_id.innerText;
 +
        } else {
 +
           sups[i].title = note_id.textContent;
 
         }
 
         }
 +
      }
 +
    }
 +
  }
 
}
 
}
  
// collapsible parts: div and tr → Template:Hidden
 
//  may be fused later with toggleCollapse
 
//  main difference: initCollapsebox() uses a switcher defined by the Wikitemplate
 
//  and is not using a javascript resource title
 
function initCollapsebox() {
 
  /* is nested in: div.collapsebox
 
                    └ div.switcher
 
                    └ div.collapsecontent */
 
  jQuery("div.collapsebox div.switcher").live('click',
 
    function() {
 
      jQuery(this).nextAll("div.collapsecontent:first").slideToggle(250);
 
      /* $(this).toggle() does not work in live as toggle is a bind()
 
          therefore toggle must be bound to a different DOM element */
 
      jQuery(this).find(".show, .hide").toggle();
 
    });
 
  /* is in a table: tr.collapsebox
 
                      └ div.switcher
 
                    tr.collapsecontent */
 
  jQuery("tr.collapsebox div.switcher").live('click',
 
    function() {
 
      jQuery(this).closest("tr.collapsebox").nextAll("tr.collapsecontent:first").toggle();
 
      jQuery(this).find(".show, .hide").toggle();
 
    });
 
}// END initCollapsebox()
 
  
 
///////////////////////////////////
 
///////////////////////////////////
Line 108: Line 147:
 
//////////////////////////////////
 
//////////////////////////////////
 
function initConfirmDeleteSubform() {
 
function initConfirmDeleteSubform() {
   $j.extend(true, $j.jI18n, {
+
   $.extend(true, $.jI18n, {
   en: {  
+
   en: {
 
     message : "'Delete this sub form irreversibly?'"
 
     message : "'Delete this sub form irreversibly?'"
 
     },
 
     },
Line 117: Line 156:
 
   });
 
   });
 
   // default buttons: <input type="button" ... class="remove"/>
 
   // default buttons: <input type="button" ... class="remove"/>
   $j("input.remove").attr("onClick", function() {// case sensitive not: onclick
+
   $("input.remove").attr("onClick", function() {// case sensitive not: onclick
 
     //typeof this.onclick → function
 
     //typeof this.onclick → function
 
     var currentClickHandlerString = this.getAttributeNode('onclick').value;
 
     var currentClickHandlerString = this.getAttributeNode('onclick').value;
 
     // add a confirm
 
     // add a confirm
     return "var removethis = confirm("+$j.resource('message')+");  if(removethis) {return " + currentClickHandlerString + "};";
+
     return "var removethis = confirm("+$.resource('message')+");  if(removethis) {return " + currentClickHandlerString + "};";
 
   });
 
   });
 
   /* added delete buttons by the SMW-form: <input type="button" />
 
   /* added delete buttons by the SMW-form: <input type="button" />
 
     add onclick handling */
 
     add onclick handling */
   $j("input.addAnother").click(function () {
+
   $("input.addAnother").click(function () {
 
     // just new generated div#div_gen_1
 
     // just new generated div#div_gen_1
   $j("div")
+
   $("div")
 
     .filter(function() { return this.id.match(/div_gen_\d+/); })
 
     .filter(function() { return this.id.match(/div_gen_\d+/); })
 
     .find(":button")
 
     .find(":button")
 
     .attr("onClick",function() {// case sensitive not: onclick
 
     .attr("onClick",function() {// case sensitive not: onclick
 
       // add a confirm
 
       // add a confirm
       return "var removethis = confirm("+$j.resource('message')+");  if(removethis) {$j('#' + String($j(this).parent().attr('id'))).remove();} else {return false;};";
+
       return "var removethis = confirm("+$.resource('message')+");  if(removethis) {$('#' + String($(this).parent().attr('id'))).remove();} else {return false;};";
 
     });
 
     });
 
   });
 
   });
 
}// end initConfirmDeleteSubform()
 
}// end initConfirmDeleteSubform()
+
 
 
/*
 
/*
///////////////////////////////////
+
  @description indicates form elements created by template:Hidden
// indicate hidden inputs created
+
  having class indicateHiddenInputs or other fields
// from template:Hidden
+
 
//////////////////////////////////
+
  structure of template:Hidden:
structure of template:Hidden:
+
  div.mw-collapsible
+
    └ div.mw-collapsible-content.indicateHiddenInputs
div.collapsebox
+
 
  ├ div.switcher (float)
+
  @return null|true
  ├ div.collapsetitle
+
*/
  └ div.collapsecontent
+
window.markHiddenFormFields = function () {
+
  "use strict";
tr.collapsebox
+
   var jDivHiddenFormTexts = $(
  └ th/td
+
     // select all inputs that have definite values
      ├ div.switcher (float)
+
      'div.mw-collapsible-content.indicateHiddenInputs * input'
      └ div.collapsetitle
+
     ).filter(
tr.collapsecontent
+
      function () { return this.value.length > 0 }
*/
+
     )
function initMarkHiddenInputs(){
+
    .add(
   var jDivHiddenFormTexts = $j(
+
     // select only textarea not being empty
     // select only input type text + textarea with values
+
      'div.mw-collapsible-content.indicateHiddenInputs * textarea:not(:empty)'
      "div.collapsecontent.indicateHiddenInputs * :text[value!=]"
+
     ),
     +", div.collapsecontent.indicateHiddenInputs * textarea[value!=]"
+
    /*
     );
+
    pale orange:
  var jTrHiddenFormTexts = $j(
+
    hsv →  36 20 99 36 10 99  36 05 99
     // select only input type text + textarea with values
+
          #fce8ca  #fcf2e3  #fcf7f0
      "tr.collapsecontent.indicateHiddenInputs *:not(.collapsecontent) :text[value!=]"
+
    pale yellow
     +", tr.collapsecontent.indicateHiddenInputs *:not(.collapsecontent) textarea[value!=]"
+
    hsv → 50 18 100  50 10 100
     );
+
          #fff7d0    #fffbe6
 +
    */
 +
    bgcolor =       {'background-color':'#fffbe6'},
 +
     bgcolor_darker = {'background-color':'#fff7d0'};
 +
 
 
// <div>
 
// <div>
   jDivHiddenFormTexts
+
   if (jDivHiddenFormTexts.length) {
     .parents(".collapsebox")
+
     jDivHiddenFormTexts
    .css({'border-left':'2px solid #ce5c00'});
+
      .closest(".mw-collapsible")
  //indicate the fields itself
+
      .css({'border-left': '2px solid #ce5c00'})
  jDivHiddenFormTexts
+
      .find(".mw-collapsible-toggle")
    .css({'background-color':'#fcdeb1'}); //pale orange
+
      .css(bgcolor_darker);
// <tr>
+
    //indicate the fields itself
  //indicate the fields itself
+
    jDivHiddenFormTexts
  jTrHiddenFormTexts
+
      .css(bgcolor); //pale orange
    .css({'background-color':'#fcdeb1'}); //pale orange
+
    return true;
  //indicate current level
+
   } else {
   jTrHiddenFormTexts
+
     return null;
     .closest(".collapsebox")
+
  }
    .css({'border-left':'2px solid #ce5c00'});
+
// <td> implement in Template:Hidden
  // to ?upermost level
+
}; // markHiddenFormFields()
  jTrHiddenFormTexts
+
    .parents(".collapsecontent")
+
    .prev(".collapsebox")
+
    .css({'border-left':'2px solid #ce5c00'});  
+
}// END initMarkHiddenInputs()
+
  
addOnloadHook(presort);
+
function showSynonymFileNames() {
$j(document).ready(function() {
+
  // does only work when ":File:....jpg" is linked, not with "File:....jpg"
 +
  // it is recommended to do a redirect like so: "#REDIRECT [[:File:BEQ1B VT Schaedel Alke.jpg]]{{redirect}}"
 +
  var apiUrl = mw.config.get("wgServer")+mw.util.wikiScript("api"),
 +
  backLinkDataParameter = {
 +
      "bltitle":mw.config.get("wgPageName"),
 +
      "format":"json",
 +
      "action":"query",
 +
      "list":"backlinks",
 +
      "blfilterredir":"redirects"
 +
  };
 +
  // list redirect files as synonym files
 +
  $.getJSON(apiUrl , backLinkDataParameter)
 +
    .done(function( responseText ) {
 +
      if (responseText.query.backlinks.length) {
 +
        $("ul#filetoc").append('<li class="show-synonym-file-names"></li>');
 +
        $.each(responseText.query.backlinks, function(i, backlinks) {
 +
          if (i===0) {
 +
            $("ul#filetoc .show-synonym-file-names").html("<i>You can also use the synonym file name(s): </i>").append("<ul>");
 +
            //$("ul#filetoc .show-synonym-file-names ul").append("<li>").html(backlinks.title);
 +
          }
 +
          $("ul#filetoc .show-synonym-file-names ul").append("<li>" + backlinks.title + "</li>");
 +
        });
 +
      }
 +
  });
 +
}// showSynonymFileNames()
 +
 
 +
// click-text modifications for mw-customcollapsible triggering from outside of mw-collapsible
 +
importScript("MediaWiki:Mw-customcollapsible.js");
 +
 
 +
/**
 +
* @description create jQuery UI Tabs on CSS class="use-jquery-ui-tabs" Used for Form:Metadata/Metadata_Fusaria_Autographice_Delineata_Wollenweber
 +
*
 +
* @requires https://www.mediawiki.org/wiki/Extension:Semantic_Forms
 +
* @requires jQuery-UI mw.loader.using( 'jquery.ui.tabs', function () {});
 +
* @returns {undefined}
 +
*/
 +
function initUiTabsInForms() {
 +
  console.log("initUiTabsInForms");
 +
  var use_jquery_ui_tabs= $(".use-jquery-ui-tabs");
 +
  var use_jquery_ui_tabs_vertical= $(".use-jquery-ui-tabs-vertical");
 +
  if (use_jquery_ui_tabs.length || use_jquery_ui_tabs_vertical.length) {
 +
    mw.loader.using( 'jquery.ui.tabs', function () {
 +
      var use_jquery_ui_tabs= $(".use-jquery-ui-tabs");// Google Chrome Fix
 +
      var use_jquery_ui_tabs_vertical= $(".use-jquery-ui-tabs-vertical");// Google Chrome Fix
 +
      console.log("initUiTabsInForms mw.loader.using");
 +
      if ($(".use-jquery-ui-tabs").length) {
 +
        $(".use-jquery-ui-tabs").tabs({event: "mouseover"});
 +
        console.log("initUiTabsInForms tabs");
 +
      }
 +
      if (use_jquery_ui_tabs_vertical.length) {
 +
        use_jquery_ui_tabs_vertical.tabs({event: "mouseover"}).addClass( "ui-tabs-vertical ui-helper-clearfix" );
 +
        use_jquery_ui_tabs_vertical.find( "li" ).removeClass( "ui-corner-top" ).addClass( "ui-corner-left" );
 +
        console.log("initUiTabsInForms tabs_vertical");
 +
      }
 +
    });
 +
  }
 +
}
 +
/**
 +
* Hide Category:Taxon Category
 +
*
 +
* Display only the taxa and hide Category:Taxon Category and its parents/siblings
 +
* @requires: Template:Taxinfo CSS class "table.category-taxon-tree"
 +
*/
 +
function hideTaxonCategoryInCategoryTree () {
 +
  if($('table.category-taxon-tree').length) {
 +
    $('div.CategoryTreeItem').each(function () {
 +
      $(this).css({'display': ( $(this).text().match(/Taxon categor(y|ies)$/) ? 'none' : 'block') });
 +
      $(this).siblings('.CategoryTreeChildren').css({'display': ( $(this).text().match(/Taxon categor(y|ies)$/) ? 'none' : 'block') }); 
 +
    });
 +
  }
 +
}
 +
$(document).ready(function() {
 
   // try to add the toolbar on uploading
 
   // try to add the toolbar on uploading
   if(wgPageName == "Special:Upload" && wgUserName){
+
   if(mw.config.get("wgPageName") === "Special:Upload" && mw.config.get("wgUserName")){
   $j("textarea#wpUploadDescription").before('<div id="toolbar"></div>');
+
   $("textarea#wpUploadDescription").before('<div id="toolbar"></div>');
 
   }
 
   }
  initCollapsebox();//collapsable parts
 
 
   // page specific
 
   // page specific
   if(wgAction=="formedit" || wgPageName=="Spezial:FormEdit"){
+
   if(mw.config.get("wgAction")==="formedit"  
 +
  || mw.config.get("wgPageName")==="Special:FormEdit"
 +
  || mw.config.get( 'wgCanonicalSpecialPageName' )==="FormEdit"){
 
     initConfirmDeleteSubform();
 
     initConfirmDeleteSubform();
     initMarkHiddenInputs();
+
     markHiddenFormFields();
 +
    initUiTabsInForms();
 +
  }
 +
  // page specific
 +
  if (mw.config.get("wgNamespaceNumber") === 6 ) { // File
 +
    showSynonymFileNames();
 
   }
 
   }
 +
  hideTaxonCategoryInCategoryTree();
 +
  reference_footnote_tooltips()
 
});
 
});
  
 
importScript('MediaWiki:Multilingual description.js');
 
importScript('MediaWiki:Multilingual description.js');
// </source>
+
//</source>

Latest revision as of 14:05, 6 November 2016

/*global jQuery, $, mw, mw.config, console, importScript */
/*jslint maxerr: 50, indent: 2 */
/* Any JavaScript here will be loaded for all users on every page load. */
// <source lang="javascript">
// This JavaScript will be loaded for all users on every page load.
// Except for additions at the end, imported from en.wikipedia.org and modified (parts removed).
// for authors see http://en.wikipedia.org/w/index.php?title=MediaWiki:Common.js&action=history
// NEW: targetHighlighting (Hagedorn) and collapsibleTables (wikipedia) moved to jKey.js!
/*
 * @requires: MediaWiki:Mw-customcollapsible.js
 * @requires: MediaWiki:Multilingual description.js
 * @requires: MediaWiki:Common.js/edit.js
 * @requires: MediaWiki:AddFileCommentByInputBoxExtension.js
 * @requires: MediaWiki:AddNewFileVersion.js
 * @requires: MediaWiki:Gadget-ImageAnnotator.js
 * @deprecated: MediaWiki:Edittools.js (is loaded by Gadget system MediaWiki:Gadget-Edittools.js)
*/
/* Import more specific scripts if necessary 
if (mw.config.get("wgAction") === "edit" || mw.config.get("wgAction") === "submit" || mw.config.get("wgPageName") === "Special:Upload") { //scripts specific to editing pages
    importScript("MediaWiki:Common.js/edit.js");
}
*/
/* define resource language dictionary as $.jI18n[lang-iso-code][resourceKey] for te first time */
$.jI18n = {};

$.extend(true, $.jI18n, {
  en: {
    CollapseBox_captionCollapse :        "&nbsp;(show less)&nbsp;",
    CollapseBox_captionExpand :          "&nbsp;(more...)&nbsp;",
    CollapseBox_toolTipCollapse :        "(click to hide information below)",
    CollapseBox_toolTipExpand :          "(click to show more information below)"
    },
  de: {
    CollapseBox_captionCollapse :        "&nbsp;(weniger anzeigen)&nbsp;",
    CollapseBox_captionExpand :          "&nbsp;(mehr...)&nbsp;",
    CollapseBox_toolTipCollapse :        "(klicken um Zusatzinformationen zu verbergen)",
    CollapseBox_toolTipExpand :          "(klicken um Zusatzinformationen anzuzeigen)"
    }
});

/*
 * Description: Get resource string (text, image URLs) for a given language, based on a string-key
 *  If no resource is defined in a given language for a resource key, the resource for "en" will be returned, if this is missing as well an error message.
 * resourceKey: key for the resource (string)
 */
$.resource = function (resourceKey) {
    var lang = mw.config.get("wgUserLanguage").split("-")[0]; // language: "pt-BR", "de-formal", etc.
    return ($.jI18n[lang] && $.jI18n[lang][resourceKey] ?
      $.jI18n[lang][resourceKey] :
      ($.jI18n.en[resourceKey]) ? $.jI18n.en[resourceKey] : "MISSING RESOURCE: no $.jI18n.en." + resourceKey + " defined.");
  };

// add a comment button to File namespace
importScript("MediaWiki:AddFileCommentByInputBoxExtension.js");
importScript("MediaWiki:AddNewFileVersion.js");

/* Scripts specific to Internet Explorer */
if (navigator.appName === "Microsoft Internet Explorer") {
    /** Internet Explorer bug fix **************************************************
     *  Description: Fixes IE horizontal scrollbar bug
     *  Maintainers: [[User:Tom-]]?
     */
    var oldWidth;
    var docEl = document.documentElement;

    var fixIEScroll = function() {
        if (!oldWidth || docEl.clientWidth > oldWidth) {
            doFixIEScroll();
        } else {
            setTimeout(doFixIEScroll, 1);
        }
        oldWidth = docEl.clientWidth;
    };

    var doFixIEScroll = function () {
      docEl.style.overflowX = (docEl.scrollWidth - docEl.clientWidth < 4) ? "hidden" : "";
    };

    document.attachEvent("onreadystatechange", fixIEScroll);
    document.attachEvent("onresize", fixIEScroll);

    // In print IE (7?) does not like line-height
    appendCSS( '@media print { sup, sub, p, .documentDescription { line-height: normal; }}');

    //Import scripts specific to Internet Explorer 6
    // THIS IS A PNG transparency FIX, here commented out:
    // if (navigator.appVersion.substr(22, 1) == "6") {
    //    importScript("MediaWiki:Common.js/IE60Fixes.js");
    // }
} // END "Microsoft Internet Explorer"

/**
 * ImageAnnotator
 * Globally enabled per
 * http://commons.wikimedia.org/?title=Commons:Village_pump&oldid=26818359#New_interface_feature
 * Maintainer: [[User:Lupo]]
 */
// Not on Special pages, and only if viewing the page
if (mw.config.get("wgNamespaceNumber") != -1 && $.inArray(mw.config.get('wgAction'), ['view', 'purge']) != -1 ) {
  if (typeof ImageAnnotator_disable === 'undefined' || !ImageAnnotator_disable) {
    // Don't even import it if it's disabled.
    importScript('MediaWiki:Gadget-ImageAnnotator.js');
  }
}

// Table sorting fixes
// Disables code in table sorting routine to set classes on even/odd rows
var ts_alternate_row_colors = false;

// helper function to escape jQuery IDs
$.jqueryEscapeId = function (myid) {
  if(myid.substr(0, 1) === "#"){
    return myid.replace(/(:|\.)/g,'\\$1');
  } else {
    return '#' + myid.replace(/(:|\.)/g,'\\$1');
  }
}

/**
 * Footenote tooltips from <references>
 * @description Footnotes as unformatted tooltip - from it.wikipedia.org under same license
 * Note (2015-12-21 14:19:20): Use of "addOnloadHook" is deprecated. Use jQuery instead.
 * @returns {undefined}
 */
function reference_footnote_tooltips() {
  var sups = document.getElementsByTagName("sup");
  for (var i = sups.length - 1; i >= 0; i -= 1) {
    var note_id = sups[i].childNodes[0].href;
    if (note_id && (note_id.indexOf("#") !== -1)) {
      note_id = document.getElementById(note_id.substr(note_id.indexOf("#")+1));
      if (note_id) {
        if (document.all) {
          sups[i].title = note_id.innerText;
          sups[i].childNodes[0].title = note_id.innerText;
        } else {
          sups[i].title = note_id.textContent;
        }
      }
    }
  }
}


///////////////////////////////////
// confirm deletion using SMW forms
//   does not work in IE 6
//////////////////////////////////
function initConfirmDeleteSubform() {
  $.extend(true, $.jI18n, {
  en: {
    message : "'Delete this sub form irreversibly?'"
    },
  de: {
    message : "'Dieses Teilformular unwiderruflich löschen?'"
    }
  });
  // default buttons: <input type="button" ... class="remove"/>
  $("input.remove").attr("onClick", function() {// case sensitive not: onclick
    //typeof this.onclick → function
    var currentClickHandlerString = this.getAttributeNode('onclick').value;
    // add a confirm
    return "var removethis = confirm("+$.resource('message')+");  if(removethis) {return " + currentClickHandlerString + "};";
  });
  /* added delete buttons by the SMW-form: <input type="button" />
    add onclick handling */
  $("input.addAnother").click(function () {
    // just new generated div#div_gen_1
   $("div")
     .filter(function() { return this.id.match(/div_gen_\d+/); })
     .find(":button")
     .attr("onClick",function() {// case sensitive not: onclick
      // add a confirm
       return "var removethis = confirm("+$.resource('message')+");  if(removethis) {$('#' + String($(this).parent().attr('id'))).remove();} else {return false;};";
     });
  });
}// end initConfirmDeleteSubform()

/*
   @description indicates form elements created by template:Hidden
  having class indicateHiddenInputs or other fields

   structure of template:Hidden:
   div.mw-collapsible
    └ div.mw-collapsible-content.indicateHiddenInputs

   @return null|true
 */
window.markHiddenFormFields = function () {
  "use strict";
  var jDivHiddenFormTexts = $(
    // select all inputs that have definite values
      'div.mw-collapsible-content.indicateHiddenInputs * input'
    ).filter(
      function () { return this.value.length > 0 }
    )
    .add(
    // select only textarea not being empty
      'div.mw-collapsible-content.indicateHiddenInputs * textarea:not(:empty)'
    ),
    /*
    pale orange:
    hsv →  36 20 99 36 10 99  36 05 99
           #fce8ca  #fcf2e3   #fcf7f0
    pale yellow
    hsv → 50 18 100  50 10 100
          #fff7d0    #fffbe6
    */
    bgcolor =       {'background-color':'#fffbe6'},
    bgcolor_darker = {'background-color':'#fff7d0'};

// <div>
  if (jDivHiddenFormTexts.length) {
    jDivHiddenFormTexts
      .closest(".mw-collapsible")
      .css({'border-left': '2px solid #ce5c00'})
      .find(".mw-collapsible-toggle")
      .css(bgcolor_darker);
    //indicate the fields itself
    jDivHiddenFormTexts
      .css(bgcolor); //pale orange
    return true;
  } else {
    return null;
  }
// <td> implement in Template:Hidden
}; // markHiddenFormFields()

function showSynonymFileNames() {
  // does only work when ":File:....jpg" is linked, not with "File:....jpg"
  // it is recommended to do a redirect like so: "#REDIRECT [[:File:BEQ1B VT Schaedel Alke.jpg]]{{redirect}}"
  var apiUrl = mw.config.get("wgServer")+mw.util.wikiScript("api"),
  backLinkDataParameter = {
      "bltitle":mw.config.get("wgPageName"),
      "format":"json",
      "action":"query",
      "list":"backlinks",
      "blfilterredir":"redirects"
  };
  // list redirect files as synonym files
  $.getJSON(apiUrl , backLinkDataParameter)
    .done(function( responseText ) {
      if (responseText.query.backlinks.length) {
        $("ul#filetoc").append('<li class="show-synonym-file-names"></li>');
        $.each(responseText.query.backlinks, function(i, backlinks) {
          if (i===0) {
            $("ul#filetoc .show-synonym-file-names").html("<i>You can also use the synonym file name(s): </i>").append("<ul>");
            //$("ul#filetoc .show-synonym-file-names ul").append("<li>").html(backlinks.title);
          }
          $("ul#filetoc .show-synonym-file-names ul").append("<li>" + backlinks.title + "</li>");
        });
      }
  });
}// showSynonymFileNames()

// click-text modifications for mw-customcollapsible triggering from outside of mw-collapsible
importScript("MediaWiki:Mw-customcollapsible.js");

/**
 * @description create jQuery UI Tabs on CSS class="use-jquery-ui-tabs" Used for Form:Metadata/Metadata_Fusaria_Autographice_Delineata_Wollenweber
 * 
 * @requires https://www.mediawiki.org/wiki/Extension:Semantic_Forms
 * @requires jQuery-UI mw.loader.using( 'jquery.ui.tabs', function () {});
 * @returns {undefined}
 */
function initUiTabsInForms() {
  console.log("initUiTabsInForms");
  var use_jquery_ui_tabs= $(".use-jquery-ui-tabs");
  var use_jquery_ui_tabs_vertical= $(".use-jquery-ui-tabs-vertical");
  if (use_jquery_ui_tabs.length || use_jquery_ui_tabs_vertical.length) {
    mw.loader.using( 'jquery.ui.tabs', function () {
      var use_jquery_ui_tabs= $(".use-jquery-ui-tabs");// Google Chrome Fix
      var use_jquery_ui_tabs_vertical= $(".use-jquery-ui-tabs-vertical");// Google Chrome Fix
      console.log("initUiTabsInForms mw.loader.using");
      if ($(".use-jquery-ui-tabs").length) {
        $(".use-jquery-ui-tabs").tabs({event: "mouseover"});
        console.log("initUiTabsInForms tabs");
      }
      if (use_jquery_ui_tabs_vertical.length) {
        use_jquery_ui_tabs_vertical.tabs({event: "mouseover"}).addClass( "ui-tabs-vertical ui-helper-clearfix" );
        use_jquery_ui_tabs_vertical.find( "li" ).removeClass( "ui-corner-top" ).addClass( "ui-corner-left" );
        console.log("initUiTabsInForms tabs_vertical");
      }
    });
  }
}
/**
 * Hide Category:Taxon Category
 *
 * Display only the taxa and hide Category:Taxon Category and its parents/siblings
 * @requires: Template:Taxinfo CSS class "table.category-taxon-tree"
 */
function hideTaxonCategoryInCategoryTree () {
  if($('table.category-taxon-tree').length) {
    $('div.CategoryTreeItem').each(function () {
      $(this).css({'display': ( $(this).text().match(/Taxon categor(y|ies)$/) ? 'none' : 'block') }); 
      $(this).siblings('.CategoryTreeChildren').css({'display': ( $(this).text().match(/Taxon categor(y|ies)$/) ? 'none' : 'block') });   
    });
  }
}
$(document).ready(function() {
  // try to add the toolbar on uploading
  if(mw.config.get("wgPageName") === "Special:Upload" && mw.config.get("wgUserName")){
   $("textarea#wpUploadDescription").before('<div id="toolbar"></div>');
  }
  // page specific
  if(mw.config.get("wgAction")==="formedit" 
  || mw.config.get("wgPageName")==="Special:FormEdit"
  || mw.config.get( 'wgCanonicalSpecialPageName' )==="FormEdit"){
    initConfirmDeleteSubform();
    markHiddenFormFields();
    initUiTabsInForms();
  }
  // page specific
  if (mw.config.get("wgNamespaceNumber") === 6 ) { // File
    showSynonymFileNames();
  }
  hideTaxonCategoryInCategoryTree();
  reference_footnote_tooltips()
});

importScript('MediaWiki:Multilingual description.js');
//</source>