Skip to content

Commit 771d51e

Browse files
committed
kick hammer out
1 parent 2ea3bfe commit 771d51e

File tree

3 files changed

+214
-56
lines changed

3 files changed

+214
-56
lines changed

package.json

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,6 @@
3030
"type": "git",
3131
"url": "https://github.com/eCollect/vue-swipe-actions"
3232
},
33-
"dependencies": {
34-
"hammerjs": "^2.0.8"
35-
},
3633
"main": "./dist/vue-swipe-actions.common.js",
3734
"devDependencies": {
3835
"@vue/cli-plugin-babel": "^3.1.1",

src/components/SwipeOut.vue

Lines changed: 26 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
<template>
22
<div class="swipeout"
3+
v-touch-pan.prevent.horizontal="_onPan"
34
:class="{'swipeout--transitioning' : isTransitioning, 'swipeout--disabled': disabled}">
45
<div v-if="hasLeft" class="swipeout-left" ref="left">
56
<slot name="left" :close="closeActions"></slot>
@@ -13,8 +14,7 @@
1314
</div>
1415
</template>
1516
<script>
16-
/* eslint-disable */
17-
import Hammer from 'hammerjs';
17+
import touchPan from '../directives/touch-horizontal-pan';
1818
1919
function reduceSwipe(x) {
2020
return Math.pow(x, 0.65); // eslint-disable-line
@@ -29,15 +29,16 @@
2929
3030
export default {
3131
name: 'swipe-item',
32+
directives: {
33+
touchPan,
34+
},
3235
data() {
3336
return {
3437
hammer: null,
3538
startLeft: 0,
3639
isActive: false,
3740
isTransitioning: false,
3841
direction: null,
39-
// hasLeft: true, //'left' in this.$slots || 'left' in this.$scopedSlots,
40-
// hasRight: 'right' in this.$slots,
4142
leftOpen: false,
4243
rightOpen: false,
4344
leftActionsWidth: 0,
@@ -68,7 +69,6 @@
6869
mounted() {
6970
if (!this.hasLeft && !this.hasRight)
7071
return;
71-
this._createHammer();
7272
},
7373
beforeDestroy() {
7474
if (this.hammer)
@@ -103,65 +103,43 @@
103103
this._animateSlide(-this.rightActionsWidth, oldLeft);
104104
},
105105
// private
106-
_createHammer() {
107-
this.hammer = new Hammer.Manager(this.$el, {
108-
touchAction: 'pan-y',
109-
cssProps: {
110-
userSelect: '',
111-
},
112-
});
113-
114-
const doubelTab = new Hammer.Tap({ event: 'doubletap', taps: 2 });
115-
this.hammer.add(doubelTab);
116-
117-
const singleTap = new Hammer.Tap({ event: 'singletap' });
118-
this.hammer.add(singleTap);
119-
120-
doubelTab.recognizeWith(singleTap);
121-
singleTap.requireFailure(doubelTab);
122-
123-
const pan = new Hammer.Pan({ event: 'pan' });
124-
this.hammer.add(pan);
125-
126-
this.hammer.on('singletap', e => this._singleTap(e));
127-
this.hammer.on('doubletap', e => this._doubleTap(e));
128-
129-
this.hammer.get('pan').set({ threshold: 0 });
130-
this.hammer.on('panstart', this._startListener);
131-
this.hammer.on('panleft panright', this._swipeListener);
132-
this.hammer.on('panend', this._stopListener);
133-
},
134106
_distanceSwiped() {
135107
const contentRect = this.$refs.content.getBoundingClientRect();
136108
const elementRect = this.$el.getBoundingClientRect();
137109
return contentRect.left - elementRect.left - this.$el.clientLeft;
138110
},
139-
_startListener(event) {
111+
_onPan(pan) {
140112
if (this.disabled)
141113
return null;
142114
115+
if (pan.isFirst)
116+
return this._startListener(pan);
117+
118+
if (!this.isActive)
119+
return null;
120+
121+
if (pan.isFinal)
122+
return this._stopListener(pan);
123+
124+
return this._swipeListener(pan);
125+
},
126+
_startListener({ offset, direction }) {
143127
this.isTransitioning = false;
144-
if (event.deltaY >= -5 && event.deltaY <= 5) {
128+
if (offset.y >= -5 && offset.y <= 5) {
145129
this.leftActionsWidth = this.$refs.left ? this.$refs.left.clientWidth : 0;
146130
this.rightActionsWidth = this.$refs.right ? this.$refs.right.clientWidth : 0;
147131
148132
this.startLeft = this._distanceSwiped();
149133
this.isActive = true;
150134
this.$emit('active', true);
151135
152-
if (event.deltaX > 0)
153-
this.direction = 'ltr';
154-
if (event.deltaX < 0)
155-
this.direction = 'rtl';
136+
this.direction = direction;
156137
}
157138
158139
this.closeActions();
159140
},
160-
_swipeListener(event) {
161-
if (!this.isActive || this.disabled)
162-
return null;
163-
164-
const newX = this.startLeft + event.deltaX;
141+
_swipeListener({ offset }) {
142+
const newX = this.startLeft + offset.x;
165143
166144
// attempting to reveal the right actions after revealing the left actions
167145
if (this.startLeft === 0 && this.direction === 'ltr' && newX < 0)
@@ -189,23 +167,20 @@
189167
190168
return this._animateSlide(newX);
191169
},
192-
_stopListener(event) {
193-
if (!this.isActive || this.disabled)
194-
return null;
195-
170+
_stopListener({ offset }) {
196171
const oldLeft = this.$refs.content.getBoundingClientRect().left;
197172
this.isActive = false;
198173
this.$emit('active', false);
199174
200175
// close left actions
201-
if (this.startLeft > 0 && event.deltaX <= -this.threshold)
176+
if (this.startLeft > 0 && offset.x <= -this.threshold)
202177
return this.closeActions(); // _animateSlide(0, oldLeft);
203178
204179
// close right actions
205-
if (this.startLeft < 0 && event.deltaX >= this.threshold)
180+
if (this.startLeft < 0 && offset.x >= this.threshold)
206181
return this.closeActions(); // this._animateSlide(0, oldLeft);
207182
208-
const currentLeft = this.startLeft + event.deltaX;
183+
const currentLeft = this.startLeft + offset.x;
209184
210185
// reveal left actions
211186
if (this.startLeft === 0 && this.direction === 'ltr' && currentLeft >= this.threshold)
@@ -256,7 +231,6 @@
256231
child.style.transform = translateX(deltaX - (child.offsetLeft * progress));
257232
}
258233
},
259-
260234
_animateSlide(to, from) {
261235
if (from) {
262236
if ((to - from) === 0)
@@ -292,7 +266,6 @@
292266
.swipeout {
293267
position: relative;
294268
overflow: hidden;
295-
user-select: none;
296269
display: flex;
297270
}
298271
Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
// taken from https://github.com/quasarframework/quasar/blob/v1-work/src/utils/event.js
2+
3+
const listenOpts = {};
4+
5+
Object.defineProperty(listenOpts, "passive", {
6+
configurable: true,
7+
get() {
8+
let passive;
9+
10+
try {
11+
var opts = Object.defineProperty({}, "passive", {
12+
get() {
13+
passive = { passive: true };
14+
}
15+
});
16+
window.addEventListener("qtest", null, opts);
17+
window.removeEventListener("qtest", null, opts);
18+
} catch (e) {
19+
// do nothing
20+
}
21+
22+
listenOpts.passive = passive;
23+
return passive;
24+
},
25+
set(val) {
26+
Object.defineProperty(this, "passive", {
27+
value: val
28+
});
29+
}
30+
});
31+
32+
function position(e) {
33+
if (e.touches && e.touches[0]) {
34+
e = e.touches[0];
35+
} else if (e.changedTouches && e.changedTouches[0]) {
36+
e = e.changedTouches[0];
37+
}
38+
39+
return {
40+
top: e.clientY,
41+
left: e.clientX
42+
};
43+
}
44+
45+
const leftClick = e => e.button === 0;
46+
47+
function processChanges(evt, ctx, isFinal) {
48+
const pos = position(evt);
49+
const distX = pos.left - ctx.event.x;
50+
const distY = pos.top - ctx.event.y;
51+
const direction = distX < 0 ? "rtl" : "ltr";
52+
53+
return {
54+
evt,
55+
direction,
56+
isFirst: ctx.event.isFirst,
57+
isFinal,
58+
offset: {
59+
x: distX,
60+
y: distY
61+
},
62+
};
63+
}
64+
65+
const shouldTrigger = changes => Math.abs(changes.offset.x) > 0;
66+
67+
export default {
68+
name: "touch-pan",
69+
70+
bind(el, binding) {
71+
const mouse = binding.modifiers.noMouse !== true,
72+
stopPropagation = binding.modifiers.stop,
73+
preventDefault = binding.modifiers.prevent,
74+
evtOpts =
75+
preventDefault || binding.modifiers.mightPrevent
76+
? null
77+
: listenOpts.passive;
78+
79+
let ctx = {
80+
handler: binding.value,
81+
mouseStart(evt) {
82+
if (leftClick(evt)) {
83+
document.addEventListener("mousemove", ctx.move, evtOpts);
84+
document.addEventListener("mouseup", ctx.mouseEnd, evtOpts);
85+
ctx.start(evt);
86+
}
87+
},
88+
89+
mouseEnd(evt) {
90+
document.removeEventListener("mousemove", ctx.move, evtOpts);
91+
document.removeEventListener("mouseup", ctx.mouseEnd, evtOpts);
92+
ctx.end(evt);
93+
},
94+
95+
start(evt) {
96+
const pos = position(evt);
97+
98+
ctx.event = {
99+
x: pos.left,
100+
y: pos.top,
101+
time: new Date().getTime(),
102+
detected: false,
103+
abort: false,
104+
isFirst: true,
105+
};
106+
},
107+
108+
move(evt) {
109+
if (ctx.event.abort) {
110+
return;
111+
}
112+
113+
if (ctx.event.detected) {
114+
stopPropagation && evt.stopPropagation();
115+
preventDefault && evt.preventDefault();
116+
117+
const changes = processChanges(evt, ctx, false);
118+
if (shouldTrigger(changes)) {
119+
ctx.handler(changes);
120+
ctx.event.isFirst = false;
121+
}
122+
123+
return;
124+
}
125+
126+
const pos = position(evt),
127+
distX = Math.abs(pos.left - ctx.event.x),
128+
distY = Math.abs(pos.top - ctx.event.y);
129+
130+
if (distX === distY) {
131+
return;
132+
}
133+
134+
ctx.event.detected = true;
135+
ctx.event.abort = distX < distY;
136+
137+
ctx.move(evt);
138+
},
139+
140+
end(evt) {
141+
el.classList.remove("q-touch");
142+
if (ctx.event.abort || !ctx.event.detected || ctx.event.isFirst) {
143+
return;
144+
}
145+
146+
stopPropagation && evt.stopPropagation();
147+
preventDefault && evt.preventDefault();
148+
ctx.handler(processChanges(evt, ctx, true));
149+
}
150+
};
151+
152+
if (el.__qtouchpan) {
153+
el.__qtouchpan_old = el.__qtouchpan;
154+
}
155+
156+
el.__qtouchpan = ctx;
157+
158+
if (mouse) {
159+
el.addEventListener("mousedown", ctx.mouseStart, evtOpts);
160+
}
161+
el.addEventListener("touchstart", ctx.start, evtOpts);
162+
el.addEventListener("touchmove", ctx.move, evtOpts);
163+
el.addEventListener("touchend", ctx.end, evtOpts);
164+
},
165+
166+
update(el, { oldValue, value }) {
167+
const ctx = el.__qtouchpan;
168+
169+
if (oldValue !== value) {
170+
ctx.handler = value;
171+
}
172+
},
173+
174+
unbind(el, binding) {
175+
let ctx = el.__qtouchpan_old || el.__qtouchpan;
176+
if (ctx !== void 0) {
177+
const evtOpts = binding.modifiers.prevent ? null : listenOpts.passive;
178+
179+
el.removeEventListener("mousedown", ctx.mouseStart, evtOpts);
180+
181+
el.removeEventListener("touchstart", ctx.start, evtOpts);
182+
el.removeEventListener("touchmove", ctx.move, evtOpts);
183+
el.removeEventListener("touchend", ctx.end, evtOpts);
184+
185+
delete el[el.__qtouchpan_old ? "__qtouchpan_old" : "__qtouchpan"];
186+
}
187+
}
188+
};

0 commit comments

Comments
 (0)