MediaWiki:Common.js

From Meta-Omics Data of Collection Objects
Revision as of 12:50, 7 November 2018 by Andreas Plank (Talk | contribs) (http/https: general solution trimming of protocol (http or https) of //URL)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

Note: After saving, you may have to bypass your browser's cache to see the changes.

  • Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
  • Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
  • Internet Explorer: Hold Ctrl while clicking Refresh, or press Ctrl-F5
  • Opera: Clear the cache in Tools → Preferences
// <pre>
/* Any JavaScript here will be loaded for all users on every page load. 
 *
 * @requires MediaWiki:Jquery.zoomImage.js
 */
$.jI18n = {/*  resource string dictionary
 
  Note: Commons uses collapse/expand ▲/▼, but this looks better in strict box
  layouts that in the free-wrapping key statements
 
  Nomenclature proposal: if an extra plugin is used, strings can be designated as
  “plugin_toolTipSomthing” otherwise just “toolTipSomthing” (global string). So it’s more clear if
  somebody wants to deactivate a plugin and remove strings from the resource dictionary.
*/
  en: {
    captionCollapse :        "&nbsp;(show less)&nbsp;",
    captionExpand :          "&nbsp;(more...)&nbsp;",
    expandAll :              "Show all extras",
    iconCloseWindowHover :   "//upload.wikimedia.org/wikipedia/commons/d/d0/Close_icon_hover.jpg",
    iconCloseWindow :        "//upload.wikimedia.org/wikipedia/commons/8/87/Close_icon_default.jpg",
    iconOverview  :          "//upload.wikimedia.org/wikipedia/commons/thumb/2/22/View-pause_Gion_simple.svg/20px-View-pause_Gion_simple.svg.png",
    iconResume  :            "//upload.wikimedia.org/wikipedia/commons/thumb/4/49/View-playback_Gion_simple.svg/20px-View-playback_Gion_simple.svg.png",
    iconStart1st  :          "//upload.wikimedia.org/wikipedia/commons/thumb/4/49/View-playback_Gion_simple.svg/20px-View-playback_Gion_simple.svg.png",
    iconStartNew  :          "//upload.wikimedia.org/wikipedia/commons/thumb/0/05/View-refresh_Gion_simple.svg/20px-View-refresh_Gion_simple.svg.png",
    imageMetadataLink :      "(Information about Creator, License and Copyright)",
    newWindow :              "(New Window …)",
    toolTipClose  :          "Click to close",
    toolTipCollapse :        "(click to hide information below)",
    toolTipExpand :          "(click to show more information below)",
    toolTipImageZooming :    "Images can be enlarged by clicking on it",
    toolTipNavigatePagetop : "Top of page",
    toolTipNewWindow :       "(click to open content in a new window or tab)",
    toolTipFloatleft : "floating on the left side",
    toolTipFloatright: "floating on the right side",
    toolTipUnfloat: "back to default position",
    toolTipNoContentLoadable:"<i>No content could be loaded</i>",
    toolTipHeadingLink:      "Click to show (permanent) link to this headline", // MediaWiki:Gadget-HeadingLink
    toolTipHeadingLinkHelp:  "(1) Normal link to this head line or (2) the permanent link with version number:",// MediaWiki:Gadget-HeadingLink
    zoomNotPossible :        "(This image can not be further enlarged)",
    // see MediaWiki:Jquery.zoomImage.js
    ZoomImage_iconMagnifier: "//www.species-id.net/o/media/f/f7/Iviewer.zoom_in.gif",
    ZoomImage_iconMagnifierHover: "//www.species-id.net/o/media/5/5c/Iviewer.zoom_out.gif",
    ZoomImage_iconLoader:  "//upload.wikimedia.org/wikipedia/commons/d/de/Ajax-loader.gif",
    ZoomImage_toolTipLoad :  "(click to load largest available image; this may take considerable time to load)",
    ZoomImage_textZoomOrig:  "Zooming facility"
  },
  de: {
    captionCollapse :        "&nbsp;(weniger anzeigen)&nbsp;",
    captionExpand :          "&nbsp;(mehr...)&nbsp;",
    expandAll :              "Alle Zusatzinformationen zeigen",
    imageMetadataLink :      "(Informationen zu Autor, Lizenz und Copyright)",
    newWindow :              "(Neues Fenster …)",
    toolTipClose  :          "Zum Schließen klicken",
    toolTipCollapse :        "(klicken um Zusatzinformationen zu verbergen)",
    toolTipExpand :          "(klicken um Zusatzinformationen anzuzeigen)",
    toolTipHeadingLink:      "Klicken um (permanenten) Link dieser Überschrift anzuzeigen",// MediaWiki:Gadget-HeadingLink
    toolTipHeadingLinkHelp:  "(1) Link zu dieser Überschrift oder (2) Link mit Versionsnummer:",// MediaWiki:Gadget-HeadingLink
    toolTipImageZooming :    "Bilder können durch Anklicken vergrößert betrachtet werden",
    toolTipNavigatePagetop : "Zum Seitenanfang",
    toolTipNewWindow :       "(klicken um Inhalt in neuem Fenster oder Reiter zu öffnen)",
    toolTipFloatleft : "Links schwebend",
    toolTipFloatright: "Rechts schwebend",
    toolTipUnfloat: "Zurück zur Normalposition",
    toolTipNoContentLoadable:"<i>Leider konnte der Inhalt nicht geladen werden.</i>",
    zoomNotPossible :        "(Dieses Bild kann nicht weiter vergrößert werden)",
    // see MediaWiki:zoomImage.js
    ZoomImage_toolTipLoad :  "(klicken um Originalbild nachzuladen; bei großen Bildern kann dies u. U. langsam sein)",
    ZoomImage_textZoomOrig:  "Vergrößerungsfunktion"
  },
  it: {
    captionCollapse :        "&nbsp;(mostra di meno)&nbsp;",
    captionExpand :          "&nbsp;(più...)&nbsp;",
    expandAll :              "Mostra tutti informazione", //REVISE
    imageMetadataLink   :    "(Informazione sull'Autore, Licenza e Copyright)",
    toolTipClose  :          "Clicca per chiudere",
    toolTipImageZooming :    "Le immagini possono essere ingrandite cliccandoci sopra",
    zoomNotPossible :        "(Al momento non è possibilie ingrandire questa immagine)" // TODO translation see en version
  }
};

/*
 * 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 = 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.");
  };

/*
 * Descriptions: Create html string for link with image and/or text content
 * attributes: string of combined other attributes of link element; must use ' as inner quotes, and \" inside event functions
 * imgResourceKey, txtResourceKey: resource keys (multilingual);
 * txtContent: string literal (untranslated)
 * href: URI (available for linkBuilder only, images only per js in attributes)
 */
$.linkBuilder = function (txtResourceKey, txtContent, href, attributes) {
  return (txtResourceKey.length ? "<a "
    + " href='" + href + "' " 
    + " " + (attributes.length ? attributes : "") + ">"
    + $.resource(txtResourceKey)
    + "</a>" : (txtContent.length ? "<a "
      + " href='" + href + "' "
      + " " + (attributes.length ? attributes : "") + ">"
      + txtContent + 
      "</a>" : "")
  );
};

$.random = function (min, max) { // NO CHECKS: if(min>max) {return -1;}  if(min==max) {return min;}
  return (min + parseInt(Math.random() * (max - min + 1), 10));
};
// Utility for Cluetip, Modal layer, Image Zoom:
// Create appendable jquery object, fnAction = function bound to click
// NOTE All functions called within createButton() should return false
// to prevent appending a # to the URL from clicking <a href='#'></a>
function createButton(kindOfButton, fnAction) {
  switch (kindOfButton) {
  case "zoomImg":
    return $("<a href='#' title='"+$.resource('ZoomImage_toolTipLoad')+"' />")
      .append(
        "<img src='"+$.resource("ZoomImage_iconMagnifier")+"' align='middle' style='border:1px solid gray;'>" +
        '<span style="position:absolute;left:20px;top:0px;white-space:nowrap;">'+$.resource("ZoomImage_textZoomOrig")+'</span>'
      ) // text after img seems to be inline only with position:absolute
      .hover(
        function() { $(this).find("img:first").attr({src: $.resource("ZoomImage_iconMagnifierHover"), style :'border:1px solid black;'}); },
        function() { $(this).find("img:first").attr({src: $.resource("ZoomImage_iconMagnifier"), style :'border:1px solid gray;'}); })
      .click(fnAction);
    break;
  case "close":
  default:
    return $("<a href='#' title='"+$.resource('toolTipClose')+"'/>")
      .append("<img src='"+$.resource("iconCloseWindow")+"' />")
      .hover(
        function() { $(this).find("img:first").attr("src", $.resource("iconCloseWindowHover")); },
        function() { $(this).find("img:first").attr("src", $.resource("iconCloseWindow")); })
      .click(fnAction);
  }// end switch case
}

////////////////////////////////////
// Modal Layer base functionality //
////////////////////////////////////
// for program flow see [[MediaWiki:ModalLayer and image zoom docu‎]]
 
// Description: Hide (= close) modal layer (Note: cyclical dependency with next method unavoidable)
function modalLayer_Hide() {
  $(document).unbind("keydown", modalLayer_KeyDown);
  $("#modal-fg").fadeOut(function() {
    $("#modal-bg").hide();
    $(this).empty().hide();
  });
  return false;
}
 
// Description: Close (hide) modal layer on escape, backspace and arrow left key
// e: the keyboard event object
function modalLayer_KeyDown(e) {
  if ((e.keyCode == 8) || (e.keyCode == 27) || (e.keyCode == 37)) { modalLayer_Hide(); }
}
 
// Description: Create modal layer and execute fnRender
// fnRender: custom function to display something
// paramsObj: generic parameters passed to "fnRender"
function modalLayer_Create(fnRender, paramsObj) {
  // find existing or create background & layer
  var modalBG = $("#modal-bg"),
    modalFG = $("#modal-fg");
  if (modalBG.length === 0) { // first time init
    if (typeof(document.body.style.maxHeight) === "undefined") { // if IE 6
      $("body","html").css({height: "100%", width: "100%"});
    }
    // add styles (IE6 hack not possible as element style!)
    $("head").append("<style type=\"text/css\">#modal-bg {position:fixed; z-index:100; top:0px;left:0px; height:100%;width:100%; background:black; opacity:0.8; filter:alpha(opacity=80); display:none;}\n" +
    "#modal-fg {position:fixed; z-index:101; top:50%;left:50%; padding:3px; border:2px solid #E0E0E0; background-color:white; display:none;}\n" + // IE6 hack: add (very!) slow IE-CSS-expression only for IE < 7
    ($.browser.msie && $.browser.version < 7 ? "* html #modal-bg {position: absolute; height:expression(document.body.scrollHeight > document.body.offsetHeight ? document.body.scrollHeight : document.body.offsetHeight + 'px');}\n* html #modal-fg {position: absolute; margin-top: expression(0 - parseInt(this.offsetHeight / 2) + (TBWindowMargin = document.documentElement && document.documentElement.scrollTop || document.body.scrollTop) + 'px');}\n" : "") +
    "#modal-fg img {display:block;}\n</style>");
    modalBG = $("<div id='modal-bg'/>"); // #### in old code version: HEIGHT was changed to: $(document).height()-- necessary for some browsers??? Trying without!
    modalFG = $("<div id='modal-fg'/>");
    modalBG.click(function() { modalLayer_Hide(); });
    $("body").append(modalBG).append(modalFG);
  } // END first time init
  $(document).keydown(modalLayer_KeyDown);
  // generic view port functionality: close icon and background click
  modalFG
    .append( $('<div style="position:absolute;right:4px;"/>')
    .append(createButton("close", modalLayer_Hide)) );
  modalBG
    .append('<img src="' + $.resource('ZoomImage_iconLoader') + '"  id="loaderIcon"  style="position:absolute;top:50%;left:50%;"/>')
    .show();
  fnRender(paramsObj); // Execute custom logic, example: modalLayer_ZoomImage
}
 
//////////////////////
// Modal Image zoom
// Description: Create modal layer and execute fnRender
// fnRender: custom function to display something
// paramsObj: generic parameters passed to "fnRender"
// dependencies: $.linkBuilder
function modalLayer_ShowImage(newImg, oriImg) {
  var title = oriImg.title,
    imgWidth = newImg.width,
    imgHeight = newImg.height,
    modalBG = $("#modal-bg"),
    modalFG = $("#modal-fg");
 
  modalBG.find("#loaderIcon").remove();
 
  if (imgWidth===0) { // Only IE, only if newImg = oriImg.clone(): cloned image in IE has no width
    imgWidth = oriImg.width;
    imgHeight = oriImg.height;
  }
  // extend height of modal layer for no-zoom msg
  var zoomIsPossible = (imgWidth != oriImg.width),
    layerHeight = imgHeight + 105 + ((!zoomIsPossible) ? 60 : 0),
    layerWidth = Math.max(300, imgWidth + 70); // reserve minimal text width
    // delete alt text & add click function to hide modal
    $(newImg).removeAttr("alt")
      .attr("title", title.replace($.resource("toolTipImageZooming"),$.resource("toolTipClose")))
      .click( function() {modalLayer_Hide();});
 
    modalFG
      .css({width: layerWidth + "px", height: layerHeight + "px", "margin-left": -(layerWidth/2)})
      .append( zoomIsPossible ? $('<div style="position:absolute;left:4px;" id="iviewer_zoom_icon"/>').append(createButton("zoomImg",  modalLayer_InitShowIviewerZoomImage)) :"" )
      // append content to foreground; wrap image with <div>
      .append($("<div id='modal-fg-wrapper' style='margin-left:" +
        (layerWidth-imgWidth) / 2 + "px; margin-top:35px;'/>")
        .append(newImg)// add image
      )
      // + caption
      .append($("<div id='zoomcaption' class='zoomcaption' style='text-align:center; margin:8px 2px 2px 2px; font-weight:bold;'/>")
        .append(title.replace("("+$.resource("toolTipImageZooming")+")","")+"<br />")
      // URL to metadata page from "a[href]" around img
        .append($.linkBuilder("imageMetadataLink", "", $(oriImg).closest("a").attr("href"), "target='_blank'"))
        .append( !zoomIsPossible ? "<br/><br/><span style='color:red;'>" + $.resource("zoomNotPossible") + "</span>" : "")
      );
  // take away IE6 modifications
  if ( !($.browser.msie && $.browser.version < 7)) {
    modalFG.css({"margin-top": -((layerHeight + 8) / 2)}); // 8 from other margin-top
  }
  modalFG.fadeIn(50);
}
 
// Description: load script and functionality on demand for jQuery plugin iviewer
function modalLayer_InitShowIviewerZoomImage() {
  if (typeof modalLayer_ShowIviewerZoomImage !== "function") {
    $.getScript(mw.config.get('wgServer') + mw.config.get('wgScript') + "?title=MediaWiki:Jquery.zoomImage.js&action=raw&ctype=text/javascript",
      function(){modalLayer_ShowIviewerZoomImage();});
  } else {
    modalLayer_ShowIviewerZoomImage ();
  }
  return false;// needed for click on <a href'#'></a> → no # appended to the URL
}
 
//   Description: custom function to be passed to modal layer zooming an image
//   paramsObj: object containing "caller" = ref to a link including an img
// @dependencies: $.random()
function modalLayer_ZoomImage(paramsObj) {
  var oriImg = $(paramsObj.caller).find("img").get(0), // caller is typically a[href]
    urlParts = oriImg.src.split("/");
  if ((oriImg.src.search(/\/thumb\//) === -1) ||
      (urlParts[urlParts.length - 1].search(/px-/) === -1))   {
    // no larger picture possible, use existing
    modalLayer_ShowImage($(oriImg).clone().get(0), oriImg);
  } else { // images with "/thumb/" in path can be enlarged using URL-based resize
    var stdThumbWidths = [1600,1400,1280,1024,900,800,700,640,600,550,480,400,350,320,300,250,200,180,150,120,100,80],
      maxHeight = $(window).height() - 105, // 70 for additional text; 35 for space at top and bottom
      maxWidth  = $(window).width()  - 50; // 50 for space left & right
    // smallest possible of upscaling factor for height, width, multiply back to get max possible width
    var maxScaledWidth = oriImg.width * Math.min(maxHeight/oriImg.height, maxWidth/oriImg.width),
      maxScaledHeight = oriImg.height * maxScaledWidth / oriImg.width;
    // reduce to next smaller standard thumb width (mediawiki preview settings plus additions)
    for (var i = 0; i < 22; i++) {
      if (stdThumbWidths[i] < maxScaledWidth) {
        maxScaledWidth = stdThumbWidths[i];
        maxScaledHeight = oriImg.height * maxScaledWidth / oriImg.width;
        break;
      }
    }
    urlParts[urlParts.length - 1] = maxScaledWidth + "px-" + urlParts[urlParts.length - 2];
    var newImg = new Image(maxScaledWidth, maxScaledHeight);
    // Load image. load/error occur asynchronously, need independent calls
    // appending "random()" seems necessary for IE6-8, else "zoom image, close, zoom again" fails. REASON?
    $(newImg)
      .attr("src", urlParts.join("/")+"&rnd="+$.random(0,10000))
      .load(function() { // load succeeded: create modal layer after loading image, else values (width, etc.) are 0
        modalLayer_ShowImage(newImg, oriImg);
      })
      .error(function() { // Error loading thumb, main reason: thumbs must be smaller than ori size.
      // Currently assuming this reason, loading full original image; BETTER: test using API:
      // http://commons.wikimedia.org/w/api.php?action=query&titles=Image:Lamium_purpureum_scan.jpg&prop=imageinfo&iiprop=size
      urlParts.pop(); // remove last part (e.g. 800px-xyz.jpg)
      // set default width and height in case of thumbnail generation failure with huge images
      newImg = new Image(maxScaledWidth, maxScaledHeight); // load original image
      $(newImg)
        .attr("src", urlParts.join("/").replace("/thumb", "")) // remove "/thumb" from url to get full. DO NOT ADD random here!
        .load(function() {modalLayer_ShowImage(newImg, oriImg);}) // load succeeded
      // 2nd level fail -> load from wikimedia.org
        .error(function() {
          // set default width and height in case of thumbnail generation failure with huge images
          newImg = new Image(maxScaledWidth, maxScaledHeight);
          $(newImg)
            .attr("src", "//commons.wikimedia.org/w/thumb.php?f="+urlParts[urlParts.length-1]+"&width="+maxScaledWidth+"px"+"&rnd="+$.random(0,10000))
            .load(function() {modalLayer_ShowImage(newImg, oriImg);}) // load succeeded
      // 3rd level fail -> load unchanged wiki page thumb
            .error(function() {modalLayer_ShowImage($(oriImg).clone().get(0), oriImg);});
        });
      }); // end first level error
  }
}
 
 
// Description: Show image in modal layer
// caller: reference to a link around image
function zoomImage(caller) {
  modalLayer_Create(modalLayer_ZoomImage, {caller: caller});
  return false; // cancel default event
}
 
/* Description: Add a modal zoom functionality to all images linking to own metadata
 * the CSS 
 * class=no-image-popup or class=no-popup-image OR
 * class=no-image-zoom or class=no-zoom-image prevents an image from being zoomable, e.g.
 * [[File:Example.jpg|caption text|thumb|class=no-popup-image]]
 */
function initImageZooming() {
  $("a[href].image img:not(.no-image-popup,.no-popup-image,.no-image-zoom,.no-zoom-image)").each(function() {
    var jParent = $(this).parent(),
      metaURL = jParent.attr("href"),
      urlParts = this.src.split("/"),
      imgFileName = (this.src.search(/\/thumb\//) != -1) ? urlParts[urlParts.length - 2] : urlParts[urlParts.length - 1];
    // Is file name also in metadata page link? Else abort (e.g. for |link=parameter| wiki-images)
    // Problem: a.href and img.scr inconsistently! use encoded or non-encoded versions of e.g. () or "," -> unescape
    if (unescape(metaURL).indexOf(unescape(imgFileName)) == -1) { return; }
    // pass along the image
    jParent.click(function() { return zoomImage(this); });
    // set or change title, set alt to title
    var newTitle = this.alt + ((this.alt.length === 0) ? "" : " ") + "(" + $.resource("toolTipImageZooming") + ")";
    $(this).attr({title:newTitle, alt:newTitle});
  });
}
 
// END Modal Layer/Img Zoom
////////////////////////////

$(document).ready(function() {
  // initImageZooming(); // extension:MultimediaViewer is used
});
// </pre>