1/** 2 * jquery.youtubeplaylist.js 3 * 4 * By Dan Drayne 5 * https://github.com/dan0/youtubeplaylist/ 6 * 7 * Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php 8 */ 9 10(function ( $, window, document, undefined ) { 11 12 var pluginName = 'ytplaylist'; 13 var defaults = { 14 holderId: 'ytvideo', 15 playerHeight: 300, 16 playerWidth: 450, 17 addThumbs: false, 18 thumbSize: 'small', 19 showInline: false, 20 autoPlay: true, 21 showRelated: true, 22 allowFullScreen: false, 23 deepLinks: false, 24 onChange: function(){ 25 console.log(this); 26 $('html, body').animate({ 27 scrollTop: $("#" + this.options.holderId).offset().top 28 }, 200); 29 }, 30 start: 1, 31 secure: 'auto' //false|true|'auto' 32 }; 33 34 35 /** 36 * Get a youtube id from a url 37 * 38 * @param {String} url Url to youtube video. 39 * @return {String|Null} Id of video, or null if none found. 40 */ 41 42 function youtubeid(url) { 43 var id = null; 44 if (url.indexOf('//www.youtube.com') !== -1) { 45 id = url.match("[\\?&]v=([^&#]*)")[1]; 46 } 47 else if (url.indexOf('//youtu.be') !== -1){ 48 id = url.substr(url.lastIndexOf("/") + 1); 49 } 50 return id; 51 } 52 53 54 /** 55 * Main plugin contstructor 56 * 57 * @param {Object} element object representing UL element. 58 * @param {Object} options Options object. 59 */ 60 61 function Plugin(element, options ) { 62 this.element = element; 63 this.options = $.extend( {}, defaults, options) ; 64 this._defaults = defaults; 65 this._name = pluginName; 66 67 this._protocol = (this.options.secure === 'auto') ? window.location.protocol === 'https:' ? 'https://' : 'http://' : 68 this.options.secure ? 'https://' : 'http://'; 69 this._autoPlay = (this.options.autoPlay) ? '&autoplay=1' : ''; 70 this._showRelated = (this.options.showRelated) ? '&rel=1' : ''; 71 this._fullscreen = (this.options.allowFullScreen) ? '&fs=1' : ''; 72 this.init(); 73 } 74 75 76 Plugin.prototype = { 77 78 /** 79 * Initialise gallery 80 * 81 * Loop through <li> elements, setting up click 82 * handlers etc. 83 */ 84 85 init: function() { 86 var self = this; 87 var initialItem = self.options.deepLinks && window.location.hash.indexOf('#yt-gal-') !== -1 ? window.location.hash : null; 88 // Setup initial classification of content 89 $(self.element).find('li').each(function(index) { 90 91 var listItem = $(this); 92 var listIndex = index + 1; 93 94 listItem.find('a:first').each(function() { 95 96 var link = $(this); 97 var ytid = youtubeid(link.attr('href')); 98 var replacedText = listItem.text(); 99 100 link.data('yt-href', link.attr('href')); 101 link.attr('href', '#yt-gal-' + listIndex); 102 103 if (ytid) { 104 105 link.addClass('yt-vid'); 106 link.data('yt-id', ytid); 107 if (self.options.addThumbs) { 108 109 if(self.options.thumbSize == 'small') { 110 thumbUrl = self._protocol + 'img.youtube.com/vi/' + ytid + '/2.jpg'; 111 } 112 else { 113 thumbUrl = self._protocol + 'img.youtube.com/vi/' + ytid + '/0.jpg'; 114 } 115 var thumbHtml = '<img src="' + thumbUrl + '" alt="' + replacedText + '" />'; 116 link.empty().html(thumbHtml + replacedText).attr('title', replacedText); 117 } 118 } 119 else { 120 //must be an image link (naive) 121 link.addClass('img-link'); 122 if (self.options.addThumbs) { 123 var $img = $('<img/>').attr('src', link.data('yt-href')); 124 link.empty().html($img).attr("title", replacedText); 125 } 126 127 } 128 129 if (!self.options.deepLinks) { 130 link.click(function(e) { 131 e.preventDefault(); 132 self.handleClick(link, self.options); 133 self.options.onChange.apply(self); 134 }); 135 } 136 137 }); 138 139 var firstLink = $(listItem.children('a')[0]); 140 if (initialItem) { 141 if (firstLink.attr('href') === initialItem) { 142 self.handleClick(firstLink, self.options); 143 } 144 } 145 else if (listIndex === self.options.start) { 146 self.handleClick(firstLink, self.options); 147 } 148 149 }); 150 151 if (self.options.deepLinks) { 152 $(window).bind('hashchange', function(e) { 153 var hash = window.location.hash; 154 var clicked = $(self.element).find('a[href="' + hash + '"]'); 155 if (clicked.length > 0) { 156 self.handleClick(clicked, self.options); 157 } 158 else if (hash === '') { 159 self.handleClick($(self.element).find('a:first'), self.options); 160 } 161 }); 162 } 163 164 }, 165 166 167 /** 168 * Get old-style youtube embed code 169 * 170 * @param {Object} options Plugin options object. 171 * @param {String} id ID of youtube video. 172 * @return {String} HTML embed code. 173 */ 174 175 getOldEmbedCode: function(options, id) { 176 //throw a youtube player in 177 var html = ''; 178
179 html += '<object height="' + options.playerHeight + '" width="' + options.playerWidth + '">'; 180 html += '<param name="movie" value="' + this._protocol + 'www.youtube.com/v/' + id + this._autoPlay + this._showRelated + this._fullScreen + '"> </param>'; 181 html += '<param name="wmode" value="transparent"> </param>'; 182 if(options.allowFullScreen) { 183 html += '<param name="allowfullscreen" value="true"> </param>'; 184 } 185 html += '<embed src="' + this._protocol + 'www.youtube.com/v/' + id + this._autoPlay + this._showRelated + this._fullScreen + '"'; 186 if(options.allowFullScreen) { 187 html += ' allowfullscreen="true" '; 188 } 189 html += 'type="application/x-shockwave-flash" wmode="transparent" height="' + options.playerHeight + '" width="' + options.playerWidth + '"></embed>'; 190 html += '</object>'; 191 192 return html; 193 }, 194 195 196 /** 197 * Get new-style youtube embed code 198 * 199 * @param {Object} options Plugin options object. 200 * @param {String} id ID of youtube video. 201 * @return {String} HTML embed code. 202 */ 203 204 getNewEmbedCode: function(options, id) { 205 var html = ''; 206 html += '<iframe title="YouTube video player" width="' + options.playerWidth + '" height="' + options.playerHeight + '"'; 207 html += ' src="' + this._protocol + 'www.youtube.com/embed/' + id + '?wmode=opaque&rel=0' + this._showRelated + '" frameborder="0"'; 208 html += ' allowfullscreen></iframe>'; 209 210 return html; 211 }, 212 213 214 /** 215 * Handle clicks on all items 216 * 217 * @param {Object} link jQuery object representing clicked link. 218 * @param {Object} options Plugin options object. 219 * @return {Function} Appropriate handler function. 220 */ 221 222 handleClick: function(link, options) { 223 if (link.hasClass('yt-vid')) { 224 return this.handleVideoClick(link, options); 225 } 226 else { 227 return this.handleImageClick(link, options); 228 } 229 }, 230 231 232 /** 233 * Handle clicks on video items 234 * 235 * @param {Object} link jQuery object representing clicked link. 236 * @param {Object} options Plugin options object. 237 * @return {Boolean} False, cancelling click event. 238 */ 239 240 handleVideoClick: function(link, options) { 241 var self = this; 242 if(options.showInline) { 243 $('li.currentvideo').removeClass('currentvideo'); 244 link.parent('li').addClass('currentvideo').html(self.getNewEmbedCode(self.options, link.data('yt-id'))); 245 } 246 else { 247 var holder = (options.holder ? options.holder : $('#' + options.holderId)); 248 holder.html(self.getNewEmbedCode(self.options, link.data('yt-id'))); 249 link.parent().parent('ul').find('li.currentvideo').removeClass('currentvideo'); 250 link.parent('li').addClass('currentvideo'); 251 } 252 return false; 253 }, 254 255 256 /** 257 * Handle clicks on image items 258 * 259 * @param {Object} link jQuery object representing clicked link. 260 * @param {Object} options Plugin options object. 261 * @return {Boolean} False, cancelling click event. 262 */ 263 264 handleImageClick: function(link, options) { 265 var thisImage = new Image(); 266 var $thisImage = $(thisImage); 267 var $link = $(link); 268 269 thisImage.onload = function() { 270 if ($thisImage.height() < $thisImage.width()) { 271 $thisImage.width(options.playerWidth).css('margin-top',parseInt($thisImage.height()/-2, 10)).css({ 272 height: 'auto' 273 }); 274 } 275 else { 276 $thisImage.css({ 277 height: options.playerHeight, 278 width: 'auto', 279 top: '0px', 280 position: 'relative' 281 }); 282 } 283 $thisImage.fadeIn(); 284 }; 285 286 $thisImage.attr({src:$link.data('yt-href') }) 287 .css({ 288 display: 'none', 289 position: 'absolute', 290 left: '0px', 291 top: '50%'});
292 293 if(options.showInline) { 294 $('li.currentvideo').removeClass('currentvideo'); 295 $link.parent('li').addClass('currentvideo').html($thisImage); 296 } 297 else { 298 var holder = (options.holder ? options.holder : $('#' + options.holderId)); 299 holder.html($thisImage); 300 $link.closest('ul').find('li.currentvideo').removeClass('currentvideo'); 301 $link.parent('li').addClass('currentvideo'); 302 } 303 304 305 306 return false; 307 } 308 }; 309 310 $.fn[pluginName] = function (options) { 311 return this.each(function () { 312 if (!$.data(this, 'plugin_' + pluginName)) { 313 $.data(this, 'plugin_' + pluginName, 314 new Plugin(this, options)); 315 } 316 }); 317 }; 318 319})(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.