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