PageSourceSearch

https://www.fricke-ritschel.de/js/swipe.js

js fricke-ritschel.de collected 2026-10-06 22:11:24 UTC 21,505 bytes, 778 lines download raw bytes

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.