1/*! 2 * Swipe 2.2.11 3 * 4 * Brad Birdsall 5 * Copyright 2013, MIT License 6 * 7*/ 8 9// if the module has no dependencies, the above pattern can be simplified to 10// eslint-disable-next-line no-extra-semi 11;(function (root, factory) { 12 // eslint-disable-next-line no-undef 13 if (typeof define === 'function' && define.amd) { 14 // AMD. Register as an anonymous module. 15 // eslint-disable-next-line no-undef 16 define([], function(){ 17 root.Swipe = factory(); 18 return root.Swipe; 19 }); 20 } else if (typeof module === 'object' && module.exports) { 21 // Node. Does not work with strict CommonJS, but 22 // only CommonJS-like environments that support module.exports, 23 // like Node. 24 module.exports = factory(); 25 } else { 26 // Browser globals 27 root.Swipe = factory(); 28 } 29}(this, function () { 30 // Establish the root object, `window` (`self`) in the browser, `global` 31 // on the server, or `this` in some virtual machines. We use `self` 32 // instead of `window` for `WebWorker` support. 33 var root = typeof self == 'object' && self.self === self && self || 34 typeof global == 'object' && global.global === global && global || 35 this; 36 37 var _document = root.document; 38 39 function Swipe(container, options) { 40 41 'use strict'; 42 43 options = options || {}; 44 45 // setup initial vars 46 var start = {}; 47 var delta = {}; 48 var isScrolling; 49 50 // setup auto slideshow 51 var delay = options.auto || 0; 52 var interval; 53 54 var disabled = false; 55 56 // utilities 57 // simple no operation function 58 var noop = function() {}; 59 // offload a functions execution 60 var offloadFn = function(fn) { setTimeout(fn || noop, 0); }; 61 // Returns a function, that, as long as it continues to be invoked, will not 62 // be triggered. 63 var throttle = function (fn, threshhold) { 64 threshhold = threshhold || 100; 65 var timeout = null; 66 67 function cancel() { 68 if (timeout) clearTimeout(timeout); 69 } 70 71 function throttledFn() { 72 var context = this; 73 var args = arguments; 74 cancel(); 75 timeout = setTimeout(function() { 76 timeout = null; 77 fn.apply(context, args); 78 }, threshhold); 79 } 80 81 // allow remove throttled timeout 82 throttledFn.cancel = cancel; 83 84 return throttledFn; 85 }; 86 87 // check browser capabilities 88 var browser = { 89 addEventListener: !!root.addEventListener, 90 // eslint-disable-next-line no-undef 91 touch: ('ontouchstart' in root) || root.DocumentTouch && _document instanceof DocumentTouch, 92 transitions: (function(temp) { 93 var props = ['transitionProperty', 'WebkitTransition', 'MozTransition', 'OTransition', 'msTransition']; 94 for ( var i in props ) { 95 if (temp.style[ props[i] ] !== undefined){ 96 return true; 97 } 98 } 99 return false; 100 })(_document.createElement('swipe')) 101 }; 102 103 // quit if no root element 104 if (!container) return; 105 106 var element = container.children[0]; 107 var slides, slidePos, width, length; 108 var index = parseInt(options.startSlide, 10) || 0; 109 var speed = options.speed || 300; 110 options.continuous = options.continuous !== undefined ? options.continuous : true; 111 112 // check text direction 113 var slideDir = (function(el, prop, dir) { 114 if (el.currentStyle) { 115 dir = el.currentStyle[prop]; 116 } else if (root.getComputedStyle) { 117 dir = root.getComputedStyle(el, null).getPropertyValue(prop); 118 } 119 return 'rtl' === dir ? 'right' : 'left'; 120 })(container, 'direction'); 121 122 // AutoRestart option: auto restart slideshow after user's touch event 123 options.autoRestart = options.autoRestart !== undefined ? options.autoRestart : false;
124 125 // throttled setup 126 var throttledSetup = throttle(setup); 127 128 // setup event capturing 129 var events = { 130 131 handleEvent: function(event) { 132 if (disabled) return; 133 134 switch (event.type) { 135 case 'mousedown': 136 case 'touchstart': this.start(event); break; 137 case 'mousemove': 138 case 'touchmove': this.move(event); break; 139 case 'mouseup': 140 case 'mouseleave': 141 case 'touchend': this.end(event); break; 142 case 'webkitTransitionEnd': 143 case 'msTransitionEnd': 144 case 'oTransitionEnd': 145 case 'otransitionend': 146 case 'transitionend': this.transitionEnd(event); break; 147 case 'resize': throttledSetup(); break; 148 } 149 150 if (options.stopPropagation) { 151 event.stopPropagation(); 152 } 153 }, 154 155 start: function(event) { 156 var touches; 157 158 if (isMouseEvent(event)) { 159 touches = event; 160 event.preventDefault(); // For desktop Safari drag 161 } else { 162 touches = event.touches[0]; 163 } 164 165 // measure start values 166 start = { 167 168 // get initial touch coords 169 x: touches.pageX, 170 y: touches.pageY, 171 172 // store time to determine touch duration 173 time: +new Date() 174 175 }; 176 177 // used for testing first move event 178 isScrolling = undefined; 179 180 // reset delta and end measurements 181 delta = {}; 182 183 // attach touchmove and touchend listeners 184 if (isMouseEvent(event)) { 185 element.addEventListener('mousemove', this, false); 186 element.addEventListener('mouseup', this, false); 187 element.addEventListener('mouseleave', this, false); 188 } else { 189 element.addEventListener('touchmove', this, false); 190 element.addEventListener('touchend', this, false); 191 } 192 193 }, 194 195 move: function(event) { 196 var touches; 197 198 if (isMouseEvent(event)) { 199 touches = event; 200 } else { 201 // ensure swiping with one touch and not pinching 202 if ( event.touches.length > 1 || event.scale && event.scale !== 1) { 203 return; 204 } 205 206 if (options.disableScroll) { 207 event.preventDefault(); 208 } 209 210 touches = event.touches[0]; 211 } 212 213 // measure change in x and y 214 delta = { 215 x: touches.pageX - start.x, 216 y: touches.pageY - start.y 217 }; 218 219 // determine if scrolling test has run - one time test 220 if ( typeof isScrolling === 'undefined') { 221 isScrolling = !!( isScrolling || Math.abs(delta.x) < Math.abs(delta.y) ); 222 } 223 224 // if user is not trying to scroll vertically 225 if (!isScrolling) { 226 227 // prevent native scrolling 228 event.preventDefault(); 229 230 // stop slideshow 231 stop(); 232 233 // increase resistance if first or last slide 234 if (options.continuous) { // we don't add resistance at the end 235 236 translate(circle(index-1), delta.x + slidePos[circle(index-1)], 0); 237 translate(index, delta.x + slidePos[index], 0); 238 translate(circle(index+1), delta.x + slidePos[circle(index+1)], 0); 239 240 } else { 241 242 delta.x = 243 delta.x / 244 ( (!index && delta.x > 0 || // if first slide and sliding left 245 index === slides.length - 1 && // or if last slide and sliding right 246 delta.x < 0 // and if sliding at all 247 ) ? 248 ( Math.abs(delta.x) / width + 1 ) // determine resistance level 249 : 1 ); // no resistance if false 250 251 // translate 1:1 252 translate(index-1, delta.x + slidePos[index-1], 0); 253 translate(index, delta.x + slidePos[index], 0); 254 translate(index+1, delta.x + slidePos[index+1], 0); 255 } 256 } 257 }, 258 259 end: function(event) { 260 261 // measure duration 262 var duration = +new Date() - start.time; 263 264 // determine if slide attempt triggers next/prev slide 265 var isValidSlide = 266 Number(duration) < 250 && // if slide duration is less than 250ms 267 Math.abs(delta.x) > 20 || // and if slide amt is greater than 20px 268 Math.abs(delta.x) > width/2; // or if slide amt is greater than half the width 269 270 // determine if slide attempt is past start and end 271 var isPastBounds = 272 !index && delta.x > 0 || // if first slide and slide amt is greater than 0 273 index === slides.length - 1 && delta.x < 0; // or if last slide and slide amt is less than 0 274 275 if (options.continuous) { 276 isPastBounds = false;
277 } 278 279 // OLD determine direction of swipe (true:right, false:left) 280 // determine direction of swipe (1: backward, -1: forward) 281 var direction = Math.abs(delta.x) / delta.x; 282 283 // if not scrolling vertically 284 if (!isScrolling) { 285 286 if (isValidSlide && !isPastBounds) { 287 288 // if we're moving right 289 if (direction < 0) { 290 291 if (options.continuous) { // we need to get the next in this direction in place 292 293 move(circle(index-1), -width, 0); 294 move(circle(index+2), width, 0); 295 296 } else { 297 move(index-1, -width, 0); 298 } 299 300 move(index, slidePos[index]-width, speed); 301 move(circle(index+1), slidePos[circle(index+1)]-width, speed); 302 index = circle(index+1); 303 304 } else { 305 if (options.continuous) { // we need to get the next in this direction in place 306 307 move(circle(index+1), width, 0); 308 move(circle(index-2), -width, 0); 309 310 } else { 311 move(index+1, width, 0); 312 } 313 314 move(index, slidePos[index]+width, speed); 315 move(circle(index-1), slidePos[circle(index-1)]+width, speed); 316 index = circle(index-1); 317 } 318 319 runCallback(getPos(), slides[index], direction); 320 321 } else { 322 323 if (options.continuous) { 324 325 move(circle(index-1), -width, speed); 326 move(index, 0, speed); 327 move(circle(index+1), width, speed); 328 329 } else { 330 331 move(index-1, -width, speed); 332 move(index, 0, speed); 333 move(index+1, width, speed); 334 } 335 } 336 } 337 338 // kill touchmove and touchend event listeners until touchstart called again 339 if (isMouseEvent(event)) { 340 element.removeEventListener('mousemove', events, false); 341 element.removeEventListener('mouseup', events, false); 342 element.removeEventListener('mouseleave', events, false); 343 } else { 344 element.removeEventListener('touchmove', events, false); 345 element.removeEventListener('touchend', events, false); 346 } 347 348 }, 349 350 transitionEnd: function(event) { 351 var currentIndex = parseInt(event.target.getAttribute('data-index'), 10); 352 if (currentIndex === index) { 353 if (delay || options.autoRestart) restart(); 354 355 runTransitionEnd(getPos(), slides[index]); 356 } 357 } 358 }; 359 360 // trigger setup 361 setup(); 362 363 // start auto slideshow if applicable 364 begin(); 365 366 // Expose the Swipe API 367 return { 368 // initialize 369 setup: setup, 370 371 // go to slide 372 slide: function(to, speed) { 373 stop(); 374 slide(to, speed); 375 }, 376 377 // move to previous 378 prev: function() { 379 stop(); 380 prev(); 381 }, 382 383 // move to next 384 next: function() { 385 stop(); 386 next(); 387 }, 388 389 // Restart slideshow 390 restart: restart, 391 392 // cancel slideshow 393 stop: stop, 394 395 // return current index position 396 getPos: getPos, 397 398 // disable slideshow 399 disable: disable, 400 401 // enable slideshow 402 enable: enable, 403 404 // return total number of slides 405 getNumSlides: function() { return length; }, 406 407 // completely remove swipe 408 kill: kill 409 }; 410 411 // remove all event listeners 412 function detachEvents() { 413 if (browser.addEventListener) { 414 // remove current event listeners 415 element.removeEventListener('touchstart', events, false); 416 element.removeEventListener('mousedown', events, false); 417 element.removeEventListener('webkitTransitionEnd', events, false); 418 element.removeEventListener('msTransitionEnd', events, false); 419 element.removeEventListener('oTransitionEnd', events, false); 420 element.removeEventListener('otransitionend', events, false); 421 element.removeEventListener('transitionend', events, false); 422 root.removeEventListener('resize', events, false); 423 } else { 424 root.onresize = null; 425 } 426 } 427 428 // add event listeners 429 function attachEvents() { 430 if (browser.addEventListener) { 431 432 // set touchstart event on element 433 if (browser.touch) { 434 element.addEventListener('touchstart', events, false); 435 } 436 437 if (options.draggable) { 438 element.addEventListener('mousedown', events, false); 439 } 440 441 if (browser.transitions) { 442 element.addEventListener('webkitTransitionEnd', events, false); 443 element.addEventListener('msTransitionEnd', events, false); 444 element.addEventListener('oTransitionEnd', events, false); 445 element.addEventListener('otransitionend', events, false); 446 element.addEventListener('transitionend', events, false); 447 } 448 449 // set resize event on window 450 root.addEventListener('resize', events, false); 451 452 } else { 453 root.onresize = throttledSetup; // to play nice with old IE 454 } 455 } 456 457 // clone nodes when there is only two slides 458 function cloneNode(el) { 459 var clone = el.cloneNode(true); 460 element.appendChild(clone); 461 462 // tag these slides as clones (to remove them on kill) 463 clone.setAttribute('data-cloned', true); 464 465 // Remove id from element 466 clone.removeAttribute('id'); 467 } 468 469 function setup(opts) { 470 // Overwrite options if necessary 471 if (opts != null) { 472 for (var prop in opts) { 473 options[prop] = opts[prop]; 474 } 475 } 476 477 // cache slides 478 slides = element.children; 479 length = slides.length; 480 481 // slides length correction, minus cloned slides 482 for (var i = 0; i < slides.length; i++) { 483 if (slides[i].getAttribute('data-cloned')) length--; 484 } 485 486 // set continuous to false if only one slide 487 if (slides.length < 2) { 488 options.continuous = false;
489 } 490 491 // special case if two slides 492 if (browser.transitions && options.continuous && slides.length < 3) { 493 cloneNode(slides[0]); 494 cloneNode(slides[1]); 495 496 slides = element.children; 497 } 498 499 // adjust style on rtl 500 if ('right' === slideDir) { 501 for (var j = 0; j < slides.length; j++) { 502 slides[j].style.float = 'right'; 503 } 504 } 505 506 // create an array to store current positions of each slide 507 slidePos = new Array(slides.length); 508 509 // determine width of each slide 510 width = container.getBoundingClientRect().width || container.offsetWidth; 511 512 element.style.width = (slides.length * width * 2) + 'px'; 513 514 // stack elements 515 var pos = slides.length; 516 while(pos--) { 517 var slide = slides[pos]; 518 519 slide.style.width = width + 'px'; 520 slide.setAttribute('data-index', pos); 521 522 if (browser.transitions) { 523 slide.style[slideDir] = (pos * -width) + 'px'; 524 move(pos, index > pos ? -width : (index < pos ? width : 0), 0); 525 } 526 } 527 528 // reposition elements before and after index 529 if (options.continuous && browser.transitions) { 530 move(circle(index-1), -width, 0); 531 move(circle(index+1), width, 0); 532 } 533 534 if (!browser.transitions) { 535 element.style[slideDir] = (index * -width) + 'px'; 536 } 537 538 container.style.visibility = 'visible'; 539 540 // reinitialize events 541 detachEvents(); 542 attachEvents(); 543 } 544 545 function prev() { 546 if (disabled) return; 547 548 if (options.continuous) { 549 slide(index-1); 550 } else if (index) { 551 slide(index-1); 552 } 553 } 554 555 function next() { 556 if (disabled) return; 557 558 if (options.continuous) { 559 slide(index+1); 560 } else if (index < slides.length - 1) { 561 slide(index+1); 562 } 563 } 564 565 function runCallback(pos, index, dir) { 566 if (options.callback) { 567 options.callback(pos, index, dir); 568 } 569 } 570 571 function runTransitionEnd(pos, index) { 572 if (options.transitionEnd) { 573 options.transitionEnd(pos, index); 574 } 575 } 576 577 function circle(index) { 578 579 // a simple positive modulo using slides.length 580 return (slides.length + (index % slides.length)) % slides.length; 581 } 582 583 function getPos() { 584 // Fix for the clone issue in the event of 2 slides 585 var currentIndex = index; 586 587 if (currentIndex >= length) { 588 currentIndex = currentIndex - length; 589 } 590 591 return currentIndex; 592 } 593 594 function slide(to, slideSpeed) { 595 596 // ensure to is of type 'number' 597 to = typeof to !== 'number' ? parseInt(to, 10) : to; 598 599 // do nothing if already on requested slide 600 if (index === to) return; 601 602 if (browser.transitions) { 603 604 var direction = Math.abs(index-to) / (index-to); // 1: backward, -1: forward 605 606 // get the actual position of the slide 607 if (options.continuous) { 608 var natural_direction = direction; 609 direction = -slidePos[circle(to)] / width; 610 611 // if going forward but to < index, use to = slides.length + to 612 // if going backward but to > index, use to = -slides.length + to 613 if (direction !== natural_direction) { 614 to = -direction * slides.length + to; 615 } 616 617 } 618 619 var diff = Math.abs(index-to) - 1; 620 621 // move all the slides between index and to in the right direction 622 while (diff--) { 623 move( circle((to > index ? to : index) - diff - 1), width * direction, 0); 624 } 625 626 to = circle(to); 627 628 move(index, width * direction, slideSpeed || speed); 629 move(to, 0, slideSpeed || speed); 630 631 if (options.continuous) { // we need to get the next in place 632 move(circle(to - direction), -(width * direction), 0); 633 } 634 635 } else { 636 637 to = circle(to); 638 animate(index * -width, to * -width, slideSpeed || speed); 639 // no fallback for a circular continuous if the browser does not accept transitions 640 } 641 642 index = to; 643 offloadFn(function() { 644 runCallback(getPos(), slides[index], direction); 645 }); 646 } 647 648 function move(index, dist, speed) { 649 translate(index, dist, speed); 650 slidePos[index] = dist; 651 } 652 653 function translate(index, dist, speed) { 654 655 var slide = slides[index]; 656 var style = slide && slide.style; 657 658 if (!style) return; 659 660 style.webkitTransitionDuration = 661 style.MozTransitionDuration = 662 style.msTransitionDuration = 663 style.OTransitionDuration = 664 style.transitionDuration = speed + 'ms'; 665 666 style.webkitTransform = 667 style.msTransform = 668 style.MozTransform = 669 style.OTransform = 670 style.transform = 'translateX(' + dist + 'px)'; 671 } 672 673 function animate(from, to, speed) { 674 675 // if not an animation, just reposition 676 if (!speed) { 677 element.style[slideDir] = to + 'px'; 678 return; 679 } 680 681 var start = +new Date(); 682 683 var timer = setInterval(function() { 684 var timeElap = +new Date() - start; 685 686 if (timeElap > speed) { 687 688 element.style[slideDir] = to + 'px'; 689 690 if (delay || options.autoRestart) restart(); 691 692 runTransitionEnd(getPos(), slides[index]); 693 694 clearInterval(timer); 695 696 return; 697 } 698 699 element.style[slideDir] = (( (to - from) * (Math.floor((timeElap / speed) * 100) / 100) ) + from) + 'px'; 700 }, 4); 701 702 } 703 704 function begin() {
705 delay = options.auto || 0; 706 if (delay) interval = setTimeout(next, delay); 707 } 708 709 function stop() { 710 delay = 0; 711 clearTimeout(interval); 712 } 713 714 function restart() { 715 stop(); 716 begin(); 717 } 718 719 function disable() { 720 stop(); 721 disabled = true; 722 } 723 724 function enable() { 725 disabled = false; 726 restart(); 727 } 728 729 function isMouseEvent(e) { 730 return /^mouse/.test(e.type); 731 } 732 733 function kill() { 734 // cancel slideshow 735 stop(); 736 737 // remove inline styles 738 container.style.visibility = ''; 739 740 // reset element 741 element.style.width = ''; 742 element.style[slideDir] = ''; 743 744 // reset slides 745 var pos = slides.length; 746 while (pos--) { 747 748 if (browser.transitions) { 749 translate(pos, 0, 0); 750 } 751 752 var slide = slides[pos]; 753 754 // if the slide is tagged as clone, remove it 755 if (slide.getAttribute('data-cloned')) { 756 var _parent = slide.parentElement; 757 _parent.removeChild(slide); 758 } 759 760 // remove styles 761 slide.style.width = ''; 762 slide.style[slideDir] = ''; 763 764 slide.style.webkitTransitionDuration = 765 slide.style.MozTransitionDuration = 766 slide.style.msTransitionDuration = 767 slide.style.OTransitionDuration = 768 slide.style.transitionDuration = ''; 769 770 slide.style.webkitTransform = 771 slide.style.msTransform = 772 slide.style.MozTransform = 773 slide.style.OTransform = ''; 774 775 // remove custom attributes (?) 776 // slide.removeAttribute('data-index'); 777 } 778 779 // remove all events 780 detachEvents(); 781 782 // remove throttled function timeout 783 throttledSetup.cancel(); 784 } 785 } 786 787 if ( root.jQuery || root.Zepto ) { 788 (function($) { 789 $.fn.Swipe = function(params) { 790 return this.each(function() { 791 $(this).data('Swipe', new Swipe($(this)[0], params)); 792 }); 793 }; 794 })( root.jQuery || root.Zepto ); 795 } 796 797 return Swipe; 798}));
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.