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