1/* jQuery tubular plugin 2|* by Sean McCambridge 3|* http://www.seanmccambridge.com/tubular 4|* version: 1.0 5|* updated: October 1, 2012 6|* since 2010 7|* licensed under the MIT License 8|* Enjoy. 9|* 10|* Thanks, 11|* Sean */ 12 13;(function ($, window) { 14 15 // test for feature support and return if failure 16 17 // defaults 18 var defaults = { 19 ratio: 16/9, // usually either 4/3 or 16/9 -- tweak as needed 20 videoId: 'waTteMeg4Ag', // toy robot in space is a good default, no? 21 mute: true, 22 repeat: true, 23 width: $(window).width(), 24 wrapperZIndex: 99, 25 playButtonClass: 'tubular-play', 26 pauseButtonClass: 'tubular-pause', 27 muteButtonClass: 'tubular-mute', 28 volumeUpClass: 'tubular-volume-up', 29 volumeDownClass: 'tubular-volume-down', 30 increaseVolumeBy: 10, 31 start: 0 32 }; 33 34 // methods 35 36 var tubular = function(node, options) { // should be called on the wrapper div 37 var options = $.extend({}, defaults, options), 38 $body = $('body') // cache body node 39 $node = $(node); // cache wrapper node 40 41 // build container 42 var tubularContainer = '<div class="apps-craft-video-bg-section" style="overflow: hidden; position: absolute; z-index: 99; width: 100%; height: 100vh; top: 0; left: 0;"><div id="tubular-player" style="position: absolute"></div></div><div id="tubular-shield" style="width: 100%; height: 100%; z-index: 2; position: absolute; left: 0; top: 0;"></div>'; 43 44 // set up css prereq's, inject tubular container and set up wrapper defaults 45 $('html,body').css({'width': '100%', 'height': '100vh'}); 46 $body.prepend(tubularContainer); 47 $node.css({position: 'relative', 'z-index': options.wrapperZIndex}); 48 49 // set up iframe player, use global scope so YT api can talk 50 window.player; 51 window.onYouTubeIframeAPIReady = function() { 52 player = new YT.Player('tubular-player', { 53 width: options.width, 54 height: Math.ceil(options.width / options.ratio), 55 videoId: options.videoId, 56 playerVars: { 57 controls: 0, 58 showinfo: 0, 59 modestbranding: 1, 60 wmode: 'transparent' 61 }, 62 events: { 63 'onReady': onPlayerReady, 64 'onStateChange': onPlayerStateChange 65 } 66 }); 67 } 68 69 window.onPlayerReady = function(e) { 70 resize(); 71 if (options.mute) e.target.mute(); 72 e.target.seekTo(options.start); 73 e.target.playVideo(); 74 } 75 76 window.onPlayerStateChange = function(state) { 77 if (state.data === 0 && options.repeat) { // video ended and repeat option is set true 78 player.seekTo(options.start); // restart 79 } 80 } 81 82 // resize handler updates width, height and offset of player after resize/init 83 var resize = function() { 84 var width = $(window).width(), 85 pWidth, // player width, to be defined 86 height = $(window).height(), 87 pHeight, // player height, tbd 88 $tubularPlayer = $('#tubular-player'); 89 90 // when screen aspect ratio differs from video, video must center and underlay one dimension 91 92 if (width / options.ratio < height) { // if new video height < window height (gap underneath) 93 pWidth = Math.ceil(height * options.ratio); // get new player width 94 $tubularPlayer.width(pWidth).height(height).css({left: (width - pWidth) / 2, top: 0}); // player width is greater, offset left; reset top 95 } else { // new video width < window width (gap to right) 96 pHeight = Math.ceil(width / options.ratio); // get new player height 97 $tubularPlayer.width(width).height(pHeight).css({left: 0, top: (height - pHeight) / 2}); // player height is greater, offset top; reset left 98 } 99 100 } 101 102 // events 103 $(window).on('resize.tubular', function() { 104 resize(); 105 }) 106 107 $('body').on('click','.' + options.playButtonClass, function(e) { // play button 108 e.preventDefault(); 109 player.playVideo(); 110 }).on('click', '.' + options.pauseButtonClass, function(e) { // pause button 111 e.preventDefault(); 112 player.pauseVideo(); 113 }).on('click', '.' + options.muteButtonClass, function(e) { // mute button 114 e.preventDefault(); 115 (player.isMuted()) ? player.unMute() : player.mute(); 116 }).on('click', '.' + options.volumeDownClass, function(e) { // volume down button 117 e.preventDefault(); 118 var currentVolume = player.getVolume(); 119 if (currentVolume < options.increaseVolumeBy) currentVolume = options.increaseVolumeBy; 120 player.setVolume(currentVolume - options.increaseVolumeBy); 121 }).on('click', '.' + options.volumeUpClass, function(e) { // volume up button 122 e.preventDefault(); 123 if (player.isMuted()) player.unMute(); // if mute is on, unmute 124 var currentVolume = player.getVolume(); 125 if (currentVolume > 100 - options.increaseVolumeBy) currentVolume = 100 - options.increaseVolumeBy; 126 player.setVolume(currentVolume + options.increaseVolumeBy); 127 }) 128 } 129 130 // load yt iframe js api 131 132 var tag = document.createElement('script'); 133 tag.src = "//www.youtube.com/iframe_api"; 134 var firstScriptTag = document.getElementsByTagName('script')[0]; 135 firstScriptTag.parentNode.insertBefore(tag, firstScriptTag); 136 137 // create plugin 138 139 $.fn.tubular = function (options) { 140 return this.each(function () { 141 if (!$.data(this, 'tubular_instantiated')) { // let's only run one 142 $.data(this, 'tubular_instantiated', 143 tubular(this, options)); 144 } 145 }); 146 } 147 148})(jQuery, window);
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.