1/* ====================================================================================================================================================== 2Avia Slideshow 3====================================================================================================================================================== 4*/ 5 6(function($) 7{ 8 "use strict"; 9 10 $.AviaSlider = function( options, slider ) 11 { 12 var self = this; 13 14 this.$win = $( window ); 15 this.$slider = $( slider ); 16 17 this.isMobile = $.avia_utilities.isMobile; 18 this.isTouchDevice = $.avia_utilities.isTouchDevice, 19 20 this._prepareSlides(options); 21 22 //default preload images then init slideshow 23 $.avia_utilities.preload({ 24 container: this.$slider, 25 single_callback: function(){ self._init( options ); } 26 }); 27 }; 28 29 $.AviaSlider.defaults = 30 { 31 //interval between autorotation switches 32 interval: 5, 33 34 //start autorotation active or not 35 autoplay: false, 36 37 //stop on last slide - shortcut for stopinfiniteloop - kept for backwards comp. With 5.0 added extended support also for manual rotation 38 autoplay_stopper: false, 39 40 // @since 5.0 'endless' | 'once' 41 loop_autoplay: 'once', 42 43 // @since 5.0 'manual-endless' | 'manual-once' 44 loop_manual: 'manual-endless', 45 46 //set if the loop will stop at the last/first slide or if the slides will loop infinite 47 //set to false for infinite loop, "last" to stop at the last slide or "first" to stop at the first slide 48 stopinfiniteloop: false, 49 50 // true to ignore all user navigation 51 noNavigation: false, 52 53 //fade or slide animation 54 animation: 'slide', 55 56 //transition speed when switching slide 57 transitionSpeed: 900, 58 59 //easing method for the transition 60 easing: 'easeInOutQuart', 61 62 //slide wrapper 63 wrapElement: '>ul', 64 65 //slide element 66 slideElement: '>li', 67 68 //pause if mouse cursor is above item 69 hoverpause: false, 70 71 //attach images as background 72 bg_slider: false, 73 74 //delay of milliseconds to wait before showing the next slide 75 show_slide_delay: 0, 76 77 //if slider animation is set to "fade" the fullfade property sets the crossfade behaviour 78 fullfade: false, 79 80 //set to true to keep padding (e.g. for featured image slideshow, carousel slideshow 81 keep_padding: false, 82 83 //enable carousel mode with multiple visible slides 84 carousel: 'no', 85 86 // how many slides are displayed at once in the carousel 87 carouselSlidesToShow: 3, 88 89 // TODO: how many slides are scrolled in the carousel 90 carouselSlidesToScroll: 1, 91 92 // responsive carousel 93 carouselResponsive: new Array() 94 95 }; 96 97 $.AviaSlider.prototype = 98 { 99 _init: function( options ) 100 { 101 // set slider options 102 this.options = this._setOptions( options ); 103 104 //slidewrap 105 this.$sliderUl = this.$slider.find(this.options.wrapElement); 106 107 // slide elements 108 this.$slides = this.$sliderUl.find(this.options.slideElement); 109 110 // slide navigaton arrows wrap 111 this.slide_arrows = this.$slider.find( '.avia-slideshow-arrows' ); 112 113 // goto dots 114 this.gotoButtons = this.$slider.find( '.avia-slideshow-dots a' ); 115 116 //perma caption 117 this.permaCaption = this.$slider.find( '>.av-slideshow-caption' ); 118 119 // slide count 120 this.itemsCount = this.$slides.length; 121 122 // current image index 123 this.current = 0; 124 125 // current carousel index 126 this.currentCarousel = 0; 127 128 // carousel slide width 129 this.slideWidthCarousel = '240'; 130 131 //loop count 132 this.loopCount = 0; 133 134 // control if the slicebox is animating 135 this.isAnimating = false; 136 137 // css browser prefix like -webkit-, -moz- 138 this.browserPrefix = $.avia_utilities.supports('transition'); 139 140 // css3 animation? 141 this.cssActive = this.browserPrefix !== false ? true : false; 142 143 // css3D animation? 144 this.css3DActive = document.documentElement.className.indexOf('avia_transform3d') !== -1 ? true : false; 145 146 //if we have a bg slider no images were preloaded yet. in that case start preloading and attaching images 147 if( this.options.bg_slider == true ) 148 { 149 //create array that holds all image urls to preload 150 this.imageUrls = []; 151 152 //create a preloader icon to indicate loading 153 this.loader = $.avia_utilities.loading( this.$slider ); 154 155 //preload the images ony by one 156 this._bgPreloadImages(); 157 158 } 159 else //if it was a default slider all images are already loaded and we can start showing the slider 160 {
161 //kickoff the slider: bind functions, show first slide, if active start the autorotation timer 162 this._kickOff(); 163 } 164 165 if( this.options.carousel === 'yes' ) 166 { 167 this.options.animation = 'carouselslide'; 168 } 169 }, 170 171 //set the slider options by first merging the default options and the passed options, then checking the slider element if any data attributes overwrite the option set 172 _setOptions: function( options ) 173 { 174 var jsonOptions = this.$slider.data( 'slideshow-options' ); 175 176 // since 5.0 - render options via json to clean up html - $.data returns parsed object 177 if( 'object' == typeof jsonOptions ) 178 { 179 var newOptions = $.extend( {}, $.AviaSlider.defaults, options, jsonOptions ); 180 181 if( 'undefined' != typeof newOptions.transition_speed ) 182 { 183 newOptions.transitionSpeed = newOptions.transition_speed; 184 } 185 186 return newOptions; 187 } 188 189 var newOptions = $.extend( true, {}, $.AviaSlider.defaults, options ), 190 htmlData = this.$slider.data(); 191 192 //overwrite passed option set with any data properties on the html element 193 for( var i in htmlData ) 194 { 195 // data attribute is transformed to lower case, but js is case sensitive - transform key 196 var key = ( 'transition_speed' != i ) ? i :'transitionSpeed'; 197 198 if( typeof htmlData[ i ] === "string" || typeof htmlData[ i ] === "number" || typeof htmlData[ i ] === "boolean" ) 199 { 200 newOptions[ key ] = htmlData[ i ]; 201 } 202 203 if( 'undefined' != typeof newOptions.autoplay_stopper && newOptions.autoplay_stopper == 1 ) 204 { 205 newOptions.autoplay_stopper = true; 206 } 207 } 208 209 return newOptions; 210 }, 211 212 _prepareSlides: function(options) 213 { 214 //if its a mobile device find all video slides that need to be altered 215 if( this.isMobile ) 216 { 217 var alter = this.$slider.find('.av-mobile-fallback-image'); 218 alter.each(function() 219 { 220 var current = $(this).removeClass('av-video-slide').data({'avia_video_events': true, 'video-ratio':0}), 221 fallback = current.data('mobile-img'), 222 fallback_link = current.data('fallback-link'), 223 appendTo = current.find('.avia-slide-wrap'); 224 225 current.find('.av-click-overlay, .mejs-mediaelement, .mejs-container').remove(); 226 227 if(!fallback) 228 { 229 $('<p class="av-fallback-message"><span>Please set a mobile device fallback image for this video in your wordpress backend</span></p>').appendTo(appendTo); 230 } 231 232 if(options && options.bg_slider) 233 { 234 current.data('img-url', fallback); 235 236 //if we got a fallback link we need to either replace the default link on mobile devices, or if there is no default link change the wrapping <div> to an <a> 237 if(fallback_link != "") 238 { 239 if(appendTo.is('a')) 240 { 241 appendTo.attr('href', fallback_link); 242 } 243 else 244 { 245 appendTo.find('a').remove(); 246 appendTo.replaceWith(function(){ 247 var cur_slide = $(this); 248 return $("<a>").attr({'data-rel': cur_slide.data('rel'), 'class': cur_slide.attr('class'), 'href': fallback_link} ).append( $(this).contents() ); 249 }); 250 251 appendTo = current.find('.avia-slide-wrap'); 252 } 253 254 if($.fn.avia_activate_lightbox) 255 { 256 current.parents('#main').avia_activate_lightbox(); 257 } 258 } 259 } 260 else 261 { 262 var image = '<img src="'+fallback+'" alt="" title="" />'; 263 var lightbox = false; 264 265 if( 'string' == typeof fallback_link && fallback_link.trim() != '' ) 266 { 267 if( appendTo.is('a') ) 268 { 269 appendTo.attr('href', fallback_link); 270 } 271 else 272 { 273 var rel = fallback_link.match(/\.(jpg|jpeg|gif|png)$/i) != null ? ' rel="lightbox" ' : ''; 274 image = '<a href="' + fallback_link.trim() + '"' + rel + '>' + image + '</a>'; 275 } 276 lightbox = true; 277 } 278 279 current.find('.avia-slide-wrap').append(image); 280 281 if( lightbox && $.fn.avia_activate_lightbox) 282 { 283 current.parents('#main').avia_activate_lightbox(); 284 } 285 } 286 287 }); 288 } 289 290 if ($('html').is('.pointer-device-fine')) 291 { 292 if( $('body').is('.avia-slider-video-controls-fix-support')) 293 { 294 avia_slider_video_controls_fix(this); 295 } 296 } 297 }, 298 299 //start preloading the background images 300 _bgPreloadImages: function(callback) 301 { 302 this._getImageURLS(); 303 304 this._preloadSingle(0, function() 305 { 306 this._kickOff(); 307 this._preloadNext(1); 308 }); 309 }, 310 311 //if we are using a background image slider, fetch the images from a data attribute and preload them one by one 312 _getImageURLS: function() 313 { 314 var _self = this; 315 316 //collect url strings of the images to preload 317 this.$slides.each( function(i) 318 { 319 _self.imageUrls[i] = []; 320 _self.imageUrls[i]['url'] = $(this).data("img-url"); 321 322 //if no image is passed we can set the slide to loaded 323 if(typeof _self.imageUrls[i]['url'] == 'string') 324 { 325 _self.imageUrls[i]['status'] = false;
326 } 327 else 328 { 329 _self.imageUrls[i]['status'] = true; 330 } 331 }); 332 }, 333 334 _preloadSingle: function(key, callback) 335 { 336 var _self = this, 337 objImage = new Image(); 338 339 if( typeof _self.imageUrls[key]['url'] == 'string' ) 340 { 341 $(objImage).on('load error', function() 342 { 343 _self.imageUrls[key]['status'] = true; 344 _self.$slides.eq(key).css('background-image','url(' + _self.imageUrls[key]['url'] + ')'); 345 346 if( typeof callback == 'function' ) 347 { 348 callback.apply( _self, [objImage, key] ); 349 } 350 }); 351 352 if(_self.imageUrls[key]['url'] != "") 353 { 354 objImage.src = _self.imageUrls[key]['url']; 355 } 356 else 357 { 358 $(objImage).trigger('error'); 359 } 360 } 361 else 362 { 363 if( typeof callback == 'function' ) 364 { 365 callback.apply( _self, [objImage, key] ); 366 } 367 } 368 }, 369 370 _preloadNext: function(key) 371 { 372 if(typeof this.imageUrls[key] != "undefined") 373 { 374 this._preloadSingle(key, function() 375 { 376 this._preloadNext(key + 1); 377 }); 378 } 379 }, 380 381 382 //bind click events of slide controlls to the public functions 383 _bindEvents: function() 384 { 385 var self = this, 386 win = $( window ); 387 388 this.$slider.on( 'click', '.next-slide', this.next.bind( this ) ); 389 this.$slider.on( 'click', '.prev-slide', this.previous.bind( this ) ); 390 this.$slider.on( 'click', '.goto-slide', this.go2.bind( this ) ); 391 392 if( this.options.hoverpause ) 393 { 394 this.$slider.on( 'mouseenter', this.pause.bind( this ) ); 395 this.$slider.on( 'mouseleave', this.resume.bind( this ) ); 396 } 397 398 // activate permanent caption link of image 399 if( this.permaCaption.length ) 400 { 401 this.permaCaption.on( 'click', this._routePermaCaptionClick ); 402 this.$slider.on( 'avia_slider_first_slide avia_slider_last_slide avia_slider_navigate_slide', this._setPermaCaptionPointer.bind( this ) ); 403 } 404 405 if( this.options.stopinfiniteloop && this.options.autoplay ) 406 { 407 if( this.options.stopinfiniteloop == 'last' ) 408 { 409 this.$slider.on( 'avia_slider_last_slide', this._stopSlideshow.bind( this ) ); 410 } 411 else if( this.options.stopinfiniteloop == 'first' ) 412 { 413 this.$slider.on( 'avia_slider_first_slide', this._stopSlideshow.bind( this ) ); 414 } 415 } 416 417 if( this.options.carousel === 'yes' ) 418 { 419 // recalculate carousel dimensions on viewport size change 420 // use on desktop only, debouncedresize fires on scroll on mobile 421 if( ! this.isMobile ) 422 { 423 win.on( 'debouncedresize', this._buildCarousel.bind( this ) ); 424 } 425 } 426 else 427 { 428 win.on( 'debouncedresize.aviaSlider', this._setSize.bind( this ) ); 429 } 430 431 if( ! this.options.noNavigation ) 432 { 433 //if its a desktop browser add arrow navigation, otherwise add touch nav (also for touch devices) 434 if( ! this.isMobile ) 435 { 436 this.$slider.avia_keyboard_controls(); 437 } 438 439 if( this.isMobile || this.isTouchDevice ) 440 { 441 this.$slider.avia_swipe_trigger(); 442 } 443 } 444 445 self._attach_video_events(); 446 }, 447 448 //kickoff the slider by binding all functions to slides and buttons, show the first slide and start autoplay 449 _kickOff: function() 450 { 451 var self = this, 452 first_slide = self.$slides.eq(0), 453 video = first_slide.data('video-ratio'); 454 455 // bind events to to the controll buttons 456 self._bindEvents(); 457 self._set_slide_arrows_visibility(); 458 459 this.$slider.removeClass('av-default-height-applied'); 460 461 //show the first slide. if its a video set the correct size, otherwise make sure to remove the % padding 462 if( video ) 463 { 464 self._setSize( true ); 465 } 466 else 467 { 468 if( this.options.keep_padding != true ) 469 { 470 self.$sliderUl.css('padding',0); 471 self.$win.trigger('av-height-change'); 472 } 473 } 474 475 self._setCenter(); 476 477 if( this.options.carousel === 'no' ) 478 { 479 first_slide.addClass( 'next-active-slide' ); 480 first_slide.css( {visibility:'visible', opacity:0} ).avia_animate( {opacity:1}, function() 481 { 482 var current = $(this).addClass( 'active-slide' ); 483 484 if( self.permaCaption.length ) 485 { 486 self.permaCaption.addClass( 'active-slide' ); 487 } 488 }); 489 } 490 491 self.$slider.trigger( 'avia_slider_first_slide' ); 492 493 494 // start autoplay if active 495 if( self.options.autoplay ) 496 { 497 self._startSlideshow(); 498 } 499 500 // prepare carousel if active 501 if( self.options.carousel === 'yes' ) 502 { 503 self._buildCarousel(); 504 } 505 506 self.$slider.trigger( '_kickOff' ); 507 }, 508 509 _set_slide_arrows_visibility: function() 510 { 511 // special use case - hardcoded as only used in timeline 512 if( this.options.carousel == 'yes' ) 513 { 514 if( 0 == this.currentCarousel ) 515 { 516 this.slide_arrows.removeClass( 'av-visible-prev' ); 517 this.slide_arrows.addClass( 'av-visible-next' ); 518 } 519 else if( this.currentCarousel + this.options.carouselSlidesToShow >= this.itemsCount ) 520 { 521 this.slide_arrows.addClass( 'av-visible-prev' ); 522 this.slide_arrows.removeClass( 'av-visible-next' ); 523 } 524 else 525 { 526 this.slide_arrows.addClass( 'av-visible-prev' ); 527 this.slide_arrows.addClass( 'av-visible-next' ); 528 } 529 530 return; 531 } 532 533 if( 'endless' == this.options.loop_autoplay || 'manual-endless' == this.options.loop_manual ) 534 { 535 this.slide_arrows.addClass( 'av-visible-prev' ); 536 this.slide_arrows.addClass( 'av-visible-next' ); 537 } 538 else if( 0 == this.current ) 539 { 540 this.slide_arrows.removeClass( 'av-visible-prev' ); 541 this.slide_arrows.addClass( 'av-visible-next' ); 542 } 543 else if( this.current + 1 >= this.itemsCount ) 544 { 545 this.slide_arrows.addClass( 'av-visible-prev' ); 546 this.slide_arrows.removeClass( 'av-visible-next' ); 547 } 548 else 549 {
550 this.slide_arrows.addClass( 'av-visible-prev' ); 551 this.slide_arrows.addClass( 'av-visible-next' ); 552 } 553 }, 554 555 _buildCarousel: function() 556 { 557 var self = this, 558 stageWidth = this.$slider.outerWidth(), 559 slidesWidth = parseInt(stageWidth / this.options.carouselSlidesToShow), 560 windowWidth = window.innerWidth || $(window).width(); 561 562 // responsive carousel 563 if( this.options.carouselResponsive && 564 this.options.carouselResponsive.length && 565 this.options.carouselResponsive !== null ) 566 { 567 568 for( var breakpoint in this.options.carouselResponsive ) 569 { 570 var breakpointValue = this.options.carouselResponsive[breakpoint]['breakpoint']; 571 var newSlidesToShow = this.options.carouselResponsive[breakpoint]['settings']['carouselSlidesToShow']; 572 573 if( breakpointValue >= windowWidth ) 574 { 575 slidesWidth = parseInt(stageWidth / newSlidesToShow); 576 this.options.carouselSlidesToShow = newSlidesToShow; 577 } 578 } 579 } 580 581 // set width and height for each slide 582 this.slideWidthCarousel = slidesWidth; 583 584 this.$slides.each(function(i) 585 { 586 $(this).width(slidesWidth); 587 }); 588 589 // set width for the UL 590 var slideTrackWidth = slidesWidth * this.itemsCount; 591 this.$sliderUl.width(slideTrackWidth).css( 'transform', 'translateX(0px)' ); 592 593 // hide nav if not needed 594 if( this.options.carouselSlidesToShow >= this.itemsCount ) 595 { 596 this.$slider.find('.av-timeline-nav').hide(); 597 } 598 }, 599 600 //calculate which slide should be displayed next and call the executing transition function 601 _navigate: function( dir, pos ) 602 { 603 if( this.isAnimating || this.itemsCount < 2Â || ! this.$slider.is( ':visible' ) ) 604 { 605 return false; 606 } 607 608 this.isAnimating = true; 609 610 // current item's index 611 this.prev = this.current; 612 613 // if position is passed 614 if( pos !== undefined ) 615 { 616 this.current = pos; 617 dir = this.current > this.prev ? 'next' : 'prev'; 618 } 619 620 // if not check the boundaries 621 else if( dir === 'next' ) 622 { 623 this.current = this.current < this.itemsCount - 1 ? this.current + 1 : 0; 624 625 if( this.current === 0 && this.options.autoplay_stopper && this.options.autoplay ) 626 { 627 this.isAnimating = false; 628 this.current = this.prev; 629 this._stopSlideshow(); 630 return false; 631 } 632 633 // check if we can rotate 634 if( 0 === this.current ) 635 { 636 if( 'endless' != this.options.loop_autoplay && 'manual-endless' != this.options.loop_manual ) 637 { 638 this.isAnimating = false; 639 this.current = this.prev; 640 return false; 641 } 642 } 643 } 644 else if( dir === 'prev' ) 645 { 646 this.current = this.current > 0 ? this.current - 1 : this.itemsCount - 1; 647 648 // check if we can rotate 649 if( this.itemsCount - 1 === this.current ) 650 { 651 if( 'endless' != this.options.loop_autoplay && 'manual-endless' != this.options.loop_manual ) 652 { 653 this.isAnimating = false; 654 this.current = this.prev; 655 return false; 656 } 657 } 658 } 659 660 //set goto button 661 this.gotoButtons.removeClass( 'active' ).eq( this.current ).addClass( 'active' ); 662 this._set_slide_arrows_visibility(); 663 664 //set slideshow size if carousel not in use 665 if( this.options.carousel === 'no' ) 666 { 667 this._setSize(); 668 } 669 670 //if we are using a background slider make sure that the image is loaded. if not preload it, then show the slide 671 if( this.options.bg_slider == true ) 672 { 673 if( this.imageUrls[this.current]['status'] == true ) 674 { 675 this['_' + this.options.animation].call(this, dir); 676 } 677 else 678 { 679 this.loader.show(); 680 this._preloadSingle(this.current, function() 681 { 682 this['_' + this.options.animation].call( this, dir ); 683 this.loader.hide(); 684 }); 685 } 686 } 687 else //no background loader -> images are already loaded 688 { 689 //call the executing function. for example _slide, or _fade. since the function call is absed on a var we can easily extend the slider with new animations 690 this['_' + this.options.animation].call( this, dir ); 691 } 692 693 if( this.current == 0 ) 694 { 695 this.loopCount++; 696 this.$slider.trigger( 'avia_slider_first_slide' ); 697 } 698 else if( this.current == this.itemsCount - 1 ) 699 { 700 this.$slider.trigger( 'avia_slider_last_slide' ); 701 } 702 else 703 {
704 this.$slider.trigger( 'avia_slider_navigate_slide' ); 705 } 706 }, 707 708 //if the next slide has a different height than the current change the slideshow height 709 _setSize: function(instant) 710 { 711 //if images are attached as bg images the slider has a fixed height 712 if( this.options.bg_slider == true ) 713 { 714 return; 715 } 716 717 var self = this, 718 slide = this.$slides.eq(this.current), 719 img = slide.find('img'), 720 current = Math.floor(this.$sliderUl.height()), 721 ratio = slide.data('video-ratio'), 722 setTo = ratio ? this.$sliderUl.width() / ratio : Math.floor(slide.height()), 723 video_height = slide.data('video-height'), //forced video height %. needs to be set only once 724 video_toppos = slide.data('video-toppos'); //forced video top position 725 726 this.$sliderUl.height(current).css('padding',0); //make sure to set the slideheight to an actual value 727 728 if(setTo != current) 729 { 730 if(instant == true) 731 { 732 this.$sliderUl.css({height:setTo}); 733 this.$win.trigger('av-height-change'); 734 } 735 else 736 { 737 this.$sliderUl.avia_animate({height:setTo}, function() 738 { 739 self.$win.trigger('av-height-change'); 740 }); 741 } 742 } 743 744 this._setCenter(); 745 746 if(video_height && video_height!= "set") 747 { 748 slide.find('iframe, embed, video, object, .av_youtube_frame').css({height: video_height + '%', top: video_toppos + '%'}); 749 slide.data('video-height','set'); 750 } 751 }, 752 753 _setCenter: function() 754 { 755 //if the image has a min width and is larger than the slider center it 756 //positon img based on caption. right caption->left pos, left caption -> right pos 757 var slide = this.$slides.eq(this.current), 758 img = slide.find('img'), 759 min_width = parseInt(img.css('min-width'),10), 760 slide_width = slide.width(), 761 caption = slide.find('.av-slideshow-caption'), 762 css_left = ((slide_width - min_width) / 2); 763 764 if(caption.length) 765 { 766 if(caption.is('.caption_left')) 767 { 768 css_left = ((slide_width - min_width) / 1.5); 769 } 770 else if(caption.is('.caption_right')) 771 { 772 css_left = ((slide_width - min_width) / 2.5); 773 } 774 } 775 776 if(slide_width >= min_width) 777 { 778 css_left = 0; 779 } 780 781 img.css({left:css_left}); 782 }, 783 784 _carouselmove : function(){ 785 786 // var offset = (this.options.carouselSlidesToScroll*this.slideWidthCarousel)*this.currentCarousel; 787 var offset = this.slideWidthCarousel * this.currentCarousel; 788 this.$sliderUl.css('transform', 'translateX(-' + offset + 'px)'); 789 }, 790 791 _carouselslide: function(dir) 792 { 793 console.log( '_carouselslide:', dir, this.currentCarousel ); 794 795 if( dir === 'next' ) 796 { 797 if (this.options.carouselSlidesToShow + this.currentCarousel < this.itemsCount) 798 { 799 this.currentCarousel++; 800 this._carouselmove(); 801 } 802 } 803 else if( dir === 'prev' ) 804 { 805 if( this.currentCarousel > 0 ) 806 { 807 this.currentCarousel--; 808 this._carouselmove(); 809 } 810 } 811 812 this._set_slide_arrows_visibility(); 813 814 this.isAnimating = false; 815 }, 816 817 _slide: function(dir) 818 { 819 var dynamic = false, //todo: pass by option if a slider is dynamic 820 modifier = dynamic == true ? 2 : 1, 821 sliderWidth = this.$slider.width(), 822 direction = dir === 'next' ? -1 : 1, 823 property = this.browserPrefix + 'transform', 824 reset = {}, 825 transition = {}, 826 transition2 = {}, 827 trans_val = ( sliderWidth * direction * -1 ), 828 trans_val2 = ( sliderWidth * direction ) / modifier; 829 830 //do a css3 animation 831 if(this.cssActive) 832 { 833 property = this.browserPrefix + 'transform'; 834 835 //do a translate 3d transformation if available, since it uses hardware acceleration 836 if(this.css3DActive) 837 { 838 reset[property] = "translate3d(" + trans_val + "px, 0, 0)"; 839 transition[property] = "translate3d(" + trans_val2 + "px, 0, 0)"; 840 transition2[property] = "translate3d(0,0,0)"; 841 } 842 else //do a 2d transform. still faster than a position "left" change 843 {
844 reset[property] = "translate(" + trans_val + "px,0)"; 845 transition[property] = "translate(" + trans_val2 + "px,0)"; 846 transition2[property] = "translate(0,0)"; 847 } 848 } 849 else 850 { 851 reset.left = trans_val; 852 transition.left = trans_val2; 853 transition2.left = 0; 854 } 855 856 if(dynamic) 857 { 858 transition['z-index'] = "1"; 859 transition2['z-index'] = "2"; 860 } 861 862 this._slide_animate(reset, transition, transition2); 863 }, 864 865 _slide_up: function(dir) 866 { 867 var dynamic = true, //todo: pass by option if a slider is dynamic 868 modifier = dynamic == true ? 2 : 1, 869 sliderHeight = this.$slider.height(), 870 direction = dir === 'next' ? -1 : 1, 871 property = this.browserPrefix + 'transform', 872 reset = {}, 873 transition = {}, 874 transition2 = {}, 875 trans_val = ( sliderHeight * direction * -1), 876 trans_val2 = ( sliderHeight * direction) / modifier; 877 878 //do a css3 animation 879 if(this.cssActive) 880 { 881 property = this.browserPrefix + 'transform'; 882 883 //do a translate 3d transformation if available, since it uses hardware acceleration 884 if(this.css3DActive) 885 { 886 reset[property] = "translate3d( 0," + trans_val + "px, 0)"; 887 transition[property] = "translate3d( 0," + trans_val2 + "px, 0)"; 888 transition2[property] = "translate3d(0,0,0)"; 889 } 890 else //do a 2d transform. still faster than a position "left" change 891 { 892 reset[property] = "translate( 0," + trans_val + "px)"; 893 transition[property] = "translate( 0," + trans_val2 + "px)"; 894 transition2[property] = "translate(0,0)"; } 895 } 896 else 897 { 898 reset.top = trans_val; 899 transition.top = trans_val2; 900 transition2.top = 0; 901 } 902 903 if(dynamic) 904 { 905 transition['z-index'] = "1"; 906 transition2['z-index'] = "2"; 907 } 908 this._slide_animate(reset, transition, transition2); 909 }, 910 911 912 //slide animation: do a slide transition by css3 transform if possible. if not simply do a position left transition 913 _slide_animate: function( reset , transition , transition2 ) 914 { 915 var self = this, 916 displaySlide = this.$slides.eq(this.current), 917 hideSlide = this.$slides.eq(this.prev); 918 919 hideSlide.trigger('pause'); 920 if( ! displaySlide.data('disableAutoplay') ) 921 { 922 if(displaySlide.hasClass('av-video-lazyload') && !displaySlide.hasClass('av-video-lazyload-complete')) 923 { 924 displaySlide.find('.av-click-to-play-overlay').trigger('click'); 925 } 926 else 927 { 928 displaySlide.trigger('play'); 929 } 930 } 931 932 displaySlide.css({visibility:'visible', zIndex:4, opacity:1, left
932:0, top:0}); 933 displaySlide.css(reset); 934 935 hideSlide.avia_animate(transition, this.options.transitionSpeed, this.options.easing); 936 937 var after_slide = function() 938 { 939 self.isAnimating = false; 940 displaySlide.addClass( 'active-slide' ); 941 hideSlide.css( {visibility:'hidden'} ).removeClass( 'active-slide next-active-slide' ); 942 self.$slider.trigger( 'avia-transition-done' ); 943 }; 944 945 if( self.options.show_slide_delay > 0 ) 946 { 947 setTimeout( function() 948 { 949 displaySlide.addClass( 'next-active-slide' ); 950 displaySlide.avia_animate( transition2, self.options.transitionSpeed, self.options.easing, after_slide ); 951 }, self.options.show_slide_delay ); 952 } 953 else 954 { 955 displaySlide.addClass( 'next-active-slide' ); 956 displaySlide.avia_animate( transition2, self.options.transitionSpeed, self.options.easing, after_slide ); 957 } 958 }, 959 960 //simple fade transition of the slideshow 961 _fade: function() 962 { 963 var self = this, 964 displaySlide = this.$slides.eq(this.current), 965 hideSlide = this.$slides.eq(this.prev), 966 properties = {visibility:'visible', zIndex:3, opacity:0}, 967 fadeCallback = function() 968 { 969 self.isAnimating = false; 970 displaySlide.addClass( 'active-slide' ); 971 hideSlide.css({visibility:'hidden', zIndex:2}).removeClass( 'active-slide next-active-slide' ); 972 self.$slider.trigger( 'avia-transition-done' ); 973 }; 974 975 hideSlide.trigger('pause'); 976 977 if( ! displaySlide.data('disableAutoplay') ) 978 { 979 if(displaySlide.hasClass('av-video-lazyload') && ! displaySlide.hasClass('av-video-lazyload-complete')) 980 { 981 displaySlide.find('.av-click-to-play-overlay').trigger('click'); 982 } 983 else 984 { 985 displaySlide.trigger('play'); 986 } 987 } 988 989 displaySlide.addClass( 'next-active-slide' ); 990 991 if( self.options.fullfade == true ) 992 { 993 hideSlide.avia_animate( {opacity:0}, 200, 'linear', function() 994 { 995 displaySlide.css( properties ).avia_animate( {opacity:1}, self.options.transitionSpeed, 'linear', fadeCallback ); 996 }); 997 } 998 else 999 { 1000 if( self.current === 0 ) 1001 { 1002 hideSlide.avia_animate( {opacity:0}, self.options.transitionSpeed/2, 'linear' ); 1003 displaySlide.css(properties).avia_animate( {opacity:1}, self.options.transitionSpeed/2, 'linear', fadeCallback ); 1004 } 1005 else 1006 { 1007 displaySlide.css(properties).avia_animate( {opacity:1}, self.options.transitionSpeed/2, 'linear', function() 1008 { 1009 hideSlide.avia_animate({opacity:0}
1009, 200, 'linear', fadeCallback ); 1010 }); 1011 } 1012 } 1013 }, 1014 1015 /************************************************************************ 1016 Video functions 1017 *************************************************************************/ 1018 1019 //bind events to the video that tell the slider to autorotate once a video has been played 1020 _attach_video_events: function() 1021 { 1022 var self = this, 1023 $html = $('html'); 1024 1025 self.$slides.each( function(i) 1026 { 1027 var currentSlide = $(this), 1028 caption = currentSlide.find('.caption_fullwidth, .av-click-overlay'), 1029 mejs = currentSlide.find('.mejs-mediaelement'), 1030 lazyload = currentSlide.hasClass('av-video-lazyload') ? true : false; 1031 1032 1033 if( currentSlide.data('avia_video_events') != true ) 1034 { 1035 currentSlide.data('avia_video_events', true); 1036 1037 currentSlide.on('av-video-events-bound', { slide: currentSlide, wrap: mejs , iteration: i , self: self, lazyload: lazyload }, onReady); 1038 1039 currentSlide.on('av-video-ended', { slide: currentSlide , self: self}, onFinish); 1040 1041 currentSlide.on('av-video-play-executed', function(){ setTimeout( function(){ self.pause(); }, 100 ); } ); 1042 1043 caption.on('click', { slide: currentSlide }, toggle); 1044 1045 // also if the player was loaded before the _bindEvents function was bound trigger it manually 1046 if( currentSlide.is('.av-video-events-bound') ) 1047 { 1048 currentSlide.trigger('av-video-events-bound'); 1049 } 1050 1051 //if we are on the first slide and autoplay is enabled and lazy loading is enabled we need to simulate a click event to the lazy load container 1052 if( lazyload && i === 0 && ! currentSlide.data('disableAutoplay') ) 1053 { 1054 currentSlide.find('.av-click-to-play-overlay').trigger('click'); 1055 } 1056 } 1057 }); 1058 1059 1060 //function that takes care of events once the video is loaded for the first time. 1061 //needs to take into account 2 different scenarios: normally embedded videos or lazyloaded videos that start on user interaction/autoplay 1062 function onReady( event ) 1063 { 1064 //autostart for first slide 1065 if(event.data.iteration === 0) 1066 { 1067 event.data.wrap.css('opacity',0); 1068 1069 if( ! event.data.self.isMobile && ! event.data.slide.data('disableAutoplay') ) 1070 { 1071 event.data.slide.trigger('play'); 1072 }Â 1073 1074 setTimeout( function(){ event.data.wrap.avia_animate({opacity:1}, 400); }, 50 ); 1075 } 1076 else if( $html.is('.avia-msie') && ! event.data.slide.is('.av-video-service-html5') ) 1077 { 1078 /* 1079 * Internet Explorer fires the ready event for external videos once they become visible 1080 * as oposed to other browsers which always fire immediately. 1081 */ 1082 if( ! event.data.slide.data('disableAutoplay') ) 1083 { 1084 event.data.slide.trigger('play'); 1085 } 1086 } 1087 1088 1089 //make sure that the html5 element does not play if autoply is enabled but its not the first slide. 1090 //the autoplay attribute on the video element might cause this 1091 if( event.data.slide.is('.av-video-service-html5') && event.data.iteration !== 0 ) 1092 { 1093 event.data.slide.trigger('pause'); 1094 } 1095 1096 //make sure that lazyloaded videos always get started once a user clicks them 1097 if( event.data.lazyload) 1098 { 1099 event.data.slide.addClass('av-video-lazyload-complete'); 1100 event.data.slide.trigger('play'); 1101 } 1102 } 1103 1104 function onFinish( event ) 1105 { 1106 //if the video is not looped resume the slideshow 1107 if( ! event.data.slide.is('.av-single-slide') && ! event.data.slide.is('.av-loop-video') ) 1108 { 1109 event.data.slide.trigger('reset'); 1110 self._navigate( 'next' ); 1111 self.resume(); 1112 } 1113
1114 //safari 8 workaround for self hosted videos which wont loop by default 1115 if( event.data.slide.is('.av-loop-video') && event.data.slide.is('.av-video-service-html5') ) 1116 { 1117 if( $html.is('.avia-safari-8') ) 1118 { 1119 setTimeout( function() 1120 { 1121 event.data.slide.trigger('play'); 1122 }, 1 ); 1123 } 1124 } 1125 } 1126 1127 function toggle( event ) 1128 { 1129 if( event.target.tagName != "A" ) 1130 { 1131 event.data.slide.trigger('toggle'); 1132 } 1133 } 1134 }, 1135 1136 1137 /************************************************************************ 1138 Slideshow control functions 1139 *************************************************************************/ 1140 1141 _timer: function(callback, delay, first) 1142 { 1143 var self = this, 1144 start, 1145 remaining = delay; 1146 1147 self.timerId = 0; 1148 1149 this.pause = function() 1150 { 1151 window.clearTimeout(self.timerId); 1152 remaining -= new Date() - start; 1153 }; 1154 1155 this.resume = function() 1156 { 1157 start = new Date(); 1158 self.timerId = window.setTimeout(callback, remaining); 1159 }; 1160 1161 this.destroy = function() 1162 { 1163 window.clearTimeout(self.timerId); 1164 }; 1165 1166 this.resume(true); 1167 }, 1168 1169 //start autorotation 1170 _startSlideshow: function() 1171 { 1172 var self = this; 1173 1174 this.isPlaying = true; 1175 1176 this.slideshow = new this._timer( function() 1177 { 1178 self._navigate( 'next' ); 1179 1180 if( self.options.autoplay ) 1181 { 1182 self._startSlideshow(); 1183 } 1184 }, ( this.options.interval * 1000 ) ); 1185 }, 1186 1187 //stop autorotation 1188 _stopSlideshow: function() 1189 { 1190 if( this.options.autoplay ) 1191 { 1192 this.slideshow.destroy(); 1193 this.isPlaying = false; 1194 this.options.autoplay = false; 1195 } 1196 1197 this.options.autoplay = false; 1198 this.options.loop_autoplay = 'once'; 1199 this.$slider.removeClass( 'av-slideshow-autoplay' ).addClass( 'av-slideshow-manual' ); 1200 this.$slider.removeClass( 'av-loop-endless' ).addClass( 'av-loop-once' ); 1201 }, 1202 1203 // check if we have a link for the image and set cursor 1204 _setPermaCaptionPointer: function( e ) 1205 { 1206 if( ! this.permaCaption.length ) 1207 { 1208 return; 1209 } 1210 1211 var withLink = $( this.$slides[this.current] ).find( 'a' ).length; 1212 this.permaCaption.css( 'cursor', withLink ? 'pointer' : 'default' ); 1213 }, 1214 1215 // route perma caption to actual link of image, else allow bubble (e.g. for buttons) 1216 _routePermaCaptionClick: function( e ) 1217 { 1218 var active_slide_link = $(this).siblings( '.avia-slideshow-inner' ).find( '>.active-slide a' ); 1219 1220 if( active_slide_link.length ) 1221 { 1222 e.preventDefault(); 1223 1224 // jQuery trigger does not work !!! 1225 active_slide_link[0].click(); 1226 } 1227 }, 1228 1229 // public method: shows next image 1230 next: function(e) 1231 { 1232 e.preventDefault(); 1233 this._stopSlideshow(); 1234 this._navigate( 'next' ); 1235 }, 1236 1237 // public method: shows previous image 1238 previous: function(e) 1239 { 1240 e.preventDefault(); 1241 this._stopSlideshow(); 1242 this._navigate( 'prev' ); 1243 }, 1244 1245 // public method: goes to a specific image 1246 go2: function( pos ) 1247 { 1248 //if we didnt pass a number directly lets asume someone clicked on a link that triggered the goto transition 1249 if(isNaN(pos)) 1250 { 1251 //in that case prevent the default link behavior and set the slide number to the links hash 1252 pos.preventDefault(); 1253 pos = pos.currentTarget.hash.replace('#',''); 1254 } 1255 1256 pos -= 1; 1257 1258 if( pos === this.current || pos >= this.itemsCount || pos < 0 ) 1259 { 1260 return false; 1261 } 1262 1263 this._stopSlideshow(); 1264 this._navigate( false, pos ); 1265 1266 }, 1267 1268 // public method: starts the slideshow 1269 // any call to next(), previous() or goto() will stop the slideshow autoplay 1270 play: function() 1271 { 1272 if( !this.isPlaying ) 1273 { 1274 this.isPlaying = true; 1275 1276 this._navigate( 'next' ); 1277 this.options.autoplay = true; 1278 this._startSlideshow(); 1279 } 1280 1281 }, 1282 1283 // public methos: pauses the slideshow 1284 pause: function() 1285 { 1286 if( this.isPlaying ) 1287 { 1288 this.slideshow.pause(); 1289 } 1290 }, 1291 1292 // publiccmethos: resumes the slideshow 1293 resume: function() 1294 { 1295 if( this.isPlaying ) 1296 { 1297 this.slideshow.resume(); 1298 } 1299 }, 1300 1301 // public methos: destroys the instance 1302 destroy: function( callback ) 1303 { 1304 this.slideshow.destroy( callback ); 1305 } 1306 }; 1307 1308 //simple wrapper to call the slideshow. makes sure that the slide data is not applied twice 1309 $.fn.aviaSlider = function( options ) 1310 { 1311 return this.each(function() 1312 { 1313 var self = $.data( this, 'aviaSlider' ); 1314 1315 if( ! self ) 1316 { 1317 self = $.data( this, 'aviaSlider', new $.AviaSlider( options, this ) ); 1318 } 1319 }); 1320 }; 1321 1322})( 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.