Skip to content

Commit

Permalink
Rewrite the main APIs and add extra class support. Release v0.2.0
Browse files Browse the repository at this point in the history
  • Loading branch information
jerrybendy committed Apr 14, 2017
1 parent 351bb73 commit a5727cf
Show file tree
Hide file tree
Showing 3 changed files with 141 additions and 60 deletions.
104 changes: 82 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# vue-touch-events
# vue-touch-events [![](https://img.shields.io/npm/v/vue2-touch-events.svg)](https://www.npmjs.com/package/vue2-touch-events)
Enable tap / swipe events for VueJS 2.x

> Note: This is for **Vue 2.x** only.
## Install

To install with npm or yarn, use
Expand All @@ -22,49 +24,66 @@ import Vue2TouchEvents from 'vue2-touch-events'
Vue.use(Vue2TouchEvents)
```

In your `.vue` file:

```html
<!-- bind a tap event -->
<span v-touch:tap="touchHandler">Tap Me</span>

<!-- tap is the default event, you can omit it -->
<span v-touch="touchHandler">Tap Me</span>

<!-- bind the swipe event, no matter direction -->
<span v-touch:swipe="swipeHandler">Swipe Here</span>

<!-- only when swipe left can trigger the callback -->
<span v-touch:swpie.left="swipeHandler">Swipe Here</span>
```


## APIs

### Global config (optional)

```js
Vue.use(Vue2TouchEvents, {
disableClick: false,
touchClass: '',
tapTolerance: 10,
swipeTolerance: 30,
})
```

* `disableClick` default `false`. Use touch event only, will not trigger click event.
Set to `true` can resolve some touch pass-through issue.

* `disableClick` default `false`. Use touch event only, will not trigger click event.

You should keep this value default if you use your website on both mobile and PC.

If your website use on mobile only, it's a good choice to set this value `true` to get a better user experience, and it can resolve some touch pass-through issue.

* `touchClass` default: `''`. Add an extra CSS class when touch start, and remove it when touch end.

If `disableClick` is `false`, it will bind `mouseenter` and `mouseleave` event on your components too. So you can use it instead of `:hover` and `:active`.

This is a global config, and you can use `v-touch-class` directive to overwrite this setting in a single component.

* `tapTolerance` default `10`. The tolerance to ensure whether the tap event effective or not.
* `swipeTolerance` default `30`. The tolerance to ensure whether the swipe event effective or not.

If you don't want bind `click` event at same time, just set `disableClick` to `true`.

### Directives

#### Tap
#### v-touch
Bind the `v-touch` directive to components which you want enable touch events.

You can bind `tap` event use `v-tap` directive. The value should be a callback function.
`v-touch` accepts an argument to tell it which event you want to bind. `tap` and `swipe` are available.

```html
<span v-tap="tapHandler">Tap Me</span>
```

#### swipe

Use `v-swipe` directive when you want bind a simple swipe event. The value should be a callback function,
too.

```html
<span v-swipe="swipeHandler">Swipe here</span>
```

And you can use modifier here if you want bind a specified direction of swipe event only.

```html
<span v-swipe.left="swipeLeftHandler">Swipe Left</span>
```
The first argument of the `v-swipe` callback is the direction of swipe event. It could be `left`, `right`, `top` or `bottom`.

The first argument of the callback function is the swipe direction string, no matter there is a modifier or not.
`v-swipe` can accept extra modifiers. It means you can bind events only for specify direction.

```js
export default {
Expand All @@ -76,8 +95,49 @@ export default {
}
```

#### v-touch-class

`v-touch-class` directive allows you set an extra class on your components. If you already have a global config `touchClass`, this value will **overwrite** it.

For example:

```html
<span v-touch:tap="touchHandler" v-touch-class="'active'">Tap Me</span>
```

Now, when you start to touch, it will add an extra `active` class automatically. And remove it when touch end.

If your setting of `disableClick` is `false` (it's default), it will bind `mouseenter` and `mouseleave` events, too.

So that you can use this feature to instead of `:active` and `:hover` pseudo class, for a better user experience.

```css
/* before */
span:active, span:hover {
background: green;
}

/* now, you can write like this */
span.active {
background: green;
}
```

### Modifiers

#### left, right, top, bottom
This four modifiers are for `v-touch:swipe` only, to specify which direction you want to bind events to.

#### self

Same to `v-on:click.self`, only trigger events when the event target same to itself.

## Change History

#### v0.2.0
* `Change` change the main API. Use `v-touch` instead `v-tap` and `v-swipe`
* `Feature` add `v-touch-class` directive, and support `touchClass` global setting

#### v0.1.1
* `Feature` support `self` modifier

Expand Down
95 changes: 58 additions & 37 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ var vueTouchEvents = {
options.disableClick = options.disableClick || false
options.tapTolerance = options.tapTolerance || 10
options.swipeTolerance = options.swipeTolerance || 30
options.touchClass = options.touchClass || ''


var touchStartEvent = function (event) {
Expand All @@ -32,6 +33,8 @@ var vueTouchEvents = {
return
}

addTouchClass(this)

$this.touchStarted = true

$this.touchMoved = false
Expand Down Expand Up @@ -65,6 +68,8 @@ var vueTouchEvents = {
touchCancelEvent = function () {
var $this = this.$$touchObj

removeTouchClass(this)

$this.touchStarted = $this.touchMoved = false
$this.startX = $this.startY = 0
},
Expand All @@ -74,14 +79,16 @@ var vueTouchEvents = {

$this.touchStarted = false

removeTouchClass(this)

if (!$this.touchMoved) {
// emit tap event
if (binding.name === 'tap') {
if (binding.arg === 'tap') {
triggerEvent(event, binding)
}

} else if (!$this.swipeOutBounded) {
if (binding.name === 'swipe') {
if (binding.arg === 'swipe') {
var swipeOutBounded = options.swipeTolerance, direction

if (Math.abs($this.startX - $this.currentX) < swipeOutBounded) {
Expand Down Expand Up @@ -109,10 +116,20 @@ var vueTouchEvents = {
var $this = this.$$touchObj,
binding = this.$$binding

if (!$this.supportTouch && !options.disableClick && binding.name === 'tap' && typeof binding.value === 'function') {
if (!$this.supportTouch &&
!options.disableClick &&
binding.arg === 'tap' &&
typeof binding.value === 'function'
) {
triggerEvent(event, binding)
}
},
mouseEnterEvent = function () {
addTouchClass(this)
},
mouseLeaveEvent = function () {
removeTouchClass(this)
},
triggerEvent = function (event, binding, param) {

// handle `self` modifier`
Expand All @@ -127,54 +144,58 @@ var vueTouchEvents = {
binding.value(event)
}
}
},
addTouchClass = function ($el) {
var className = $el.$$touchClass || options.touchClass
$el.classList.add(className)
},
removeTouchClass = function ($el) {
var className = $el.$$touchClass || options.touchClass
$el.classList.remove(className)
}


