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