rytm-webflow 2.1.11 → 2.2.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.
package/README.md CHANGED
@@ -142,7 +142,9 @@ RytmWebflow.aswap.init({
142
142
  | ```animationTimeHide``` | ```800``` | Time (ms) for view's *hide* transition|
143
143
  | ```animationTimeShow``` | ```800``` | Time (ms) for view's *show* transition|
144
144
  | ```formsEnabled``` | ```true``` | Use *ASwap* on forms|
145
- | ```formsSelector``` | ```'form[method="get"]'``` | *ASwap* forms selector - as default uses forms with *GET* method only|
145
+ | ```formsSelector``` | ```'form'``` | *ASwap* forms selector|
146
+ | ```swipeEnabled``` | ```true``` | Use *ASwap* [swipe](#swipe)|
147
+ | ```swipeMinDistance``` | ```5``` | Minimum swipe move distance (px) for [swipe](#swipe) to fire|
146
148
  | ```historyEnabled``` | ```true``` | Use history push state |
147
149
  | ```historyFallback``` | ```true``` | Fallback if browser dosn't support history push state |
148
150
  | ```cacheOn``` | ```true``` | By default all requests are being cached. Set to ```false``` to turn cache off |
@@ -218,6 +220,17 @@ RytmWebflow.aswap.init(params, {
218
220
  },
219
221
  })
220
222
  ```
223
+ ## <a name="swipe">Swipe</a> ##
224
+ Add urls to `as-swipe-{direction}` data attributes, eg:
225
+ ```html
226
+ <div
227
+ data-as-swipe-left="/path/to-next"
228
+ data-as-swipe-right="/path/to-prev"
229
+ data-as-swipe-up="/path/to-back">
230
+ ...
231
+ </div>
232
+ ```
233
+
221
234
  ## <a name="webflowview">WebflowView</a> ##
222
235
  WebflowView is an universal ASwap View which can be used with the **Webflow syntax** - a minified way to describe an animation, it's duration (time), easing, delay or the trigger. Eg. `y:100,o:0` will animate an element from: `y:100px` and `opacity: 0` to it's current state. Go to [Webflow syntax](#webflowsyntax) for more.
223
236
  ### Basic usage example
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rytm-webflow",
3
- "version": "2.1.11",
3
+ "version": "2.2.0",
4
4
  "description": "rytm webflow pack - ASwap, ShowUp",
5
5
  "main": "scripts/index.js",
6
6
  "scripts": {
@@ -12,7 +12,9 @@ class ASwap {
12
12
  animationTimeHide: 800, // hide animation time
13
13
  animationTimeShow: 800, // show animation time
14
14
  formsEnabled: true, // use aswap on forms
15
- formsSelector: 'form[method="get"]', // aswap forms selector
15
+ formsSelector: 'form', // aswap forms selector
16
+ swipeEnabled: true, // use aswap `swipe`
17
+ swipeMinDistance: 5, // min swipe move distance
16
18
  historyEnabled: true, // use history push state
17
19
  historyFallback: true, // fallback of browser dosn't support history push state
18
20
  cacheOn: true, // use Aswap Cache?
@@ -88,7 +90,22 @@ class ASwap {
88
90
  this.dispatcher.openURL(url, noHistory, useCache);
89
91
  }
90
92
  }
91
-
93
+ /**
94
+ * clear cache
95
+ */
96
+ clearCache(url = null) {
97
+ if (this.dispatcher) {
98
+ this.dispatcher.clearCache(url);
99
+ }
100
+ }
101
+ /**
102
+ * submit form
103
+ */
104
+ formSubmit(form) {
105
+ if (this.dispatcher) {
106
+ this.dispatcher.formSubmit(form);
107
+ }
108
+ }
92
109
  onRequestUrl(e) {
93
110
  document.documentElement.classList.add('as-in-progress')
94
111
  this.getActiveControlles().forEach( (c, index)=> {
@@ -58,6 +58,22 @@ class ASwapDispatcher extends EventDispatcher {
58
58
  });
59
59
  return result;
60
60
  }
61
+ clearCache(url = null) {
62
+ if (url) {
63
+ this.clearCacheByUrl(url);
64
+ } else {
65
+ this.ajaxStore = [];
66
+ }
67
+ }
68
+ clearCacheByUrl(url) {
69
+ let newStore = [];
70
+ this.ajaxStore.forEach( (r, index)=> {
71
+ if (r.url !== url) {
72
+ newStore.push(r);
73
+ }
74
+ });
75
+ this.ajaxStore = newStore;
76
+ }
61
77
  /**
62
78
  * parse the result and return content between a tag, eg. <body></body>
63
79
  * @param result {String} the ajax request result
@@ -281,6 +297,22 @@ class ASwapDispatcher extends EventDispatcher {
281
297
  xhr.send();
282
298
 
283
299
  }
300
+ /**
301
+ * Form submit
302
+ */
303
+ formSubmit(form) {
304
+ const useCache = !form.classList.contains(this.noCacheClassName);
305
+ const url = form.getAttribute("action");
306
+ if (url.indexOf('://') < 0) {
307
+ this.currentTrigger = form
308
+ const method = form.getAttribute('method') ? form.getAttribute('method') : 'get'
309
+ const formData = new FormData(form);
310
+ this.submit(url, formData, method, false, useCache);
311
+ // const dataStr = new URLSearchParams(formData).toString();
312
+ // const requestUrl = method == 'get' ? (url + '?' + dataStr) : url;
313
+ // this.submit(requestUrl, formData, method, false, useCache);
314
+ }
315
+ }
284
316
  /**
285
317
  *
286
318
  * @param {string} url
@@ -289,7 +321,7 @@ class ASwapDispatcher extends EventDispatcher {
289
321
  * @param {boolean} noHistory
290
322
  * @param {boolean} useCache
291
323
  */
292
- submit(url, data, method, noHistory = false, useCache = true) {
324
+ submit(url, formData, method, noHistory = false, useCache = true) {
293
325
  // dispatch event
294
326
  this.dispatch(Events.NAV_REQUEST_URL);
295
327
  this.prevUrl = this.currentUrl;
@@ -297,11 +329,22 @@ class ASwapDispatcher extends EventDispatcher {
297
329
  if (!noHistory) {
298
330
  this.pushState(url);
299
331
  }
300
- let result = this.getStoredResult(url);
301
- if (result) {
302
- this.handleResult(result);
303
- } else {
304
- this.loadURL(url, data, method, useCache);
332
+ switch (method) {
333
+ case 'post':
334
+ // POST
335
+ this.loadURL(url, formData, method, false);
336
+ break;
337
+ default:
338
+ // GET
339
+ const dataStr = new URLSearchParams(formData).toString();
340
+ url = method == 'get' ? (url + '?' + dataStr) : url;
341
+ let result = useCache ? this.getStoredResult(url) : null;
342
+ if (result) {
343
+ this.handleResult(result);
344
+ } else {
345
+ this.loadURL(url, formData, method, useCache);
346
+ }
347
+ break;
305
348
  }
306
349
  }
307
350
  /**
@@ -330,7 +373,6 @@ class ASwapDispatcher extends EventDispatcher {
330
373
  // dispatch event
331
374
  this.dispatch(Events.NAV_REQUEST_LOAD);
332
375
  this.trace("ASwap load: ", url);
333
-
334
376
  let xhr = new XMLHttpRequest();
335
377
  xhr.onreadystatechange = () => {
336
378
  if (xhr.readyState === 4) {
@@ -427,22 +469,56 @@ class ASwapDispatcher extends EventDispatcher {
427
469
  }
428
470
  }
429
471
  }
472
+ // SUBMIT
430
473
  onDocumentSubmit(e) {
431
474
  if (e.target.tagName == 'FORM') {
432
- const f = e.target
433
- if (this.isFormElementValid(f)) {
475
+ if (this.isFormElementValid(e.target)) {
434
476
  e.preventDefault();
435
- const useCache = !f.classList.contains(this.noCacheClassName);
436
- const url = f.getAttribute("action");
437
- if (url.indexOf('://') < 0) {
438
- e.preventDefault()
439
- this.currentTrigger = f
440
- const method = f.getAttribute('method') ? f.getAttribute('method') : 'get'
441
- const dataStr = new URLSearchParams(new FormData(f)).toString()
442
- const requestUrl = method == 'get' ? (url + '?' + dataStr) : url
443
- this.submit(requestUrl, dataStr, method, false, useCache)
477
+ this.formSubmit(e.target);
478
+ }
479
+ }
480
+ }
481
+ // Swipe touch start event
482
+ handleTouchStart = (e) => {
483
+ const firstTouch = e.touches[0];
484
+ this.xDown = firstTouch.clientX;
485
+ this.yDown = firstTouch.clientY;
486
+ }
487
+ // Swipe touch move event
488
+ handleTouchMove = (e) => {
489
+ if ( !this.xDown || !this.yDown ) {
490
+ return;
491
+ }
492
+ const xUp = e.touches[0].clientX;
493
+ const yUp = e.touches[0].clientY;
494
+ const xDiff = this.xDown - xUp;
495
+ const yDiff = this.yDown - yUp;
496
+ if ( Math.abs( xDiff ) > Math.abs( yDiff ) ) {
497
+ if (Math.abs(xDiff) > this.swipeMinDistance) {
498
+ if ( xDiff > 0 ) {
499
+ this.handleSwipe(e, 'left');
500
+ } else {
501
+ this.handleSwipe(e, 'right');
444
502
  }
445
-
503
+ }
504
+ } else if (Math.abs(yDiff) > this.swipeMinDistance) {
505
+ if ( yDiff > 0 ) {
506
+ this.handleSwipe(e, 'up');
507
+ } else {
508
+ this.handleSwipe(e, 'down');
509
+ }
510
+ }
511
+ /* reset values */
512
+ this.xDown = null;
513
+ this.yDown = null;
514
+ }
515
+ // handle SWIPE direction
516
+ handleSwipe = (e, direction) => {
517
+ const d = e.target.closest('[data-as-swipe-' + direction + ']')
518
+ if (d) {
519
+ const path = d.getAttribute('data-as-swipe-' + direction);
520
+ if (path) {
521
+ this.openURL(path);
446
522
  }
447
523
  }
448
524
  }
@@ -460,6 +536,11 @@ class ASwapDispatcher extends EventDispatcher {
460
536
  if (this.formsEnabled) {
461
537
  document.addEventListener('submit', this.onDocumentSubmit.bind(this), false)
462
538
  }
539
+ // swipe?
540
+ if (this.swipeEnabled) {
541
+ document.addEventListener('touchstart', this.handleTouchStart, false);
542
+ document.addEventListener('touchmove', this.handleTouchMove, false);
543
+ }
463
544
  // browser back button
464
545
  window.addEventListener('popstate', this.onHistoryBack.bind(this), false)
465
546
  }