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