From edac3c0e2d7251d0223cd8809f12fbfcb1eac8d1 Mon Sep 17 00:00:00 2001 From: Calin Burloiu Date: Fri, 5 Aug 2011 16:19:45 +0300 Subject: [PATCH] jQuery UI NextShare Video Widget (alpha version) finished and integrated into the site --- application/views/video/watch_view.php | 14 +- css/jquery.ui.nsvideo.css | 5 +- js/jquery.ui.nsvideo.js | 822 ++++++++++++++++++------- 3 files changed, 620 insertions(+), 221 deletions(-) diff --git a/application/views/video/watch_view.php b/application/views/video/watch_view.php index a3ba044..b5f7eea 100644 --- a/application/views/video/watch_view.php +++ b/application/views/video/watch_view.php @@ -21,12 +21,6 @@

- -
') + widget.$videoContainer = $('
') .appendTo(widget.element); widget.$progressContainer = $('
') .appendTo(widget.element); @@ -63,7 +42,7 @@ $.widget( "ui.nsvideo", { widget.$controls = $('
') .appendTo(widget.element); - widget.setVideo(); + widget.video(); // Time progress slider with load progress also widget.$loadedProgress @@ -77,25 +56,35 @@ $.widget( "ui.nsvideo", { min: 0, max: 1000, //Math.floor(widget.$video[0].duration), slide: function(event, ui) { - widget.$video[0].currentTime = - ui.value / 1000 * widget.$video[0].duration; + widget.videoPlugin('crtTime', [ui.value]); } }); // Play / Pause - $('') + $('') .appendTo(widget.$controls) .button({ text: false, icons: { primary: "ui-icon-play" } }) .click(function() { - widget.togglePlay(); + widget.videoPlugin('togglePlay'); }); // Time information (current and total) - $('
--:-- / --:--
') + widget.$time = $('
--:-- / --:--
') .appendTo(widget.$controls); + + // Full screen + $('') + .appendTo(widget.$controls) + .button({ + text: false, + icons: { primary: "ui-icon-arrow-4-diag" } + }) + .click(function() { + widget.videoPlugin('fullscreen'); + }); // Video definition buttonset if (typeof widget.options.src == 'object') @@ -109,7 +98,8 @@ $.widget( "ui.nsvideo", { .appendTo($definitions) .attr('checked', (index == widget.options.definition)) .click(function() { - widget.setDefinition(index); + widget.videoPlugin('pause'); + widget.definition(index); }); $('') .appendTo($definitions); @@ -126,25 +116,40 @@ $.widget( "ui.nsvideo", { min: 0, max: 100, slide: function(event, ui) { - widget.unmuteHtml5(); - widget.$video[0].volume = ui.value / 100; + widget.videoPlugin('volume', [ui.value]); } }); // Toggle Mute - $('') + $('') .appendTo(widget.$controls) .button({ text: false, icons: { primary: "ui-icon-volume-on" } }) .click(function() { - widget.toggleMute(); + widget.videoPlugin('toggleMute'); }); + // Status information + if (widget.options.showStatus) + { + widget.$stateText = $('
...
') + .appendTo(widget.$controls) + .css('cursor', 'pointer') + .click(function() { + widget.videoPlugin('refreshAll'); + }); + } + // Clear fix helper $('
') .appendTo(widget.$controls); + + // Initialize video plugin + widget.$video.ready(function() { + widget.videoPlugin('init'); + }); }, _destroy: function() { @@ -152,6 +157,7 @@ $.widget( "ui.nsvideo", { }, _setOption: function( key, value ) { + // TODO if ( key === "TODO" ) { } @@ -159,233 +165,194 @@ $.widget( "ui.nsvideo", { this._super( "_setOption", key, value ); }, - setVideo: function() { + _leadingZeros: function(number, length) { + if (!length) + length = 2; + + var str = ''; + + if (isNaN(number)) + { + for (var i=0; i' + widget.$video = $('') - .appendTo(widget.$nsPlugin) + .appendTo(widget.$videoContainer) .bind({ ended: function() { - widget.pauseHtml5(); + widget.html5.pause(); }, play: function() { - widget.playHtml5(); + widget.html5.play(); }, pause: function() { - widget.pauseHtml5(); + widget.html5.pause(); }, timeupdate: function() { - widget.refreshTimeHtml5(); + widget.html5.refreshTime(); }, progress: function() { - widget.refreshLoadedProgressHtml5(); + widget.html5.refreshLoadedProgress(); }, loadedmetadata: function() { - widget.refreshTimeHtml5(); - widget.refreshVolumeHtml5(); + widget.html5.refreshTime(); + widget.html5.refreshVolume(); }, seeked: function() { - widget.playHtml5(); + widget.html5.play(); }, volumechange: function() { - widget.refreshVolumeHtml5(); + widget.html5.refreshVolume(); } }); } + // VLC + else if (widget.options.type == 'ns-vlc' + || widget.options.type == 'vlc') + { + var embedType; + if (widget.options.type == 'ns-vlc') + embedType = 'application/x-ns-stream'; + else + embedType = 'application/x-vlc-plugin'; + + if (navigator.appName == "Netscape") + { + widget.$video = $('') + .appendTo(widget.$videoContainer); + } + else + { + widget.$video = $('' + + '' + + '' + + '' + + '' + + '' + + '') + .appendTo(widget.$videoContainer); + } + } }, - playHtml5: function() { - if (this.$video[0].paused) - this.$video[0].play(); - - $('button.ui-nsvideo-play', this.element[0]) - .button('option', 'icons', { primary: "ui-icon-pause" }) - .button('refresh'); - - return this; - }, - - pauseHtml5: function() { - if (!this.$video[0].paused) - this.$video[0].pause(); - - $('button.ui-nsvideo-play', this.element[0]) + setPlayButton: function() { + $('button.ui-nsvideo-play', widget.element[0]) .button('option', 'icons', { primary: "ui-icon-play" }) .button('refresh'); - - return this; }, - - refreshTimeHtml5: function() { - var widget = this; - - if (widget.$video[0].seeking) - return widget; - - var crtTime = widget.$video[0].currentTime; - var totTime = widget.$video[0].duration; - - // Refresh only at 0.1 s to save CPU time. - var delta = crtTime - widget.lastTime; - if (typeof widget.lastTime != "undefined" && delta >= 0 && delta < 0.1) - return widget; - widget.lastTime = crtTime; - - // Current time string - var crtH = Math.floor(crtTime / 3600); - var crtM = Math.floor((crtTime / 60) % 60); - var crtS = Math.floor(crtTime % 60); - var strCrtTime = - (crtH == 0 ? '' : (padWithZeros(crtH) + ':')) - + padWithZeros(crtM) + ':' + padWithZeros(crtS); - - // Total time string - var totH = Math.floor(totTime / 3600); - var totM = Math.floor((totTime / 60) % 60); - var totS = Math.floor(totTime % 60); - var strTotTime = - (totH == 0 || isNaN(totH) ? '' : (padWithZeros(totH) + ':')) - + padWithZeros(totM) + ':' + padWithZeros(totS); - - $('.ui-nsvideo-time', widget.element[0]) - .html('' + strCrtTime + ' / ' + strTotTime); - - // Update time progress slider. - widget.refreshProgressHtml5(); - - return widget; + setPauseButton: function() { + $('button.ui-nsvideo-play', widget.element[0]) + .button('option', 'icons', { primary: "ui-icon-pause" }) + .button('refresh'); }, - - muteHtml5: function() { - if (!this.$video[0].muted) - this.$video[0].muted = true; - - $('button.ui-nsvideo-mute', this.element[0]) + setMuteButton: function() { + $('button.ui-nsvideo-mute', widget.element[0]) .button('option', 'icons', { primary: "ui-icon-volume-off" }) .button('refresh'); - - return this; }, - - unmuteHtml5: function() { - if (this.$video[0].muted) - this.$video[0].muted = false; - - $('button.ui-nsvideo-mute', this.element[0]) + setUnmuteButton: function() { + $('button.ui-nsvideo-mute', widget.element[0]) .button('option', 'icons', { primary: "ui-icon-volume-on" }) .button('refresh'); - - return this; }, - - refreshVolumeHtml5: function() { - var vol; - - if (this.$video[0].muted) - vol = 0; - else - vol = Math.floor(this.$video[0].volume * 100); - - $('.ui-nsvideo-volume', this.element[0]) + setTimeText: function(text) { + //$('.ui-nsvideo-time', widget.element[0]) + this.$time + .html(text); + }, + setVolumeSlider: function(vol) { + $('.ui-nsvideo-volume', widget.element[0]) .slider('value', vol); - - return this; }, - - refreshProgressHtml5: function() { - var crtTime = this.$video[0].currentTime; - var totTime = this.$video[0].duration; - var permilia; - if (isNaN(totTime) || totTime == 0) - permilia = 0 - else - permilia = Math.floor(crtTime / totTime * 1000); - - $('.ui-nsvideo-progress', this.element[0]) - .slider('value', permilia); - - return this; + setProgressSlider: function(prog) { + $('.ui-nsvideo-progress', widget.element[0]) + .slider('value', prog); }, - - /** - * Supported for Firefox 4.0 or later. - */ - refreshLoadedProgressHtml5: function() { - // Return if buffering status not available in browser. - if (typeof this.$video[0].buffered == 'undefined' - || this.$video[0].buffered.length === 0) - return this; - - var loadedTime = this.$video[0].buffered.end(0); - var totTime = this.$video[0].duration; - var percent; - if (isNaN(totTime) || totTime == 0) - percent = 0 - else - percent = Math.floor(loadedTime / totTime * 100); - - $('.ui-nsvideo-loaded-progress', this.element[0]) - .progressbar('value', percent); - - return this; + setLoadedProgressSlider: function(prog) { + $('.ui-nsvideo-loaded-progress', widget.element[0]) + .progressbar('value', prog); }, - togglePlay: function() { + videoPlugin: function(method, args) { + if (typeof args == 'undefined') + args = []; + var videoPlugin = null; + if (this.options.type.indexOf('html5') != -1) { - if (this.$video[0].paused) - { - this.playHtml5(); - } - else - { - this.pauseHtml5(); - } + videoPlugin = this.html5; } - else if (this.options.type == 'ns-vlc') + else if (this.options.type.indexOf('vlc') != -1) { - + videoPlugin = this.vlc; } - return this; + if (videoPlugin) + return videoPlugin[method].apply(this, args); + + return null; }, - toggleMute: function() { - if (this.options.type.indexOf('html5') != -1) - { - if (!this.$video[0].muted) - { - this.muteHtml5(); - } - else - { - this.unmuteHtml5(); - } - } - else if (this.options.type == 'ns-vlc') - { - - } + definition: function(def) { + var widget = this; + + if (typeof def == 'undefined') + return widget.options.definition; + + widget.options.definition = def; + widget.video(); + + return widget; + }, + + type: function(type) { + var widget = this; + + if (typeof type == 'undefined') + return widget.options.type; + + widget.options.type = type; + widget.video(); + + // Initialize video plugin + widget.$video.ready(function() { + widget.videoPlugin('init'); + }); - return this; + return widget; }, - getCrtSrc: function() { + crtSrc: function() { var src; var widget = this; @@ -409,14 +376,451 @@ $.widget( "ui.nsvideo", { return src; }, - setDefinition: function(definition) { - if (this.options.type.indexOf('html5') != -1) - { - this.options.definition = definition; - this.setVideo(); + html5: { + widget: this, + //lastTime: null, + + init: function() { + widget.html5.refreshAll(); + + //if (widget.options.autoplay) + // widget.html5.play(); + }, + + togglePlay: function() { + if (widget.$video[0].paused) + { + widget.html5.play(); + } + else + { + widget.html5.pause(); + } + }, + + play: function() { + if (widget.$video[0].paused) + widget.$video[0].play(); + + widget.setPauseButton(); + + return widget; + }, + + pause: function() { + if (!widget.$video[0].paused) + widget.$video[0].pause(); + + widget.setPlayButton(); + + return widget; + }, + + toggleMute: function() { + if (!widget.$video[0].muted) + { + widget.html5.mute(); + } + else + { + widget.html5.unmute(); + } + }, + + mute: function() { + if (!widget.$video[0].muted) + widget.$video[0].muted = true; + + widget.setMuteButton(); + + return widget; + }, + + unmute: function() { + if (widget.$video[0].muted) + widget.$video[0].muted = false; + + widget.setUnmuteButton(); + + return widget; + }, + + /** + * Volume value is expressed in percents. + */ + volume: function(vol) { + if (typeof vol == 'undefined') + return Math.round(widget.$video[0].volume * 100); + + widget.html5.unmute(); + widget.$video[0].volume = vol / 100; + + return widget; + }, + + /** + * Seek position is a value between 0 and 1000. + */ + crtTime: function(pos) { + // getter + if (typeof pos == 'undefined') + { + var crtTime = widget.$video[0].currentTime; + var totTime = widget.$video[0].duration; + if (isNaN(totTime) || totTime == 0) + return 0; + else + return Math.round(crtTime / totTime * 1000.0); + } + + // setter + widget.$video[0].currentTime = + pos / 1000 * widget.$video[0].duration; + }, + + refreshAll: function() { + widget.html5.refreshState(); + widget.html5.refreshVolume(); + widget.html5.refreshLoadedProgress(); + widget.$time.html('--:-- / --:--'); + widget.$stateText.html('...'); + widget.html5.refreshTime(); + }, + + refreshTime: function() { + if (widget.$video[0].seeking) + return widget; + + var crtTime = widget.$video[0].currentTime; + var totTime = widget.$video[0].duration; + + // Refresh only at refreshInterval seconds to save CPU time. + var delta = crtTime - widget.html5.lastTime; + if (typeof widget.html5.lastTime !== "undefined" + && delta >= 0 && delta < widget.options.refreshInterval) + return widget; + widget.html5.lastTime = crtTime; + + // Current time string + var crtH = Math.floor(crtTime / 3600); + var crtM = Math.floor((crtTime / 60) % 60); + var crtS = Math.floor(crtTime % 60); + var strCrtTime = + (crtH == 0 ? '' : (widget._leadingZeros(crtH) + ':')) + + widget._leadingZeros(crtM) + ':' + widget._leadingZeros(crtS); + + // Total time string + var totH = Math.floor(totTime / 3600); + var totM = Math.floor((totTime / 60) % 60); + var totS = Math.floor(totTime % 60); + var strTotTime = + (totH == 0 || isNaN(totH) ? '' : (widget._leadingZeros(totH) + ':')) + + widget._leadingZeros(totM) + ':' + widget._leadingZeros(totS); + + widget.setTimeText('' + strCrtTime + ' / ' + strTotTime); + + // Update time progress slider. + widget.html5.refreshProgress(); + + return widget; + }, + + refreshState: function() { + // TODO refresh HTML5 plugin state + + return widget; + }, + + refreshVolume: function() { + var vol; + + if (widget.$video[0].muted) + vol = 0; + else + vol = Math.floor(widget.$video[0].volume * 100); + + widget.setVolumeSlider(vol); + + return widget; + }, + + refreshProgress: function() { + widget.setProgressSlider(widget.html5.crtTime()); + + return widget; + }, + + /** + * Supported for Firefox 4.0 or later. + */ + refreshLoadedProgress: function() { + // Return if buffering status not available in browser. + if (typeof widget.$video[0].buffered == 'undefined' + || widget.$video[0].buffered.length === 0) + return widget; + + var loadedTime = widget.$video[0].buffered.end(0); + var totTime = widget.$video[0].duration; + var percent; + if (isNaN(totTime) || totTime == 0) + percent = 0 + else + percent = Math.floor(loadedTime / totTime * 100); + + widget.setLoadedProgressSlider(percent); + + return widget; + }, + + fullscreen: function() { + 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.'); } + }, + + vlc: { + widget: this, + timerHandle: null, + + STATES: { + IDLE_CLOSE: [0, "Idle / Close"], + OPENING: [1, "Opening..."], + BUFFERING: [2, "Buffering..."], + PLAYING: [3, "Playing..."], + PAUSED: [4, "Paused"], + STOPPING: [5, "Stopping..."], + ERROR: [6, "Error!"] + }, + + init: function() { + if (widget.options.autoplay) + widget.vlc.play(); + widget.vlc.refreshAll(); + }, + + togglePlay: function() { + if (! widget.$video[0].playlist.isPlaying) + { + widget.vlc.play(); + } + else + { + widget.vlc.pause(); + } + }, + + play: function() { + if (! widget.$video[0].playlist.isPlaying) + widget.$video[0].playlist.play(); + + widget.setPauseButton(); + + // Schedule information refreshment at refreshInterval seconds. + if (! widget.vlc.timerHandle) + widget.vlc.timerHandle = setTimeout(widget.vlc.refreshHandler, + widget.options.refreshInterval * 1000); + + widget.vlc.refreshState(); + + return widget; + }, + + pause: function() { + if (widget.$video[0].playlist.isPlaying) + widget.$video[0].playlist.togglePause(); + + widget.setPlayButton(); + + // Cancel information refreshment scheduling. + clearTimeout(widget.vlc.timerHandle); + widget.vlc.timerHandle = null; + + widget.vlc.refreshState(); + + return widget; + }, + + toggleMute: function() { + if (! widget.$video[0].audio.mute) + { + widget.vlc.mute(); + } + else + { + widget.vlc.unmute(); + } + }, + + mute: function() { + if (! widget.$video[0].audio.mute) + widget.$video[0].audio.toggleMute(); + + widget.setMuteButton(); + + widget.vlc.refreshVolume(); + + return widget; + }, + + unmute: function() { + if (widget.$video[0].audio.mute) + widget.$video[0].audio.toggleMute(); + + widget.setUnmuteButton(); + + widget.vlc.refreshVolume(); + + return widget; + }, + + /** + * Volume value is expressed in percents. + */ + volume: function(vol) { + if (typeof vol == 'undefined') + return Math.round(widget.$video[0].audio.volume); + + widget.vlc.unmute(); + widget.$video[0].audio.volume = vol; + + return widget; + }, + + /** + * Seek position is a value between 0 and 1000. + */ + crtTime: function(pos) { + // getter + if (typeof pos == 'undefined') + { + var crtTime = widget.$video[0].input.time; + var totTime = widget.$video[0].input.length; + if (isNaN(totTime) || totTime == 0) + return 0; + else + return Math.round(crtTime / totTime * 1000.0); + } + + // setter + widget.$video[0].input.time = + pos / 1000 * widget.$video[0].input.length; + + widget.vlc.refreshState(); + }, + + /** + * Timeout callback called at refreshInterval during playing in order + * to refresh information. + */ + refreshHandler: function() { + if (widget.$video[0].input.state + == widget.vlc.STATES.PLAYING[0]) + { + widget.vlc.refreshTime(); + widget.vlc.timerHandle = setTimeout(widget.vlc.refreshHandler, + widget.options.refreshInterval * 1000); + } + else + widget.vlc.pause(); + + widget.vlc.refreshState(); + }, + + refreshAll: function() { + widget.vlc.refreshState(); + widget.vlc.refreshVolume(); + widget.vlc.refreshLoadedProgress(); + + try { + widget.vlc.refreshTime(); + } catch(e) { + console.log(e); + widget.$time.html('--:-- / --:--'); + } + }, + + refreshTime: function() { + // TODO while seeking (maybe not necessary for VLC) +// if (widget.$video[0].seeking) +// return widget; + + // Time values in seconds. + var crtTime = widget.$video[0].input.time / 1000.0; + var totTime = widget.$video[0].input.length / 1000.0; + //var crtTime = widget.$video[0].input.position * totTime; + + // Current time string + var crtH = Math.floor(crtTime / 3600); + var crtM = Math.floor((crtTime / 60) % 60); + var crtS = Math.floor(crtTime % 60); + var strCrtTime = + (crtH == 0 ? '' : (widget._leadingZeros(crtH) + ':')) + + widget._leadingZeros(crtM) + ':' + widget._leadingZeros(crtS); + + // Total time string + var totH = Math.floor(totTime / 3600); + var totM = Math.floor((totTime / 60) % 60); + var totS = Math.floor(totTime % 60); + var strTotTime = + (totH == 0 || isNaN(totH) ? '' : (widget._leadingZeros(totH) + ':')) + + widget._leadingZeros(totM) + ':' + widget._leadingZeros(totS); + + widget.setTimeText('' + strCrtTime + ' / ' + strTotTime); + + // Update time progress slider. + widget.vlc.refreshProgress(); + + return widget; + }, + + _state: function(code) { + var r; + $.each(widget.vlc.STATES, function(index, value) { + if ('' + code == '' + value[0]) + { + r = value; + return false; + } + }); + + return r; + }, + + refreshState: function() { + widget.$stateText + .html(widget.vlc._state(widget.$video[0].input.state)[1]); + }, + + refreshVolume: function() { + var vol; + + if (widget.$video[0].audio.mute) + vol = 0; + else + vol = Math.floor(widget.$video[0].audio.volume); + + widget.setVolumeSlider(vol); + + return widget; + }, + + refreshProgress: function() { + widget.setProgressSlider(widget.vlc.crtTime()); + + return widget; + }, - return this; + /** + * Not supported for VLC. + */ + refreshLoadedProgress: function() { + // TODO Currently not possible through VLC API. + + return widget; + }, + + fullscreen: function() { + widget.$video[0].video.toggleFullscreen(); + } } }); -- 2.20.1