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