1/** 2 * @name Owl Carousel - code name Phenix 3 * @author Bartosz Wojciechowski 4 * @release 2014 5 * Licensed under MIT 6 * 7 * @version 2.0.0-beta.1.8 8 * @versionNotes Not compatibile with Owl Carousel <2.0.0 9 */ 10 11/* 12 13To do: 14 15* Lazy Load Icon 16* prevent animationend bubling 17* itemsScaleUp 18* Test Zepto 19 20Callback events list: 21 22onInitBefore 23onInitAfter 24onResponsiveBefore 25onResponsiveAfter 26onTransitionStart 27onTransitionEnd 28onTouchStart 29onTouchEnd 30onChangeState 31onLazyLoaded 32onVideoPlay 33onVideoStop 34 35Custom events list: 36 37next.owl 38prev.owl 39goTo.owl 40jumpTo.owl 41addItem.owl 42removeItem.owl 43refresh.owl 44play.owl 45stop.owl 46stopVideo.owl 47 48*/ 49 50 51;(function ( $, window, document, undefined ) { 52 53 var defaults = { 54 items: 3, 55 loop: false, 56 center: false, 57 58 mouseDrag: true, 59 touchDrag: true, 60 pullDrag: true, 61 freeDrag: false, 62 63 margin: 0, 64 stagePadding: 0, 65 66 merge: false, 67 mergeFit: true, 68 autoWidth: false, 69 autoHeight: false, 70 71 startPosition: 0, 72 URLhashListener: false, 73 74 nav: false, 75 navRewind: true, 76 navText: ['prev','next'], 77 slideBy: 1, 78 dots: true, 79 dotsEach: false, 80 dotData: false, 81 82 lazyLoad: false, 83 lazyContent: false, 84 85 autoplay: false, 86 autoplayTimeout: 5000, 87 autoplayHoverPause: false, 88 89 smartSpeed: 250, 90 fluidSpeed: false, 91 autoplaySpeed: false, 92 navSpeed: false, 93 dotsSpeed: false, 94 dragEndSpeed: false, 95 96 responsive: {}, 97 responsiveRefreshRate : 200, 98 responsiveBaseElement: window, 99 responsiveClass: false, 100 101 video: false, 102 videoHeight: false, 103 videoWidth: false, 104 105 animateOut: false, 106 animateIn: false, 107 108 fallbackEasing: 'swing', 109 110 callbacks: false, 111 info: false, 112 113 nestedItemSelector: false, 114 itemElement: 'div', 115 stageElement: 'div', 116 117 //Classes and Names 118 themeClass: 'owl-theme', 119 baseClass: 'owl-carousel', 120 itemClass: 'owl-item', 121 centerClass: 'center', 122 activeClass: 'active', 123 navContainerClass: 'owl-nav', 124 navClass: ['owl-prev','owl-next'], 125 controlsClass: 'owl-controls', 126 dotClass: 'owl-dot', 127 dotsClass: 'owl-dots', 128 autoHeightClass: 'owl-height' 129 130 }; 131 132 // Reference to DOM elements 133 // Those with $ sign are jQuery objects 134 135 var dom = { 136 el: null, // main element 137 $el: null, // jQuery main element 138 stage: null, // stage 139 $stage: null, // jQuery stage 140 oStage: null, // outer stage 141 $oStage: null, // $ outer stage 142 $items: null, // all items, clones and originals included 143 $oItems: null, // original items 144 $cItems: null, // cloned items only 145 $cc: null, 146 $navPrev: null, 147 $navNext: null, 148 $page: null, 149 $nav: null, 150 $content: null 151 }; 152 153 /** 154 * Variables 155 * @since 2.0.0 156 */ 157 158 // Only for development process 159 160 // Widths 161 162 var width = { 163 el: 0, 164 stage: 0, 165 item: 0, 166 prevWindow: 0, 167 cloneLast: 0 168 }; 169 170 // Numbers 171 172 var num = { 173 items: 0, 174 oItems: 0, 175 cItems: 0, 176 active: 0, 177 merged: [], 178 nav: [], 179 allPages: 0 180 }; 181 182 // Positions 183 184 var pos = { 185 start: 0, 186 max: 0, 187 maxValue: 0, 188 prev: 0, 189 current: 0, 190 currentAbs: 0, 191 currentPage:0, 192 stage: 0, 193 items: [], 194 lsCurrent: 0 195 }; 196 197 // Drag/Touches 198 199 var drag = { 200 start: 0, 201 startX: 0, 202 startY: 0, 203 current: 0, 204 currentX: 0, 205 currentY: 0, 206 offsetX: 0, 207 offsetY: 0, 208 distance: null, 209 startTime: 0, 210 endTime: 0, 211 updatedX: 0, 212 targetEl: null 213 }; 214 215 // Speeds 216 217 var speed = { 218 onDragEnd: 300, 219 nav: 300, 220 css2speed: 0 221 222 }; 223 224 // States 225 226 var state = { 227 isTouch: false, 228 isScrolling: false, 229 isSwiping: false, 230 direction: false, 231 inMotion: false, 232 autoplay: false, 233 lazyContent: false 234 }; 235 236 // Event functions references 237 238 var e = { 239 _onDragStart: null, 240 _onDragMove: null, 241 _onDragEnd: null, 242 _transitionEnd: null, 243 _resizer: null, 244 _responsiveCall:null, 245 _goToLoop: null, 246 _checkVisibile: null, 247 _autoplay: null, 248 _pause: null, 249 _play: null, 250 _stop: null 251 }; 252 253 function Owl( element, options ) { 254 255 // add basic Owl information to dom element 256 257 element.owlCarousel = { 258 'name': 'Owl Carousel', 259 'author': 'Bartosz Wojciechowski',
260 'version': '2.0.0-beta.1.8', 261 'released': '03.05.2014' 262 }; 263 264 // Attach variables to object 265 // Only for development process 266 267 this.options = $.extend( {}, defaults, options); 268 this._options = $.extend( {}, defaults, options); 269 this.dom = $.extend( {}, dom); 270 this.width = $.extend( {}, width); 271 this.num = $.extend( {}, num); 272 this.pos = $.extend( {}, pos); 273 this.drag = $.extend( {}, drag); 274 this.speed = $.extend( {}, speed); 275 this.state = $.extend( {}, state); 276 this.e = $.extend( {}, e); 277 278 this.dom.el = element; 279 this.dom.$el = $(element); 280 this.init(); 281 } 282 283 /** 284 * init 285 * @since 2.0.0 286 */ 287 288 Owl.prototype.init = function(){ 289 290 this.fireCallback('onInitBefore'); 291 292 //Add base class 293 if(!this.dom.$el.hasClass(this.options.baseClass)){ 294 this.dom.$el.addClass(this.options.baseClass); 295 } 296 297 //Add theme class 298 if(!this.dom.$el.hasClass(this.options.themeClass)){ 299 this.dom.$el.addClass(this.options.themeClass); 300 } 301 302 //Add theme class 303 if(this.options.rtl){ 304 this.dom.$el.addClass('owl-rtl'); 305 } 306 307 // Check support 308 this.browserSupport(); 309 310 // Sort responsive items in array 311 this.sortOptions(); 312 313 // Update options.items on given size 314 this.setResponsiveOptions(); 315 316 if(this.options.autoWidth && this.state.imagesLoaded !== true){ 317 var imgs = this.dom.$el.find('img'); 318 if(imgs.length){ 319 this.preloadAutoWidthImages(imgs); 320 return false; 321 } 322 } 323 324 // Get and store window width 325 // iOS safari likes to trigger unnecessary resize event 326 this.width.prevWindow = this.windowWidth(); 327 328 // create stage object 329 this.createStage(); 330 331 // Append local content 332 this.fetchContent(); 333 334 // attach generic events 335 this.eventsCall(); 336 337 // attach custom control events 338 this.addCustomEvents(); 339 340 // attach generic events 341 this.internalEvents(); 342 343 this.dom.$el.addClass('owl-loading'); 344 this.refresh(true); 345 this.dom.$el.removeClass('owl-loading').addClass('owl-loaded'); 346 this.fireCallback('onInitAfter'); 347 }; 348 349 /** 350 * sortOptions 351 * @desc Sort responsive sizes 352 * @since 2.0.0 353 */ 354 355 Owl.prototype.sortOptions = function(){ 356 357 var resOpt = this.options.responsive; 358 this.responsiveSorted = {}; 359 var keys = [], 360 i, j, k; 361 for (i in resOpt){ 362 keys.push(i); 363 } 364 365 keys = keys.sort(function (a, b) {return a - b;}); 366 367 for (j = 0; j < keys.length; j++){ 368 k = keys[j]; 369 this.responsiveSorted[k] = resOpt[k]; 370 } 371 372 }; 373 374 /** 375 * setResponsiveOptions 376 * @since 2.0.0 377 */ 378 379 Owl.prototype.setResponsiveOptions = function(){ 380 if(this.options.responsive === false){return false;} 381 382 var width = this.windowWidth(); 383 var resOpt = this.options.responsive; 384 var i,j,k, minWidth; 385 386 // overwrite non resposnive options 387 for(k in this._options){ 388 if(k !== 'responsive'){ 389 this.options[k] = this._options[k]; 390 } 391 } 392 393 // find responsive width 394 for (i in this.responsiveSorted){ 395 if(i<= width){ 396 minWidth = i; 397 // set responsive options 398 for(j in this.responsiveSorted[minWidth]){ 399 this.options[j] = this.responsiveSorted[minWidth][j]; 400 } 401 402 } 403 } 404 this.num.breakpoint = minWidth; 405 406 // Responsive Class 407 if(this.options.responsiveClass){ 408 this.dom.$el.attr('class', 409 function(i, c){ 410 return c.replace(/\b owl-responsive-\S+/g, ''); 411 }).addClass('owl-responsive-'+minWidth); 412 } 413 414 415 }; 416 417 /** 418 * optionsLogic 419 * @desc Update option logic if necessery 420 * @since 2.0.0 421 */ 422 423 Owl.prototype.optionsLogic = function(){ 424 // Toggle Center class 425 this.dom.$el.toggleClass('owl-center',this.options.center); 426 427 // Scroll per - 'page' option will scroll per visible items number 428 // You can set this to any other number below visible items. 429 if(this.options.slideBy && this.options.slideBy === 'page'){ 430 this.options.slideBy = this.options.items; 431 } else if(this.options.slideBy > this.options.items){ 432 this.options.slideBy = this.options.items; 433 } 434 435 // if items number is less than in body 436 if(this.options.loop && this.num.oItems < this.options.items){ 437 this.options.loop = false; 438 } 439 440 if(this.num.oItems <= this.options.items){ 441 this.options.navRewind = false;
442 } 443 444 if(this.options.autoWidth){ 445 this.options.stagePadding = false; 446 this.options.dotsEach = 1; 447 this.options.merge = false; 448 } 449 if(this.state.lazyContent){ 450 this.options.loop = false; 451 this.options.merge = false; 452 this.options.dots = false; 453 this.options.freeDrag = false; 454 this.options.lazyContent = true; 455 } 456 457 if((this.options.animateIn || this.options.animateOut) && this.options.items === 1 && this.support3d){ 458 this.state.animate = true; 459 } else {this.state.animate = false;} 460 461 }; 462 463 /** 464 * createStage 465 * @desc Create stage and Outer-stage elements 466 * @since 2.0.0 467 */ 468 469 Owl.prototype.createStage = function(){ 470 var oStage = document.createElement('div'); 471 var stage = document.createElement(this.options.stageElement); 472 473 oStage.className = 'owl-stage-outer'; 474 stage.className = 'owl-stage'; 475 476 oStage.appendChild(stage); 477 this.dom.el.appendChild(oStage); 478 479 this.dom.oStage = oStage; 480 this.dom.$oStage = $(oStage); 481 this.dom.stage = stage; 482 this.dom.$stage = $(stage); 483 484 oStage = null; 485 stage = null; 486 }; 487 488 /** 489 * createItem 490 * @desc Create item container 491 * @since 2.0.0 492 */ 493 494 Owl.prototype.createItem = function(){ 495 var item = document.createElement(this.options.itemElement); 496 item.className = this.options.itemClass; 497 return item; 498 }; 499 500 /** 501 * fetchContent 502 * @since 2.0.0 503 */ 504 505 Owl.prototype.fetchContent = function(extContent){ 506 if(extContent){ 507 this.dom.$content = (extContent instanceof jQuery) ? extContent : $(extContent); 508 } 509 else if(this.options.nestedItemSelector){ 510 this.dom.$content= this.dom.$el.find('.'+this.options.nestedItemSelector).not('.owl-stage-outer'); 511 } 512 else { 513 this.dom.$content= this.dom.$el.children().not('.owl-stage-outer'); 514 } 515 // content length 516 this.num.oItems = this.dom.$content.length; 517 518 // init Structure 519 if(this.num.oItems !== 0){ 520 this.initStructure(); 521 } 522 }; 523 524 525 /** 526 * initStructure 527 * @param [refresh] - if refresh and not lazyContent then dont create normal structure 528 * @since 2.0.0 529 */ 530 531 Owl.prototype.initStructure = function(){ 532 533 // lazyContent needs at least 3*items 534 535 if(this.options.lazyContent && this.num.oItems >= this.options.items*3){ 536 this.state.lazyContent = true; 537 } else { 538 this.state.lazyContent = false; 539 } 540 541 if(this.state.lazyContent){ 542 543 // start position 544 this.pos.currentAbs = this.options.items; 545 546 //remove lazy content from DOM 547 this.dom.$content.remove(); 548 549 } else { 550 // create normal structure 551 this.createNormalStructure(); 552 } 553 }; 554 555 /** 556 * createNormalStructure 557 * @desc Create normal structure for small/mid weight content 558 * @since 2.0.0 559 */ 560 561 Owl.prototype.createNormalStructure = function(){ 562 for(var i = 0; i < this.num.oItems; i++){ 563 // fill 'owl-item' with content 564 var item = this.fillItem(this.dom.$content,i); 565 // append into stage 566 this.dom.$stage.append(item); 567 } 568 this.dom.$content = null; 569 }; 570 571 /** 572 * createCustomStructure 573 * @since 2.0.0 574 */ 575 576 Owl.prototype.createCustomStructure = function(howManyItems){ 577 for(var i = 0; i < howManyItems; i++){ 578 var emptyItem = this.createItem(); 579 var item = $(emptyItem); 580 581 this.setData(item,false); 582 this.dom.$stage.append(item); 583 } 584 }; 585 586 /** 587 * createLazyContentStructure 588 * @desc Create lazyContent structure for large content and better mobile experience 589 * @since 2.0.0 590 */ 591 592 Owl.prototype.createLazyContentStructure = function(refresh){ 593 if(!this.state.lazyContent){return false;} 594 595 // prevent recreate - to do 596 if(refresh && this.dom.$stage.children().length === this.options.items*3){ 597 return false; 598 } 599 // remove items from stage 600 this.dom.$stage.empty(); 601 602 // create custom structure 603 this.createCustomStructure(3*this.options.items); 604 }; 605 606 /** 607 * fillItem 608 * @desc Fill empty item container with provided content 609 * @since 2.0.0 610 * @param [content] - string/$dom - passed owl-item 611 * @param [i] - index in jquery object 612 * return $ new object 613 */ 614 615 Owl.prototype.fillItem = function(content,i){ 616 var emptyItem = this.createItem(); 617 var c = content[i] || content; 618 // set item data 619 var traversed = this.traversContent(c); 620 this.setData(emptyItem,false,traversed); 621 return $(emptyItem).append(c); 622 }; 623 624 /** 625 * traversContent 626 * @since 2.0.0 627 * @param [c] - content 628 * return object 629 */ 630 631 Owl.prototype.traversContent = function(c){ 632 var $c = $(c), dotValue, hashValue; 633 if(this.options.dotData){ 634 dotValue = $c.find('[data-dot]').andSelf().data('dot'); 635 } 636 // update URL hash
637 if(this.options.URLhashListener){ 638 hashValue = $c.find('[data-hash]').andSelf().data('hash'); 639 } 640 return { 641 dot : dotValue || false, 642 hash : hashValue || false 643 }; 644 }; 645 646 647 /** 648 * setData 649 * @desc Set item jQuery Data 650 * @since 2.0.0 651 * @param [item] - dom - passed owl-item 652 * @param [cloneObj] - $dom - passed clone item 653 */ 654 655 656 Owl.prototype.setData = function(item,cloneObj,traversed){ 657 var dot,hash; 658 if(traversed){ 659 dot = traversed.dot; 660 hash = traversed.hash; 661 } 662 var itemData = { 663 index: false, 664 indexAbs: false, 665 posLeft: false, 666 clone: false, 667 active: false, 668 loaded: false, 669 lazyLoad: false, 670 current: false, 671 width: false, 672 center: false, 673 page: false, 674 hasVideo: false, 675 playVideo: false, 676 dot: dot, 677 hash: hash 678 }; 679 680 // copy itemData to cloned item 681 682 if(cloneObj){ 683 itemData = $.extend({}, itemData, cloneObj.data('owl-item')); 684 } 685 686 $(item).data('owl-item', itemData); 687 }; 688 689 /** 690 * updateLocalContent 691 * @since 2.0.0 692 */ 693 694 Owl.prototype.updateLocalContent = function(){ 695 this.dom.$oItems = this.dom.$stage.find('.'+this.options.itemClass).filter(function(){ 696 return $(this).data('owl-item').clone === false; 697 }); 698 699 this.num.oItems = this.dom.$oItems.length; 700 //update index on original items 701 702 for(var k = 0; k<this.num.oItems; k++){ 703 var item = this.dom.$oItems.eq(k); 704 item.data('owl-item').index = k; 705 } 706 }; 707 708 /** 709 * checkVideoLinks 710 * @desc Check if for any videos links 711 * @since 2.0.0 712 */ 713 714 Owl.prototype.checkVideoLinks = function(){ 715 if(!this.options.video){return false;} 716 var videoEl,item; 717 718 for(var i = 0; i<this.num.items; i++){ 719 720 item = this.dom.$items.eq(i); 721 if(item.data('owl-item').hasVideo){ 722 continue; 723 } 724 725 videoEl = item.find('.owl-video'); 726 if(videoEl.length){ 727 this.state.hasVideos = true; 728 this.dom.$items.eq(i).data('owl-item').hasVideo = true; 729 videoEl.css('display','none'); 730 this.getVideoInfo(videoEl,item); 731 } 732 } 733 }; 734 735 /** 736 * getVideoInfo 737 * @desc Get Video ID and Type (YouTube/Vimeo only) 738 * @since 2.0.0 739 */ 740 741 Owl.prototype.getVideoInfo = function(videoEl,item){ 742 743 var info, type, id, 744 vimeoId = videoEl.data('vimeo-id'), 745 youTubeId = videoEl.data('youtube-id'), 746 width = videoEl.data('width') || this.options.videoWidth, 747 height = videoEl.data('height') || this.options.videoHeight, 748 url = videoEl.attr('href'); 749 750 if(vimeoId){ 751 type = 'vimeo'; 752 id = vimeoId; 753 } else if(youTubeId){ 754 type = 'youtube'; 755 id = youTubeId; 756 } else if(url){ 757 id = url.match(/(http:|https:|)\/\/(player.|www.)?(vimeo\.com|youtu(be\.com|\.be|be\.googleapis\.com))\/(video\/|embed\/|watch\?v=|v\/)?([A-Za-z0-9._%-]*)(\&\S+)?/); 758 759 if (id[3].indexOf('youtu') > -1) { 760 type = 'youtube'; 761 } else if (id[3].indexOf('vimeo') > -1) { 762 type = 'vimeo'; 763 } 764 id = id[6]; 765 } else { 766 throw new Error('Missing video link.'); 767 } 768 769 item.data('owl-item').videoType = type; 770 item.data('owl-item').videoId = id; 771 item.data('owl-item').videoWidth = width; 772 item.data('owl-item').videoHeight = height; 773 774 info = { 775 type: type, 776 id: id 777 }; 778 779 // Check dimensions 780 var dimensions = width && height ? 'style="width:'+width+'px;height:'+height+'px;"' : ''; 781 782 // wrap video content into owl-video-wrapper div 783 videoEl.wrap('<div class="owl-video-wrapper"'+dimensions+'></div>'); 784 785 this.createVideoTn(videoEl,info); 786 }; 787 788 /** 789 * createVideoTn 790 * @desc Create Video Thumbnail 791 * @since 2.0.0 792 */ 793 794 Owl.prototype.createVideoTn = function(videoEl,info){ 795 796 var tnLink,icon,height; 797 var customTn = videoEl.find('img'); 798 var srcType = 'src'; 799 var lazyClass = ''; 800 var that = this; 801 802 if(this.options.lazyLoad){ 803 srcType = 'data-src'; 804 lazyClass = 'owl-lazy'; 805 } 806 807 // Custom thumbnail 808 809 if(customTn.length){ 810 addThumbnail(customTn.attr(srcType)); 811 customTn.remove(); 812 return false; 813 } 814 815 function addThumbnail(tnPath){ 816 icon = '<div class="owl-video-play-icon"></div>'; 817 818 if(that.options.lazyLoad){ 819 tnLink = '<div class="owl-video-tn '+ lazyClass +'" '+ srcType +'="'+ tnPath +'"></div>'; 820 } else{ 821 tnLink = '<div class="owl-video-tn" style="opacity:1;background-image:url(' + tnPath + ')"></div>'; 822 } 823 videoEl.after(tnLink); 824 videoEl.after(icon); 825 } 826 827 if(info.type === 'youtube'){ 828 var path = "http://img.youtube.com/vi/"+ info.id +"/hqdefault.jpg"; 829 addThumbnail(path); 830 } else 831 if(info.type === 'vimeo'){ 832 $.ajax({ 833 type:'GET', 834 url: 'http://vimeo.com/api/v2/video/' + info.id + '.json', 835 jsonp: 'callback', 836 dataType: 'jsonp', 837 success: function(data){ 838 var path = data[0].thumbnail_large; 839 addThumbnail(path); 840 if(that.options.loop){ 841 that.updateItemState(); 842 } 843 } 844 }); 845 } 846 }; 847 848 /** 849 * stopVideo 850 * @since 2.0.0 851 */ 852 853 Owl.prototype.stopVideo = function(){ 854 this.fireCallback('onVideoStop'); 855 var item = this.dom.$items.eq(this.state.videoPlayIndex); 856 item.find('.owl-video-frame').remove(); 857 item.removeClass('owl-video-playing'); 858 this.state.videoPlay = false;
859 }; 860 861 /** 862 * playVideo 863 * @since 2.0.0 864 */ 865 866 Owl.prototype.playVideo = function(ev){ 867 this.fireCallback('onVideoPlay'); 868 869 if(this.state.videoPlay){ 870 this.stopVideo(); 871 } 872 var videoLink,videoWrap, 873 target = $(ev.target || ev.srcElement), 874 item = target.closest('.'+this.options.itemClass); 875 876 var videoType = item.data('owl-item').videoType, 877 id = item.data('owl-item').videoId, 878 width = item.data('owl-item').videoWidth || Math.floor(item.data('owl-item').width - this.options.margin), 879 height = item.data('owl-item').videoHeight || this.dom.$stage.height(); 880 881 if(videoType === 'youtube'){ 882 videoLink = "<iframe width=\""+ width +"\" height=\""+ height +"\" src=\"http://www.youtube.com/embed/" + id + "?autoplay=1&v=" + id + "\" frameborder=\"0\" allowfullscreen></iframe>"; 883 } else if(videoType === 'vimeo'){ 884 videoLink = '<iframe src="http://player.vimeo.com/video/'+ id +'?autoplay=1" width="'+ width +'" height="'+ height +'" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>'; 885 } 886 887 item.addClass('owl-video-playing'); 888 this.state.videoPlay = true; 889 this.state.videoPlayIndex = item.data('owl-item').indexAbs; 890 891 videoWrap = $('<div style="height:'+ height +'px; width:'+ width +'px" class="owl-video-frame">' + videoLink + '</div>'); 892 target.after(videoWrap); 893 }; 894 895 /** 896 * loopClone 897 * @desc Make a clones for infinity loop 898 * @since 2.0.0 899 */ 900 901 Owl.prototype.loopClone = function(){ 902 if(!this.options.loop || this.state.lazyContent || this.num.oItems < this.options.items){return false;} 903 904 var firstClone, lastClone, i, 905 num = this.options.items, 906 lastNum = this.num.oItems-1; 907 908 // if neighbour margin then add one more duplicat 909 if(this.options.stagePadding && this.options.items === 1){ 910 num+=1; 911 } 912 this.num.cItems = num * 2; 913 914 for(i = 0; i < num; i++){ 915 // Clone item 916 var first = this.dom.$oItems.eq(i).clone(true,true); 917 var last = this.dom.$oItems.eq(lastNum-i).clone(true,true); 918 firstClone = $(first[0]).addClass('cloned'); 919 lastClone = $(last[0]).addClass('cloned'); 920 921 // set clone data 922 // Somehow data has reference to same data id in cash 923 924 this.setData(firstClone[0],first); 925 this.setData(lastClone[0],last); 926 927 firstClone.data('owl-item').clone = true; 928 lastClone.data('owl-item').clone = true; 929 930 this.dom.$stage.append(firstClone); 931 this.dom.$stage.prepend(lastClone); 932 933 firstClone = lastClone = null; 934 } 935 936 this.dom.$cItems = this.dom.$stage.find('.'+this.options.itemClass).filter(function(){ 937 return $(this).data('owl-item').clone === true; 938 }); 939 }; 940 941 /** 942 * reClone 943 * @desc Update Cloned elements 944 * @since 2.0.0 945 */ 946 947 Owl.prototype.reClone = function(){ 948 // remove cloned items 949 if(this.dom.$cItems !== null){ // && (this.num.oItems !== 0 && this.num.oItems <= this.options.items)){ 950 this.dom.$cItems.remove(); 951 this.dom.$cItems = null; 952 this.num.cItems = 0; 953 } 954 955 if(!this.options.loop){ 956 return; 957 } 958 // generete new elements 959 this.loopClone(); 960 }; 961 962 /** 963 * calculate 964 * @desc Update item index data 965 * @since 2.0.0 966 */ 967 968 Owl.prototype.calculate = function(){ 969 970 var i,j,k,dist,posLeft=0,fullWidth=0; 971 972 // element width minus neighbour 973 this.width.el = this.dom.$el.width() - (this.options.stagePadding*2); 974 975 //to check 976 this.width.view = this.dom.$el.width(); 977 978 // calculate width minus addition margins 979 var elMinusMargin = this.width.el - (this.options.margin * (this.options.items === 1 ? 0 : this.options.items -1)); 980 981 // calculate element width and item width 982 this.width.el = this.width.el + this.options.margin; 983 this.width.item = ((elMinusMargin / this.options.items) + this.options.margin).toFixed(3); 984 985 this.dom.$items = this.dom.$stage.find('.owl-item'); 986 this.num.items = this.dom.$items.length; 987 988 //change to autoWidths 989 if(this.options.autoWidth){ 990 this.dom.$items.css('width',''); 991 } 992 993 // Set grid array 994 this.pos.items = []; 995 this.num.merged = []; 996 this.num.nav = []; 997 998 // item distances 999 if(this.options.rtl){ 1000 dist = this.options.center ? -((this.width.el)/2) : 0; 1001 } else { 1002 dist = this.options.center ? (this.width.el)/2 : 0; 1003 } 1004 1005 this.width.mergeStage = 0; 1006 1007 // Calculate items positions 1008 for(i = 0; i<this.num.items; i++){ 1009 1010 // check merged items 1011 1012 if(this.options.merge){ 1013 var mergeNumber = this.dom.$items.eq(i).find('[data-merge]').attr('data-merge') || 1; 1014 if(this.options.mergeFit && mergeNumber > this.options.items){ 1015 mergeNumber = this.options.items; 1016 } 1017 this.num.merged.push(parseInt(mergeNumber)); 1018 this.width.mergeStage += this.width.item * this.num.merged[i]; 1019 } else { 1020 this.num.merged.push(1); 1021 } 1022 1023 // Array based on merged items used by dots and navigation 1024 if(this.options.loop){ 1025 if(i>
1025=this.num.cItems/2 && i<this.num.cItems/2+this.num.oItems){ 1026 this.num.nav.push(this.num.merged[i]); 1027 } 1028 } else { 1029 this.num.nav.push(this.num.merged[i]); 1030 } 1031 1032 var iWidth = this.width.item * this.num.merged[i]; 1033 1034 // autoWidth item size 1035 if(this.options.autoWidth){ 1036 iWidth = this.dom.$items.eq(i).width() + this.options.margin; 1037 if(this.options.rtl){ 1038 this.dom.$items[i].style.marginLeft = this.options.margin + 'px'; 1039 } else { 1040 this.dom.$items[i].style.marginRight = this.options.margin + 'px'; 1041 } 1042 1043 } 1044 // push item position into array 1045 this.pos.items.push(dist); 1046 1047 // update item data 1048 this.dom.$items.eq(i).data('owl-item').posLeft = posLeft; 1049 this.dom.$items.eq(i).data('owl-item').width = iWidth; 1050 1051 // dist starts from middle of stage if center 1052 // posLeft always starts from 0 1053 if(this.options.rtl){ 1054 dist += iWidth; 1055 posLeft += iWidth; 1056 } else{ 1057 dist -= iWidth; 1058 posLeft -= iWidth; 1059 } 1060 1061 fullWidth -= Math.abs(iWidth); 1062 1063 // update position if center 1064 if(this.options.center){ 1065 this.pos.items[i] = !this.options.rtl ? this.pos.items[i] - (iWidth/2) : this.pos.items[i] + (iWidth/2); 1066 } 1067 } 1068 1069 if(this.options.autoWidth){ 1070 this.width.stage = this.options.center ? Math.abs(fullWidth) : Math.abs(dist); 1071 } else { 1072 this.width.stage = Math.abs(fullWidth); 1073 } 1074 1075 //update indexAbs on all items 1076 var allItems = this.num.oItems + this.num.cItems; 1077 1078 for(j = 0; j< allItems; j++){ 1079 this.dom.$items.eq(j).data('owl-item').indexAbs = j; 1080 } 1081 1082 // Set Min and Max 1083 this.setMinMax(); 1084 1085 // Recalculate grid 1086 this.setSizes(); 1087 }; 1088 1089 /** 1090 * setMinMax 1091 * @since 2.0.0 1092 */ 1093 1094 Owl.prototype.setMinMax = function(){ 1095 1096 // set Min 1097 var minimum = this.dom.$oItems.eq(0).data('owl-item').indexAbs; 1098 this.pos.min = 0; 1099 this.pos.minValue = this.pos.items[minimum]; 1100 1101 // set max position 1102 if(!this.options.loop){ 1103 this.pos.max = this.num.oItems-1; 1104 } 1105 1106 if(this.options.loop){ 1107 this.pos.max = this.num.oItems+this.options.items; 1108 } 1109 1110 if(!this.options.loop && !this.options.center){ 1111 this.pos.max = this.num.oItems-this.options.items; 1112 } 1113 1114 if(this.options.loop && this.options.center){ 1115 this.pos.max = this.num.oItems+this.options.items; 1116 } 1117 1118 //set max value 1119 this.pos.maxValue = this.pos.items[this.pos.max]; 1120 1121 //Max for autoWidth content 1122 if((!this.options.loop && !this.options.center && this.options.autoWidth) || (this.options.merge && !this.options.center) ){ 1123 var revert = this.options.rtl ? 1 : -1; 1124 for (i = 0; i < this.pos.items.length; i++) { 1125 if( (this.pos.items[i] * revert) < this.width.stage-this.width.el ){ 1126 this.pos.max = i+1; 1127 } 1128 } 1129 this.pos.maxValue = this.options.rtl ? this.width.stage-this.width.el : -(this.width.stage-this.width.el); 1130 this.pos.items[this.pos.max] = this.pos.maxValue; 1131 } 1132 1133 // Set loop boundries 1134 if(this.options.center){ 1135 this.pos.loop = this.pos.items[0]-this.pos.items[this.num.oItems]; 1136 } else { 1137 this.pos.loop = -this.pos.items[this.num.oItems]; 1138 } 1139 1140 //if is less items 1141 if(this.num.oItems < this.options.items && !this.options.center){ 1142 this.pos.max = 0; 1143 this.pos.maxValue = this.pos.items[0]; 1144 } 1145 }; 1146 1147 /** 1148 * setSizes 1149 * @desc Set sizes on elements (from collectData function) 1150 * @since 2.0.0 1151 */ 1152 1153 Owl.prototype.setSizes = function(){ 1154 1155 // show neighbours 1156 if(this.options.stagePadding !== false){ 1157 this.dom.oStage.style.paddingLeft = this.options.stagePadding + 'px'; 1158 this.dom.oStage.style.paddingRight = this.options.stagePadding + 'px'; 1159 } 1160 1161 // CRAZY FIX!!! Doublecheck this! 1162 //if(this.width.stagePrev > this.width.stage){ 1163 if(this.options.rtl){ 1164 window.setTimeout(function(){ 1165 this.dom.stage.style.width = this.width.stage + 'px'; 1166 }.bind(this),0); 1167 } else{ 1168 this.dom.stage.style.width = this.width.stage + 'px'; 1169 } 1170 1171 for(var i=0; i<this.num.items; i++){ 1172 1173 // Set items width 1174 if(!this.options.autoWidth){ 1175 this.dom.$items[i].style.width = this.width.item - (this.options.margin) + 'px'; 1176 } 1177 // add margin 1178 if(this.options.rtl){ 1179 this.dom.$items[i].style.marginLeft = this.options.margin + 'px'; 1180 } else { 1181 this.dom.$items[i].style.marginRight = this.options.margin + 'px'; 1182 } 1183 1184 if(this.num.merged[i] !== 1 && !this.options.autoWidth){ 1185 this.dom.$items[i].style.width = (this.width.item * this.num.merged[i]) - (this.options.margin) + 'px'; 1186 } 1187 } 1188 1189 // save prev stage size 1190 this.width.stagePrev = this.width.stage; 1191 }; 1192 1193 /** 1194 * responsive 1195 * @desc Responsive function update all data by calling refresh() 1196 * @since 2.0.0 1197 */ 1198 1199 Owl.prototype.responsive = function(){ 1200 1201 if(!this.num.oItems){return false;} 1202 // If El width hasnt change then stop responsive 1203 var elChanged = this.isElWidthChanged(); 1204 if(!elChanged){return false;} 1205 1206 // if Vimeo Fullscreen mode 1207 var fullscreenElement = document.fullscreenElement || document.mozFullScreenElement || document.webkitFullscreenElement; 1208 if(fullscreenElement){ 1209 if($(fullscreenElement.parentNode).hasClass('owl-video-frame')){ 1210 this.setSpeed(0); 1211 this.state.isFullScreen = true; 1212 } 1213 } 1214 1215 if(fullscreenElement && this.state.isFullScreen && this.state.videoPlay){ 1216 return false;
1217 } 1218 1219 // Comming back from fullscreen 1220 if(this.state.isFullScreen){ 1221 this.state.isFullScreen = false; 1222 return false; 1223 } 1224 1225 // check full screen mode and window orientation 1226 if (this.state.videoPlay) { 1227 if(this.state.orientation !== window.orientation){ 1228 this.state.orientation = window.orientation; 1229 return false; 1230 } 1231 } 1232 1233 this.fireCallback('onResponsiveBefore'); 1234 this.state.responsive = true; 1235 this.refresh(); 1236 this.state.responsive = false; 1237 this.fireCallback('onResponsiveAfter'); 1238 }; 1239 1240 /** 1241 * refresh 1242 * @desc Refresh method is basically collection of functions that are responsible for Owl responsive functionality 1243 * @since 2.0.0 1244 */ 1245 1246 Owl.prototype.refresh = function(init){ 1247 1248 if(this.state.videoPlay){ 1249 this.stopVideo(); 1250 } 1251 1252 // Update Options for given width 1253 this.setResponsiveOptions(); 1254 1255 //set lazy structure 1256 this.createLazyContentStructure(true); 1257 1258 // update info about local content 1259 this.updateLocalContent(); 1260 1261 // udpate options 1262 this.optionsLogic(); 1263 1264 // if no items then stop 1265 if(this.num.oItems === 0){ 1266 if(this.dom.$page !== null){ 1267 this.dom.$page.hide(); 1268 } 1269 return false; 1270 } 1271 1272 // Hide and Show methods helps here to set a proper widths. 1273 // This prevents Scrollbar to be calculated in stage width 1274 this.dom.$stage.addClass('owl-refresh'); 1275 1276 // Remove clones and generate new ones 1277 this.reClone(); 1278 1279 // calculate 1280 this.calculate(); 1281 1282 //aaaand show. 1283 this.dom.$stage.removeClass('owl-refresh'); 1284 1285 // to do 1286 // lazyContent last position on refresh 1287 if(this.state.lazyContent){ 1288 this.pos.currentAbs = this.options.items; 1289 } 1290 1291 this.initPosition(init); 1292 1293 // jump to last position 1294 if(!this.state.lazyContent && !init){ 1295 this.jumpTo(this.pos.current,false); // fix that 1296 } 1297 1298 //Check for videos ( YouTube and Vimeo currently supported) 1299 this.checkVideoLinks(); 1300 1301 this.updateItemState(); 1302 1303 // Update controls 1304 this.rebuildDots(); 1305 1306 this.updateControls(); 1307 1308 // update drag events 1309 //this.updateEvents(); 1310 1311 // update autoplay 1312 this.autoplay(); 1313 1314 this.autoHeight(); 1315 1316 this.state.orientation = window.orientation; 1317 1318 this.watchVisibility(); 1319 }; 1320 1321 /** 1322 * updateItemState 1323 * @desc Update information about current state of items (visibile, hidden, active, etc.) 1324 * @since 2.0.0 1325 */ 1326 1327 Owl.prototype.updateItemState = function(update){ 1328 1329 if(!this.state.lazyContent){ 1330 this.updateActiveItems(); 1331 } else { 1332 this.updateLazyContent(update); 1333 } 1334 1335 if(this.options.center){ 1336 this.dom.$items.eq(this.pos.currentAbs) 1337 .addClass(this.options.centerClass) 1338 .data('owl-item').center = true; 1339 } 1340 1341 if(this.options.lazyLoad){ 1342 this.lazyLoad(); 1343 } 1344 }; 1345 1346 /** 1347 * updateActiveItems 1348 * @since 2.0.0 1349 */ 1350 1351 1352 Owl.prototype.updateActiveItems = function(){ 1353 var i,j,item,ipos,iwidth,wpos,stage,outsideView,foundCurrent; 1354 // clear states 1355 for(i = 0; i<this.num.items; i++){ 1356 this.dom.$items.eq(i).data('owl-item').active = false; 1357 this.dom.$items.eq(i).data('owl-item').current = false; 1358 this.dom.$items.eq(i).removeClass(this.options.activeClass).removeClass(this.options.centerClass); 1359 } 1360 1361 this.num.active = 0; 1362 stageX = this.pos.stage; 1363 view = this.options.rtl ? this.width.view : -this.width.view; 1364 1365 for(j = 0; j<this.num.items; j++){ 1366 1367 item = this.dom.$items.eq(j); 1368 ipos = item.data('owl-item').posLeft; 1369 iwidth = item.data('owl-item').width; 1370 outsideView = this.options.rtl ? ipos + iwidth : ipos - iwidth; 1371 1372 if( (this.op(ipos,'<=',stageX) && (this.op(ipos,'>',stageX + view))) || 1373 (this.op(outsideView,'<',stageX) && this.op(outsideView,'>',stageX + view)) 1374 ){ 1375 1376 this.num.active++; 1377 1378 if(this.options.freeDrag && !foundCurrent){ 1379 foundCurrent = true; 1380 this.pos.current = item.data('owl-item').index; 1381 this.pos.currentAbs = item.data('owl-item').indexAbs; 1382 } 1383 1384 item.data('owl-item').active = true; 1385 item.data('owl-item').current = true; 1386 item.addClass(this.options.activeClass); 1387 1388 if(!this.options.lazyLoad){ 1389 item.data('owl-item').loaded = true; 1390 } 1391 if(this.options.loop && (this.options.lazyLoad || this.options.center)){ 1392 this.updateClonedItemsState(item.data('owl-item').index); 1393 } 1394 } 1395 } 1396 }; 1397 1398 /** 1399 * updateClonedItemsState 1400 * @desc Set current state on sibilings items for lazyLoad and center 1401 * @since 2.0.0 1402 */ 1403 1404 Owl.prototype.updateClonedItemsState = function(activeIndex){ 1405 1406 //find cloned center 1407 var center, $el,i; 1408 if(this.options.center){ 1409 center = this.dom.$items.eq(this.pos.currentAbs).data('owl-item').index; 1410 } 1411 1412 for(i = 0; i<this.num.items; i++){ 1413 $el = this.dom.$items.eq(i); 1414 if( $el.data('owl-item').index === activeIndex ){ 1415 $el.data('owl-item').current = true; 1416 if($el.data('owl-item').index === center ){ 1417 $el.addClass(this.options.centerClass); 1418 } 1419 } 1420 } 1421 }; 1422 1423 /** 1424 * updateLazyPosition 1425 * @desc Set current state on sibilings items for lazyLoad and center 1426 * @since 2.0.0 1427 */ 1428 1429 Owl.prototype.updateLazyPosition = function(){ 1430 var jumpTo = this.pos.goToLazyContent || 0; 1431 1432 this.pos.lcMovedBy = Math.abs(this.options.items - this.pos.currentAbs); 1433 1434 if(this.options.items < this.pos.currentAbs ){ 1435 this.pos.lcCurrent += this.pos.currentAbs - this.options.items; 1436 this.state.lcDirection = 'right'; 1437 } else if(this.options.items > this.pos.currentAbs ){ 1438 this.pos.lcCurrent -= this.options.items - this.pos.currentAbs; 1439 this.state.lcDirection = 'left'; 1440 } 1441 1442 this.pos.lcCurrent = jumpTo !== 0 ? jumpTo : this.pos.lcCurrent; 1443 1444 if(this.pos.lcCurrent >= this.dom.$content.length){ 1445 this.pos.lcCurrent = this.pos.lcCurrent-this.dom.$content.length; 1446 } else if(this.pos.lcCurrent < -this.dom.$content.length+1){ 1447 this.pos.lcCurrent = this.pos.lcCurrent+this.dom.$content.length; 1448 } 1449 1450 if(this.options.startPosition>0){ 1451 this.pos.lcCurrent = this.options.startPosition; 1452 this._options.startPosition = this.options.startPosition = 0; 1453 } 1454 1455 this.pos.lcCurrentAbs = this.pos.lcCurrent < 0 ? this.pos.lcCurrent+this.dom.$content.length : this.pos.lcCurrent; 1456 1457 }; 1458 1459 /** 1460 * updateLazyContent 1461 * @param [update] - boolean - update call by content manipulations 1462 * @since 2.0.0 1463 */ 1464 1465 Owl.prototype.updateLazyContent = function(update){ 1466 1467 if(this.pos.lcCurrent === undefined){ 1468 this.pos.lcCurrent = 0; 1469 this.pos.current = this.pos.currentAbs = this.options.items; 1470 } 1471 1472 if(!update){ 1473 this.updateLazyPosition(); 1474 }
1475 var i,j,item,contentPos,content,freshItem,freshData; 1476 1477 if(this.state.lcDirection !== false){ 1478 for(i = 0; i<this.pos.lcMovedBy; i++){ 1479 1480 if(this.state.lcDirection === 'right'){ 1481 item = this.dom.$stage.find('.owl-item').eq(0); //.appendTo(this.dom.$stage); 1482 item.appendTo(this.dom.$stage); 1483 } 1484 if(this.state.lcDirection === 'left'){ 1485 item = this.dom.$stage.find('.owl-item').eq(-1); 1486 item.prependTo(this.dom.$stage); 1487 } 1488 item.data('owl-item').active = false; 1489 } 1490 } 1491 1492 // recollect 1493 this.dom.$items = this.dom.$stage.find('.owl-item'); 1494 1495 for(j = 0; j<this.num.items; j++){ 1496 // to do 1497 this.dom.$items.eq(j).removeClass(this.options.centerClass); 1498 1499 // get Content 1500 contentPos = this.pos.lcCurrent + j - this.options.items;// + this.options.startPosition; 1501 1502 if(contentPos >= this.dom.$content.length){ 1503 contentPos = contentPos - this.dom.$content.length; 1504 } 1505 if(contentPos < -this.dom.$content.length){ 1506 contentPos = contentPos + this.dom.$content.length; 1507 } 1508 1509 content = this.dom.$content.eq(contentPos); 1510 freshItem = this.dom.$items.eq(j); 1511 freshData = freshItem.data('owl-item'); 1512 1513 if(freshData.active === false || this.pos.goToLazyContent !== 0 || update === true){ 1514 1515 freshItem.empty(); 1516 freshItem.append(content.clone(true,true)); 1517 freshData.active = true; 1518 freshData.current = true; 1519 if(!this.options.lazyLoad){ 1520 freshData.loaded = true; 1521 } else { 1522 freshData.loaded = false; 1523 } 1524 } 1525 } 1526 1527 this.pos.goToLazyContent = 0; 1528 this.pos.current = this.pos.currentAbs = this.options.items; 1529 this.setSpeed(0); 1530 this.animStage(this.pos.items[this.options.items]); 1531 }; 1532 1533 /** 1534 * eventsCall 1535 * @desc Save internal event references and add event based functions like transitionEnd,responsive etc. 1536 * @since 2.0.0 1537 */ 1538 1539 Owl.prototype.eventsCall = function(){ 1540 // Save events references 1541 this.e._onDragStart = function(e){this.onDragStart(e); }.bind(this); 1542 this.e._onDragMove = function(e){this.onDragMove(e); }.bind(this); 1543 this.e._onDragEnd = function(e){this.onDragEnd(e); }.bind(this); 1544 this.e._transitionEnd = function(e){this.transitionEnd(e); }.bind(this); 1545 this.e._resizer = function(){this.responsiveTimer(); }.bind(this); 1546 this.e._responsiveCall =function(){this.responsive(); }.bind(this); 1547 this.e._preventClick = function(e){this.preventClick(e); }.bind(this); 1548 this.e._goToHash = function(){this.goToHash(); }.bind(this); 1549 this.e._goToPage = function(e){this.goToPage(e); }.bind(this); 1550 this.e._ap = function(){this.autoplay(); }.bind(this); 1551 this.e._play = function(){this.play(); }.bind(this); 1552 this.e._pause = function(){this.pause(); }.bind(this); 1553 this.e._playVideo = function(e){this.playVideo(e); }.bind(this); 1554 1555 this.e._navNext = function(e){ 1556 if($(e.target).hasClass('disabled')){return false;} 1557 e.preventDefault(); 1558 this.next(); 1559 }.bind(this); 1560 1561 this.e._navPrev = function(e){ 1562 if($(e.target).hasClass('disabled')){return false;} 1563 e.preventDefault(); 1564 this.prev(); 1565 }.bind(this); 1566 1567 }; 1568 1569 /** 1570 * responsiveTimer 1571 * @desc Check Window resize event with 200ms delay / this.options.responsiveRefreshRate 1572 * @since 2.0.0 1573 */ 1574 1575 Owl.prototype.responsiveTimer = function(){ 1576 if(this.windowWidth() === this.width.prevWindow){ 1577 return false; 1578 } 1579 window.clearInterval(this.e._autoplay); 1580 window.clearTimeout(this.resizeTimer); 1581 this.resizeTimer = window.setTimeout(this.e._responsiveCall, this.options.responsiveRefreshRate); 1582 this.width.prevWindow = this.windowWidth(); 1583 }; 1584 1585 /** 1586 * internalEvents 1587 * @desc Checks for touch/mouse drag options and add necessery event handlers. 1588 * @since 2.0.0 1589 */ 1590 1591 Owl.prototype.internalEvents = function(){ 1592 var isTouch = isTouchSupport(); 1593 var isTouchIE = isTouchSupportIE(); 1594 1595 if(isTouch && !isTouchIE){ 1596 this.dragType = ['touchstart','touchmove','touchend','touchcancel']; 1597 } else if(isTouch && isTouchIE){ 1598 this.dragType = ['MSPointerDown','MSPointerMove','MSPointerUp','MSPointerCancel']; 1599 } else { 1600 this.dragType = ['mousedown','mousemove','mouseup']; 1601 } 1602 1603 if( (isTouch || isTouchIE) && this.options.touchDrag){ 1604 //touch cancel event 1605 this.on(document, this.dragType[3], this.e._onDragEnd); 1606 1607 } else { 1608 // firefox startdrag fix - addeventlistener doesnt work here :/ 1609 this.dom.$stage.on('dragstart', function() {return false;}); 1610 1611 if(this.options.mouseDrag){ 1612 //disable text select 1613 this.dom.stage.onselectstart = function(){return false;}; 1614 } else { 1615 // enable text select 1616 this.dom.$el.addClass('owl-text-select-on'); 1617 } 1618 } 1619 1620 // Video Play Button event delegation 1621 this.dom.$stage.on(this.dragType[2], '.owl-video-play-icon', this.e._playVideo); 1622
1623 if(this.options.URLhashListener){ 1624 this.on(window, 'hashchange', this.e._goToHash, false); 1625 } 1626 1627 if(this.options.autoplayHoverPause){ 1628 var that = this; 1629 this.dom.$stage.on('mouseover', this.e._pause ); 1630 this.dom.$stage.on('mouseleave', this.e._ap ); 1631 } 1632 1633 // Catch transitionEnd event 1634 if(this.transitionEndVendor){ 1635 this.on(this.dom.stage, this.transitionEndVendor, this.e._transitionEnd, false); 1636 } 1637 1638 // Responsive 1639 if(this.options.responsive !== false){ 1640 this.on(window, 'resize', this.e._resizer, false); 1641 } 1642 1643 this.updateEvents(); 1644 }; 1645 1646 /** 1647 * updateEvents 1648 * @since 2.0.0 1649 */ 1650 1651 Owl.prototype.updateEvents = function(){ 1652 1653 if(this.options.touchDrag && (this.dragType[0] === 'touchstart' || this.dragType[0] === 'MSPointerDown')){ 1654 this.on(this.dom.stage, this.dragType[0], this.e._onDragStart,false); 1655 } else if(this.options.mouseDrag && this.dragType[0] === 'mousedown'){ 1656 this.on(this.dom.stage, this.dragType[0], this.e._onDragStart,false); 1657 1658 } else { 1659 this.off(this.dom.stage, this.dragType[0], this.e._onDragStart); 1660 } 1661 }; 1662 1663 /** 1664 * onDragStart 1665 * @desc touchstart/mousedown event 1666 * @since 2.0.0 1667 */ 1668 1669 Owl.prototype.onDragStart = function(event){ 1670 var ev = event.originalEvent || event || window.event; 1671 // prevent right click 1672 if (ev.which === 3) { 1673 return false; 1674 } 1675 1676 if(this.dragType[0] === 'mousedown'){ 1677 this.dom.$stage.addClass('owl-grab'); 1678 } 1679 1680 this.fireCallback('onTouchStart'); 1681 this.drag.startTime = new Date().getTime(); 1682 this.setSpeed(0); 1683 this.state.isTouch = true; 1684 this.state.isScrolling = false; 1685 this.state.isSwiping = false; 1686 this.drag.distance = 0; 1687 1688 // if is 'touchstart' 1689 var isTouchEvent = ev.type === 'touchstart'; 1690 var pageX = isTouchEvent ? event.targetTouches[0].pageX : (ev.pageX || ev.clientX); 1691 var pageY = isTouchEvent ? event.targetTouches[0].pageY : (ev.pageY || ev.clientY); 1692 1693 //get stage position left 1694 this.drag.offsetX = this.dom.$stage.position().left - this.options.stagePadding; 1695 this.drag.offsetY = this.dom.$stage.position().top; 1696 1697 if(this.options.rtl){ 1698 this.drag.offsetX = this.dom.$stage.position().left + this.width.stage - this.width.el + this.options.margin; 1699 } 1700 1701 //catch position // ie to fix 1702 if(this.state.inMotion && this.support3d){ 1703 var animatedPos = this.getTransformProperty(); 1704 this.drag.offsetX = animatedPos; 1705 this.animStage(animatedPos); 1706 } else if(this.state.inMotion && !this.support3d ){ 1707 this.state.inMotion = false; 1708 return false; 1709 } 1710 1711 this.drag.startX = pageX - this.drag.offsetX; 1712 this.drag.startY = pageY - this.drag.offsetY; 1713 1714 this.drag.start = pageX - this.drag.startX; 1715 this.drag.targetEl = ev.target || ev.srcElement; 1716 this.drag.updatedX = this.drag.start; 1717 1718 // to do/check 1719 //prevent links and images dragging; 1720 //this.drag.targetEl.draggable = false; 1721 1722 this.on(document, this.dragType[1], this.e._onDragMove, false); 1723 this.on(document, this.dragType[2], this.e._onDragEnd, false); 1724 }; 1725 1726 /** 1727 * onDragMove 1728 * @desc touchmove/mousemove event 1729 * @since 2.0.0 1730 */ 1731 1732 Owl.prototype.onDragMove = function(event){ 1733 if (!this.state.isTouch){ 1734 return; 1735 } 1736 1737 if (this.state.isScrolling){ 1738 return; 1739 } 1740 1741 var neighbourItemWidth=0; 1742 var ev = event.originalEvent || event || window.event; 1743 1744 // if is 'touchstart' 1745 var isTouchEvent = ev.type == 'touchmove'; 1746 var pageX = isTouchEvent ? ev.targetTouches[0].pageX : (ev.pageX || ev.clientX); 1747 var pageY = isTouchEvent ? ev.targetTouches[0].pageY : (ev.pageY || ev.clientY); 1748 1749 // Drag Direction 1750 this.drag.currentX = pageX - this.drag.startX; 1751 this.drag.currentY = pageY - this.drag.startY; 1752 this.drag.distance = this.drag.currentX - this.drag.offsetX; 1753 1754 // Check move direction 1755 if (this.drag.distance < 0) { 1756 this.state.direction = this.options.rtl ? 'right' : 'left'; 1757 } else if(this.drag.distance > 0){ 1758 this.state.direction = this.options.rtl ? 'left' : 'right'; 1759 } 1760 // Loop 1761 if(this.options.loop){ 1762 if(this.op(this.drag.currentX, '>', this.pos.minValue) && this.state.direction === 'right' ){ 1763 this.drag.currentX -= this.pos.loop; 1764 }else if(this.op(this.drag.currentX, '<', this.pos.maxValue) && this.state.direction === 'left' ){ 1765 this.drag.currentX += this.pos.loop; 1766 } 1767 } else { 1768 // pull 1769 var minValue = this.options.rtl ? this.pos.maxValue : this.pos.minValue; 1770 var maxValue = this.options.rtl ? this.pos.minValue : this.pos.maxValue; 1771 var pull = this.options.pullDrag ? this.drag.distance / 5 : 0; 1772 this.drag.currentX = Math.max(Math.min(this.drag.currentX, minValue + pull), maxValue + pull); 1773 } 1774 1775 1776 1777 // Lock browser if swiping horizontal 1778 1779 if ((this.drag.distance > 8 || this.drag.distance < -8)) { 1780 if (ev.preventDefault !== undefined) { 1781 ev.preventDefault(); 1782 } else { 1783 ev.returnValue = false;
1784 } 1785 this.state.isSwiping = true; 1786 } 1787 1788 this.drag.updatedX = this.drag.currentX; 1789 1790 // Lock Owl if scrolling 1791 if ((this.drag.currentY > 16 || this.drag.currentY < -16) && this.state.isSwiping === false) { 1792 this.state.isScrolling = true; 1793 this.drag.updatedX = this.drag.start; 1794 } 1795 1796 this.animStage(this.drag.updatedX); 1797 }; 1798 1799 /** 1800 * onDragEnd 1801 * @desc touchend/mouseup event 1802 * @since 2.0.0 1803 */ 1804 1805 Owl.prototype.onDragEnd = function(event){ 1806 if (!this.state.isTouch){ 1807 return; 1808 } 1809 if(this.dragType[0] === 'mousedown'){ 1810 this.dom.$stage.removeClass('owl-grab'); 1811 } 1812 1813 this.fireCallback('onTouchEnd'); 1814 1815 //prevent links and images dragging; 1816 //this.drag.targetEl.draggable = true; 1817 1818 //remove drag event listeners 1819 1820 this.state.isTouch = false; 1821 this.state.isScrolling = false; 1822 this.state.isSwiping = false; 1823 1824 //to check 1825 if(this.drag.distance === 0 && this.state.inMotion !== true){ 1826 this.state.inMotion = false; 1827 return false; 1828 } 1829 1830 // prevent clicks while scrolling 1831 1832 this.drag.endTime = new Date().getTime(); 1833 var compareTimes = this.drag.endTime - this.drag.startTime; 1834 var distanceAbs = Math.abs(this.drag.distance); 1835 1836 //to test 1837 if(distanceAbs > 3 || compareTimes > 300){ 1838 this.removeClick(this.drag.targetEl); 1839 } 1840 1841 var closest = this.closest(this.drag.updatedX); 1842 1843 this.setSpeed(this.options.dragEndSpeed, false, true); 1844 this.animStage(this.pos.items[closest]); 1845 1846 //if pullDrag is off then fire transitionEnd event manually when stick to border 1847 if(!this.options.pullDrag && this.drag.updatedX === this.pos.items[closest]){ 1848 this.transitionEnd(); 1849 } 1850 1851 this.drag.distance = 0; 1852 1853 this.off(document, this.dragType[1], this.e._onDragMove); 1854 this.off(document, this.dragType[2], this.e._onDragEnd); 1855 }; 1856 1857 /** 1858 * removeClick 1859 * @desc Attach preventClick function to disable link while swipping 1860 * @since 2.0.0 1861 * @param [target] - clicked dom element 1862 */ 1863 1864 Owl.prototype.removeClick = function(target){ 1865 this.drag.targetEl = target; 1866 this.on(target,'click', this.e._preventClick, false); 1867 }; 1868 1869 /** 1870 * preventClick 1871 * @desc Add preventDefault for any link and then remove removeClick event hanlder 1872 * @since 2.0.0 1873 */ 1874 1875 Owl.prototype.preventClick = function(ev){ 1876 if(ev.preventDefault) { 1877 ev.preventDefault(); 1878 }else { 1879 ev.returnValue = false; 1880 } 1881 if(ev.stopPropagation){ 1882 ev.stopPropagation(); 1883 } 1884 this.off(this.drag.targetEl,'click',this.e._preventClick,false); 1885 }; 1886 1887 /** 1888 * getTransformProperty 1889 * @desc catch stage position while animate (only css3) 1890 * @since 2.0.0 1891 */ 1892 1893 Owl.prototype.getTransformProperty = function(){ 1894 var transform = window.getComputedStyle(this.dom.stage, null).getPropertyValue(this.vendorName + 'transform'); 1895 //var transform = this.dom.$stage.css(this.vendorName + 'transform') 1896 transform = transform.replace(/matrix(3d)?\(|\)/g, '').split(','); 1897 var matrix3d = transform.length === 16; 1898 1899 return matrix3d !== true ? transform[4] : transform[12]; 1900 }; 1901 1902 /** 1903 * closest 1904 * @desc Get closest item after touchend/mouseup 1905 * @since 2.0.0 1906 * @param [x] - curent position in pixels 1907 * return position in pixels 1908 */ 1909 1910 Owl.prototype.closest = function(x){ 1911 var newX = 0, 1912 pull = 30; 1913 1914 if(!this.options.freeDrag){ 1915 // Check closest item 1916 for(var i = 0; i< this.num.items; i++){ 1917 if(x > this.pos.items[i]-pull && x < this.pos.items[i]+pull){ 1918 newX = i; 1919 }else if(this.op(x,'<',this.pos.items[i]) && this.op(x,'>',this.pos.items[i+1 || this.pos.items[i] - this.width.el]) ){ 1920 newX = this.state.direction === 'left' ? i+1 : i; 1921 } 1922 } 1923 } 1924 //non loop boundries 1925 if(!this.options.loop){ 1926 if(this.op(x,'>',this.pos.minValue)){ 1927 newX = x = this.pos.min; 1928 } else if(this.op(x,'<',this.pos.maxValue)){ 1929 newX = x = this.pos.max; 1930 } 1931 } 1932 1933 if(!this.options.freeDrag){ 1934 // set positions 1935 this.pos.currentAbs = newX; 1936 this.pos.current = this.dom.$items.eq(newX).data('owl-item').index; 1937 } else { 1938 this.updateItemState(); 1939 return x; 1940 } 1941 1942 return newX; 1943 }; 1944 1945 /** 1946 * animStage 1947 * @desc animate stage position (both css3/css2) and perform onChange functions/events 1948 * @since 2.0.0 1949 * @param [x] - curent position in pixels 1950 */ 1951 1952 Owl.prototype.animStage = function(pos){ 1953
1954 // if speed is 0 the set inMotion to false 1955 if(this.speed.current !== 0 && this.pos.currentAbs !== this.pos.min){ 1956 this.fireCallback('onTransitionStart'); 1957 this.state.inMotion = true; 1958 } 1959 1960 var posX = this.pos.stage = pos, 1961 style = this.dom.stage.style; 1962 1963 if(this.support3d){ 1964 translate = 'translate3d(' + posX + 'px'+',0px, 0px)'; 1965 style[this.transformVendor] = translate; 1966 } else if(this.state.isTouch){ 1967 style.left = posX+'px'; 1968 } else { 1969 this.dom.$stage.animate({left: posX},this.speed.css2speed, this.options.fallbackEasing, function(){ 1970 if(this.state.inMotion){ 1971 this.transitionEnd(); 1972 } 1973 }.bind(this)); 1974 } 1975 1976 this.onChange(); 1977 }; 1978 1979 /** 1980 * updatePosition 1981 * @desc Update current positions 1982 * @since 2.0.0 1983 * @param [pos] - number - new position 1984 */ 1985 1986 Owl.prototype.updatePosition = function(pos){ 1987 1988 // if no items then stop 1989 if(this.num.oItems === 0){return false;} 1990 // to do 1991 //if(pos > this.num.items){pos = 0;} 1992 if(pos === undefined){return false;} 1993 1994 //pos - new current position 1995 var nextPos = pos; 1996 this.pos.prev = this.pos.currentAbs; 1997 1998 if(this.state.revert){ 1999 this.pos.current = this.dom.$items.eq(nextPos).data('owl-item').index; 2000 this.pos.currentAbs = nextPos; 2001 return; 2002 } 2003 2004 if(!this.options.loop){ 2005 if(this.options.navRewind){ 2006 nextPos = nextPos > this.pos.max ? this.pos.min : (nextPos < 0 ? this.pos.max : nextPos); 2007 } else { 2008 nextPos = nextPos > this.pos.max ? this.pos.max : (nextPos <= 0 ? 0 : nextPos); 2009 } 2010 } else { 2011 nextPos = nextPos >= this.num.oItems ? this.num.oItems-1 : nextPos; 2012 } 2013 2014 this.pos.current = this.dom.$oItems.eq(nextPos).data('owl-item').index; 2015 this.pos.currentAbs = this.dom.$oItems.eq(nextPos).data('owl-item').indexAbs; 2016 2017 }; 2018 2019 /** 2020 * setSpeed 2021 * @since 2.0.0 2022 * @param [speed] - number 2023 * @param [pos] - number - next position - use this param to calculate smartSpeed 2024 * @param [drag] - boolean - if drag is true then smart speed is disabled 2025 * return speed 2026 */ 2027 2028 Owl.prototype.setSpeed = function(speed,pos,drag) { 2029 var s = speed, 2030 nextPos = pos; 2031 2032 if((s === false && s !== 0 && drag !== true) || s === undefined){ 2033 2034 //Double check this 2035 // var nextPx = this.pos.items[nextPos]; 2036 // var currPx = this.pos.stage 2037 // var diff = Math.abs(nextPx-currPx); 2038 // var s = diff/1 2039 // if(s>1000){ 2040 // s = 1000; 2041 // } 2042 2043 var diff = Math.abs(nextPos - this.pos.prev); 2044 diff = diff === 0 ? 1 : diff; 2045 if(diff>6){diff = 6;} 2046 s = diff * this.options.smartSpeed; 2047 } 2048 2049 if(s === false && drag === true){ 2050 s = this.options.smartSpeed; 2051 } 2052 2053 if(s === 0){s=0;} 2054 2055 if(this.support3d){ 2056 var style = this.dom.stage.style; 2057 style.webkitTransitionDuration = style.MsTransitionDuration = style.msTransitionDuration = style.MozTransitionDuration = style.OTransitionDuration = style.transitionDuration = (s / 1000) + 's'; 2058 } else{ 2059 this.speed.css2speed = s; 2060 } 2061 this.speed.current = s; 2062 return s; 2063 }; 2064 2065 /** 2066 * jumpTo 2067 * @since 2.0.0 2068 * @param [pos] - number - next position - use this param to calculate smartSpeed 2069 * @param [update] - boolean - if drag is true then smart speed is disabled 2070 */ 2071 2072 Owl.prototype.jumpTo = function(pos,update){ 2073 if(this.state.lazyContent){ 2074 this.pos.goToLazyContent = pos; 2075 } 2076 this.updatePosition(pos); 2077 this.setSpeed(0); 2078 this.animStage(this.pos.items[this.pos.currentAbs]); 2079 if(update !== true){ 2080 this.updateItemState(); 2081 } 2082 }; 2083 2084 /** 2085 * goTo 2086 * @since 2.0.0 2087 * @param [pos] - number 2088 * @param [speed] - speed in ms 2089 * @param [speed] - speed in ms 2090 */ 2091 2092 Owl.prototype.goTo = function(pos,speed){ 2093 if(this.state.lazyContent && this.state.inMotion){ 2094 return false; 2095 } 2096 2097 this.updatePosition(pos); 2098 2099 if(this.state.animate){speed = 0;} 2100 this.setSpeed(speed,this.pos.currentAbs); 2101 2102 if(this.state.animate){this.animate();} 2103 this.animStage(this.pos.items[this.pos.currentAbs]); 2104 2105 }; 2106 2107 /** 2108 * next 2109 * @since 2.0.0 2110 */ 2111 2112 Owl.prototype.next = function(optionalSpeed){ 2113 var s = optionalSpeed || this.options.navSpeed; 2114 if(this.options.loop && !this.state.lazyContent){ 2115 this.goToLoop(this.options.slideBy, s); 2116 }else{ 2117 this.goTo(this.pos.current + this.options.slideBy, s); 2118 } 2119 }; 2120 2121 /** 2122 * prev 2123 * @since 2.0.0 2124 */ 2125 2126 Owl.prototype.prev = function(optionalSpeed){ 2127 var s = optionalSpeed || this.options.navSpeed; 2128 if(this.options.loop && !this.state.lazyContent){ 2129 this.goToLoop(-this.options.slideBy, s); 2130 }else{ 2131 this.goTo(this.pos.current-this.options.slideBy, s); 2132 } 2133 }; 2134 2135 /** 2136 * goToLoop 2137 * @desc Go to given position if loop is enabled - used only internal 2138 * @since 2.0.0 2139 * @param [distance] - number -how far to go
2140 * @param [speed] - number - speed in ms 2141 */ 2142 2143 Owl.prototype.goToLoop = function(distance,speed){ 2144 2145 var revert = this.pos.currentAbs, 2146 prevPosition = this.pos.currentAbs, 2147 newPosition = this.pos.currentAbs + distance, 2148 direction = prevPosition - newPosition < 0 ? true : false; 2149 2150 this.state.revert = true; 2151 2152 if(newPosition < 1 && direction === false){ 2153 2154 this.state.bypass = true; 2155 revert = this.num.items - (this.options.items-prevPosition) - this.options.items; 2156 this.jumpTo(revert,true); 2157 2158 } else if(newPosition >= this.num.items - this.options.items && direction === true ){ 2159 2160 this.state.bypass = true; 2161 revert = prevPosition - this.num.oItems; 2162 this.jumpTo(revert,true); 2163 2164 } 2165 window.clearTimeout(this.e._goToLoop); 2166 this.e._goToLoop = window.setTimeout(function(){ 2167 this.state.bypass = false; 2168 this.goTo(revert + distance, speed); 2169 this.state.revert = false; 2170 2171 }.bind(this), 30); 2172 }; 2173 2174 /** 2175 * initPosition 2176 * @since 2.0.0 2177 */ 2178 2179 Owl.prototype.initPosition = function(init){ 2180 2181 if( !this.dom.$oItems || !init || this.state.lazyContent ){return false;} 2182 var pos = this.options.startPosition; 2183 2184 if(this.options.startPosition === 'URLHash'){ 2185 pos = this.options.startPosition = this.hashPosition(); 2186 } else if(typeof this.options.startPosition !== Number && !this.options.center){ 2187 this.options.startPosition = 0; 2188 } 2189 this.dom.oStage.scrollLeft = 0; 2190 this.jumpTo(pos,true); 2191 }; 2192 2193 /** 2194 * goToHash 2195 * @since 2.0.0 2196 */ 2197 2198 Owl.prototype.goToHash = function(){ 2199 var pos = this.hashPosition(); 2200 if(pos === false){ 2201 pos = 0; 2202 } 2203 this.dom.oStage.scrollLeft = 0; 2204 this.goTo(pos,this.options.navSpeed); 2205 }; 2206 2207 /** 2208 * hashPosition 2209 * @desc Find hash in URL then look into items to find contained ID 2210 * @since 2.0.0 2211 * return hashPos - number of item 2212 */ 2213 2214 Owl.prototype.hashPosition = function(){ 2215 var hash = window.location.hash.substring(1), 2216 hashPos; 2217 if(hash === ""){return false;} 2218 2219 for(var i=0;i<this.num.oItems; i++){ 2220 if(hash === this.dom.$oItems.eq(i).data('owl-item').hash){ 2221 hashPos = i; 2222 } 2223 } 2224 return hashPos; 2225 }; 2226 2227 /** 2228 * Autoplay 2229 * @since 2.0.0 2230 */ 2231 2232 Owl.prototype.autoplay = function(){ 2233 if(this.options.autoplay && !this.state.videoPlay){ 2234 window.clearInterval(this.e._autoplay); 2235 this.e._autoplay = window.setInterval(this.e._play, this.options.autoplayTimeout); 2236 } else { 2237 window.clearInterval(this.e._autoplay); 2238 this.state.autoplay=false; 2239 } 2240 }; 2241 2242 /** 2243 * play 2244 * @param [timeout] - Integrer 2245 * @param [speed] - Integrer 2246 * @since 2.0.0 2247 */ 2248 2249 Owl.prototype.play = function(timeout, speed){ 2250 2251 // if tab is inactive - doesnt work in <IE10 2252 if(document.hidden === true){return false;} 2253 2254 // overwrite default options (custom options are always priority) 2255 if(!this.options.autoplay){ 2256 this._options.autoplay = this.options.autoplay = true; 2257 this._options.autoplayTimeout = this.options.autoplayTimeout = timeout || this.options.autoplayTimeout || 4000; 2258 this._options.autoplaySpeed = speed || this.options.autoplaySpeed; 2259 } 2260 2261 if(this.options.autoplay === false || this.state.isTouch || this.state.isScrolling || this.state.isSwiping || this.state.inMotion){ 2262 window.clearInterval(this.e._autoplay); 2263 return false; 2264 } 2265 2266 if(!this.options.loop && this.pos.current >= this.pos.max){ 2267 window.clearInterval(this.e._autoplay); 2268 this.goTo(0); 2269 } else { 2270 this.next(this.options.autoplaySpeed); 2271 } 2272 this.state.autoplay=true; 2273 }; 2274 2275 /** 2276 * stop 2277 * @since 2.0.0 2278 */ 2279 2280 Owl.prototype.stop = function(){ 2281 this._options.autoplay = this.options.autoplay = false; 2282 this.state.autoplay = false; 2283 window.clearInterval(this.e._autoplay); 2284 }; 2285 2286 Owl.prototype.pause = function(){ 2287 window.clearInterval(this.e._autoplay); 2288 }; 2289 2290 /** 2291 * transitionEnd 2292 * @desc event used by css3 animation end and $.animate callback like transitionEnd,responsive etc. 2293 * @since 2.0.0 2294 */ 2295 2296 Owl.prototype.transitionEnd = function(event){ 2297 2298 // if css2 animation then event object is undefined 2299 if(event !== undefined){ 2300 event.stopPropagation(); 2301 2302 // Catch only owl-stage transitionEnd event 2303 var eventTarget = event.target || event.srcElement || event.originalTarget; 2304 if(eventTarget !== this.dom.stage){ 2305 return false;
2306 } 2307 } 2308 2309 this.state.inMotion = false; 2310 this.updateItemState(); 2311 this.autoplay(); 2312 this.fireCallback('onTransitionEnd'); 2313 }; 2314 2315 /** 2316 * isElWidthChanged 2317 * @desc Check if element width has changed 2318 * @since 2.0.0 2319 */ 2320 2321 Owl.prototype.isElWidthChanged = function(){ 2322 var newElWidth = this.dom.$el.width() - this.options.stagePadding,//to check 2323 prevElWidth = this.width.el + this.options.margin; 2324 return newElWidth !== prevElWidth; 2325 }; 2326 2327 /** 2328 * windowWidth 2329 * @desc Get Window/responsiveBaseElement width 2330 * @since 2.0.0 2331 */ 2332 2333 Owl.prototype.windowWidth = function() { 2334 if(this.options.responsiveBaseElement !== window){ 2335 this.width.window = $(this.options.responsiveBaseElement).width(); 2336 } else if (window.innerWidth){ 2337 this.width.window = window.innerWidth; 2338 } else if (document.documentElement && document.documentElement.clientWidth){ 2339 this.width.window = document.documentElement.clientWidth; 2340 } 2341 return this.width.window; 2342 }; 2343 2344 /** 2345 * Controls 2346 * @desc Calls controls container, navigation and dots creator 2347 * @since 2.0.0 2348 */ 2349 2350 Owl.prototype.controls = function(){ 2351 var cc = document.createElement('div'); 2352 cc.className = this.options.controlsClass; 2353 this.dom.$el.append(cc); 2354 this.dom.$cc = $(cc); 2355 }; 2356 2357 /** 2358 * updateControls 2359 * @since 2.0.0 2360 */ 2361 2362 Owl.prototype.updateControls = function(){ 2363 2364 if(this.dom.$cc === null && (this.options.nav || this.options.dots)){ 2365 this.controls(); 2366 } 2367 2368 if(this.dom.$nav === null && this.options.nav){ 2369 this.createNavigation(this.dom.$cc[0]); 2370 } 2371 2372 if(this.dom.$page === null && this.options.dots){ 2373 this.createDots(this.dom.$cc[0]); 2374 } 2375 2376 if(this.dom.$nav !== null){ 2377 if(this.options.nav){ 2378 this.dom.$nav.show(); 2379 this.updateNavigation(); 2380 } else { 2381 this.dom.$nav.hide(); 2382 } 2383 } 2384 2385 if(this.dom.$page !== null){ 2386 if(this.options.dots){ 2387 this.dom.$page.show(); 2388 this.updateDots(); 2389 } else { 2390 this.dom.$page.hide(); 2391 } 2392 } 2393 }; 2394 2395 /** 2396 * createNavigation 2397 * @since 2.0.0 2398 * @param [cc] - dom element - Controls Container 2399 */ 2400 2401 Owl.prototype.createNavigation = function(cc){ 2402 2403 // Create nav container 2404 var nav = document.createElement('div'); 2405 nav.className = this.options.navContainerClass; 2406 cc.appendChild(nav); 2407 2408 // Create left and right buttons 2409 var navPrev = document.createElement('div'), 2410 navNext = document.createElement('div'); 2411 2412 navPrev.className = this.options.navClass[0]; 2413 navNext.className = this.options.navClass[1]; 2414 2415 nav.appendChild(navPrev); 2416 nav.appendChild(navNext); 2417 2418 this.dom.$nav = $(nav); 2419 this.dom.$navPrev = $(navPrev).html(this.options.navText[0]); 2420 this.dom.$navNext = $(navNext).html(this.options.navText[1]); 2421 2422 // add events to do 2423 //this.on(navPrev, this.dragType[2], this.e._navPrev, false); 2424 //this.on(navNext, this.dragType[2], this.e._navNext, false); 2425 2426 //FF fix? 2427 this.dom.$nav.on(this.dragType[2], '.'+this.options.navClass[0], this.e._navPrev); 2428 this.dom.$nav.on(this.dragType[2], '.'+this.options.navClass[1], this.e._navNext); 2429 }; 2430 2431 /** 2432 * createNavigation 2433 * @since 2.0.0 2434 * @param [cc] - dom element - Controls Container 2435 */ 2436 2437 Owl.prototype.createDots = function(cc){ 2438 2439 // Create dots container 2440 var page = document.createElement('div'); 2441 page.className = this.options.dotsClass; 2442 cc.appendChild(page); 2443 2444 // save reference 2445 this.dom.$page = $(page); 2446 2447 // add events 2448 //this.on(page, this.dragType[2], this.e._goToPage, false); 2449 2450 // FF fix? To test! 2451 var that = this; 2452 this.dom.$page.on(this.dragType[2], '.'+this.options.dotClass, goToPage); 2453 2454 function goToPage(e){ 2455 e.preventDefault(); 2456 var page = $(this).data('page'); 2457 that.goTo(page,that.options.dotsSpeed); 2458 } 2459 // build dots 2460 this.rebuildDots(); 2461 }; 2462 2463 /** 2464 * goToPage 2465 * @desc Event used by dots 2466 * @since 2.0.0 2467 */ 2468 2469 // Owl.prototype.goToPage = function(e){ 2470 // console.log(e.taget); 2471 // var page = $(e.currentTarget).data('page') 2472 // this.goTo(page,this.options.dotsSpeed); 2473 // return false; 2474 // }; 2475 2476 /** 2477 * rebuildDots 2478 * @since 2.0.0 2479 */ 2480 2481 Owl.prototype.rebuildDots = function(){ 2482 if(this.dom.$page === null){return false;}
2483 var each, dot, span, counter = 0, last = 0, i, page=0, roundPages = 0; 2484 2485 each = this.options.dotsEach || this.options.items; 2486 2487 // display full dots if center 2488 if(this.options.center || this.options.dotData){ 2489 each = 1; 2490 } 2491 2492 // clear dots 2493 this.dom.$page.html(''); 2494 2495 for(i = 0; i < this.num.nav.length; i++){ 2496 2497 if(counter >= each || counter === 0){ 2498 2499 dot = document.createElement('div'); 2500 dot.className = this.options.dotClass; 2501 span = document.createElement('span'); 2502 dot.appendChild(span); 2503 var $dot = $(dot); 2504 2505 if(this.options.dotData){ 2506 $dot.html(this.dom.$oItems.eq(i).data('owl-item').dot); 2507 } 2508 2509 $dot.data('page',page); 2510 $dot.data('goToPage',roundPages); 2511 2512 this.dom.$page.append(dot); 2513 2514 counter = 0; 2515 roundPages++; 2516 } 2517 2518 this.dom.$oItems.eq(i).data('owl-item').page = roundPages-1; 2519 2520 //add merged items 2521 counter += this.num.nav[i]; 2522 page++; 2523 } 2524 // find rest of dots 2525 if(!this.options.loop && !this.options.center){ 2526 for(var j = this.num.nav.length-1; j >= 0; j--){ 2527 last += this.num.nav[j]; 2528 this.dom.$oItems.eq(j).data('owl-item').page = roundPages-1; 2529 if(last >= each){ 2530 break; 2531 } 2532 } 2533 } 2534 2535 this.num.allPages = roundPages-1; 2536 }; 2537 2538 /** 2539 * updateDots 2540 * @since 2.0.0 2541 */ 2542 2543 Owl.prototype.updateDots = function(){ 2544 var dots = this.dom.$page.children(); 2545 var itemIndex = this.dom.$oItems.eq(this.pos.current).data('owl-item').page; 2546 2547 for(var i = 0; i < dots.length; i++){ 2548 var dotPage = dots.eq(i).data('goToPage'); 2549 2550 if(dotPage===itemIndex){ 2551 this.pos.currentPage = i; 2552 dots.eq(i).addClass('active'); 2553 }else{ 2554 dots.eq(i).removeClass('active'); 2555 } 2556 } 2557 }; 2558 2559 /** 2560 * updateNavigation 2561 * @since 2.0.0 2562 */ 2563 2564 Owl.prototype.updateNavigation = function(){ 2565 2566 var isNav = this.options.nav; 2567 2568 this.dom.$navNext.toggleClass('disabled',!isNav); 2569 this.dom.$navPrev.toggleClass('disabled',!isNav); 2570 2571 if(!this.options.loop && isNav && !this.options.navRewind){ 2572 2573 if(this.pos.current <= 0){ 2574 this.dom.$navPrev.addClass('disabled'); 2575 } 2576 if(this.pos.current >= this.pos.max){ 2577 this.dom.$navNext.addClass('disabled'); 2578 } 2579 } 2580 }; 2581 2582 Owl.prototype.insertContent = function(content){ 2583 this.dom.$stage.empty(); 2584 this.fetchContent(content); 2585 this.refresh(); 2586 }; 2587 2588 /** 2589 * addItem - Add an item 2590 * @since 2.0.0 2591 * @param [content] - dom element / string '<div>content</div>' 2592 * @param [pos] - number - position 2593 */ 2594 2595 Owl.prototype.addItem = function(content,pos){ 2596 pos = pos || 0; 2597 2598 if(this.state.lazyContent){ 2599 this.dom.$content = this.dom.$content.add($(content)); 2600 this.updateItemState(true); 2601 } else { 2602 // wrap content 2603 var item = this.fillItem(content); 2604 // if carousel is empty then append item 2605 if(this.dom.$oItems.length === 0){ 2606 this.dom.$stage.append(item); 2607 } else { 2608 // append item 2609 var it = this.dom.$oItems.eq(pos); 2610 if(pos !== -1){it.before(item);} else {it.after(item);} 2611 } 2612 // update and calculate carousel 2613 this.refresh(); 2614 } 2615 2616 }; 2617 2618 /** 2619 * removeItem - Remove an Item 2620 * @since 2.0.0 2621 * @param [pos] - number - position 2622 */ 2623 2624 Owl.prototype.removeItem = function(pos){ 2625 if(this.state.lazyContent){ 2626 this.dom.$content.splice(pos,1); 2627 this.updateItemState(true); 2628 } else { 2629 this.dom.$oItems.eq(pos).remove(); 2630 this.refresh(); 2631 } 2632 }; 2633 2634 /** 2635 * addCustomEvents 2636 * @desc Add custom events by jQuery .on method 2637 * @since 2.0.0 2638 */ 2639 2640 Owl.prototype.addCustomEvents = function(){ 2641 2642 this.e.next = function(e,s){this.next(s); }.bind(this); 2643 this.e.prev = function(e,s){this.prev(s); }.bind(this); 2644 this.e.goTo = function(e,p,s){this.goTo(p,s); }.bind(this); 2645 this.e.jumpTo = function(e,p){this.jumpTo(p); }.bind(this); 2646 this.e.addItem = function(e,c,p){this.addItem(c,p); }.bind(this); 2647 this.e.removeItem = function(e,p){this.removeItem(p);}.bind(this); 2648 this.e.refresh = function(e){this.refresh(); }.bind(this); 2649 this.e.destroy = function(e){this.destroy(); }.bind(this); 2650 this.e.autoHeight = function(e){this.autoHeight(true);}.bind(this); 2651 this.e.stop = function(){this.stop(); }.bind(this); 2652 this.e.play = function(e,t,s){this.play(t,s); }.bind(this); 2653 this.e.insertContent = function(e,d){this.insertContent(d); }.bind(this); 2654 2655 this.dom.$el.on('next.owl',this.e.next); 2656 this.dom.$el.on('prev.owl',this.e.prev); 2657 this.dom.$el.on('goTo.owl',this.e.goTo); 2658 this.dom.$el.on('jumpTo.owl',this.e.jumpTo); 2659 this.dom.$el.on('addItem.owl',this.e.addItem); 2660 this.dom.$el.on('removeItem.owl',this.e.removeItem); 2661 this.dom.$el.on('destroy.owl',this.e.destroy); 2662 this.dom.$el.on('refresh.owl',this.e.refresh); 2663 this.dom.$el.on('autoHeight.owl',this.e.autoHeight); 2664 this.dom.$el.on('play.owl',this.e.play); 2665 this.dom.$el.on('stop.owl',this.e.stop); 2666 this.dom.$el.on('stopVideo.owl',this.e.stop); 2667 this.dom.$el.on('insertContent.owl',this.e.insertContent); 2668 2669 }; 2670 2671 /** 2672 * on 2673 * @desc On method for adding internal events 2674 * @since 2.0.0 2675 */ 2676 2677 Owl.prototype.on = function (element, event, listener, capture) { 2678 2679 if (element.addEventListener) { 2680 element.addEventListener(event, listener, capture); 2681 } 2682 else if (element.attachEvent) { 2683 element.attachEvent('on' + event, listener); 2684 } 2685 }; 2686 2687 /** 2688 * off 2689 * @desc Off method for removing internal events 2690 * @since 2.0.0 2691 */ 2692 2693 Owl.prototype.off = function (element, event, listener, capture) { 2694 if (element.removeEventListener) { 2695 element.removeEventListener(event, listener, capture); 2696 } 2697 else if (element.detachEvent) { 2698 element.detachEvent('on' + event, listener); 2699 } 2700 }; 2701 2702 /** 2703 * fireCallback 2704 * @since 2.0.0 2705 * @param event - string - event name 2706 * @param data - object - additional options - to do 2707 */ 2708 2709 Owl.prototype.fireCallback = function(event, data){ 2710 if(!this.options.callbacks){return;} 2711 2712 if(this.dom.el.dispatchEvent){ 2713 2714 // dispatch event 2715 var evt = document.createEvent('CustomEvent'); 2716 2717 //evt.initEvent(event, false, true ); 2718 evt.initCustomEvent(event, true, true, data); 2719 return this.dom.el.dispatchEvent(evt); 2720 2721 } else if (!this.dom.el.dispatchEvent){ 2722 2723 // There is no clean solution for custom events name in <=IE8 2724 // But if you know better way, please let me know :) 2725 return this.dom.$el.trigger(event); 2726 } 2727 }; 2728 2729 /** 2730 * watchVisibility 2731 * @desc check if el is visible - handy if Owl is inside hidden content (tabs etc.) 2732 * @since 2.0.0 2733 */ 2734 2735 Owl.prototype.watchVisibility = function(){ 2736 2737 // test on zepto 2738 if(!isElVisible(this.dom.el)) { 2739 this.dom.$el.addClass('owl-hidden'); 2740 window.clearInterval(this.e._checkVisibile); 2741 this.e._checkVisibile = window.setInterval(checkVisible.bind(this),500); 2742 } 2743 2744 function isElVisible(el) { 2745 return el.offsetWidth > 0 && el.offsetHeight > 0; 2746 } 2747 2748 function checkVisible(){ 2749 if (isElVisible(this.dom.el)) { 2750 this.dom.$el.removeClass('owl-hidden'); 2751 this.refresh(); 2752 window.clearInterval(this.e._checkVisibile); 2753 } 2754 } 2755 }; 2756 2757 /** 2758 * onChange 2759 * @since 2.0.0 2760 */ 2761 2762 Owl.prototype.onChange = function(){ 2763 2764 if(!this.state.isTouch && !this.state.bypass && !this.state.responsive ){ 2765 2766 if (this.options.nav || this.options.dots) { 2767 this.updateControls(); 2768 } 2769 this.autoHeight(); 2770 2771 this.fireCallback('onChangeState'); 2772 } 2773 2774 if(!this.state.isTouch && !this.state.bypass){ 2775 // set Status to do 2776 this.storeInfo(); 2777 2778 // stopVideo 2779 if(this.state.videoPlay){ 2780 this.stopVideo(); 2781 } 2782 } 2783 }; 2784 2785 /** 2786 * storeInfo 2787 * store basic information about current states 2788 * @since 2.0.0 2789 */ 2790 2791 Owl.prototype.storeInfo = function(){ 2792 var currentPosition = this.state.lazyContent ? this.pos.lcCurrentAbs || 0 : this.pos.current; 2793 var allItems = this.state.lazyContent ? this.dom.$content.length-1 : this.num.oItems; 2794 2795 this.info = { 2796 items: this.options.items, 2797 allItems: allItems, 2798 currentPosition:currentPosition, 2799 currentPage: this.pos.currentPage, 2800 allPages: this.num.allPages, 2801 autoplay: this.state.autoplay, 2802 windowWidth: this.width.window, 2803 elWidth: this.width.el, 2804 breakpoint: this.num.breakpoint 2805 }; 2806 2807 if (typeof this.options.info === 'function') { 2808 this.options.info.apply(this,[this.info,this.dom.el]); 2809 } 2810 }; 2811 2812 /** 2813 * autoHeight 2814 * @since 2.0.0 2815 */ 2816 2817 Owl.prototype.autoHeight = function(callback){ 2818 if(this.options.autoHeight !== true && callback !== true){ 2819 return false;
2820 } 2821 if(!this.dom.$oStage.hasClass(this.options.autoHeightClass)){ 2822 this.dom.$oStage.addClass(this.options.autoHeightClass); 2823 } 2824 2825 var loaded = this.dom.$items.eq(this.pos.currentAbs); 2826 var stage = this.dom.$oStage; 2827 var iterations = 0; 2828 2829 var isLoaded = window.setInterval(function() { 2830 iterations += 1; 2831 if(loaded.data('owl-item').loaded){ 2832 stage.height(loaded.height() + 'px'); 2833 clearInterval(isLoaded); 2834 } else if(iterations === 500){ 2835 clearInterval(isLoaded); 2836 } 2837 }, 100); 2838 }; 2839 2840 /** 2841 * preloadAutoWidthImages 2842 * @desc still to test 2843 * @since 2.0.0 2844 */ 2845 2846 Owl.prototype.preloadAutoWidthImages = function(imgs){ 2847 var loaded = 0; 2848 var that = this; 2849 imgs.each(function(i,el){ 2850 var $el = $(el); 2851 var img = new Image(); 2852 2853 img.onload = function(){ 2854 loaded++; 2855 $el.attr('src',img.src); 2856 $el.css('opacity',1); 2857 if(loaded >= imgs.length){ 2858 that.state.imagesLoaded = true; 2859 that.init(); 2860 } 2861 } 2862 2863 img.src = $el.attr('src') || $el.attr('data-src') || $el.attr('data-src-retina');; 2864 }) 2865 }; 2866 2867 /** 2868 * lazyLoad 2869 * @desc lazyLoad images 2870 * @since 2.0.0 2871 */ 2872 2873 Owl.prototype.lazyLoad = function(){ 2874 var attr = isRetina() ? 'data-src-retina' : 'data-src'; 2875 var src, img,i; 2876 2877 for(i = 0; i < this.num.items; i++){ 2878 var $item = this.dom.$items.eq(i); 2879 2880 if( $item.data('owl-item').current === true && $item.data('owl-item').loaded === false){ 2881 img = $item.find('.owl-lazy'); 2882 src = img.attr(attr); 2883 src = src || img.attr('data-src'); 2884 if(src){ 2885 img.css('opacity','0'); 2886 this.preload(img,$item); 2887 } 2888 } 2889 } 2890 }; 2891 2892 /** 2893 * preload 2894 * @since 2.0.0 2895 */ 2896 2897 Owl.prototype.preload = function(images,$item){ 2898 var that = this; // fix this later 2899 2900 images.each(function(i,el){ 2901 var $el = $(el); 2902 var img = new Image(); 2903 2904 img.onload = function(){ 2905 2906 $item.data('owl-item').loaded = true; 2907 if($el.is('img')){ 2908 $el.attr('src',img.src); 2909 }else{ 2910 $el.css('background-image','url(' + img.src + ')'); 2911 } 2912 2913 $el.css('opacity',1); 2914 that.fireCallback('onLazyLoaded'); 2915 }; 2916 img.src = $el.attr('data-src') || $el.attr('data-src-retina'); 2917 }); 2918 }; 2919 2920 /** 2921 * animate 2922 * @since 2.0.0 2923 */ 2924 2925 Owl.prototype.animate = function(){ 2926 2927 var prevItem = this.dom.$items.eq(this.pos.prev), 2928 prevPos = Math.abs(prevItem.data('owl-item').width) * this.pos.prev, 2929 currentItem = this.dom.$items.eq(this.pos.currentAbs), 2930 currentPos = Math.abs(currentItem.data('owl-item').width) * this.pos.currentAbs; 2931 2932 if(this.pos.currentAbs === this.pos.prev){ 2933 return false; 2934 } 2935 2936 var pos = currentPos - prevPos; 2937 var tIn = this.options.animateIn; 2938 var tOut = this.options.animateOut; 2939 var that = this; 2940 2941 removeStyles = function(){ 2942 $(this).css({ 2943 "left" : "" 2944 }) 2945 .removeClass('animated owl-animated-out owl-animated-in') 2946 .removeClass(tIn) 2947 .removeClass(tOut); 2948 2949 that.transitionEnd(); 2950 }; 2951 2952 if(tOut){ 2953 prevItem 2954 .css({ 2955 "left" : pos + "px" 2956 }) 2957 .addClass('animated owl-animated-out '+tOut) 2958 .one('webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend', removeStyles); 2959 } 2960 2961 if(tIn){ 2962 currentItem 2963 .addClass('animated owl-animated-in '+tIn) 2964 .one('webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend', removeStyles); 2965 } 2966 }; 2967 2968 /** 2969 * destroy 2970 * @desc Remove Owl structure and events :( 2971 * @since 2.0.0 2972 */ 2973 2974 Owl.prototype.destroy = function(){ 2975 2976 window.clearInterval(this.e._autoplay); 2977 2978 if(this.dom.$el.hasClass(this.options.themeClass)){ 2979 this.dom.$el.removeClass(this.options.themeClass); 2980 } 2981 2982 if(this.options.responsive !== false){ 2983 this.off(window, 'resize', this.e._resizer); 2984 } 2985 2986 if(this.transitionEndVendor){ 2987 this.off(this.dom.stage, this.transitionEndVendor, this.e._transitionEnd); 2988 } 2989 2990 if(this.options.mouseDrag || this.options.touchDrag){ 2991 this.off(this.dom.stage, this.dragType[0], this.e._onDragStart); 2992 if(this.options.mouseDrag){ 2993 this.off(document, this.dragType[3], this.e._onDragStart); 2994 } 2995 if(this.options.mouseDrag){ 2996 this.dom.$stage.off('dragstart', function() {return false;}); 2997 this.dom.stage.onselectstart = function(){}; 2998 } 2999 } 3000
3001 if(this.options.URLhashListener){ 3002 this.off(window, 'hashchange', this.e._goToHash); 3003 } 3004 3005 this.dom.$el.off('next.owl',this.e.next); 3006 this.dom.$el.off('prev.owl',this.e.prev); 3007 this.dom.$el.off('goTo.owl',this.e.goTo); 3008 this.dom.$el.off('jumpTo.owl',this.e.jumpTo); 3009 this.dom.$el.off('addItem.owl',this.e.addItem); 3010 this.dom.$el.off('removeItem.owl',this.e.removeItem); 3011 this.dom.$el.off('refresh.owl',this.e.refresh); 3012 this.dom.$el.off('autoHeight.owl',this.e.autoHeight); 3013 this.dom.$el.off('play.owl',this.e.play); 3014 this.dom.$el.off('stop.owl',this.e.stop); 3015 this.dom.$el.off('stopVideo.owl',this.e.stop); 3016 this.dom.$stage.off('click',this.e._playVideo); 3017 3018 if(this.dom.$cc !== null){ 3019 this.dom.$cc.remove(); 3020 } 3021 if(this.dom.$cItems !== null){ 3022 this.dom.$cItems.remove(); 3023 } 3024 this.e = null; 3025 this.dom.$el.data('owlCarousel',null); 3026 delete this.dom.el.owlCarousel; 3027 3028 this.dom.$stage.unwrap(); 3029 this.dom.$items.unwrap(); 3030 this.dom.$items.contents().unwrap(); 3031 this.dom = null; 3032 }; 3033 3034 /** 3035 * Opertators 3036 * @desc Used to calculate RTL 3037 * @param [a] - Number - left side 3038 * @param [o] - String - operator 3039 * @param [b] - Number - right side 3040 * @since 2.0.0 3041 */ 3042 3043 Owl.prototype.op = function(a,o,b){ 3044 var rtl = this.options.rtl; 3045 switch(o) { 3046 case '<': 3047 return rtl ? a > b : a < b; 3048 case '>': 3049 return rtl ? a < b : a > b; 3050 case '>=': 3051 return rtl ? a <= b : a >= b; 3052 case '<=': 3053 return rtl ? a >= b : a <= b; 3054 default: 3055 break; 3056 } 3057 }; 3058 3059 /** 3060 * Opertators 3061 * @desc Used to calculate RTL 3062 * @since 2.0.0 3063 */ 3064 3065 Owl.prototype.browserSupport = function(){ 3066 this.support3d = isPerspective(); 3067 3068 if(this.support3d){ 3069 this.transformVendor = isTransform(); 3070 3071 // take transitionend event name by detecting transition 3072 var endVendors = ['transitionend','webkitTransitionEnd','transitionend','oTransitionEnd']; 3073 this.transitionEndVendor = endVendors[isTransition()]; 3074 3075 // take vendor name from transform name 3076 this.vendorName = this.transformVendor.replace(/Transform/i,''); 3077 this.vendorName = this.vendorName !== '' ? '-'+this.vendorName.toLowerCase()+'-' : ''; 3078 } 3079 3080 this.state.orientation = window.orientation; 3081 }; 3082 3083 // Pivate methods 3084 3085 // CSS detection; 3086 function isStyleSupported(array){ 3087 var p,s,fake = document.createElement('div'),list = array; 3088 for(p in list){ 3089 s = list[p]; 3090 if(typeof fake.style[s] !== 'undefined'){ 3091 fake = null; 3092 return [s,p]; 3093 } 3094 } 3095 return [false]; 3096 } 3097 3098 function isTransition(){ 3099 return isStyleSupported(['transition','WebkitTransition','MozTransition','OTransition'])[1]; 3100 } 3101 3102 function isTransform() { 3103 return isStyleSupported(['transform','WebkitTransform','MozTransform','OTransform','msTransform'])[0]; 3104 } 3105 3106 function isPerspective(){ 3107 return isStyleSupported(['perspective','webkitPerspective','MozPerspective','OPerspective','MsPerspective'])[0]; 3108 } 3109 3110 function isTouchSupport(){ 3111 return 'ontouchstart' in window || !!(navigator.msMaxTouchPoints); 3112 } 3113 3114 function isTouchSupportIE(){ 3115 return window.navigator.msPointerEnabled; 3116 } 3117 3118 function isRetina(){ 3119 return window.devicePixelRatio > 1; 3120 } 3121 3122 $.fn.owlCarousel = function ( options ) { 3123 return this.each(function () { 3124 if (!$(this).data('owlCarousel')) { 3125 $(this).data( 'owlCarousel', 3126 new Owl( this, options )); 3127 } 3128 }); 3129 3130 }; 3131 3132})( window.Zepto || window.jQuery, window, document ); 3133 3134//https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind 3135//The bind() method creates a new function that, when called, has its this keyword set to the provided value, with a given sequence of arguments preceding any provided when the new function is called. 3136 3137if (!Function.prototype.bind) { 3138 Function.prototype.bind = function (oThis) { 3139 if (typeof this !== 'function') { 3140 // closest thing possible to the ECMAScript 5 internal IsCallable function 3141 throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable'); 3142 } 3143 3144 var aArgs = Array.prototype.slice.call(arguments, 1), 3145 fToBind = this, 3146 fNOP = function () {}, 3147 fBound = function () {
3148 return fToBind.apply(this instanceof fNOP && oThis ? this : oThis, aArgs.concat(Array.prototype.slice.call(arguments))); 3149 }; 3150 fNOP.prototype = this.prototype; 3151 fBound.prototype = new fNOP(); 3152 return fBound; 3153 }; 3154}
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.