Created
August 19, 2020 07:15
-
-
Save th3hunt/68b14010f92e5cbb117b39249a3ed6d6 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Marionette from 'backbone.marionette'; | |
import Hammer from 'hammerjs'; | |
import $ from 'jquery'; | |
import _ from 'underscore'; | |
export default Marionette.Behavior.extend({ | |
defaults: { | |
threshold: 30 | |
}, | |
ui() { | |
return { | |
content: this.options.content || 'item__content', | |
actions: this.options.actions || 'item__actions' | |
}; | |
}, | |
events: { | |
'tap @ui.content': 'onTap' | |
}, | |
initialize() { | |
_.bindAll(this, 'onPan', 'onPanEnd'); | |
this.swipeEnabled = this.view.getOption('swipeEnabled'); | |
this.view.swipeOpen = this.swipeOpen.bind(this); | |
this.view.swipeClose = this.swipeClose.bind(this); | |
}, | |
isEnabled() { | |
return _.result(this, 'swipeEnabled'); | |
}, | |
onRender() { | |
this.contentEl = this.ui.content[0]; | |
}, | |
onAttach() { | |
this.hammer = new Hammer.Manager(this.contentEl, { | |
touchAction: 'auto', | |
inputClass: Hammer.SUPPORT_POINTER_EVENTS ? Hammer.PointerEventInput : Hammer.TouchInput | |
}); | |
this.hammer.add(new Hammer.Pan({direction: Hammer.DIRECTION_HORIZONTAL, threshold: this.getOption('threshold')})); | |
this.hammer.on('panleft panright', this.onPan); | |
this.hammer.on('panend', this.onPanEnd); | |
}, | |
onDestroy() { | |
this.hammer && this.hammer.off('panleft panright panend'); | |
delete this.hammer; | |
}, | |
onTap(e) { | |
if (e && (this.isOpen || this.isStarted)) { | |
e.stopPropagation(); | |
} | |
_.delay(this.swipeClose.bind(this), 200); | |
}, | |
swipeOpen() { | |
this.el.classList.add('swipe-animate'); | |
this.transform(this.snapPoint); | |
this.isOpen = true; | |
this.isStarted = false; | |
this.view.isSwipedOpen = true; | |
this.view.triggerMethod('swipe:open'); | |
}, | |
swipeClose() { | |
this.el.classList.add('swipe-animate'); | |
this.transform(null); | |
this.isOpen = false; | |
this.isStarted = false; | |
this.view.isSwipedOpen = false; | |
this.view.triggerMethod('swipe:close'); | |
}, | |
slide(distance) { | |
let snapOffset; | |
let transform; | |
snapOffset = distance - this.snapPoint; | |
if (snapOffset > 0) { | |
this.readyToSnap = true; | |
// add resistance as we move beyond the snap point | |
transform = this.snapPoint + (snapOffset * this.snapPoint / distance); | |
} else { | |
this.resetOnEnd = false; | |
this.readyToSnap = false; | |
transform = distance; | |
} | |
transform = Math.min(this.maxDistance, Math.max(transform, 0)); | |
this.el.classList.remove('swipe-animate'); | |
this.view.triggerMethod('swipe:slide'); | |
this.transform(transform); | |
}, | |
start(e) { | |
const threshold = this.getOption('threshold'); | |
if (e && _.isNumber(threshold)) { | |
if (e.direction === Hammer.DIRECTION_LEFT) { | |
this.distanceFix = -threshold; | |
} else { | |
this.distanceFix = +threshold; | |
} | |
} else { | |
this.distanceFix = 0; | |
} | |
this.snapPoint = this.calculateSnapPoint(); | |
this.maxDistance = this.getOption('maxDistance') || this.el.offsetWidth / 1.5; | |
this.initialDistance = this.isOpen ? this.snapPoint : 0; | |
this.readyToSnap = false; | |
this.resetOnEnd = this.isOpen; | |
this.isStarted = true; | |
this.view.triggerMethod('swipe:start'); | |
}, | |
onPan(e) { | |
if (!this.isEnabled()) { | |
return; | |
} | |
if (!this.isStarted) { | |
// start only if the movement has a direction < 45 degrees | |
if (Math.abs(e.deltaY) > 0 && (Math.abs(e.deltaX / e.deltaY)) < 1) { | |
return; | |
} | |
this.start(e); | |
} | |
const distance = this.initialDistance - e.deltaX + this.distanceFix; | |
if (distance < 0 || distance > this.maxDistance) { | |
return; | |
} | |
e.srcEvent.stopPropagation(); | |
e.srcEvent.preventDefault(); | |
this.slide(distance); | |
}, | |
onPanEnd(e) { | |
e.srcEvent.preventDefault(); | |
if (this.readyToSnap && !this.resetOnEnd) { | |
this.swipeOpen(); | |
} else { | |
this.swipeClose(); | |
} | |
this.view.triggerMethod('swipe:end'); | |
}, | |
calculateSnapPoint() { | |
return this.ui.actions.width() - this.ui.actions.find('>div:visible').last().offset().left; | |
}, | |
transform(pixels) { | |
if (pixels === null) { | |
this.contentEl.style[$.support.transform] = ''; | |
} else { | |
this.contentEl.style[$.support.transform] = 'translateX(-' + pixels + 'px)'; | |
} | |
} | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment