mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/MultimediaViewer
synced 2024-11-17 04:43:18 +00:00
Reveal full text when metadata panel is opened
Automatically reveal/hide full text as metadata panel is opened/closed. Also makes metadata open/close a proper event. Changes scrollTop calculation for the fully open metadatapanel so it is not confused by the size of the panel changing. Also rename MetadataPanel.$controlBar to $aboveFold (that field was missed when the corresponding CSS class got renamed). Change-Id: I7e66ca0f45c2188dab4b78508ad7f91154187de4 Mingle: https://wikimedia.mingle.thoughtworks.com/projects/multimedia/cards/396
This commit is contained in:
parent
f5ccd12ee5
commit
0423bfbe5a
|
@ -72,7 +72,7 @@
|
|||
this.$postDiv = $( '<div>' )
|
||||
.addClass( 'mw-mmv-post-image' );
|
||||
|
||||
this.$controlBar = $( '<div>' )
|
||||
this.$aboveFold = $( '<div>' )
|
||||
.addClass( 'mw-mmv-above-fold' );
|
||||
|
||||
this.$main.append(
|
||||
|
@ -88,7 +88,7 @@
|
|||
|
||||
this.setupCanvasButtons();
|
||||
|
||||
this.panel = new mw.mmv.ui.MetadataPanel( this.$postDiv, this.$controlBar, window.localStorage );
|
||||
this.panel = new mw.mmv.ui.MetadataPanel( this.$postDiv, this.$aboveFold, window.localStorage );
|
||||
this.buttons = new mw.mmv.ui.CanvasButtons( this.$preDiv, this.$closeButton, this.$fullscreenButton );
|
||||
this.canvas = new mw.mmv.ui.Canvas( this.$innerWrapper, this.$imageWrapper, this.$wrapper );
|
||||
};
|
||||
|
|
|
@ -25,13 +25,13 @@
|
|||
* @extends mw.mmv.ui.Element
|
||||
* @constructor
|
||||
* @param {jQuery} $container The container for the panel (.mw-mmv-post-image).
|
||||
* @param {jQuery} $controlBar The control bar element (.mw-mmv-above-fold).
|
||||
* @param {jQuery} $aboveFold The always-visible part of the metadata panel (.mw-mmv-above-fold).
|
||||
* @param {Object} localStorage the localStorage object, for dependency injection
|
||||
*/
|
||||
function MetadataPanel( $container, $controlBar, localStorage ) {
|
||||
function MetadataPanel( $container, $aboveFold, localStorage ) {
|
||||
mw.mmv.ui.Element.call( this, $container );
|
||||
|
||||
this.$controlBar = $controlBar;
|
||||
this.$aboveFold = $aboveFold;
|
||||
|
||||
/** @property {mw.mmv.Config} config - */
|
||||
this.config = new mw.mmv.Config(
|
||||
|
@ -69,6 +69,16 @@
|
|||
}
|
||||
panel.toggleTruncatedText();
|
||||
} );
|
||||
|
||||
$( this.$container ).on( 'mmv-metadata-open', function () {
|
||||
panel.revealTruncatedText( true );
|
||||
} ).on( 'mmv-metadata-close', function () {
|
||||
panel.hideTruncatedText();
|
||||
} );
|
||||
|
||||
this.handleEvent( 'jq-fullscreen-change.lip', function() {
|
||||
panel.hideTruncatedText();
|
||||
} );
|
||||
};
|
||||
|
||||
MPP.unattach = function() {
|
||||
|
@ -135,16 +145,16 @@
|
|||
* @param {Object} localStorage the localStorage object, for dependency injection
|
||||
*/
|
||||
MPP.initializeHeader = function ( localStorage ) {
|
||||
this.progressBar = new mw.mmv.ui.ProgressBar( this.$controlBar );
|
||||
this.progressBar = new mw.mmv.ui.ProgressBar( this.$aboveFold );
|
||||
|
||||
this.scroller = new mw.mmv.ui.MetadataPanelScroller( this.$container, this.$controlBar,
|
||||
this.scroller = new mw.mmv.ui.MetadataPanelScroller( this.$container, this.$aboveFold,
|
||||
localStorage );
|
||||
|
||||
this.$titleDiv = $( '<div>' )
|
||||
.addClass( 'mw-mmv-title-contain' )
|
||||
.appendTo( this.$controlBar );
|
||||
.appendTo( this.$aboveFold );
|
||||
|
||||
this.$container.append( this.$controlBar );
|
||||
this.$container.append( this.$aboveFold );
|
||||
|
||||
this.initializeButtons(); // float, needs to be on top
|
||||
this.initializeTitleAndCredit();
|
||||
|
@ -868,12 +878,18 @@
|
|||
/**
|
||||
* Shows truncated text in the title and credit (this also rearranges the layout a bit).
|
||||
* Opens the panel partially to make sure the revealed text is visible.
|
||||
* @param {boolean} noScroll if set, do not scroll the panel (because the function was triggered from a
|
||||
* scroll event in the first place)
|
||||
*/
|
||||
MPP.revealTruncatedText = function () {
|
||||
MPP.revealTruncatedText = function ( noScroll ) {
|
||||
if ( this.$container.hasClass( 'mw-mmv-untruncated' ) ) {
|
||||
// avoid self-triggering via reveal -> scroll -> reveal
|
||||
return;
|
||||
}
|
||||
this.$container.addClass( 'mw-mmv-untruncated' );
|
||||
this.title.grow();
|
||||
this.creditField.grow();
|
||||
if ( this.aboveFoldIsLargerThanNormal() ) {
|
||||
if ( this.aboveFoldIsLargerThanNormal() && !noScroll ) {
|
||||
this.scroller.scrollIntoView( this.$datetimeLi, 500 );
|
||||
}
|
||||
};
|
||||
|
@ -882,6 +898,10 @@
|
|||
* Undoes changes made by revealTruncatedText().
|
||||
*/
|
||||
MPP.hideTruncatedText = function () {
|
||||
if ( !this.$container.hasClass( 'mw-mmv-untruncated' ) ) {
|
||||
// avoid double-triggering
|
||||
return;
|
||||
}
|
||||
this.title.shrink();
|
||||
this.creditField.shrink();
|
||||
this.$container.removeClass( 'mw-mmv-untruncated' );
|
||||
|
@ -892,7 +912,7 @@
|
|||
* calling revealTruncatedText().
|
||||
*/
|
||||
MPP.aboveFoldIsLargerThanNormal = function () {
|
||||
return this.$controlBar.height() > parseInt( this.$controlBar.css( 'min-height' ), 10 );
|
||||
return this.$aboveFold.height() > parseInt( this.$aboveFold.css( 'min-height' ), 10 );
|
||||
};
|
||||
|
||||
mw.mmv.ui.MetadataPanel = MetadataPanel;
|
||||
|
|
|
@ -23,15 +23,21 @@
|
|||
* @extends mw.mmv.ui.Element
|
||||
* Handles scrolling behavior of the metadata panel.
|
||||
* @constructor
|
||||
* @param {jQuery} $container The container for the panel (.mw-mmv-post-image).
|
||||
* @param {jQuery} $aboveFold The control bar element (.mw-mmv-above-fold).
|
||||
* @param {Object} localStorage the localStorage object, for dependency injection
|
||||
*/
|
||||
function MetadataPanelScroller( $container, $controlBar, localStorage ) {
|
||||
function MetadataPanelScroller( $container, $aboveFold, localStorage ) {
|
||||
mw.mmv.ui.Element.call( this, $container );
|
||||
|
||||
this.$controlBar = $controlBar;
|
||||
this.$aboveFold = $aboveFold;
|
||||
|
||||
/** @property {Object} localStorage the window.localStorage object */
|
||||
this.localStorage = localStorage;
|
||||
|
||||
/** @property {boolean} panelIsOpen state flag which will be used to detect open <-> closed transitions */
|
||||
this.panelIsOpen = null;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
|
@ -64,6 +70,18 @@
|
|||
panel.scroll();
|
||||
} ) );
|
||||
|
||||
this.$container.on( 'mmv-metadata-open', function () {
|
||||
if ( !panel.hasOpenedMetadata && panel.localStorage ) {
|
||||
panel.hasOpenedMetadata = true;
|
||||
panel.$dragIcon.removeClass( 'panel-never-opened' );
|
||||
try {
|
||||
panel.localStorage.setItem( 'mmv.hasOpenedMetadata', true );
|
||||
} catch ( e ) {
|
||||
// localStorage is full or disabled
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
// reset animation flag when the viewer is reopened
|
||||
this.hasAnimatedMetadata = false;
|
||||
};
|
||||
|
@ -71,6 +89,7 @@
|
|||
MPSP.unattach = function() {
|
||||
this.clearEvents();
|
||||
$.scrollTo().off( 'scroll.mmvp' );
|
||||
this.$container.off( 'mmv-metadata-open' );
|
||||
};
|
||||
|
||||
MPSP.empty = function () {
|
||||
|
@ -78,6 +97,8 @@
|
|||
|
||||
// need to remove this to avoid animating again when reopening lightbox on same page
|
||||
this.$container.removeClass( 'invite' );
|
||||
|
||||
this.panelIsOpen = !!$.scrollTo().scrollTop();
|
||||
};
|
||||
|
||||
MPSP.initialize = function () {
|
||||
|
@ -88,9 +109,18 @@
|
|||
.toggleClass( 'panel-never-opened', !this.hasOpenedMetadata )
|
||||
.prop( 'title', mw.message( 'multimediaviewer-panel-open-popup-text' ).text() )
|
||||
.tipsy( { gravity: 's', delayIn: mw.config.get( 'wgMultimediaViewer').tooltipDelay } )
|
||||
.appendTo( this.$controlBar )
|
||||
.appendTo( this.$aboveFold )
|
||||
.click( function () {
|
||||
panel.toggle();
|
||||
// Trigger open event and do related actions that would be normally done by the scroll handler.
|
||||
// If we left this to the scroll handler, the size of the panel would change mid-animation
|
||||
// and the end position would be off.
|
||||
panel.panelIsOpen = true;
|
||||
panel.$dragIcon.addClass( 'panel-open' );
|
||||
// use triggerHandler instead of trigger because it is non-async; the untruncate handler
|
||||
// must run before the toggle() call
|
||||
panel.$container.triggerHandler( 'mmv-metadata-open' );
|
||||
|
||||
panel.toggle( 'up' );
|
||||
} );
|
||||
|
||||
this.$dragIconBottom = $( '<div>' )
|
||||
|
@ -99,7 +129,7 @@
|
|||
.tipsy( { gravity: 's', delayIn: mw.config.get( 'wgMultimediaViewer').tooltipDelay } )
|
||||
.appendTo( this.$container )
|
||||
.click( function () {
|
||||
panel.toggle();
|
||||
panel.toggle( 'down' );
|
||||
} );
|
||||
|
||||
this.hasOpenedMetadata = !this.localStorage || this.localStorage.getItem( 'mmv.hasOpenedMetadata' );
|
||||
|
@ -124,7 +154,7 @@
|
|||
*/
|
||||
MPSP.toggle = function ( forceDirection ) {
|
||||
var deferred = $.Deferred(),
|
||||
scrollTopWhenOpen = this.$container.outerHeight() - this.$controlBar.outerHeight(),
|
||||
scrollTopWhenOpen = this.$container.outerHeight() - parseInt( this.$aboveFold.css( 'min-height' ), 10 ),
|
||||
scrollTopWhenClosed = 0,
|
||||
scrollTop = $.scrollTo().scrollTop(),
|
||||
panelIsOpen = scrollTop > scrollTopWhenClosed,
|
||||
|
@ -192,23 +222,16 @@
|
|||
* Receives the window's scroll events and flips the chevron if necessary.
|
||||
*/
|
||||
MPSP.scroll = function () {
|
||||
var scrolled = !!$.scrollTo().scrollTop();
|
||||
var panelIsOpen = !!$.scrollTo().scrollTop();
|
||||
|
||||
this.$dragIcon.toggleClass( 'panel-open', scrolled );
|
||||
this.$dragIcon.toggleClass( 'panel-open', panelIsOpen );
|
||||
|
||||
if (
|
||||
!this.hasOpenedMetadata
|
||||
&& scrolled
|
||||
&& this.localStorage
|
||||
) {
|
||||
this.hasOpenedMetadata = true;
|
||||
this.$dragIcon.removeClass( 'panel-never-opened' );
|
||||
try {
|
||||
this.localStorage.setItem( 'mmv.hasOpenedMetadata', true );
|
||||
} catch ( e ) {
|
||||
// localStorage is full or disabled
|
||||
}
|
||||
if ( panelIsOpen && !this.panelIsOpen ) { // just opened (this is skipped in some cases, see the $dragIcon click handler)
|
||||
this.$container.trigger( 'mmv-metadata-open' );
|
||||
} else if ( !panelIsOpen && this.panelIsOpen ) { // just closed
|
||||
this.$container.trigger( 'mmv-metadata-close' );
|
||||
}
|
||||
this.panelIsOpen = panelIsOpen;
|
||||
};
|
||||
|
||||
mw.mmv.ui.MetadataPanelScroller = MetadataPanelScroller;
|
||||
|
|
|
@ -83,7 +83,13 @@
|
|||
localStorage = { getItem : $.noop, setItem : this.sandbox.stub().throwsException( 'I am full' ) },
|
||||
scroller = new mw.mmv.ui.MetadataPanelScroller( $qf, $( '<div>' ).appendTo( $qf ), localStorage );
|
||||
|
||||
this.sandbox.stub( $, 'scrollTo', function() { return { scrollTop : function() { return 10; } }; } );
|
||||
this.sandbox.stub( $, 'scrollTo', function() { return {
|
||||
scrollTop : function() { return 10; },
|
||||
on: $.noop,
|
||||
off: $.noop
|
||||
}; } );
|
||||
|
||||
scroller.attach();
|
||||
|
||||
scroller.scroll();
|
||||
|
||||
|
@ -92,6 +98,8 @@
|
|||
scroller.scroll();
|
||||
|
||||
assert.ok( localStorage.setItem.calledOnce, 'localStorage only written once' );
|
||||
|
||||
scroller.unattach();
|
||||
} );
|
||||
|
||||
/**
|
||||
|
@ -141,9 +149,9 @@
|
|||
QUnit.test( 'Metadata scrolling', 7, function ( assert ) {
|
||||
var $qf = $( '#qunit-fixture' ),
|
||||
$container = $( '<div>' ).css( 'height', 100 ).appendTo( $qf ),
|
||||
$controlBar = $( '<div>' ).css( 'height', 50 ).appendTo( $container ),
|
||||
$aboveFold = $( '<div>' ).css( 'height', 50 ).appendTo( $container ),
|
||||
fakeLocalStorage = { getItem : $.noop, setItem : $.noop },
|
||||
scroller = new mw.mmv.ui.MetadataPanelScroller( $container, $controlBar, fakeLocalStorage),
|
||||
scroller = new mw.mmv.ui.MetadataPanelScroller( $container, $aboveFold, fakeLocalStorage),
|
||||
keydown = $.Event( 'keydown' );
|
||||
|
||||
stubScrollFunctions( this.sandbox, scroller );
|
||||
|
@ -176,7 +184,7 @@
|
|||
scroller.$dragIcon.click();
|
||||
this.clock.tick( scroller.toggleScrollDuration );
|
||||
|
||||
scroller.$dragIcon.click();
|
||||
scroller.$dragIconBottom.click();
|
||||
this.clock.tick( scroller.toggleScrollDuration );
|
||||
|
||||
assert.strictEqual( $.scrollTo().scrollTop(), 0,
|
||||
|
@ -209,8 +217,8 @@
|
|||
QUnit.test( 'Metadata scroll logging', 6, function ( assert ) {
|
||||
var $qf = $( '#qunit-fixture' ),
|
||||
$container = $( '<div>' ).css( 'height', 100 ).appendTo( $qf ),
|
||||
$controlBar = $( '<div>' ).css( 'height', 50 ).appendTo( $container ),
|
||||
scroller = new mw.mmv.ui.MetadataPanelScroller( $container, $controlBar ),
|
||||
$aboveFold = $( '<div>' ).css( 'height', 50 ).appendTo( $container ),
|
||||
scroller = new mw.mmv.ui.MetadataPanelScroller( $container, $aboveFold ),
|
||||
keydown = $.Event( 'keydown' );
|
||||
|
||||
stubScrollFunctions( this.sandbox, scroller );
|
||||
|
@ -251,7 +259,7 @@
|
|||
assert.ok( mw.mmv.actionLogger.log.calledWithExactly( 'metadata-open' ), 'Opening click logged' );
|
||||
mw.mmv.actionLogger.log.reset();
|
||||
|
||||
scroller.$dragIcon.click();
|
||||
scroller.$dragIconBottom.click();
|
||||
this.clock.tick( scroller.toggleScrollDuration );
|
||||
|
||||
assert.ok( mw.mmv.actionLogger.log.calledWithExactly( 'metadata-close' ), 'Closing click logged' );
|
||||
|
|
Loading…
Reference in a new issue