function bindEvents($el, binding) {
$el.$$touchObj = {
supportTouch: false // will change to true when `touchstart` event first trigger
}
$el.$$binding = binding

$el.addEventListener('touchstart', touchStartEvent)
$el.addEventListener('touchmove', touchMoveEvent)
$el.addEventListener('touchcancel', touchCancelEvent)
$el.addEventListener('touchend', touchEndEvent)

if (!options.disableClick) {
$el.addEventListener('click', clickEvent)
}
}
Vue.directive('touch', {
bind: function ($el, binding) {
$el.$$touchObj = {
// will change to true when `touchstart` event first trigger
supportTouch: false
}
$el.$$binding = binding

function unbindEvents($el) {
$el.removeEventListener('touchstart', touchStartEvent)
$el.removeEventListener('touchmove', touchMoveEvent)
$el.removeEventListener('touchcancel', touchCancelEvent)
$el.removeEventListener('touchend', touchEndEvent)
// parse the arg argument, default is `tap`
$el.$$binding.arg = binding.arg ? binding.arg : 'tap'

if (!options.disableClick) {
$el.removeEventListener('click', clickEvent)
}
}

$el.addEventListener('touchstart', touchStartEvent)
$el.addEventListener('touchmove', touchMoveEvent)
$el.addEventListener('touchcancel', touchCancelEvent)
$el.addEventListener('touchend', touchEndEvent)

Vue.directive('tap', {
bind: function ($el, binding) {
bindEvents($el, binding)
if (!options.disableClick) {
$el.addEventListener('click', clickEvent)
$el.addEventListener('mouseenter', mouseEnterEvent)
$el.addEventListener('mouseleave', mouseLeaveEvent)
}
},

unbind: function ($el) {
unbindEvents($el)
$el.removeEventListener('touchstart', touchStartEvent)
$el.removeEventListener('touchmove', touchMoveEvent)
$el.removeEventListener('touchcancel', touchCancelEvent)
$el.removeEventListener('touchend', touchEndEvent)

if (!options.disableClick) {
$el.removeEventListener('click', clickEvent)
$el.removeEventListener('mouseenter', mouseEnterEvent)
$el.removeEventListener('mouseleave', mouseLeaveEvent)
}
}
})

Vue.directive('swipe', {
Vue.directive('touch-class', {
bind: function ($el, binding) {
bindEvents($el, binding)
},

unbind: function ($el) {
unbindEvents($el)
$el.$$touchClass = binding.value
}
})
}
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "vue2-touch-events",
"version": "0.1.1",
"version": "0.2.0",
"description": "Tap and swipe event support for vueJS2",
"main": "index.js",
"scripts": {
Expand Down

0 comments on commit a5727cf

Please sign in to comment.