first commit
[ratchet] / lib / js / sliders.js
1 /* ----------------------------------
2  * SLIDER v1.0.0
3  * Licensed under The MIT License
4  * Adapted from Brad Birdsall's swipe
5  * http://opensource.org/licenses/MIT
6  * ---------------------------------- */
7
8 !function () {
9
10   var pageX;
11   var pageY;
12   var slider;
13   var deltaX;
14   var deltaY;
15   var offsetX;
16   var lastSlide;
17   var startTime;
18   var resistance;
19   var sliderWidth;
20   var slideNumber;
21   var isScrolling;
22   var scrollableArea;
23
24   var getSlider = function (target) {
25     var i, sliders = document.querySelectorAll('.slider ul');
26     for (; target && target !== document; target = target.parentNode) {
27       for (i = sliders.length; i--;) { if (sliders[i] === target) return target; }
28     }
29   }
30
31   var getScroll = function () {
32     var translate3d = slider.style.webkitTransform.match(/translate3d\(([^,]*)/);
33     return parseInt(translate3d ? translate3d[1] : 0)
34   };
35
36   var setSlideNumber = function (offset) {
37     var round = offset ? (deltaX < 0 ? 'ceil' : 'floor') : 'round';
38     slideNumber = Math[round](getScroll() / ( scrollableArea / slider.children.length) );
39     slideNumber += offset;
40     slideNumber = Math.min(slideNumber, 0);
41     slideNumber = Math.max(-(slider.children.length - 1), slideNumber);
42   }
43
44   var onTouchStart = function (e) {
45     slider = getSlider(e.target);
46
47     if (!slider) return;
48
49     var firstItem  = slider.querySelector('li');
50
51     scrollableArea = firstItem.offsetWidth * slider.children.length;
52     isScrolling    = undefined;
53     sliderWidth    = slider.offsetWidth;
54     resistance     = 1;
55     lastSlide      = -(slider.children.length - 1);
56     startTime      = +new Date;
57     pageX          = e.touches[0].pageX;
58     pageY          = e.touches[0].pageY;
59
60     setSlideNumber(0);
61
62     slider.style['-webkit-transition-duration'] = 0;
63   };
64
65   var onTouchMove = function (e) {
66     if (e.touches.length > 1 || !slider) return; // Exit if a pinch || no slider
67
68     deltaX = e.touches[0].pageX - pageX;
69     deltaY = e.touches[0].pageY - pageY;
70     pageX  = e.touches[0].pageX;
71     pageY  = e.touches[0].pageY;
72
73     if (typeof isScrolling == 'undefined') {
74       isScrolling = Math.abs(deltaY) > Math.abs(deltaX);
75     }
76
77     if (isScrolling) return;
78
79     offsetX = (deltaX / resistance) + getScroll();
80
81     e.preventDefault();
82
83     resistance = slideNumber == 0         && deltaX > 0 ? (pageX / sliderWidth) + 1.25 :
84                  slideNumber == lastSlide && deltaX < 0 ? (Math.abs(pageX) / sliderWidth) + 1.25 : 1;
85
86     slider.style.webkitTransform = 'translate3d(' + offsetX + 'px,0,0)';
87   };
88
89   var onTouchEnd = function (e) {
90     if (!slider || isScrolling) return;
91
92     setSlideNumber(
93       (+new Date) - startTime < 1000 && Math.abs(deltaX) > 15 ? (deltaX < 0 ? -1 : 1) : 0
94     );
95
96     offsetX = slideNumber * sliderWidth;
97
98     slider.style['-webkit-transition-duration'] = '.2s';
99     slider.style.webkitTransform = 'translate3d(' + offsetX + 'px,0,0)';
100
101     e = new CustomEvent('slide', {
102       detail: { slideNumber: Math.abs(slideNumber) },
103       bubbles: true,
104       cancelable: true
105     });
106
107     slider.parentNode.dispatchEvent(e);
108   };
109
110   window.addEventListener('touchstart', onTouchStart);
111   window.addEventListener('touchmove', onTouchMove);
112   window.addEventListener('touchend', onTouchEnd);
113
114 }();