User:Xover/loupe.js
Jump to navigation
Jump to search
Note: After saving, changes may not occur immediately. Click here to learn how to bypass your browser's cache.
- Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (Cmd-R on a Mac)
- Google Chrome: Press Ctrl-Shift-R (Cmd-Shift-R on a Mac)
- Internet Explorer: Hold Ctrl while clicking Refresh, or press Ctrl-F5
- Opera: Clear the cache in Tools → Preferences
For details and instructions about other browsers, see Wikipedia:Bypass your cache.
Code that you insert on this page could contain malicious content capable of compromising your account. If you are unsure whether code you are adding to this page is safe, you can ask at the central discussion page, Scriptorium. The code will be executed when previewing this page under some skins, including Monobook. You can in the interim if you wish to refresh the content sooner under another skin. |
Documentation for this script can be added at User:Xover/loupe. |
/* global $, mw */
"use strict";
console.log("loupe.js loading");
// Make sure the necessary modules are loaded
mw.loader.using(['mediawiki.util', 'mediawiki.api'], function() {
console.log("loupe.js in mw.loader.using");
// Wait for the page to be parsed (new-style $(document).ready())
$(function() {
console.log("loupe.js in $(document).ready()");
// Only active on Page:-namespace pages.
if (mw.config.get('wgCanonicalNamespace') !== 'Page') {
return;
}
console.log("loupe.js passed namespace check");
// Page image is statically positioned in view mode, so force it to relative
if (mw.config.get('wgAction') == 'view') {
$('.prp-page-image').css('position', 'relative');
}
// Pre-load loading GIF
var loadingGifUrl = '//upload.wikimedia.org/wikipedia/commons/4/42/Loading.gif';
$('<img />').attr('src', loadingGifUrl).appendTo('body').hide();
// Track whether full-sized image has loaded
var fullwidth_image_loaded = false;
// Set up the loupe
var loupe = $('<div></div>').attr('id', 'loupe').css({
'width': '200px',
'height': '125px',
'position': 'absolute',
'border-radius': '.2ex',
'box-shadow': '0 0 0 1px rgba(0, 0, 0, 0.85), 0 0 7px 7px rgba(0, 0, 0, 0.25), inset 0 0 40px 2px rgba(0, 0, 0, 0.25)',
'background-color': 'white',
'background-image': "url('" + loadingGifUrl + "')",
'background-repeat': 'no-repeat',
'background-position': 'center',
'cursor': 'crosshair',
'display': 'none'
}).appendTo('.mw-content-text').hide();
var fullsize_width = $('.prp-page-image img').data('fileWidth');
var match = /(.*?)\/(\d+)/.exec(mw.config.get('wgTitle'));
var file = match[1];
var page = match[2];
console.log("loupe.js about to call API");
var api = new mw.Api();
api.get({
'action': 'query',
'prop': 'imageinfo',
'titles': "File:" + file,
'formatversion': 2,
'format': 'json',
'iiprop': 'url',
'iiurlwidth': fullsize_width,
'iiurlparam': "page" + page + "-" + fullsize_width + "px"
})
.done(function(data) {
console.log("loupe.js API call called .done(" + data.query.pages[0].imageinfo[0].thumburl + ")");
var thumburl = data.query.pages[0].imageinfo[0].thumburl;
$('<img />').on('load', {thumburl: thumburl}, function(e) {
console.log("loupe.js DOM called .on(load)");
var thumburl = e.data.thumburl;
fullwidth_image_loaded = true;
$('#loupe').css({'background-image': "url('" + thumburl + "')"});
}).attr('src', thumburl).appendTo('body').hide();
});
// Now set up the mouse tracking and loupe display
$('.prp-page-image').mousemove(function(e) {
var img = $('.prp-page-image img');
var img_offset = img.offset();
var imgX = img_offset.left;
var imgY = img_offset.top;
var imgW = img.width();
var imgH = img.height();
// Subtract the page image container offsets from the mouse offsets to
// make the mouse offsets relative to the page image container.
var mX = e.pageX - imgX;
var mY = e.pageY - imgY;
// Fade in the loupe if the mouse offsets are within the bounds of the
// page image container. Otherwise, fade it out.
//
// Apply a safety margin since mousemove events are coalesced and there is
// a window where the mouse can be outside .prp-page-image, so it no
// longer gets mousemove events, but still inside the image rectangle so
// it doesn't fade the loupe out.
// FIXME: Should get clever with .mouseenter here instead.
var fuzz = 5;
var insideRightEdge = mX < (imgW - fuzz) ? true : false;
var insideLeftEdge = mX > ( 0 + fuzz) ? true : false;
var insideTopEdge = mY < (imgH - fuzz) ? true : false;
var insideBottomEdge = mY > ( 0 + fuzz) ? true : false;
if (insideRightEdge && insideLeftEdge && insideTopEdge && insideBottomEdge) {
$("#loupe").fadeIn(200);
} else {
$("#loupe").fadeOut(200);
}
// Position full-resolution image relative to mouse position so that the
// magnification effect works.
if ($('#loupe').is(':visible')) {
// Calculate the position of the loupe relative to the mouse position.
var loupe_left = mX - ($('#loupe').width() / 2);
var loupe_top = mY - ($('#loupe').height() / 2);
// Percentage offset of the mouse pointer in the small image, which
// translates to a percentage offset for the large image.
// FIXME: Need an "accelleration curve" here, so that the offset between
// the mouse position (center) and edge of the loupe doesn't cut off the
// edge of the image (problem on tight margins).
var bgposition_left = (100 / imgW) * mX;
var bgposition_top = (100 / imgH) * mY;
var bgposition = bgposition_left + "% " + bgposition_top + "%";
if (!fullwidth_image_loaded) {
bgposition = 'center';
}
// Position the loupe and background.
$("#loupe").css({left: loupe_left, top: loupe_top, backgroundPosition: bgposition});
}
});
}); // END: $(document).ready()
}); // END: mw.loader.using()