twitter_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.
Files changed (56) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/Rakefile +34 -0
  4. data/app/assets/fonts/ratchicons.eot +0 -0
  5. data/app/assets/fonts/ratchicons.svg +61 -0
  6. data/app/assets/fonts/ratchicons.ttf +0 -0
  7. data/app/assets/fonts/ratchicons.woff +0 -0
  8. data/app/assets/javascripts/twitter_ratchet_rails/ratchet.js +916 -0
  9. data/app/assets/javascripts/twitter_ratchet_rails.js +1 -0
  10. data/app/assets/stylesheets/ratchet_android.css +4 -0
  11. data/app/assets/stylesheets/ratchet_base.css +3 -0
  12. data/app/assets/stylesheets/ratchet_ios.css +4 -0
  13. data/app/assets/stylesheets/twitter_ratchet_rails/ratchet-theme-android.css +588 -0
  14. data/app/assets/stylesheets/twitter_ratchet_rails/ratchet-theme-ios.css +471 -0
  15. data/app/assets/stylesheets/twitter_ratchet_rails/ratchet.css.erb +1430 -0
  16. data/app/helpers/twitter_ratchet_rails/application_helper.rb +4 -0
  17. data/app/views/layouts/twitter_ratchet_rails/application.html.erb +14 -0
  18. data/lib/tasks/twitter_ratchet_rails_tasks.rake +4 -0
  19. data/lib/twitter_ratchet_rails/engine.rb +5 -0
  20. data/lib/twitter_ratchet_rails/version.rb +3 -0
  21. data/lib/twitter_ratchet_rails.rb +4 -0
  22. data/test/dummy/README.rdoc +28 -0
  23. data/test/dummy/Rakefile +6 -0
  24. data/test/dummy/app/assets/javascripts/application.js +13 -0
  25. data/test/dummy/app/assets/stylesheets/application.css +13 -0
  26. data/test/dummy/app/controllers/application_controller.rb +5 -0
  27. data/test/dummy/app/helpers/application_helper.rb +2 -0
  28. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  29. data/test/dummy/bin/bundle +3 -0
  30. data/test/dummy/bin/rails +4 -0
  31. data/test/dummy/bin/rake +4 -0
  32. data/test/dummy/config/application.rb +23 -0
  33. data/test/dummy/config/boot.rb +5 -0
  34. data/test/dummy/config/database.yml +25 -0
  35. data/test/dummy/config/environment.rb +5 -0
  36. data/test/dummy/config/environments/development.rb +29 -0
  37. data/test/dummy/config/environments/production.rb +80 -0
  38. data/test/dummy/config/environments/test.rb +36 -0
  39. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  40. data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  41. data/test/dummy/config/initializers/inflections.rb +16 -0
  42. data/test/dummy/config/initializers/mime_types.rb +5 -0
  43. data/test/dummy/config/initializers/secret_token.rb +12 -0
  44. data/test/dummy/config/initializers/session_store.rb +3 -0
  45. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  46. data/test/dummy/config/locales/en.yml +23 -0
  47. data/test/dummy/config/routes.rb +4 -0
  48. data/test/dummy/config.ru +4 -0
  49. data/test/dummy/public/404.html +58 -0
  50. data/test/dummy/public/422.html +58 -0
  51. data/test/dummy/public/500.html +57 -0
  52. data/test/dummy/public/favicon.ico +0 -0
  53. data/test/integration/navigation_test.rb +10 -0
  54. data/test/test_helper.rb +15 -0
  55. data/test/twitter_ratchet_rails_test.rb +7 -0
  56. metadata +146 -0
