Bug 649490 - Switch the volume slider on the media controls to be horizontal and always visible. r=Gijs
@ -54,7 +54,7 @@
|
||||
* is hidden by videocontrols.xml, and that alters the position of the
|
||||
* play button. This workaround moves it back to center.
|
||||
*/
|
||||
.controlBar.audio .playButton {
|
||||
.controlBar.audio-only .playButton {
|
||||
transform: translateX(28px);
|
||||
}
|
||||
|
||||
|
@ -54,7 +54,7 @@
|
||||
* is hidden by videocontrols.xml, and that alters the position of the
|
||||
* play button. This workaround moves it back to center.
|
||||
*/
|
||||
.controlBar.audio .playButton {
|
||||
.controlBar.audio-only .playButton {
|
||||
transform: translateX(28px);
|
||||
}
|
||||
|
||||
|
@ -30,14 +30,15 @@ const muteButtonWidth = 33;
|
||||
const muteButtonHeight = 28;
|
||||
const durationWidth = 34;
|
||||
const fullscreenButtonWidth = document.mozFullScreenEnabled ? 28 : 0;
|
||||
const scrubberWidth = videoWidth - playButtonWidth - muteButtonWidth - durationWidth - fullscreenButtonWidth;
|
||||
const volumeSliderWidth = 32;
|
||||
const scrubberWidth = videoWidth - playButtonWidth - durationWidth - muteButtonWidth - volumeSliderWidth - fullscreenButtonWidth;
|
||||
const scrubberHeight = 28;
|
||||
|
||||
// Play button is on the bottom-left
|
||||
const playButtonCenterX = 0 + Math.round(playButtonWidth / 2);
|
||||
const playButtonCenterY = videoHeight - Math.round(playButtonHeight / 2);
|
||||
// Mute button is on the bottom-right before the full screen button
|
||||
const muteButtonCenterX = videoWidth - Math.round(muteButtonWidth / 2) - fullscreenButtonWidth;
|
||||
// Mute button is on the bottom-right before the full screen button and volume slider
|
||||
const muteButtonCenterX = videoWidth - Math.round(muteButtonWidth / 2) - fullscreenButtonWidth - volumeSliderWidth;
|
||||
const muteButtonCenterY = videoHeight - Math.round(muteButtonHeight / 2);
|
||||
// Scrubber bar is between the play and mute buttons. We don't need it's
|
||||
// X center, just the offset of its box.
|
||||
|
@ -92,7 +92,8 @@ html|span.statActivity[seeking] > html|span.statActivitySeeking {
|
||||
.controlBar[size="hidden"],
|
||||
.controlBar[size="small"] .durationBox,
|
||||
.controlBar[size="small"] .durationLabel,
|
||||
.controlBar[size="small"] .positionLabel {
|
||||
.controlBar[size="small"] .positionLabel,
|
||||
.controlBar[size="small"] .volumeStack {
|
||||
visibility: collapse;
|
||||
}
|
||||
|
||||
|
@ -287,9 +287,10 @@
|
||||
<button class="muteButton"
|
||||
mutelabel="&muteButton.muteLabel;"
|
||||
unmutelabel="&muteButton.unmuteLabel;"/>
|
||||
<stack class="volumeStack" hidden="true" fadeout="true">
|
||||
<box class="volumeBackgroundBar"/>
|
||||
<scale class="volumeControl" orient="vertical" dir="reverse" movetoclick="true"/>
|
||||
<stack class="volumeStack">
|
||||
<box class="volumeBackground"/>
|
||||
<box class="volumeForeground" anonid="volumeForeground"/>
|
||||
<scale class="volumeControl" movetoclick="true"/>
|
||||
</stack>
|
||||
<button class="fullscreenButton"
|
||||
enterfullscreenlabel="&fullscreenButton.enterfullscreenlabel;"
|
||||
@ -313,7 +314,6 @@
|
||||
controlBar : null,
|
||||
playButton : null,
|
||||
muteButton : null,
|
||||
volumeStack : null,
|
||||
volumeControl : null,
|
||||
durationLabel : null,
|
||||
positionLabel : null,
|
||||
@ -345,9 +345,11 @@
|
||||
if (!this.isTopLevelSyntheticDocument)
|
||||
return;
|
||||
if (this._isAudioOnly) {
|
||||
this.controlBar.setAttribute("audio-only", true);
|
||||
this.video.style.height = this._controlBarHeight + "px";
|
||||
this.video.style.width = "66%";
|
||||
} else {
|
||||
this.controlBar.removeAttribute("audio-only");
|
||||
this.video.style.removeProperty("height");
|
||||
this.video.style.removeProperty("width");
|
||||
}
|
||||
@ -462,6 +464,7 @@
|
||||
this._playButtonWidth = this.playButton.clientWidth;
|
||||
this._durationLabelWidth = this.durationLabel.clientWidth;
|
||||
this._muteButtonWidth = this.muteButton.clientWidth;
|
||||
this._volumeControlWidth = this.volumeControl.clientWidth;
|
||||
this._fullscreenButtonWidth = this.fullscreenButton.clientWidth;
|
||||
this._controlBarHeight = this.controlBar.clientHeight;
|
||||
this.controlBar.hidden = true;
|
||||
@ -554,9 +557,11 @@
|
||||
this.setupStatusFader();
|
||||
break;
|
||||
case "volumechange":
|
||||
var volume = this.video.muted ? 0 : Math.round(this.video.volume * 100);
|
||||
var volume = this.video.muted ? 0 : this.video.volume;
|
||||
var volumePercentage = Math.round(volume * 100);
|
||||
this.setMuteButtonState(this.video.muted);
|
||||
this.volumeControl.value = volume;
|
||||
this.volumeControl.value = volumePercentage;
|
||||
this.volumeForeground.style.paddingRight = (1 - volume) * this._volumeControlWidth + "px";
|
||||
break;
|
||||
case "loadedmetadata":
|
||||
this.adjustControlSize();
|
||||
@ -854,21 +859,6 @@
|
||||
this.bufferBar.value = endTime;
|
||||
},
|
||||
|
||||
onVolumeMouseInOut : function (event) {
|
||||
let doc = this.video.ownerDocument;
|
||||
let win = doc.defaultView;
|
||||
if (this.isVideoWithoutAudioTrack() ||
|
||||
(this.isAudioOnly && this.isTopLevelSyntheticDocument)) {
|
||||
return;
|
||||
}
|
||||
// Ignore events caused by transitions between mute button and volumeStack,
|
||||
// or between nodes inside these two elements.
|
||||
if (this.isEventWithin(event, this.muteButton, this.volumeStack))
|
||||
return;
|
||||
var isMouseOver = (event.type == "mouseover");
|
||||
this.startFade(this.volumeStack, isMouseOver);
|
||||
},
|
||||
|
||||
_controlsHiddenByTimeout : false,
|
||||
_showControlsTimeout : 0,
|
||||
SHOW_CONTROLS_TIMEOUT_MS: 500,
|
||||
@ -1360,6 +1350,7 @@
|
||||
_playButtonWidth : 0,
|
||||
_durationLabelWidth : 0,
|
||||
_muteButtonWidth : 0,
|
||||
_volumeControlWidth : 0,
|
||||
_fullscreenButtonWidth : 0,
|
||||
_controlBarHeight : 0,
|
||||
_overlayPlayButtonHeight : 64,
|
||||
@ -1377,6 +1368,7 @@
|
||||
minScrubberWidth +
|
||||
this._durationLabelWidth +
|
||||
this._muteButtonWidth +
|
||||
this._volumeControlWidth +
|
||||
this._fullscreenButtonWidth;
|
||||
let minHeightForControlBar = this._controlBarHeight;
|
||||
let minWidthOnlyPlayPause = this._playButtonWidth + this._muteButtonWidth;
|
||||
@ -1400,14 +1392,12 @@
|
||||
init : function (binding) {
|
||||
this.video = binding.parentNode;
|
||||
this.videocontrols = binding;
|
||||
this.isAudioOnly = (this.video instanceof HTMLAudioElement);
|
||||
|
||||
this.statusIcon = document.getAnonymousElementByAttribute(binding, "class", "statusIcon");
|
||||
this.controlBar = document.getAnonymousElementByAttribute(binding, "class", "controlBar");
|
||||
this.playButton = document.getAnonymousElementByAttribute(binding, "class", "playButton");
|
||||
this.muteButton = document.getAnonymousElementByAttribute(binding, "class", "muteButton");
|
||||
this.volumeControl = document.getAnonymousElementByAttribute(binding, "class", "volumeControl");
|
||||
this.volumeStack = document.getAnonymousElementByAttribute(binding, "class", "volumeStack");
|
||||
this.progressBar = document.getAnonymousElementByAttribute(binding, "class", "progressBar");
|
||||
this.bufferBar = document.getAnonymousElementByAttribute(binding, "class", "bufferBar");
|
||||
this.scrubber = document.getAnonymousElementByAttribute(binding, "class", "scrubber");
|
||||
@ -1419,6 +1409,7 @@
|
||||
this.controlsSpacer = document.getAnonymousElementByAttribute(binding, "class", "controlsSpacer");
|
||||
this.clickToPlay = document.getAnonymousElementByAttribute(binding, "class", "clickToPlay");
|
||||
this.fullscreenButton = document.getAnonymousElementByAttribute(binding, "class", "fullscreenButton");
|
||||
this.volumeForeground = document.getAnonymousElementByAttribute(binding, "anonid", "volumeForeground");
|
||||
|
||||
this.statsTable = document.getAnonymousElementByAttribute(binding, "class", "statsTable");
|
||||
this.stats.filename = document.getAnonymousElementByAttribute(binding, "class", "statFilename");
|
||||
@ -1432,6 +1423,7 @@
|
||||
this.stats.framesPresented = document.getAnonymousElementByAttribute(binding, "class", "statFramesPresented");
|
||||
this.stats.framesPainted = document.getAnonymousElementByAttribute(binding, "class", "statFramesPainted");
|
||||
|
||||
this.isAudioOnly = (this.video instanceof HTMLAudioElement);
|
||||
this.setupInitialState();
|
||||
this.setupNewLoadState();
|
||||
|
||||
@ -1459,15 +1451,6 @@
|
||||
addListener(this.controlsSpacer, "click", this.clickToPlayClickHandler);
|
||||
addListener(this.controlsSpacer, "dblclick", this.toggleFullscreen);
|
||||
|
||||
if (this.isAudioOnly) {
|
||||
this.controlBar.classList.add("audio");
|
||||
} else {
|
||||
addListener(this.muteButton, "mouseover", this.onVolumeMouseInOut);
|
||||
addListener(this.muteButton, "mouseout", this.onVolumeMouseInOut);
|
||||
addListener(this.volumeStack, "mouseover", this.onVolumeMouseInOut);
|
||||
addListener(this.volumeStack, "mouseout", this.onVolumeMouseInOut);
|
||||
}
|
||||
|
||||
addListener(this.videocontrols, "resizevideocontrols", this.adjustControlSize);
|
||||
addListener(this.videocontrols, "transitionend", this.onTransitionEnd);
|
||||
addListener(this.video.ownerDocument, "mozfullscreenchange", this.onFullscreenChange);
|
||||
@ -1539,11 +1522,12 @@
|
||||
<button class="muteButton"
|
||||
mutelabel="&muteButton.muteLabel;"
|
||||
unmutelabel="&muteButton.unmuteLabel;"/>
|
||||
<stack class="volumeStack" hidden="true" fadeout="true">
|
||||
<box class="volumeBackgroundBar"/>
|
||||
<scale class="volumeControl" orient="vertical" dir="reverse" movetoclick="true"/>
|
||||
<stack class="volumeStack">
|
||||
<box class="volumeBackground"/>
|
||||
<box class="volumeForeground" anonid="volumeForeground"/>
|
||||
<scale class="volumeControl" movetoclick="true"/>
|
||||
</stack>
|
||||
</hbox>
|
||||
</hbox>
|
||||
<stack class="scrubberStack" flex="1">
|
||||
<box class="backgroundBar"/>
|
||||
<progressmeter class="bufferBar"/>
|
||||
|
@ -174,8 +174,8 @@ toolkit.jar:
|
||||
skin/classic/global/media/error.png (media/error.png)
|
||||
skin/classic/global/media/throbber.png (media/throbber.png)
|
||||
skin/classic/global/media/stalled.png (media/stalled.png)
|
||||
skin/classic/global/media/volumeThumb.png (media/volumeThumb.png)
|
||||
skin/classic/global/media/volumeThumb@2x.png (media/volumeThumb@2x.png)
|
||||
skin/classic/global/media/volume-empty.png (media/volume-empty.png)
|
||||
skin/classic/global/media/volume-full.png (media/volume-full.png)
|
||||
skin/classic/global/media/clicktoplay-bgtexture.png (media/clicktoplay-bgtexture.png)
|
||||
skin/classic/global/media/videoClickToPlayButton.svg (media/videoClickToPlayButton.svg)
|
||||
skin/classic/global/menu/menu-arrow.png (menu/menu-arrow.png)
|
||||
|
@ -59,6 +59,10 @@
|
||||
background-image: url(chrome://global/skin/media/noAudio.png);
|
||||
}
|
||||
|
||||
.muteButton[noAudio] + .volumeStack {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.fullscreenButton {
|
||||
background-image: -moz-image-rect(url("chrome://global/skin/media/fullscreenButton.png"), 0, 16, 16, 0);
|
||||
}
|
||||
@ -67,36 +71,37 @@
|
||||
background-image: -moz-image-rect(url("chrome://global/skin/media/fullscreenButton.png"), 0, 32, 16, 16);
|
||||
}
|
||||
|
||||
.volumeStack {
|
||||
width: 28px;
|
||||
height: 70px;
|
||||
background-color: rgba(35,31,32,.74);
|
||||
/* use negative margin to place stack over the mute button to its left. */
|
||||
margin: -70px 3px 28px -31px;
|
||||
overflow: hidden; /* crop it when sliding down, don't grow the control bar */
|
||||
position: relative; /* Trick to work around negative margin interfering with dragging the thumb. */
|
||||
padding-top: 6px;
|
||||
}
|
||||
|
||||
.volumeControl {
|
||||
min-height: 64px;
|
||||
height: 32px;
|
||||
width: 32px;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.volumeBackground,
|
||||
.volumeForeground {
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
}
|
||||
|
||||
.volumeBackground {
|
||||
background-image: url(chrome://global/skin/media/volume-empty.png);
|
||||
}
|
||||
|
||||
.volumeForeground {
|
||||
background-image: url(chrome://global/skin/media/volume-full.png);
|
||||
background-clip: content-box;
|
||||
}
|
||||
|
||||
.controlBar[audio-only] > .volumeStack {
|
||||
-moz-margin-end: 8px;
|
||||
}
|
||||
|
||||
/* .scale-thumb is an element inside the <scale> implementation. */
|
||||
.volumeControl .scale-thumb {
|
||||
/* Override the default thumb appearance with a custom image. */
|
||||
-moz-appearance: none;
|
||||
background: url(chrome://global/skin/media/volumeThumb.png) no-repeat center;
|
||||
border: none;
|
||||
min-width: 20px;
|
||||
min-height: 10px;
|
||||
}
|
||||
|
||||
.volumeBackgroundBar {
|
||||
/* margin left/right: make bar 8px wide (control width = 28, minus 2 * 10 margin) */
|
||||
margin: 0 10px;
|
||||
background-color: rgba(255,255,255,.75);
|
||||
border-radius: 2.5px;
|
||||
min-width: 0;
|
||||
min-height: 32px;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.durationBox {
|
||||
@ -337,10 +342,6 @@ html|table {
|
||||
background-image: -moz-image-rect(url("chrome://global/skin/media/fullscreenButton@2x.png"), 0, 64, 32, 32);
|
||||
background-size: 16px 16px;
|
||||
}
|
||||
.volumeControl .scale-thumb {
|
||||
background-image: url(chrome://global/skin/media/volumeThumb@2x.png);
|
||||
background-size: 20px 10px;
|
||||
}
|
||||
.timeThumb {
|
||||
background-image: url(chrome://global/skin/media/scrubberThumb@2x.png);
|
||||
background-size: 33px 28px;
|
||||
|
BIN
toolkit/themes/osx/global/media/volume-empty.png
Normal file
After Width: | Height: | Size: 295 B |
BIN
toolkit/themes/osx/global/media/volume-full.png
Normal file
After Width: | Height: | Size: 297 B |
Before Width: | Height: | Size: 163 B |
Before Width: | Height: | Size: 281 B |
@ -163,7 +163,8 @@ toolkit.jar:
|
||||
skin/classic/global/media/scrubberThumbWide.png (media/scrubberThumbWide.png)
|
||||
skin/classic/global/media/throbber.png (media/throbber.png)
|
||||
skin/classic/global/media/stalled.png (media/stalled.png)
|
||||
skin/classic/global/media/volumeThumb.png (media/volumeThumb.png)
|
||||
skin/classic/global/media/volume-empty.png (media/volume-empty.png)
|
||||
skin/classic/global/media/volume-full.png (media/volume-full.png)
|
||||
skin/classic/global/media/error.png (media/error.png)
|
||||
skin/classic/global/media/clicktoplay-bgtexture.png (media/clicktoplay-bgtexture.png)
|
||||
skin/classic/global/media/videoClickToPlayButton.svg (media/videoClickToPlayButton.svg)
|
||||
@ -344,7 +345,8 @@ toolkit.jar:
|
||||
skin/classic/aero/global/media/scrubberThumbWide.png (media/scrubberThumbWide.png)
|
||||
skin/classic/aero/global/media/throbber.png (media/throbber.png)
|
||||
skin/classic/aero/global/media/stalled.png (media/stalled.png)
|
||||
skin/classic/aero/global/media/volumeThumb.png (media/volumeThumb.png)
|
||||
skin/classic/aero/global/media/volume-empty.png (media/volume-empty.png)
|
||||
skin/classic/aero/global/media/volume-full.png (media/volume-full.png)
|
||||
skin/classic/aero/global/media/error.png (media/error.png)
|
||||
skin/classic/aero/global/media/clicktoplay-bgtexture.png (media/clicktoplay-bgtexture.png)
|
||||
skin/classic/aero/global/media/videoClickToPlayButton.svg (media/videoClickToPlayButton.svg)
|
||||
|
@ -59,6 +59,10 @@
|
||||
background-image: url(chrome://global/skin/media/noAudio.png);
|
||||
}
|
||||
|
||||
.muteButton[noAudio] + .volumeStack {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.fullscreenButton {
|
||||
background-image: -moz-image-rect(url("chrome://global/skin/media/fullscreenButton.png"), 0, 16, 16, 0);
|
||||
}
|
||||
@ -67,36 +71,37 @@
|
||||
background-image: -moz-image-rect(url("chrome://global/skin/media/fullscreenButton.png"), 0, 32, 16, 16);
|
||||
}
|
||||
|
||||
.volumeStack {
|
||||
width: 28px;
|
||||
height: 70px;
|
||||
background-color: rgba(35,31,32,.74);
|
||||
/* use negative margin to place stack over the mute button to its left. */
|
||||
margin: -70px 3px 28px -31px;
|
||||
overflow: hidden; /* crop it when sliding down, don't grow the control bar */
|
||||
position: relative; /* Trick to work around negative margin interfering with dragging the thumb. */
|
||||
padding-top: 6px;
|
||||
}
|
||||
|
||||
.volumeControl {
|
||||
min-height: 64px;
|
||||
height: 32px;
|
||||
width: 32px;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.volumeBackground,
|
||||
.volumeForeground {
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
}
|
||||
|
||||
.volumeBackground {
|
||||
background-image: url(chrome://global/skin/media/volume-empty.png);
|
||||
}
|
||||
|
||||
.volumeForeground {
|
||||
background-image: url(chrome://global/skin/media/volume-full.png);
|
||||
background-clip: content-box;
|
||||
}
|
||||
|
||||
.controlBar[audio-only] > .volumeStack {
|
||||
-moz-margin-end: 8px;
|
||||
}
|
||||
|
||||
/* .scale-thumb is an element inside the <scale> implementation. */
|
||||
.volumeControl .scale-thumb {
|
||||
/* Override the default thumb appearance with a custom image. */
|
||||
-moz-appearance: none;
|
||||
background: url(chrome://global/skin/media/volumeThumb.png) no-repeat center;
|
||||
border: none;
|
||||
min-width: 20px;
|
||||
min-height: 10px;
|
||||
}
|
||||
|
||||
.volumeBackgroundBar {
|
||||
/* margin left/right: make bar 8px wide (control width = 28, minus 2 * 10 margin) */
|
||||
margin: 0 10px;
|
||||
background-color: rgba(255,255,255,.75);
|
||||
border-radius: 2.5px;
|
||||
min-width: 0;
|
||||
min-height: 32px;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.durationBox {
|
||||
@ -170,7 +175,8 @@
|
||||
}
|
||||
|
||||
/* .scale-thumb is an element inside the <scale> implementation. */
|
||||
.scrubber .scale-thumb {
|
||||
.scrubber .scale-thumb,
|
||||
.volumeControl .scale-thumb {
|
||||
/* Override the default thumb appearance with a custom image. */
|
||||
-moz-appearance: none;
|
||||
background: transparent;
|
||||
|
BIN
toolkit/themes/windows/global/media/volume-empty.png
Normal file
After Width: | Height: | Size: 295 B |
BIN
toolkit/themes/windows/global/media/volume-full.png
Normal file
After Width: | Height: | Size: 297 B |
Before Width: | Height: | Size: 163 B |