From 9967b75eef7c8466cf7e62217026bc3c013ff8a9 Mon Sep 17 00:00:00 2001 From: Evandro Junior Date: Fri, 6 Feb 2015 19:14:49 -0300 Subject: [PATCH] falta escolher qual galeria apresentar no bloco --- plugins/video/lib/ext/article.rb | 32 ++++++++++++++++++++++++++++++++ plugins/video/lib/video_plugin.rb | 4 +--- plugins/video/lib/video_plugin/video_gallery_helper.rb | 2 +- plugins/video/public/javascripts/videojs/vjs.youtube.js | 931 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- plugins/video/public/style.css | 20 +++++++++++++++++++- plugins/video/views/content_viewer/video_plugin/_video.html.erb | 6 +++--- plugins/video/views/content_viewer/video_plugin/video_video.html.erb | 34 ---------------------------------- plugins/video/views/content_viewer/video_plugin/video_video_gallery.html.erb | 28 ---------------------------- plugins/video/views/shared/video_list.html.erb | 24 ++++++++++++++++++++++-- plugins/video/views/shared/video_plugin/apagar_video_block.html.erb | 21 +++++++++++++++++++++ plugins/video/views/shared/video_plugin/video_block.html.erb | 21 --------------------- 11 files changed, 1029 insertions(+), 94 deletions(-) delete mode 100644 plugins/video/views/content_viewer/video_plugin/video_video.html.erb delete mode 100644 plugins/video/views/content_viewer/video_plugin/video_video_gallery.html.erb create mode 100644 plugins/video/views/shared/video_plugin/apagar_video_block.html.erb delete mode 100644 plugins/video/views/shared/video_plugin/video_block.html.erb diff --git a/plugins/video/lib/ext/article.rb b/plugins/video/lib/ext/article.rb index 7579c53..a870126 100644 --- a/plugins/video/lib/ext/article.rb +++ b/plugins/video/lib/ext/article.rb @@ -2,6 +2,8 @@ require_dependency 'article' class Article + scope :video_gallery, :conditions => ["articles.type == 'VideoGallery'"] + #FIXME This should be done via hotspot def self.folder_types_with_video self.folder_types_without_video << 'VideoPlugin::VideoGallery' @@ -11,5 +13,35 @@ class Article class << self alias_method_chain :folder_types, :video end + +# def self.articles_columns +# Article.column_names.map {|c| "articles.#{c}"} .join(",") +# end +# +# def self.most_accessed(owner, limit = nil) +# conditions = owner.kind_of?(Environment) ? ["hits > 0"] : ["profile_id = ? and hits > 0", owner.id] +# result = Article.relevant_content.find( +# :all, +# :order => 'hits desc', +# :limit => limit, +# :conditions => conditions) +# result.paginate({:page => 1, :per_page => limit}) +# end + + def self.can_be_listed + conditions = owner.kind_of?(Environment) ? ["hits > 0"] : ["profile_id = ? and hits > 0", owner.id] + result = Article.video_gallery.find( + :all, + :order => 'hits desc', + :conditions => conditions) + end + + end + + + + + + diff --git a/plugins/video/lib/video_plugin.rb b/plugins/video/lib/video_plugin.rb index 3b53f0e..61dd947 100644 --- a/plugins/video/lib/video_plugin.rb +++ b/plugins/video/lib/video_plugin.rb @@ -9,9 +9,7 @@ class VideoPlugin < Noosfero::Plugin end def self.extra_blocks - { - VideoPlugin::VideoBlock => {} - } + { VideoPlugin::VideoBlock => {}, VideoPlugin::VideoGalleryBlock => {} } end def stylesheet? diff --git a/plugins/video/lib/video_plugin/video_gallery_helper.rb b/plugins/video/lib/video_plugin/video_gallery_helper.rb index ba5c8ce..513874e 100644 --- a/plugins/video/lib/video_plugin/video_gallery_helper.rb +++ b/plugins/video/lib/video_plugin/video_gallery_helper.rb @@ -6,7 +6,7 @@ module VideoPlugin::VideoGalleryHelper if !configure[:contents].blank? configure[:contents] = configure[:contents].paginate( :order => "updated_at DESC", - :per_page => 16, + :per_page => 17, :page => params[:npage] ) render :file => 'shared/video_list', :locals => configure diff --git a/plugins/video/public/javascripts/videojs/vjs.youtube.js b/plugins/video/public/javascripts/videojs/vjs.youtube.js index 4c29da0..80ab81f 100644 --- a/plugins/video/public/javascripts/videojs/vjs.youtube.js +++ b/plugins/video/public/javascripts/videojs/vjs.youtube.js @@ -1 +1,930 @@ -!function(){function addEventListener(element,event,cb){element.addEventListener?element.addEventListener(event,cb,!0):element.attachEvent(event,cb)}function setInnerText(element,text){if("undefined"==typeof element)return!1;var textProperty="innerText"in element?"innerText":"textContent";try{element[textProperty]=text}catch(anException){element.setAttribute("innerText",text)}}videojs.Youtube=videojs.MediaTechController.extend({init:function(player,options,ready){if(this.features.progressEvents=!1,this.features.timeupdateEvents=!1,videojs.MediaTechController.call(this,player,options,ready),this.isIos=/(iPad|iPhone|iPod)/g.test(navigator.userAgent),this.isAndroid=/(Android)/g.test(navigator.userAgent),this.playVideoIsAllowed=!(this.isIos||this.isAndroid),"undefined"!=typeof options.source)for(var key in options.source)options.source.hasOwnProperty(key)&&(player.options()[key]=options.source[key]);this.userQuality=videojs.Youtube.convertQualityName(player.options().quality),this.player_=player,this.playerEl_=document.getElementById(player.id()),this.playerEl_.className+=" vjs-youtube",this.qualityButton=document.createElement("div"),this.qualityButton.setAttribute("class","vjs-quality-button vjs-menu-button vjs-control"),this.qualityButton.setAttribute("tabindex",0);var qualityContent=document.createElement("div");this.qualityButton.appendChild(qualityContent),this.qualityTitle=document.createElement("span"),qualityContent.appendChild(this.qualityTitle),"undefined"!==player.options().quality&&setInnerText(this.qualityTitle,player.options().quality||"auto");var qualityMenu=document.createElement("div");if(qualityMenu.setAttribute("class","vjs-menu"),this.qualityButton.appendChild(qualityMenu),this.qualityMenuContent=document.createElement("ul"),this.qualityMenuContent.setAttribute("class","vjs-menu-content"),qualityMenu.appendChild(this.qualityMenuContent),this.id_=this.player_.id()+"_youtube_api",this.el_=videojs.Component.prototype.createEl("iframe",{id:this.id_,className:"vjs-tech",scrolling:"no",marginWidth:0,marginHeight:0,frameBorder:0}),this.el_.setAttribute("allowFullScreen",""),this.playerEl_.insertBefore(this.el_,this.playerEl_.firstChild),/MSIE (\d+\.\d+);/.test(navigator.userAgent)){var ieVersion=Number(RegExp.$1);this.addIframeBlocker(ieVersion)}else/(iPad|iPhone|iPod|android)/g.test(navigator.userAgent)||(this.el_.className+=" onDesktop",this.addIframeBlocker());this.parseSrc(player.options().src),this.playOnReady=this.player_.options().autoplay||!1,this.forceSSL=!("undefined"!=typeof this.player_.options().forceSSL&&this.player_.options().forceSSL!==!0),this.forceHTML5=!("undefined"!=typeof this.player_.options().forceHTML5&&this.player_.options().forceHTML5!==!0),this.updateIframeSrc();var self=this;player.ready(function(){var controlBar=self.playerEl_.querySelectorAll(".vjs-control-bar")[0];controlBar.appendChild(self.qualityButton),self.playOnReady&&!self.player_.options().ytcontrols&&("undefined"!=typeof self.player_.loadingSpinner&&self.player_.loadingSpinner.show(),"undefined"!=typeof self.player_.bigPlayButton&&self.player_.bigPlayButton.hide()),player.trigger("loadstart")}),this.on("dispose",function(){this.ytplayer&&this.ytplayer.destroy(),this.player_.options().ytcontrols||this.player_.off("waiting",this.bindedWaiting),this.playerEl_.querySelectorAll(".vjs-poster")[0].style.backgroundImage="none",this.el_.parentNode&&this.el_.parentNode.removeChild(this.el_),this.qualityButton.parentNode&&this.qualityButton.parentNode.removeChild(this.qualityButton),"undefined"!=typeof this.player_.loadingSpinner&&this.player_.loadingSpinner.hide(),"undefined"!=typeof this.player_.bigPlayButton&&this.player_.bigPlayButton.hide(),this.iframeblocker&&this.playerEl_.removeChild(this.iframeblocker)})}}),videojs.Youtube.prototype.updateIframeSrc=function(){var params={enablejsapi:1,iv_load_policy:3,playerapiid:this.id(),disablekb:1,wmode:"transparent",controls:this.player_.options().ytcontrols?1:0,html5:this.player_.options().forceHTML5?1:null,playsinline:this.player_.options().playsInline?1:0,showinfo:0,modestbranding:1,rel:0,autoplay:this.playOnReady?1:0,loop:this.player_.options().loop?1:0,list:this.playlistId,vq:this.userQuality,origin:window.location.protocol+"//"+window.location.host};"file:"===window.location.protocol&&delete params.origin;for(var prop in params)!params.hasOwnProperty(prop)||"undefined"!=typeof params[prop]&&null!==params[prop]||delete params[prop];var self=this;if(null===this.videoId)this.el_.src="about:blank",setTimeout(function(){self.triggerReady()},500);else if(this.el_.src=(this.forceSSL||"file:"===window.location.protocol?"https:":window.location.protocol)+"//www.youtube.com/embed/"+this.videoId+"?"+videojs.Youtube.makeQueryString(params),this.player_.options().ytcontrols?this.player_.controls(!1):"undefined"==typeof this.player_.poster()&&setTimeout(function(){var posterEl=self.playerEl_.querySelectorAll(".vjs-poster")[0];posterEl.style.backgroundImage="url(https://img.youtube.com/vi/"+self.videoId+"/0.jpg)",posterEl.style.display=""},100),this.bindedWaiting=function(){self.onWaiting()},this.player_.on("waiting",this.bindedWaiting),videojs.Youtube.apiReady)this.loadYoutube();else if(videojs.Youtube.loadingQueue.push(this),!videojs.Youtube.apiLoading){var tag=document.createElement("script");tag.onerror=function(e){self.onError(e)},tag.src=this.forceSSL||"file:"===window.location.protocol?"https://www.youtube.com/iframe_api":"//www.youtube.com/iframe_api";var firstScriptTag=document.getElementsByTagName("script")[0];firstScriptTag.parentNode.insertBefore(tag,firstScriptTag),videojs.Youtube.apiLoading=!0}},videojs.Youtube.prototype.onWaiting=function(){this.player_.bigPlayButton.hide()},videojs.Youtube.prototype.addIframeBlocker=function(ieVersion){this.iframeblocker=videojs.Component.prototype.createEl("div"),this.iframeblocker.className="iframeblocker",this.iframeblocker.style.position="absolute",this.iframeblocker.style.left=0,this.iframeblocker.style.right=0,this.iframeblocker.style.top=0,this.iframeblocker.style.bottom=0,this.iframeblocker.style.zIndex=9999,ieVersion&&9>ieVersion?this.iframeblocker.style.opacity=.01:this.iframeblocker.style.background="rgba(255, 255, 255, 0.01)";var self=this;addEventListener(this.iframeblocker,"mousemove",function(e){self.player_.userActive()||self.player_.userActive(!0),e.stopPropagation(),e.preventDefault()}),addEventListener(this.iframeblocker,"click",function(){self.paused()?self.play():self.pause()}),this.playerEl_.insertBefore(this.iframeblocker,this.el_.nextSibling)},videojs.Youtube.prototype.parseSrc=function(src){if(this.srcVal=src,src){var regId=/^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|\&v=)([^#\&\?]*).*/,match=src.match(regId);this.videoId=match&&11===match[2].length?match[2]:null;var regPlaylist=/[?&]list=([^#\&\?]+)/;match=src.match(regPlaylist),null!==match&&match.length>1?this.playlistId=match[1]:this.playlistId&&delete this.playlistId;var regVideoQuality=/[?&]vq=([^#\&\?]+)/;match=src.match(regVideoQuality),null!==match&&match.length>1&&(this.userQuality=match[1],setInnerText(this.qualityTitle,videojs.Youtube.parseQualityName(this.userQuality)))}},videojs.Youtube.prototype.src=function(src){if("undefined"!=typeof src){if(this.parseSrc(src),"about:blank"===this.el_.src)return void this.updateIframeSrc();delete this.defaultQuality,null!==this.videoId&&(this.player_.options().autoplay&&this.playVideoIsAllowed?this.ytplayer.loadVideoById({videoId:this.videoId,suggestedQuality:this.userQuality}):this.ytplayer.cueVideoById({videoId:this.videoId,suggestedQuality:this.userQuality}),this.playerEl_.querySelectorAll(".vjs-poster")[0].style.backgroundImage="url(https://img.youtube.com/vi/"+this.videoId+"/0.jpg)",this.player_.poster("https://img.youtube.com/vi/"+this.videoId+"/0.jpg"))}return this.srcVal},videojs.Youtube.prototype.load=function(){},videojs.Youtube.prototype.play=function(){null!==this.videoId&&(this.player_.options().ytcontrols||this.player_.trigger("waiting"),this.isReady_?(this.ytplayer.setVolume(100*this.player_.volume()),this.volumeVal>0?this.ytplayer.unMute():this.ytplayer.mute(),this.playVideoIsAllowed&&this.ytplayer.playVideo()):this.playOnReady=!0)},videojs.Youtube.prototype.pause=function(){this.ytplayer.pauseVideo()},videojs.Youtube.prototype.paused=function(){return this.ytplayer?this.lastState!==YT.PlayerState.PLAYING&&this.lastState!==YT.PlayerState.BUFFERING:!0},videojs.Youtube.prototype.currentTime=function(){return this.ytplayer&&this.ytplayer.getCurrentTime?this.ytplayer.getCurrentTime():0},videojs.Youtube.prototype.setCurrentTime=function(seconds){this.ytplayer.seekTo(seconds,!0),this.player_.trigger("timeupdate")},videojs.Youtube.prototype.duration=function(){return this.ytplayer&&this.ytplayer.getDuration?this.ytplayer.getDuration():0},videojs.Youtube.prototype.currentSrc=function(){return this.srcVal},videojs.Youtube.prototype.volume=function(){return this.ytplayer&&isNaN(this.volumeVal)&&(this.volumeVal=this.ytplayer.getVolume()/100,this.player_.volume(this.volumeVal)),this.volumeVal},videojs.Youtube.prototype.setVolume=function(percentAsDecimal){"undefined"!=typeof percentAsDecimal&&percentAsDecimal!==this.volumeVal&&(this.ytplayer.setVolume(100*percentAsDecimal),this.volumeVal=percentAsDecimal,this.player_.trigger("volumechange"))},videojs.Youtube.prototype.muted=function(){return this.mutedVal},videojs.Youtube.prototype.setMuted=function(muted){muted?(this.ytplayer.mute(),this.player_.volume(0)):(this.ytplayer.unMute(),this.player_.volume(this.volumeVal)),this.mutedVal=muted,this.player_.trigger("volumechange")},videojs.Youtube.prototype.buffered=function(){if(this.ytplayer&&this.ytplayer.getVideoBytesLoaded){var loadedBytes=this.ytplayer.getVideoBytesLoaded(),totalBytes=this.ytplayer.getVideoBytesTotal();if(!loadedBytes||!totalBytes)return 0;var duration=this.ytplayer.getDuration(),secondsBuffered=loadedBytes/totalBytes*duration,secondsOffset=this.ytplayer.getVideoStartBytes()/totalBytes*duration;return videojs.createTimeRange(secondsOffset,secondsOffset+secondsBuffered)}return videojs.createTimeRange(0,0)},videojs.Youtube.prototype.supportsFullScreen=function(){return!0},videojs.Youtube.isSupported=function(){return!0},videojs.Youtube.canPlaySource=function(srcObj){return"video/youtube"===srcObj.type},videojs.Youtube.canControlVolume=function(){return!0},videojs.Youtube.loadingQueue=[],videojs.Youtube.prototype.loadYoutube=function(){this.ytplayer=new YT.Player(this.id_,{events:{onReady:function(e){e.target.vjsTech.onReady()},onStateChange:function(e){e.target.vjsTech.onStateChange(e.data)},onPlaybackQualityChange:function(e){e.target.vjsTech.onPlaybackQualityChange(e.data)},onError:function(e){e.target.vjsTech.onError(e.data)}}}),this.ytplayer.vjsTech=this},videojs.Youtube.makeQueryString=function(args){var array=[];for(var key in args)args.hasOwnProperty(key)&&array.push(key+"="+args[key]);return array.join("&")},window.onYouTubeIframeAPIReady=function(){for(var yt;yt=videojs.Youtube.loadingQueue.shift();)yt.loadYoutube();videojs.Youtube.loadingQueue=[],videojs.Youtube.apiReady=!0},videojs.Youtube.prototype.onReady=function(){this.isReady_=!0,this.triggerReady(),this.player_.trigger("loadedmetadata"),this.player_.trigger("durationchange"),this.player_.trigger("timeupdate"),"undefined"!=typeof this.player_.loadingSpinner&&this.player_.loadingSpinner.hide(),this.player_.options().muted&&this.setMuted(!0),this.playOnReady&&(this.playOnReady=!1,this.play())},videojs.Youtube.prototype.updateQualities=function(){function setupEventListener(el){addEventListener(el,"click",function(){var quality=this.getAttribute("data-val");self.ytplayer.setPlaybackQuality(quality),self.userQuality=quality,setInnerText(self.qualityTitle,videojs.Youtube.parseQualityName(quality));var selected=self.qualityMenuContent.querySelector(".vjs-selected");selected&&videojs.Youtube.removeClass(selected,"vjs-selected"),videojs.Youtube.addClass(this,"vjs-selected")})}var qualities=this.ytplayer.getAvailableQualityLevels(),self=this;if(qualities.indexOf(this.userQuality)<0&&setInnerText(self.qualityTitle,videojs.Youtube.parseQualityName(this.defaultQuality)),0===qualities.length)this.qualityButton.style.display="none";else{for(this.qualityButton.style.display="";this.qualityMenuContent.hasChildNodes();)this.qualityMenuContent.removeChild(this.qualityMenuContent.lastChild);for(var i=0;i=0;i--)classNames[i]===classToRemove&&classNames.splice(i,1);element.className=classNames.join(" ")}};var style=document.createElement("style"),def=" .vjs-youtube .vjs-poster { background-size: 100%!important; }.vjs-youtube .vjs-poster, .vjs-youtube .vjs-loading-spinner, .vjs-youtube .vjs-text-track-display{ pointer-events: none !important; }.vjs-youtube.vjs-user-active .iframeblocker { display: none; }.vjs-youtube.vjs-user-inactive .vjs-tech.onDesktop { pointer-events: none; }.vjs-quality-button > div:first-child > span:first-child { position:relative;top:7px }";style.setAttribute("type","text/css"),document.getElementsByTagName("head")[0].appendChild(style),style.styleSheet?style.styleSheet.cssText=def:style.appendChild(document.createTextNode(def)),Array.prototype.indexOf||(Array.prototype.indexOf=function(elt){var len=this.length>>>0,from=Number(arguments[1])||0;for(from=0>from?Math.ceil(from):Math.floor(from),0>from&&(from+=len);len>from;from++)if(from in this&&this[from]===elt)return from;return-1})}(); \ No newline at end of file +/* global videojs, YT */ +/* jshint browser: true */ + +(function() { + /** + * @fileoverview YouTube Media Controller - Wrapper for YouTube Media API + */ + + /** + * YouTube Media Controller - Wrapper for YouTube Media API + * @param {videojs.Player|Object} player + * @param {Object=} options + * @param {Function=} ready + * @constructor + */ + + function addEventListener(element, event, cb) { + if(!element.addEventListener) { + element.attachEvent(event, cb); + } else { + element.addEventListener(event, cb, true); + } + } + + videojs.Youtube = videojs.MediaTechController.extend({ + /** @constructor */ + init: function(player, options, ready) { + // Save this for internal usage + this.player_ = player; + + // No event is triggering this for YouTube + this['featuresProgressEvents'] = false; + this['featuresTimeupdateEvents'] = false; + // Enable rate changes + this['featuresPlaybackRate'] = true; + + videojs.MediaTechController.call(this, player, options, ready); + + this.isIos = /(iPad|iPhone|iPod)/g.test( navigator.userAgent ); + this.isAndroid = /(Android)/g.test( navigator.userAgent ); + //used to prevent play events on IOS7 and Android > 4.2 until the user has clicked the player + this.playVideoIsAllowed = !(this.isIos || this.isAndroid); + + // autoplay is disabled for mobile + if (this.isIos || this.isAndroid) { + this.player_.options()['autoplay'] = false; + } + + // Copy the JavaScript options if they exists + if(typeof options['source'] !== 'undefined') { + for(var key in options['source']) { + if(options['source'].hasOwnProperty(key)) { + player.options()[key] = options['source'][key]; + } + } + } + + this.userQuality = videojs.Youtube.convertQualityName(player.options()['quality']); + + this.playerEl_ = document.getElementById(player.id()); + this.playerEl_.className += ' vjs-youtube'; + + // Create the Quality button + this.qualityButton = document.createElement('div'); + this.qualityButton.setAttribute('class', 'vjs-quality-button vjs-menu-button vjs-control'); + this.qualityButton.setAttribute('tabindex', 0); + + var qualityContent = document.createElement('div'); + qualityContent.setAttribute('class', 'vjs-control-content'); + this.qualityButton.appendChild(qualityContent); + + this.qualityTitle = document.createElement('span'); + this.qualityTitle.setAttribute('class', 'vjs-control-text'); + qualityContent.appendChild(this.qualityTitle); + + if(player.options()['quality'] !== 'undefined') { + setInnerText(this.qualityTitle, player.options()['quality'] || 'auto'); + } + + var qualityMenu = document.createElement('div'); + qualityMenu.setAttribute('class', 'vjs-menu'); + qualityContent.appendChild(qualityMenu); + + this.qualityMenuContent = document.createElement('ul'); + this.qualityMenuContent.setAttribute('class', 'vjs-menu-content'); + qualityMenu.appendChild(this.qualityMenuContent); + + this.id_ = this.player_.id() + '_youtube_api'; + + this.el_ = videojs.Component.prototype.createEl('iframe', { + id: this.id_, + className: 'vjs-tech', + scrolling: 'no', + marginWidth: 0, + marginHeight: 0, + frameBorder: 0 + }); + + this.el_.setAttribute('allowFullScreen', ''); + + this.playerEl_.insertBefore(this.el_, this.playerEl_.firstChild); + + if(/MSIE (\d+\.\d+);/.test(navigator.userAgent)) { + var ieVersion = Number(RegExp.$1); + this.addIframeBlocker(ieVersion); + } else if(!/(iPad|iPhone|iPod|Android)/g.test(navigator.userAgent)) { + // the pointer-events: none block the mobile player + this.el_.className += ' onDesktop'; + this.addIframeBlocker(); + } + + this.parseSrc(player.options()['src']); + + this.playOnReady = this.player_.options()['autoplay'] && this.playVideoIsAllowed; + this.forceSSL = !!( + typeof this.player_.options()['forceSSL'] === 'undefined' || + this.player_.options()['forceSSL'] === true + ); + this.forceHTML5 = !!( + typeof this.player_.options()['forceHTML5'] === 'undefined' || + this.player_.options()['forceHTML5'] === true + ); + + this.updateIframeSrc(); + + var self = this; + + player.ready(function() { + if (self.player_.options()['controls']) { + var controlBar = self.playerEl_.querySelectorAll('.vjs-control-bar')[0]; + if (controlBar) { + controlBar.appendChild(self.qualityButton); + } + } + + if(self.playOnReady && !self.player_.options()['ytcontrols']) { + if(typeof self.player_.loadingSpinner !== 'undefined') { + self.player_.loadingSpinner.show(); + } + if(typeof self.player_.bigPlayButton !== 'undefined') { + self.player_.bigPlayButton.hide(); + } + } + + player.trigger('loadstart'); + }); + + this.on('dispose', function() { + if(this.ytplayer) { + this.ytplayer.destroy(); + } + + if(!this.player_.options()['ytcontrols']) { + this.player_.off('waiting', this.bindedWaiting); + } + + // Remove the poster + this.playerEl_.querySelectorAll('.vjs-poster')[0].style.backgroundImage = 'none'; + + // If still connected to the DOM, remove it. + if(this.el_.parentNode) { + this.el_.parentNode.removeChild(this.el_); + } + + // Get rid of the created DOM elements + if (this.qualityButton.parentNode) { + this.qualityButton.parentNode.removeChild(this.qualityButton); + } + + if(typeof this.player_.loadingSpinner !== 'undefined') { + this.player_.loadingSpinner.hide(); + } + if(typeof this.player_.bigPlayButton !== 'undefined') { + this.player_.bigPlayButton.hide(); + } + + if(this.iframeblocker) { + this.playerEl_.removeChild(this.iframeblocker); + } + }); + } + }); + + videojs.Youtube.prototype.updateIframeSrc = function() { + var params = { + enablejsapi: 1, + /*jshint -W106 */ + iv_load_policy: 3, + /*jshint +W106 */ + playerapiid: this.id(), + disablekb: 1, + wmode: 'transparent', + controls: (this.player_.options()['ytcontrols']) ? 1 : 0, + html5: (this.player_.options()['forceHTML5']) ? 1 : null, + playsinline: (this.player_.options()['playsInline']) ? 1 : 0, + showinfo: 0, + rel: 0, + autoplay: (this.playOnReady) ? 1 : 0, + loop: (this.player_.options()['loop']) ? 1 : 0, + list: this.playlistId, + vq: this.userQuality, + origin: window.location.protocol + '//' + window.location.host + }; + + // When running with no Web server, we can't specify the origin or it will break the YouTube API messages + if(window.location.protocol === 'file:') { + delete params.origin; + } + + // Delete unset properties + for(var prop in params) { + if(params.hasOwnProperty(prop) && + ( typeof params[ prop ] === 'undefined' || params[ prop ] === null ) + ) { + delete params[ prop ]; + } + } + var self = this; + + if(!this.videoId) { + this.el_.src = 'about:blank'; + setTimeout(function() { + self.triggerReady(); + }, 500); + } else { + this.el_.src = ( + (this.forceSSL || window.location.protocol === 'file:') ? + 'https:' + : window.location.protocol + ) + '//www.youtube.com/embed/' + this.videoId + '?' + videojs.Youtube.makeQueryString(params); + + if(this.player_.options()['ytcontrols']) { + // Disable the video.js controls if we use the YouTube controls + this.player_.controls(false); + } else if(typeof this.player_.poster() === 'undefined' || this.player_.poster().length === 0) { + // Wait here because the tech is still null in constructor + setTimeout(function() { + self.player_.poster('https://img.youtube.com/vi/' + self.videoId + '/0.jpg'); + }, 100); + } + + this.bindedWaiting = function() { + self.onWaiting(); + }; + + this.player_.on('waiting', this.bindedWaiting); + + if(videojs.Youtube.apiReady) { + this.loadYoutube(); + } else { + // Add to the queue because the YouTube API is not ready + videojs.Youtube.loadingQueue.push(this); + + // Load the YouTube API if it is the first YouTube video + if(!videojs.Youtube.apiLoading) { + var tag = document.createElement('script'); + tag.onerror = function(e) { + self.onError(e); + }; + tag.src = ( !this.forceSSL && window.location.protocol !== 'file:' ) ? + '//www.youtube.com/iframe_api' + : 'https://www.youtube.com/iframe_api'; + var firstScriptTag = document.getElementsByTagName('script')[0]; + firstScriptTag.parentNode.insertBefore(tag, firstScriptTag); + videojs.Youtube.apiLoading = true; + } + } + } + }; + + videojs.Youtube.prototype.onWaiting = function(/*e*/) { + // Make sure to hide the play button while the spinner is there + if(typeof this.player_.bigPlayButton !== 'undefined') { + this.player_.bigPlayButton.hide(); + } + }; + + videojs.Youtube.prototype.addIframeBlocker = function(ieVersion) { + this.iframeblocker = videojs.Component.prototype.createEl('div'); + + this.iframeblocker.className = 'iframeblocker'; + + this.iframeblocker.style.position = 'absolute'; + this.iframeblocker.style.left = 0; + this.iframeblocker.style.right = 0; + this.iframeblocker.style.top = 0; + this.iframeblocker.style.bottom = 0; + + // Odd quirk for IE8 (doesn't support rgba) + if(ieVersion && ieVersion < 9) { + this.iframeblocker.style.opacity = 0.01; + } else { + this.iframeblocker.style.background = 'rgba(255, 255, 255, 0.01)'; + } + + var self = this; + addEventListener(this.iframeblocker, 'mousemove', function(e) { + if(!self.player_.userActive()) { + self.player_.userActive(true); + } + + e.stopPropagation(); + e.preventDefault(); + }); + + addEventListener(this.iframeblocker, 'click', function(/*e*/) { + if(self.paused()) { + self.play(); + } else { + self.pause(); + } + }); + + this.playerEl_.insertBefore(this.iframeblocker, this.el_.nextSibling); + }; + + videojs.Youtube.prototype.parseSrc = function(src) { + this.srcVal = src; + + if(src) { + // Regex to parse the video ID + var regId = /^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|\&v=)([^#\&\?]*).*/; + var match = src.match(regId); + + if(match && match[2].length === 11) { + this.videoId = match[2]; + } else { + this.videoId = null; + } + + // Regex to parse the playlist ID + var regPlaylist = /[?&]list=([^#\&\?]+)/; + match = src.match(regPlaylist); + + if(match !== null && match.length > 1) { + this.playlistId = match[1]; + } else { + // Make sure their is no playlist + if(this.playlistId) { + delete this.playlistId; + } + } + + // Parse video quality option + var regVideoQuality = /[?&]vq=([^#\&\?]+)/; + match = src.match(regVideoQuality); + + if(match !== null && match.length > 1) { + this.userQuality = match[1]; + setInnerText(this.qualityTitle, videojs.Youtube.parseQualityName(this.userQuality)); + } + } + }; + + videojs.Youtube.prototype.src = function(src) { + if(typeof src !== 'undefined') { + this.parseSrc(src); + + if(this.el_.src === 'about:blank') { + this.updateIframeSrc(); + return; + } + + delete this.defaultQuality; + + if(this.videoId !== null) { + if(this.player_.options()['autoplay'] && this.playVideoIsAllowed) { + this.ytplayer.loadVideoById({ + videoId: this.videoId, + suggestedQuality: this.userQuality + }); + } else { + this.ytplayer.cueVideoById({ + videoId: this.videoId, + suggestedQuality: this.userQuality + }); + } + + // Update the poster + this.playerEl_.querySelectorAll('.vjs-poster')[0].style.backgroundImage = + 'url(https://img.youtube.com/vi/' + this.videoId + '/0.jpg)'; + this.player_.poster('https://img.youtube.com/vi/' + this.videoId + '/0.jpg'); + } + /* else Invalid URL */ + } + + return this.srcVal; + }; + + videojs.Youtube.prototype.load = function() { + }; + + videojs.Youtube.prototype.play = function() { + if(this.videoId !== null) { + + // Make sure to not display the spinner for mobile + if(!this.player_.options()['ytcontrols']) { + // Display the spinner until the video is playing by YouTube + this.player_.trigger('waiting'); + } + + if(this.isReady_) { + // Sync the player volume with YouTube + this.ytplayer.setVolume(this.player_.volume() * 100); + + if(this.volumeVal > 0) { + this.ytplayer.unMute(); + } else { + this.ytplayer.mute(); + } + + if(this.playVideoIsAllowed) { + this.ytplayer.playVideo(); + } + } else { + this.playOnReady = true; + } + } + }; + + videojs.Youtube.prototype.pause = function() { + this.ytplayer.pauseVideo(); + }; + videojs.Youtube.prototype.paused = function() { + return (this.ytplayer) ? + (this.lastState !== YT.PlayerState.PLAYING && this.lastState !== YT.PlayerState.BUFFERING) + : true; + }; + videojs.Youtube.prototype.currentTime = function() { + return (this.ytplayer && this.ytplayer.getCurrentTime) ? this.ytplayer.getCurrentTime() : 0; + }; + videojs.Youtube.prototype.setCurrentTime = function(seconds) { + this.ytplayer.seekTo(seconds, true); + this.player_.trigger('timeupdate'); + this.player_.trigger('seeking'); + this.isSeeking = true; + }; + videojs.Youtube.prototype.playbackRate = function() { + return (this.ytplayer && this.ytplayer.getPlaybackRate) ? this.ytplayer.getPlaybackRate() : 1.0; + }; + videojs.Youtube.prototype.setPlaybackRate = function(suggestedRate) { + if (this.ytplayer && this.ytplayer.setPlaybackRate) { + this.ytplayer.setPlaybackRate(suggestedRate); + this.player_.trigger('ratechange'); + } + }; + videojs.Youtube.prototype.duration = function() { + return (this.ytplayer && this.ytplayer.getDuration) ? this.ytplayer.getDuration() : 0; + }; + videojs.Youtube.prototype.currentSrc = function() { + return this.srcVal; + }; + videojs.Youtube.prototype.ended = function() { + return (this.ytplayer) ? (this.lastState === YT.PlayerState.ENDED) : false; + }; + + videojs.Youtube.prototype.volume = function() { + if(this.ytplayer && isNaN(this.volumeVal)) { + this.volumeVal = this.ytplayer.getVolume() / 100.0; + this.player_.volume(this.volumeVal); + } + + return this.volumeVal; + }; + + videojs.Youtube.prototype.setVolume = function(percentAsDecimal) { + if(typeof(percentAsDecimal) !== 'undefined' && percentAsDecimal !== this.volumeVal) { + this.ytplayer.setVolume(percentAsDecimal * 100.0); + this.volumeVal = percentAsDecimal; + this.player_.trigger('volumechange'); + } + }; + + videojs.Youtube.prototype.muted = function() { + return this.mutedVal; + }; + videojs.Youtube.prototype.setMuted = function(muted) { + if(muted) { + this.storedVolume = this.volumeVal; + this.ytplayer.mute(); + this.player_.volume(0); + } else { + this.ytplayer.unMute(); + this.player_.volume(this.storedVolume); + } + + this.mutedVal = muted; + + this.player_.trigger('volumechange'); + }; + + videojs.Youtube.prototype.buffered = function() { + if(this.ytplayer && this.ytplayer.getVideoBytesLoaded) { + var loadedBytes = this.ytplayer.getVideoBytesLoaded(); + var totalBytes = this.ytplayer.getVideoBytesTotal(); + if(!loadedBytes || !totalBytes) { + return 0; + } + + var duration = this.ytplayer.getDuration(); + var secondsBuffered = (loadedBytes / totalBytes) * duration; + var secondsOffset = (this.ytplayer.getVideoStartBytes() / totalBytes) * duration; + + return videojs.createTimeRange(secondsOffset, secondsOffset + secondsBuffered); + } else { + return videojs.createTimeRange(0, 0); + } + }; + + videojs.Youtube.prototype.supportsFullScreen = function() { + if (typeof this.el_.webkitEnterFullScreen === 'function') { + + // Seems to be broken in Chromium/Chrome && Safari in Leopard + if (/Android/.test(videojs.USER_AGENT) || !/Chrome|Mac OS X 10.5/.test(videojs.USER_AGENT)) { + return true; + } + } + return false; + }; + + // YouTube is supported on all platforms + videojs.Youtube.isSupported = function() { + return true; + }; + + // You can use video/youtube as a media in your HTML5 video to specify the source + videojs.Youtube.canPlaySource = function(srcObj) { + return (srcObj.type === 'video/youtube'); + }; + + // Always can control the volume + videojs.Youtube.canControlVolume = function() { + return true; + }; + + ////////////////////////////// YouTube specific functions ////////////////////////////// + + // All videos created before YouTube API is loaded + videojs.Youtube.loadingQueue = []; + + // Create the YouTube player + videojs.Youtube.prototype.loadYoutube = function() { + this.ytplayer = new YT.Player(this.id_, { + events: { + onReady: function(e) { + e.target.vjsTech.onReady(); + }, + onStateChange: function(e) { + e.target.vjsTech.onStateChange(e.data); + }, + onPlaybackQualityChange: function(e) { + e.target.vjsTech.onPlaybackQualityChange(e.data); + }, + onError: function(e) { + e.target.vjsTech.onError(e.data); + } + } + }); + + this.ytplayer.vjsTech = this; + }; + + // Transform a JavaScript object into URL params + videojs.Youtube.makeQueryString = function(args) { + var array = ['modestbranding=1']; + for(var key in args) { + if(args.hasOwnProperty(key)) { + array.push(key + '=' + args[key]); + } + } + + return array.join('&'); + }; + + // Called when YouTube API is ready to be used + window.onYouTubeIframeAPIReady = function() { + var yt; + while((yt = videojs.Youtube.loadingQueue.shift())) { + yt.loadYoutube(); + } + videojs.Youtube.loadingQueue = []; + videojs.Youtube.apiReady = true; + }; + + videojs.Youtube.prototype.onReady = function() { + this.isReady_ = true; + this.triggerReady(); + + this.player_.trigger('loadedmetadata'); + + // The duration is loaded so we might as well fire off the timeupdate and duration events + // this allows for the duration of the video (timeremaining) to be displayed if styled + // to show the control bar initially. This gives the user the ability to see how long the video + // is before clicking play + this.player_.trigger('durationchange'); + this.player_.trigger('timeupdate'); + + // Let the player take care of itself as soon as the YouTube is ready + // The loading spinner while waiting for the tech would be impossible otherwise + if (typeof this.player_.loadingSpinner !== 'undefined' && !this.isIos && !this.isAndroid) { + this.player_.loadingSpinner.hide(); + } + + if(this.player_.options()['muted']) { + this.setMuted(true); + } + + // Play ASAP if they clicked play before it's ready + if(this.playOnReady) { + this.playOnReady = false; + this.play(); + } + }; + + videojs.Youtube.prototype.updateQualities = function() { + + function setupEventListener(el) { + addEventListener(el, 'click', function() { + var quality = this.getAttribute('data-val'); + self.ytplayer.setPlaybackQuality(quality); + + self.userQuality = quality; + setInnerText(self.qualityTitle, videojs.Youtube.parseQualityName(quality)); + + var selected = self.qualityMenuContent.querySelector('.vjs-selected'); + if(selected) { + videojs.Youtube.removeClass(selected, 'vjs-selected'); + } + + videojs.Youtube.addClass(this, 'vjs-selected'); + }); + } + + var qualities = this.ytplayer.getAvailableQualityLevels(); + var self = this; + + if(qualities.indexOf(this.userQuality) < 0) { + setInnerText(self.qualityTitle, videojs.Youtube.parseQualityName(this.defaultQuality)); + } + + if(qualities.length === 0) { + this.qualityButton.style.display = 'none'; + } else { + this.qualityButton.style.display = ''; + + while(this.qualityMenuContent.hasChildNodes()) { + this.qualityMenuContent.removeChild(this.qualityMenuContent.lastChild); + } + + for(var i = 0; i < qualities.length; ++i) { + var el = document.createElement('li'); + el.setAttribute('class', 'vjs-menu-item'); + setInnerText(el, videojs.Youtube.parseQualityName(qualities[i])); + el.setAttribute('data-val', qualities[i]); + if(qualities[i] === this.quality) { + videojs.Youtube.addClass(el, 'vjs-selected'); + } + setupEventListener(el); + + + this.qualityMenuContent.appendChild(el); + } + } + }; + + videojs.Youtube.prototype.onStateChange = function(state) { + if(state !== this.lastState) { + switch(state) { + case -1: + this.player_.trigger('durationchange'); + break; + + case YT.PlayerState.ENDED: + // Replace YouTube play button by our own + if(!this.player_.options()['ytcontrols']) { + this.playerEl_.querySelectorAll('.vjs-poster')[0].style.display = 'block'; + if(typeof this.player_.bigPlayButton !== 'undefined') { + this.player_.bigPlayButton.show(); + } + } + + this.player_.trigger('ended'); + break; + + case YT.PlayerState.PLAYING: + this.playerEl_.querySelectorAll('.vjs-poster')[0].style.display = ''; + + this.playVideoIsAllowed = true; + this.updateQualities(); + this.player_.trigger('timeupdate'); + this.player_.trigger('durationchange'); + this.player_.trigger('playing'); + this.player_.trigger('play'); + + if (this.isSeeking) { + this.player_.trigger('seeked'); + this.isSeeking = false; + } + break; + + case YT.PlayerState.PAUSED: + this.player_.trigger('pause'); + break; + + case YT.PlayerState.BUFFERING: + this.player_.trigger('timeupdate'); + + // Make sure to not display the spinner for mobile + if(!this.player_.options()['ytcontrols']) { + this.player_.trigger('waiting'); + } + break; + + case YT.PlayerState.CUED: + break; + } + + this.lastState = state; + } + }; + + videojs.Youtube.convertQualityName = function(name) { + switch(name) { + case '144p': + return 'tiny'; + + case '240p': + return 'small'; + + case '360p': + return 'medium'; + + case '480p': + return 'large'; + + case '720p': + return 'hd720'; + + case '1080p': + return 'hd1080'; + } + + return 'auto'; + }; + + videojs.Youtube.parseQualityName = function(name) { + switch(name) { + case 'tiny': + return '144p'; + + case 'small': + return '240p'; + + case 'medium': + return '360p'; + + case 'large': + return '480p'; + + case 'hd720': + return '720p'; + + case 'hd1080': + return '1080p'; + } + + return 'auto'; + }; + + videojs.Youtube.prototype.onPlaybackQualityChange = function(quality) { + if(typeof this.defaultQuality === 'undefined') { + this.defaultQuality = quality; + + if(typeof this.userQuality !== 'undefined') { + return; + } + } + + this.quality = quality; + setInnerText(this.qualityTitle, videojs.Youtube.parseQualityName(quality)); + + switch(quality) { + case 'medium': + this.player_.videoWidth = 480; + this.player_.videoHeight = 360; + break; + + case 'large': + this.player_.videoWidth = 640; + this.player_.videoHeight = 480; + break; + + case 'hd720': + this.player_.videoWidth = 960; + this.player_.videoHeight = 720; + break; + + case 'hd1080': + this.player_.videoWidth = 1440; + this.player_.videoHeight = 1080; + break; + + case 'highres': + this.player_.videoWidth = 1920; + this.player_.videoHeight = 1080; + break; + + case 'small': + this.player_.videoWidth = 320; + this.player_.videoHeight = 240; + break; + + case 'tiny': + this.player_.videoWidth = 144; + this.player_.videoHeight = 108; + break; + + default: + this.player_.videoWidth = 0; + this.player_.videoHeight = 0; + break; + } + + this.player_.trigger('ratechange'); + }; + + videojs.Youtube.prototype.onError = function(error) { + this.player_.error(error); + + if(error === 100 || error === 101 || error === 150) { + this.player_.bigPlayButton.hide(); + this.player_.loadingSpinner.hide(); + this.player_.posterImage.hide(); + } + }; + + /** + * Add a CSS class name to an element + * @param {Element} element Element to add class name to + * @param {String} classToAdd Classname to add + */ + videojs.Youtube.addClass = function(element, classToAdd) { + if((' ' + element.className + ' ').indexOf(' ' + classToAdd + ' ') === -1) { + element.className = element.className === '' ? classToAdd : element.className + ' ' + classToAdd; + } + }; + + /** + * Remove a CSS class name from an element + * @param {Element} element Element to remove from class name + * @param {String} classToRemove Classname to remove + */ + videojs.Youtube.removeClass = function(element, classToRemove) { + var classNames, i; + + if(element.className.indexOf(classToRemove) === -1) { + return; + } + + classNames = element.className.split(' '); + + // no arr.indexOf in ie8, and we don't want to add a big shim + for(i = classNames.length - 1; i >= 0; i--) { + if(classNames[i] === classToRemove) { + classNames.splice(i, 1); + } + } + + element.className = classNames.join(' '); + }; + + // Cross-browsers support (IE8 wink wink) + function setInnerText(element, text) { + if(typeof element === 'undefined') { + return false; + } + + var textProperty = ('innerText' in element) ? 'innerText' : 'textContent'; + + try { + element[textProperty] = text; + } catch(anException) { + //IE<9 FIX + element.setAttribute('innerText', text); + } + } + + +// Stretch the YouTube poster + var style = document.createElement('style'); + var def = ' ' + + '.vjs-youtube .vjs-poster { background-size: 100%!important; }' + + '.vjs-youtube .vjs-poster, ' + + '.vjs-youtube .vjs-loading-spinner, ' + + '.vjs-youtube .vjs-big-play-button, .vjs-youtube .vjs-text-track-display{ pointer-events: none !important; }' + + '.vjs-youtube.vjs-user-active .iframeblocker { display: none; }' + + '.vjs-youtube.vjs-user-inactive .vjs-tech.onDesktop { pointer-events: none; }' + + '.vjs-quality-button > div:first-child > span:first-child { position:relative;top:7px }'; + + style.setAttribute('type', 'text/css'); + document.getElementsByTagName('head')[0].appendChild(style); + + if(style.styleSheet) { + style.styleSheet.cssText = def; + } else { + style.appendChild(document.createTextNode(def)); + } + + // IE8 fix for indexOf + if(!Array.prototype.indexOf) { + Array.prototype.indexOf = function(elt /*, from*/) { + var len = this.length >>> 0; // jshint ignore:line + + var from = Number(arguments[1]) || 0; + from = (from < 0) ? + Math.ceil(from) + : Math.floor(from); + if(from < 0) { + from += len; + } + + for(; from < len; from++) { + if(from in this && this[from] === elt) { + return from; + } + } + return -1; + }; + } +})(); diff --git a/plugins/video/public/style.css b/plugins/video/public/style.css index 4c9f1cf..5fd2e3c 100644 --- a/plugins/video/public/style.css +++ b/plugins/video/public/style.css @@ -38,5 +38,23 @@ } .video-gallery-thumbnail:hover div{ - display: inline-block; + display: inline-block; +} + +.video-gallery-table-big{ + width: 100%; + overflow: hidden; +} + +.video-gallery-left-column-big{ + width: 350px; + float: left; +} + +.video-gallery-right-column-big{ + margin-left: 370px; +} + +.video-title-big{ + font-size: 2em; } \ No newline at end of file diff --git a/plugins/video/views/content_viewer/video_plugin/_video.html.erb b/plugins/video/views/content_viewer/video_plugin/_video.html.erb index a2bf68b..26d34cc 100644 --- a/plugins/video/views/content_viewer/video_plugin/_video.html.erb +++ b/plugins/video/views/content_viewer/video_plugin/_video.html.erb @@ -1,7 +1,7 @@
<%if @page.video_provider=='youtube' %> -