jenkins-bot has submitted this change and it was merged. Change subject: Reveal full text when metadata panel is opened ......................................................................
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 --- M resources/mmv/mmv.lightboxinterface.js M resources/mmv/ui/mmv.ui.metadataPanel.js M resources/mmv/ui/mmv.ui.metadataPanelScroller.js M tests/qunit/mmv/ui/mmv.ui.metadataPanelScroller.test.js 4 files changed, 90 insertions(+), 39 deletions(-) Approvals: MarkTraceur: Looks good to me, approved jenkins-bot: Verified diff --git a/resources/mmv/mmv.lightboxinterface.js b/resources/mmv/mmv.lightboxinterface.js index 3d34ba2..2222365 100644 --- a/resources/mmv/mmv.lightboxinterface.js +++ b/resources/mmv/mmv.lightboxinterface.js @@ -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 ); }; diff --git a/resources/mmv/ui/mmv.ui.metadataPanel.js b/resources/mmv/ui/mmv.ui.metadataPanel.js index bc16d87..8541d5f 100644 --- a/resources/mmv/ui/mmv.ui.metadataPanel.js +++ b/resources/mmv/ui/mmv.ui.metadataPanel.js @@ -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( @@ -68,6 +68,16 @@ return; } 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(); } ); }; @@ -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; diff --git a/resources/mmv/ui/mmv.ui.metadataPanelScroller.js b/resources/mmv/ui/mmv.ui.metadataPanelScroller.js index 3caf40c..436cf67 100644 --- a/resources/mmv/ui/mmv.ui.metadataPanelScroller.js +++ b/resources/mmv/ui/mmv.ui.metadataPanelScroller.js @@ -23,14 +23,20 @@ * @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. @@ -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; diff --git a/tests/qunit/mmv/ui/mmv.ui.metadataPanelScroller.test.js b/tests/qunit/mmv/ui/mmv.ui.metadataPanelScroller.test.js index 8077da5..01b9b94 100644 --- a/tests/qunit/mmv/ui/mmv.ui.metadataPanelScroller.test.js +++ b/tests/qunit/mmv/ui/mmv.ui.metadataPanelScroller.test.js @@ -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' ); -- To view, visit https://gerrit.wikimedia.org/r/146992 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: merged Gerrit-Change-Id: I7e66ca0f45c2188dab4b78508ad7f91154187de4 Gerrit-PatchSet: 5 Gerrit-Project: mediawiki/extensions/MultimediaViewer Gerrit-Branch: master Gerrit-Owner: Gergő Tisza <[email protected]> Gerrit-Reviewer: Gergő Tisza <[email protected]> Gerrit-Reviewer: Gilles <[email protected]> Gerrit-Reviewer: Jaredzimmerman <[email protected]> Gerrit-Reviewer: MarkTraceur <[email protected]> Gerrit-Reviewer: jenkins-bot <> _______________________________________________ MediaWiki-commits mailing list [email protected] https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits
