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