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