1/* 2 * YoutubeBackground - A wrapper for the Youtube API - Great for fullscreen background videos or just regular videos. 3 * 4 * Licensed under the MIT license: 5 * http://www.opensource.org/licenses/mit-license.php 6 * 7 * 8 * Version: 1.0.5 9 * 10 */ 11 12// Chain of Responsibility pattern. Creates base class that can be overridden. 13if (typeof Object.create !== "function") { 14 Object.create = function(obj) { 15 function F() {} 16 F.prototype = obj; 17 return new F(); 18 }; 19} 20 21(function($, window, document) { 22 var 23 loadAPI = function loadAPI(callback) { 24 25 // Load Youtube API 26 var tag = document.createElement('script'), 27 head = document.getElementsByTagName('head')[0]; 28 29 if(window.location.origin == 'file://') { 30 tag.src = 'https://www.youtube.com/iframe_api'; 31 } else { 32 tag.src = '//www.youtube.com/iframe_api'; 33 } 34 35 head.appendChild(tag); 36 37 // Clean up Tags. 38 head = null; 39 tag = null; 40 41 iframeIsReady(callback); 42 }, 43 iframeIsReady = function iframeIsReady(callback) { 44 // Listen for Gobal YT player callback 45 if (typeof YT === 'undefined' && typeof window.loadingPlayer === 'undefined') { 46 // Prevents Ready Event from being called twice 47 window.loadingPlayer = true; 48 49 50 // Creates deferred so, other players know when to wait. 51 window.dfd = $.Deferred(); 52 window.onYouTubeIframeAPIReady = function() { 53 window.onYouTubeIframeAPIReady = null; 54 window.dfd.resolve( "done" ); 55 callback(); 56 }; 57 } else if (typeof YT === 'object') { 58 callback(); 59 } else { 60 window.dfd.done(function( name ) { 61 callback(); 62 }); 63 } 64 }; 65 66 // YTPlayer Object 67 YTPlayer = { 68 player: null, 69 70 // Defaults 71 defaults: { 72 ratio: 16 / 9, 73 videoId: '', 74 mute: false, 75 repeat: true, 76 width: $(window).width(), 77 playButtonClass: 'YTPlayer-play', 78 pauseButtonClass: 'YTPlayer-pause', 79 muteButtonClass: 'YTPlayer-mute', 80 volumeUpClass: 'YTPlayer-volume-up', 81 volumeDownClass: 'YTPlayer-volume-down', 82 start: 0, 83 pauseOnScroll: false, 84 fitToBackground: true, 85 playerVars: { 86 iv_load_policy: 3, 87 modestbranding: 1, 88 autoplay: 0, 89 controls: 0, 90 showinfo: 0, 91 wmode: 'opaque', 92 branding: 0, 93 autohide: 0 94 }, 95 events: null 96 }, 97 98 /** 99 * @function init 100 * Intializes YTPlayer object 101 */ 102 init: function init(node, userOptions) { 103 var self = this; 104 105 self.userOptions = userOptions; 106 107 self.$body = $('body'), 108 self.$node = $(node), 109 self.$window = $(window); 110 111 // Setup event defaults with the reference to this 112 self.defaults.events = { 113 'onReady': function(e) { 114 self.onPlayerReady(e); 115 116 // setup up pause on scroll 117 if (self.options.pauseOnScroll) { 118 self.pauseOnScroll(); 119 } 120 121 // Callback for when finished 122 if (typeof self.options.callback == 'function') { 123 self.options.callback.call(this); 124 } 125 }, 126 'onStateChange': function(e) { 127 if (e.data === 1) { 128 129 self.$node.find('img').fadeOut(400); 130 self.$node.addClass('loaded'); 131 } else if (e.data === 0 && self.options.repeat) { // video ended and repeat option is set true 132 self.player.seekTo(self.options.start); 133 } 134 } 135 } 136 137 138 self.options = $.extend(true, {}, self.defaults, self.userOptions); 139 self.options.height = Math.ceil(self.options.width / self.options.ratio); 140 self.ID = (new Date()).getTime(); 141 self.holderID = 'YTPlayer-ID-' + self.ID; 142 143 if (self.options.fitToBackground) { 144 self.createBackgroundVideo(); 145 } else { 146 self.createContainerVideo(); 147 } 148 // Listen for Resize Event 149 self.$window.on('resize.YTplayer' + self.ID, function() { 150 self.resize(self); 151 }); 152 153 loadAPI(self.onYouTubeIframeAPIReady.bind(self)); 154 155 self.resize(self); 156 157 return self; 158 }, 159 160 161 /** 162 * @function pauseOnScroll 163 * Adds window events to pause video on scroll. 164 */ 165 pauseOnScroll: function pauseOnScroll() { 166 var self = this; 167 self.$window.on('scroll.YTplayer' + self.ID, function() { 168 var state = self.player.getPlayerState(); 169 if (state === 1) { 170 self.player.pauseVideo(); 171 } 172 }); 173 self.$window.scrollStopped(function(){ 174 var state = self.player.getPlayerState(); 175 if (state === 2) { 176 self.player.playVideo(); 177 } 178 }); 179 }, 180 /** 181 * @function createContainerVideo 182 * Adds HTML for video in a container 183 */ 184 createContainerVideo: function createContainerVideo() { 185 var self = this; 186 187 /*jshint multistr: true */ 188 var $YTPlayerString = $('<div id="ytplayer-container' + self.ID + '" >\ 189 <div id="' + self.holderID + '" class="ytplayer-player-inline"></div> \ 190 </div> \ 191 <div id="ytplayer-shield" class="ytplayer-shield"></div>'); 192 193 self.$node.append($YTPlayerString); 194 self.$YTPlayerString = $YTPlayerString; 195 $YTPlayerString = null; 196 }, 197 198 /**
199 * @function createBackgroundVideo 200 * Adds HTML for video background 201 */ 202 createBackgroundVideo: function createBackgroundVideo() { 203 /*jshint multistr: true */ 204 var self = this, 205 $YTPlayerString = $('<div id="ytplayer-container' + self.ID + '" class="ytplayer-container background">\ 206 <div id="' + self.holderID + '" class="ytplayer-player"></div>\ 207 </div>\ 208 <div id="ytplayer-shield" class="ytplayer-shield"></div>'); 209 210 self.$node.append($YTPlayerString); 211 self.$YTPlayerString = $YTPlayerString; 212 $YTPlayerString = null; 213 }, 214 215 /** 216 * @function resize 217 * Resize event to change video size 218 */ 219 resize: function resize(self) { 220 //var self = this; 221 var container = $(window); 222 223 if (!self.options.fitToBackground) { 224 container = self.$node; 225 } 226 227 var width = container.width(), 228 pWidth, // player width, to be defined 229 height = container.height(), 230 pHeight, // player height, tbd 231 $YTPlayerPlayer = $('#' + self.holderID); 232 233 // when screen aspect ratio differs from video, video must center and underlay one dimension 234 if (width / self.options.ratio < height) { 235 pWidth = Math.ceil(height * self.options.ratio); // get new player width 236 $YTPlayerPlayer.width(pWidth).height(height).css({ 237 left: (width - pWidth) / 2, 238 top: 0 239 }); // player width is greater, offset left; reset top 240 } else { // new video width < window width (gap to right) 241 pHeight = Math.ceil(width / self.options.ratio); // get new player height 242 $YTPlayerPlayer.width(width).height(pHeight).css({ 243 left: 0, 244 top: (height - pHeight) / 2 245 }); // player height is greater, offset top; reset left 246 } 247 248 $YTPlayerPlayer = null; 249 container = null; 250 }, 251 252 /** 253 * @function onYouTubeIframeAPIReady 254 * @ params {object} YTPlayer object for access to options 255 * Youtube API calls this function when the player is ready. 256 */ 257 onYouTubeIframeAPIReady: function onYouTubeIframeAPIReady() { 258 var self = this; 259 self.player = new window.YT.Player(self.holderID, self.options); 260 }, 261 262 /** 263 * @function onPlayerReady 264 * @ params {event} window event from youtube player 265 */ 266 // had to add logic to e.target.playVideo(); as it was forcibly playing video regardless of autoplay setting. 267 onPlayerReady: function onPlayerReady(e) { 268 if (this.options.mute) { 269 e.target.mute(); 270 } 271 if (this.options.playerVars.autoplay){ 272 e.target.playVideo(); 273 } 274 }, 275 276 /** 277 * @function getPlayer 278 * returns youtube player 279 */ 280 getPlayer: function getPlayer() { 281 return this.player; 282 }, 283 284 /** 285 * @function destroy 286 * destroys all! 287 */ 288 destroy: function destroy() { 289 var self = this; 290 291 self.$node 292 .removeData('yt-init') 293 .removeData('ytPlayer') 294 .removeClass('loaded'); 295 296 self.$YTPlayerString.remove(); 297 298 $(window).off('resize.YTplayer' + self.ID); 299 $(window).off('scroll.YTplayer' + self.ID); 300 self.$body = null; 301 self.$node = null; 302 self.$YTPlayerString = null; 303 self.player.destroy(); 304 self.player = null; 305 } 306 }; 307 308 // Scroll Stopped event. 309 $.fn.scrollStopped = function(callback) { 310 var $this = $(this), self = this; 311 $this.scroll(function(){ 312 if ($this.data('scrollTimeout')) { 313 clearTimeout($this.data('scrollTimeout')); 314 } 315 $this.data('scrollTimeout', setTimeout(callback,250,self)); 316 }); 317 }; 318 319 // Create plugin 320 $.fn.YTPlayer = function(options) { 321 322 return this.each(function() { 323 var el = this; 324 325 $(el).data("yt-init", true); 326 var player = Object.create(YTPlayer); 327 player.init(el, options); 328 $.data(el, "ytPlayer", player); 329 }); 330 }; 331 332})(jQuery, window, document);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.