middleman-ratchet 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 caedes
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,18 @@
1
+ # middleman-ratchet
2
+
3
+
4
+ ## Install
5
+
6
+ ```shell
7
+ gem install middleman
8
+ gem install middleman-ratchet
9
+ middleman init --template ratchet
10
+ ```
11
+
12
+ ## Contributing
13
+
14
+ 1. Fork it
15
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
16
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
17
+ 4. Push to the branch (`git push origin my-new-feature`)
18
+ 5. Create new Pull Request
@@ -0,0 +1 @@
1
+ require 'bundler/gem_tasks'
@@ -0,0 +1,6 @@
1
+ require 'middleman-core'
2
+
3
+ require 'middleman-ratchet/version'
4
+ require 'middleman-ratchet/template'
5
+
6
+ Middleman::Templates.register :ratchet, Middleman::Ratchet::Template
@@ -0,0 +1,33 @@
1
+ require 'middleman-core/templates'
2
+
3
+ module Middleman
4
+ module Ratchet
5
+
6
+ class Template < Middleman::Templates::Base
7
+ class_option 'css_dir',
8
+ default: 'stylesheets',
9
+ desc: 'The path to the css files'
10
+ class_option 'js_dir',
11
+ default: 'javascripts',
12
+ desc: 'The path to the javascript files'
13
+ class_option 'images_dir',
14
+ default: 'images',
15
+ desc: 'The path to the image files'
16
+
17
+ def self.source_root
18
+ File.join(File.dirname(__FILE__), 'template')
19
+ end
20
+
21
+ def build_scaffold
22
+ template 'shared/config.tt', File.join(location, 'config.rb')
23
+ directory 'source', File.join(location, 'source')
24
+
25
+ empty_directory File.join(location, 'source', options[:css_dir])
26
+ empty_directory File.join(location, 'source', options[:js_dir])
27
+ empty_directory File.join(location, 'source', options[:images_dir])
28
+ end
29
+ end
30
+ end
31
+ end
32
+
33
+ Middleman::Templates.register :ratchet, Middleman::Ratchet::Template
@@ -0,0 +1,17 @@
1
+ ---
2
+ title: Index
3
+ ---
4
+
5
+ / Make sure all your bars are the first things in your <body>
6
+ %header.bar-title
7
+ %h1.title= 'Index'
8
+
9
+ / Wrap all non-bar HTML in the .content div (this is actually what scrolls)
10
+ .content
11
+ .content-padded
12
+ %p= 'Fake Index Description'
13
+ %ul.list.inset
14
+ %li
15
+ = link_to 'page1.html', data: { transition: 'slide-in'} do
16
+ %strong= 'Page 1'
17
+ %span.chevron
@@ -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
+ }();