2 * jQuery UI NS-Video @VERSION
4 * Copyright 2011, Călin-Andrei Burloiu
5 * Dual licensed under the MIT or GPL Version 2 licenses.
6 * http://jquery.org/license
13 (function( $, undefined ) {
15 $.widget( "ui.nsvideo", {
22 refreshInterval: 0.1, // seconds
32 .addClass( "ui-widget ui-widget-content ui-corner-all" );
34 widget.$videoContainer = $('<div class="ui-nsvideo-nsplugin"></div>')
35 .appendTo(widget.element);
36 widget.$progressContainer = $('<div class="ui-nsvideo-progress-container ui-widget-content ui-corner-top"></div>')
37 .appendTo(widget.element);
38 widget.$progress = $('<div class="ui-nsvideo-progress"></div>')
39 .appendTo(widget.$progressContainer);
40 widget.$loadedProgress = $('<div class="ui-nsvideo-loaded-progress"></div>')
41 .appendTo(widget.$progress);
42 widget.$controls = $('<div class="ui-nsvideo-controls ui-widget-content ui-corner-bottom"></div>')
43 .appendTo(widget.element);
47 // Time progress slider with load progress also
48 widget.$loadedProgress
49 // TODO an object that inherits progressbar should be used in order to customize min value.
57 max: 1000, //Math.floor(widget.$video[0].duration),
58 slide: function(event, ui) {
59 widget.videoPlugin('crtTime', [ui.value]);
64 $('<button class="ui-nsvideo-play ui-nsvideo-button ui-nsvideo-control-left">Play / Pause</button>')
65 .appendTo(widget.$controls)
68 icons: { primary: "ui-icon-play" }
71 widget.videoPlugin('togglePlay');
74 // Time information (current and total)
75 widget.$time = $('<div class="ui-nsvideo-time ui-nsvideo-text ui-nsvideo-control-left">--:-- / --:--</div>')
76 .appendTo(widget.$controls);
79 $('<button class="ui-nsvideo-fullscreen ui-nsvideo-button ui-nsvideo-control-right">Full Screen</button>')
80 .appendTo(widget.$controls)
83 icons: { primary: "ui-icon-arrow-4-diag" }
86 widget.videoPlugin('fullscreen');
89 // Video definition buttonset
90 if (typeof widget.options.src == 'object')
92 var $definitions = $('<form><div class="ui-nsvideo-definitions ui-nsvideo-control-right"></div></form>')
93 .appendTo(widget.$controls);
94 $definitions = $('.ui-nsvideo-definitions', $definitions[0]);
95 $.each(widget.options.src, function(index, value) {
96 id = widget.element.attr('id') + '-def-' + index;
97 $('<input type="radio" id="' + id + '" name="definition" />')
98 .appendTo($definitions)
99 .attr('checked', (index == widget.options.definition))
101 widget.videoPlugin('pause');
102 widget.definition(index);
104 $('<label for="' + id + '">' + index + '</label>')
105 .appendTo($definitions);
108 $definitions.buttonset();
112 $('<div class="ui-nsvideo-volume ui-nsvideo-control-right"></div>')
113 .appendTo(widget.$controls)
118 slide: function(event, ui) {
119 widget.videoPlugin('volume', [ui.value]);
124 $('<button class="ui-nsvideo-mute ui-nsvideo-button ui-nsvideo-control-right">Mute</button>')
125 .appendTo(widget.$controls)
128 icons: { primary: "ui-icon-volume-on" }
131 widget.videoPlugin('toggleMute');
134 // Status information
135 if (widget.options.showStatus)
137 widget.$stateText = $('<div class="ui-nsvideo-text ui-nsvideo-control-right">...</div>')
138 .appendTo(widget.$controls)
139 .css('cursor', 'pointer')
141 widget.videoPlugin('refreshAll');
146 $('<div class="ui-helper-clearfix"></div>')
147 .appendTo(widget.$controls);
149 // Initialize video plugin
150 widget.$video.ready(function() {
151 widget.videoPlugin('init');
155 _destroy: function() {
159 _setOption: function( key, value ) {
161 if ( key === "TODO" ) {
165 this._super( "_setOption", key, value );
168 _leadingZeros: function(number, length) {
176 for (var i=0; i<length; i++)
182 while (str.length < length)
193 // Select video source.
194 // If src option is string, that's the source.
195 // If src is an object, properties are definitions and values are
197 var src = widget.crtSrc();
201 widget.$videoContainer.html('');
204 if (widget.options.type == 'ns-html5'
205 || widget.options.type == 'html5')
207 widget.$video = $('<video id="' + widget.element.attr('id') + '-video" src="' + src + '" width="' + widget.options.width + '" height="' + widget.options.height + '" preload="auto"' + (widget.options.autoplay ? ' autoplay="autoplay"' : '') + '>'
208 +'Error: Your browser does not support HTML5 or the video format!'
210 .appendTo(widget.$videoContainer)
213 widget.html5.pause();
219 widget.html5.pause();
221 timeupdate: function() {
222 widget.html5.refreshTime();
224 progress: function() {
225 widget.html5.refreshLoadedProgress();
227 loadedmetadata: function() {
228 widget.html5.refreshTime();
229 widget.html5.refreshVolume();
234 volumechange: function() {
235 widget.html5.refreshVolume();
240 else if (widget.options.type == 'ns-vlc'
241 || widget.options.type == 'vlc')
244 if (widget.options.type == 'ns-vlc')
245 embedType = 'application/x-ns-stream';
247 embedType = 'application/x-vlc-plugin';
249 if (navigator.appName == "Netscape")
251 widget.$video = $('<embed type="' + embedType + '" name="vlcVideo" id="' + widget.element.attr('id') + '-video" autoplay="' + (widget.options.autoplay ? 'yes' : 'no') + '" loop="no" width="' + widget.options.width + '" height="' + widget.options.height + '" target="' + src + '" />')
252 .appendTo(widget.$videoContainer);
256 widget.$video = $('<object classid="clsid:1800B8AF-4E33-43C0-AFC7-894433C13538" width="' + widget.options.width + '" height="' + widget.options.height + '" id="' + widget.element.attr('id') + '-video" name="vlcVideo" events="True" target="">'
257 + '<param name="Src" value="' + src + '" />'
258 + '<param name="ShowDisplay" value="True" />'
259 + '<param name="Loop" value="False" />'
260 + '<param name="AutoPlay" value="' + (widget.options.autoplay ? 'True' : 'False') + '" />'
261 + '<param name="Toolbar" value="False" />'
263 .appendTo(widget.$videoContainer);
268 setPlayButton: function() {
269 $('button.ui-nsvideo-play', widget.element[0])
270 .button('option', 'icons', { primary: "ui-icon-play" })
273 setPauseButton: function() {
274 $('button.ui-nsvideo-play', widget.element[0])
275 .button('option', 'icons', { primary: "ui-icon-pause" })
278 setMuteButton: function() {
279 $('button.ui-nsvideo-mute', widget.element[0])
280 .button('option', 'icons', { primary: "ui-icon-volume-off" })
283 setUnmuteButton: function() {
284 $('button.ui-nsvideo-mute', widget.element[0])
285 .button('option', 'icons', { primary: "ui-icon-volume-on" })
288 setTimeText: function(text) {
289 //$('.ui-nsvideo-time', widget.element[0])
293 setVolumeSlider: function(vol) {
294 $('.ui-nsvideo-volume', widget.element[0])
295 .slider('value', vol);
297 setProgressSlider: function(prog) {
298 $('.ui-nsvideo-progress', widget.element[0])
299 .slider('value', prog);
301 setLoadedProgressSlider: function(prog) {
302 $('.ui-nsvideo-loaded-progress', widget.element[0])
303 .progressbar('value', prog);
306 videoPlugin: function(method, args) {
307 if (typeof args == 'undefined')
309 var videoPlugin = null;
311 if (this.options.type.indexOf('html5') != -1)
313 videoPlugin = this.html5;
315 else if (this.options.type.indexOf('vlc') != -1)
317 videoPlugin = this.vlc;
321 return videoPlugin[method].apply(this, args);
326 definition: function(def) {
329 if (typeof def == 'undefined')
330 return widget.options.definition;
332 widget.options.definition = def;
338 type: function(type) {
341 if (typeof type == 'undefined')
342 return widget.options.type;
344 widget.options.type = type;
347 // Initialize video plugin
348 widget.$video.ready(function() {
349 widget.videoPlugin('init');
359 if (typeof widget.options.src == 'string')
360 src = widget.options.src;
361 else if (typeof widget.options.src == 'object')
363 if (typeof widget.options.definition == 'undefined')
366 if (typeof widget.options.src[ widget.options.definition ]
370 src = widget.options.src[ widget.options.definition ];
373 if (widget.options.type == 'ns-html5')
374 src = 'tribe://' + src;
384 widget.html5.refreshAll();
386 //if (widget.options.autoplay)
387 // widget.html5.play();
390 togglePlay: function() {
391 if (widget.$video[0].paused)
397 widget.html5.pause();
402 if (widget.$video[0].paused)
403 widget.$video[0].play();
405 widget.setPauseButton();
411 if (!widget.$video[0].paused)
412 widget.$video[0].pause();
414 widget.setPlayButton();
419 toggleMute: function() {
420 if (!widget.$video[0].muted)
426 widget.html5.unmute();
431 if (!widget.$video[0].muted)
432 widget.$video[0].muted = true;
434 widget.setMuteButton();
440 if (widget.$video[0].muted)
441 widget.$video[0].muted = false;
443 widget.setUnmuteButton();
449 * Volume value is expressed in percents.
451 volume: function(vol) {
452 if (typeof vol == 'undefined')
453 return Math.round(widget.$video[0].volume * 100);
455 widget.html5.unmute();
456 widget.$video[0].volume = vol / 100;
462 * Seek position is a value between 0 and 1000.
464 crtTime: function(pos) {
466 if (typeof pos == 'undefined')
468 var crtTime = widget.$video[0].currentTime;
469 var totTime = widget.$video[0].duration;
470 if (isNaN(totTime) || totTime == 0)
473 return Math.round(crtTime / totTime * 1000.0);
477 widget.$video[0].currentTime =
478 pos / 1000 * widget.$video[0].duration;
481 refreshAll: function() {
482 widget.html5.refreshState();
483 widget.html5.refreshVolume();
484 widget.html5.refreshLoadedProgress();
485 widget.$time.html('--:-- / --:--');
486 widget.$stateText.html('...');
487 widget.html5.refreshTime();
490 refreshTime: function() {
491 if (widget.$video[0].seeking)
494 var crtTime = widget.$video[0].currentTime;
495 var totTime = widget.$video[0].duration;
497 // Refresh only at refreshInterval seconds to save CPU time.
498 var delta = crtTime - widget.html5.lastTime;
499 if (typeof widget.html5.lastTime !== "undefined"
500 && delta >= 0 && delta < widget.options.refreshInterval)
502 widget.html5.lastTime = crtTime;
504 // Current time string
505 var crtH = Math.floor(crtTime / 3600);
506 var crtM = Math.floor((crtTime / 60) % 60);
507 var crtS = Math.floor(crtTime % 60);
509 (crtH == 0 ? '' : (widget._leadingZeros(crtH) + ':'))
510 + widget._leadingZeros(crtM) + ':' + widget._leadingZeros(crtS);
513 var totH = Math.floor(totTime / 3600);
514 var totM = Math.floor((totTime / 60) % 60);
515 var totS = Math.floor(totTime % 60);
517 (totH == 0 || isNaN(totH) ? '' : (widget._leadingZeros(totH) + ':'))
518 + widget._leadingZeros(totM) + ':' + widget._leadingZeros(totS);
520 widget.setTimeText('' + strCrtTime + ' / ' + strTotTime);
522 // Update time progress slider.
523 widget.html5.refreshProgress();
528 refreshState: function() {
529 // TODO refresh HTML5 plugin state
534 refreshVolume: function() {
537 if (widget.$video[0].muted)
540 vol = Math.floor(widget.$video[0].volume * 100);
542 widget.setVolumeSlider(vol);
547 refreshProgress: function() {
548 widget.setProgressSlider(widget.html5.crtTime());
554 * Supported for Firefox 4.0 or later.
556 refreshLoadedProgress: function() {
557 // Return if buffering status not available in browser.
558 if (typeof widget.$video[0].buffered == 'undefined'
559 || widget.$video[0].buffered.length === 0)
562 var loadedTime = widget.$video[0].buffered.end(0);
563 var totTime = widget.$video[0].duration;
565 if (isNaN(totTime) || totTime == 0)
568 percent = Math.floor(loadedTime / totTime * 100);
570 widget.setLoadedProgressSlider(percent);
575 fullscreen: function() {
576 alert('Your web browser does not support switching to full screen in HTML5 mode with this button. You can switch to full screen manually by right clicking on the video and choosing "Full Screen" from the popup menu.');
585 IDLE_CLOSE: [0, "Idle / Close"],
586 OPENING: [1, "Opening..."],
587 BUFFERING: [2, "Buffering..."],
588 PLAYING: [3, "Playing..."],
589 PAUSED: [4, "Paused"],
590 STOPPING: [5, "Stopping..."],
595 if (widget.options.autoplay)
597 widget.vlc.refreshAll();
600 togglePlay: function() {
601 if (! widget.$video[0].playlist.isPlaying)
612 if (! widget.$video[0].playlist.isPlaying)
613 widget.$video[0].playlist.play();
615 widget.setPauseButton();
617 // Schedule information refreshment at refreshInterval seconds.
618 if (! widget.vlc.timerHandle)
619 widget.vlc.timerHandle = setTimeout(widget.vlc.refreshHandler,
620 widget.options.refreshInterval * 1000);
622 widget.vlc.refreshState();
628 if (widget.$video[0].playlist.isPlaying)
629 widget.$video[0].playlist.togglePause();
631 widget.setPlayButton();
633 // Cancel information refreshment scheduling.
634 clearTimeout(widget.vlc.timerHandle);
635 widget.vlc.timerHandle = null;
637 widget.vlc.refreshState();
642 toggleMute: function() {
643 if (! widget.$video[0].audio.mute)
654 if (! widget.$video[0].audio.mute)
655 widget.$video[0].audio.toggleMute();
657 widget.setMuteButton();
659 widget.vlc.refreshVolume();
665 if (widget.$video[0].audio.mute)
666 widget.$video[0].audio.toggleMute();
668 widget.setUnmuteButton();
670 widget.vlc.refreshVolume();
676 * Volume value is expressed in percents.
678 volume: function(vol) {
679 if (typeof vol == 'undefined')
680 return Math.round(widget.$video[0].audio.volume);
683 widget.$video[0].audio.volume = vol;
689 * Seek position is a value between 0 and 1000.
691 crtTime: function(pos) {
693 if (typeof pos == 'undefined')
695 var crtTime = widget.$video[0].input.time;
696 var totTime = widget.$video[0].input.length;
697 if (isNaN(totTime) || totTime == 0)
700 return Math.round(crtTime / totTime * 1000.0);
704 widget.$video[0].input.time =
705 pos / 1000 * widget.$video[0].input.length;
707 widget.vlc.refreshState();
711 * Timeout callback called at refreshInterval during playing in order
712 * to refresh information.
714 refreshHandler: function() {
715 if (widget.$video[0].input.state
716 == widget.vlc.STATES.PLAYING[0])
718 widget.vlc.refreshTime();
719 widget.vlc.timerHandle = setTimeout(widget.vlc.refreshHandler,
720 widget.options.refreshInterval * 1000);
725 widget.vlc.refreshState();
728 refreshAll: function() {
729 widget.vlc.refreshState();
730 widget.vlc.refreshVolume();
731 widget.vlc.refreshLoadedProgress();
734 widget.vlc.refreshTime();
737 widget.$time.html('--:-- / --:--');
741 refreshTime: function() {
742 // TODO while seeking (maybe not necessary for VLC)
743 // if (widget.$video[0].seeking)
746 // Time values in seconds.
747 var crtTime = widget.$video[0].input.time / 1000.0;
748 var totTime = widget.$video[0].input.length / 1000.0;
749 //var crtTime = widget.$video[0].input.position * totTime;
751 // Current time string
752 var crtH = Math.floor(crtTime / 3600);
753 var crtM = Math.floor((crtTime / 60) % 60);
754 var crtS = Math.floor(crtTime % 60);
756 (crtH == 0 ? '' : (widget._leadingZeros(crtH) + ':'))
757 + widget._leadingZeros(crtM) + ':' + widget._leadingZeros(crtS);
760 var totH = Math.floor(totTime / 3600);
761 var totM = Math.floor((totTime / 60) % 60);
762 var totS = Math.floor(totTime % 60);
764 (totH == 0 || isNaN(totH) ? '' : (widget._leadingZeros(totH) + ':'))
765 + widget._leadingZeros(totM) + ':' + widget._leadingZeros(totS);
767 widget.setTimeText('' + strCrtTime + ' / ' + strTotTime);
769 // Update time progress slider.
770 widget.vlc.refreshProgress();
775 _state: function(code) {
777 $.each(widget.vlc.STATES, function(index, value) {
778 if ('' + code == '' + value[0])
788 refreshState: function() {
790 .html(widget.vlc._state(widget.$video[0].input.state)[1]);
793 refreshVolume: function() {
796 if (widget.$video[0].audio.mute)
799 vol = Math.floor(widget.$video[0].audio.volume);
801 widget.setVolumeSlider(vol);
806 refreshProgress: function() {
807 widget.setProgressSlider(widget.vlc.crtTime());
813 * Not supported for VLC.
815 refreshLoadedProgress: function() {
816 // TODO Currently not possible through VLC API.
821 fullscreen: function() {
822 widget.$video[0].video.toggleFullscreen();