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('');
203 var width = widget.options.width;
204 var height = widget.options.height;
207 if (widget.options.type == 'ns-html5'
208 || widget.options.type == 'html5')
210 widget.$video = $('<video id="' + widget.element.attr('id') + '-video" src="' + src + '"' + (width == 0 ? '' : ' width="' + width + '"') + (height == 0 ? '' : ' height="' + height + '"') + ' preload="auto"' + (widget.options.autoplay ? ' autoplay="autoplay"' : '') + '>'
211 +'Error: Your browser does not support HTML5 or the video format!'
213 .appendTo(widget.$videoContainer)
216 widget.html5.pause();
222 widget.html5.pause();
224 timeupdate: function() {
225 widget.html5.refreshTime();
227 progress: function() {
228 widget.html5.refreshLoadedProgress();
230 loadedmetadata: function() {
231 widget.html5.refreshTime();
232 widget.html5.refreshVolume();
233 if (widget.options.width == 0)
234 widget.element.css('width',
235 widget.$video.width() + 8 + 'px');
240 volumechange: function() {
241 widget.html5.refreshVolume();
246 else if (widget.options.type == 'ns-vlc'
247 || widget.options.type == 'vlc')
250 if (widget.options.type == 'ns-vlc')
251 embedType = 'application/x-ns-stream';
253 embedType = 'application/x-vlc-plugin';
255 if (navigator.appName == "Netscape")
257 widget.$video = $('<embed type="' + embedType + '" name="vlcVideo" id="' + widget.element.attr('id') + '-video" autoplay="' + (widget.options.autoplay ? 'yes' : 'no') + '" loop="no" width="' + (width == 0 ? '640' : width) + '" height="' + (height == 0 ? '480' : height) + '" target="' + src + '" />')
258 .appendTo(widget.$videoContainer);
262 widget.$video = $('<object classid="clsid:1800B8AF-4E33-43C0-AFC7-894433C13538" width="' + (width == 0 ? '640' : width) + '" height="' + (height == 0 ? '480' : height) + '" id="' + widget.element.attr('id') + '-video" name="vlcVideo" events="True" target="">'
263 + '<param name="Src" value="' + src + '" />'
264 + '<param name="ShowDisplay" value="True" />'
265 + '<param name="Loop" value="False" />'
266 + '<param name="AutoPlay" value="' + (widget.options.autoplay ? 'True' : 'False') + '" />'
267 + '<param name="Toolbar" value="False" />'
269 .appendTo(widget.$videoContainer);
273 widget.element.css('width',
274 widget.$video.width() + 8 + 'px');
277 setPlayButton: function() {
278 $('button.ui-nsvideo-play', widget.element[0])
279 .button('option', 'icons', { primary: "ui-icon-play" })
282 setPauseButton: function() {
283 $('button.ui-nsvideo-play', widget.element[0])
284 .button('option', 'icons', { primary: "ui-icon-pause" })
287 setMuteButton: function() {
288 $('button.ui-nsvideo-mute', widget.element[0])
289 .button('option', 'icons', { primary: "ui-icon-volume-off" })
292 setUnmuteButton: function() {
293 $('button.ui-nsvideo-mute', widget.element[0])
294 .button('option', 'icons', { primary: "ui-icon-volume-on" })
297 setTimeText: function(text) {
298 //$('.ui-nsvideo-time', widget.element[0])
302 setVolumeSlider: function(vol) {
303 $('.ui-nsvideo-volume', widget.element[0])
304 .slider('value', vol);
306 setProgressSlider: function(prog) {
307 $('.ui-nsvideo-progress', widget.element[0])
308 .slider('value', prog);
310 setLoadedProgressSlider: function(prog) {
311 $('.ui-nsvideo-loaded-progress', widget.element[0])
312 .progressbar('value', prog);
315 videoPlugin: function(method, args) {
316 if (typeof args == 'undefined')
318 var videoPlugin = null;
320 if (this.options.type.indexOf('html5') != -1)
322 videoPlugin = this.html5;
324 else if (this.options.type.indexOf('vlc') != -1)
326 videoPlugin = this.vlc;
330 return videoPlugin[method].apply(this, args);
335 definition: function(def) {
338 if (typeof def == 'undefined')
339 return widget.options.definition;
341 widget.options.definition = def;
347 type: function(type) {
350 if (typeof type == 'undefined')
351 return widget.options.type;
353 widget.options.type = type;
356 // Initialize video plugin
357 widget.$video.ready(function() {
358 widget.videoPlugin('init');
368 if (typeof widget.options.src == 'string')
369 src = widget.options.src;
370 else if (typeof widget.options.src == 'object')
372 if (typeof widget.options.definition == 'undefined')
375 if (typeof widget.options.src[ widget.options.definition ]
379 src = widget.options.src[ widget.options.definition ];
382 if (widget.options.type == 'ns-html5')
383 src = 'tribe://' + src;
393 //widget.html5.refreshAll();
395 //if (widget.options.autoplay)
396 // widget.html5.play();
399 togglePlay: function() {
400 if (widget.$video[0].paused)
406 widget.html5.pause();
411 if (widget.$video[0].paused)
412 widget.$video[0].play();
414 widget.setPauseButton();
420 if (!widget.$video[0].paused)
421 widget.$video[0].pause();
423 widget.setPlayButton();
428 toggleMute: function() {
429 if (!widget.$video[0].muted)
435 widget.html5.unmute();
440 if (!widget.$video[0].muted)
441 widget.$video[0].muted = true;
443 widget.setMuteButton();
449 if (widget.$video[0].muted)
450 widget.$video[0].muted = false;
452 widget.setUnmuteButton();
458 * Volume value is expressed in percents.
460 volume: function(vol) {
461 if (typeof vol == 'undefined')
462 return Math.round(widget.$video[0].volume * 100);
464 widget.html5.unmute();
465 widget.$video[0].volume = vol / 100;
471 * Seek position is a value between 0 and 1000.
473 crtTime: function(pos) {
475 if (typeof pos == 'undefined')
477 var crtTime = widget.$video[0].currentTime;
478 var totTime = widget.$video[0].duration;
479 if (isNaN(totTime) || totTime == 0)
482 return Math.round(crtTime / totTime * 1000.0);
486 widget.$video[0].currentTime =
487 pos / 1000 * widget.$video[0].duration;
490 refreshAll: function() {
491 widget.html5.refreshState();
492 widget.html5.refreshVolume();
493 widget.html5.refreshLoadedProgress();
494 widget.$time.html('--:-- / --:--');
495 widget.$stateText.html('...');
496 widget.html5.refreshTime();
499 refreshTime: function() {
500 if (widget.$video[0].seeking)
503 var crtTime = widget.$video[0].currentTime;
504 var totTime = widget.$video[0].duration;
506 // Refresh only at refreshInterval seconds to save CPU time.
507 var delta = crtTime - widget.html5.lastTime;
508 if (typeof widget.html5.lastTime !== "undefined"
509 && delta >= 0 && delta < widget.options.refreshInterval)
511 widget.html5.lastTime = crtTime;
513 // Current time string
514 var crtH = Math.floor(crtTime / 3600);
515 var crtM = Math.floor((crtTime / 60) % 60);
516 var crtS = Math.floor(crtTime % 60);
518 (crtH == 0 ? '' : (widget._leadingZeros(crtH) + ':'))
519 + widget._leadingZeros(crtM) + ':' + widget._leadingZeros(crtS);
522 var totH = Math.floor(totTime / 3600);
523 var totM = Math.floor((totTime / 60) % 60);
524 var totS = Math.floor(totTime % 60);
526 (totH == 0 || isNaN(totH) ? '' : (widget._leadingZeros(totH) + ':'))
527 + widget._leadingZeros(totM) + ':' + widget._leadingZeros(totS);
529 widget.setTimeText('' + strCrtTime + ' / ' + strTotTime);
531 // Update time progress slider.
532 widget.html5.refreshProgress();
537 refreshState: function() {
538 // TODO refresh HTML5 plugin state
543 refreshVolume: function() {
546 if (widget.$video[0].muted)
549 vol = Math.floor(widget.$video[0].volume * 100);
551 widget.setVolumeSlider(vol);
556 refreshProgress: function() {
557 widget.setProgressSlider(widget.html5.crtTime());
563 * Supported for Firefox 4.0 or later.
565 refreshLoadedProgress: function() {
566 // Return if buffering status not available in browser.
567 if (typeof widget.$video[0].buffered == 'undefined'
568 || widget.$video[0].buffered.length === 0)
571 var loadedTime = widget.$video[0].buffered.end(0);
572 var totTime = widget.$video[0].duration;
574 if (isNaN(totTime) || totTime == 0)
577 percent = Math.floor(loadedTime / totTime * 100);
579 widget.setLoadedProgressSlider(percent);
584 fullscreen: function() {
585 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.');
594 IDLE_CLOSE: [0, "Idle / Close"],
595 OPENING: [1, "Opening..."],
596 BUFFERING: [2, "Buffering..."],
597 PLAYING: [3, "Playing..."],
598 PAUSED: [4, "Paused"],
599 STOPPING: [5, "Stopping..."],
604 if (widget.options.autoplay)
606 widget.vlc.refreshAll();
609 togglePlay: function() {
610 if (! widget.$video[0].playlist.isPlaying)
621 if (! widget.$video[0].playlist.isPlaying)
622 widget.$video[0].playlist.play();
624 widget.setPauseButton();
626 // Schedule information refreshment at refreshInterval seconds.
627 if (! widget.vlc.timerHandle)
628 widget.vlc.timerHandle = setTimeout(widget.vlc.refreshHandler,
629 widget.options.refreshInterval * 1000);
631 widget.vlc.refreshState();
637 if (widget.$video[0].playlist.isPlaying)
638 widget.$video[0].playlist.togglePause();
640 widget.setPlayButton();
642 // Cancel information refreshment scheduling.
643 clearTimeout(widget.vlc.timerHandle);
644 widget.vlc.timerHandle = null;
646 widget.vlc.refreshState();
651 toggleMute: function() {
652 if (! widget.$video[0].audio.mute)
663 if (! widget.$video[0].audio.mute)
664 widget.$video[0].audio.toggleMute();
666 widget.setMuteButton();
668 widget.vlc.refreshVolume();
674 if (widget.$video[0].audio.mute)
675 widget.$video[0].audio.toggleMute();
677 widget.setUnmuteButton();
679 widget.vlc.refreshVolume();
685 * Volume value is expressed in percents.
687 volume: function(vol) {
688 if (typeof vol == 'undefined')
689 return Math.round(widget.$video[0].audio.volume);
692 widget.$video[0].audio.volume = vol;
698 * Seek position is a value between 0 and 1000.
700 crtTime: function(pos) {
702 if (typeof pos == 'undefined')
704 var crtTime = widget.$video[0].input.time;
705 var totTime = widget.$video[0].input.length;
706 if (isNaN(totTime) || totTime == 0)
709 return Math.round(crtTime / totTime * 1000.0);
713 widget.$video[0].input.time =
714 pos / 1000 * widget.$video[0].input.length;
716 widget.vlc.refreshState();
720 * Timeout callback called at refreshInterval during playing in order
721 * to refresh information.
723 refreshHandler: function() {
724 if (widget.$video[0].input.state
725 == widget.vlc.STATES.PLAYING[0])
727 widget.vlc.refreshTime();
728 widget.vlc.timerHandle = setTimeout(widget.vlc.refreshHandler,
729 widget.options.refreshInterval * 1000);
734 widget.vlc.refreshState();
737 refreshAll: function() {
738 widget.vlc.refreshState();
739 widget.vlc.refreshVolume();
740 widget.vlc.refreshLoadedProgress();
743 widget.vlc.refreshTime();
746 widget.$time.html('--:-- / --:--');
750 refreshTime: function() {
751 // TODO while seeking (maybe not necessary for VLC)
752 // if (widget.$video[0].seeking)
755 // Time values in seconds.
756 var crtTime = widget.$video[0].input.time / 1000.0;
757 var totTime = widget.$video[0].input.length / 1000.0;
758 //var crtTime = widget.$video[0].input.position * totTime;
760 // Current time string
761 var crtH = Math.floor(crtTime / 3600);
762 var crtM = Math.floor((crtTime / 60) % 60);
763 var crtS = Math.floor(crtTime % 60);
765 (crtH == 0 ? '' : (widget._leadingZeros(crtH) + ':'))
766 + widget._leadingZeros(crtM) + ':' + widget._leadingZeros(crtS);
769 var totH = Math.floor(totTime / 3600);
770 var totM = Math.floor((totTime / 60) % 60);
771 var totS = Math.floor(totTime % 60);
773 (totH == 0 || isNaN(totH) ? '' : (widget._leadingZeros(totH) + ':'))
774 + widget._leadingZeros(totM) + ':' + widget._leadingZeros(totS);
776 widget.setTimeText('' + strCrtTime + ' / ' + strTotTime);
778 // Update time progress slider.
779 widget.vlc.refreshProgress();
784 _state: function(code) {
786 $.each(widget.vlc.STATES, function(index, value) {
787 if ('' + code == '' + value[0])
797 refreshState: function() {
799 .html(widget.vlc._state(widget.$video[0].input.state)[1]);
802 refreshVolume: function() {
805 if (widget.$video[0].audio.mute)
808 vol = Math.floor(widget.$video[0].audio.volume);
810 widget.setVolumeSlider(vol);
815 refreshProgress: function() {
816 widget.setProgressSlider(widget.vlc.crtTime());
822 * Not supported for VLC.
824 refreshLoadedProgress: function() {
825 // TODO Currently not possible through VLC API.
830 fullscreen: function() {
831 widget.$video[0].video.toggleFullscreen();