1/** 2 * Copyright (c) 2012 Anders Ekdahl (http://coffeescripter.com/) 3 * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) 4 * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses. 5 * 6 * Version: 1.2.7 7 * 8 * Demo and documentation: http://coffeescripter.com/code/ad-gallery/ 9 */ 10(function($) { 11 $.fn.adGallery = function(options) { 12 var defaults = { loader_image: 'loader.gif', 13 start_at_index: 0, 14 update_window_hash: true, 15 description_wrapper: false, 16 thumb_opacity: 0.7, 17 animate_first_image: false, 18 animation_speed: 400, 19 width: false, 20 height: false, 21 display_next_and_prev: true, 22 display_back_and_forward: true, 23 scroll_jump: 0, // If 0, it jumps the width of the container 24 slideshow: { 25 enable: true, 26 autostart: false, 27 speed: 5000, 28 start_label: 'Start', 29 stop_label: 'Stop', 30 stop_on_scroll: true, 31 countdown_prefix: '(', 32 countdown_sufix: ')', 33 onStart: false, 34 onStop: false 35 }, 36 effect: 'slide-hori', // or 'slide-vert', 'fade', or 'resize', 'none' 37 enable_keyboard_move: true, 38 cycle: true, 39 hooks: { 40 displayDescription: false 41 }, 42 callbacks: { 43 init: false, 44 afterImageVisible: false, 45 beforeImageVisible: false 46 } 47 }; 48 var settings = $.extend(false, defaults, options); 49 if(options && options.slideshow) { 50 settings.slideshow = $.extend(false, defaults.slideshow, options.slideshow); 51 }; 52 if(!settings.slideshow.enable) { 53 settings.slideshow.autostart = false;
54 }; 55 var galleries = []; 56 $(this).each(function() { 57 var gallery = new AdGallery(this, settings); 58 galleries[galleries.length] = gallery; 59 }); 60 // Sorry, breaking the jQuery chain because the gallery instances 61 // are returned so you can fiddle with them 62 return galleries; 63 }; 64 65 function VerticalSlideAnimation(img_container, direction, desc) { 66 var current_top = parseInt(img_container.css('top'), 10); 67 if(direction == 'left') { 68 var old_image_top = '-'+ this.image_wrapper_height +'px'; 69 img_container.css('top', this.image_wrapper_height +'px'); 70 } else { 71 var old_image_top = this.image_wrapper_height +'px'; 72 img_container.css('top', '-'+ this.image_wrapper_height +'px'); 73 }; 74 if(desc) { 75 desc.css('bottom', '-'+ desc[0].offsetHeight +'px'); 76 desc.animate({bottom: 0}, this.settings.animation_speed * 2); 77 }; 78 if(this.current_description) { 79 this.current_description.animate({bottom: '-'+ this.current_description[0].offsetHeight +'px'}, this.settings.animation_speed * 2); 80 }; 81 return {old_image: {top: old_image_top}, 82 new_image: {top: current_top}}; 83 }; 84 85 function HorizontalSlideAnimation(img_container, direction, desc) { 86 var current_left = parseInt(img_container.css('left'), 10); 87 if(direction == 'left') { 88 var old_image_left = '-'+ this.image_wrapper_width +'px'; 89 img_container.css('left',this.image_wrapper_width +'px'); 90 } else { 91 var old_image_left = this.image_wrapper_width +'px'; 92 img_container.css('left','-'+ this.image_wrapper_width +'px'); 93 }; 94 if(desc) { 95 desc.css('bottom', '-'+ desc[0].offsetHeight +'px'); 96 desc.animate({bottom: 0}, this.settings.animation_speed * 2); 97 }; 98 if(this.current_description) { 99 this.current_description.animate({bottom: '-'+ this.current_description[0].offsetHeight +'px'}, this.settings.animation_speed * 2); 100 }; 101 return {old_image: {left: old_image_left}, 102 new_image: {left: current_left}}; 103 }; 104 105 function ResizeAnimation(img_container, direction, desc) { 106 var image_width = img_container.width(); 107 var image_height = img_container.height(); 108 var current_left = parseInt(img_container.css('left'), 10); 109 var current_top = parseInt(img_container.css('top'), 10); 110 img_container.css({width: 0, height: 0, top: this.image_wrapper_height / 2, left: this.image_wrapper_width / 2}); 111 return {old_image: {width: 0, 112 height: 0, 113 top: this.image_wrapper_height / 2, 114 left: this.image_wrapper_width / 2}, 115 new_image: {width: image_width, 116 height: image_height, 117 top: current_top, 118 left: current_left}}; 119 }; 120 121 function FadeAnimation(img_container, direction, desc) { 122 img_container.css('opacity', 0); 123 return {old_image: {opacity: 0}, 124 new_image: {opacity: 1}}; 125 }; 126 127 // Sort of a hack, will clean this up... eventually 128 function NoneAnimation(img_container, direction, desc) { 129 img_container.css('opacity', 0); 130 return {old_image: {opacity: 0}, 131 new_image: {opacity: 1}, 132 speed: 0}; 133 }; 134 135 function AdGallery(wrapper, settings) { 136 this.init(wrapper, settings); 137 }; 138 AdGallery.prototype = { 139 // Elements 140 wrapper: false, 141 image_wrapper: false, 142 gallery_info: false, 143 nav: false, 144 loader: false, 145 preloads: false, 146 thumbs_wrapper: false, 147 thumbs_wrapper_width: 0, 148 scroll_back: false, 149 scroll_forward: false, 150 next_link: false, 151 prev_link: false, 152 153 slideshow: false, 154 image_wrapper_width: 0, 155 image_wrapper_height: 0, 156 current_index: -1, 157 current_image: false, 158 current_description: false, 159 nav_display_width: 0, 160 settings: false, 161 images: false, 162 in_transition: false, 163 animations: false, 164 init: function(wrapper, settings) { 165 var context = this; 166 this.wrapper = $(wrapper); 167 this.settings = settings; 168 this.setupElements(); 169 this.setupAnimations(); 170 if(this.settings.width) { 171 this.image_wrapper_width = this.settings.width; 172 this.image_wrapper.width(this.settings.width); 173 this.wrapper.width(this.settings.width); 174 } else { 175 this.image_wrapper_width = this.image_wrapper.width(); 176 }; 177 if(this.settings.height) { 178 this.image_wrapper_height = this.settings.height; 179 this.image_wrapper.height(this.settings.height); 180 } else { 181 this.image_wrapper_height = this.image_wrapper.height(); 182 }; 183 this.nav_display_width = this.nav.width(); 184 this.current_index = -1; 185 this.current_image = false;
186 this.current_description = false; 187 this.in_transition = false; 188 this.findImages(); 189 if(this.settings.display_next_and_prev) { 190 this.initNextAndPrev(); 191 }; 192 // The slideshow needs a callback to trigger the next image to be shown 193 // but we don't want to give it access to the whole gallery instance 194 var nextimage_callback = function(callback) { 195 return context.nextImage(callback); 196 }; 197 this.slideshow = new AdGallerySlideshow(nextimage_callback, this.settings.slideshow); 198 this.controls.append(this.slideshow.create()); 199 if(this.settings.slideshow.enable) { 200 this.slideshow.enable(); 201 } else { 202 this.slideshow.disable(); 203 }; 204 if(this.settings.display_back_and_forward) { 205 this.initBackAndForward(); 206 }; 207 if(this.settings.enable_keyboard_move) { 208 this.initKeyEvents(); 209 }; 210 this.initHashChange(); 211 var start_at = parseInt(this.settings.start_at_index, 10); 212 if(typeof this.getIndexFromHash() != "undefined") { 213 start_at = this.getIndexFromHash(); 214 }; 215 this.loading(true); 216 this.showImage(start_at, 217 function() { 218 // We don't want to start the slideshow before the image has been 219 // displayed 220 if(context.settings.slideshow.autostart) { 221 context.preloadImage(start_at + 1); 222 context.slideshow.start(); 223 }; 224 } 225 ); 226 this.fireCallback(this.settings.callbacks.init); 227 }, 228 setupAnimations: function() { 229 this.animations = { 230 'slide-vert': VerticalSlideAnimation, 231 'slide-hori': HorizontalSlideAnimation, 232 'resize': ResizeAnimation, 233 'fade': FadeAnimation, 234 'none': NoneAnimation 235 }; 236 }, 237 setupElements: function() { 238 this.controls = this.wrapper.find('.ad-controls'); 239 this.gallery_info = $('<p class="ad-info"></p>'); 240 this.controls.append(this.gallery_info); 241 this.image_wrapper = this.wrapper.find('.ad-image-wrapper'); 242 this.image_wrapper.empty(); 243 this.nav = this.wrapper.find('.ad-nav'); 244 this.thumbs_wrapper = this.nav.find('.ad-thumbs'); 245 this.preloads = $('<div class="ad-preloads"></div>'); 246 this.loader = $('<img class="ad-loader" src="'+ this.settings.loader_image +'">'); 247 this.image_wrapper.append(this.loader); 248 this.loader.hide(); 249 $(document.body).append(this.preloads); 250 }, 251 loading: function(bool) { 252 if(bool) { 253 this.loader.show(); 254 } else { 255 this.loader.hide(); 256 }; 257 }, 258 addAnimation: function(name, fn) { 259 if($.isFunction(fn)) { 260 this.animations[name] = fn; 261 }; 262 }, 263 findImages: function() { 264 var context = this; 265 this.images = []; 266 var thumbs_loaded = 0; 267 var thumbs = this.thumbs_wrapper.find('a'); 268 var thumb_count = thumbs.length; 269 if(this.settings.thumb_opacity < 1) { 270 thumbs.find('img').css('opacity', this.settings.thumb_opacity); 271 }; 272 thumbs.each( 273 function(i) { 274 var link = $(this); 275 link.data("ad-i", i); 276 var image_src = link.attr('href'); 277 var thumb = link.find('img'); 278 context.whenImageLoaded(thumb[0], function() { 279 var width = thumb[0].parentNode.parentNode.offsetWidth; 280 if(thumb[0].width == 0) { 281 // If the browser tells us that the image is loaded, but the width 282 // is still 0 for some reason, we default to 100px width. 283 // It's not very nice, but it's better than 0. 284 width = 100; 285 }; 286 context.thumbs_wrapper_width += width; 287 thumbs_loaded++; 288 }); 289 context._initLink(link); 290 context.images[i] = context._createImageData(link, image_src); 291 } 292 ); 293 // Wait until all thumbs are loaded, and then set the width of the ul 294 var inter = setInterval( 295 function() { 296 if(thumb_count == thumbs_loaded) { 297 context._setThumbListWidth(context.thumbs_wrapper_width); 298 clearInterval(inter); 299 }; 300 }, 301 100 302 ); 303 }, 304 _setThumbListWidth: function(wrapper_width) { 305 wrapper_width -= 100; 306 var list = this.nav.find('.ad-thumb-list'); 307 list.css('width', wrapper_width +'px'); 308 var i = 1; 309 var last_height = list.height(); 310 while(i < 201) { 311 list.css('width', (wrapper_width + i) +'px'); 312 if(last_height != list.height()) { 313 break; 314 }; 315 last_height = list.height(); 316 i++; 317 }; 318 if(list.width() < this.nav.width()) { 319 list.width(this.nav.width()); 320 }; 321 }, 322 _initLink: function(link) { 323 var context = this; 324 link.click( 325 function() { 326 context.showImage(link.data("ad-i")); 327 context.slideshow.stop(); 328 return false;
329 } 330 ).hover( 331 function() { 332 if(!$(this).is('.ad-active') && context.settings.thumb_opacity < 1) { 333 $(this).find('img').fadeTo(300, 1); 334 }; 335 context.preloadImage(link.data("ad-i")); 336 }, 337 function() { 338 if(!$(this).is('.ad-active') && context.settings.thumb_opacity < 1) { 339 $(this).find('img').fadeTo(300, context.settings.thumb_opacity); 340 }; 341 } 342 ); 343 }, 344 _createImageData: function(thumb_link, image_src) { 345 var link = false; 346 var thumb_img = thumb_link.find("img"); 347 if(thumb_img.data('ad-link')) { 348 link = thumb_link.data('ad-link'); 349 } else if(thumb_img.attr('longdesc') && thumb_img.attr('longdesc').length) { 350 link = thumb_img.attr('longdesc'); 351 }; 352 var desc = false; 353 if(thumb_img.data('ad-desc')) { 354 desc = thumb_img.data('ad-desc'); 355 } else if(thumb_img.attr('alt') && thumb_img.attr('alt').length) { 356 desc = thumb_img.attr('alt'); 357 }; 358 var title = false; 359 if(thumb_img.data('ad-title')) { 360 title = thumb_img.data('ad-title'); 361 } else if(thumb_img.attr('title') && thumb_img.attr('title').length) { 362 title = thumb_img.attr('title'); 363 }; 364 return { thumb_link: thumb_link, image: image_src, error: false, 365 preloaded: false, desc: desc, title: title, size: false, 366 link: link }; 367 }, 368 initKeyEvents: function() { 369 var context = this; 370 $(document).keydown( 371 function(e) { 372 if(e.keyCode == 39) { 373 // right arrow 374 context.nextImage(); 375 context.slideshow.stop(); 376 } else if(e.keyCode == 37) { 377 // left arrow 378 context.prevImage(); 379 context.slideshow.stop(); 380 }; 381 } 382 ); 383 }, 384 getIndexFromHash: function() { 385 if(window.location.hash && window.location.hash.indexOf('#ad-image-') === 0) { 386 var id = window.location.hash.replace(/^#ad-image-/g, ''); 387 var thumb = this.thumbs_wrapper.find("#"+ id); 388 if(thumb.length) { 389 return this.thumbs_wrapper.find("a").index(thumb); 390 } else if(!isNaN(parseInt(id, 10))) { 391 return parseInt(id, 10); 392 }; 393 }; 394 return undefined; 395 }, 396 removeImage: function(index) { 397 if(index < 0 || index >= this.images.length) { 398 throw "Cannot remove image for index "+ index; 399 }; 400 var image = this.images[index]; 401 this.images.splice(index, 1); 402 var thumb_link = image.thumb_link; 403 var thumb_width = thumb_link[0].parentNode.offsetWidth; 404 this.thumbs_wrapper_width -= thumb_width; 405 thumb_link.remove(); 406 this._setThumbListWidth(this.thumbs_wrapper_width); 407 this.gallery_info.html((this.current_index + 1) +' / '+ this.images.length); 408 this.thumbs_wrapper.find('a').each( 409 function(i) { 410 $(this).data("ad-i", i); 411 } 412 ); 413 if(index == this.current_index && this.images.length != 0) { 414 this.showImage(0); 415 }; 416 }, 417 removeAllImages: function() { 418 for (var i = this.images.length - 1; i >= 0; i--) { 419 this.removeImage(i); 420 }; 421 }, 422 addImage: function(thumb_url, image_url, image_id, title, description) { 423 image_id = image_id || ""; 424 title = title || ""; 425 description = description || ""; 426 var li = $('<li><a href="'+ image_url +'" id="'+ image_id +'">' + 427 '<img src="'+ thumb_url +'" title="'+ title +'" alt="'+ description +'">' + 428 '</a></li>'); 429 var context = this; 430 this.thumbs_wrapper.find("ul").append(li); 431 432 var link = li.find("a"); 433 var thumb = link.find("img"); 434 thumb.css('opacity', this.settings.thumb_opacity); 435 436 this.whenImageLoaded(thumb[0], function() { 437 var thumb_width = thumb[0].parentNode.parentNode.offsetWidth; 438 if(thumb[0].width == 0) { 439 // If the browser tells us that the image is loaded, but the width 440 // is still 0 for some reason, we default to 100px width. 441 // It's not very nice, but it's better than 0. 442 thumb_width = 100; 443 }; 444 445 context.thumbs_wrapper_width += thumb_width; 446 context._setThumbListWidth(context.thumbs_wrapper_width); 447 }); 448 var i = this.images.length; 449 link.data("ad-i", i); 450 this._initLink(link); 451 this.images[i] = context._createImageData(link, image_url); 452 this.gallery_info.html((this.current_index + 1) +' / '+ this.images.length); 453 }, 454 initHashChange: function() { 455 var context = this; 456 if("onhashchange" in window) { 457 $(window).bind("hashchange", function() { 458 var index = context.getIndexFromHash(); 459 if(typeof index != "undefined" && index != context.current_index) { 460 context.showImage(index); 461 }; 462 }); 463 } else { 464 var current_hash = window.location.hash; 465 setInterval(function() { 466 if(window.location.hash != current_hash) { 467 current_hash = window.location.hash; 468 var index = context.getIndexFromHash(); 469 if(typeof index != "undefined" && index != context.current_index) { 470 context.showImage(index); 471 }; 472 }; 473 }, 200); 474 }; 475 }, 476 initNextAndPrev: function() { 477 this.next_link = $('<div class="ad-next"><div class="ad-next-image"></div></div>'); 478 this.prev_link = $('<div class="ad-prev"><div class="ad-prev-image"></div></div>'); 479 this.image_wrapper.append(this.next_link); 480 this.image_wrapper.append(this.prev_link); 481 var context = this; 482 this.prev_link.add(this.next_link).mouseover( 483 function(e) { 484 // IE 6 hides the wrapper div, so we have to set it's width
485 $(this).css('height', context.image_wrapper_height); 486 $(this).find('div').show(); 487 } 488 ).mouseout( 489 function(e) { 490 $(this).find('div').hide(); 491 } 492 ).click( 493 function() { 494 if($(this).is('.ad-next')) { 495 context.nextImage(); 496 context.slideshow.stop(); 497 } else { 498 context.prevImage(); 499 context.slideshow.stop(); 500 }; 501 } 502 ).find('div').css('opacity', 0.7); 503 }, 504 initBackAndForward: function() { 505 var context = this; 506 this.scroll_forward = $('<div class="ad-forward"></div>'); 507 this.scroll_back = $('<div class="ad-back"></div>'); 508 this.nav.append(this.scroll_forward); 509 this.nav.prepend(this.scroll_back); 510 var has_scrolled = 0; 511 var thumbs_scroll_interval = false; 512 $(this.scroll_back).add(this.scroll_forward).click( 513 function() { 514 // We don't want to jump the whole width, since an image 515 // might be cut at the edge 516 var width = context.nav_display_width - 50; 517 if(context.settings.scroll_jump > 0) { 518 var width = context.settings.scroll_jump; 519 }; 520 if($(this).is('.ad-forward')) { 521 var left = context.thumbs_wrapper.scrollLeft() + width; 522 } else { 523 var left = context.thumbs_wrapper.scrollLeft() - width; 524 }; 525 if(context.settings.slideshow.stop_on_scroll) { 526 context.slideshow.stop(); 527 }; 528 context.thumbs_wrapper.animate({scrollLeft: left +'px'}); 529 return false; 530 } 531 ).css('opacity', 0.6).hover( 532 function() { 533 var direction = 'left'; 534 if($(this).is('.ad-forward')) { 535 direction = 'right'; 536 }; 537 thumbs_scroll_interval = setInterval( 538 function() { 539 has_scrolled++; 540 // Don't want to stop the slideshow just because we scrolled a pixel or two 541 if(has_scrolled > 30 && context.settings.slideshow.stop_on_scroll) { 542 context.slideshow.stop(); 543 }; 544 var left = context.thumbs_wrapper.scrollLeft() + 1; 545 if(direction == 'left') { 546 left = context.thumbs_wrapper.scrollLeft() - 1; 547 }; 548 context.thumbs_wrapper.scrollLeft(left); 549 }, 550 10 551 ); 552 $(this).css('opacity', 1); 553 }, 554 function() { 555 has_scrolled = 0; 556 clearInterval(thumbs_scroll_interval); 557 $(this).css('opacity', 0.6); 558 } 559 ); 560 }, 561 _afterShow: function() { 562 this.gallery_info.html((this.current_index + 1) +' / '+ this.images.length); 563 564 //if(this.current_index == 3){ 565 // $(".ad-image").hide(); 566 // var ad_item = "<div class='ad-image' style='width: 286px; height: 430px; top: 25%; left: 241px;'><div id='div-gpt-ad-1077196-1'></div></div>"; 567 // $(".ad-image-wrapper").append(ad_item); 568 // googletag.cmd.push(function() { googletag.display('div-gpt-ad-1077196-1'); }); 569 // } 570 571 if(!this.settings.cycle) { 572 // Needed for IE 573 this.prev_link.show().css('height', this.image_wrapper_height); 574 this.next_link.show().css('height', this.image_wrapper_height); 575 if(this.current_index == (this.images.length - 1)) { 576 this.next_link.hide(); 577 }; 578 if(this.current_index == 0) { 579 this.prev_link.hide(); 580 }; 581 }; 582 if(this.settings.update_window_hash) { 583 var thumb_link = this.images[this.current_index].thumb_link; 584 if (thumb_link.attr("id")) { 585 window.location.hash = "#ad-image-"+ thumb_link.attr("id"); 586 } else { 587 window.location.hash = "#ad-image-"+ this.current_index; 588 }; 589 }; 590 this.fireCallback(this.settings.callbacks.afterImageVisible); 591 }, 592 /** 593 * Checks if the image is small enough to fit inside the container 594 * If it's not, shrink it proportionally 595 */ 596 _getContainedImageSize: function(image_width, image_height) { 597 if(image_height > this.image_wrapper_height) { 598 var ratio = image_width / image_height; 599 image_height = this.image_wrapper_height; 600 image_width = this.image_wrapper_height * ratio; 601 }; 602 if(image_width > this.image_wrapper_width) { 603 var ratio = image_height / image_width; 604 image_width = this.image_wrapper_width; 605 image_height = this.image_wrapper_width * ratio; 606 }; 607 return {width: image_width, height: image_height}; 608 }, 609 /** 610 * If the image dimensions are smaller than the wrapper, we position 611 * it in the middle anyway 612 */ 613 _centerImage: function(img_container, image_width, image_height) { 614 img_container.css('top', '0px'); 615 if(image_height < this.image_wrapper_height) { 616 var dif = this.image_wrapper_height - image_height; 617 img_container.css('top', (dif / 2) +'px'); 618 }; 619 img_container.css('left', '0px'); 620 if(image_width < this.image_wrapper_width) { 621 var dif = this.image_wrapper_width - image_width; 622 img_container.css('left', (dif / 2) +'px'); 623 }; 624 }, 625 _getDescription: function(image) { 626 var desc = false;
627 if(image.desc.length || image.title.length) { 628 var title = ''; 629 if(image.title.length) { 630 title = '<strong class="ad-description-title">'+ image.title +'</strong>'; 631 }; 632 var desc = ''; 633 if(image.desc.length) { 634 desc = '<span>'+ image.desc +'</span>'; 635 }; 636 desc = $('<p class="ad-image-description">'+ title + desc +'</p>'); 637 }; 638 return desc; 639 }, 640 /** 641 * @param function callback Gets fired when the image has loaded, is displaying 642 * and it's animation has finished 643 */ 644 showImage: function(index, callback) { 645 if(this.images[index] && !this.in_transition && index != this.current_index) { 646 var context = this; 647 var image = this.images[index]; 648 this.in_transition = true; 649 if(!image.preloaded) { 650 this.loading(true); 651 this.preloadImage(index, function() { 652 context.loading(false); 653 context._showWhenLoaded(index, callback); 654 }); 655 } else { 656 this._showWhenLoaded(index, callback); 657 }; 658 }; 659 }, 660 /** 661 * @param function callback Gets fired when the image has loaded, is displaying 662 * and it's animation has finished 663 */ 664 _showWhenLoaded: function(index, callback) { 665 if(this.images[index]) { 666 var context = this; 667 var image = this.images[index]; 668 var img_container = $(document.createElement('div')).addClass('ad-image'); 669 var img = $(new Image()).attr('src', image.image); 670 671 if(image.link) { 672 var link = $('<a href="'+ image.link +'" target="_blank"></a>'); 673 link.append(img); 674 img_container.append(link); 675 } else { 676 img_container.append(img); 677 }; 678 this.image_wrapper.prepend(img_container); 679 var size = this._getContainedImageSize(image.size.width, image.size.height); 680 img.attr('width', size.width); 681 img.attr('height', size.height); 682 img_container.css({width: size.width +'px', height: size.height +'px'}); 683 this._centerImage(img_container, size.width, size.height); 684 var desc = this._getDescription(image); 685 if(desc) { 686 if(!this.settings.description_wrapper && !this.settings.hooks.displayDescription) { 687 img_container.append(desc); 688 var width = size.width - parseInt(desc.css('padding-left'), 10) - parseInt(desc.css('padding-right'), 10); 689 desc.css('width', width +'px'); 690 } else if(this.settings.hooks.displayDescription) { 691 this.settings.hooks.displayDescription.call(this, image); 692 } else { 693 var wrapper = this.settings.description_wrapper; 694 wrapper.append(desc); 695 }; 696 }; 697 this.highLightThumb(this.images[index].thumb_link); 698 699 var direction = 'right'; 700 if(this.current_index < index) { 701 direction = 'left'; 702 }; 703 this.fireCallback(this.settings.callbacks.beforeImageVisible); 704 if(this.current_image || this.settings.animate_first_image) { 705 var animation_speed = this.settings.animation_speed; 706 var easing = 'swing'; 707 var animation = this.animations[this.settings.effect].call(this, img_container, direction, desc); 708 if(typeof animation.speed != 'undefined') { 709 animation_speed = animation.speed; 710 }; 711 if(typeof animation.easing != 'undefined') { 712 easing = animation.easing; 713 }; 714 if(this.current_image) { 715 var old_image = this.current_image; 716 var old_description = this.current_description; 717 old_image.animate(animation.old_image, animation_speed, easing, 718 function() { 719 old_image.remove(); 720 if(old_description) old_description.remove(); 721 } 722 ); 723 }; 724 img_container.animate(animation.new_image, animation_speed, easing, 725 function() { 726 context.current_index = index; 727 context.current_image = img_container; 728 context.current_description = desc;
729 context.in_transition = false; 730 context._afterShow(); 731 context.fireCallback(callback); 732 } 733 ); 734 } else { 735 this.current_index = index; 736 this.current_image = img_container; 737 context.current_description = desc; 738 this.in_transition = false; 739 context._afterShow(); 740 this.fireCallback(callback); 741 }; 742 }; 743 }, 744 nextIndex: function() { 745 if(this.current_index == (this.images.length - 1)) { 746 if(!this.settings.cycle) { 747 return false; 748 }; 749 var next = 0; 750 } else { 751 var next = this.current_index + 1; 752 }; 753 return next; 754 }, 755 nextImage: function(callback) { 756 var next = this.nextIndex(); 757 if(next === false) return false; 758 this.preloadImage(next + 1); 759 this.showImage(next, callback); 760 return true; 761 }, 762 prevIndex: function() { 763 if(this.current_index == 0) { 764 if(!this.settings.cycle) { 765 return false; 766 }; 767 var prev = this.images.length - 1; 768 } else { 769 var prev = this.current_index - 1; 770 }; 771 return prev; 772 }, 773 prevImage: function(callback) { 774 var prev = this.prevIndex(); 775 if(prev === false) return false; 776 this.preloadImage(prev - 1); 777 this.showImage(prev, callback); 778 return true; 779 }, 780 preloadAll: function() { 781 var context = this; 782 var i = 0; 783 function preloadNext() {
784 if(i < context.images.length) { 785 i++; 786 context.preloadImage(i, preloadNext); 787 }; 788 }; 789 context.preloadImage(i, preloadNext); 790 }, 791 preloadImage: function(index, callback) { 792 if(this.images[index]) { 793 var image = this.images[index]; 794 if(!this.images[index].preloaded) { 795 var img = $(new Image()); 796 img.attr('src', image.image); 797 if(!this.isImageLoaded(img[0])) { 798 this.preloads.append(img); 799 var context = this; 800 img.load( 801 function() { 802 image.preloaded = true; 803 image.size = { width: this.width, height: this.height }; 804 context.fireCallback(callback); 805 } 806 ).error( 807 function() { 808 image.error = true; 809 image.preloaded = false; 810 image.size = false; 811 } 812 ); 813 } else { 814 image.preloaded = true; 815 image.size = { width: img[0].width, height: img[0].height }; 816 this.fireCallback(callback); 817 }; 818 } else { 819 this.fireCallback(callback); 820 }; 821 }; 822 }, 823 whenImageLoaded: function(img, callback) { 824 if (this.isImageLoaded(img)) { 825 callback && callback(); 826 } else { 827 $(img).load(callback); 828 }; 829 }, 830 isImageLoaded: function(img) { 831 if(typeof img.complete != 'undefined' && !img.complete) { 832 return false; 833 }; 834 if(typeof img.naturalWidth != 'undefined' && img.naturalWidth == 0) { 835 return false; 836 }; 837 return true; 838 }, 839 highLightThumb: function(thumb) { 840 this.thumbs_wrapper.find('.ad-active').removeClass('ad-active'); 841 thumb.addClass('ad-active'); 842 if(this.settings.thumb_opacity < 1) { 843 this.thumbs_wrapper.find('a:not(.ad-active) img').fadeTo(300, this.settings.thumb_opacity); 844 thumb.find('img').fadeTo(300, 1); 845 }; 846 var left = thumb[0].parentNode.offsetLeft; 847 left -= (this.nav_display_width / 2) - (thumb[0].offsetWidth / 2); 848 this.thumbs_wrapper.animate({scrollLeft: left +'px'}); 849 }, 850 fireCallback: function(fn) { 851 if($.isFunction(fn)) { 852 fn.call(this); 853 }; 854 } 855 }; 856 857 function AdGallerySlideshow(nextimage_callback, settings) { 858 this.init(nextimage_callback, settings); 859 }; 860 AdGallerySlideshow.prototype = { 861 start_link: false, 862 stop_link: false, 863 countdown: false, 864 controls: false, 865 866 settings: false, 867 nextimage_callback: false, 868 enabled: false, 869 running: false, 870 countdown_interval: false, 871 init: function(nextimage_callback, settings) { 872 var context = this; 873 this.nextimage_callback = nextimage_callback; 874 this.settings = settings; 875 }, 876 create: function() { 877 this.start_link = $('<span class="ad-slideshow-start">'+ this.settings.start_label +'</span>'); 878 this.stop_link = $('<span class="ad-slideshow-stop">'+ this.settings.stop_label +'</span>'); 879 this.countdown = $('<span class="ad-slideshow-countdown"></span>'); 880 this.controls = $('<div class="ad-slideshow-controls"></div>'); 881 882 this.controls.append(this.start_link).append(this.stop_link).append(this.countdown); 883 this.countdown.hide(); 884 885 var context = this; 886 this.start_link.click( 887 function() { 888 context.start(); 889 } 890 ); 891 this.stop_link.click( 892 function() { 893 context.stop(); 894 } 895 ); 896 $(document).keydown( 897 function(e) { 898 if(e.keyCode == 83) { 899 // 's' 900 if(context.running) { 901 context.stop(); 902 } else { 903 context.start(); 904 }; 905 }; 906 } 907 ); 908 return this.controls; 909 }, 910 disable: function() { 911 this.enabled = false; 912 this.stop(); 913 this.controls.hide(); 914 }, 915 enable: function() { 916 this.enabled = true; 917 this.controls.show(); 918 }, 919 toggle: function() { 920 if(this.enabled) { 921 this.disable(); 922 } else { 923 this.enable(); 924 }; 925 }, 926 start: function() { 927 if(this.running || !this.enabled) return false;
928 var context = this; 929 this.running = true; 930 this.controls.addClass('ad-slideshow-running'); 931 this._next(); 932 this.fireCallback(this.settings.onStart); 933 return true; 934 }, 935 stop: function() { 936 if(!this.running) return false; 937 this.running = false; 938 this.countdown.hide(); 939 this.controls.removeClass('ad-slideshow-running'); 940 clearInterval(this.countdown_interval); 941 this.fireCallback(this.settings.onStop); 942 return true; 943 }, 944 _next: function() { 945 var context = this; 946 var pre = this.settings.countdown_prefix; 947 var su = this.settings.countdown_sufix; 948 clearInterval(context.countdown_interval); 949 this.countdown.show().html(pre + (this.settings.speed / 1000) + su); 950 var slide_timer = 0; 951 this.countdown_interval = setInterval( 952 function() { 953 slide_timer += 1000; 954 if(slide_timer >= context.settings.speed) { 955 var whenNextIsShown = function() { 956 // A check so the user hasn't stoped the slideshow during the 957 // animation 958 if(context.running) { 959 context._next(); 960 }; 961 slide_timer = 0; 962 }; 963 if(!context.nextimage_callback(whenNextIsShown)) { 964 context.stop(); 965 }; 966 slide_timer = 0; 967 }; 968 var sec = parseInt(context.countdown.text().replace(/[^0-9]/g, ''), 10); 969 sec--; 970 if(sec > 0) { 971 context.countdown.html(pre + sec + su); 972 }; 973 }, 974 1000 975 ); 976 }, 977 fireCallback: function(fn) { 978 if($.isFunction(fn)) { 979 fn.call(this); 980 }; 981 } 982 }; 983})(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.