2 * @preserve FastClick: polyfill to remove click delays on browsers with touch UIs.
5 * @codingstandard ftlabs-jsv2
6 * @copyright The Financial Times Limited [All Rights Reserved]
7 * @license MIT License (see LICENSE.txt)
9 function FastClick(a
, b
) {
13 return a
.apply(b
, arguments
)
18 if (b
= b
|| {}, this.trackingClick
= !1, this.trackingClickStart
= 0, this.targetElement
= null, this.touchStartX
= 0, this.touchStartY
= 0, this.lastTouchIdentifier
= 0, this.touchBoundary
= b
.touchBoundary
|| 10, this.layer
= a
, this.tapDelay
= b
.tapDelay
|| 200, !FastClick
.notNeeded(a
)) {
19 for (var e
= ["onMouse", "onClick", "onTouchStart", "onTouchMove", "onTouchEnd", "onTouchCancel"], f
= this, g
= 0, h
= e
.length
; h
> g
; g
++)f
[e
[g
]] = c(f
[e
[g
]], f
);
20 deviceIsAndroid
&& (a
.addEventListener("mouseover", this.onMouse
, !0), a
.addEventListener("mousedown", this.onMouse
, !0), a
.addEventListener("mouseup", this.onMouse
, !0)), a
.addEventListener("click", this.onClick
, !0), a
.addEventListener("touchstart", this.onTouchStart
, !1), a
.addEventListener("touchmove", this.onTouchMove
, !1), a
.addEventListener("touchend", this.onTouchEnd
, !1), a
.addEventListener("touchcancel", this.onTouchCancel
, !1), Event
.prototype.stopImmediatePropagation
|| (a
.removeEventListener = function (b
, c
, d
) {
21 var e
= Node
.prototype.removeEventListener
;
22 "click" === b
? e
.call(a
, b
, c
.hijacked
|| c
, d
) : e
.call(a
, b
, c
, d
)
23 }, a
.addEventListener = function (b
, c
, d
) {
24 var e
= Node
.prototype.addEventListener
;
25 "click" === b
? e
.call(a
, b
, c
.hijacked
|| (c
.hijacked = function (a
) {
26 a
.propagationStopped
|| c(a
)
27 }), d
) : e
.call(a
, b
, c
, d
)
28 }), "function" == typeof a
.onclick
&& (d
= a
.onclick
, a
.addEventListener("click", function (a
) {
30 }, !1), a
.onclick
= null)
33 var deviceIsAndroid
= navigator
.userAgent
.indexOf("Android") > 0, deviceIsIOS
= /iP(ad|hone|od)/.test(navigator
.userAgent
), deviceIsIOS4
= deviceIsIOS
&& /OS 4_\d(_\d)?/.test(navigator
.userAgent
), deviceIsIOSWithBadTarget
= deviceIsIOS
&& /OS ([6-9]|\d{2})_\d/.test(navigator
.userAgent
), deviceIsBlackBerry10
= navigator
.userAgent
.indexOf("BB10") > 0;
34 FastClick
.prototype.needsClick = function (a
) {
36 switch (a
.nodeName
.toLowerCase()) {
40 if (a
.disabled
)return !0;
43 if (deviceIsIOS
&& "file" === a
.type
|| a
.disabled
)return !0;
49 return /\bneedsclick\b/.test(a
.className
)
50 }, FastClick
.prototype.needsFocus = function (a
) {
52 switch (a
.nodeName
.toLowerCase()) {
56 return !deviceIsAndroid
;
67 return !a
.disabled
&& !a
.readOnly
;
69 return /\bneedsfocus\b/.test(a
.className
)
71 }, FastClick
.prototype.sendClick = function (a
, b
) {
74 document
.activeElement
&& document
.activeElement
!== a
&& document
.activeElement
.blur(), d
= b
.changedTouches
[0], c
= document
.createEvent("MouseEvents"), c
.initMouseEvent(this.determineEventType(a
), !0, !0, window
, 1, d
.screenX
, d
.screenY
, d
.clientX
, d
.clientY
, !1, !1, !1, !1, 0, null), c
.forwardedTouchEvent
= !0, a
.dispatchEvent(c
)
75 }, FastClick
.prototype.determineEventType = function (a
) {
77 return deviceIsAndroid
&& "select" === a
.tagName
.toLowerCase() ? "mousedown" : "click"
78 }, FastClick
.prototype.focus = function (a
) {
81 deviceIsIOS
&& a
.setSelectionRange
&& 0 !== a
.type
.indexOf("date") && "time" !== a
.type
? (b
= a
.value
.length
, a
.setSelectionRange(b
, b
)) : a
.focus()
82 }, FastClick
.prototype.updateScrollParent = function (a
) {
85 if (b
= a
.fastClickScrollParent
, !b
|| !b
.contains(a
)) {
88 if (c
.scrollHeight
> c
.offsetHeight
) {
89 b
= c
, a
.fastClickScrollParent
= c
;
95 b
&& (b
.fastClickLastScrollTop
= b
.scrollTop
)
96 }, FastClick
.prototype.getTargetElementFromEventTarget = function (a
) {
98 return a
.nodeType
=== Node
.TEXT_NODE
? a
.parentNode
: a
99 }, FastClick
.prototype.onTouchStart = function (a
) {
102 if (a
.targetTouches
.length
> 1)return !0;
103 if (b
= this.getTargetElementFromEventTarget(a
.target
), c
= a
.targetTouches
[0], deviceIsIOS
) {
104 if (d
= window
.getSelection(), d
.rangeCount
&& !d
.isCollapsed
)return !0;
106 if (c
.identifier
&& c
.identifier
=== this.lastTouchIdentifier
)return a
.preventDefault(), !1;
107 this.lastTouchIdentifier
= c
.identifier
, this.updateScrollParent(b
)
110 return this.trackingClick
= !0, this.trackingClickStart
= a
.timeStamp
, this.targetElement
= b
, this.touchStartX
= c
.pageX
, this.touchStartY
= c
.pageY
, a
.timeStamp
- this.lastClickTime
< this.tapDelay
&& a
.preventDefault(), !0
111 }, FastClick
.prototype.touchHasMoved = function (a
) {
113 var b
= a
.changedTouches
[0], c
= this.touchBoundary
;
114 return Math
.abs(b
.pageX
- this.touchStartX
) > c
|| Math
.abs(b
.pageY
- this.touchStartY
) > c
? !0 : !1
115 }, FastClick
.prototype.onTouchMove = function (a
) {
117 return this.trackingClick
? ((this.targetElement
!== this.getTargetElementFromEventTarget(a
.target
) || this.touchHasMoved(a
)) && (this.trackingClick
= !1, this.targetElement
= null), !0) : !0
118 }, FastClick
.prototype.findControl = function (a
) {
120 return void 0 !== a
.control
? a
.control
: a
.htmlFor
? document
.getElementById(a
.htmlFor
) : a
.querySelector("button, input:not([type=hidden]), keygen, meter, output, progress, select, textarea")
121 }, FastClick
.prototype.onTouchEnd = function (a
) {
123 var b
, c
, d
, e
, f
, g
= this.targetElement
;
124 if (!this.trackingClick
)return !0;
125 if (a
.timeStamp
- this.lastClickTime
< this.tapDelay
)return this.cancelNextClick
= !0, !0;
126 if (this.cancelNextClick
= !1, this.lastClickTime
= a
.timeStamp
, c
= this.trackingClickStart
, this.trackingClick
= !1, this.trackingClickStart
= 0, deviceIsIOSWithBadTarget
&& (f
= a
.changedTouches
[0], g
= document
.elementFromPoint(f
.pageX
- window
.pageXOffset
, f
.pageY
- window
.pageYOffset
) || g
, g
.fastClickScrollParent
= this.targetElement
.fastClickScrollParent
), d
= g
.tagName
.toLowerCase(), "label" === d
) {
127 if (b
= this.findControl(g
)) {
128 if (this.focus(g
), deviceIsAndroid
)return !1;
131 } else if (this.needsFocus(g
))return a
.timeStamp
- c
> 100 || deviceIsIOS
&& window
.top
!== window
&& "input" === d
? (this.targetElement
= null, !1) : (this.focus(g
), this.sendClick(g
, a
), deviceIsIOS
&& "select" === d
|| (this.targetElement
= null, a
.preventDefault()), !1);
132 return deviceIsIOS
&& !deviceIsIOS4
&& (e
= g
.fastClickScrollParent
, e
&& e
.fastClickLastScrollTop
!== e
.scrollTop
) ? !0 : (this.needsClick(g
) || (a
.preventDefault(), this.sendClick(g
, a
)), !1)
133 }, FastClick
.prototype.onTouchCancel = function () {
135 this.trackingClick
= !1, this.targetElement
= null
136 }, FastClick
.prototype.onMouse = function (a
) {
138 return this.targetElement
? a
.forwardedTouchEvent
? !0 : a
.cancelable
&& (!this.needsClick(this.targetElement
) || this.cancelNextClick
) ? (a
.stopImmediatePropagation
? a
.stopImmediatePropagation() : a
.propagationStopped
= !0, a
.stopPropagation(), a
.preventDefault(), !1) : !0 : !0
139 }, FastClick
.prototype.onClick = function (a
) {
142 return this.trackingClick
? (this.targetElement
= null, this.trackingClick
= !1, !0) : "submit" === a
.target
.type
&& 0 === a
.detail
? !0 : (b
= this.onMouse(a
), b
|| (this.targetElement
= null), b
)
143 }, FastClick
.prototype.destroy = function () {
146 deviceIsAndroid
&& (a
.removeEventListener("mouseover", this.onMouse
, !0), a
.removeEventListener("mousedown", this.onMouse
, !0), a
.removeEventListener("mouseup", this.onMouse
, !0)), a
.removeEventListener("click", this.onClick
, !0), a
.removeEventListener("touchstart", this.onTouchStart
, !1), a
.removeEventListener("touchmove", this.onTouchMove
, !1), a
.removeEventListener("touchend", this.onTouchEnd
, !1), a
.removeEventListener("touchcancel", this.onTouchCancel
, !1)
147 }, FastClick
.notNeeded = function (a
) {
150 if ("undefined" == typeof window
.ontouchstart
)return !0;
151 if (c
= +(/Chrome\/([0-9]+)/.exec(navigator
.userAgent
) || [, 0])[1]) {
152 if (!deviceIsAndroid
)return !0;
153 if (b
= document
.querySelector("meta[name=viewport]")) {
154 if (-1 !== b
.content
.indexOf("user-scalable=no"))return !0;
155 if (c
> 31 && document
.documentElement
.scrollWidth
<= window
.outerWidth
)return !0
158 if (deviceIsBlackBerry10
&& (d
= navigator
.userAgent
.match(/Version\/([0-9]*)\.([0-9]*)/), d
[1] >= 10 && d
[2] >= 3 && (b
= document
.querySelector("meta[name=viewport]")))) {
159 if (-1 !== b
.content
.indexOf("user-scalable=no"))return !0;
160 if (document
.documentElement
.scrollWidth
<= window
.outerWidth
)return !0
162 return "none" === a
.style
.msTouchAction
? !0 : !1
163 }, FastClick
.attach = function (a
, b
) {
165 return new FastClick(a
, b
)
166 }, "function" == typeof define
&& "object" == typeof define
.amd
&& define
.amd
? define(function () {
169 }) : "undefined" != typeof module
&& module
.exports
? (module
.exports
= FastClick
.attach
, module
.exports
.FastClick
= FastClick
) : window
.FastClick
= FastClick
;