-
Notifications
You must be signed in to change notification settings - Fork 0
/
jquery.tappable.js
151 lines (131 loc) · 4.23 KB
/
jquery.tappable.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
/*
* jquery.tappable.js version 0.2
*
* More responsive (iOS-like) touch behaviour for buttons and other 'tappable' UI
* elements, instead of Mobile Safari's 300ms delay and ugly grey overlay:
*
* - A 'touched' class is added to the element as soon as it is tapped (or, in
* the case of a "long tap" - when the user keeps their finger down for a
* moment - after a specified delay).
*
* - The supplied callback is called as soon as the user lifts their finger.
*
* - The class is removed, and firing of the callback cancelled, if the user moves
* their finger (though this can be disabled).
*
* - If the browser doesn't support touch events, it falls back to click events.
*
* More detailed explanation of behaviour and background:
* http://aanandprasad.com/articles/jquery-tappable/
*
* See it in action here: http://nnnnext.com
*
* I recommend that you add a `-webkit-tap-highlight-color: rgba(0,0,0,0)`
* style rule to any elements you wish to make tappable, to hide the ugly grey
* click overlay.
*
* Tested on iOS 4.3 and some version of Android, I don't know. Leave me alone.
*
* Basic usage:
*
* $(element).tappable(function() { console.log("Hello World!") })
*
* Advanced usage:
*
* $(element).tappable({
* callback: function() { console.log("Hello World!") },
* cancelOnMove: false,
* touchDelay: 150,
* onlyIf: function(el) { return $(el).hasClass('enabled') }
* })
*
* Options:
*
* cancelOnMove: If truthy, then as soon as the user moves their finger, the
* 'touched' class is removed from the element. When they lift
* their finger, the callback will *not* be fired. Defaults to
* true.
*
* touchDelay: Time to wait (ms) before adding the 'touched' class when the
* user performs a "long tap". Best employed on elements that the
* user is likely to touch while scrolling. Around 150 will work
* well. Defaults to 0.
*
* onlyIf: Function to run as soon as the user touches the element, to
* determine whether to do anything. If it returns a falsy value,
* the 'touched' class will not be added and the callback will
* not be fired.
*
*/
;(function($) {
var touchSupported = ('ontouchstart' in window)
$.fn.tappable = function(options) {
var cancelOnMove = true,
onlyIf = function() { return true },
touchDelay = 0,
callback
switch(typeof options) {
case 'function':
callback = options
break;
case 'object':
callback = options.callback
if (typeof options.cancelOnMove != 'undefined') {
cancelOnMove = options.cancelOnMove
}
if (typeof options.onlyIf != 'undefined') {
onlyIf = options.onlyIf
}
if (typeof options.touchDelay != 'undefined') {
touchDelay = options.touchDelay
}
break;
}
var fireCallback = function(el, event) {
if (typeof callback == 'function' && onlyIf(el)) {
callback.call(el, event)
}
}
if (touchSupported) {
this.bind('touchstart', function(event) {
var el = this
if (onlyIf(this)) {
$(el).addClass('touch-started')
window.setTimeout(function() {
if ($(el).hasClass('touch-started')) {
$(el).addClass('touched')
}
}, touchDelay)
}
return true
})
this.bind('touchend', function(event) {
var el = this
if ($(el).hasClass('touch-started')) {
$(el)
.removeClass('touched')
.removeClass('touch-started')
fireCallback(el, event)
}
return true
})
this.bind('click', function(event) {
event.preventDefault()
})
if (cancelOnMove) {
this.bind('touchmove', function() {
$(this)
.removeClass('touched')
.removeClass('touch-started')
})
}
} else if (typeof callback == 'function') {
this.bind('click', function(event) {
if (onlyIf(this)) {
callback.call(this, event)
}
})
}
return this
}
})(jQuery);