mediawiki-extensions-Multim.../resources/multilightbox/lightboxinterface.js
Mark Holmquist a86a6d5b9e Fix resize engine for fullscreen
This sorta has a few other miscellaneous fixes in it, but it works!

There are maybe still funky behaviours left. Test it?

Also refactor some bits, so we aren't accessing mw.mediaViewer in the
interface code.

Change-Id: I69db8e7b4ff5f994ba706fd4965688f3c26859f4
2014-01-29 11:50:22 +01:00

273 lines
6.1 KiB
JavaScript

( function ( $ ) {
var LIP, lightboxHooks;
/**
* @class
* @constructor
*/
function LightboxInterface() {
lightboxHooks = window.lightboxHooks;
var result,
addToPre = [],
addToPost = [],
lbinterface = this;
// Staging area for image resizes
this.$staging = $( '<div>' )
.addClass( 'mlb-staging-area' );
$( document.body ).append( this.$staging );
this.$overlay = $( '<div>' )
.addClass( 'mlb-overlay' );
this.$wrapper = $( '<div>' )
.addClass( 'mlb-wrapper' );
this.$main = $( '<div>' )
.addClass( 'mlb-main' );
this.$imageDiv = $( '<div>' )
.addClass( 'mlb-image' );
// I blame CSS for this
this.$innerWrapper = $( '<div>' )
.addClass( 'mlb-image-inner-wrapper' )
.append( this.$imageDiv );
this.$imageWrapper = $( '<div>' )
.addClass( 'mlb-image-wrapper' )
.append( this.$innerWrapper );
this.$preDiv = $( '<div>' )
.addClass( 'mlb-pre-image' );
result = lightboxHooks.callAll( 'addToPreDiv', this, addToPre );
this.setupPreDiv( result, addToPre );
this.$postDiv = $( '<div>' )
.addClass( 'mlb-post-image' );
result = lightboxHooks.callAll( 'addToPostDiv', this, addToPost );
this.setupPostDiv( result, addToPost );
this.$main.append(
this.$preDiv,
this.$imageWrapper,
this.$postDiv
);
this.$wrapper.append(
this.$main
);
lightboxHooks.callAll( 'modifyInterface', this );
window.addEventListener( 'keyup', function ( e ) {
if ( e.keyCode === 27 ) {
// Escape button pressed
lbinterface.unattach();
}
} );
$( document ).on( 'jq-fullscreen-change', function ( e ) {
lbinterface.isFullscreen = e.fullscreen;
lightboxHooks.callAll( 'fullscreen', this, e.fullscreen );
if ( !lbinterface.fullscreenButtonJustPressed && !e.fullscreen ) {
// Close the interface all the way if the user pressed 'esc'
lbinterface.unattach();
} else if ( lbinterface.fullscreenButtonJustPressed ) {
lbinterface.fullscreenButtonJustPressed = false;
}
} );
}
LIP = LightboxInterface.prototype;
/**
* @type {LightboxImage}
* @protected
*/
LIP.currentImage = null;
LIP.empty = function () {
this.$imageDiv.empty();
lightboxHooks.callAll( 'clearInterface', this );
if ( this.resizeListener ) {
window.removeEventListener( 'resize', this.resizeListener );
}
};
/**
* Attaches interface to document or given parent id.
*
* @param {string} [parentId] parent id where we want to attach the UI. Mainly for testing.
*/
LIP.attach = function ( parentId ) {
// Re-appending the same content can have nasty side-effects
// Such as the browser leaving fullscreen mode if the fullscreened element is part of it
if ( this.currentlyAttached ) {
return;
}
var parent = $( parentId || document.body );
parent
.append(
this.$wrapper,
this.$overlay
);
this.currentlyAttached = true;
};
/**
* Unattaches interface from parent element. Calls global lightboxHooks.
*/
LIP.unattach = function () {
// TODO(aarcos): This is global and it breaks tests.
lightboxHooks.callAll( 'closeInterface', this );
this.$wrapper.detach();
this.$overlay.detach();
this.currentlyAttached = false;
};
/**
* @protected
*/
LIP.resizeCallback = function() {
if ( this.currentlyAttached ) {
var result = lightboxHooks.callAll( 'imageResize', this );
if ( result !== false ) {
this.autoResizeImage();
}
}
};
/**
* @protected
*/
LIP.loadCallback = function ( image, ele ) {
var iface = this;
image.globalMaxWidth = ele.width;
image.globalMaxHeight = ele.height;
this.$image = $( ele );
this.autoResizeImage();
// Capture listener so we can remove it later, otherwise
// we are going to leak listeners !
this.resizeListener = function () { iface.resizeCallback(); };
window.addEventListener( 'resize', this.resizeListener );
lightboxHooks.callAll( 'imageLoaded', this );
};
/**
* @param {LightboxImage} image
*/
LIP.load = function ( image ) {
var iface = this;
this.currentImage = image;
image.getImageElement().done( function( image, ele ) {
iface.loadCallback.call( iface, image, ele );
} );
};
LIP.autoResizeImage = function () {
this.$staging.append( this.$image );
this.currentImage.autoResize( this.$image.get( 0 ), this.$imageDiv );
this.$imageDiv.append( this.$image );
};
/**
* Changes what image is being displayed.
* @param {HTMLImageElement} imageEle
*/
LIP.replaceImageWith = function ( imageEle ) {
var $image = $( imageEle );
this.currentImage.src = imageEle.src;
this.$image.replaceWith( $image );
this.$image = $image;
this.currentImage.globalMaxWidth = this.$image.width();
this.currentImage.globalMaxHeight = this.$image.height();
this.currentImage.autoResize( imageEle );
};
LIP.exitFullscreen = function () {
this.fullscreenButtonJustPressed = true;
this.$main.exitFullscreen();
};
LIP.enterFullscreen = function () {
this.$main.enterFullscreen();
};
LIP.setupPreDiv = function ( buildDefaults, toAdd ) {
var lbinterface = this;
if ( buildDefaults ) {
this.$controlBar = $( '<div>' )
.addClass( 'mlb-controls' );
this.$closeButton = $( '<div>' )
.text( ' ' )
.addClass( 'mlb-close' )
.click( function () {
lbinterface.unattach();
} );
this.$fullscreenButton = $( '<div>' )
.text( ' ' )
.addClass( 'mlb-fullscreen' )
.click( function () {
if ( lbinterface.isFullscreen ) {
lbinterface.exitFullscreen();
} else {
lbinterface.enterFullscreen();
}
} );
this.$controlBar.append(
this.$closeButton,
this.$fullscreenButton
);
this.$preDiv.append( this.$controlBar );
lightboxHooks.callAll( 'modifyDefaultPreDiv', this );
}
this.addElementsToDiv( this.$preDiv, toAdd );
};
LIP.setupPostDiv = function ( buildDefaults, toAdd ) {
if ( buildDefaults ) {
lightboxHooks.callAll( 'modifyDefaultPostDiv', this );
}
this.addElementsToDiv( this.$postDiv, toAdd );
};
LIP.addElementsToDiv = function ( $div, toAdd ) {
var i;
for ( i = 0; i < toAdd.length; i++ ) {
$div.append( toAdd[i] );
}
};
window.LightboxInterface = LightboxInterface;
}( jQuery ) );