[Modern Media Controls] Turn modern media controls on by default
[WebKit-https.git] / Source / WebCore / Modules / mediacontrols / mediaControlsGtk.js
1 function createControls(root, video, host)
2 {
3     return new ControllerGtk(root, video, host);
4 };
5
6 function ControllerGtk(root, video, host)
7 {
8     Controller.call(this, root, video, host);
9 };
10
11 function contains(list, obj)
12 {
13     var i = list.length;
14     while (i--)
15         if (list[i] === obj)
16             return true;
17     return false;
18 };
19
20 ControllerGtk.prototype = {
21
22     createControls: function()
23     {
24         Controller.prototype.createControls.apply(this);
25
26         this.controls.currentTime.classList.add(this.ClassNames.hidden);
27         this.controls.remainingTime.classList.add(this.ClassNames.hidden);
28
29         this.controls.volumeBox.classList.add(this.ClassNames.hiding);
30
31         this.listenFor(this.controls.muteBox, 'mouseout', this.handleVolumeBoxMouseOut);
32         this.listenFor(this.controls.muteButton, 'mouseover', this.handleMuteButtonMouseOver);
33         this.listenFor(this.controls.volumeBox, 'mouseover', this.handleMuteButtonMouseOver);
34         this.listenFor(this.controls.volume, 'mouseover', this.handleMuteButtonMouseOver);
35         this.listenFor(this.controls.captionButton, 'mouseover', this.handleCaptionButtonMouseOver);
36         this.listenFor(this.controls.captionButton, 'mouseout', this.handleCaptionButtonMouseOut);
37
38         var enclosure = this.controls.enclosure = document.createElement('div');
39         enclosure.setAttribute('pseudo', '-webkit-media-controls-enclosure');
40     },
41
42     configureInlineControls: function()
43     {
44         this.controls.panel.appendChild(this.controls.playButton);
45         this.controls.panel.appendChild(this.controls.timeline);
46         this.controls.panel.appendChild(this.controls.currentTime);
47         this.controls.panel.appendChild(this.controls.remainingTime);
48         this.controls.panel.appendChild(this.controls.captionButton);
49         this.controls.panel.appendChild(this.controls.fullscreenButton);
50         this.controls.panel.appendChild(this.controls.muteBox);
51         this.controls.muteBox.appendChild(this.controls.muteButton);
52         this.controls.muteBox.appendChild(this.controls.volumeBox);
53         this.controls.volumeBox.appendChild(this.controls.volume);
54         this.controls.enclosure.appendChild(this.controls.panel);
55     },
56
57     shouldHaveControls: function()
58     {
59         return this.video.controls || this.isFullScreen();
60     },
61
62     reconnectControls: function()
63     {
64         Controller.prototype.disconnectControls.apply(this, arguments);
65
66         this.configureInlineControls();
67
68         if (this.shouldHaveControls())
69             this.addControls();
70     },
71
72     setStatusHidden: function(hidden)
73     {
74     },
75
76     updateTime: function(forceUpdate)
77     {
78         if (!forceUpdate && this.controlsAreHidden())
79             return;
80
81         var currentTime = this.video.currentTime;
82         var duration = this.video.duration;
83
84         this.controls.currentTime.innerText = this.formatTime(currentTime);
85         this.controls.timeline.value = currentTime;
86         if (duration === Infinity || duration === NaN)
87             this.controls.remainingTime.classList.add(this.ClassNames.hidden);
88         else {
89             this.controls.currentTime.innerText += " / " + this.formatTime(duration);
90             this.controls.remainingTime.innerText = this.formatTime(duration);
91             if (this.controls.currentTime.classList.contains(this.ClassNames.hidden))
92                 this.controls.remainingTime.classList.remove(this.ClassNames.hidden);
93         }
94
95         if (currentTime > 0)
96             this.showCurrentTime();
97     },
98
99     showCurrentTime: function()
100     {
101         this.controls.currentTime.classList.remove(this.ClassNames.hidden);
102         this.controls.remainingTime.classList.add(this.ClassNames.hidden);
103     },
104
105     handlePlay: function(event)
106     {
107         Controller.prototype.handlePlay.apply(this, arguments);
108         this.showCurrentTime();
109         if (!this.isLive)
110             this.showCurrentTime();
111     },
112
113     handleTimeUpdate: function(event)
114     {
115         this.updateTime();
116     },
117
118     handleMuteButtonMouseOver: function(event)
119     {
120         if (this.video.offsetTop + this.controls.enclosure.offsetTop < 105) {
121             this.controls.volumeBox.classList.add(this.ClassNames.down);
122             this.controls.panel.classList.add(this.ClassNames.down);
123         } else {
124             this.controls.volumeBox.classList.remove(this.ClassNames.down);
125             this.controls.panel.classList.remove(this.ClassNames.down);
126         }
127         this.controls.volumeBox.classList.remove(this.ClassNames.hiding);
128         return true;
129     },
130
131     handleVolumeBoxMouseOut: function(event)
132     {
133         this.controls.volumeBox.classList.add(this.ClassNames.hiding);
134         return true;
135     },
136
137     removeControls: function()
138     {
139         if (this.controls.enclosure.parentNode)
140             this.controls.enclosure.parentNode.removeChild(this.controls.enclosure);
141         this.destroyCaptionMenu();
142     },
143
144     addControls: function()
145     {
146         this.base.appendChild(this.controls.enclosure);
147     },
148
149     updateReadyState: function()
150     {
151         if (this.host.supportsFullscreen && this.video.videoTracks.length)
152             this.controls.fullscreenButton.classList.remove(this.ClassNames.hidden);
153         else
154             this.controls.fullscreenButton.classList.add(this.ClassNames.hidden);
155         this.updateVolume();
156     },
157
158     updateDuration: function()
159     {
160         Controller.prototype.updateDuration.apply(this, arguments);
161         if (this.isLive)
162             this.controls.timeline.max = 0;
163     },
164
165     setIsLive: function(live)
166     {
167         Controller.prototype.setIsLive.apply(this, arguments);
168         this.controls.timeline.disabled = this.isLive;
169     },
170
171     updatePlaying: function()
172     {
173         Controller.prototype.updatePlaying.apply(this, arguments);
174         if (!this.canPlay())
175             this.showControls();
176     },
177
178     handleCaptionButtonClicked: function(event)
179     {
180         this.handleCaptionButtonShowMenu(event)
181         return true;
182     },
183
184     buildCaptionMenu: function()
185     {
186         Controller.prototype.buildCaptionMenu.apply(this, arguments);
187
188         this.listenFor(this.captionMenu, 'mouseout', this.handleCaptionMouseOut);
189         this.listenFor(this.captionMenu, 'transitionend', this.captionMenuTransitionEnd);
190
191         this.captionMenu.captionMenuTreeElements = this.captionMenu.getElementsByTagName("*");
192
193         // Caption menu has to be centered to the caption button.
194         var captionButtonCenter =  this.controls.panel.offsetLeft + this.controls.captionButton.offsetLeft +
195             this.controls.captionButton.offsetWidth / 2;
196         var captionMenuLeft = (captionButtonCenter - this.captionMenu.offsetWidth / 2);
197         if (captionMenuLeft + this.captionMenu.offsetWidth > this.controls.panel.offsetLeft + this.controls.panel.offsetWidth)
198             this.captionMenu.classList.add(this.ClassNames.out);
199         this.captionMenu.style.left = captionMenuLeft + 'px';
200         // As height is not in the css, it needs to be specified to animate it.
201         this.captionMenu.height = this.captionMenu.offsetHeight;
202         this.captionMenu.style.height = 0;
203     },
204
205     destroyCaptionMenu: function()
206     {
207         this.hideCaptionMenu();
208     },
209
210     showCaptionMenu: function()
211     {
212         this.captionMenu.style.height = this.captionMenu.height + 'px';
213     },
214
215     hideCaptionMenu: function()
216     {
217         this.captionMenu.style.height = 0;
218     },
219
220     captionMenuTransitionEnd: function(event)
221     {
222         if (this.captionMenu.offsetHeight === 0)
223             Controller.prototype.destroyCaptionMenu.apply(this, arguments);
224     },
225
226     handleCaptionButtonMouseOver: function(event)
227     {
228         this.handleCaptionButtonShowMenu(event);
229         return true;
230     },
231
232     handleCaptionButtonShowMenu: function(event)
233     {
234         if (!this.captionMenu)
235             this.buildCaptionMenu();
236         if (!contains(this.captionMenu.captionMenuTreeElements, event.relatedTarget))
237             this.showCaptionMenu();
238         return true;
239     },
240
241     handleCaptionButtonMouseOut: function(event)
242     {
243         if (this.captionMenu && !contains(this.captionMenu.captionMenuTreeElements, event.relatedTarget))
244             this.hideCaptionMenu();
245         return true;
246     },
247
248     handleCaptionMouseOut: function(event)
249     {
250         if (event.relatedTarget != this.controls.captionButton &&
251             !contains(this.captionMenu.captionMenuTreeElements, event.relatedTarget))
252             this.hideCaptionMenu();
253         return true;
254     },
255 };
256
257 Object.create(Controller.prototype).extend(ControllerGtk.prototype);
258 Object.defineProperty(ControllerGtk.prototype, 'constructor', { enumerable:false, value:ControllerGtk });