1/** 2 * 3 * MediaSPIP player 4 * 5 * Player html5 pour les balises <audio> et <video> 6 * avec fallback vers version flash pour flv/mp4/mp3/aac 7 * 8 * $version : 1.3.3 9 * © GNU/GPL v3 - kent1 (http://kent1.info - [email protected]) 10 * cf : http://www.mediaspip.net/technical-documentation/plugins-used-by-mediaspip/html5-player-video-sound-media/ 11 * 12 * Remplace les controles des lecteurs html5 par défaut des navigateurs 13 * Remplace la balise <video> par un lecteur flash si on ne peut jouer le media : 14 * - sur Firefox si seulement la version mp4 ou flv est disponible et pas de version ogv ou ogg 15 * - sur Safari si seulement la version flv disponible et pas la mp4 16 * - sur IE dans tous les cas 17 * 18 * Plugins jQuery compatibles et utilisés: 19 * - jQuery UI slider : http://jqueryui.com/slider/ (pour que les barres de progressions et de volume soient des sliders) 20 * - jQuery cookies : https://github.com/carhartl/jquery-cookie (Pour l'option qui garde en mémoire le niveau de volume) 21 * - jQuery mousewheel : https://github.com/brandonaaron/jquery-mousewheel (Diminue et augmente le volume lors d'un mousewheel sur le lecteur) 22 * 23 * Options : 24 * - autoplay boolean true/false : lit automatiquement la video ou le son (défaut : false) 25 * - autoload boolean true/false : précharge automatiquement la video ou le son (défaut : true) 26 * - minwidth int : La largeur minimale 27 * - movieSize string 'adapt' uniquement pour l'instant : 28 * - "adapt" fais prendre la largeur du bloc parent à la vidéo 29 * - cookie_volume boolean true/false : met dans un cookie ms_volume le niveau de volume 30 * et dans html_volume_muted la valeur 'muted' si on a désactivé le son 31 * play / pause / autres changements d'état... (defaut : true) 32 * - volume int : un int représentant un pourcentage de volume 33 * - volume_bloque boolean : bloquer le niveau de volume 34 * - volume_slider_orientation vertical|horizontal : permet de définir l'orientation du slider de volume (défaut vertical) 35 * - muted boolean : true si muted à l'initialisation, false sinon 36 * - muted_bloque boolean : true pour rendre impossible le changement de mute 37 * - boutons_caches array : un tableau des boutons à ne pas afficher ['fullscreen','volume','loop','time_remaining','time_elapsed','play_pause','progress_bar'] 38 * - messages bool : si false, n'affiche pas les messages au dessus du player lors d'actions utilisateur 39 */ 40 41(function($) { 42 43 /** 44 * Vérifier si on a accès à l'API fullscreen de html5 45 * http://johndyer.name/native-fullscreen-javascript-api-plus-jquery-plugin/ 46 */ 47 var fullScreenApi = { 48 supportsFullScreen: false, 49 isFullScreen: function() { return false; }, 50 requestFullScreen: function() {}, 51 cancelFullScreen: function() {}, 52 fullScreenEventName: '', 53 prefix: '' 54 },browserPrefixes = 'webkit moz o ms khtml'.split(' '); 55 56 if (typeof document.cancelFullScreen != 'undefined') { 57 // check for native support 58 fullScreenApi.supportsFullScreen = true; 59 } else { 60 // check for fullscreen support by vendor prefix 61 for (var i = 0, il = browserPrefixes.length; i < il; i++ ) { 62 fullScreenApi.prefix = browserPrefixes[i]; 63 if (typeof document[fullScreenApi.prefix + 'CancelFullScreen' ] != 'undefined' ) { 64 fullScreenApi.supportsFullScreen = true; 65 break; 66 } 67 } 68 } 69 // update methods to do something useful 70 if (fullScreenApi.supportsFullScreen) { 71 fullScreenApi.fullScreenEventName = fullScreenApi.prefix + 'fullscreenchange'; 72 fullScreenApi.isFullScreen = function() { 73 switch (this.prefix) { 74 case '': 75 return document.fullScreen; 76 case 'webkit': 77 return document.webkitIsFullScreen; 78 default: 79 return document[this.prefix + 'FullScreen']; 80 } 81 }; 82 fullScreenApi.requestFullScreen = function(el) { 83 return (this.prefix === '') ? el.requestFullScreen() : el[this.prefix + 'RequestFullScreen'](); 84 }; 85 fullScreenApi.cancelFullScreen = function(el) { 86 return (this.prefix === '') ? document.cancelFullScreen() : document[this.prefix + 'CancelFullScreen'](); 87 }; 88 } 89 90 window.fullScreenApi = fullScreenApi; 91 92 var slider = (typeof($.ui) == 'object') && (typeof($.ui.slider) == 'function'), 93 cookies = (typeof($.cookie) == 'function'), 94 stop_message_timeout = false, 95 error_message = false, 96 UA = navigator.userAgent, 97 IS_IE = /MSIE/.test(UA), 98 IS_IPAD = /iPad|MeeGo/.test(UA), 99 IS_IPHONE = /iP(hone|od)/i.test(UA), 100 IS_ANDROID = /Android/.test(UA), 101 IS_MOBILE = IS_IPAD || IS_ANDROID || IS_IPHONE; 102 103 /** 104 * Fonction d'initialisation du lecteur sur une balise <audio> ou <video> 105 * 106 * Exemple d'appel : 107 * $('video').ms_player_init(); 108 */ 109 $.extend($.fn, { 110 ms_player_init : function(options){ 111 /** 112 * Si c'est iTruc, cela ne fonctionne pas => on sort direct et on laisse la balise html5 faire ce qu'elle peut 113 */ 114 if(IS_IPHONE || IS_ANDROID){ return;} 115 116 var defaults = { 117 autoplay:false, // Lire automatiquement au chargement 118 autoload:true, // Précharger automatiquement au chargement 119 minwidth:null, // Largeur minimale 120 movieSize:'adapt', 121 ratio:null, 122 volume:100, // Niveau de volume au chargement 123 volume_bloque:false, // bloque le niveau de volume 124 volume_slider_orientation:'horizontal', // Si on a les sliders, orientation du slider de volume 125 volume_mousewheel:true, 126 muted:false, // Le lecteur n'est pas mute par défaut 127 muted_bloque:false, // On autorise le switch mute/unmute sur le lecteur 128 cookie_volume:false, // Garder le niveau de volume de l'utilisateur dans un cookie 129 messages:true, // Affiche ou non les messages sur le lecteur 130 boutons_caches:[] 131 }; 132 133 options = $.extend(defaults, options); 134 135 var media = $(this), id = media[0], playable = false;
136 137 if(media.is(':hidden')) media.show(); 138 if(media.is('audio')) options.movieSize = null; 139 140 /** 141 * Test si le navigateur dispose du support des balises <video> ou <audio> 142 */ 143 if(typeof(id) != "undefined" && typeof(id.canPlayType) != "undefined"){ 144 id.isFullScreen = id.has_html5_cover = false; 145 id.options = options; 146 147 media.children('source').each(function(){ 148 if(!$(this).attr('type').match('flv') && id.canPlayType($(this).attr('type')) !== ''){ 149 if(($(this).attr('type').match('video/ogg') || $(this).attr('type').match('video/webm')) && /Safari/i.test(navigator.userAgent) && !/Chrome/i.test(navigator.userAgent)){ 150 playable = false; 151 }else{ 152 playable = true; 153 return false; 154 } 155 } 156 }); 157 /** 158 * Si le navigateur ne peut pas : 159 * - Utiliser correctement les balises <audio> et <video> 160 * - Jouer une des sources disponibles 161 * 162 * On essaie de faire un fallback en flash (mp3/flv/mp4/aac) 163 */ 164 if(!playable && (typeof($.fn.ms_test_fallback) == 'function')) 165 media.ms_test_fallback(options); 166 else{ 167 var wrapper = false, 168 control = false, 169 controls = false, 170 class_wrapper = '', 171 styles = ' style="', 172 style = true, 173 bloc_messages = '', 174 height = options.height, 175 width = options.width; 176 177 id.mediacanplay = id.isFullScreen = id.slider_control = id.slider_volume = id.has_metadas = id.has_to_play = false; 178 id.percent_loaded = 0; 179 id.messages = options.messages; 180 id.type = (media.is('video')) ? 'video' : 'audio'; 181 182 if(slider) id.slider = true; 183 184 if(typeof(media.attr('loop')) == 'string'){ 185 class_wrapper += 'loop'; 186 id.loop = true; 187 } 188 else id.loop = false; 189 190 if(typeof(media.attr('muted')) == 'string') id.muted = true; 191 192 if(!width){ 193 if(media.attr('width')) width = media.attr('width'); 194 else if(media.width() > 0) width = media.width(); 195 } 196 197 if(!height){ 198 if(media.attr('height')) height = media.attr('height'); 199 else if(media.height() > 0) height = media.height(); 200 } 201 202 if(id.controls) id.addcontrols = true; 203 id.controls = false; 204 class_wrapper += ' loading no_metadata'; 205 206 if(media.prev().is('img')) 207 media.prev().wrap('<div class="html5_cover"></div>'); 208 209 if(id.addcontrols){ 210 media.wrap('<div class="media_wrapper '+id.type+' '+class_wrapper+'"></div>'); 211 if(media.parents('.media_wrapper').prev().is('.html5_cover')){ 212 var cover_html = media.parents('.media_wrapper').prev().html(); 213 media.parents('.media_wrapper').prepend(cover_html); 214 media.parents('.media_wrapper').find('img').click(function(){ 215 media.ms_play_pause(); 216 }); 217 media.parents('.media_wrapper').prev().detach(); 218 if(media.parents('.media_wrapper').height() > 200) 219 id.has_html5_cover = true; 220 } 221 if(id.type == 'video' || id.has_html5_cover) 222 controls = '<div class="ms_splash"></div><div class="ms-waiting"><em> </em><em> </em><em> </em></div>'; 223 else 224 controls = ''; 225 226 controls += '<div class="controls small">'; 227 if($.inArray('play_pause',options.boutons_caches) == '-1') 228 controls += '<div class="buttons_left">' 229 +'<span class="play_pause_button" title="'+ms_player_lang.bouton_loading+'"></span>' 230 +'</div>'; 231 232 if($.inArray('progress_bar',options.boutons_caches) == '-1'){ 233 controls += '<div class="progress_bar">'; 234 controls += ($.inArray('time_elapsed',options.boutons_caches) == '-1') ? '<em class="elapsed_time" title="'+ms_player_lang.info_ecoule+'"></em>' : ''; 235 controls += '<div class="progress_back">' 236 +'<div class="progress_loading_wrapper">' 237 +'<div class="progress_loading_stripes"></div>' 238 +'</div>' 239 +'<div class="progress_buffered"></div>' 240 +'<div class="progress_elapsed_time"></div>' 241 +'<span class="progress_indicator"></span>' 242 +'</div>'; 243 controls += ($.inArray('time_remaining',options.boutons_caches) == '-1') ? '<em class="remaining_time remaining" title="'+ms_player_lang.info_restant+'"></em>' : ''; 244 controls += '</div>'; 245 } 246 247 controls += '<div class="buttons_right">'; 248 controls += ($.inArray('volume',options.boutons_caches) == '-1') ? '<span class="volume_button '+ (id.muted ? 'muted' : '') +'" title="'+ms_player_lang.bouton_volume+' ('+Math.floor(id.volume*100)+'%)"></span>' : ''; 249 250 /** 251 * Si on a les sliders, on ajoute une div ici pour avoir un slider de volume 252 */ 253 controls += (slider && $.inArray('volume',options.boutons_caches) == '-1') ? '<span class="volume_slider_container '+options.volume_slider_orientation+'"><span class="volume_slider"></span></span>' : ''; 254 controls += (media.is('video') && $.inArray('fullscreen',o
254ptions.boutons_caches) == '-1') ? '<span class="fullwindow_button" title="'+ms_player_lang.bouton_fullscreen+'"></span>' : ''; 255 controls += ($.inArray('loop',options.boutons_caches) == '-1') ? '<span class="loop_button" title="'+ms_player_lang.bouton_loop+'"></span>' : ''; 256 controls +='</div>'; 257 wrapper = media.parent(); 258 wrapper.append(controls); 259 control = wrapper.find('.controls'); 260 } 261 262 if(id.type == 'video'){ 263 if(options.height) 264 media.parent().height(height); 265 if(options.width && options.width != '100%') 266 media.parent().width(width); 267 else if(options.width && options.width != '100%') 268 media.parent().css({width:'auto'}).removeAttr('width'); 269 else if(options.width && options.width == '100%') 270 id.options.movieSize = options.movieSize = 'adapt'; 271 }else 272 media.parent().width(width); 273 274 if(!wrapper) wrapper = media.parent(); 275 276 if(id.type == 'video' && !height){ 277 height = media.parents('.media_wrapper').find('.controls').height(); 278 media.parents('.media_wrapper').height(height); 279 } 280 281 if(wrapper){ 282 if(options.minwidth && media.width() > options.minwidth) wrapper.width(options.minwidth); 283 284 if(wrapper.height() < 100) options.messages = false; 285 286 if(id.addcontrols && options.messages){ 287 bloc_messages = '<div class="messages" style="display:none"></div>'; 288 wrapper.append(bloc_messages); 289 } 290 } 291 292 if(control){ 293 var elapsed_time = control.find('.elapsed_time'), 294 remaining_time = control.find('.remaining_time'), 295 progress_indicator = control.find('.progress_indicator'), 296 progress_elapse = control.find('.progress_elapsed_time'); 297 media.ms_resize_controls(); 298 } 299 300 //if(!IS_IPAD){ 301 media.bind("loadedmetadata",function(e){ 302 id.has_metadatas = true; 303 media.ms_start('loadedmetadata'); 304 if(wrapper) wrapper.removeClass('no_metadata').removeClass('loading').addClass('has_metadata'); 305 if(id.has_to_play) media.ms_buttons(); 306 /** 307 * Cas d'un stream audio (Radio) 308 */ 309 if(id.duration == 'Infinity'){ 310 id.isstream = true; 311 control.find('.progress_back').detach(); 312 remaining_time.addClass('total_time').attr('title','').html(ms_player_lang.info_streaming); 313 } 314 media.ms_resize_controls(); 315 }).bind("error", function(e){ 316 if (id.error) { 317 switch (id.error.code) { 318 case 1: 319 error_message = ms_player_lang.statut_error_stopped; 320 break; 321 case 2: 322 error_message = ms_player_lang.statut_error_network; 323 break; 324 case 3: 325 error_message = ms_player_lang.statut_error_broken; 326 break; 327 case 4: 328 error_message = ms_player_lang.statut_error; 329 break; 330 default: 331 error_message = ms_player_lang.statut_error; 332 break; 333 } 334 if(options.messages && error_message) media.ms_messages('error',error_message); 335 wrapper.removeClass('loading').addClass('player_error').find('.play_pause_button').attr('title',ms_player_lang.info_erreur); 336 } 337 }).bind("timeupdate", function(e){ 338 if(id.addcontrols){ 339 if(id.percent_loaded != 100) media.ms_update_loaded(e); 340 341 var percent_time = ms_anything_to_percent(id.currentTime,id.duration); 342 if(remaining_time.is('.remaining') && (id.duration != 'Infinity')) 343 remaining_time.text('-'+ms_second_to_time(id.duration - id.currentTime)); 344 345 elapsed_time.text(ms_second_to_time(id.currentTime));
346 if(slider && (typeof(id.slider_control) == 'object')){ 347 progress_elapse.css('width',percent_time+'%'); 348 id.slider_control.slider("value", percent_time); 349 }else 350 progress_indicator.css('left',percent_time+'%'); 351 352 media.ms_resize_controls(); 353 } 354 }).bind("seeking",function(e){ 355 if(id.addcontrols) wrapper.addClass('seeking').find('.play_pause_button').attr('title',ms_player_lang.bouton_seeking); 356 }).bind("seeked",function(e){ 357 if(id.addcontrols){ 358 wrapper.removeClass('seeking'); 359 if(id.paused) 360 wrapper.find('.play_pause_button').removeClass('pause').attr('title',ms_player_lang.bouton_pause); 361 else 362 wrapper.find('.play_pause_button').addClass('pause').attr('title',ms_player_lang.bouton_lire); 363 } 364 }).bind("progress", function(e){ 365 if(id.addcontrols && id.percent_loaded != 100) media.ms_update_loaded(e); 366 }).bind("pause", function(e){ 367 if(id.addcontrols) media.ms_buttons(); 368 }).bind("play", function(e){ 369 if(id.preload == 'none') id.preload = false;// Fix pour chromium 370 if(id.addcontrols){ 371 if(id.percent_loaded != 100) media.ms_update_loaded(e); 372 media.ms_buttons(); 373 } 374 }).bind("ended", function(e){ 375 if(id.addcontrols){ 376 if(!id.loop){ 377 wrapper.addClass('ended').find('.play_pause_button').removeClass('pause').attr('title',ms_player_lang.bouton_lire); 378 id.paused = true; 379 }else{ 380 id.currentTime = 0; 381 id.play(); 382 } 383 } 384 }).bind("loadeddata", function(e){ 385 if(id.addcontrols) media.ms_update_loaded(e); 386 }).bind("volumechange", function(e){ 387 media.ms_volume(false); 388 }).click(function(){ 389 if(id.addcontrols) media.ms_play_pause(); 390 }).dblclick(function(e){ 391 if(id.addcontrols) media.ms_fullscreen(); 392 e.preventDefault(); 393 e.stopPropagation(); 394 }); 395 396 document.addEventListener(fullScreenApi.fullScreenEventName, function(e){ 397 if(id.isFullScreen && !fullScreenApi.isFullScreen()) 398 media.ms_fullscreen(); 399 media.ms_resize_controls(); 400 }, true); 401 402 media.parent().find('.ms_splash').click(function(){ 403 if((id.paused || id.ended) && $(this).is(':visible')){ 404 wrapper.removeClass('paused').removeClass('ended'); 405 if(!id.has_metadatas) 406 wrapper.addClass('loading'); 407 media.ms_play_pause(); 408 } 409 }); 410 411 if(wrapper){ 412 var stop_timeout = false, 413 last_moved=0, 414 clientx = 0, 415 clienty = 0; 416 wrapper.mousemove(function(e){ 417 if(id.isFullScreen && !id.paused){ 418 if ((e.timeStamp - last_moved > 1000) && ((e.clientX != clientx) || (e.clientY != clienty))) { 419 wrapper.addClass('hover'); 420 clearTimeout(stop_timeout); 421 var full_onmousestop = function() { wrapper.removeClass('hover'); }; 422 stop_timeout = setTimeout(full_onmousestop, 1500); 423 last_moved = e.timeStamp; 424 clientx = e.clientX; 425 clienty = e.clientY; 426 } 427 } 428 }); 429 } 430 431 /** 432 * Les actions sur les éléments des controles : 433 * 434 * - Le switch Play/Pause sur le click du bouton adéquat 435 * - Seek lors d'un click sur la barre de progression 436 * - Le switch Mute/Unmute sur le click du bouton de volume 437 * - Le switch fullscreen/normal screen sur le bouton adéquat 438 */ 439 if(id.addcontrols){ 440 control.find('.play_pause_button').click(function(){ 441 media.ms_play_pause(); 442 }); 443 444 control.find('.progress_back').click(function(e){ 445 if(!slider) 446 media.ms_seek_to(e.clientX,slider); 447 }); 448 449 if($.inArray('volume',options.boutons_caches) == '-1' && !options.muted_bloque){ 450 control.find('.volume_button').click(function(e){ 451 media.ms_volume(true); 452 }); 453 } 454 455 if($.inArray('fullscreen',options.boutons_caches) == '-1'){ 456 control.find('.fullwindow_button').click(function(e){ 457 media.ms_fullscreen(); 458 }); 459 } 460 461 if($.inArray('loop',options.boutons_caches) == '-1'){ 462 control.find('.loop_button').click(function(e){ 463 media.ms_loop(); 464 }); 465 } 466 remaining_time.click(function(e){ 467 if(!id.isstream){ 468 if($(this).is('.remaining')){ 469 $(this).removeClass('remaining').addClass('total_time') 470 .attr('title',ms_player_lang.info_total) 471 .html(ms_second_to_time(id.duration)); 472 }else{ 473 $(this).removeClass('total_time').addClass('remaining') 474 .attr('title',ms_player_lang.info_restant) 475 .html('-'+ms_second_to_time(id.duration - id.currentTime)); 476 } 477 media.ms_resize_controls(); 478 } 479 }); 480 } 481 /** 482 * Fonction modifiant le niveau de volume au scroll sur le lecteur 483 * Cette action fonctionne au scroll au hover du lecteur. 484 * Nécessite le plugin jQuery mousewheel : 485 * http://github.com/brandonaaron/jquery-mousewheel 486 * 487 * - bloque l'évènement normal du scroll (descendre dans la page); 488 * - baisse le volume de 10% lors d'un scroll bas avec la souris; 489 * - augmente le volume de 10% lors d'un scroll haut avec la souris; 490 * - si le volume est "muted", l'action ne fait rien sur le volume; 491 */
492 if(id.addcontrols && wrapper && !options.volume_bloque && typeof($.fn.mousewheel) != "undefined" && options.volume_mousewheel){ 493 wrapper.mousewheel(function(event, delta) { 494 if(!id.muted && id.duration){ 495 var volume_new = Math.round((id.volume + parseFloat((delta > 0) ? '0.1' : '-0.1'))*10)/10; 496 if((volume_new <= 1) && (volume_new >= 0)) id.volume = volume_new; 497 } 498 event.preventDefault(); 499 }); 500 } 501 } 502 media.ms_start('canplay'); 503 //} 504 }else 505 media.ms_test_fallback(options); 506 this.trigger('ms_init'); 507 }, 508 ms_start : function(action){ 509 var media = $(this), 510 id = media[0], 511 options = id.options, 512 wrapper = media.parent(), 513 control = id.addcontrols ? wrapper.find('.controls') : false, 514 elapsed_time = id.addcontrols ? control.find('.elapsed_time') : false, 515 remaining_time = id.addcontrols ? control.find('.remaining_time') : false; 516 517 if(!id.mediacanplay || action == 'loadedmetadata'){ 518 if(wrapper.hasClass('player_error')) 519 wrapper.removeClass('player_error').addClass('loading'); 520 521 id.mediacanplay = true; 522 523 var width_wrapper = media.width(), parent_width = wrapper.parent().width(); 524 if(id.videoHeight && id.videoWidth){ 525 id.has_metadatas = true; 526 if(wrapper.hasClass('loading')) 527 wrapper.removeClass('loading').removeClass('no_metadata').addClass('has_metadata'); 528 id.ratio = id.videoWidth/id.videoHeight; 529 } 530 else if(options.ratio) id.ratio = options.ratio; 531 else id.ratio = media.width()/media.height(); 532 533 if(options.movieSize == 'adapt' && !id.isFullScreen && (!media.hasClass('noresize') || (options.movieSize != 'noresize'))){ 534 /** 535 * En mode adapt : 536 * - on dimensionne la largeur à 100% 537 * - on dimensionne la hauteur à un ratio correspondant au ratio réel de la vidéo 538 * par rapport à la largeur du bloc parent 539 */ 540 width_wrapper = parent_width; 541 if(id.videoHeight && id.videoWidth){ 542 var ratio = (width_wrapper/id.videoWidth), 543 height_final = (id.videoHeight*ratio).toFixed(); 544 id.ratio = (id.videoWidth/id.videoHeight); 545 }else 546 var height_final = width_wrapper/id.ratio; 547 548 if(id.type == 'video' && wrapper.height() != height_final){ 549 wrapper.css({width:'auto'}).animate({height:height_final+'px'},'fast',function(){ 550 media.animate({height:'100%',width:'100%'},'fast').removeAttr('height').removeAttr('width').ms_resize_controls(); 551 }).removeAttr('width'); 552 }else{ 553 wrapper.css({width:'auto'}).removeAttr('width'); 554 media.animate({width:'100%'},'fast').ms_resize_controls(); 555 } 556 media.removeAttr('height'); 557 var handler_media_resize = function(){ 558 if(!id.isFullScreen){ 559 wrapper.css({width:'auto'}).css({height:(wrapper.width()/id.ratio)+'px'}); 560 media.ms_resize_controls(); 561 } 562 }; 563 $(window).unbind('resize',handler_media_resize).bind('resize',handler_media_resize); 564 }else if(!media.hasClass('noresize') && (options.movieSize != 'noresize')){ 565 /** 566 * En mode normal, on redimentionne la hauteur de la vidéo en fonction 567 * du ratio réel récupéré des métadonnées 568 */ 569 if(!options.height){ 570 media.removeAttr('height'); 571 if(id.type == 'video'){ 572 wrapper.height(media.width()/id.ratio); 573 media.animate({height:'100%',width:'100%'},'fast').removeAttr('height').removeAttr('width').ms_resize_controls(); 574 } 575 }else if(id.type == 'video'){ 576 wrapper.add(media).width(media.height()*id.ratio).removeAttr('width'); 577 media.animate({width:'100%'},'fast') 578 media.removeAttr('height'); 579 } 580 } 581 582 if(id.addcontrols){ 583 if(wrapper.hasClass('loading')) 584 wrapper.removeClass('loading').addClass('paused').find('.play_pause_button').attr('title',ms_player_lang.bouton_lire); 585 586 if(remaining_time && remaining_time.is('.remaining') && (id.duration != 'Infinity') && !isNaN(id.duration)) 587 remaining_time.text('-'+ms_second_to_time(id.duration)); 588 589 elapsed_time.text(ms_second_to_time(id.currentTime)); 590 591 try { 592 arg.buffer = id.buffered.end(null); 593 } catch (ignored) {} 594 595 if((id.networkState == 2) && id.duration && !isNaN(id.duration) && id.buffer) 596 control.find('.progress_buffered').css('width', ms_anything_to_percent(id.buffered.end(0),id.duration)+'%'); 597 598 if(slider){ 599 var replay = false;
600 control.find('.progress_indicator').hide(); 601 control.find('.progress_back').unbind('click'); 602 id.slider_control = control.find('.progress_back').slider({ 603 min: 0, 604 max: 100, 605 range: "min", 606 slide: function(event,ui){ 607 /** 608 * - On change les valeurs de temps 609 * - On fait avancer la barre de lecture sans lancer la lecture 610 */ 611 control.find('.progress_elapsed_time').css('width',ui.value+'%'); 612 if(remaining_time.is('.remaining') && (id.duration != 'Infinity')) 613 remaining_time.text('-'+ms_percent_to_time((100 - ui.value),id.duration)); 614 elapsed_time.text(ms_percent_to_time(ui.value,id.duration)); 615 }, 616 stop: function(event,ui){ 617 /** 618 * On saute la lecture au bon endroit ? 619 */ 620 media.ms_seek_to(event.clientX,true,false); 621 } 622 }); 623 624 if($.inArray('volume',options.boutons_caches) == '-1'){ 625 id.slider_volume = control.find('.volume_slider').slider({ 626 value: Math.floor(id.volume*100), 627 orientation: options.volume_slider_orientation, 628 min:0, 629 max:100, 630 disabled: (options.volume_bloque || id.muted) ? true : false, 631 range: "min", 632 slide: function(event,ui){ 633 /** 634 * On change le volume 635 */ 636 var volume_new = ui.value/100; 637 if((volume_new <= 1) && (volume_new >= 0)) id.volume = volume_new; 638 }, 639 stop: function(event,ui){ 640 /** 641 * On change le volume et on le sauvegarde dans le cookie si nécessaire 642 */ 643 var volume_new = ui.value/100; 644 if((volume_new <= 1) && (volume_new >= 0)) id.volume = volume_new; 645 } 646 }); 647 } 648 } 649 id.volume = Math.floor(parseInt(options.volume)/100); 650 651 if(!options.volume_bloque && !options.volume && cookies && options.cookie_volume){ 652 var volume_cookie = parseFloat($.cookie('ms_volume')); 653 if((volume_cookie >= 0) && (volume_cookie <= 1)) 654 id.volume = volume_cookie; 655 if(($.cookie('ms_volume_muted') == 'muted') && !id.muted) 656 media.ms_volume(true); 657 } 658 } 659 } 660 if(id.addcontrols){ 661 if(options.autoplay && id.mediacanplay){ 662 wrapper.removeClass('paused').find('.play_pause_button').addClass('pause').attr('title',ms_player_lang.bouton_pause); 663 id.play(); 664 } 665 wrapper.attr("tabindex",-1).hover(function(){$(this).focus();}).unbind('keydown').keydown(function(e) { 666 $(this).unbind('keyup').keyup(function(e){e.stopPropagation();e.preventDefault();}).ms_activate_keys(e); 667 }); 668 /** 669 * Il se peut que la vidéo soit déjà chargée, donc ne passera pas par loadedmetadata 670 */ 671 if(id.duration && wrapper.is('.no_metadata')) 672 wrapper.removeClass('no_metadata').removeClass('loading').addClass('has_metadata'); 673 media.ms_resize_controls(); 674 } 675 676 this.trigger('ms_start'); 677 }, 678 ms_buttons : function(){ 679 var media = $(this), 680 id = media[0], 681 wrapper = media.parent('.media_wrapper'); 682 if(id.addcontrols){ 683 if(id.paused){ 684 wrapper.removeClass('loading').addClass('paused').find('.play_pause_button').removeClass('pause').attr('title',ms_player_lang.bouton_lire); 685 media.ms_messages('pause',ms_player_lang.statut_pause); 686 } 687 else if (id.ended){ 688 wrapper.removeClass('loading').removeClass('paused').removeClass('ended').find('.play_pause_button').addClass('pause').attr('title',ms_player_lang.bouton_pause); 689 id.currentTime = id.startTime ? id.startTime : '0'; 690 if(!id.options.volume_bloque && cookies && id.options.cookie_volume){ 691 var volume_cookie = parseFloat($.cookie('ms_volume')); 692 if((volume_cookie >= 0) && (volume_cookie <= 1)) 693 id.volume = volume_cookie; 694 if($.cookie('ms_volume_muted') == 'muted') 695 id.muted = true; 696 } 697 } 698 else{ 699 // On a déjà les metadonnées 700 if(id.has_metadatas){ 701 wrapper.removeClass('loading').removeClass('paused').removeClass('ended').find('.play_pause_button').addClass('pause').attr('title',ms_player_lang.bouton_pause); 702 media.ms_messages('play',ms_player_lang.statut_play); 703 }else{ 704 wrapper.addClass('loading'); 705 id.has_to_play = true; 706 } 707 if(!id.options.volume_bloque && cookies && id.options.cookie_volume){ 708 var volume_cookie = parseFloat($.cookie('ms_volume')); 709 if((volume_cookie >= 0) && (volume_cookie <= 1)) 710 id.volume = volume_cookie; 711 if($.cookie('ms_volume_muted') == 'muted') 712 id.muted = true; 713 } 714 } 715 } 716 }, 717 ms_play_pause : function(){ 718 var id = $(this)[0];
719 if(id.addcontrols && id.mediacanplay && !id.seeking){ 720 if(id.paused || id.ended){ 721 id.play(); 722 $(this).parent().removeClass('paused').removeClass('ended'); 723 this.trigger('ms_play'); 724 }else{ 725 id.pause(); 726 $(this).parent().addClass('paused'); 727 this.trigger('ms_pause'); 728 } 729 } 730 }, 731 /** 732 * Fonction de modification du volume 733 * 734 * Paramètres : 735 * - mute boolean (true/false) : signifie si le media est muted ou pas; 736 */ 737 ms_volume : function(mute){ 738 var media = $(this), 739 id = media[0], 740 controls = media.parent().find('.controls'), 741 options = id.options; 742 if(id.addcontrols && id.mediacanplay){ 743 if(mute){ 744 if(id.muted){ 745 media.ms_messages('mute',ms_player_lang.statut_unmute); 746 var volume_title = ms_player_lang.bouton_volume+' ('+Math.floor(id.volume*100)+'%)'; 747 controls.find('.volume_button').removeClass('muted').attr('title',volume_title); 748 id.muted = false; 749 if(id.slider && (typeof(id.slider_volume) == 'object')) 750 id.slider_volume.slider('value',(id.volume*100)).slider((options.volume_bloque) ? 'disable' : 'enable'); 751 if(cookies && options.cookie_volume) 752 $.cookie('ms_volume_muted',null); 753 }else{ 754 media.ms_messages('mute',ms_player_lang.statut_mute); 755 controls.find('.volume_button').addClass('muted').attr('title',ms_player_lang.bouton_volume_muted); 756 id.muted = true; 757 if(id.slider && (typeof(id.slider_volume) == 'object')) 758 id.slider_volume.slider('disable'); 759 if(cookies && options.cookie_volume) 760 $.cookie('ms_volume_muted','muted'); 761 } 762 }else if(!id.muted){ 763 var volume = id.volume, 764 sound_button = controls.find('.volume_button'), 765 class_remove = (controls.length > 0) ? sound_button.attr('class').match('volume_button_[0-9]{1,3}') : null; 766 if(options.volume_bloque && options.volume) volume = id.volume = (options.volume) ? id.volume : options.volume; 767 768 if((volume <= 0.66) && (volume > 0.33)){ 769 if(class_remove !== null) sound_button.removeClass(class_remove[0]); 770 sound_button.addClass('volume_button_66'); 771 }else if((volume <= 1) && (volume > 0.66)){ 772 if(class_remove !== null) sound_button.removeClass(class_remove[0]); 773 sound_button.addClass('volume_button_100'); 774 }else if((volume <= 0.33) && (volume > 0)){ 775 if(class_remove !== null) sound_button.removeClass(class_remove[0]); 776 sound_button.addClass('volume_button_33'); 777 }else if(volume === 0){ 778 if(class_remove !== null) sound_button.removeClass(class_remove[0]); 779 sound_button.addClass('volume_button_0'); 780 } 781 var volume_title = ms_player_lang.bouton_volume+' ('+Math.floor(id.volume*100)+'%)'; 782 controls.find('.volume_button').attr('title',volume_title); 783 if(id.slider && (typeof(id.slider_volume) == 'object')){ 784 id.slider_volume.slider('value',(id.volume*100)); 785 id.slider_volume.slider((options.volume_bloque) ? 'disable' : 'enable'); 786 } 787 media.ms_messages('volume',volume_title); 788 789 if(cookies && options.cookie_volume) 790 $.cookie('ms_volume', id.volume); 791 } 792 } 793 }, 794 /** 795 * Fonction de saut d'un point à un autre dans le média 796 * Utilisée lors d'un click sur la barre de progression 797 * 798 * Prends deux arguments : 799 * - La position du curseur de la souris lors du click sur la barre de progression 800 * - slider : si on a ou non les sliders d'activé 801 */ 802 ms_seek_to : function(cursor_position){ 803 if(!$(this)[0].controls){ 804 var media = $(this), 805 id = media[0], 806 was_playing = false, 807 controls = media.parent().find('.controls'), 808 progress = controls.find('.progress_back'), 809 percent = Math.floor(((parseInt(cursor_position)-parseInt(progress.offset().left))/ parseInt(progress.width())) * 100), 810 time = Math.floor((id.duration * percent) / 100), 811 time_affiche = ms_second_to_time(time); 812 813 if(typeof(id.slider_control) != "object"){ 814 controls.find('.progress_elapsed_time').css('width',percent+'%'); 815 controls.find('.progress_indicator').css('left',percent+'%'); 816 } 817 818 if(id.currentTime > time) 819 media.ms_messages('seek_back',ms_player_lang.statut_seek_back+' '+time_affiche); 820 else 821 media.ms_messages('seek_to',ms_player_lang.statut_seek_to+' '+time_affiche); 822 823 id.currentTime = time; 824 } 825 }, 826 /** 827 * ms_seek_to_percent 828 * 829 * On seek à X% de la video ou du son 830 * 831 * Paramètres : 832 * - percent int : le pourcentage; 833 * - slider boolean true/false : le slider si présents; 834 * - update_slider boolean true/false : doit on mettre à jour le slider (pas utile quand on vient du slider justement); 835 */ 836 ms_seek_to_percent : function(percent,update_slider){ 837 if($(this)[0].controls) return; 838 var media = $(this), 839 id = media[0], 840 duration = id.duration, 841 currenttime = id.currentTime; 842 843 if(((currenttime === duration) && (percent === 100)) || ((currenttime === 0) && (percent === 0))) 844 return false;
845 846 var time = (percent === 0) ? 0 : ((duration * percent) / 100), 847 time_affiche = ms_second_to_time(time); 848 849 if(currenttime > time) 850 media.ms_messages('seek_back',ms_player_lang.statut_seek_back+' '+time_affiche); 851 else 852 media.ms_messages('seek_to',ms_player_lang.statut_seek_to+' '+time_affiche); 853 854 id.currentTime = time; 855 856 if(typeof(id.slider_control) != "object"){ 857 var controls = media.parent().find('.controls'); 858 controls.find('.progress_elapsed_time').css('width',percent+'%'); 859 controls.find('.progress_indicator').css('left',percent+'%'); 860 }else if(update_slider) 861 id.slider_control.slider("value", percent); 862 }, 863 /** 864 * Activer ou désactiver la boucle (mode loop) 865 */ 866 ms_loop : function(){ 867 var media = $(this), 868 id = media[0], 869 wrapper = media.parent(); 870 if(id.controls) return; 871 if(!id.loop && !wrapper.hasClass('loop')){ 872 media.attr('title',ms_player_lang.bouton_loop_looped).ms_messages('loop',ms_player_lang.statut_loop); 873 wrapper.addClass('loop'); 874 if (typeof(id.loop) == 'boolean') id.loop = true; 875 }else{ 876 media.attr('title',ms_player_lang.bouton_loop).removeAttr('loop').ms_messages('unloop',ms_player_lang.statut_unloop); 877 wrapper.removeClass('loop'); 878 if (typeof(id.loop) == 'boolean') id.loop = false; 879 } 880 }, 881 ms_fullscreen : function(){ 882 if($(this)[0].controls) return; 883 var media = $(this), id = media[0], wrapper = media.parent(), id_wrapper = wrapper[0]; 884 if(id.mediacanplay){ 885 if(!id.isFullScreen){ 886 id.videoOrigWidth = media.width(); 887 id.videoOrigHeight = media.height(); 888 id_wrapper.origWidth = wrapper.width(); 889 id_wrapper.origHeight = wrapper.height(); 890 id.isFullScreen = true; 891 if (fullScreenApi.supportsFullScreen) 892 media.ms_fullscreen_resize(); 893 else{ 894 $('body').css({'overflow' : 'hidden', '-moz-user-select' : 'none'}); 895 media.ms_fullscreen_resize(); 896 var handler_fullscreen_resize = function(){ media.ms_fullscreen_resize(); }; 897 $(window).unbind('resize',handler_fullscreen_resize).bind('resize',handler_fullscreen_resize); 898 } 899 }else{ 900 if (fullScreenApi.supportsFullScreen) { 901 (fullScreenApi.prefix === '') ? document.cancelFullScreen() : document[fullScreenApi.prefix + 'CancelFullScreen'](); 902 var handler_resize = function(){ 903 wrapper.css({width:id_wrapper.origWidth,height:id_wrapper.origHeight}).removeClass('media_wrapper_full'); 904 media.ms_resize_controls(); 905 }; 906 wrapper.bind('ms_fullscreen_resize',handler_resize); 907 }else{ 908 var handler_resize = function(){ 909 wrapper.removeClass('media_wrapper_full').animate({width:id_wrapper.origWidth+'px',height:id_wrapper.origHeight+'px',left:'0',top:'0'},500,function(){ 910 media.ms_resize_controls(); 911 }); 912 }; 913 wrapper.bind('ms_fullscreen_resize',handler_resize); 914 var media_handler_resize = function(){ 915 media.animate({width:id.videoOrigWidth+'px',height:id.videoOrigHeight+'px',left:'0',top:'0'},500,function(){ 916 media.ms_resize_controls(); 917 }); 918 }; 919 media.bind('ms_fullscreen_resize',media_handler_resize); 920 $('body').css({'overflow' : 'inherit', '-moz-user-select' : 'inherit'}); 921 $(window).unbind('resize'); 922 } 923 wrapper.add(media).trigger('ms_fullscreen_resize'); 924 wrapper.unbind('ms_fullscreen_resize',handler_resize); 925 media.unbind('ms_fullscreen_resize',media_handler_resize); 926 wrapper.find('.controls').addClass('small').find('span.fullwindow_button').attr('title',ms_player_lang.bouton_fullscreen); 927 id.isFullScreen = false; 928 } 929 } 930 }, 931 ms_fullscreen_resize : function(){ 932 if($(this)[0].controls) return; 933 var media = $(this), id = media[0], wrapper = media.parent(), id_wrapper = wrapper[0]; 934 935 wrapper.css({width:'100%',height:'100%',left:'0',top:'0'}).addClass('media_wrapper_full').find('.controls').removeClass('small') 936 .find('span.fullwindow_button').attr('title',ms_player_lang.bouton_fullscreen_full); 937 938 if (fullScreenApi.supportsFullScreen) { 939 (fullScreenApi.prefix === '') ? id_wrapper.requestFullScreen() : id_wrapper[fullScreenApi.prefix + 'RequestFullScreen'](); 940 }else{ 941 var window_width = window.innerWidth, 942 window_height = window.innerHeight, 943 ratio = (window_height/id.videoHeight),
944 width_final = (id.videoWidth*ratio).toFixed(); 945 if(width_final > window_width){ 946 var ratio = (window_width/id.videoWidth), 947 height_final = (id.videoHeight*ratio).toFixed(), 948 top = ((window_height-height_final)/2).toFixed(); 949 media.css({position:'absolute',width:window_width+'px',height:height_final+'px',top:top+'px',left:'0'}); 950 }else{ 951 var left = ((window_width-width_final)/2).toFixed(); 952 media.css({position:'auto',width:width_final+'px',height:window_height+'px',left:left+'px',top:'0'}); 953 } 954 } 955 media.ms_resize_controls(); 956 }, 957 958 /** 959 * Change dynamiquement la taille de la barre de progression et de son conteneur 960 * en fonction de la taille du lecteur. 961 * 962 * @param force boolean true / false : permet d'éviter de boucle lorsque la taille du lecteur est petite 963 * 964 * La largeur du conteneur de la barre de progession correspond à : 965 * - La largeur du lecteur 966 * - Moins la largeur des boutons de gauche (inclus leurs padding, leurs marges, et leurs bordure droite et gauche) 967 * - Moins la largeur des boutons de droite (inclus leurs padding, leurs marges, et leurs bordure droite et gauche) 968 * - Moins les marges, padding et margin css de la barre de progression elle-même 969 * 970 * La largeur de la barre de progression elle-même correspond à : 971 * - La largeur de son conteneur 972 * - Moins la largeur de l'indication de temps ecoulé (inclus ses margins, padding et bordures droite et gauche) 973 * - Moins la largeur de l'indication de temps restant (inclus ses margins, padding et bordures droite et gauche) 974 * 975 * Si on a un petit lecteur, que l'on a le slider de volume et que celui-ci est horizontal, on le force à passer vertical 976 * 977 */ 978 ms_resize_controls : function(force){ 979 if($(this)[0].controls || !$(this)[0].addcontrols) return; 980 var media = $(this), id = media[0], wrapper = media.parent(), 981 id_wrapper = wrapper[0], controls = wrapper.find('.controls'), 982 play_width = controls.find('.buttons_left').outerWidth()+parseFloat(controls.find('.buttons_left').css('margin-left'))+parseFloat(controls.find('.buttons_left').css('margin-right')), 983 sound_width = controls.find('.buttons_right').outerWidth()+parseFloat(controls.find('.buttons_right').css('margin-left'))+parseFloat(controls.find('.buttons_right').css('margin-right')), 984 progresswidth = parseFloat(controls.width())-parseFloat(play_width)-parseFloat(sound_width) - parseFloat(controls.find('.progress_bar').css('border-left-width')) - parseFloat(controls.find('.progress_bar').css('border-right-width'))-parseFloat(controls.find('.progress_bar').css('margin-right')) - parseFloat(controls.find('.progress_bar').css('margin-left')) - parseFloat(controls.find('.progress_bar').css('padding-right')) - parseFloat(controls.find('.progress_bar').css('padding-left')) -1; 985 986 controls.find('.progress_bar').width(progresswidth); 987 988 var remaining_width = controls.find(".remaining_time").outerWidth()+parseFloat(controls.find('.remaining_time').css('margin-left'))+parseFloat(controls.find('.remaining_time').css('margin-right')), 989 elapsed_width = controls.find(".elapsed_time").outerWidth()+parseFloat(controls.find('.elapsed_time').css('margin-left'))+parseFloat(controls.find('.elapsed_time').css('margin-right')); 990 991 if((controls.find(".remaining_time").size() == 0) || controls.find(".remaining_time").is(':hidden')) remaining_width = 0; 992 if((controls.find(".elapsed_time").size() == 0) || controls.find(".elapsed_time").is(':hidden')) elapsed_width = 0; 993 994 var progressback_width = progresswidth - elapsed_width - remaining_width - parseFloat(controls.find('.progress_back').css('border-left-width')) - parseFloat(controls.find('.progress_back').css('border-right-width'))-parseFloat(controls.find('.progress_back').css('margin-right')) - parseFloat(controls.find('.progress_back').css('margin-left')) - parseFloat(controls.find('.progress_back').css('padding-right')) - parseFloat(controls.find('.progress_back').css('padding-left'))-2; 995 if(slider && progressback_width < 0 && !force){ 996 if(id.slider && (typeof(id.slider_volume) == 'object')){ 997 id.slider_volume.slider('option',{'orientation':'vertical'}); 998 controls.find('.volume_slider_container').removeClass('horizontal').addClass('vertical'); 999 } 1000 media.ms_resize_controls(true); 1001 }else{
1002 if(controls.find('.remaining_time').is(':hidden') && controls.find('.loop_button').is(':visible') && progressback_width < 30){ 1003 controls.find('.loop_button').hide(); 1004 controls.ms_resize_controls(true); 1005 } 1006 else if(controls.find('.remaining_time').is(':visible') && progressback_width < 30){ 1007 controls.find('.remaining_time').hide(); 1008 media.ms_resize_controls(true); 1009 }else if(controls.find('.remaining_time').is(':hidden') && progressback_width < 30){ 1010 controls.find('.progress_back').hide(); 1011 return; 1012 } 1013 controls.find('.progress_back').width(progressback_width); 1014 } 1015 }, 1016 /** 1017 * Modifie le message dans la boite de message si présente 1018 * 1019 * @param type string : type de message (utilisé comme class sur le span entourant le message) 1020 * @param message string : le contenu du message 1021 */ 1022 ms_messages : function(type,message,force){ 1023 var media = $(this), 1024 id = media[0], 1025 wrapper = $(this).is('.media_wrapper') ? $(this) : $(this).parents('.media_wrapper'); 1026 1027 if((!id.options.messages || id.controls) && !force) return; 1028 1029 var messages = wrapper.find('.messages'), 1030 message = (type == 'error') ? '<span>'+message+'</span>' : '<span class="'+type+'">'+message+'</span>'; 1031 1032 var fade_play = function() { 1033 if(!messages.is('.error')) messages.fadeOut(function(){ $(this).html(''); }); 1034 }; 1035 if(type == 'error') messages.addClass('error'); 1036 else if(messages.is('.error')) return; 1037 1038 messages.html(message); 1039 if(messages.is(':hidden')){ 1040 messages.fadeIn('normal',function(){ 1041 if(type != 'error') stop_message_timeout = setTimeout(fade_play, 1500); 1042 }); 1043 }else{ 1044 clearTimeout(stop_message_timeout); 1045 if(type != 'error') stop_message_timeout = setTimeout(fade_play, 1500); 1046 } 1047 }, 1048 /** 1049 * La fonction de test de fallback en flash 1050 * 1051 * Si le navigateur ne sait pas lire le media en html5, 1052 * on regarde si on a une fonction de fallback flash et dans ce cas on l'utilise. 1053 */ 1054 ms_test_fallback : function(options){ 1055 var media = $(this); 1056 if(typeof($.fn.ms_fallback_flash) == 'function'){ 1057 if(IS_IE) 1058 var sources = media.parent().children("source"); 1059 else 1060 var sources = media.children("source"); 1061 $.each(sources, function(index, value){ 1062 var source = $(this); 1063 if((source.attr('type').match('video/x-flv'))||(source.attr('type').match('video/mp4'))||(source.attr('type').match('audio/mpeg'))||(source.attr('type').match('audio/mp4'))){ 1064 var defaults_flash = { 1065 flowurl:options.flowurl, 1066 flasherror:options.flasherror ? options.flasherror : '', 1067 autoplay:options.autoplay, 1068 autoload:options.autoload, 1069 wmode : 'transparent', 1070 poster : media.attr('poster'), 1071 sources : $(this), 1072 loop : (typeof(media.attr('loop')) == 'undefined') ? false : true 1073 }; 1074 var options_flash = $.extend(options,defaults_flash); 1075 media.ms_fallback_flash(options_flash); 1076 return false;// On s'arrête au premier élément qui nous convient 1077 } 1078 }); 1079 } 1080 }, 1081 ms_update_loaded : function(e){ 1082 var media = $(this), id = media[0], percent_loaded = null; 1083 if(id.controls) return; 1084 else if(id.buffered && id.buffered.length) 1085 id.percent_loaded = percent_loaded = ms_anything_to_percent(id.buffered.end(0),id.duration); 1086 else if((typeof(e.loaded) != 'undefined') && (typeof(e.total) != 'undefined')) 1087 id.percent_loaded = percent_loaded = ms_anything_to_percent(e.loaded,e.total); 1088 if(percent_loaded !== null) 1089 media.parent().find('.progress_buffered').css('width',percent_loaded+'%'); 1090 }, 1091 /** 1092 * Quelques évènements à la pression de touches sur le clavier 1093 * -* esc : sort du fullscreen 1094 * -* f : passe en fullscreen sur la video en lecture ou sur celle en hover/focus 1095 * -* l : active ou désactive la lecture en boucle 1096 * -* space : lance la lecture d'une vidéo ou la met en pause 1097 * -* flèches haut et bas : augmente ou baisse le volume 1098 * -* flèches gauche et droite : recule ou avance la lecture de 5% 1099 */ 1100 ms_activate_keys : function(e){ 1101 if($(this)[0].controls) return; 1102 var media = $(this), meta_key_pressed = e.ctrlKey || e.metaKey || e.altKey || e.shiftKey; 1103 if(!meta_key_pressed){ 1104 switch (e.keyCode) { 1105 case 27 : 1106 /** 1107 * Touche esc : sort du mode fullscreen (uniquement sur videos) 1108 */ 1109 e.preventDefault(); 1110 if (!fullScreenApi.supportsFullScreen && media.find('video')[0].isFullScreen) 1111 media.find('video').ms_fullscreen(); 1112 break; 1113 case 70 : 1114 /** 1115 * Touche f 1116 * Active le fullscreen sur la video en lecture ou la video en hover/focus (uniquement sur videos) 1117 */ 1118 if(!media.find('video')[0].isFullScreen && ($('input:focus,textarea:focus').size() === 0)){ 1119 media.find('video').ms_fullscreen(); 1120 e.preventDefault(); 1121 } 1122 break; 1123 case 76 : 1124 /** 1125 * Touche l 1126 * Active ou désactive le mode boucle (loop) sur le média en cours de lecture 1127 */ 1128 if(media.find('video,audio')[0].isFullScreen || $('input:focus,textarea:focus').size() === 0){ 1129 media.find('video,audio').ms_loop(); 1130 e.preventDefault(); 1131 } 1132 break; 1133 case 77 : 1134 /** 1135 * Touche M : mute ou unmute 1136 */ 1137 if(media.find('video,audio')[0].isFullScreen || $('input:focus,textarea:focus').size() === 0){ 1138 media.find('video,audio').ms_volume(true); 1139 e.preventDefault(); 1140 } 1141 break; 1142 case 32 : 1143 /** 1144 * Touche Space : lance la lecture ou met le media en pause 1145 */ 1146 if(media.find('video,audio')[0].isFullScreen || ($('input:focus,textarea:focus').size() === 0)){ 1147 media.find('video,audio').ms_play_pause(); 1148 e.preventDefault(); 1149 } 1150 break; 1151 case 38 : case 40 : 1152 /** 1153 * Touches Up (38) et Down (40) 1154 * Baisse ou augmente de 10% le volume de la video en cours de lecture 1155 */ 1156 if(media.find('video,audio')[0].duration && (media.find('video,audio')[0].isFullScreen||($('input:focus,textarea:focus').size() === 0))){ 1157 if(!media.find('video,audio')[0].muted){ 1158 var delta = (e.keyCode == 38) ? 1 : -1, 1159 volume = media.find('video,audio')[0].volume, 1160 volume_diff = (delta > 0) ? '0.1' : '-0.1', 1161 volume_new = Math.round((volume + parseFloat(volume_diff))*10)/10; 1162 if((volume_new <= 1) && (volume_new >= 0)) 1163 media.find('video,audio')[0].volume = volume_new; 1164 } 1165 e.preventDefault(); 1166 e.stopPropagation(); 1167 } 1168 break; 1169 case 37 : case 39 : 1170 /** 1171 * Gauche (37) et droite (39) 1172 * Avance ou recule de 5% la video en cours de lecture 1173 * Il faut également modifier la valeur de la barre 1174 */ 1175 if(media.find('video,audio')[0].duration && (media.find('video,audio')[0].isFullScreen||($('input:focus,textarea:focus,select:focus').size() === 0))){ 1176 var pourcent_actuel = ((media.find('video,audio')[0].currentTime / media.find('video,audio')[0].duration) * 100); 1177 if(e.keyCode == 37) 1178 var new_percent = (pourcent_actuel >= 5) ? (pourcent_actuel - 5) : 0; 1179 else 1180 var new_percent = (pourcent_actuel > 95) ? 100 : (pourcent_actuel + 5); 1181 media.find('video,audio').ms_seek_to_percent(new_percent,true); 1182 e.preventDefault(); 1183 e.stopPropagation(); 1184 } 1185 break; 1186 } 1187 } 1188 } 1189 }); 1190})(jQuery); 1191 1192/**
1193 * Converti un nombre de secondes en une heure lisible hh:mm:ss 1194 * 1195 * @param seconds int Le nombre de secondes 1196 * @return 1197 */ 1198function ms_second_to_time(seconds){ 1199 if(seconds === 0) return '00:00'; 1200 var uTime = Math.round(seconds*Math.pow(10,0))/Math.pow(10,0), 1201 hours = Math.floor(uTime/3600); 1202 hours = (hours >0) ? (hours<10?'0'+hours:hours)+':' : ''; 1203 var minutes = (Math.floor(uTime/60)%60); 1204 minutes= minutes<10?'0'+minutes:minutes; 1205 seconds = (uTime%60); 1206 seconds = seconds<10?'0'+seconds:seconds; 1207 return hours+minutes+':'+seconds; 1208} 1209 1210function ms_percent_to_time(percent,total){ 1211 return ms_second_to_time(Math.ceil((total * percent) / 100)); 1212} 1213 1214function ms_anything_to_percent(current,total){ 1215 return Math.ceil((current / total) * 100); 1216}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.