Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(228)

Side by Side Diff: Source/core/html/shadow/MediaControls.js

Issue 456323002: [WIP] Re-implement MediaControls in Blink-in-JS (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 'use strict';
6
7 // FIXME: AXObject
8
9 installClass('MediaControls', function(MediaControlsPrototype) {
10
11 var kFadeInDuration = 0.1;
12 var kFadeOutDuration = 0.3;
13
14 // If you change this value, then also update the corresponding value in
15 // LayoutTests/media/media-controls.js.
16 var kTimeWithoutMouseMovementBeforeHidingMediaControls = 3;
17
18 var kIgnoreVideoHover = 1 << 0;
19 var kIgnoreFocus = 1 << 1;
20
21 function fillZero(num, length) {
22 var str = num.toString();
23 while (str.length < length) {
24 str = '0' + str;
25 }
26 return str;
27 }
28
29 function formatMediaControlsTime(time, duration) {
30 if (!isFinite(time)) {
31 time = 0;
32 }
33 if (!isFinite(duration)) {
34 duration = 0;
35 }
36 var seconds = Math.floor(Math.abs(time));
37 var hours = Math.floor(seconds / (60 * 60));
38 var minutes = Math.floor((seconds / 60) % 60);
39 seconds %= 60;
40
41 // duration defines the format of how the time is rendered
42 var durationSecs = Math.floor(Math.abs(duration));
43 var durationHours = Math.floor(durationSecs / (60 * 60));
44 var durationMins = Math.floor((durationSecs / 60) % 60);
45
46 var sign = time < 0 ? '-' : '';
47 if (durationHours || hours) {
48 return sign + fillZero(hours, 1) + ':' + fillZero(minutes, 2) + ':' + fillZero(seconds, 2);
49 }
50 if (durationMins > 9) {
51 return sign + fillZero(minutes, 2) + ':' + fillZero(seconds, 2);
52 }
53 return sign + fillZero(minutes, 1) + ':' + fillZero(seconds, 2);
54 }
55
56 function show(element) {
57 element.style.removeProperty('display');
58 }
59
60 function hide(element) {
61 element.style.setProperty('display', 'none')
62 }
63
64 function createElement(parent, pseudoId) {
65 var e = window.document.createElement(parent);
66 if (!e) {
67 throw 'not reached';
68 }
69 e.setAttribute('pseudo', pseudoId);
70 return e;
71 }
72
73 function createOverlayPlayButton(mediaControls) {
74 var button = createElement('input', '-webkit-media-controls-overlay-play -button');
75 button.mediaControls_ = mediaControls;
76 button.type = 'button';
77 button.onclick = function(e) {
78 this.mediaControls_.togglePlayState();
79 this.updateDisplayType();
80 e.preventDefault();
81 };
82 button.updateDisplayType = function() {
83 if (this.mediaControls_.shouldShowControls() && this.mediaControls_. togglePlayStateWillPlay()) {
84 show(this);
85 } else {
86 hide(this);
87 }
88 };
89 button.updateDisplayType();
90 return button;
91 }
92
93 function createPanel() {
94 var panel = createElement('div', '-webkit-media-controls-panel')
95 panel.isDisplayed_ = false;
96 panel.opaque_ = true;
97 panel.transitionTimer_ = null;
98 panel.startTimer = function() {
99 stopTimer();
100 // FIXME: Use transition end event
101 this.transitionTimer_ = setTimeout(kFadeOutDuration, this.transition TimerFired);
102 };
103 panel.stopTimer = function() {
104 if (this.transitionTimer_ !== null) {
105 clearTimeout(this.this.transitionTimer_);
106 this.transitionTimer_ = null;
107 }
108 };
109 panel.transitionTimerFired = function() {
110 if (!this.opaque_) {
111 hide(this);
112 }
113 // FIXME: Use web animation
114 this.stopTimer();
115 };
116 panel.makeOpaque = function() {
117 if (this.opaque_) {
118 return;
119 }
120 this.style.transformProperty = 'opacity';
121 this.style.transformDuration = kFadeInDuration + 's';
122 this.style.opacity = 1.0;
123 this.opaque_ = true;
124 if (this.isDisplayed_) {
125 show(this);
126 }
127 };
128 panel.makeTransparent = function() {
129 if (!this.opaque_) {
130 return;
131 }
132 this.style.transformProperty = 'opacity';
133 this.style.transformDuration = kFadeOutDuration + 's';
134 this.style.opacity = 0.0;
135 this.opacity_ = false;
136 this.startTimer();
137 };
138 panel.setIsDisplayed = function(isDisplayed) {
139 this.isDisplayed_ = isDisplayed;
140 };
141 return panel;
142 }
143
144 function createPlayButton(mediaControls) {
145 var imagePlay = 'url(' + mediaControls.getResourceDataURL('mediaplayerPl ay') + ')';
146 var imagePause = 'url(' + mediaControls.getResourceDataURL('mediaplayerP ause') + ')';
147 var imagePlayDisabled = 'url(' + mediaControls.getResourceDataURL('media playerPlayDisabled') + ')';
148
149 // FIXME: Consider MediaControlInputElement::isMouseFocusable()
150
151 var button = createElement('input', '-webkit-media-controls-play-button' );
152 button.mediaControls_ = mediaControls;
153 button.style.backgroundSize = '100%';
154 button.setAttribute('type', 'button');
155 button.onclick = function(e) {
156 this.mediaControls_.togglePlayState();
157 this.updateDisplayType();
158 e.preventDefault();
159 };
160 button.updateDisplayType = function() {
161 if (!this.mediaControls_.hasSource()) {
162 this.style.backgroundImage = imagePlayDisabled;
163 return;
164 }
165 if (this.mediaControls_.togglePlayStateWillPlay()) {
166 this.style.backgroundImage = imagePlay;
167 } else {
168 this.style.backgroundImage = imagePause;
169 }
170 };
171 button.updateDisplayType();
172 return button;
173 }
174
175 function createTimeline(mediaControls) {
176 var timeline = createElement('input', '-webkit-media-controls-timeline') ;
177 timeline.mediaControls_ = mediaControls;
178 timeline.setAttribute('type', 'range');
179 timeline.setAttribute('step', 'any');
180 timeline.onmousedown = function(e) {
181 if (e.button != 0) {
182 return;
183 }
184 this.mediaControls_.beginScrubbing();
185 this.mediaControls_.updateCurrentTimeDisplay();
186 };
187 timeline.onmouseup = function(e) {
188 if (e.button != 0) {
189 return;
190 }
191 this.mediaControls_.endScrubbing();
192 this.mediaControls_.updateCurrentTimeDisplay();
193 };
194 timeline.oninput = function(e) {
195 e.preventDefault();
196 this.mediaControls_.setCurrentTime(this.value);
197 this.mediaControls_.updateCurrentTimeDisplay();
198 };
199 timeline.setPosition = function(currentTime) {
200 this.value = currentTime;
201 };
202 timeline.setDuration = function(duration) {
203 this.setAttribute('max', isFinite(duration) ? duration : 0);
204 };
205 return timeline;
206 }
207
208 function createCurrentTimeDisplay() {
209 var display = createElement('div', '-webkit-media-controls-current-time- display');;
210 return display;
211 }
212
213 function createTimeRemainingDisplay() {
214 var display = createElement('div', '-webkit-media-controls-time-remainin g-display');;
215 return display;
216 }
217
218 function createMuteButton(mediaControls) {
219 var imageSoundLevel3 = 'url(\'' + mediaControls.getResourceDataURL('medi aplayerSoundLevel3') + '\')';
220 var imageSoundLevel2 = 'url(\'' + mediaControls.getResourceDataURL('medi aplayerSoundLevel2') + '\')';
221 var imageSoundLevel1 = 'url(\'' + mediaControls.getResourceDataURL('medi aplayerSoundLevel1') + '\')';
222 var imageSoundLevel0 = 'url(\'' + mediaControls.getResourceDataURL('medi aplayerSoundLevel0') + '\')';
223 var imageSoundDisabled = 'url(\'' + mediaControls.getResourceDataURL('me diaplayerSoundDisabled') + '\')';
224
225 var button = createElement('input', '-webkit-media-controls-mute-button' );
226 button.mediaControls_ = mediaControls;
227 button.setAttribute('type', 'button');
228 button.style.backgroundSize = '100%';
229 button.onclick = function(e) {
230 this.mediaControls_.toggleMuted();
231 e.preventDefault();
232 };
233 button.updateDisplayType = function() {
234 if (!this.mediaControls_.hasSource() || !this.mediaControls_.hasAudi o()) {
235 this.style.backgroundImage = imageSoundDisabled;
236 return;
237 }
238 if (this.mediaControls_.isMuted() || this.mediaControls_.volume() <= 0) {
239 this.style.backgroundImage = imageSoundLevel0;
240 return;
241 }
242 if (this.mediaControls_.volume() <= 0.33) {
243 this.style.backgroundImage = imageSoundLevel1;
244 return;
245 }
246 if (this.mediaControls_.volume() <= 0.66) {
247 this.style.backgroundImage = imageSoundLevel2;
248 return;
249 }
250 this.style.backgroundImage = imageSoundLevel3;
251 };
252 button.updateDisplayType();
253 return button
254 }
255
256 function createVolumeSlider(mediaControls) {
257 var slider = createElement('input', '-webkit-media-controls-volume-slide r');
258 slider.mediaControls_ = mediaControls;
259 slider.setAttribute('type', 'range');
260 slider.setAttribute('step', 'any');
261 slider.setAttribute('max', '1');
262 var defaultEventHandler = function(e) {
263 if (e.button !== undefined && e.button !== 0) {
264 return;
265 }
266 this.mediaControls_.setVolume(this.value);
267 this.mediaControls_.setMuted(false);
268 };
269 slider.oninput = defaultEventHandler;
270 slider.onmouseup = defaultEventHandler;
271 slider.onmousedown = defaultEventHandler;
272 return slider;
273 }
274
275 function createToggleClosedCaptionsButton(mediaControls) {
276 var imageClosedCaption = 'url(\'' + mediaControls.getResourceDataURL('me diaplayerClosedCaption') + '\')';
277 var imageClosedCaptionDisabled = 'url(\'' + mediaControls.getResourceDat aURL('mediaplayerClosedCaptionDisabled') + '\')';
278
279 var button = createElement('input', '-webkit-media-controls-toggle-close d-captions-button');
280 button.mediaControls_ = mediaControls;
281 button.setAttribute('type', 'button');
282 hide(button);
283 button.updateDisplayType = function() {
284 var captionsVisible = this.mediaControls_.isClosedCaptionsVisible();
285 if (captionsVisible) {
286 this.style.backgroundImage = imageClosedCaption;
287 } else {
288 this.style.backgroundImage = imageClosedCaptionDisabled;
289 }
290 this.checked = captionsVisible;
291 };
292 button.onclick = function(e) {
293 this.mediaControls_.toggleClosedCaptionsVisible();
294 this.checked = this.mediaControls_.isClosedCaptionsVisible();
295 this.updateDisplayType();
296 e.preventDefault();
297 };
298 button.updateDisplayType();
299 return button;
300 }
301
302 function createFullscreenButton(mediaControls) {
303 var button = createElement('input', '-webkit-media-controls-fullscreen-b utton');
304 button.mediaControls_ = mediaControls;
305 button.setAttribute('type', 'button');
306 hide(button);
307 button.onclick = function(e) {
308 this.mediaControls_.toggleFullscreen();
309 e.preventDefault();
310 };
311 button.setIsFullscreen = function(isFullscreen) {
312 // This function will be needed for AXObject.
313 };
314 return button;
315 }
316
317 function createTextTrackContainer(mediaControls) {
318 var container = createElement('div', '-webkit-media-text-track-container ');
319 container.updateDisplay = function() {
320 this.mediaControls_.updateTextTrackContainerDisplay(this);
321 if (this.hasChildNodes()) {
322 show(this);
323 } else {
324 hide(this);
325 }
326 };
327 container.updateSizes = function() {
328 this.style.fontSize = this.mediaControls_.getTextTrackContainerFontS ize() + 'px';
329 };
330 container.updateDisplay();
331 return container
332 }
333
334 function mouseOverEventHandler(e) {
335 if (!this.containsRelatedTarget_(e)) {
336 this.isMouseOverControls_ = true;
337 if (!this.togglePlayStateWillPlay()) {
338 this.makeOpaque_();
339 if (this.shouldHideMediaControls_()) {
340 this.startHideMediaControlsTimer_();
341 }
342 }
343 }
344 }
345
346 function mouseOutEventHandler(e) {
347 if (!this.containsRelatedTarget_(e)) {
348 this.isMouseOverControls_ = false;
349 this.stopHideMediaControlsTimer_();
350 }
351 }
352
353 function mouseMoveEventHandler(e) {
354 this.makeOpaque_();
355 if (this.shouldHideMediaControls_(kIgnoreVideoHover)) {
356 this.startHideMediaControlsTimer_();
357 }
358 }
359
360 MediaControlsPrototype.createdCallback = function(mediaElement) {
361 this.mediaElement_ = mediaElement;
362 this.textDisplayContainer_ = null;
363 this.hideMediaControlsTimer_ = null;
364 this.isMouseOverControls_ = false;
365 this.isPausedForScrubbing_ = false;
366
367 this.setAttribute('pseudo', '-webkit-media-controls');
368
369 if (this.isOverlayPlayButtonEnabled()) {
370 this.overlayEnclosure_ = createElement('div', '-webkit-media-control s-overlay-enclosure');
371 this.overlayPlayButton_ = createOverlayPlayButton(this);
372 this.overlayEnclosure_.appendChild(this.overlayPlayButton_);
373 this.appendChild(this.overlayEnclosure_);
374 }
375
376 this.enclosure_ = createElement('div', '-webkit-media-controls-enclosure ');
377 this.panel_ = createPanel();
378
379 this.playButton_ = createPlayButton(this);
380 this.panel_.appendChild(this.playButton_);
381 this.timeline_ = createTimeline(this);
382 this.panel_.appendChild(this.timeline_);
383 this.currentTimeDisplay_ = createCurrentTimeDisplay();
384 this.panel_.appendChild(this.currentTimeDisplay_);
385 hide(this.currentTimeDisplay_);
386 this.durationDisplay_ = createTimeRemainingDisplay();
387 this.panel_.appendChild(this.durationDisplay_);
388 this.muteButton_ = createMuteButton(this);
389 this.panel_.appendChild(this.muteButton_);
390 this.volumeSlider_ = createVolumeSlider(this);
391 this.panel_.appendChild(this.volumeSlider_);
392 this.toggleClosedCaptionsButton_ = createToggleClosedCaptionsButton(this );
393 this.panel_.appendChild(this.toggleClosedCaptionsButton_);
394 this.fullscreenButton_ = createFullscreenButton(this);
395 this.panel_.appendChild(this.fullscreenButton_);
396
397 this.enclosure_.appendChild(this.panel_);
398 this.appendChild(this.enclosure_);
399
400 this.onmouseover = mouseOverEventHandler;
401 this.onmouseout = mouseOutEventHandler;
402 this.onmousemove = mouseMoveEventHandler;
403 };
404
405 MediaControlsPrototype.hasSource = function() {
406 return this.mediaElement_.networkState != HTMLMediaElement.NETWORK_EMPTY && this.mediaElement_.networkState != HTMLMediaElement.NETWORK_NO_SOURCE;
407 }
408
409 MediaControlsPrototype.reset = function() {
410 var duration = this.mediaElement_.duration;
411 this.durationDisplay_.innerText = formatMediaControlsTime(duration, dura tion);
412 // FIXME: this will be needed for AccessibilityMediaTimeDisplay::stringV alue
413 // this.durationDisplay_.setCurrentValue(duration);
414 this.updatePlayState_();
415 this.updateCurrentTimeDisplay();
416 this.timeline_.setDuration(duration);
417 this.timeline_.setPosition(this.mediaElement_.currentTime);
418 if (this.hasAudio()) {
419 show(this.volumeSlider_);
420 } else {
421 hide(this.volumeSlider_);
422 }
423 this.updateVolume();
424 this.refreshClosedCaptionsButtonVisibility();
425 if (this.hasVideo() && this.fullscreenIsSupported()) {
426 show(this.fullscreenButton_);
427 } else {
428 hide(this.fullscreenButton_);
429 }
430 };
431
432 MediaControlsPrototype.show = function() {
433 this.makeOpaque_();
434 this.panel_.setIsDisplayed(true);
435 show(this.panel_);
436 if (this.overlayPlayButton_) {
437 this.overlayPlayButton_.updateDisplayType();
438 }
439 };
440
441 MediaControlsPrototype.mediaElementFocused = function() {
442 show(this);
443 this.stopHideMediaControlsTimer_();
444 };
445
446 MediaControlsPrototype.hide = function() {
447 this.panel_.setIsDisplayed(false);
448 hide(this.panel_);
449 if (this.overlayPlayButton_) {
450 hide(this.overlayPlayButton_);
451 }
452 };
453
454 MediaControlsPrototype.makeOpaque_ = function() {
455 this.panel_.makeOpaque();
456 };
457
458 MediaControlsPrototype.makeTransparent_ = function() {
459 this.panel_.makeTransparent();
460 };
461
462 MediaControlsPrototype.shouldHideMediaControls_ = function(behaviorFlags) {
463 if (this.hasVideo()) {
464 return false;
465 }
466 var ignoreVideoHover = behaviorFlags & kIgnoreVideoHover;
467 // FIXME: Implement hovered()
468 if (this.panel_.hovered() || (!ignoreVideoHover && this.isMouseOverContr ols)) {
469 return false;
470 }
471 var ignoreFocus = behaviroFlags & kIgnoreFocus;
472 // FIXME: Implement contains(document().focusedElement())
473 if (!ignoreFocus || (this.mediaElement_.focused() || false)) {
474 return false;
475 }
476 return true;
477 };
478
479 MediaControlsPrototype.playbackStarted = function() {
480 show(this.currentTimeDisplay_);
481 hide(this.durationDisplay_);
482 this.updatePlayState_();
483 this.timeline_.setPosition(this.mediaElement_.currentTime);
484 this.updateCurrentTimeDisplay();
485 this.startHideMediaControlsTimer_();
486 };
487
488 MediaControlsPrototype.playbackProgressed = function() {
489 this.timeline_.setPosition(this.mediaElement_.currentTime);
490 this.updateCurrentTimeDisplay();
491 if (this.shouldHideMediaControls_()) {
492 this.makeTransparent_();
493 }
494 };
495
496 MediaControlsPrototype.playbackStopped = function() {
497 this.updatePlayState_();
498 this.timeline_.setPosition(this.mediaElement_.currentTime);
499 this.updateCurrentTimeDisplay();
500 this.makeOpaque_();
501 this.stopHideMediaControlsTimer_();
502 };
503
504 MediaControlsPrototype.updatePlayState_ = function() {
505 if (this.isPausedForScrubbing_) {
506 return;
507 }
508 if (this.overlayPlayButton_) {
509 this.overlayPlayButton_.updateDisplayType();
510 }
511 this.playButton_.updateDisplayType();
512 };
513
514 MediaControlsPrototype.beginScrubbing = function() {
515 if (!this.togglePlayStateWillPlay()) {
516 this.isPausedForScrubbing_ = true;
517 this.togglePlayState();
518 }
519 };
520
521 MediaControlsPrototype.endScrubbing = function() {
522 if (this.isPausedForScrubbing_) {
523 this.isPausedForScrubbing_ = false;
524 if (this.togglePlayStateWillPlay()) {
525 this.togglePlayState();
526 }
527 }
528 };
529
530 MediaControlsPrototype.updateCurrentTimeDisplay = function() {
531 var now = this.mediaElement_.currentTime;
532 var duration = this.mediaElement_.duration;
533 if (now > 0) {
534 show(this.currentTimeDisplay_);
535 hide(this.durationDisplay_);
536 }
537 this.currentTimeDisplay_.innerText = formatMediaControlsTime(now, durati on);
538 // FIXME: this will be needed for AccessibilityMediaTimeDisplay::stringV alue
539 //this.currentTimeDisplay.setCurrentValue(now);
540 };
541
542 MediaControlsPrototype.updateVolume = function() {
543 this.muteButton_.updateDisplayType();
544 if (this.mediaElement_.muted) {
545 this.volumeSlider_.value = 0;
546 } else {
547 this.volumeSlider_.value = this.mediaElement_.volume;
548 }
549 };
550
551 MediaControlsPrototype.changedClosedCaptionsVisibility = function() {
552 // FIXME
553 //this.toggleClosedCaptionsButton_.updateDisplayType();
554 };
555
556 MediaControlsPrototype.refreshClosedCaptionsButtonVisibility = function() {
557 if (this.hasClosedCaptions()) {
558 show(this.toggleClosedCaptionsButton_);
559 } else {
560 hide(this.toggleClosedCaptionsButton_);
561 }
562 };
563
564 MediaControlsPrototype.closedCaptionTracksChanged = function() {
565 this.refreshClosedCaptionsButtonVisibility();
566 };
567
568 MediaControlsPrototype.enteredFullscreen = function() {
569 this.fullscreenButton_.setIsFullscreen(true);
570 this.stopHideMediaControlsTimer_();
571 this.startHideMediaControlsTimer_();
572 };
573
574 MediaControlsPrototype.exitedFullscreen = function() {
575 this.fullscreenButton_.setIsFullscreen(false);
576 this.stopHideMediaControlsTimer_();
577 this.startHideMediaControlsTimer_();
578 };
579
580 MediaControlsPrototype.hideMediaControlsTimerFired_ = function(timer) {
581 if (this.togglePlayStateWillPlay()) {
582 return;
583 }
584 if (!this.shouldHideMediaControls_(kIgnoreFocus | kIgnoreVideoHover)) {
585 return;
586 }
587 this.makeTransparent_();
588 };
589
590 MediaControlsPrototype.startHideMediaControlsTimer_ = function() {
591 // FIXME
592 // this.hideMediaControlsTimer_.startOneShot(timeWithoutMouseMovementBef oreHidingMediaControls, FROM_HERE);
593 };
594
595 MediaControlsPrototype.stopHideMediaControlsTimer_ = function() {
596 // FIXME
597 // this.hideMediaControlsTimer_.stop();
598 };
599
600 MediaControlsPrototype.containsRelatedTarget_ = function(e) {
601 if (!(e instanceof MouseEvent)) {
602 return false;
603 }
604 var relatedTarget = e.relatedTarget;
605 if (!relatedTarget) {
606 return false;
607 }
608 return this.contains(relatedTarget);
609 };
610
611 MediaControlsPrototype.createTextTrackDisplay_ = function() {
612 if (this.textDisplayContainer_) {
613 return;
614 }
615
616 this.textDisplayContainer_ = createTextTrackContainerElement();
617 if (this.overlayEnclosure_ && this.overlayPlayButton_) {
618 this.overlayEnclosure_.insertBefore(this.textDisplayContainer_, this .overlayPlayButton_);
619 } else {
620 this.insertBefore_(this.textDisplayContainer_, this.enclosure_);
621 }
622 };
623
624 MediaControlsPrototype.showTextTarckDisplay_ = function() {
625 if (!this.textDisplayContainer_) {
626 this.createTextTrackDisplay_();
627 }
628 this.textDisplayContainer_.show();
629 };
630
631 MediaControlsPrototype.hideTextTrackDisplay_ = function() {
632 if (!this.textDisplayContainer_) {
633 this.createTextTrackDisplay_();
634 }
635 this.textDisplayContainer_.hide();
636 };
637
638 MediaControlsPrototype.updateTextTrackDisplay = function() {
639 if (!this.textDisplayContainer_) {
640 this.createTextTrackDisplay_();
641 }
642 this.textDisplayContainer_.updateDisplay();
643 };
644
645 MediaControlsPrototype.toggleMuted = function() {
646 this.mediaElement_.muted = !this.mediaElement_.muted;
647 };
648
649 MediaControlsPrototype.isMuted = function() {
650 return this.mediaElement_.muted;
651 };
652
653 MediaControlsPrototype.setMuted = function(muted) {
654 this.mediaElement_.muted = muted;
655 };
656
657 MediaControlsPrototype.volume = function() {
658 return this.mediaElement_.volume;
659 };
660
661 MediaControlsPrototype.setVolume = function(volume) {
662 this.mediaElement_.volume = volume;
663 };
664
665 MediaControlsPrototype.width = function() {
666 return this.mediaElement_.width;
667 };
668
669 MediaControlsPrototype.height = function() {
670 return this.mediaElement_.height;
671 };
672 });
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698