middleman-ratchet 0.1.0

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,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
+ }();