@@ -0,0 +1,916 @@
1
+ /*!
2
+ * =====================================================
3
+ * Ratchet v2.0.1 (http://goratchet.com)
4
+ * Copyright 2014 Connor Sears
5
+ * Licensed under MIT.
6
+ *
7
+ * v2.0.1 designed by @connors.
8
+ * =====================================================
9
+ */
10
+ /* ----------------------------------
11
+ * MODAL v2.0.1
12
+ * Licensed under The MIT License
13
+ * http://opensource.org/licenses/MIT
14
+ * ---------------------------------- */
15
+
16
+ !(function () {
17
+ 'use strict';
18
+
19
+ var findModals = function (target) {
20
+ var i, modals = document.querySelectorAll('a');
21
+ for (; target && target !== document; target = target.parentNode) {
22
+ for (i = modals.length; i--;) {
23
+ if (modals[i] === target) {
24
+ return target;
25
+ }
26
+ }
27
+ }
28
+ };
29
+
30
+ var getModal = function (event) {
31
+ var modalToggle = findModals(event.target);
32
+ if (modalToggle && modalToggle.hash) {
33
+ return document.querySelector(modalToggle.hash);
34
+ }
35
+ };
36
+
37
+ window.addEventListener('touchend', function (event) {
38
+ var modal = getModal(event);
39
+ if (modal) {
40
+ if (modal && modal.classList.contains('modal')) {
41
+ modal.classList.toggle('active');
42
+ }
43
+ event.preventDefault(); // prevents rewriting url (apps can still use hash values in url)
44
+ }
45
+ });
46
+ }());
47
+
48
+ /* ----------------------------------
49
+ * POPOVER v2.0.1
50
+ * Licensed under The MIT License
51
+ * http://opensource.org/licenses/MIT
52
+ * ---------------------------------- */
53
+
54
+ !(function () {
55
+ 'use strict';
56
+
57
+ var popover;
58
+
59
+ var findPopovers = function (target) {
60
+ var i, popovers = document.querySelectorAll('a');
61
+ for (; target && target !== document; target = target.parentNode) {
62
+ for (i = popovers.length; i--;) {
63
+ if (popovers[i] === target) {
64
+ return target;
65
+ }
66
+ }
67
+ }
68
+ };
69
+
70
+ var onPopoverHidden = function () {
71
+ popover.style.display = 'none';
72
+ popover.removeEventListener('webkitTransitionEnd', onPopoverHidden);
73
+ };
74
+
75
+ var backdrop = (function () {
76
+ var element = document.createElement('div');
77
+
78
+ element.classList.add('backdrop');
79
+
80
+ element.addEventListener('touchend', function () {
81
+ popover.addEventListener('webkitTransitionEnd', onPopoverHidden);
82
+ popover.classList.remove('visible');
83
+ popover.parentNode.removeChild(backdrop);
84
+ });
85
+
86
+ return element;
87
+ }());
88
+
89
+ var getPopover = function (e) {
90
+ var anchor = findPopovers(e.target);
91
+
92
+ if (!anchor || !anchor.hash || (anchor.hash.indexOf('/') > 0)) {
93
+ return;
94
+ }
95
+
96
+ try {
97
+ popover = document.querySelector(anchor.hash);
98
+ }
99
+ catch (error) {
100
+ popover = null;
101
+ }
102
+
103
+ if (popover == null) {
104
+ return;
105
+ }
106
+
107
+ if (!popover || !popover.classList.contains('popover')) {
108
+ return;
109
+ }
110
+
111
+ return popover;
112
+ };
113
+
114
+ var showHidePopover = function (e) {
115
+ var popover = getPopover(e);
116
+
117
+ if (!popover) {
118
+ return;
119
+ }
120
+
121
+ popover.style.display = 'block';
122
+ popover.offsetHeight;
123
+ popover.classList.add('visible');
124
+
125
+ popover.parentNode.appendChild(backdrop);
126
+ };
127
+
128
+ window.addEventListener('touchend', showHidePopover);
129
+ window.addEventListener('click', showHidePopover);
130
+
131
+ }());
132
+
133
+ /* ----------------------------------
134
+ * PUSH v2.0.1
135
+ * Licensed under The MIT License
136
+ * inspired by chris's jquery.pjax.js
137
+ * http://opensource.org/licenses/MIT
138
+ * ---------------------------------- */
139
+
140
+ /* global _gaq: true */
141
+
142
+ !(function () {
143
+ 'use strict';
144
+
145
+ var noop = function () {};
146
+
147
+
148
+ // Pushstate cacheing
149
+ // ==================
150
+
151
+ var isScrolling;
152
+ var maxCacheLength = 20;
153
+ var cacheMapping = sessionStorage;
154
+ var domCache = {};
155
+ var transitionMap = {
156
+ 'slide-in' : 'slide-out',
157
+ 'slide-out' : 'slide-in',
158
+ 'fade' : 'fade'
159
+ };
160
+
161
+ var bars = {
162
+ bartab : '.bar-tab',
163
+ barnav : '.bar-nav',
164
+ barfooter : '.bar-footer',
165
+ barheadersecondary : '.bar-header-secondary'
166
+ };
167
+
168
+ var cacheReplace = function (data, updates) {
169
+ PUSH.id = data.id;
170
+ if (updates) {
171
+ data = getCached(data.id);
172
+ }
173
+ cacheMapping[data.id] = JSON.stringify(data);
174
+ window.history.replaceState(data.id, data.title, data.url);
175
+ domCache[data.id] = document.body.cloneNode(true);
176
+ };
177
+
178
+ var cachePush = function () {
179
+ var id = PUSH.id;
180
+
181
+ var cacheForwardStack = JSON.parse(cacheMapping.cacheForwardStack || '[]');
182
+ var cacheBackStack = JSON.parse(cacheMapping.cacheBackStack || '[]');
183
+
184
+ cacheBackStack.push(id);
185
+
186
+ while (cacheForwardStack.length) {
187
+ delete cacheMapping[cacheForwardStack.shift()];
188
+ }
189
+ while (cacheBackStack.length > maxCacheLength) {
190
+ delete cacheMapping[cacheBackStack.shift()];
191
+ }
192
+
193
+ window.history.pushState(null, '', cacheMapping[PUSH.id].url);
194
+
195
+ cacheMapping.cacheForwardStack = JSON.stringify(cacheForwardStack);
196
+ cacheMapping.cacheBackStack = JSON.stringify(cacheBackStack);
197
+ };
198
+
199
+ var cachePop = function (id, direction) {
200
+ var forward = direction === 'forward';
201
+ var cacheForwardStack = JSON.parse(cacheMapping.cacheForwardStack || '[]');
202
+ var cacheBackStack = JSON.parse(cacheMapping.cacheBackStack || '[]');
203
+ var pushStack = forward ? cacheBackStack : cacheForwardStack;
204
+ var popStack = forward ? cacheForwardStack : cacheBackStack;
205
+
206
+ if (PUSH.id) {
207
+ pushStack.push(PUSH.id);
208
+ }
209
+ popStack.pop();
210
+
211
+ cacheMapping.cacheForwardStack = JSON.stringify(cacheForwardStack);
212
+ cacheMapping.cacheBackStack = JSON.stringify(cacheBackStack);
213
+ };
214
+
215
+ var getCached = function (id) {
216
+ return JSON.parse(cacheMapping[id] || null) || {};
217
+ };
218
+
219
+ var getTarget = function (e) {
220
+ var target = findTarget(e.target);
221
+
222
+ if (!target ||
223
+ e.which > 1 ||
224
+ e.metaKey ||
225
+ e.ctrlKey ||
226
+ isScrolling ||
227
+ location.protocol !== target.protocol ||
228
+ location.host !== target.host ||
229
+ !target.hash && /#/.test(target.href) ||
230
+ target.hash && target.href.replace(target.hash, '') === location.href.replace(location.hash, '') ||
231
+ target.getAttribute('data-ignore') === 'push') { return; }
232
+
233
+ return target;
234
+ };
235
+
236
+
237
+ // Main event handlers (touchend, popstate)
238
+ // ==========================================
239
+
240
+ var touchend = function (e) {
241
+ var target = getTarget(e);
242
+
243
+ if (!target) {
244
+ return;
245
+ }
246
+
247
+ e.preventDefault();
248
+
249
+ PUSH({
250
+ url : target.href,
251
+ hash : target.hash,
252
+ timeout : target.getAttribute('data-timeout'),
253
+ transition : target.getAttribute('data-transition')
254
+ });
255
+ };
256
+
257
+ var popstate = function (e) {
258
+ var key;
259
+ var barElement;
260
+ var activeObj;
261
+ var activeDom;
262
+ var direction;
263
+ var transition;
264
+ var transitionFrom;
265
+ var transitionFromObj;
266
+ var id = e.state;
267
+
268
+ if (!id || !cacheMapping[id]) {
269
+ return;
270
+ }
271
+
272
+ direction = PUSH.id < id ? 'forward' : 'back';
273
+
274
+ cachePop(id, direction);
275
+
276
+ activeObj = getCached(id);
277
+ activeDom = domCache[id];
278
+
279
+ if (activeObj.title) {
280
+ document.title = activeObj.title;
281
+ }
282
+
283
+ if (direction === 'back') {
284
+ transitionFrom = JSON.parse(direction === 'back' ? cacheMapping.cacheForwardStack : cacheMapping.cacheBackStack);
285
+ transitionFromObj = getCached(transitionFrom[transitionFrom.length - 1]);
286
+ } else {
287
+ transitionFromObj = activeObj;
288
+ }
289
+
290
+ if (direction === 'back' && !transitionFromObj.id) {
291
+ return (PUSH.id = id);
292
+ }
293
+
294
+ transition = direction === 'back' ? transitionMap[transitionFromObj.transition] : transitionFromObj.transition;
295
+
296
+ if (!activeDom) {
297
+ return PUSH({
298
+ id : activeObj.id,
299
+ url : activeObj.url,
300
+ title : activeObj.title,
301
+ timeout : activeObj.timeout,
302
+ transition : transition,
303
+ ignorePush : true
304
+ });
305
+ }
306
+
307
+ if (transitionFromObj.transition) {
308
+ activeObj = extendWithDom(activeObj, '.content', activeDom.cloneNode(true));
309
+ for (key in bars) {
310
+ if (bars.hasOwnProperty(key)) {
311
+ barElement = document.querySelector(bars[key]);
312
+ if (activeObj[key]) {
313
+ swapContent(activeObj[key], barElement);
314
+ } else if (barElement) {
315
+ barElement.parentNode.removeChild(barElement);
316
+ }
317
+ }
318
+ }
319
+ }
320
+
321
+ swapContent(
322
+ (activeObj.contents || activeDom).cloneNode(true),
323
+ document.querySelector('.content'),
324
+ transition
325
+ );
326
+
327
+ PUSH.id = id;
328
+
329
+ document.body.offsetHeight; // force reflow to prevent scroll
330
+ };
331
+
332
+
333
+ // Core PUSH functionality
334
+ // =======================
335
+
336
+ var PUSH = function (options) {
337
+ var key;
338
+ var xhr = PUSH.xhr;
339
+
340
+ options.container = options.container || options.transition ? document.querySelector('.content') : document.body;
341
+
342
+ for (key in bars) {
343
+ if (bars.hasOwnProperty(key)) {
344
+ options[key] = options[key] || document.querySelector(bars[key]);
345
+ }
346
+ }
347
+
348
+ if (xhr && xhr.readyState < 4) {
349
+ xhr.onreadystatechange = noop;
350
+ xhr.abort();
351
+ }
352
+
353
+ xhr = new XMLHttpRequest();
354
+ xhr.open('GET', options.url, true);
355
+ xhr.setRequestHeader('X-PUSH', 'true');
356
+
357
+ xhr.onreadystatechange = function () {
358
+ if (options._timeout) {
359
+ clearTimeout(options._timeout);
360
+ }
361
+ if (xhr.readyState === 4) {
362
+ xhr.status === 200 ? success(xhr, options) : failure(options.url);
363
+ }
364
+ };
365
+
366
+ if (!PUSH.id) {
367
+ cacheReplace({
368
+ id : +new Date(),
369
+ url : window.location.href,
370
+ title : document.title,
371
+ timeout : options.timeout,
372
+ transition : null
373
+ });
374
+ }
375
+
376
+ if (options.timeout) {
377
+ options._timeout = setTimeout(function () { xhr.abort('timeout'); }, options.timeout);
378
+ }
379
+
380
+ xhr.send();
381
+
382
+ if (xhr.readyState && !options.ignorePush) {
383
+ cachePush();
384
+ }
385
+ };
386
+
387
+
388
+ // Main XHR handlers
389
+ // =================
390
+
391
+ var success = function (xhr, options) {
392
+ var key;
393
+ var barElement;
394
+ var data = parseXHR(xhr, options);
395
+
396
+ if (!data.contents) {
397
+ return locationReplace(options.url);
398
+ }
399
+
400
+ if (data.title) {
401
+ document.title = data.title;
402
+ }
403
+
404
+ if (options.transition) {
405
+ for (key in bars) {
406
+ if (bars.hasOwnProperty(key)) {
407
+ barElement = document.querySelector(bars[key]);
408
+ if (data[key]) {
409
+ swapContent(data[key], barElement);
410
+ } else if (barElement) {
411
+ barElement.parentNode.removeChild(barElement);
412
+ }
413
+ }
414
+ }
415
+ }
416
+
417
+ swapContent(data.contents, options.container, options.transition, function () {
418
+ cacheReplace({
419
+ id : options.id || +new Date(),
420
+ url : data.url,
421
+ title : data.title,
422
+ timeout : options.timeout,
423
+ transition : options.transition
424
+ }, options.id);
425
+ triggerStateChange();
426
+ });
427
+
428
+ if (!options.ignorePush && window._gaq) {
429
+ _gaq.push(['_trackPageview']); // google analytics
430
+ }
431
+ if (!options.hash) {
432
+ return;
433
+ }
434
+ };
435
+
436
+ var failure = function (url) {
437
+ throw new Error('Could not get: ' + url);
438
+ };
439
+
440
+
441
+ // PUSH helpers
442
+ // ============
443
+
444
+ var swapContent = function (swap, container, transition, complete) {
445
+ var enter;
446
+ var containerDirection;
447
+ var swapDirection;
448
+
449
+ if (!transition) {
450
+ if (container) {
451
+ container.innerHTML = swap.innerHTML;
452
+ } else if (swap.classList.contains('content')) {
453
+ document.body.appendChild(swap);
454
+ } else {
455
+ document.body.insertBefore(swap, document.querySelector('.content'));
456
+ }
457
+ } else {
458
+ enter = /in$/.test(transition);
459
+
460
+ if (transition === 'fade') {
461
+ container.classList.add('in');
462
+ container.classList.add('fade');
463
+ swap.classList.add('fade');
464
+ }
465
+
466
+ if (/slide/.test(transition)) {
467
+ swap.classList.add('sliding-in', enter ? 'right' : 'left');
468
+ swap.classList.add('sliding');
469
+ container.classList.add('sliding');
470
+ }
471
+
472
+ container.parentNode.insertBefore(swap, container);
473
+ }
474
+
475
+ if (!transition) {
476
+ complete && complete();
477
+ }
478
+
479
+ if (transition === 'fade') {
480
+ container.offsetWidth; // force reflow
481
+ container.classList.remove('in');
482
+ var fadeContainerEnd = function () {
483
+ container.removeEventListener('webkitTransitionEnd', fadeContainerEnd);
484
+ swap.classList.add('in');
485
+ swap.addEventListener('webkitTransitionEnd', fadeSwapEnd);
486
+ };
487
+ var fadeSwapEnd = function () {
488
+ swap.removeEventListener('webkitTransitionEnd', fadeSwapEnd);
489
+ container.parentNode.removeChild(container);
490
+ swap.classList.remove('fade');
491
+ swap.classList.remove('in');
492
+ complete && complete();
493
+ };
494
+ container.addEventListener('webkitTransitionEnd', fadeContainerEnd);
495
+
496
+ }
497
+
498
+ if (/slide/.test(transition)) {
499
+ var slideEnd = function () {
500
+ swap.removeEventListener('webkitTransitionEnd', slideEnd);
501
+ swap.classList.remove('sliding', 'sliding-in');
502
+ swap.classList.remove(swapDirection);
503
+ container.parentNode.removeChild(container);
504
+ complete && complete();
505
+ };
506
+
507
+ container.offsetWidth; // force reflow
508
+ swapDirection = enter ? 'right' : 'left';
509
+ containerDirection = enter ? 'left' : 'right';
510
+ container.classList.add(containerDirection);
511
+ swap.classList.remove(swapDirection);
512
+ swap.addEventListener('webkitTransitionEnd', slideEnd);
513
+ }
514
+ };
515
+
516
+ var triggerStateChange = function () {
517
+ var e = new CustomEvent('push', {
518
+ detail: { state: getCached(PUSH.id) },
519
+ bubbles: true,
520
+ cancelable: true
521
+ });
522
+
523
+ window.dispatchEvent(e);
524
+ };
525
+
526
+ var findTarget = function (target) {
527
+ var i, toggles = document.querySelectorAll('a');
528
+ for (; target && target !== document; target = target.parentNode) {
529
+ for (i = toggles.length; i--;) {
530
+ if (toggles[i] === target) {
531
+ return target;
532
+ }
533
+ }
534
+ }
535
+ };
536
+
537
+ var locationReplace = function (url) {
538
+ window.history.replaceState(null, '', '#');
539
+ window.location.replace(url);
540
+ };
541
+
542
+ var extendWithDom = function (obj, fragment, dom) {
543
+ var i;
544
+ var result = {};
545
+
546
+ for (i in obj) {
547
+ if (obj.hasOwnProperty(i)) {
548
+ result[i] = obj[i];
549
+ }
550
+ }
551
+
552
+ Object.keys(bars).forEach(function (key) {
553
+ var el = dom.querySelector(bars[key]);
554
+ if (el) {
555
+ el.parentNode.removeChild(el);
556
+ }
557
+ result[key] = el;
558
+ });
559
+
560
+ result.contents = dom.querySelector(fragment);
561
+
562
+ return result;
563
+ };
564
+
565
+ var parseXHR = function (xhr, options) {
566
+ var head;
567
+ var body;
568
+ var data = {};
569
+ var responseText = xhr.responseText;
570
+
571
+ data.url = options.url;
572
+
573
+ if (!responseText) {
574
+ return data;
575
+ }
576
+
577
+ if (/<html/i.test(responseText)) {
578
+ head = document.createElement('div');
579
+ body = document.createElement('div');
580
+ head.innerHTML = responseText.match(/<head[^>]*>([\s\S.]*)<\/head>/i)[0];
581
+ body.innerHTML = responseText.match(/<body[^>]*>([\s\S.]*)<\/body>/i)[0];
582
+ } else {
583
+ head = body = document.createElement('div');
584
+ head.innerHTML = responseText;
585
+ }
586
+
587
+ data.title = head.querySelector('title');
588
+ data.title = data.title && data.title.innerText.trim();
589
+
590
+ if (options.transition) {
591
+ data = extendWithDom(data, '.content', body);
592
+ } else {
593
+ data.contents = body;
594
+ }
595
+
596
+ return data;
597
+ };
598
+
599
+
600
+ // Attach PUSH event handlers
601
+ // ==========================
602
+
603
+ window.addEventListener('touchstart', function () { isScrolling = false; });
604
+ window.addEventListener('touchmove', function () { isScrolling = true; });
605
+ window.addEventListener('touchend', touchend);
606
+ window.addEventListener('click', function (e) { if (getTarget(e)) {e.preventDefault();} });
607
+ window.addEventListener('popstate', popstate);
608
+ window.PUSH = PUSH;
609
+
610
+ }());
611
+
612
+ /* ----------------------------------
613
+ * Segmented controls v2.0.1
614
+ * Licensed under The MIT License
615
+ * http://opensource.org/licenses/MIT
616
+ * ---------------------------------- */
617
+
618
+ !(function () {
619
+ 'use strict';
620
+
621
+ var getTarget = function (target) {
622
+ var i, segmentedControls = document.querySelectorAll('.segmented-control .control-item');
623
+ for (; target && target !== document; target = target.parentNode) {
624
+ for (i = segmentedControls.length; i--;) {
625
+ if (segmentedControls[i] === target) {
626
+ return target;
627
+ }
628
+ }
629
+ }
630
+ };
631
+
632
+ window.addEventListener('touchend', function (e) {
633
+ var activeTab;
634
+ var activeBodies;
635
+ var targetBody;
636
+ var targetTab = getTarget(e.target);
637
+ var className = 'active';
638
+ var classSelector = '.' + className;
639
+
640
+ if (!targetTab) {
641
+ return;
642
+ }
643
+
644
+ activeTab = targetTab.parentNode.querySelector(classSelector);
645
+
646
+ if (activeTab) {
647
+ activeTab.classList.remove(className);
648
+ }
649
+
650
+ targetTab.classList.add(className);
651
+
652
+ if (!targetTab.hash) {
653
+ return;
654
+ }
655
+
656
+ targetBody = document.querySelector(targetTab.hash);
657
+
658
+ if (!targetBody) {
659
+ return;
660
+ }
661
+
662
+ activeBodies = targetBody.parentNode.querySelectorAll(classSelector);
663
+
664
+ for (var i = 0; i < activeBodies.length; i++) {
665
+ activeBodies[i].classList.remove(className);
666
+ }
667
+
668
+ targetBody.classList.add(className);
669
+ });
670
+
671
+ window.addEventListener('click', function (e) { if (getTarget(e.target)) {e.preventDefault();} });
672
+ }());
673
+ /* ----------------------------------
674
+ * SLIDER v2.0.1
675
+ * Licensed under The MIT License
676
+ * Adapted from Brad Birdsall's swipe
677
+ * http://opensource.org/licenses/MIT
678
+ * ---------------------------------- */
679
+
680
+ !(function () {
681
+ 'use strict';
682
+
683
+ var pageX;
684
+ var pageY;
685
+ var slider;
686
+ var deltaX;
687
+ var deltaY;
688
+ var offsetX;
689
+ var lastSlide;
690
+ var startTime;
691
+ var resistance;
692
+ var sliderWidth;
693
+ var slideNumber;
694
+ var isScrolling;
695
+ var scrollableArea;
696
+
697
+ var getSlider = function (target) {
698
+ var i, sliders = document.querySelectorAll('.slider > .slide-group');
699
+ for (; target && target !== document; target = target.parentNode) {
700
+ for (i = sliders.length; i--;) {
701
+ if (sliders[i] === target) {
702
+ return target;
703
+ }
704
+ }
705
+ }
706
+ };
707
+
708
+ var getScroll = function () {
709
+ var translate3d = slider.style.webkitTransform.match(/translate3d\(([^,]*)/);
710
+ var ret = translate3d ? translate3d[1] : 0;
711
+ return parseInt(ret, 10);
712
+ };
713
+
714
+ var setSlideNumber = function (offset) {
715
+ var round = offset ? (deltaX < 0 ? 'ceil' : 'floor') : 'round';
716
+ slideNumber = Math[round](getScroll() / ( scrollableArea / slider.children.length) );
717
+ slideNumber += offset;
718
+ slideNumber = Math.min(slideNumber, 0);
719
+ slideNumber = Math.max(-(slider.children.length - 1), slideNumber);
720
+ };
721
+
722
+ var onTouchStart = function (e) {
723
+ slider = getSlider(e.target);
724
+
725
+ if (!slider) {
726
+ return;
727
+ }
728
+
729
+ var firstItem = slider.querySelector('.slide');
730
+
731
+ scrollableArea = firstItem.offsetWidth * slider.children.length;
732
+ isScrolling = undefined;
733
+ sliderWidth = slider.offsetWidth;
734
+ resistance = 1;
735
+ lastSlide = -(slider.children.length - 1);
736
+ startTime = +new Date();
737
+ pageX = e.touches[0].pageX;
738
+ pageY = e.touches[0].pageY;
739
+ deltaX = 0;
740
+ deltaY = 0;
741
+
742
+ setSlideNumber(0);
743
+
744
+ slider.style['-webkit-transition-duration'] = 0;
745
+ };
746
+
747
+ var onTouchMove = function (e) {
748
+ if (e.touches.length > 1 || !slider) {
749
+ return; // Exit if a pinch || no slider
750
+ }
751
+
752
+ deltaX = e.touches[0].pageX - pageX;
753
+ deltaY = e.touches[0].pageY - pageY;
754
+ pageX = e.touches[0].pageX;
755
+ pageY = e.touches[0].pageY;
756
+
757
+ if (typeof isScrolling === 'undefined') {
758
+ isScrolling = Math.abs(deltaY) > Math.abs(deltaX);
759
+ }
760
+
761
+ if (isScrolling) {
762
+ return;
763
+ }
764
+
765
+ offsetX = (deltaX / resistance) + getScroll();
766
+
767
+ e.preventDefault();
768
+
769
+ resistance = slideNumber === 0 && deltaX > 0 ? (pageX / sliderWidth) + 1.25 :
770
+ slideNumber === lastSlide && deltaX < 0 ? (Math.abs(pageX) / sliderWidth) + 1.25 : 1;
771
+
772
+ slider.style.webkitTransform = 'translate3d(' + offsetX + 'px,0,0)';
773
+ };
774
+
775
+ var onTouchEnd = function (e) {
776
+ if (!slider || isScrolling) {
777
+ return;
778
+ }
779
+
780
+ setSlideNumber(
781
+ (+new Date()) - startTime < 1000 && Math.abs(deltaX) > 15 ? (deltaX < 0 ? -1 : 1) : 0
782
+ );
783
+
784
+ offsetX = slideNumber * sliderWidth;
785
+
786
+ slider.style['-webkit-transition-duration'] = '.2s';
787
+ slider.style.webkitTransform = 'translate3d(' + offsetX + 'px,0,0)';
788
+
789
+ e = new CustomEvent('slide', {
790
+ detail: { slideNumber: Math.abs(slideNumber) },
791
+ bubbles: true,
792
+ cancelable: true
793
+ });
794
+
795
+ slider.parentNode.dispatchEvent(e);
796
+ };
797
+
798
+ window.addEventListener('touchstart', onTouchStart);
799
+ window.addEventListener('touchmove', onTouchMove);
800
+ window.addEventListener('touchend', onTouchEnd);
801
+
802
+ }());
803
+
804
+ /* ----------------------------------
805
+ * TOGGLE v2.0.1
806
+ * Licensed under The MIT License
807
+ * http://opensource.org/licenses/MIT
808
+ * ---------------------------------- */
809
+
810
+ !(function () {
811
+ 'use strict';
812
+
813
+ var start = {};
814
+ var touchMove = false;
815
+ var distanceX = false;
816
+ var toggle = false;
817
+
818
+ var findToggle = function (target) {
819
+ var i, toggles = document.querySelectorAll('.toggle');
820
+ for (; target && target !== document; target = target.parentNode) {
821
+ for (i = toggles.length; i--;) {
822
+ if (toggles[i] === target) {
823
+ return target;
824
+ }
825
+ }
826
+ }
827
+ };
828
+
829
+ window.addEventListener('touchstart', function (e) {
830
+ e = e.originalEvent || e;
831
+
832
+ toggle = findToggle(e.target);
833
+
834
+ if (!toggle) {
835
+ return;
836
+ }
837
+
838
+ var handle = toggle.querySelector('.toggle-handle');
839
+ var toggleWidth = toggle.clientWidth;
840
+ var handleWidth = handle.clientWidth;
841
+ var offset = toggle.classList.contains('active') ? (toggleWidth - handleWidth) : 0;
842
+
843
+ start = { pageX : e.touches[0].pageX - offset, pageY : e.touches[0].pageY };
844
+ touchMove = false;
845
+ });
846
+
847
+ window.addEventListener('touchmove', function (e) {
848
+ e = e.originalEvent || e;
849
+
850
+ if (e.touches.length > 1) {
851
+ return; // Exit if a pinch
852
+ }
853
+
854
+ if (!toggle) {
855
+ return;
856
+ }
857
+
858
+ var handle = toggle.querySelector('.toggle-handle');
859
+ var current = e.touches[0];
860
+ var toggleWidth = toggle.clientWidth;
861
+ var handleWidth = handle.clientWidth;
862
+ var offset = toggleWidth - handleWidth;
863
+
864
+ touchMove = true;
865
+ distanceX = current.pageX - start.pageX;
866
+
867
+ if (Math.abs(distanceX) < Math.abs(current.pageY - start.pageY)) {
868
+ return;
869
+ }
870
+
871
+ e.preventDefault();
872
+
873
+ if (distanceX < 0) {
874
+ return (handle.style.webkitTransform = 'translate3d(0,0,0)');
875
+ }
876
+ if (distanceX > offset) {
877
+ return (handle.style.webkitTransform = 'translate3d(' + offset + 'px,0,0)');
878
+ }
879
+
880
+ handle.style.webkitTransform = 'translate3d(' + distanceX + 'px,0,0)';
881
+
882
+ toggle.classList[(distanceX > (toggleWidth/2 - handleWidth/2)) ? 'add' : 'remove']('active');
883
+ });
884
+
885
+ window.addEventListener('touchend', function (e) {
886
+ if (!toggle) {
887
+ return;
888
+ }
889
+
890
+ var handle = toggle.querySelector('.toggle-handle');
891
+ var toggleWidth = toggle.clientWidth;
892
+ var handleWidth = handle.clientWidth;
893
+ var offset = (toggleWidth - handleWidth);
894
+ var slideOn = (!touchMove && !toggle.classList.contains('active')) || (touchMove && (distanceX > (toggleWidth/2 - handleWidth/2)));
895
+
896
+ if (slideOn) {
897
+ handle.style.webkitTransform = 'translate3d(' + offset + 'px,0,0)';
898
+ } else {
899
+ handle.style.webkitTransform = 'translate3d(0,0,0)';
900
+ }
901
+
902
+ toggle.classList[slideOn ? 'add' : 'remove']('active');
903
+
904
+ e = new CustomEvent('toggle', {
905
+ detail: { isActive: slideOn },
906
+ bubbles: true,
907
+ cancelable: true
908
+ });
909
+
910
+ toggle.dispatchEvent(e);
911
+
912
+ touchMove = false;
913
+ toggle = false;
914
+ });
915
+
916
+ }());