Gergő Tisza has uploaded a new change for review. https://gerrit.wikimedia.org/r/124032
Change subject: Show tooltip when all sorts of conditions are met ...................................................................... Show tooltip when all sorts of conditions are met Change-Id: I987d5d517c3db2409e138b85b90115260d9116bd Mingle: https://wikimedia.mingle.thoughtworks.com/projects/multimedia/cards/261 --- M resources/mmv/mmv.js M resources/mmv/ui/mmv.ui.stripeButtons.js M tests/qunit/mmv/ui/mmv.ui.stripeButtons.test.js 3 files changed, 173 insertions(+), 3 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/MultimediaViewer refs/changes/32/124032/1 diff --git a/resources/mmv/mmv.js b/resources/mmv/mmv.js index fce0409..13b83bf 100755 --- a/resources/mmv/mmv.js +++ b/resources/mmv/mmv.js @@ -630,6 +630,35 @@ }; /** + * @event mmv.close + * Fired when the viewer is closed. + */ + /** + * @event mmv-close + * Fired when the viewer is closed. + */ + /** + * @event mmv-next + * Fired when the user requests the next image. + */ + /** + * @event mmv-next + * Fired when the user requests the next image. + */ + /** + * @event mmv-prev + * Fired when the user requests the previous image. + */ + /** + * @event mmv-resize + * Fired when the screen size changes. + */ + /** + * @event mmv-request-thumbnail + * Used by components to request a thumbnail URL for the current thumbnail, with a given size. + * @param {number} size + */ + /** * Registers all event handlers */ MMVP.setupEventHandlers = function () { diff --git a/resources/mmv/ui/mmv.ui.stripeButtons.js b/resources/mmv/ui/mmv.ui.stripeButtons.js index 1719dc1..c34b507 100644 --- a/resources/mmv/ui/mmv.ui.stripeButtons.js +++ b/resources/mmv/ui/mmv.ui.stripeButtons.js @@ -104,8 +104,79 @@ href: this.getFeedbackSurveyUrl() } ).click( function ( e ) { buttons.openSurveyInNewWindow(); + buttons.maxOutTooltipDisplayCount(); e.preventDefault(); } ); + }; + + SBP.feedbackSettings = { + /** Show the tooltip this many seconds to get the user's attention, even when it is not hovered. */ + tooltipDisplayDuration: 5, + /** Wait for this long after the viewer is opened, before showing the tooltip. */ + tooltipDelay: 5, + /** Only show the tooltip this many times */ + tooltipMaxDisplayCount: 3 + }; + + /** + * Returns the number of times the tooltip was shown so far. This number is set to 999 if the + * user clicked on the link already, or we cannot count how many times the tooltip was shown + * already. + * @return {number} + */ + SBP.getTooltipDisplayCount = function () { + if ( !window.localStorage ) { + return 999; + } + if ( this.tooltipDisplayCount === undefined ) { + this.tooltipDisplayCount = localStorage.getItem( 'mmv.tooltipDisplayCount' ); + if ( this.tooltipDisplayCount === null ) { + this.tooltipDisplayCount = 0; + localStorage.setItem( 'mmv.tooltipDisplayCount', 0 ); + } + } + return this.tooltipDisplayCount; + }; + + /** + * Increases tooltip display count. + */ + SBP.increaseTooltipDisplayCount = function () { + this.getTooltipDisplayCount(); + if ( this.tooltipDisplayCount !== undefined ) { + this.tooltipDisplayCount++; + localStorage.setItem( 'mmv.tooltipDisplayCount', this.tooltipDisplayCount ); + } + }; + + /** + * Sets tooltip display count so large that the tooltip will never be shown again. + * We use this for users who already opened the form. + */ + SBP.maxOutTooltipDisplayCount = function () { + this.getTooltipDisplayCount(); + if ( this.tooltipDisplayCount !== undefined ) { + this.tooltipDisplayCount = 999; + localStorage.setItem( 'mmv.tooltipDisplayCount', this.tooltipDisplayCount ); + } + }; + + /** + * Show the tooltip to the user if it was not shown often enough yet. + */ + SBP.maybeDisplayTooltip = function () { + var buttons = this; + if ( + this.readyToShowFeedbackTooltip && + this.getTooltipDisplayCount() < this.feedbackSettings.tooltipMaxDisplayCount + ) { + this.buttons.$feedback.tipsy( 'show' ); + setTimeout( function () { + buttons.buttons.$feedback.tipsy( 'hide' ); + }, this.feedbackSettings.tooltipDisplayDuration * 1000 ); + this.increaseTooltipDisplayCount(); + this.readyToShowFeedbackTooltip = false; + } }; /** @@ -183,6 +254,8 @@ if ( !mw.user.isAnon() ) { this.setDescriptionPageButton( imageInfo, repoInfo ); } + + this.maybeDisplayTooltip(); }; /** @@ -211,7 +284,7 @@ this.setInlineStyle( 'stripe-button-description-page', '.mw-mmv-stripe-button-dynamic:before {' + 'background-image: url("' + repoInfo.favIcon + '");' + - '}' + '}' ); } }; @@ -241,7 +314,8 @@ * Registers listeners. */ SBP.attach = function () { - var buttons = this.buttons; + var that = this, + buttons = this.buttons; buttons.$reuse.on( 'click.mmv-stripeButtons', function ( e ) { $( document ).trigger( 'mmv-reuse-open' ); @@ -253,6 +327,12 @@ this.handleEvent( 'mmv-reuse-closed', function () { buttons.$reuse.removeClass( 'open' ); } ); + + this.readyToShowFeedbackTooltip = false; + this.readyToShowFeedbackTooltipTimer = setTimeout( function () { + that.readyToShowFeedbackTooltip = true; + that.maybeDisplayTooltip(); + }, this.feedbackSettings.tooltipDelay * 1000 ); }; /** @@ -261,6 +341,10 @@ SBP.unattach = function () { this.constructor.super.prototype.unattach.call( this ); this.buttons.$reuse.off( 'click.mmv-stripeButtons' ); + + if ( this.readyToShowFeedbackTooltipTimer ) { + clearTimeout( this.readyToShowFeedbackTooltipTimer ); + } }; mw.mmv.ui.StripeButtons = StripeButtons; diff --git a/tests/qunit/mmv/ui/mmv.ui.stripeButtons.test.js b/tests/qunit/mmv/ui/mmv.ui.stripeButtons.test.js index 0105907..fa1d37e 100644 --- a/tests/qunit/mmv/ui/mmv.ui.stripeButtons.test.js +++ b/tests/qunit/mmv/ui/mmv.ui.stripeButtons.test.js @@ -16,7 +16,11 @@ */ ( function( mw, $ ) { - QUnit.module( 'mmv.ui.StripeButtons', QUnit.newMwEnvironment() ); + QUnit.module( 'mmv.ui.StripeButtons', QUnit.newMwEnvironment( { + setup: function () { + this.clock = this.sandbox.useFakeTimers(); + } + } ) ); function createStripeButtons() { var fixture = $( '#qunit-fixture' ); @@ -77,4 +81,57 @@ $( document ).off( 'mmv-reuse-open.test' ); } ); + + QUnit.test( 'Feedback tooltip', 8, function ( assert ) { + var buttons = createStripeButtons(), + displayCount, + hasTooltip = function () { return !!$( '.tipsy' ).length; }; + + this.sandbox.stub( window.localStorage, 'getItem', function () { return displayCount; } ); + this.sandbox.stub( window.localStorage, 'setItem', function ( _, val ) { displayCount = val; } ); + + displayCount = 0; + buttons.attach(); + + assert.ok( !hasTooltip(), 'No tooltip initially' ); + + this.clock.tick( 1000 ); + assert.ok( !hasTooltip(), 'No tooltip after 1s' ); + + this.clock.tick( 5000 ); + assert.ok( hasTooltip(), 'Tooltip visible after 6s' ); + assert.strictEqual( displayCount, 1, 'displayCount was increased' ); + + this.clock.tick( 5000 ); + assert.ok( !hasTooltip(), 'Tooltip hidden again after 11s' ); + + buttons.unattach(); + delete buttons.tooltipDisplayCount; + + displayCount = 3; + buttons.attach(); + + this.clock.tick( 6000 ); + assert.ok( !hasTooltip(), 'No tooltip after 6s when display count limit reached' ); + + buttons.unattach(); + delete buttons.tooltipDisplayCount; + + displayCount = 0; + buttons.openSurveyInNewWindow = this.sandbox.stub(); + buttons.attach(); + buttons.buttons.$feedback.triggerHandler( 'click' ); + + this.clock.tick( 6000 ); + assert.ok( !hasTooltip(), 'No tooltip if button was clicked' ); + + buttons.unattach(); + delete buttons.tooltipDisplayCount; + + displayCount = 0; + buttons.attach(); + buttons.unattach(); + this.clock.tick( 6000 ); + assert.ok( !hasTooltip(), 'No tooltip when unattached' ); + } ); }( mediaWiki, jQuery ) ); -- To view, visit https://gerrit.wikimedia.org/r/124032 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I987d5d517c3db2409e138b85b90115260d9116bd Gerrit-PatchSet: 1 Gerrit-Project: mediawiki/extensions/MultimediaViewer Gerrit-Branch: master Gerrit-Owner: Gergő Tisza <[email protected]> _______________________________________________ MediaWiki-commits mailing list [email protected] https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits
