1/* 2 * jQuery Infinite Carousel 3 * @author [email protected] - http://www.catchmyfame.com 4 * @version 3.0.3 5 * @date January 24, 2011 6 * @category jQuery plugin 7 * @copyright (c) [email protected] (www.catchmyfame.com) 8 * @license CC Attribution-Share Alike 3.0 - http://creativecommons.org/licenses/by-sa/3.0/ 9 */ 10(function($){ 11 $.fn.extend({ 12 infiniteCarousel: function(options) 13 { 14 var defaults = 15 { 16 transitionSpeed: 800, 17 displayTime: 6000, 18 displayProgressRing: true, 19 progressRingColorOpacity: '0,0,0,.5', 20 progressRingBackgroundOn: true, 21 progressRingBackgroundColorOpacity: '255,255,255,.5', 22 thumbnailType: 'none', // buttons, images, numbers, count, or none 23 easeLeft: 'linear', 24 easeRight: 'linear', 25 imagePath: '/js/infinitecarousel/images/', 26 inView: 1, 27 margin: 0, 28 advance: 1, 29 customClass: null, 30 showControls: true, 31 autoHideCaptions: false, 32 autoPilot: false, 33 prevNextInternal: true, 34 internalThumbnails: false, 35 enableKeyboardNav: true, 36 onSlideStart: function(){}, 37 onSlideEnd: function(){}, 38 onPauseClick: function(){}, 39 onPlayClick: function(){} 40 }; 41 var options = $.extend(defaults, options); 42 43 return this.each(function() { 44 var o=options; 45 var obj = $(this); 46 var randID = Math.round(Math.random()*100000000); 47 48 var numItems = $('li', obj).length; // Number of items 49 var captions=[]; // captions array 50 var links=[]; // links array 51 var itemSources=[]; // sources array 52 var vidThumb=[]; // video thumbnails (supplied by the longdesc attribute in the iframe) 53 var widthSource,heightSource; // width and height of each item 54 var nextLeft,nextRight; // pointers to the next array index for moving left and right 55 var clrTimerInterval; // interval handle variable for timer and autoPilot 56 var u,elapsedTime=0; 57 var canvasSupported = "HTMLCanvasElement" in window; 58 $('li',obj).each(function(index){ // populate arrays 59 captions.push( $('p',this).html() ); 60 links.push( $('a',this).attr('href') ); 61 vidThumb.push( $(this).find('iframe').attr('longdesc') ); 62 itemSources.push( $(this).find('img, iframe').attr('src') ); // finds images and youtube and vimeo iframe sources 63 }); 64 65 // Check for improper values in inview and advance 66 if(o.inView > numItems) o.inView = numItems; // Prevent trying to view more images than given 67 if(o.advance > o.inView) o.advance = o.inView; // Prevent advancing more than inView images at a time 68 69 // Dimensions should be set explicitly on the items so that we don't have to defer loading code until the images are loaded 70 widthSource = $(this).find('img, iframe').width(); 71 heightSource = $(this).find('img, iframe').height(); 72 73 // Build carousel container 74 $(obj).replaceWith('<div class="infiniteCarousel" id="ic_'+randID+'">'); // Kick the list and its content to the curb and replace with a div 75 obj=$('#ic_'+randID); // Reassign the new div as our obj 76 $(obj).height(heightSource).width(widthSource*o.inView).css({'overflow':'hidden','position':'relative'}); 77 78 // Build tray to hold items and populate with item container divs. Move tray one item width to the left. 79 $(obj).append('<div class="ic_tray" style="position:relative;width:'+(numItems*2)*widthSource+'px;left:-'+widthSource+'px">'); 80 for(var i=0;i<numItems;i++) $('div.ic_tray',obj).append('<div style="overflow:hidden;background:url('+o.imagePath+'wait.gif) no-repeat scroll 50% 50% #ddd;float:left;position:relative;width:'+widthSource+'px;height:'+heightSource+'px;" class="infiniteCarousel_item">'); 81 82 // Populate the individual tray divs with items. Add links and captions where available. 83 $('.infiniteCarousel_item',obj).each(function(index){ 84 if(itemSources[index].indexOf('youtube.com') > 0 || itemSources[index].indexOf('vimeo.com') > 0 || itemSources[index].indexOf('funnyordie.com') > 0) 85 { 86 var querystring = itemSources[index].split("?"); // Need to disassemble and reassemble any querystring parameters so that we can append wmode=opaque as first parameter (see http://stackoverflow.com/questions/3820325/overlay-opaque-div-over-youtube-iframe)
87 $(this).append('<iframe src="'+querystring[0]+"?wmode=opaque&"+querystring[1]+'" frameborder="0" allowfullscreen="" style="width: '+widthSource+'px; height: '+heightSource+'px">" />'); 88 if(links[index]!=undefined) $('iframe',this).wrap('<a class="ic_link" href="'+links[index]+'"></a>'); // IE8 needs the </a>. see http://outwardfocusdesign.com/blog/web-design-professionals/jquery/possible-fix-for-jquerys-wrap-function-for-ie8/ 89 } 90 else 91 { 92 $(this).append('<img src="'+itemSources[index]+'" />'); 93 if(links[index]!=undefined) $('img',this).wrap('<a class="ic_link" href="'+links[index]+'"></a>'); // IE8 needs the </a>. see http://outwardfocusdesign.com/blog/web-design-professionals/jquery/possible-fix-for-jquerys-wrap-function-for-ie8/ 94 } 95 if(captions[index]!=undefined) $(this).append('<div class="ic_caption" style="position:absolute;bottom:0;">'+captions[index]+'</div>'); 96 }); 97 98 // Once the tray is built and populate, clone all items and double the list. This allows us to easily handle any combination of advance and inview options with no lag 99 $('.infiniteCarousel_item',obj).clone().appendTo($('div.ic_tray',obj)); // Double the set of item containers 100 $('.infiniteCarousel_item',obj).each(function(index){ $(this).attr('id','ic_'+randID+'_'+index) }); // Assign IDs to each item container 101 $('.ic_tray',obj).prepend( $('.infiniteCarousel_item:last',obj).remove() ); // Move the last div to the beginning 102 103 // Compensate for margins applied to items. 104 if(o.margin != 0) 105 { 106 $(obj).width($(obj).width()+(o.inView+1)*o.margin).height($(obj).height()+2*o.margin); 107 $('.infiniteCarousel_item',obj).css('margin',o.margin+'px 0px '+o.margin+'px '+o.margin+'px'); 108 $('.ic_tray',obj).css('left', parseInt( $('.ic_tray',obj).css('left') ) - o.margin +'px' ).width( $('.ic_tray',obj).width() + o.margin*(numItems*2) ); 109 } 110 111 // Build left/right nav 112 $(obj).append('<div class="ic_left_nav" style="position:absolute;left:0;width:32px;top:'+(heightSource/2-16)+'px;">').append('<div class="ic_right_nav" style="position:absolute;width:32px;right:0;top:'+(heightSource/2-16)+'px;">'); 113 $('.ic_left_nav',obj).append('<img style="cursor:pointer;" src="'+o.imagePath+'left.png" />'); 114 $('.ic_right_nav',obj).append('<img style="cursor:pointer;" src="'+o.imagePath+'right.png" />'); 115 if( !o.prevNextInternal && ( parseInt( $(obj).css('border-left-width') ) + parseInt( $(obj).css('border-right-width') ) ) > 0) $('.ic_right_nav',obj).css('right','-'+(parseInt( $(obj).css('border-left-width') ) + parseInt( $(obj).css('border-right-width') ) )+'px'); // adjust right nav of margin, external nav, and a border exist 116 117 // Add click events for the left/right nav 118 $('.ic_left_nav img',obj).on('click', function(event){ 119 if( !$('.ic_tray',obj).is(':animated') ) 120 { 121 stop(); 122 moveRight(o.advance); 123 } 124 }); 125 $('.ic_right_nav img',obj).on('click', function(event){ 126 if( !$('.ic_tray',obj).is(':animated') ) 127 { 128 stop(); 129 moveLeft(o.advance); 130 } 131 }); 132 133 // If inView = numItems, don't enable any features; we're already viewing all items 134 if(o.inView == numItems) {o.displayProgressRing=false;o.thumbnailType='none';o.showControls=false;o.autoPilot=false;o.enableKeyboardNav=false;$('.ic_left_nav,.ic_right_nav',obj).hide();} 135 136 // If nav outside carousel, wrap carousel in a div and set padding to compensate for nav. also dont animate nav if outside images 137 if(!o.prevNextInternal) 138 { 139 $(obj).wrap('<div id="ic_'+randID+'_wrapper" class="ic_wrapper" style="padding:0 32px;position:relative;">'); 140 $('#ic_'+randID+'_wrapper').width( $(obj).width() ); 141 $('#ic_'+randID+'_wrapper').prepend( $('.ic_left_nav',obj).detach() ); 142 $('#ic_'+randID+'_wrapper').prepend( $('.ic_right_nav',obj).detach() ); 143 } 144 else 145 { 146 // Animate left/right nav in/out of view when mouse enters/leaves carousel 147 $(obj).hover(function(){ 148 $('.ic_left_nav',obj).stop().animate({opacity:1,left:'0px'},300); 149 $('.ic_right_nav',obj).stop().animate({opacity:1,right:'0px'},300); 150 },function(){ 151 $('.ic_left_nav',obj).stop().animate({opacity:0,left:'-32px'},500); 152 $('.ic_right_nav',obj).stop().animate({opacity:0,right:'-32px'},500); 153 });
154 } 155 156 // Adjust wrapped width when using peek padding 157 $('#ic_'+randID).addClass('ic_peek_padding'); 158 $('#ic_'+randID+'_wrapper').width( $(obj).width() + parseInt($('#ic_'+randID).css('padding-left')) + parseInt($('#ic_'+randID).css('padding-right'))); //$(obj).width() + parseInt($('#ic_'+randID).css('padding-left')) + parseInt($('#ic_'+randID).css('padding-right')) 159 160 // Thumbnails 161 if(o.thumbnailType != 'none') 162 { 163 // Add a tray div for the thumbnails to exist in. If using external thumbnails, move div in DOM. 164 $(obj).append('<div id="ic_'+randID+'_thumbnail_tray" class="ic_thumbnail_tray" style="position:absolute;bottom:0;padding:5px 0;width:100%;text-align:center;">'); 165 $('#ic_'+randID+'_thumbnail_tray').append('<div class="ic_thumbnails">'); 166 for(var i=0;i<numItems;i++) $('.ic_thumbnails',obj).append('<div class="ic_button" style="cursor:pointer">'); 167 for(var i=0;i<o.inView;i++) $('.ic_button:eq('+i+')',obj).addClass('ic_active'); 168 $('.ic_button').hover(function(){ if( !$(this).hasClass('ic_active') ) $(this).css('background','#699') },function(){$(this).css('background','')}); 169 170 if(o.thumbnailType == 'images') 171 { 172 // insert images in the ic_button divs with width/height set to 100%. need to set width and height on .ic_button in css 173 $('.ic_button',obj).each(function(index){ 174 if( itemSources[index]!=undefined ) thumbImage = itemSources[index]; 175 if( vidThumb[index]!=undefined ) thumbImage = vidThumb[index]; 176 $(this).append('<img width="100%" height="100%" src="'+thumbImage+'" />'); 177 }); 178 } 179 if(o.thumbnailType == 'numbers') 180 { 181 // numbered thumbs 182 $('.ic_button',obj).each(function(index){ 183 $(this).html(index+1); 184 }); 185 } 186 if(o.thumbnailType == 'count') 187 { 188 // X of Y thumbs 189 $('.ic_button',obj).remove(); 190 $('.ic_thumbnails',obj).html('<span>1</span> of '+numItems); 191 manageThumbButtons(); 192 } 193 if(!o.internalThumbnails) 194 { 195 // Check and see if our wrapper is already in place from the navigation. if so, add thumb tray div. if not, build and add. 196 if(!$('#ic_'+randID+'_wrapper').length) 197 { 198 $(obj).wrap('<div id="ic_'+randID+'_wrapper" class="ic_wrapper" style="position:relative;">'); 199 $('#ic_'+randID+'_wrapper').width( $(obj).width() ); 200 } 201 // Move the existing thumbnail tray to be a child of the wrapper 202 $('#ic_'+randID+'_thumbnail_tray').css({'bottom':'','position':'relative'}).appendTo($('#ic_'+randID+'_wrapper')); 203 } 204 205 // add click events to the thumbnail buttons 206 var thumbTopParent = ($('#ic_'+randID+'_wrapper').length) ? $('#ic_'+randID+'_wrapper'):obj; 207 $('.ic_button',thumbTopParent).on('click', function(){ 208 if( !$('.ic_tray',obj).is(':animated') ) 209 { 210 stop(); 211 212 var jumpStart = parseInt( $('.infiniteCarousel_item:eq(1)',obj).attr('id').split('_').pop() ); 213 var jumpFinish = $(this).index(); 214 if(jumpStart > (numItems-1)) jumpStart -= numItems; 215 216 var a = Math.abs(jumpStart-jumpFinish); 217 var b = numItems - a; 218 var jumpDist = Math.min(a,b); 219 if(jumpStart < jumpFinish) 220 { 221 if(a<b || a==b) moveLeft(jumpDist); 222 if(a>b) moveRight(jumpDist); 223 } 224 if(jumpStart > jumpFinish) 225 { 226 if(a<b) moveRight(jumpDist); 227 if(a>b || a==b) moveLeft(jumpDist); 228 } 229 } 230 }); 231 } 232 233 if( (!o.prevNextInternal || !o.internalThumbnails) && o.customClass !== null ) { $('#ic_'+randID+'_wrapper').addClass('ic_'+o.customClass); } 234 else if (o.customClass!== null) { $(obj).addClass('ic_'+o.customClass); } 235 236 if(o.enableKeyboardNav) 237 { 238 $(document).keydown(function(event){ 239 if(event.keyCode == 39) if( !$('.ic_tray',obj).is(':animated') ) { stop(); moveLeft(o.advance); } 240 if(event.keyCode == 37) if( !$('.ic_tray',obj).is(':animated') ) { stop(); moveRight(o.advance); } 241 if(event.keyCode == 80 || event.keyCode == 111) if( !$('.ic_tray',obj).is(':animated') ) if(o.autoPilot) pause(); 242 if(event.keyCode == 83 || event.keyCode == 115) if( !$('.ic_tray',obj).is(':animated') ) play(); 243 });
244 } 245 246 // Play/pause controls 247 if(o.showControls) 248 { 249 $(obj).append('<div id="ic_controls_'+randID+'" class="ic_controls" style="background:url('+o.imagePath+'controls.png) no-repeat -12px 0;opacity:.5;cursor:pointer;height:10px;position:absolute;right:9px;top:10px;width:10px;z-index:1">'); 250 if(!o.autoPilot) $('#ic_controls_'+randID).css('background-position','1px 0'); 251 $('.ic_controls',obj).on('click', function(){ 252 if( !$('.ic_tray',obj).is(':animated') ) 253 { 254 if(o.autoPilot) pause(); // pause 255 else play();// play 256 } 257 }); 258 } 259 260 // Build a canvas autopilot timer 261 if(canvasSupported) 262 { 263 $(obj).append('<canvas id="ic_canvas_'+randID+'" width="30" height="30" style="position:absolute;top:0;right:0;"></canvas>'); 264 var ctx = $('#ic_canvas_'+randID)[0].getContext('2d'); //var ctx = $('canvas')[0].getContext('2d'); 265 ctx.lineWidth = 3; 266 ctx.strokeStyle = "rgba("+o.progressRingColorOpacity+")"; 267 ctx.shadowOffsetX = 0; 268 ctx.shadowOffsetY = 0; 269 ctx.shadowBlur = 3; 270 ctx.shadowColor = "#fff"; 271 if(!o.displayProgressRing) $('#ic_canvas_'+randID).hide(); 272 } else { $(obj).append('<div id="ic_ie_timer_'+randID+'" style="width:100%;height:6px;position:absolute;bottom:0;left:0;background:#ccc"></div>');$('#ic_ie_timer_'+randID).css('opacity','.25') } 273 function hideCaptions() 274 { 275 if(o.autoHideCaptions) $('.ic_caption',obj).stop().animate({bottom:-heightSource+'px'}); 276 } 277 function showCaptions() 278 { 279 if(o.autoHideCaptions) $('.ic_caption',obj).stop().animate({bottom:'0px'}); 280 } 281 function manageThumbButtons() 282 { 283 thumbButtonStart = parseInt( $('.infiniteCarousel_item',obj).attr('id').split('_').pop() ) + 1; 284 if(thumbButtonStart > (numItems-1)) thumbButtonStart -= numItems; 285 if(o.thumbnailType == 'count') 286 { 287 var ary=[]; 288 for(var i=thumbButtonStart;i<thumbButtonStart+o.inView;i++) ary.push( ((i+1) > numItems) ? (i+1)-numItems:(i+1) ); 289 var last = ary.pop(); 290 var amp = (o.inView>1) ? " & ":''; 291 $('.ic_thumbnails span',thumbTopParent).text(ary.join(", ") + amp + last); 292 } 293 for(var i=thumbButtonStart;i<thumbButtonStart+o.inView;i++) (i>numItems-1) ? $('.ic_button:eq('+Math.abs(numItems-i)+')',thumbTopParent).addClass('ic_active'):$('.ic_button:eq('+i+')',thumbTopParent).addClass('ic_active'); 294 } 295 function moveRight(dist) 296 { 297 o.onSlideStart.call(this); 298 $('.ic_button',thumbTopParent).removeClass('ic_active'); 299 $('.infiniteCarousel_item',obj).slice(-dist).prependTo('#ic_'+randID+' .ic_tray',obj); 300 $('.ic_tray',obj).css({left:'-='+(widthSource*dist)+'px'}); 301 $('.ic_tray',obj).stop().animate({left:"+="+widthSource*dist+"px"},o.transitionSpeed,o.easeRight,function(){ 302 showCaptions(); 303 manageThumbButtons(); 304 o.onSlideEnd.call(this); 305 }); 306 hideCaptions(); 307 } 308 function moveLeft(dist) 309 { 310 o.onSlideStart.call(this); 311 $('.ic_button',thumbTopParent).removeClass('ic_active'); 312 $('.ic_tray',obj).stop().animate({left:"-="+(widthSource+o.margin)*dist+"px"},o.transitionSpeed,o.easeLeft,function(){ 313 $('.infiniteCarousel_item',obj).slice(0,dist).appendTo('#ic_'+randID+' .ic_tray',obj); 314 $('.ic_tray',obj).css({left:'-'+(widthSource+o.margin)+'px'}); 315 showCaptions(); 316 manageThumbButtons(); 317 o.onSlideEnd.call(this); 318 if(o.autoPilot) animatedTimer(o.displayTime); 319 }); 320 hideCaptions(); 321 } 322 function pause() 323 { 324 o.onPauseClick.call(this); 325 o.autoPilot = false; 326 $('#ic_controls_'+randID).css('background-position','1px 0'); 327 clearInterval(clrTimerInterval); 328 elapsedTime=u; 329 } 330 function play() 331 { 332 o.autoPilot = true; 333 if(o.autoPilot && !$('.ic_tray',obj).is(':animated') ) animatedTimer(o.displayTime); 334 $('#ic_controls_'+randID).css('background-position','-12px 0'); 335 } 336 function stop() 337 { 338 o.onPlayClick.call(this); 339 o.autoPilot = false; 340 resetTimer(); 341 $('#ic_controls_'+randID).css('background-position','1px 0'); 342 clearInterval(clrTimerInterval); 343 } 344 function animatedTimer(delay) 345 { 346 var startTime = new Date().getTime(), newTime, angle=0; 347 348 clrTimerInterval = setInterval(function() { 349 if (angle < 359) 350 { 351 newTime = new Date().getTime(); 352 u = (newTime - startTime)+elapsedTime; 353 angle = Math.floor(u / delay * 360); 354 if(angle>359) angle=359; // insurance that the angle stays < 360 due to fast setinterval peri
354od 355 if(canvasSupported) 356 { 357 ctx.clearRect(0,0,30,30); // clear canvas 358 ctx.save(); // needed for the translation and rotation 359 ctx.translate(15,15); 360 ctx.rotate(-Math.PI/2); // rotate -90 degrees ccw 361 if(o.progressRingBackgroundOn) 362 { 363 ctx.strokeStyle = "rgba("+o.progressRingBackgroundColorOpacity+")"; 364 ctx.beginPath(); 365 ctx.arc(0, 0, 10, 0, (360 * (Math.PI / 180) ), true); // (x, y, radius, startAngle, endAngle, anticlockwise) 366 ctx.stroke(); 367 ctx.strokeStyle = "rgba("+o.progressRingColorOpacity+")"; 368 } 369 ctx.beginPath(); 370 ctx.arc(0, 0, 10, 0, (angle * (Math.PI / 180) ), true); // (x, y, radius, startAngle, endAngle, anticlockwise) 371 ctx.stroke(); 372 ctx.restore(); // needed for the translation and rotation 373 } 374 else 375 { 376 // animate the ie timer line 377 $('#ic_ie_timer_'+randID,obj).css('width',99-Math.floor( (u/delay)*100)+'%'); 378 } 379 } 380 else 381 { 382 elapsedTime = 0; 383 clearInterval(clrTimerInterval); 384 moveLeft(o.advance); 385 } 386 }, 20); 387 } 388 function resetTimer() 389 { 390 elapsedTime = 0; 391 if(canvasSupported) 392 { 393 ctx.clearRect(0,0,30,30); // clear canvas 394 ctx.save(); // needed for the translation and rotation 395 ctx.translate(15,15); 396 ctx.rotate(-Math.PI/2); // rotate -90 degrees ccw 397 ctx.beginPath(); 398 ctx.arc(0, 0, 10, 0, (360 * (Math.PI / 180) ), true); // (x, y, radius, startAngle, endAngle, anticlockwise) 399 ctx.stroke(); 400 ctx.restore(); // needed for the translation and rotation 401 } 402 } 403 404 // AutoPilot (pausing, keyboard, thumbnail clicks turn autopilot off/play turns on) 405 if(o.autoPilot && !$('.ic_tray',obj).is(':animated') ) { animatedTimer(o.displayTime); } else { resetTimer(); } 406 }); 407 } 408 }); 409})(jQuery);
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.