* some sequence fixes
[lhc/web/wiklou.git] / js2 / mwEmbed / skins / ctrlBuilder.js
1 //set the dismissNativeWarn flag:
2 _global['dismissNativeWarn'] = false;
3
4 var ctrlBuilder = {
5 height:29,
6 supports:{
7 'options':true,
8 'borders':true
9 },
10 menu_items:[
11 'playerselect',
12 'download',
13 'share',
14 'credits',
15 ],
16 default_menu_item:'download',
17 getControls:function( embedObj ){
18 js_log('f:controlsBuilder:: opt:');
19 this.id = (embedObj.pc)?embedObj.pc.pp.id:embedObj.id;
20 this.available_width = embedObj.playerPixelWidth();
21 //make pointer to the embedObj
22 this.embedObj = embedObj;
23 var _this = this;
24 for(var i in embedObj.supports){
25 _this.supports[i] = embedObj.supports[i];
26 };
27
28 //check for close_captions tracks:
29 if( ( embedObj.roe || embedObj.timedTextSources() )
30 && embedObj.show_meta_link )
31 this.supports['closed_captions']=true;
32
33 var o='';
34 //get the length of the play_head
35 this.player_head_length = embedObj.playerPixelWidth();
36 for( var i in this.components ){
37 if( this.supports[i] ){
38 if( i != 'play_head'){
39 this.player_head_length -= this.components[i].w;
40 }
41 }
42 }
43 for(var i in this.components){
44 if( this.supports[i] ){
45 if( this.available_width > this.components[i].w ){
46 //special case with playhead don't add unless we have 60px
47 if( i == 'play_head' && this.player_head_length < 60 )
48 continue;
49 o+=this.components[i].o();
50 this.available_width -= this.components[i].w;
51 }else{
52 js_log('not enough space for control component:' + i);
53 }
54 }
55 }
56 return o;
57 },
58 /*
59 * addControlHooks
60 * to be run once controls are attached to the dom
61 */
62 addControlHooks:function( embedObj ){
63 //add in drag/seek hooks:
64 if(!embedObj.base_seeker_slider_offset && $j('#mv_seeker_slider_'+embedObj.id).get(0))
65 embedObj.base_seeker_slider_offset = $j('#mv_seeker_slider_'+embedObj.id).get(0).offsetLeft;
66
67 //js_log('looking for: #mv_seeker_slider_'+embedObj.id + "\n " +
68 // 'start sec: '+embedObj.start_time_sec + ' base offset: '+embedObj.base_seeker_slider_offset);
69
70 var $tp=$j('#' + embedObj.id);
71
72 //@todo: which object is being play()'d (or whatever) ?
73 //We select the element to attach the event to this way:
74 //$tp.find('.ui-icon-play').parent().click(function(){alert(0)}); or we can give the button itself a class - probably better.
75
76 //add play hook for play-btn and large_play_button
77 $tp.find('.play-btn,.play-btn-large').unbind().btnBind().click(function(){
78 $j('#' + embedObj.id).get(0).play();
79 })
80 //add recomend firefox if non-native playback:
81 if( embedObj.doNativeWarningCheck() ){
82 $j('#dc_'+ embedObj.id).hover(
83 function(){
84 if($j('#gnp_' + embedObj.id).length==0){
85 $j(this).append('<div id="gnp_' + embedObj.id + '" class="ui-state-highlight ui-corner-all" ' +
86 'style="position:absolute;display:none;background:#FFF;top:10px;left:10px;right:10px;height:60px;">' +
87 gM('mv_for_best_experience') +
88 '<br><input id="ffwarn_'+embedObj.id+'" type=\"checkbox\">' +
89 gM('mv_do_not_warn_again') +
90 '</div>');
91 $j('#ffwarn_'+embedObj.id).click(function(){
92 if( $j(this).is(':checked') ){
93 //set up a cookie for 5 days:
94 $j.cookie('dismissNativeWarn', true, { expires: 5 });
95 //set the current instance
96 _global['dismissNativeWarn'] = true;
97 $j('#gnp_' + embedObj.id).fadeOut('slow');
98 }else{
99 _global['adismissNativeWarn'] = false;
100 $j.cookie('dismissNativeWarn', false);
101 }
102
103 });
104 }
105 if( ($j.cookie('dismissNativeWarn') !== true) &&
106 _global['dismissNativeWarn'] === false ){
107 $j('#gnp_' + embedObj.id).fadeIn('slow');
108 }
109 },
110 function(){
111 $j('#gnp_' + embedObj.id).fadeOut('slow');
112 }
113 );
114 }
115
116 if( $j.browser.msie && $j.browser.version <= 6){
117 $j('#big_play_link_' + embedObj.id).pngFix();
118 }
119
120 //captions binding:
121 $j('#timed_text_' + embedObj.id).unbind().btnBind().click(function(){
122 $j('#' + embedObj.id).get(0).showTextInterface();
123 });
124
125 //options binding:
126 $j('#options_button_' + embedObj.id).unbind().btnBind().click(function(){
127 $j('#' +embedObj.id).get(0).doOptionsHTML();
128 });
129
130 //fullscreen binding:
131 $j('#fullscreen_' + embedObj.id).unbind().btnBind().click(function(){
132 $j('#' +embedObj.id).get(0).fullscreen();
133 });
134
135 js_log(" should add slider binding: " + $j('#mv_play_head_'+embedObj.id).length) ;
136 // $j('#mv_play_head_'+embedObj.id).slider({
137 $tp.find( '.j-scrubber' ).slider({
138 range: "min",
139 value: 0,
140 min: 0,
141 max: 1000,
142 start: function(event, ui){
143 var id = (embedObj.pc!=null)?embedObj.pc.pp.id:embedObj.id;
144 embedObj.userSlide=true;
145 $j('#big_play_link_'+id).fadeOut('fast');
146 //if playlist always start at 0
147 embedObj.start_time_sec = (embedObj.instanceOf == 'mvPlayList')?0:
148 npt2seconds(embedObj.getTimeReq().split('/')[0]);
149 },
150 slide: function(event, ui) {
151 var perc = ui.value/1000;
152 embedObj.jump_time = seconds2npt( parseFloat( parseFloat(embedObj.getDuration()) * perc ) + embedObj.start_time_sec);
153 //js_log('perc:' + perc + ' * ' + embedObj.getDuration() + ' jt:'+ this.jump_time);
154 embedObj.setStatus( gM('seek_to')+' '+embedObj.jump_time );
155 //update the thumbnail / frame
156 if(embedObj.isPlaying==false){
157 embedObj.updateThumbPerc( perc );
158 }
159 },
160 change:function(event, ui){
161 //only run the onChange event if done by a user slide:
162 if(embedObj.userSlide){
163 embedObj.userSlide=false;
164 embedObj.seeking=true;
165 //stop the monitor timer (if we can)
166 if(embedObj.stopMonitor)
167 embedObj.stopMonitor();
168
169 var perc = ui.value/1000;
170 //set seek time (in case we have to do a url seek)
171 embedObj.seek_time_sec = npt2seconds( embedObj.jump_time, true );
172 js_log('do jump to: '+embedObj.jump_time + ' perc:' +perc + ' sts:' + embedObj.seek_time_sec);
173 embedObj.doSeek(perc);
174 }
175 }
176 });
177 //@todo: identify problem with volume button jumping...
178 $tp.find('.k-volume-slider').slider({
179 range: "min",
180 value: 80,
181 min: 0,
182 max: 100,
183 slide: function(event, ui) {
184 embedObj.updateVolumen(ui.value/100);
185 },
186 change: function(event, ui){
187 var level = ui.value/100;
188 if (level==0) {
189 $tp.find('.k-volume span').addClass('ui-icon-volume-off');
190 }else{
191 $tp.find('.k-volume span').removeClass('ui-icon-volume-off');
192 }
193 //only run the onChange event if done by a user slide:
194 if(embedObj.userSlide){
195 embedObj.userSlide=false;
196 embedObj.seeking=true;
197 // var perc = ui.value/100;
198 embedObj.updateVolumen(level);
199 }
200 }
201 });
202 //up the z-index of the default status indicator:
203 // $j('#mv_play_head_'+embedObj.id + ' .ui-slider-handle').css('z-index', 4);
204 // $j('#mv_play_head_'+embedObj.id + ' .ui-slider-range').addClass('ui-corner-all').css('z-index', 2);
205 //extended class list for jQuery ui themeing (we can probably refactor this with custom buffering highliter)
206 $j('#' + embedObj.id + ' .j-scrubber').prepend( ctrlBuilder.getMvBufferHtml() );
207
208
209 //adds options and bindings: (we do this onClick for faster vidoe tag startup times)
210 var addMvOptions = function(){
211 if($j('#' + embedObj.id + ' .k-menu').length != 0 )
212 return false;
213
214 $j('#' + embedObj.id).prepend( ctrlBuilder.components['mv_embedded_options'].o( embedObj ) );
215
216 //by default its hidden:
217 $tp.find('.k-menu').hide();
218
219 //output menu-items:
220 for(i=0; i < ctrlBuilder.menu_items.length ; i++){
221 $tp.find('.k-' + ctrlBuilder.menu_items[i] + '-btn').click(function(){
222 var mk = $j(this).attr('rel');
223 $target = $j('#' + embedObj.id + ' .menu-'+mk).hide();
224 //gennerate the menu html not already done:
225 if( $target.children().length == 0 ){
226 //call the function show{Menuitem} with target:
227 embedObj['show' + mk.charAt(0).toUpperCase() + mk.substring(1)](
228 $j('#' + embedObj.id + ' .menu-'+mk)
229 );
230 }
231 //slide out the others
232 $j('#' + embedObj.id + ' .menu-screen').hide();
233 $target.fadeIn("fast");
234 //don't follow the # link
235 return false;
236 });
237 }
238 }
239
240 //options menu display:
241 $tp.find('.k-options').click(function(){
242 if($j('#' + embedObj.id + ' .k-menu').length == 0 )
243 addMvOptions();
244 //set up the text and menu:
245 var $ktxt = $j(this).find('.ui-icon-k-menu');
246 var $kmenu = $tp.find('.k-menu');
247 if( $kmenu.is(':visible') ){
248 $kmenu.fadeOut("fast",function(){
249 $ktxt.html ( gM('menu_btn') );
250 });
251 $tp.find('.play-btn-large').fadeIn('fast');
252 }else{
253 $kmenu.fadeIn("fast", function(){
254 $ktxt.html ( gM('close_btn') );
255 });
256 $tp.find('.play-btn-large').fadeOut('fast');
257 }
258 });
259
260 //volume binding:
261 $tp.find('.k-volume').unbind().btnBind().click(function(){
262 $tp.toggleMute();
263 });
264
265 var hoverOverDelay=false;
266 /*$j('#volume_control_'+embedObj.id).unbind().btnBind().click(function(){
267 $j('#' +embedObj.id).get(0).toggleMute();
268 });
269 .hover(
270 function(){
271 $j('#vol_container_' + embedObj.id).addClass('vol_container_top');
272 //set to "below" if playing and embedType != native
273 if(embedObj && embedObj.isPlaying() && !embedObj.supports['overlays']){
274 $j('#vol_container_' + embedObj.id).removeClass('vol_container_top').addClass('vol_container_below');
275 }
276
277 $j('#vol_container_' + embedObj.id).fadeIn('fast');
278 hoverOverDelay = true;
279 },
280 function(){
281 hoverOverDelay= false;
282 setTimeout(function doHideVolume(){
283 if(!hoverOverDelay){
284 $j('#vol_container_' + embedObj.id).fadeOut('fast');
285 }
286 }, 500);
287 }
288 );
289 //Volumen Slider
290 $j('#volume_bar_'+embedObj.id).slider({
291 orientation: "vertical",
292 range: "min",
293 value: 80,
294 min: 0,
295 max: 100,
296 slide: function(event, ui) {
297 var perc = ui.value/100;
298 //js_log('update volume:' + perc);
299 embedObj.updateVolumen(perc);
300 },
301 change:function(event, ui){
302 var perc = ui.value/100;
303 if (perc==0) {
304 $j('#volume_control_'+embedObj.id + ' span').removeClass('ui-icon-volume-on').addClass('ui-icon-volume-off');
305 }else{
306 $j('#volume_control_'+embedObj.id + ' span').removeClass('ui-icon-volume-off').addClass('ui-icon-volume-on');
307 }
308 //only run the onChange event if done by a user slide:
309 if(embedObj.userSlide){
310 embedObj.userSlide=false;
311 embedObj.seeking=true;
312 var perc = ui.value/100;
313 embedObj.updateVolumen(perc);
314 }
315 }
316 });*/
317
318 },
319 getMvBufferHtml:function(){
320 return '<div class="ui-slider-horizontal ui-corner-all ui-slider-buffer" />';
321 },
322 components:{
323 'borders':{
324 'w':8,
325 'o':function(){
326 return '';
327 }
328 },
329 'mv_embedded_options':{
330 'w':0,
331 'o':function( embedObj ){
332 var o= '' +
333 '<div class="k-menu ui-widget-content" ' +
334 'style="width:' + embedObj.playerPixelWidth() + 'px; height:' + embedObj.playerPixelHeight() + 'px;">' +
335 '<ul class="k-menu-bar">';
336 //output menu item containers:
337 for(i=0; i < ctrlBuilder.menu_items.length; i++){
338 var mk = ctrlBuilder.menu_items[i];
339 o+= '<li class="k-' + mk + '-btn" rel="' + mk + '">' +
340 '<a href="#" title="' + gM( mk ) +'">' + gM( mk ) +'</a></li>';
341 }
342 o+='</ul>' +
343 //we have to substract the width of the k-menu-bar
344 '<div class="k-menu-screens" style="width:' + ( embedObj.playerPixelWidth() -75) +
345 'px; height:' + (embedObj.playerPixelHeight() - ctrlBuilder.height) + 'px;">';
346
347 //output menu item containers:
348 for(i=0; i < ctrlBuilder.menu_items.length; i++){
349 o+= '<div class="menu-screen menu-' + ctrlBuilder.menu_items[i] + '"></div>';
350 }
351 '</div>' +
352 '</div>';
353 return o;
354 }
355 },
356 'pause':{
357 'w':28, //28 147
358 'o':function(){
359 return '<button class="play-btn ui-state-default ui-corner-all" title="' +
360 gM('play_clip') + '" ><span class="ui-icon ui-icon-play"></span></button>'
361 }
362 },
363 'play_head':{ // scrubber
364 'w':0, //special case (takes up remaining space)
365 'o':function(){
366 return '<div class="ui-slider ui-slider-horizontal ui-corner-all j-scrubber"' +
367 ' style="width:' + ( ctrlBuilder.player_head_length - 30 ) + 'px;"></div>'
368 }
369 },
370 'time_display':{
371 'w':36,
372 'o':function(){
373 return '<div class="k-timer">' + seconds2npt ( ctrlBuilder.embedObj.getDuration() ) + '</div>';
374 }
375 },
376 'volume_control':{
377 'w':40,
378 'o':function(){
379 return '<button class="ui-state-default ui-corner-all k-volume">' +
380 '<span class="ui-icon ui-icon-volume-on"></span>' +
381 '</button>' +
382 '<div class="ui-slider ui-slider-horizontal k-volume-slider"></div>';
383
384 //vertical volume control:
385 /* return '<div title="' + gM('volume_control') + '" id="volume_control_'+ctrlBuilder.id+'" class="ui-state-default ui-corner-all ui-icon_link rButton">' +
386 '<span class="ui-icon ui-icon-volume-on"></span>' +
387 '<div style="position:absolute;display:none;" id="vol_container_'+ctrlBuilder.id+'" class="vol_container ui-corner-all">' +
388 '<div class="volume_bar" id="volume_bar_' + ctrlBuilder.id + '"></div>' +
389 '</div>'+
390 '</div>';
391 */
392 }
393 },
394 'closed_captions':{
395 'w':24,
396 'o':function(){
397 return '<div title="' + gM('closed_captions') + '" id="timed_text_' + ctrlBuilder.id +'" ' +
398 'class="ui-state-default ui-corner-all ui-icon_link rButton">' +
399 '<span class="ui-icon ui-icon-comment"></span></div>';
400 }
401 },
402 'fullscreen':{
403 'w':24,
404 'o':function(){
405 return '<button class="ui-state-default ui-corner-all k-fullscreen" title="' + gM('player_fullscreen') + '">' +
406 '<span class="ui-icon ui-icon-arrow-4-diag"></span></button>'
407 }
408 },
409 'options':{
410 'w':50,
411 'o':function(){
412 return '<button class="ui-state-default ui-corner-bl k-options" title="'+ gM('player_options') + '" >' +
413 '<span class="ui-icon ui-icon-k-menu">'+ gM('menu_btn') + '</span>'
414 '</button>'
415 }
416 }
417 }
418 }