Bug 475318 - video controls should display numeric position and duration. r=enn, ui-r=boriss

This commit is contained in:
Justin Dolske 2009-04-12 23:09:22 -07:00
Родитель a7ef654ea9
Коммит c226a39601
11 изменённых файлов: 200 добавлений и 42 удалений

Просмотреть файл

@ -10,6 +10,9 @@
<body>
<p id="display"></p>
<script type="text/javascript">
</script>
<div id="content">
<video width="320" height="240" id="video" src="video.ogg" controls mozNoDynamicControls></video>
</div>
@ -46,9 +49,9 @@ const playButtonWidth = 28;
const playButtonHeight = 28;
const muteButtonWidth = 33;
const muteButtonHeight = 28;
const scrubberWidth = videoWidth - playButtonWidth - muteButtonWidth;
const durationWidth = 34;
const scrubberWidth = videoWidth - playButtonWidth - muteButtonWidth - durationWidth;
const scrubberHeight = 28;
const thumbWidth = 11;
// Play button is on the bottom-left
const playButtonCenterX = 0 + Math.round(playButtonWidth / 2);
@ -176,7 +179,7 @@ function runTest(event) {
// Bug 477434 -- sometimes we get 0.098999 here instead of 0!
// is(video.currentTime, 0.0, "checking playback position");
var beginDragX = scrubberOffsetX + (thumbWidth / 2);
var beginDragX = scrubberOffsetX;
var endDragX = scrubberOffsetX + (scrubberWidth / 2);
synthesizeMouse(video, beginDragX, scrubberCenterY, { type: "mousedown", button: 0 });
synthesizeMouse(video, endDragX, scrubberCenterY, { type: "mousemove", button: 0 });

Просмотреть файл

@ -3,3 +3,7 @@
.scrubber {
-moz-binding: url("chrome://global/content/bindings/videocontrols.xml#suppressChangeEvent");
}
.scrubber .scale-thumb {
-moz-binding: url("chrome://global/content/bindings/videocontrols.xml#timeThumb");
}

Просмотреть файл

@ -6,9 +6,82 @@
xmlns:xbl="http://www.mozilla.org/xbl"
xmlns:svg="http://www.w3.org/2000/svg">
<binding id="timeThumb"
extends="chrome://global/content/bindings/scale.xml#scalethumb">
<xbl:content xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<xbl:children/>
<hbox class="timeThumb" xbl:inherits="showhours">
<label class="timeLabel"/>
</hbox>
</xbl:content>
<implementation>
<field name="timeLabel">null</field>
<constructor>
<![CDATA[
this.timeLabel = document.getAnonymousElementByAttribute(this, "class", "timeLabel");
this.timeLabel.setAttribute("value", "0:00");
]]>
</constructor>
<property name="showHours">
<getter>
<![CDATA[
return this.getAttribute("showhours") == "true";
]]>
</getter>
<setter>
<![CDATA[
this.setAttribute("showhours", val);
// If the duration becomes known while we're still showing the value
// for time=0, immediately update the value to show or hide the hours.
// It's less intrusive to do it now than when the user clicks play and
// is looking right next to the thumb.
var displayedTime = this.timeLabel.getAttribute("value");
if (val && displayedTime == "0:00")
this.timeLabel.setAttribute("value", "0:00:00");
else if (!val && displayedTime == "0:00:00")
this.timeLabel.setAttribute("value", "0:00");
]]>
</setter>
</property>
<method name="setTime">
<parameter name="time"/>
<body>
<![CDATA[
var timeString;
var hours = Math.floor(time / 3600000);
var mins = Math.floor(time % 3600000 / 60000);
var secs = Math.floor(time % 60000 / 1000);
if (secs < 10)
secs = "0" + secs;
if (hours || this.showHours) {
if (mins < 10)
mins = "0" + mins;
timeString = hours + ":" + mins + ":" + secs;
} else {
timeString = mins + ":" + secs;
}
this.timeLabel.setAttribute("value", timeString);
]]>
</body>
</method>
</implementation>
</binding>
<binding id="suppressChangeEvent"
extends="chrome://global/content/bindings/scale.xml#scale">
<implementation>
<field name="thumb">null</field>
<constructor>
<![CDATA[
this.thumb = document.getAnonymousElementByAttribute(this, "class", "scale-thumb");
]]>
</constructor>
<method name="valueChanged">
<parameter name="which"/>
<parameter name="newValue"/>
@ -20,6 +93,9 @@
// just calls the videocontrol's seekToPosition() method directly.
switch (which) {
case "curpos":
// Update the time shown in the thumb.
this.thumb.setTime(newValue);
// The value of userChanged is true when changing the position with the mouse,
// but not when pressing an arrow key. However, the base binding sets
// ._userChanged in its keypress handlers, so we just need to check both.
@ -66,6 +142,9 @@
<progressmeter class="progressBar" max="10000"/>
<scale class="scrubber" movetoclick="true"/>
</stack>
<vbox class="durationBox">
<label class="durationLabel"/>
</vbox>
<button class="muteButton" oncommand="document.getBindingParent(this).Utils.toggleMute();"/>
</hbox>
</vbox>
@ -131,11 +210,11 @@
videocontrols : null,
playButton : null,
muteButton : null,
durationLabel : null,
scrubberThumb : null,
scrubber : null,
progressBar : null,
bufferBar : null,
thumbWidth : 0,
randomID : 0,
videoEvents : ["play", "pause", "ended", "volumechange", "loadeddata",
@ -359,6 +438,25 @@
duration = this.maxCurrentTimeSeen;
this.log("Duration is " + duration + "ms");
// Format the duration as "h:mm:ss" or "m:ss"
var hours = Math.floor(duration / 3600000);
var mins = Math.floor(duration % 3600000 / 60000);
var secs = Math.floor(duration % 60000 / 1000);
var timeString;
if (secs < 10)
secs = "0" + secs;
if (hours) {
if (mins < 10)
mins = "0" + mins;
timeString = hours + ":" + mins + ":" + secs;
} else {
timeString = mins + ":" + secs;
}
this.durationLabel.setAttribute("value", timeString);
// If the duration is over an hour, thumb should show h:mm:ss instead of mm:ss
this.scrubberThumb.showHours = (duration >= 3600000);
this.scrubber.max = duration;
// XXX Can't set increment here, due to bug 473103. Also, doing so causes
// snapping when dragging with the mouse, so we can't just set a value for
@ -388,18 +486,10 @@
this.log("time update @ " + currentTime + "ms of " + duration + "ms");
this.scrubber.value = currentTime;
// Extend the progressBar so it goes to the right-edge of the
// scrubber thumb. This is a bit tricky, due to how the thumb is
// positioned... It's flush-left at the minimum position, but
// flush-right at the maximum position (so that the full thumb is
// always visible in the <scale>'s box).
// Extend the progressBar to the middle of the scrubber thumb.
var percent = currentTime / duration;
var leftEdge = Math.floor(percent * (this.scrubber.clientWidth - this.thumbWidth));
var rightEdge = leftEdge + this.thumbWidth;
var adjPercent = rightEdge / this.scrubber.clientWidth;
// The progressBar has max=10000
this.progressBar.value = Math.round(adjPercent * 10000);
this.progressBar.value = Math.round(percent * 10000);
},
onMouseInOut : function (event) {
@ -565,18 +655,14 @@
this.Utils.controlFader.element = document.getAnonymousElementByAttribute(this, "class", "controlBar");
this.Utils.statusFader.element = document.getAnonymousElementByAttribute(this, "class", "statusOverlay");
this.Utils.statusIcon = document.getAnonymousElementByAttribute(this, "class", "statusIcon");
this.Utils.playButton = document.getAnonymousElementByAttribute(this, "class", "playButton");
this.Utils.muteButton = document.getAnonymousElementByAttribute(this, "class", "muteButton");
this.Utils.statusIcon = document.getAnonymousElementByAttribute(this, "class", "statusIcon");
this.Utils.playButton = document.getAnonymousElementByAttribute(this, "class", "playButton");
this.Utils.muteButton = document.getAnonymousElementByAttribute(this, "class", "muteButton");
this.Utils.progressBar = document.getAnonymousElementByAttribute(this, "class", "progressBar");
this.Utils.bufferBar = document.getAnonymousElementByAttribute(this, "class", "bufferBar");
this.Utils.scrubber = document.getAnonymousElementByAttribute(this, "class", "scrubber");
// Get the width of the scrubber thumb.
var thumb = document.getAnonymousElementByAttribute(this.Utils.scrubber, "class", "scale-thumb");
if (thumb)
this.Utils.thumbWidth = thumb.clientWidth;
this.Utils.scrubberThumb = document.getAnonymousElementByAttribute(this.Utils.scrubber, "class", "scale-thumb");
this.Utils.durationLabel = document.getAnonymousElementByAttribute(this, "class", "durationLabel");
this.Utils.setupInitialState();

Просмотреть файл

@ -179,6 +179,7 @@ classic.jar:
+ skin/classic/global/media/muteButton.png (media/muteButton.png)
+ skin/classic/global/media/unmuteButton.png (media/unmuteButton.png)
+ skin/classic/global/media/scrubberThumb.png (media/scrubberThumb.png)
+ skin/classic/global/media/scrubberThumbWide.png (media/scrubberThumbWide.png)
+ skin/classic/global/media/error.png (media/error.png)
+ skin/classic/global/media/throbber.png (media/throbber.png)
+ skin/classic/global/menu/menu-arrow-dis.gif (menu/menu-arrow-dis.gif)

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 167 B

После

Ширина:  |  Высота:  |  Размер: 312 B

Двоичные данные
toolkit/themes/pinstripe/global/media/scrubberThumbWide.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 389 B

Просмотреть файл

@ -13,6 +13,8 @@
padding: 0px;
min-height: 28px;
min-width: 28px;
margin-right: -22px; /* 1/2 of scrubber thumb width, for overhang. */
position: relative; /* Trick to work around negative margin interfering with clicking on the button. */
}
.playButton[paused="true"] {
background: url(chrome://global/skin/media/playButton.png) no-repeat center;
@ -31,17 +33,30 @@
background: url(chrome://global/skin/media/unmuteButton.png) no-repeat center;
}
.durationBox {
-moz-box-pack: center;
}
.durationLabel {
margin-left: -22px; /* 1/2 of scrubber thumb width, for overhang. */
padding-left: 8px; /* don't bump into the scrubber bar */
padding-top: 2px; /* center vertically with scrubber bar */
color: rgba(255,255,255,0.75);
font: 11px sans-serif;
}
.backgroundBar {
/* make bar 8px tall (control height = 28, minus 2 * 10 margin) */
margin-top: 10px;
margin-bottom: 10px;
/* margin top/bottom: make bar 8px tall (control height = 28, minus 2 * 10 margin) */
/* margin left/right: 1/2 of scrubber thumb width, for overhang. */
margin: 10px 22px 10px 22px;
background-color: rgba(255,255,255,0.5);
-moz-border-radius: 4px 4px;
}
.bufferBar, .progressBar {
/* make bar 8px tall (control height = 28, minus 2 * 10 margin) */
margin: 10px 0px 10px 0px;
/* margin top/bottom: make bar 8px tall (control height = 28, minus 2 * 10 margin) */
/* margin left/right: 1/2 of scrubber thumb width, for overhang. */
margin: 10px 22px 10px 22px;
-moz-appearance: none;
min-width: 0px;
}
@ -59,7 +74,7 @@
.progressBar .progress-bar {
background-color: white;
-moz-border-radius: 4px 4px;
-moz-border-radius: 4px 0px 0px 4px;
}
/* .scale-slider is an element inside the <scale> implementation. */
@ -74,10 +89,26 @@
.scale-thumb {
/* Override the default thumb appearance with a custom image. */
-moz-appearance: none;
background: url(chrome://global/skin/media/scrubberThumb.png) no-repeat center;
background: transparent;
border: none;
min-width: 11px;
min-height: 20px;
}
.timeThumb {
background: url(chrome://global/skin/media/scrubberThumb.png) no-repeat center;
min-width: 44px;
min-height: 22px;
margin-top: -14px;
-moz-box-pack: center;
}
.timeThumb[showhours="true"] {
background: url(chrome://global/skin/media/scrubberThumbWide.png) no-repeat center;
}
.timeLabel {
color: rgba(255,255,255,0.75);
font: 10px sans-serif;
padding-top: 6px;
}
.statusOverlay {

Просмотреть файл

@ -151,6 +151,7 @@ classic.jar:
skin/classic/global/media/muteButton.png (media/muteButton.png)
skin/classic/global/media/unmuteButton.png (media/unmuteButton.png)
skin/classic/global/media/scrubberThumb.png (media/scrubberThumb.png)
skin/classic/global/media/scrubberThumbWide.png (media/scrubberThumbWide.png)
skin/classic/global/media/throbber.png (media/throbber.png)
skin/classic/global/media/error.png (media/error.png)
skin/classic/global/radio/radio-check.gif (radio/radio-check.gif)
@ -324,6 +325,7 @@ classic.jar:
skin/classic/aero/global/media/muteButton.png (media/muteButton.png)
skin/classic/aero/global/media/unmuteButton.png (media/unmuteButton.png)
skin/classic/aero/global/media/scrubberThumb.png (media/scrubberThumb.png)
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/error.png (media/error.png)
skin/classic/aero/global/radio/radio-check.gif (radio/radio-check.gif)

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 167 B

После

Ширина:  |  Высота:  |  Размер: 312 B

Двоичные данные
toolkit/themes/winstripe/global/media/scrubberThumbWide.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 389 B

Просмотреть файл

@ -14,6 +14,8 @@
min-height: 28px;
min-width: 28px;
border: none;
margin-right: -22px; /* 1/2 of scrubber thumb width, for overhang. */
position: relative; /* Trick to work around negative margin interfering with clicking on the button. */
}
.playButton[paused="true"] {
background: url(chrome://global/skin/media/playButton.png) no-repeat center;
@ -33,17 +35,30 @@
background: url(chrome://global/skin/media/unmuteButton.png) no-repeat center;
}
.durationBox {
-moz-box-pack: center;
}
.durationLabel {
margin-left: -22px; /* 1/2 of scrubber thumb width, for overhang. */
padding-left: 8px; /* don't bump into the scrubber bar */
padding-top: 0px; /* center vertically with scrubber bar */
color: rgba(255,255,255,0.75);
font: 11px sans-serif;
}
.backgroundBar {
/* make bar 8px tall (control height = 28, minus 2 * 10 margin) */
margin-top: 10px;
margin-bottom: 10px;
/* margin top/bottom: make bar 8px tall (control height = 28, minus 2 * 10 margin) */
/* margin left/right: 1/2 of scrubber thumb width, for overhang. */
margin: 10px 22px 10px 22px;
background-color: rgba(255,255,255,0.5);
-moz-border-radius: 4px 4px;
}
.bufferBar, .progressBar {
/* make bar 8px tall (control height = 28, minus 2 * 10 margin) */
margin: 10px 0px 10px 0px;
/* margin top/bottom: make bar 8px tall (control height = 28, minus 2 * 10 margin) */
/* margin left/right: 1/2 of scrubber thumb width, for overhang. */
margin: 10px 22px 10px 22px;
-moz-appearance: none;
border: none;
background-color: transparent;
@ -65,7 +80,7 @@
.progressBar .progress-bar {
background-color: white;
-moz-border-radius: 4px 4px;
-moz-border-radius: 4px 0px 0px 4px;
-moz-appearance: none;
}
@ -81,10 +96,26 @@
.scale-thumb {
/* Override the default thumb appearance with a custom image. */
-moz-appearance: none;
background: url(chrome://global/skin/media/scrubberThumb.png) no-repeat center;
background: transparent;
border: none;
min-width: 11px;
min-height: 20px;
}
.timeThumb {
background: url(chrome://global/skin/media/scrubberThumb.png) no-repeat center;
min-width: 44px;
min-height: 22px;
margin-top: -14px;
-moz-box-pack: center;
}
.timeThumb[showhours="true"] {
background: url(chrome://global/skin/media/scrubberThumbWide.png) no-repeat center;
}
.timeLabel {
color: rgba(255,255,255,0.75);
font: 10px sans-serif;
padding-top: 3px;
}
.statusOverlay {