1 // set the dismissNativeWarn flag:
2 _global
['dismissNativeWarn'] = false;
5 * Msg text is inherited from embedVideo (we should move it here (although can't load ctrlBuilder without parent EmbedVideo obj)
9 * base ctrlBuilder object
10 * @param the embedVideo element we are targeting
12 var ctrlBuilder = function( embedObj
) {
13 return this.init( embedObj
);
17 * controlsBuilder prototype:
19 ctrlBuilder
.prototype = {
20 init:function( embedObj
, opt
) {
22 this.embedObj
= embedObj
;
24 // check for skin overrides for ctrlBuilder
25 if ( _global
[ embedObj
.skin_name
+ 'Config'] ) {
26 // clone as to not override prototype:
27 var _this
= $j
.extend( true, { }, this, _global
[ embedObj
.skin_name
+ 'Config'] );
35 // default volume layout is "vertical"
36 volume_layout
: 'vertical',
42 getControls:function() {
43 // set up local pointer to the embedObj
44 var embedObj
= this.embedObj
;
45 // set up loadl ctrlBuilder ref
48 js_log( 'f:controlsBuilder:: opt:' + this.options
);
49 this.id
= ( embedObj
.pc
) ? embedObj
.pc
.pp
.id
:embedObj
.id
;
50 this.available_width
= embedObj
.playerPixelWidth();
52 // Make pointer to the embedObj
53 this.embedObj
= embedObj
;
55 for ( var i
in embedObj
.supports
) {
56 _this
.supports
[i
] = embedObj
.supports
[i
];
60 if ( ( embedObj
.roe
||
61 embedObj
.wikiTitleKey
||
62 ( embedObj
.media_element
.timedTextSources
&&
63 embedObj
.media_element
.timedTextSources() )
64 ) && embedObj
.show_meta_link
)
65 this.supports
['closed_captions'] = true;
68 // Append options to body (if not already there)
69 if ( _this
.body_options
&& $j( '#mv_vid_options_' + this.id
).length
== 0 )
70 $j( 'body' ).append( this.components
['mv_embedded_options'].o( this ) );
73 for ( var i
in this.components
) {
74 if ( this.supports
[i
] ) {
75 if ( this.available_width
> this.components
[i
].w
) {
76 // Special case with playhead don't add unless we have 60px
77 if ( i
== 'play_head' && this.available_width
< 60 )
79 o
+= this.components
[i
].o( this );
80 this.available_width
-= this.components
[i
].w
;
82 js_log( 'not enough space for control component:' + i
);
90 * to be run once controls are attached to the dom
92 addControlHooks:function( $tp
) {
93 // Set up local pointer to the embedObj
94 var embedObj
= this.embedObj
;
98 $tp
= $j( '#' + embedObj
.id
);
102 $tp
.find( '.play-btn,.play-btn-large' ).unbind().btnBind().click( function() {
106 // Add recommend firefox if we have non-native playback:
107 if ( embedObj
.doNativeWarningCheck() ) {
108 $j( '#dc_' + embedObj
.id
).hover(
110 if ( $j( '#gnp_' + embedObj
.id
).length
== 0 ) {
111 var toppos
= ( embedObj
.instanceOf
== 'mvPlayList' ) ? 25:10;
112 $j( this ).append( '<div id="gnp_' + embedObj
.id
+ '" class="ui-state-highlight ui-corner-all" ' +
113 'style="position:absolute;display:none;background:#FFF;top:' + toppos
+ 'px;left:10px;right:10px;">' +
114 gM( 'mwe-for_best_experience' ) +
115 '<br><input id="ffwarn_' + embedObj
.id
+ '" type=\"checkbox\">' +
116 gM( 'mwe-do_not_warn_again' ) +
118 $j( '#ffwarn_' + embedObj
.id
).click( function() {
119 if ( $j( this ).is( ':checked' ) ) {
120 // set up a cookie for 7 days:
121 $j
.cookie( 'dismissNativeWarn', true, { expires
: 7 } );
122 // set the current instance
123 _global
['dismissNativeWarn'] = true;
124 $j( '#gnp_' + embedObj
.id
).fadeOut( 'slow' );
126 _global
['adismissNativeWarn'] = false;
127 $j
.cookie( 'dismissNativeWarn', false );
132 if ( ( $j
.cookie( 'dismissNativeWarn' ) !== true ) &&
133 _global
['dismissNativeWarn'] === false ) {
134 $j( '#gnp_' + embedObj
.id
).fadeIn( 'slow' );
138 $j( '#gnp_' + embedObj
.id
).fadeOut( 'slow' );
143 if ( $j
.browser
.msie
&& $j
.browser
.version
<= 6 ) {
144 $j( embedObj
.id
+ ' .play-btn-large' ).pngFix();
149 $tp
.find( '.timed-text' ).unbind().btnBind().click( function() {
150 embedObj
.showTextInterface();
154 $tp
.find( '.options-btn' ).unbind().btnBind().click( function() {
155 embedObj
.doOptionsHTML();
158 // Fullscreen binding:
159 $tp
.find( '.fullscreen-btn' ).unbind().btnBind().click( function() {
160 embedObj
.fullscreen();
163 js_log( " should add slider binding: " + $tp
.find( '.play_head' ).length
);
164 $tp
.find( '.play_head' ).slider( {
169 start: function( event
, ui
) {
170 var id
= ( embedObj
.pc
!= null ) ? embedObj
.pc
.pp
.id
:embedObj
.id
;
171 embedObj
.userSlide
= true;
172 $j( id
+ ' .play-btn-large' ).fadeOut( 'fast' );
173 // If playlist always start at 0
174 embedObj
.start_time_sec
= ( embedObj
.instanceOf
== 'mvPlayList' ) ? 0:
175 npt2seconds( embedObj
.getTimeReq().split( '/' )[0] );
177 slide: function( event
, ui
) {
178 var perc
= ui
.value
/ 1000;
179 embedObj
.jump_time
= seconds2npt( parseFloat( parseFloat( embedObj
.getDuration() ) * perc
) + embedObj
.start_time_sec
);
180 // js_log('perc:' + perc + ' * ' + embedObj.getDuration() + ' jt:'+ this.jump_time);
181 if ( _this
.long_time_disp
) {
182 embedObj
.setStatus( gM( 'mwe-seek_to', embedObj
.jump_time
) );
184 embedObj
.setStatus( embedObj
.jump_time
);
186 // Update the thumbnail / frame
187 if ( embedObj
.isPlaying
== false ) {
188 embedObj
.updateThumbPerc( perc
);
191 change:function( event
, ui
) {
192 // only run the onChange event if done by a user slide
193 // (otherwise it runs times it should not)
194 if ( embedObj
.userSlide
) {
195 embedObj
.userSlide
= false;
196 embedObj
.seeking
= true;
197 // stop the monitor timer (if we can)
198 if ( embedObj
.stopMonitor
)
199 embedObj
.stopMonitor();
201 var perc
= ui
.value
/ 1000;
202 // set seek time (in case we have to do a url seek)
203 embedObj
.seek_time_sec
= npt2seconds( embedObj
.jump_time
, true );
204 js_log( 'do jump to: ' + embedObj
.jump_time
+ ' perc:' + perc
+ ' sts:' + embedObj
.seek_time_sec
);
205 embedObj
.setStatus( gM( 'mwe-seeking' ) );
206 embedObj
.doSeek( perc
);
210 // Up the z-index of the default status indicator:
211 $tp
.find( '.play_head .ui-slider-handle' ).css( 'z-index', 4 );
212 $tp
.find( '.play_head .ui-slider-range' ).addClass( 'ui-corner-all' ).css( 'z-index', 2 );
214 // Extended class list for jQuery ui themeing
215 //(we can probably refactor this with custom buffering highlighter)
216 $tp
.find( '.play_head' ).append( this.getBufferHtml() );
218 $opt
= $j( '#mv_vid_options_' + embedObj
.id
);
219 // videoOptions ... @@todo should be merged with something more like kskin.js:
220 $opt
.find( '.vo_selection' ).click( function() {
221 embedObj
.displayHTML();
222 embedObj
.showPlayerselect( $tp
.find( '.videoOptionsComplete' ) );
226 $opt
.find( '.vo_download' ).click( function() {
227 embedObj
.displayHTML();
228 embedObj
.showDownload( $tp
.find( '.videoOptionsComplete' ) );
232 $opt
.find( '.vo_showcode' ).click( function() {
233 embedObj
.displayHTML();
234 embedObj
.showShare( $tp
.find( '.videoOptionsComplete' ) );
238 this.doVolumeBinding();
240 // Check if we have any custom skin Bindings to run
241 if ( this.addSkinControlBindings
&& typeof( this.addSkinControlBindings
) == 'function' )
242 this.addSkinControlBindings();
244 doVolumeBinding:function() {
245 var embedObj
= this.embedObj
;
247 var $tp
= $j( '#' + embedObj
.id
);
248 $tp
.find( '.volume_control' ).unbind().btnBind().click( function() {
249 js_log( 'clicked volume control' );
250 $j( '#' + embedObj
.id
).get( 0 ).toggleMute();
253 // Add vertical volume display hover
254 if ( this.volume_layout
== 'vertical' ) {
255 // default volume binding:
256 var hoverOverDelay
= false;
257 var $tpvol
= $tp
.find( '.vol_container' );
258 $tp
.find( '.volume_control' ).hover(
260 $tpvol
.addClass( 'vol_container_top' );
261 // set to "below" if playing and embedType != native
262 if ( embedObj
&& embedObj
.isPlaying
&& embedObj
.isPlaying() && !embedObj
.supports
['overlays'] ) {
263 $tpvol
.removeClass( 'vol_container_top' ).addClass( 'vol_container_below' );
265 $tpvol
.fadeIn( 'fast' );
266 hoverOverDelay
= true;
269 hoverOverDelay
= false;
270 setTimeout( function doHideVolume() {
271 if ( !hoverOverDelay
) {
272 $tpvol
.fadeOut( 'fast' );
279 // Setup play-head slider:
285 slide: function( event
, ui
) {
286 var perc
= ui
.value
/ 100;
287 // js_log('update volume:' + perc);
288 embedObj
.updateVolumen( perc
);
290 change:function( event
, ui
) {
291 var perc
= ui
.value
/ 100;
293 $tp
.find( '.volume_control span' ).removeClass( 'ui-icon-volume-on' ).addClass( 'ui-icon-volume-off' );
295 $tp
.find( '.volume_control span' ).removeClass( 'ui-icon-volume-off' ).addClass( 'ui-icon-volume-on' );
297 var perc
= ui
.value
/ 100;
298 embedObj
.updateVolumen( perc
);
302 if ( this.volume_layout
== 'vertical' )
303 sliderConf
['orientation'] = "vertical";
305 $tp
.find( '.volume-slider' ).slider( sliderConf
);
308 * Gets the Buffer Html that overlays the playhead
310 getBufferHtml:function() {
311 return '<div class="ui-slider-range ui-slider-range-min ui-widget-header ' +
312 'ui-state-highlight ui-corner-all ' +
313 'mv_buffer" style="width:0px;height:100%;z-index:1;top:0px" />';
315 getComponent:function( component
) {
316 if ( this.components
[ component
] ) {
317 return this.components
[ component
].o( this );
323 * components take in the embedObj and return some html for the given component.
324 * components can be overwritten by skin javascript
329 'o':function( ctrlObj
) {
336 'o':function( ctrlObj
) {
337 // get dynamic position for big play button (@@todo maybe use margin:auto ? )
338 return $j( '<div/>' ).attr( {
339 'title' : gM( 'mwe-play_clip' ),
340 'class' : "ui-state-default play-btn-large"
343 'left' : ( ( ctrlObj
.embedObj
.playerPixelWidth() - this.w
) / 2 ),
344 'top' : ( ( ctrlObj
.embedObj
.playerPixelHeight() - this.h
) / 2 )
346 .wrap( '<div/>' ).parent().html();
349 'mv_embedded_options': {
351 'o':function( ctrlObj
) {
352 var o
= '<div id="mv_vid_options_' + ctrlObj
.id
+ '" class="videoOptions">' +
353 '<div class="videoOptionsTop"></div>' +
354 '<div class="videoOptionsBox">' +
355 '<div class="block">' +
356 '<h6>Video Options</h6>' +
358 '<div class="block">' +
359 '<p class="short_match vo_selection"><a href="#"><span>' + gM( 'mwe-chose_player' ) + '</span></a></p>' +
360 '<p class="short_match vo_download"><a href="#"><span>' + gM( 'mwe-download' ) + '</span></a></p>' +
361 '<p class="short_match vo_showcode"><a href="#"><span>' + gM( 'mwe-share' ) + '</span></a></p>';
363 // link to the stream page if we are not already there:
364 if ( ( ctrlObj
.embedObj
.roe
|| ctrlObj
.embedObj
.linkback
) && typeof mv_stream_interface
== 'undefined' )
365 o
+= '<p class="short_match"><a href="javascript:$j(\'#' + ctrlObj
.id
+ '\').get(0).doLinkBack()"><span><strong>Source Page</strong></span></a></p>';
368 '</div><!--videoOptionsInner-->' +
369 '<div class="videoOptionsBot"></div>' +
370 '</div><!--videoOptions-->';
376 'o':function( ctrlObj
) {
377 return '<div title="' + gM( 'mwe-player_fullscreen' ) + '" class="ui-state-default ui-corner-all ui-icon_link rButton fullscreen-btn">' +
378 '<span class="ui-icon ui-icon-arrow-4-diag"></span>' +
384 'o':function( ctrlObj
) {
385 return '<div title="' + gM( 'mwe-player_options' ) + '" class="ui-state-default ui-corner-all ui-icon_link rButton options-btn">' +
386 '<span class="ui-icon ui-icon-wrench"></span>' +
392 'o':function( ctrlObj
) {
393 return '<div title="' + gM( 'mwe-play_clip' ) + '" class="ui-state-default ui-corner-all ui-icon_link lButton play-btn">' +
394 '<span class="ui-icon ui-icon-play"/>' +
400 'o':function( ctrlObj
) {
401 return '<div title="' + gM( 'mwe-closed_captions' ) + '" class="ui-state-default ui-corner-all ui-icon_link rButton timed-text">' +
402 '<span class="ui-icon ui-icon-comment"></span>' +
408 'o':function( ctrlObj
) {
410 if ( ctrlObj
.volume_layout
== 'horizontal' )
411 o
+= '<div class="ui-slider ui-slider-horizontal rButton volume-slider"></div>';
413 o
+= '<div title="' + gM( 'mwe-volume_control' ) + '" class="ui-state-default ui-corner-all ui-icon_link rButton volume_control">' +
414 '<span class="ui-icon ui-icon-volume-on"></span>';
416 if ( ctrlObj
.volume_layout
== 'vertical' ) {
417 o
+= '<div style="position:absolute;display:none;left:0px;" class="vol_container ui-corner-all">' +
418 '<div class="volume-slider" ></div>' +
427 'o':function( ctrlObj
) {
428 return '<div class="ui-widget time-disp">' + ctrlObj
.embedObj
.getTimeReq() + '</div>';
432 'w':0, // special case (takes up remaining space)
433 'o':function( ctrlObj
) {
434 return '<div class="play_head" style="width: ' + ( ctrlObj
.available_width
- 34 ) + 'px;"></div>';