ratchet-rails 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,741 @@
1
+ /**
2
+ * ==================================
3
+ * Ratchet v1.0.0
4
+ * Licensed under The MIT License
5
+ * http://opensource.org/licenses/MIT
6
+ * ==================================
7
+ */
8
+
9
+ /* ----------------------------------
10
+ * POPOVER v1.0.0
11
+ * Licensed under The MIT License
12
+ * http://opensource.org/licenses/MIT
13
+ * ---------------------------------- */
14
+
15
+ !function () {
16
+
17
+ var popover;
18
+
19
+ var findPopovers = function (target) {
20
+ var i, popovers = document.querySelectorAll('a');
21
+ for (; target && target !== document; target = target.parentNode) {
22
+ for (i = popovers.length; i--;) { if (popovers[i] === target) return target; }
23
+ }
24
+ };
25
+
26
+ var onPopoverHidden = function () {
27
+ document.body.removeChild(backdrop);
28
+ popover.style.display = 'none';
29
+ popover.removeEventListener('webkitTransitionEnd', onPopoverHidden);
30
+ }
31
+
32
+ var backdrop = function () {
33
+ var element = document.createElement('div');
34
+
35
+ element.classList.add('backdrop');
36
+
37
+ element.addEventListener('touchend', function () {
38
+ popover.addEventListener('webkitTransitionEnd', onPopoverHidden);
39
+ popover.classList.remove('visible');
40
+ });
41
+
42
+ return element;
43
+ }();
44
+
45
+ var getPopover = function (e) {
46
+ var anchor = findPopovers(e.target);
47
+
48
+ if (!anchor || !anchor.hash) return;
49
+
50
+ popover = document.querySelector(anchor.hash);
51
+
52
+ if (!popover || !popover.classList.contains('popover')) return;
53
+
54
+ return popover;
55
+ }
56
+
57
+ window.addEventListener('touchend', function (e) {
58
+ var popover = getPopover(e);
59
+
60
+ if (!popover) return;
61
+
62
+ popover.style.display = 'block';
63
+ popover.offsetHeight;
64
+ popover.classList.add('visible');
65
+
66
+ popover.parentNode.appendChild(backdrop);
67
+ });
68
+
69
+ window.addEventListener('click', function (e) { if (getPopover(e)) e.preventDefault(); });
70
+
71
+ }();
72
+ /* ----------------------------------
73
+ * PUSH v1.0.0
74
+ * Licensed under The MIT License
75
+ * inspired by chris's jquery.pjax.js
76
+ * http://opensource.org/licenses/MIT
77
+ * ---------------------------------- */
78
+
79
+ !function () {
80
+
81
+ var noop = function () {};
82
+
83
+
84
+ // Pushstate cacheing
85
+ // ==================
86
+
87
+ var isScrolling;
88
+ var maxCacheLength = 20;
89
+ var cacheMapping = sessionStorage;
90
+ var domCache = {};
91
+ var transitionMap = {
92
+ 'slide-in' : 'slide-out',
93
+ 'slide-out' : 'slide-in',
94
+ 'fade' : 'fade'
95
+ };
96
+ var bars = {
97
+ bartab : '.bar-tab',
98
+ bartitle : '.bar-title',
99
+ barfooter : '.bar-footer',
100
+ barheadersecondary : '.bar-header-secondary'
101
+ }
102
+
103
+ var cacheReplace = function (data, updates) {
104
+ PUSH.id = data.id;
105
+ if (updates) data = getCached(data.id);
106
+ cacheMapping[data.id] = JSON.stringify(data);
107
+ window.history.replaceState(data.id, data.title, data.url);
108
+ domCache[data.id] = document.body.cloneNode(true);
109
+ };
110
+
111
+ var cachePush = function () {
112
+ var id = PUSH.id;
113
+
114
+ var cacheForwardStack = JSON.parse(cacheMapping.cacheForwardStack || '[]');
115
+ var cacheBackStack = JSON.parse(cacheMapping.cacheBackStack || '[]');
116
+
117
+ cacheBackStack.push(id);
118
+
119
+ while (cacheForwardStack.length) delete cacheMapping[cacheForwardStack.shift()];
120
+ while (cacheBackStack.length > maxCacheLength) delete cacheMapping[cacheBackStack.shift()];
121
+
122
+ window.history.pushState(null, '', cacheMapping[PUSH.id].url);
123
+
124
+ cacheMapping.cacheForwardStack = JSON.stringify(cacheForwardStack);
125
+ cacheMapping.cacheBackStack = JSON.stringify(cacheBackStack);
126
+ };
127
+
128
+ var cachePop = function (id, direction) {
129
+ var forward = direction == 'forward';
130
+ var cacheForwardStack = JSON.parse(cacheMapping.cacheForwardStack || '[]');
131
+ var cacheBackStack = JSON.parse(cacheMapping.cacheBackStack || '[]');
132
+ var pushStack = forward ? cacheBackStack : cacheForwardStack;
133
+ var popStack = forward ? cacheForwardStack : cacheBackStack;
134
+
135
+ if (PUSH.id) pushStack.push(PUSH.id);
136
+ popStack.pop();
137
+
138
+ cacheMapping.cacheForwardStack = JSON.stringify(cacheForwardStack);
139
+ cacheMapping.cacheBackStack = JSON.stringify(cacheBackStack);
140
+ };
141
+
142
+ var getCached = function (id) {
143
+ return JSON.parse(cacheMapping[id] || null) || {};
144
+ };
145
+
146
+ var getTarget = function (e) {
147
+ var target = findTarget(e.target);
148
+
149
+ if (
150
+ ! target
151
+ || e.which > 1
152
+ || e.metaKey
153
+ || e.ctrlKey
154
+ || isScrolling
155
+ || location.protocol !== target.protocol
156
+ || location.host !== target.host
157
+ || !target.hash && /#/.test(target.href)
158
+ || target.hash && target.href.replace(target.hash, '') === location.href.replace(location.hash, '')
159
+ || target.getAttribute('data-ignore') == 'push'
160
+ ) return;
161
+
162
+ return target;
163
+ };
164
+
165
+
166
+ // Main event handlers (touchend, popstate)
167
+ // ==========================================
168
+
169
+ var touchend = function (e) {
170
+ var target = getTarget(e);
171
+
172
+ if (!target) return;
173
+
174
+ e.preventDefault();
175
+
176
+ PUSH({
177
+ url : target.href,
178
+ hash : target.hash,
179
+ timeout : target.getAttribute('data-timeout'),
180
+ transition : target.getAttribute('data-transition')
181
+ });
182
+ };
183
+
184
+ var popstate = function (e) {
185
+ var key;
186
+ var barElement;
187
+ var activeObj;
188
+ var activeDom;
189
+ var direction;
190
+ var transition;
191
+ var transitionFrom;
192
+ var transitionFromObj;
193
+ var id = e.state;
194
+
195
+ if (!id || !cacheMapping[id]) return;
196
+
197
+ direction = PUSH.id < id ? 'forward' : 'back';
198
+
199
+ cachePop(id, direction);
200
+
201
+ activeObj = getCached(id);
202
+ activeDom = domCache[id];
203
+
204
+ if (activeObj.title) document.title = activeObj.title;
205
+
206
+ if (direction == 'back') {
207
+ transitionFrom = JSON.parse(direction == 'back' ? cacheMapping.cacheForwardStack : cacheMapping.cacheBackStack);
208
+ transitionFromObj = getCached(transitionFrom[transitionFrom.length - 1]);
209
+ } else {
210
+ transitionFromObj = activeObj;
211
+ }
212
+
213
+ if (direction == 'back' && !transitionFromObj.id) return PUSH.id = id;
214
+
215
+ transition = direction == 'back' ? transitionMap[transitionFromObj.transition] : transitionFromObj.transition;
216
+
217
+ if (!activeDom) {
218
+ return PUSH({
219
+ id : activeObj.id,
220
+ url : activeObj.url,
221
+ title : activeObj.title,
222
+ timeout : activeObj.timeout,
223
+ transition : transition,
224
+ ignorePush : true
225
+ });
226
+ }
227
+
228
+ if (transitionFromObj.transition) {
229
+ activeObj = extendWithDom(activeObj, '.content', activeDom.cloneNode(true));
230
+ for (key in bars) {
231
+ barElement = document.querySelector(bars[key])
232
+ if (activeObj[key]) swapContent(activeObj[key], barElement);
233
+ else if (barElement) barElement.parentNode.removeChild(barElement);
234
+ }
235
+ }
236
+
237
+ swapContent(
238
+ (activeObj.contents || activeDom).cloneNode(true),
239
+ document.querySelector('.content'),
240
+ transition
241
+ );
242
+
243
+ PUSH.id = id;
244
+
245
+ document.body.offsetHeight; // force reflow to prevent scroll
246
+ };
247
+
248
+
249
+ // Core PUSH functionality
250
+ // =======================
251
+
252
+ var PUSH = function (options) {
253
+ var key;
254
+ var data = {};
255
+ var xhr = PUSH.xhr;
256
+
257
+ options.container = options.container || options.transition ? document.querySelector('.content') : document.body;
258
+
259
+ for (key in bars) {
260
+ options[key] = options[key] || document.querySelector(bars[key]);
261
+ }
262
+
263
+ if (xhr && xhr.readyState < 4) {
264
+ xhr.onreadystatechange = noop;
265
+ xhr.abort()
266
+ }
267
+
268
+ xhr = new XMLHttpRequest();
269
+ xhr.open('GET', options.url, true);
270
+ xhr.setRequestHeader('X-PUSH', 'true');
271
+
272
+ xhr.onreadystatechange = function () {
273
+ if (options._timeout) clearTimeout(options._timeout);
274
+ if (xhr.readyState == 4) xhr.status == 200 ? success(xhr, options) : failure(options.url);
275
+ };
276
+
277
+ if (!PUSH.id) {
278
+ cacheReplace({
279
+ id : +new Date,
280
+ url : window.location.href,
281
+ title : document.title,
282
+ timeout : options.timeout,
283
+ transition : null
284
+ });
285
+ }
286
+
287
+ if (options.timeout) {
288
+ options._timeout = setTimeout(function () { xhr.abort('timeout'); }, options.timeout);
289
+ }
290
+
291
+ xhr.send();
292
+
293
+ if (xhr.readyState && !options.ignorePush) cachePush();
294
+ };
295
+
296
+
297
+ // Main XHR handlers
298
+ // =================
299
+
300
+ var success = function (xhr, options) {
301
+ var key;
302
+ var barElement;
303
+ var data = parseXHR(xhr, options);
304
+
305
+ if (!data.contents) return locationReplace(options.url);
306
+
307
+ if (data.title) document.title = data.title;
308
+
309
+ if (options.transition) {
310
+ for (key in bars) {
311
+ barElement = document.querySelector(bars[key])
312
+ if (data[key]) swapContent(data[key], barElement);
313
+ else if (barElement) barElement.parentNode.removeChild(barElement);
314
+ }
315
+ }
316
+
317
+ swapContent(data.contents, options.container, options.transition, function () {
318
+ cacheReplace({
319
+ id : options.id || +new Date,
320
+ url : data.url,
321
+ title : data.title,
322
+ timeout : options.timeout,
323
+ transition : options.transition
324
+ }, options.id);
325
+ triggerStateChange();
326
+ });
327
+
328
+ if (!options.ignorePush && window._gaq) _gaq.push(['_trackPageview']) // google analytics
329
+ if (!options.hash) return;
330
+ };
331
+
332
+ var failure = function (url) {
333
+ throw new Error('Could not get: ' + url)
334
+ };
335
+
336
+
337
+ // PUSH helpers
338
+ // ============
339
+
340
+ var swapContent = function (swap, container, transition, complete) {
341
+ var enter;
342
+ var containerDirection;
343
+ var swapDirection;
344
+
345
+ if (!transition) {
346
+ if (container) container.innerHTML = swap.innerHTML;
347
+ else if (swap.classList.contains('content')) document.body.appendChild(swap);
348
+ else document.body.insertBefore(swap, document.querySelector('.content'));
349
+ } else {
350
+ enter = /in$/.test(transition);
351
+
352
+ if (transition == 'fade') {
353
+ container.classList.add('in');
354
+ container.classList.add('fade');
355
+ swap.classList.add('fade');
356
+ }
357
+
358
+ if (/slide/.test(transition)) {
359
+ swap.classList.add(enter ? 'right' : 'left');
360
+ swap.classList.add('slide');
361
+ container.classList.add('slide');
362
+ }
363
+
364
+ container.parentNode.insertBefore(swap, container);
365
+ }
366
+
367
+ if (!transition) complete && complete();
368
+
369
+ if (transition == 'fade') {
370
+ container.offsetWidth; // force reflow
371
+ container.classList.remove('in');
372
+ container.addEventListener('webkitTransitionEnd', fadeContainerEnd);
373
+
374
+ function fadeContainerEnd() {
375
+ container.removeEventListener('webkitTransitionEnd', fadeContainerEnd);
376
+ swap.classList.add('in');
377
+ swap.addEventListener('webkitTransitionEnd', fadeSwapEnd);
378
+ }
379
+ function fadeSwapEnd () {
380
+ swap.removeEventListener('webkitTransitionEnd', fadeSwapEnd);
381
+ container.parentNode.removeChild(container);
382
+ swap.classList.remove('fade');
383
+ swap.classList.remove('in');
384
+ complete && complete();
385
+ }
386
+ }
387
+
388
+ if (/slide/.test(transition)) {
389
+ container.offsetWidth; // force reflow
390
+ swapDirection = enter ? 'right' : 'left'
391
+ containerDirection = enter ? 'left' : 'right'
392
+ container.classList.add(containerDirection);
393
+ swap.classList.remove(swapDirection);
394
+ swap.addEventListener('webkitTransitionEnd', slideEnd);
395
+
396
+ function slideEnd() {
397
+ swap.removeEventListener('webkitTransitionEnd', slideEnd);
398
+ swap.classList.remove('slide');
399
+ swap.classList.remove(swapDirection);
400
+ container.parentNode.removeChild(container);
401
+ complete && complete();
402
+ }
403
+ }
404
+ };
405
+
406
+ var triggerStateChange = function () {
407
+ var e = new CustomEvent('push', {
408
+ detail: { state: getCached(PUSH.id) },
409
+ bubbles: true,
410
+ cancelable: true
411
+ });
412
+
413
+ window.dispatchEvent(e);
414
+ };
415
+
416
+ var findTarget = function (target) {
417
+ var i, toggles = document.querySelectorAll('a');
418
+ for (; target && target !== document; target = target.parentNode) {
419
+ for (i = toggles.length; i--;) { if (toggles[i] === target) return target; }
420
+ }
421
+ };
422
+
423
+ var locationReplace = function (url) {
424
+ window.history.replaceState(null, '', '#');
425
+ window.location.replace(url);
426
+ };
427
+
428
+ var parseURL = function (url) {
429
+ var a = document.createElement('a'); a.href = url; return a;
430
+ };
431
+
432
+ var extendWithDom = function (obj, fragment, dom) {
433
+ var i;
434
+ var result = {};
435
+
436
+ for (i in obj) result[i] = obj[i];
437
+
438
+ Object.keys(bars).forEach(function (key) {
439
+ var el = dom.querySelector(bars[key]);
440
+ if (el) el.parentNode.removeChild(el);
441
+ result[key] = el;
442
+ });
443
+
444
+ result.contents = dom.querySelector(fragment);
445
+
446
+ return result;
447
+ };
448
+
449
+ var parseXHR = function (xhr, options) {
450
+ var head;
451
+ var body;
452
+ var data = {};
453
+ var responseText = xhr.responseText;
454
+
455
+ data.url = options.url;
456
+
457
+ if (!responseText) return data;
458
+
459
+ if (/<html/i.test(responseText)) {
460
+ head = document.createElement('div');
461
+ body = document.createElement('div');
462
+ head.innerHTML = responseText.match(/<head[^>]*>([\s\S.]*)<\/head>/i)[0]
463
+ body.innerHTML = responseText.match(/<body[^>]*>([\s\S.]*)<\/body>/i)[0]
464
+ } else {
465
+ head = body = document.createElement('div');
466
+ head.innerHTML = responseText;
467
+ }
468
+
469
+ data.title = head.querySelector('title');
470
+ data.title = data.title && data.title.innerText.trim();
471
+
472
+ if (options.transition) data = extendWithDom(data, '.content', body);
473
+ else data.contents = body;
474
+
475
+ return data;
476
+ };
477
+
478
+
479
+ // Attach PUSH event handlers
480
+ // ==========================
481
+
482
+ window.addEventListener('touchstart', function () { isScrolling = false; });
483
+ window.addEventListener('touchmove', function () { isScrolling = true; })
484
+ window.addEventListener('touchend', touchend);
485
+ window.addEventListener('click', function (e) { if (getTarget(e)) e.preventDefault(); });
486
+ window.addEventListener('popstate', popstate);
487
+
488
+ }();/* ----------------------------------
489
+ * TABS v1.0.0
490
+ * Licensed under The MIT License
491
+ * http://opensource.org/licenses/MIT
492
+ * ---------------------------------- */
493
+
494
+ !function () {
495
+ var getTarget = function (target) {
496
+ var i, popovers = document.querySelectorAll('.segmented-controller li a');
497
+ for (; target && target !== document; target = target.parentNode) {
498
+ for (i = popovers.length; i--;) { if (popovers[i] === target) return target; }
499
+ }
500
+ };
501
+
502
+ window.addEventListener("touchend", function (e) {
503
+ var activeTab;
504
+ var activeBody;
505
+ var targetBody;
506
+ var targetTab;
507
+ var className = 'active';
508
+ var classSelector = '.' + className;
509
+ var targetAnchor = getTarget(e.target);
510
+
511
+ if (!targetAnchor) return;
512
+
513
+ targetTab = targetAnchor.parentNode;
514
+ activeTab = targetTab.parentNode.querySelector(classSelector);
515
+
516
+ if (activeTab) activeTab.classList.remove(className);
517
+
518
+ targetTab.classList.add(className);
519
+
520
+ if (!targetAnchor.hash) return;
521
+
522
+ targetBody = document.querySelector(targetAnchor.hash);
523
+
524
+ if (!targetBody) return;
525
+
526
+ activeBody = targetBody.parentNode.querySelector(classSelector);
527
+
528
+ if (activeBody) activeBody.classList.remove(className);
529
+
530
+ targetBody.classList.add(className)
531
+ });
532
+
533
+ window.addEventListener('click', function (e) { if (getTarget(e.target)) e.preventDefault(); });
534
+ }();/* ----------------------------------
535
+ * SLIDER v1.0.0
536
+ * Licensed under The MIT License
537
+ * Adapted from Brad Birdsall's swipe
538
+ * http://opensource.org/licenses/MIT
539
+ * ---------------------------------- */
540
+
541
+ !function () {
542
+
543
+ var pageX;
544
+ var pageY;
545
+ var slider;
546
+ var deltaX;
547
+ var deltaY;
548
+ var offsetX;
549
+ var lastSlide;
550
+ var startTime;
551
+ var resistance;
552
+ var sliderWidth;
553
+ var slideNumber;
554
+ var isScrolling;
555
+ var scrollableArea;
556
+
557
+ var getSlider = function (target) {
558
+ var i, sliders = document.querySelectorAll('.slider ul');
559
+ for (; target && target !== document; target = target.parentNode) {
560
+ for (i = sliders.length; i--;) { if (sliders[i] === target) return target; }
561
+ }
562
+ }
563
+
564
+ var getScroll = function () {
565
+ var translate3d = slider.style.webkitTransform.match(/translate3d\(([^,]*)/);
566
+ return parseInt(translate3d ? translate3d[1] : 0)
567
+ };
568
+
569
+ var setSlideNumber = function (offset) {
570
+ var round = offset ? (deltaX < 0 ? 'ceil' : 'floor') : 'round';
571
+ slideNumber = Math[round](getScroll() / ( scrollableArea / slider.children.length) );
572
+ slideNumber += offset;
573
+ slideNumber = Math.min(slideNumber, 0);
574
+ slideNumber = Math.max(-(slider.children.length - 1), slideNumber);
575
+ }
576
+
577
+ var onTouchStart = function (e) {
578
+ slider = getSlider(e.target);
579
+
580
+ if (!slider) return;
581
+
582
+ var firstItem = slider.querySelector('li');
583
+
584
+ scrollableArea = firstItem.offsetWidth * slider.children.length;
585
+ isScrolling = undefined;
586
+ sliderWidth = slider.offsetWidth;
587
+ resistance = 1;
588
+ lastSlide = -(slider.children.length - 1);
589
+ startTime = +new Date;
590
+ pageX = e.touches[0].pageX;
591
+ pageY = e.touches[0].pageY;
592
+
593
+ setSlideNumber(0);
594
+
595
+ slider.style['-webkit-transition-duration'] = 0;
596
+ };
597
+
598
+ var onTouchMove = function (e) {
599
+ if (e.touches.length > 1 || !slider) return; // Exit if a pinch || no slider
600
+
601
+ deltaX = e.touches[0].pageX - pageX;
602
+ deltaY = e.touches[0].pageY - pageY;
603
+ pageX = e.touches[0].pageX;
604
+ pageY = e.touches[0].pageY;
605
+
606
+ if (typeof isScrolling == 'undefined') {
607
+ isScrolling = Math.abs(deltaY) > Math.abs(deltaX);
608
+ }
609
+
610
+ if (isScrolling) return;
611
+
612
+ offsetX = (deltaX / resistance) + getScroll();
613
+
614
+ e.preventDefault();
615
+
616
+ resistance = slideNumber == 0 && deltaX > 0 ? (pageX / sliderWidth) + 1.25 :
617
+ slideNumber == lastSlide && deltaX < 0 ? (Math.abs(pageX) / sliderWidth) + 1.25 : 1;
618
+
619
+ slider.style.webkitTransform = 'translate3d(' + offsetX + 'px,0,0)';
620
+ };
621
+
622
+ var onTouchEnd = function (e) {
623
+ if (!slider || isScrolling) return;
624
+
625
+ setSlideNumber(
626
+ (+new Date) - startTime < 1000 && Math.abs(deltaX) > 15 ? (deltaX < 0 ? -1 : 1) : 0
627
+ );
628
+
629
+ offsetX = slideNumber * sliderWidth;
630
+
631
+ slider.style['-webkit-transition-duration'] = '.2s';
632
+ slider.style.webkitTransform = 'translate3d(' + offsetX + 'px,0,0)';
633
+
634
+ e = new CustomEvent('slide', {
635
+ detail: { slideNumber: Math.abs(slideNumber) },
636
+ bubbles: true,
637
+ cancelable: true
638
+ });
639
+
640
+ slider.parentNode.dispatchEvent(e);
641
+ };
642
+
643
+ window.addEventListener('touchstart', onTouchStart);
644
+ window.addEventListener('touchmove', onTouchMove);
645
+ window.addEventListener('touchend', onTouchEnd);
646
+
647
+ }();
648
+ /* ----------------------------------
649
+ * TOGGLE v1.0.0
650
+ * Licensed under The MIT License
651
+ * http://opensource.org/licenses/MIT
652
+ * ---------------------------------- */
653
+
654
+ !function () {
655
+
656
+ var start = {};
657
+ var touchMove = false;
658
+ var distanceX = false;
659
+ var toggle = false;
660
+
661
+ var findToggle = function (target) {
662
+ var i, toggles = document.querySelectorAll('.toggle');
663
+ for (; target && target !== document; target = target.parentNode) {
664
+ for (i = toggles.length; i--;) { if (toggles[i] === target) return target; }
665
+ }
666
+ }
667
+
668
+ window.addEventListener('touchstart', function (e) {
669
+ e = e.originalEvent || e;
670
+
671
+ toggle = findToggle(e.target);
672
+
673
+ if (!toggle) return;
674
+
675
+ var handle = toggle.querySelector('.toggle-handle');
676
+ var toggleWidth = toggle.offsetWidth;
677
+ var handleWidth = handle.offsetWidth;
678
+ var offset = toggle.classList.contains('active') ? toggleWidth - handleWidth : 0;
679
+
680
+ start = { pageX : e.touches[0].pageX - offset, pageY : e.touches[0].pageY };
681
+ touchMove = false;
682
+
683
+ // todo: probably should be moved to the css
684
+ toggle.style['-webkit-transition-duration'] = 0;
685
+ });
686
+
687
+ window.addEventListener('touchmove', function (e) {
688
+ e = e.originalEvent || e;
689
+
690
+ if (e.touches.length > 1) return; // Exit if a pinch
691
+
692
+ if (!toggle) return;
693
+
694
+ var handle = toggle.querySelector('.toggle-handle');
695
+ var current = e.touches[0];
696
+ var toggleWidth = toggle.offsetWidth;
697
+ var handleWidth = handle.offsetWidth;
698
+ var offset = toggleWidth - handleWidth;
699
+
700
+ touchMove = true;
701
+ distanceX = current.pageX - start.pageX;
702
+
703
+ if (Math.abs(distanceX) < Math.abs(current.pageY - start.pageY)) return;
704
+
705
+ e.preventDefault();
706
+
707
+ if (distanceX < 0) return handle.style.webkitTransform = 'translate3d(0,0,0)';
708
+ if (distanceX > offset) return handle.style.webkitTransform = 'translate3d(' + offset + 'px,0,0)';
709
+
710
+ handle.style.webkitTransform = 'translate3d(' + distanceX + 'px,0,0)';
711
+
712
+ toggle.classList[(distanceX > (toggleWidth/2 - handleWidth/2)) ? 'add' : 'remove']('active');
713
+ });
714
+
715
+ window.addEventListener('touchend', function (e) {
716
+ if (!toggle) return;
717
+
718
+ var handle = toggle.querySelector('.toggle-handle');
719
+ var toggleWidth = toggle.offsetWidth;
720
+ var handleWidth = handle.offsetWidth;
721
+ var offset = toggleWidth - handleWidth;
722
+ var slideOn = (!touchMove && !toggle.classList.contains('active')) || (touchMove && (distanceX > (toggleWidth/2 - handleWidth/2)));
723
+
724
+ if (slideOn) handle.style.webkitTransform = 'translate3d(' + offset + 'px,0,0)';
725
+ else handle.style.webkitTransform = 'translate3d(0,0,0)';
726
+
727
+ toggle.classList[slideOn ? 'add' : 'remove']('active');
728
+
729
+ e = new CustomEvent('toggle', {
730
+ detail: { isActive: slideOn },
731
+ bubbles: true,
732
+ cancelable: true
733
+ });
734
+
735
+ toggle.dispatchEvent(e);
736
+
737
+ touchMove = false;
738
+ toggle = false;
739
+ });
740
+
741
+ }();