rytm-webflow 2.1.12 → 2.2.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.
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.12",
3
+ "version": "2.2.1",
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?
@@ -96,6 +98,14 @@ class ASwap {
96
98
  this.dispatcher.clearCache(url);
97
99
  }
98
100
  }
101
+ /**
102
+ * submit form
103
+ */
104
+ formSubmit(form) {
105
+ if (this.dispatcher) {
106
+ this.dispatcher.formSubmit(form);
107
+ }
108
+ }
99
109
  onRequestUrl(e) {
100
110
  document.documentElement.classList.add('as-in-progress')
101
111
  this.getActiveControlles().forEach( (c, index)=> {
@@ -297,6 +297,25 @@ class ASwapDispatcher extends EventDispatcher {
297
297
  xhr.send();
298
298
 
299
299
  }
300
+ /**
301
+ * Form submit
302
+ */
303
+ formSubmit(form) {
304
+ const useCache = !form.classList.contains(this.noCacheClassName);
305
+ let url = form.getAttribute("action");
306
+ if (url.indexOf('://') < 0) {
307
+ this.currentTrigger = form
308
+ const method = form.getAttribute('method') ? form.getAttribute('method').toLowerCase() : 'get'
309
+ const formData = new FormData(form);
310
+ if (method == 'get') {
311
+ // for GET add data string to URL
312
+ const dataStr = new URLSearchParams(formData).toString();
313
+ const dataSep = url.indexOf('?') > -1 ? '&' : '?';
314
+ url = dataStr && method == 'get' ? (url + dataSep + dataStr) : url;
315
+ }
316
+ this.submit(url, formData, method, false, useCache);
317
+ }
318
+ }
300
319
  /**
301
320
  *
302
321
  * @param {string} url
@@ -305,7 +324,7 @@ class ASwapDispatcher extends EventDispatcher {
305
324
  * @param {boolean} noHistory
306
325
  * @param {boolean} useCache
307
326
  */
308
- submit(url, data, method, noHistory = false, useCache = true) {
327
+ submit(url, formData, method, noHistory = false, useCache = true) {
309
328
  // dispatch event
310
329
  this.dispatch(Events.NAV_REQUEST_URL);
311
330
  this.prevUrl = this.currentUrl;
@@ -313,11 +332,20 @@ class ASwapDispatcher extends EventDispatcher {
313
332
  if (!noHistory) {
314
333
  this.pushState(url);
315
334
  }
316
- let result = this.getStoredResult(url);
317
- if (result) {
318
- this.handleResult(result);
319
- } else {
320
- this.loadURL(url, data, method, useCache);
335
+ switch (method) {
336
+ case 'post':
337
+ // POST
338
+ this.loadURL(url, formData, method, false);
339
+ break;
340
+ default:
341
+ // GET / PUT / PATCH / DELETE
342
+ let result = useCache ? this.getStoredResult(url) : null;
343
+ if (result) {
344
+ this.handleResult(result);
345
+ } else {
346
+ this.loadURL(url, formData, method, useCache);
347
+ }
348
+ break;
321
349
  }
322
350
  }
323
351
  /**
@@ -346,7 +374,6 @@ class ASwapDispatcher extends EventDispatcher {
346
374
  // dispatch event
347
375
  this.dispatch(Events.NAV_REQUEST_LOAD);
348
376
  this.trace("ASwap load: ", url);
349
-
350
377
  let xhr = new XMLHttpRequest();
351
378
  xhr.onreadystatechange = () => {
352
379
  if (xhr.readyState === 4) {
@@ -443,22 +470,56 @@ class ASwapDispatcher extends EventDispatcher {
443
470
  }
444
471
  }
445
472
  }
473
+ // SUBMIT
446
474
  onDocumentSubmit(e) {
447
475
  if (e.target.tagName == 'FORM') {
448
- const f = e.target
449
- if (this.isFormElementValid(f)) {
476
+ if (this.isFormElementValid(e.target)) {
450
477
  e.preventDefault();
451
- const useCache = !f.classList.contains(this.noCacheClassName);
452
- const url = f.getAttribute("action");
453
- if (url.indexOf('://') < 0) {
454
- e.preventDefault()
455
- this.currentTrigger = f
456
- const method = f.getAttribute('method') ? f.getAttribute('method') : 'get'
457
- const dataStr = new URLSearchParams(new FormData(f)).toString()
458
- const requestUrl = method == 'get' ? (url + '?' + dataStr) : url
459
- this.submit(requestUrl, dataStr, method, false, useCache)
478
+ this.formSubmit(e.target);
479
+ }
480
+ }
481
+ }
482
+ // Swipe touch start event
483
+ handleTouchStart = (e) => {
484
+ const firstTouch = e.touches[0];
485
+ this.xDown = firstTouch.clientX;
486
+ this.yDown = firstTouch.clientY;
487
+ }
488
+ // Swipe touch move event
489
+ handleTouchMove = (e) => {
490
+ if ( !this.xDown || !this.yDown ) {
491
+ return;
492
+ }
493
+ const xUp = e.touches[0].clientX;
494
+ const yUp = e.touches[0].clientY;
495
+ const xDiff = this.xDown - xUp;
496
+ const yDiff = this.yDown - yUp;
497
+ if ( Math.abs( xDiff ) > Math.abs( yDiff ) ) {
498
+ if (Math.abs(xDiff) > this.swipeMinDistance) {
499
+ if ( xDiff > 0 ) {
500
+ this.handleSwipe(e, 'left');
501
+ } else {
502
+ this.handleSwipe(e, 'right');
460
503
  }
461
-
504
+ }
505
+ } else if (Math.abs(yDiff) > this.swipeMinDistance) {
506
+ if ( yDiff > 0 ) {
507
+ this.handleSwipe(e, 'up');
508
+ } else {
509
+ this.handleSwipe(e, 'down');
510
+ }
511
+ }
512
+ /* reset values */
513
+ this.xDown = null;
514
+ this.yDown = null;
515
+ }
516
+ // handle SWIPE direction
517
+ handleSwipe = (e, direction) => {
518
+ const d = e.target.closest('[data-as-swipe-' + direction + ']')
519
+ if (d) {
520
+ const path = d.getAttribute('data-as-swipe-' + direction);
521
+ if (path) {
522
+ this.openURL(path);
462
523
  }
463
524
  }
464
525
  }
@@ -476,6 +537,11 @@ class ASwapDispatcher extends EventDispatcher {
476
537
  if (this.formsEnabled) {
477
538
  document.addEventListener('submit', this.onDocumentSubmit.bind(this), false)
478
539
  }
540
+ // swipe?
541
+ if (this.swipeEnabled) {
542
+ document.addEventListener('touchstart', this.handleTouchStart, false);
543
+ document.addEventListener('touchmove', this.handleTouchMove, false);
544
+ }
479
545
  // browser back button
480
546
  window.addEventListener('popstate', this.onHistoryBack.bind(this), false)
481
547
  }