' )
- .addClass( 'mw-mmv-drag-icon' )
- .appendTo( this.$dragBar );
+ this.$dragIconBottom = $( '
' )
+ .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' );
};
/**
* Animates the metadata area when the viewer is first opened.
*/
MPSP.animateMetadataOnce = function () {
- if ( !this.hasAnimatedMetadata ) {
+ if ( !this.hasOpenedMetadata && !this.hasAnimatedMetadata ) {
this.hasAnimatedMetadata = true;
this.$container.addClass( 'invite' );
}
@@ -124,17 +132,6 @@
mw.mmv.actionLogger.log( wasOpen ? 'metadata-open' : 'metadata-close' );
- this.$dragBar
- .prop( 'title',
- mw.message(
- 'multimediaviewer-panel-' +
- ( !wasOpen ? 'open' : 'close' ) +
- '-popup-text'
- ).text()
- );
-
- this.dragBarGravity = wasOpen ? 'n' : 's';
-
$.scrollTo( scrollTopTarget, this.toggleScrollDuration );
};
@@ -183,21 +180,20 @@
MPSP.scroll = function () {
var scrolled = !!$.scrollTo().scrollTop();
- this.$dragIcon.toggleClass( 'pointing-down', scrolled );
+ this.$dragIcon.toggleClass( 'panel-open', scrolled );
if (
- !this.savedHasOpenedMetadata &&
- scrolled &&
- this.localStorage
- ) {
+ !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
}
-
- // We mark it as saved even when localStorage failed, because retrying will very likely fail as well
- this.savedHasOpenedMetadata = true;
}
};
diff --git a/resources/mmv/ui/mmv.ui.metadataPanelScroller.less b/resources/mmv/ui/mmv.ui.metadataPanelScroller.less
index c439d11e2..58825cdba 100644
--- a/resources/mmv/ui/mmv.ui.metadataPanelScroller.less
+++ b/resources/mmv/ui/mmv.ui.metadataPanelScroller.less
@@ -2,6 +2,11 @@
@import "../mmv.mixins";
@import "mediawiki.mixins.animation";
+@drag-icon-width: 64px;
+@drag-icon-height: 18px;
+@drag-icon-color: #e6e6e6;
+@drag-icon-invite-color: #347bff;
+
.mw-mmv-post-image {
.animation( mw-mmv-appear-animation 0.5s ease 0s 1 normal forwards );
&.invite {
@@ -69,39 +74,66 @@
.mw-mmv-invite-animation;
}
-.mw-mmv-drag-affordance {
- width: 100%;
- height: @metadatabar-drag-height;
+.mw-mmv-drag-icon {
+ width: @drag-icon-width;
+ height: @drag-icon-height;
+
+ position: absolute;
+ left: 50%;
+ bottom: 0;
+ margin: 0 0 0 -(@drag-icon-width / 2);
+
+ /* @embed */
+ background-image: url(img/drag.svg);
+ background-repeat: no-repeat;
+ background-position: center bottom;
+ background-color: @drag-icon-color;
+
cursor: pointer;
+ z-index: 1; // make sure it is above the text - the icon is visually at the bottom but in the DOM at the top
+ .opacity(0.7);
+ transition: opacity 0.25s;
+
+ &-pointing-down { // use single-class selector - chevron direction is important enough to make it IE6-compatible
+ background-position: center top;
+ .rotate(180deg);
+
+ -webkit-border-bottom-left-radius: 3px;
+ -webkit-border-bottom-right-radius: 3px;
+ -moz-border-radius-bottomleft: 3px;
+ -moz-border-radius-bottomright: 3px;
+ border-bottom-left-radius: 3px;
+ border-bottom-right-radius: 3px;
+
+ .mw-mmv-post-image:hover & {
+ .opacity(1);
+ }
+ }
+ &-pointing-up {
+ -webkit-border-top-left-radius: 3px;
+ -webkit-border-top-right-radius: 3px;
+ -moz-border-radius-topleft: 3px;
+ -moz-border-radius-topright: 3px;
+ border-top-left-radius: 3px;
+ border-top-right-radius: 3px;
+
+ &:hover {
+ .opacity(1);
+ }
+ }
+
+ &.panel-open {
+ display: none;
+ }
+
+ &.panel-never-opened {
+ /* @embed */
+ background-image: url(img/drag-active.svg);
+ background-color: @drag-icon-invite-color;
+ .opacity(1);
+ }
.jq-fullscreened & {
display: none;
}
}
-
-.mw-mmv-drag-icon {
- width: 64px;
- height: @metadatabar-drag-height;
- /* @embed */
- background-image: url(img/drag.svg);
- background-repeat: no-repeat;
- background-position: center bottom;
- margin: 0 auto;
- .opacity(0.7);
- transition: opacity 0.25s;
-
- &.pointing-down {
- background-position: center top;
- .rotate(180deg);
- }
-
- .mw-mmv-post-image.invite & {
- /* @embed */
- background-image: url(img/drag-active.svg);
- .opacity(0.9);
- }
-}
-
-.mw-mmv-post-image:hover .mw-mmv-drag-icon {
- .opacity(1);
-}
diff --git a/resources/mmv/ui/mmv.ui.progressBar.less b/resources/mmv/ui/mmv.ui.progressBar.less
index 147c19d12..1473e3642 100644
--- a/resources/mmv/ui/mmv.ui.progressBar.less
+++ b/resources/mmv/ui/mmv.ui.progressBar.less
@@ -5,9 +5,10 @@
.mw-mmv-progress {
width: 100%;
height: @progress-height;
+ position: relative;
+ bottom: @progress-height;
background-color: #cccccc;
background-color: rgba( 221, 221, 221, 0.5 );
- margin-top: -@progress-height;
}
.mw-mmv-progress.empty {
diff --git a/resources/mmv/ui/mmv.ui.stripeButtons.less b/resources/mmv/ui/mmv.ui.stripeButtons.less
index ba360b9d4..c8a9795fa 100644
--- a/resources/mmv/ui/mmv.ui.stripeButtons.less
+++ b/resources/mmv/ui/mmv.ui.stripeButtons.less
@@ -14,7 +14,10 @@
float: right;
height: @button-height;
- margin-top: @metadatabar-top-content-height - ( @button-height + 2 * @button-vertical-padding );
+ margin-top: @metadatabar-above-fold-height - ( @button-height + 2 * @button-vertical-padding );
+ .jq-fullscreened & {
+ margin-top: @metadatabar-above-fold-fullscreen-height - ( @button-height + 2 * @button-vertical-padding );
+ }
border-left: 1px solid @border-text-color;
padding: @button-vertical-padding 20px;
@@ -22,7 +25,7 @@
font-size: 1.25em;
color: @button-text-color;
cursor: pointer;
- opacity: 0.8;
+ .opacity(0.8);
transition: opacity 0.25s;
// when the button is a link, we need more selector specificity
@@ -36,7 +39,7 @@
&.open,
&:hover {
- opacity: 1;
+ .opacity(1);
}
&:before {
@@ -49,7 +52,6 @@
top: 0.1em;
background-size: 100% 100%;
- margin-right: 0.25em;
content: ' ';
vertical-align: baseline;
}
diff --git a/tests/qunit/mmv/ui/mmv.ui.metadataPanelScroller.test.js b/tests/qunit/mmv/ui/mmv.ui.metadataPanelScroller.test.js
index 663cd7ef1..8077da5f3 100644
--- a/tests/qunit/mmv/ui/mmv.ui.metadataPanelScroller.test.js
+++ b/tests/qunit/mmv/ui/mmv.ui.metadataPanelScroller.test.js
@@ -22,12 +22,11 @@
}
} ) );
- QUnit.test( 'empty()', 2, function ( assert ) {
+ QUnit.test( 'empty()', 1, function ( assert ) {
var $qf = $( '#qunit-fixture' ),
scroller = new mw.mmv.ui.MetadataPanelScroller( $qf, $( '
' ).appendTo( $qf ) );
scroller.empty();
- assert.ok( !scroller.$dragIcon.hasClass( 'pointing-down' ), 'We successfully reset the chevron' );
assert.ok( !scroller.$container.hasClass( 'invite' ), 'We successfully reset the invite' );
} );
@@ -76,19 +75,23 @@
scroller.scroll();
- assert.ok( !scroller.savedHasOpenedMetadata, 'No localStorage, we don\'t try to save the opened flag' );
+ assert.strictEqual( scroller.hasOpenedMetadata, true, 'We store hasOpenedMetadata flag for the session' );
} );
- QUnit.test( 'localStorage is full', 1, function( assert ) {
+ QUnit.test( 'localStorage is full', 2, function( assert ) {
var $qf = $( '#qunit-fixture' ),
- scroller = new mw.mmv.ui.MetadataPanelScroller( $qf, $( '
' ).appendTo( $qf ),
- { getItem : $.noop, setItem : function() { throw 'I am full'; } } );
+ localStorage = { getItem : $.noop, setItem : this.sandbox.stub().throwsException( 'I am full' ) },
+ scroller = new mw.mmv.ui.MetadataPanelScroller( $qf, $( '
' ).appendTo( $qf ), localStorage );
this.sandbox.stub( $, 'scrollTo', function() { return { scrollTop : function() { return 10; } }; } );
scroller.scroll();
- assert.ok( scroller.savedHasOpenedMetadata, 'Full localStorage, we don\'t try to save the opened flag more than once' );
+ assert.strictEqual( scroller.hasOpenedMetadata, true, 'We store hasOpenedMetadata flag for the session' );
+
+ scroller.scroll();
+
+ assert.ok( localStorage.setItem.calledOnce, 'localStorage only written once' );
} );
/**
@@ -135,7 +138,7 @@
} );
}
- QUnit.test( 'Metadata scrolling', 12, function ( assert ) {
+ QUnit.test( 'Metadata scrolling', 7, function ( assert ) {
var $qf = $( '#qunit-fixture' ),
$container = $( '
' ).css( 'height', 100 ).appendTo( $qf ),
$controlBar = $( '
' ).css( 'height', 50 ).appendTo( $container ),
@@ -154,8 +157,6 @@
scroller.attach();
assert.strictEqual( $.scrollTo().scrollTop(), 0, 'scrollTo scrollTop should be set to 0' );
- assert.ok( !scroller.$dragIcon.hasClass( 'pointing-down' ),
- 'Chevron pointing up' );
assert.ok( !fakeLocalStorage.setItem.called, 'The metadata hasn\'t been open yet, no entry in localStorage' );
@@ -163,8 +164,6 @@
scroller.keydown( keydown );
this.clock.tick( scroller.toggleScrollDuration );
- assert.ok( scroller.$dragIcon.hasClass( 'pointing-down' ),
- 'Chevron pointing down after pressing up arrow' );
assert.ok( fakeLocalStorage.setItem.calledWithExactly( 'mmv.hasOpenedMetadata', true ), 'localStorage knows that the metadata has been open' );
keydown.which = 40; // Down arrow
@@ -173,22 +172,15 @@
assert.strictEqual( $.scrollTo().scrollTop(), 0,
'scrollTo scrollTop should be set to 0 after pressing down arrow' );
- assert.ok( !scroller.$dragIcon.hasClass( 'pointing-down' ),
- 'Chevron pointing up after pressing down arrow' );
scroller.$dragIcon.click();
this.clock.tick( scroller.toggleScrollDuration );
- assert.ok( scroller.$dragIcon.hasClass( 'pointing-down' ),
- 'Chevron pointing down after clicking the chevron once' );
-
scroller.$dragIcon.click();
this.clock.tick( scroller.toggleScrollDuration );
assert.strictEqual( $.scrollTo().scrollTop(), 0,
'scrollTo scrollTop should be set to 0 after clicking the chevron twice' );
- assert.ok( !scroller.$dragIcon.hasClass( 'pointing-down' ),
- 'Chevron pointing up after clicking the chevron twice' );
// Unattach lightbox from document
scroller.unattach();