2014-05-05 21:44:27 +00:00
|
|
|
/*
|
|
|
|
* This file is part of the MediaWiki extension MediaViewer.
|
|
|
|
*
|
|
|
|
* MediaViewer is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation, either version 2 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* MediaViewer is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with MediaViewer. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
( function( mw, $, oo ) {
|
|
|
|
var MPSP;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @class mw.mmv.ui.MetadataPanelScroller
|
|
|
|
* @extends mw.mmv.ui.Element
|
|
|
|
* Handles scrolling behavior of the metadata panel.
|
|
|
|
* @constructor
|
|
|
|
*/
|
|
|
|
function MetadataPanelScroller( $container, $controlBar, localStorage ) {
|
|
|
|
mw.mmv.ui.Element.call( this, $container );
|
|
|
|
|
|
|
|
this.$controlBar = $controlBar;
|
|
|
|
|
|
|
|
/** @property {Object} localStorage the window.localStorage object */
|
|
|
|
this.localStorage = localStorage;
|
|
|
|
|
2014-06-17 22:23:18 +00:00
|
|
|
/**
|
|
|
|
* Whether this user has ever opened the metadata panel.
|
|
|
|
* Based on a localstorage flag; will be set to true if the client does not support localstorage.
|
|
|
|
* @type {boolean}
|
|
|
|
*/
|
|
|
|
this.hasOpenedMetadata = undefined;
|
|
|
|
|
2014-05-05 21:44:27 +00:00
|
|
|
/**
|
|
|
|
* Whether we've already fired an animation for the metadata div in this lightbox session.
|
|
|
|
* @property {boolean}
|
|
|
|
* @private
|
|
|
|
*/
|
2014-06-17 22:23:18 +00:00
|
|
|
this.hasAnimatedMetadata = false;
|
2014-05-05 21:44:27 +00:00
|
|
|
|
|
|
|
this.initialize();
|
|
|
|
}
|
|
|
|
oo.inheritClass( MetadataPanelScroller, mw.mmv.ui.Element );
|
|
|
|
MPSP = MetadataPanelScroller.prototype;
|
|
|
|
|
2014-05-17 13:24:36 +00:00
|
|
|
MPSP.toggleScrollDuration = 400;
|
|
|
|
|
2014-05-05 21:44:27 +00:00
|
|
|
MPSP.attach = function() {
|
|
|
|
var panel = this;
|
|
|
|
|
|
|
|
this.handleEvent( 'keydown', function ( e ) {
|
|
|
|
panel.keydown( e );
|
|
|
|
} );
|
|
|
|
|
|
|
|
$.scrollTo().on( 'scroll.mmvp', $.throttle( 250, function() {
|
|
|
|
panel.scroll();
|
|
|
|
} ) );
|
|
|
|
|
|
|
|
// reset animation flag when the viewer is reopened
|
2014-06-17 22:23:18 +00:00
|
|
|
this.hasAnimatedMetadata = false;
|
2014-05-05 21:44:27 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
MPSP.unattach = function() {
|
|
|
|
this.clearEvents();
|
|
|
|
$.scrollTo().off( 'scroll.mmvp' );
|
|
|
|
};
|
|
|
|
|
|
|
|
MPSP.empty = function () {
|
2014-06-17 22:23:18 +00:00
|
|
|
this.$dragIcon.toggleClass( 'panel-never-opened', !this.hasOpenedMetadata );
|
2014-05-05 21:44:27 +00:00
|
|
|
|
|
|
|
// need to remove this to avoid animating again when reopening lightbox on same page
|
|
|
|
this.$container.removeClass( 'invite' );
|
|
|
|
};
|
|
|
|
|
|
|
|
MPSP.initialize = function () {
|
|
|
|
var panel = this;
|
|
|
|
|
2014-06-17 22:23:18 +00:00
|
|
|
this.$dragIcon = $( '<div>' )
|
|
|
|
.addClass( 'mw-mmv-drag-icon mw-mmv-drag-icon-pointing-down' )
|
|
|
|
.toggleClass( 'panel-never-opened', !this.hasOpenedMetadata )
|
2014-05-31 00:18:12 +00:00
|
|
|
.prop( 'title', mw.message( 'multimediaviewer-panel-open-popup-text' ).text() )
|
2014-06-17 22:23:18 +00:00
|
|
|
.tipsy( { gravity: 's', delayIn: mw.config.get( 'wgMultimediaViewer').tooltipDelay } )
|
2014-05-05 21:44:27 +00:00
|
|
|
.appendTo( this.$controlBar )
|
|
|
|
.click( function () {
|
|
|
|
panel.toggle();
|
|
|
|
} );
|
|
|
|
|
2014-06-17 22:23:18 +00:00
|
|
|
this.$dragIconBottom = $( '<div>' )
|
|
|
|
.addClass( 'mw-mmv-drag-icon mw-mmv-drag-icon-pointing-up' )
|
|
|
|
.prop( 'title', mw.message( 'multimediaviewer-panel-close-popup-text' ).text() )
|
|
|
|
.tipsy( { gravity: 's', delayIn: mw.config.get( 'wgMultimediaViewer').tooltipDelay } )
|
|
|
|
.appendTo( this.$container )
|
|
|
|
.click( function () {
|
|
|
|
panel.toggle();
|
|
|
|
} );
|
|
|
|
|
|
|
|
this.hasOpenedMetadata = !this.localStorage || this.localStorage.getItem( 'mmv.hasOpenedMetadata' );
|
2014-05-05 21:44:27 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Animates the metadata area when the viewer is first opened.
|
|
|
|
*/
|
|
|
|
MPSP.animateMetadataOnce = function () {
|
2014-06-17 22:23:18 +00:00
|
|
|
if ( !this.hasOpenedMetadata && !this.hasAnimatedMetadata ) {
|
2014-05-05 21:44:27 +00:00
|
|
|
this.hasAnimatedMetadata = true;
|
|
|
|
this.$container.addClass( 'invite' );
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Toggles the metadata div being totally visible.
|
2014-06-26 01:26:49 +00:00
|
|
|
* @param {string} [forceDirection] 'up' or 'down' makes the panel move on that direction (and is a noop
|
|
|
|
* if the panel is already at the upmost/bottommost position); without the parameter, the panel position
|
|
|
|
* is toggled. (Partially open counts as open.)
|
|
|
|
* @return {jQuery.Deferred} a deferred which resolves after the animation has finished.
|
2014-05-05 21:44:27 +00:00
|
|
|
*/
|
|
|
|
MPSP.toggle = function ( forceDirection ) {
|
2014-06-26 01:26:49 +00:00
|
|
|
var deferred = $.Deferred(),
|
|
|
|
scrollTopWhenOpen = this.$container.outerHeight() - this.$controlBar.outerHeight(),
|
2014-05-05 21:44:27 +00:00
|
|
|
scrollTopWhenClosed = 0,
|
|
|
|
scrollTop = $.scrollTo().scrollTop(),
|
|
|
|
panelIsOpen = scrollTop > scrollTopWhenClosed,
|
2014-05-31 00:18:12 +00:00
|
|
|
scrollTopTarget = panelIsOpen ? scrollTopWhenClosed : scrollTopWhenOpen,
|
2014-06-26 01:26:49 +00:00
|
|
|
isOpening = scrollTopTarget === scrollTopWhenOpen;
|
2014-05-05 21:44:27 +00:00
|
|
|
|
|
|
|
if ( forceDirection ) {
|
|
|
|
scrollTopTarget = forceDirection === 'down' ? scrollTopWhenClosed : scrollTopWhenOpen;
|
|
|
|
}
|
|
|
|
|
2014-06-26 01:26:49 +00:00
|
|
|
// don't log / animate if the panel is already in the end position
|
|
|
|
if ( scrollTopTarget === scrollTop ) {
|
|
|
|
deferred.resolve();
|
|
|
|
} else {
|
|
|
|
mw.mmv.actionLogger.log( isOpening ? 'metadata-open' : 'metadata-close' );
|
|
|
|
$.scrollTo( scrollTopTarget, this.toggleScrollDuration, {
|
|
|
|
onAfter: function () {
|
|
|
|
deferred.resolve();
|
|
|
|
}
|
|
|
|
} );
|
|
|
|
}
|
|
|
|
return deferred;
|
2014-05-05 21:44:27 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Makes sure that the given element (which must be a descendant of the metadata panel) is
|
|
|
|
* in view. If it isn't, scrolls the panel smoothly to reveal it.
|
|
|
|
* @param {HTMLElement|jQuery|string} target
|
|
|
|
* @param {number} [duration] animation length
|
|
|
|
* @param {Object} [settings] see jQuery.scrollTo
|
|
|
|
*/
|
|
|
|
MPSP.scrollIntoView = function( target, duration, settings ) {
|
|
|
|
var $target = $( target ),
|
|
|
|
targetHeight = $target.height(),
|
|
|
|
targetTop = $target.offset().top,
|
|
|
|
targetBottom = targetTop + targetHeight,
|
2014-05-17 13:24:36 +00:00
|
|
|
viewportHeight = $( window ).height(),
|
2014-05-05 21:44:27 +00:00
|
|
|
viewportTop = $.scrollTo().scrollTop(),
|
|
|
|
viewportBottom = viewportTop + viewportHeight;
|
|
|
|
|
|
|
|
// we omit here a bunch of cases which are logically possible but unlikely given the size
|
|
|
|
// of the panel, and only care about the one which will actually happen
|
|
|
|
if ( targetHeight <= viewportHeight ) { // target fits into screen
|
|
|
|
if (targetBottom > viewportBottom ) {
|
|
|
|
$.scrollTo( viewportTop + ( targetBottom - viewportBottom ), duration, settings );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Handles keydown events for this element.
|
|
|
|
*/
|
|
|
|
MPSP.keydown = function ( e ) {
|
|
|
|
switch ( e.which ) {
|
2014-06-10 20:01:19 +00:00
|
|
|
case 40: // Down arrow
|
|
|
|
// fall through
|
|
|
|
case 38: // Up arrow
|
|
|
|
this.toggle();
|
2014-05-05 21:44:27 +00:00
|
|
|
e.preventDefault();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Receives the window's scroll events and flips the chevron if necessary.
|
|
|
|
*/
|
|
|
|
MPSP.scroll = function () {
|
|
|
|
var scrolled = !!$.scrollTo().scrollTop();
|
|
|
|
|
2014-06-17 22:23:18 +00:00
|
|
|
this.$dragIcon.toggleClass( 'panel-open', scrolled );
|
2014-05-05 21:44:27 +00:00
|
|
|
|
|
|
|
if (
|
2014-06-17 22:23:18 +00:00
|
|
|
!this.hasOpenedMetadata
|
|
|
|
&& scrolled
|
|
|
|
&& this.localStorage
|
|
|
|
) {
|
|
|
|
this.hasOpenedMetadata = true;
|
|
|
|
this.$dragIcon.removeClass( 'panel-never-opened' );
|
2014-05-05 21:44:27 +00:00
|
|
|
try {
|
|
|
|
this.localStorage.setItem( 'mmv.hasOpenedMetadata', true );
|
|
|
|
} catch ( e ) {
|
|
|
|
// localStorage is full or disabled
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
mw.mmv.ui.MetadataPanelScroller = MetadataPanelScroller;
|
|
|
|
}( mediaWiki, jQuery, OO ) );
|