fastclick-20140819-min.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. ! function() {
  2. function FastClick(layer, options) {
  3. "use strict";
  4. function bind(method, context) {
  5. return function() {
  6. return method.apply(context, arguments)
  7. }
  8. }
  9. var oldOnClick;
  10. if (options = options || {}, this.trackingClick = !1, this.trackingClickStart = 0, this.targetElement = null, this.touchStartX = 0, this.touchStartY = 0, this.lastTouchIdentifier = 0, this.touchBoundary = options.touchBoundary || 10, this.layer = layer, this.tapDelay = options.tapDelay || 200, !FastClick.notNeeded(layer)) {
  11. for (var methods = ["onMouse", "onClick", "onTouchStart", "onTouchMove", "onTouchEnd", "onTouchCancel"], context = this, i = 0, l = methods.length; l > i; i++) context[methods[i]] = bind(context[methods[i]], context);
  12. deviceIsAndroid && (layer.addEventListener("mouseover", this.onMouse, !0), layer.addEventListener("mousedown", this.onMouse, !0), layer.addEventListener("mouseup", this.onMouse, !0)), layer.addEventListener("click", this.onClick, !0), layer.addEventListener("touchstart", this.onTouchStart, !1), layer.addEventListener("touchmove", this.onTouchMove, !1), layer.addEventListener("touchend", this.onTouchEnd, !1), layer.addEventListener("touchcancel", this.onTouchCancel, !1), Event.prototype.stopImmediatePropagation || (layer.removeEventListener = function(type, callback, capture) {
  13. var rmv = Node.prototype.removeEventListener;
  14. "click" === type ? rmv.call(layer, type, callback.hijacked || callback, capture) : rmv.call(layer, type, callback, capture)
  15. }, layer.addEventListener = function(type, callback, capture) {
  16. var adv = Node.prototype.addEventListener;
  17. "click" === type ? adv.call(layer, type, callback.hijacked || (callback.hijacked = function(event) {
  18. event.propagationStopped || callback(event)
  19. }), capture) : adv.call(layer, type, callback, capture)
  20. }), "function" == typeof layer.onclick && (oldOnClick = layer.onclick, layer.addEventListener("click", function(event) {
  21. oldOnClick(event)
  22. }, !1), layer.onclick = null)
  23. }
  24. }
  25. var deviceIsAndroid = navigator.userAgent.indexOf("Android") > 0,
  26. deviceIsIOS = /iP(ad|hone|od)/.test(navigator.userAgent),
  27. deviceIsIOS4 = deviceIsIOS && /OS 4_\d(_\d)?/.test(navigator.userAgent),
  28. deviceIsIOSWithBadTarget = deviceIsIOS && /OS ([6-9]|\d{2})_\d/.test(navigator.userAgent),
  29. deviceIsBlackBerry10 = navigator.userAgent.indexOf("BB10") > 0;
  30. FastClick.prototype.needsClick = function(target) {
  31. "use strict";
  32. switch (target.nodeName.toLowerCase()) {
  33. case "button":
  34. case "select":
  35. case "textarea":
  36. if (target.disabled) return !0;
  37. break;
  38. case "input":
  39. if (deviceIsIOS && "file" === target.type || target.disabled) return !0;
  40. break;
  41. case "label":
  42. case "video":
  43. return !0
  44. }
  45. return /\bneedsclick\b/.test(target.className)
  46. }, FastClick.prototype.needsFocus = function(target) {
  47. "use strict";
  48. switch (target.nodeName.toLowerCase()) {
  49. case "textarea":
  50. return !0;
  51. case "select":
  52. return !deviceIsAndroid;
  53. case "input":
  54. switch (target.type) {
  55. case "button":
  56. case "checkbox":
  57. case "file":
  58. case "image":
  59. case "radio":
  60. case "submit":
  61. return !1
  62. }
  63. return !target.disabled && !target.readOnly;
  64. default:
  65. return /\bneedsfocus\b/.test(target.className)
  66. }
  67. }, FastClick.prototype.sendClick = function(targetElement, event) {
  68. "use strict";
  69. var clickEvent, touch;
  70. document.activeElement && document.activeElement !== targetElement && document.activeElement.blur(), touch = event.changedTouches[0], clickEvent = document.createEvent("MouseEvents"), clickEvent.initMouseEvent(this.determineEventType(targetElement), !0, !0, window, 1, touch.screenX, touch.screenY, touch.clientX, touch.clientY, !1, !1, !1, !1, 0, null), clickEvent.forwardedTouchEvent = !0, targetElement.dispatchEvent(clickEvent)
  71. }, FastClick.prototype.determineEventType = function(targetElement) {
  72. "use strict";
  73. return deviceIsAndroid && "select" === targetElement.tagName.toLowerCase() ? "mousedown" : "click"
  74. }, FastClick.prototype.focus = function(targetElement) {
  75. "use strict";
  76. var length;
  77. deviceIsIOS && targetElement.setSelectionRange && 0 !== targetElement.type.indexOf("date") && "time" !== targetElement.type ? (length = targetElement.value.length, targetElement.setSelectionRange(length, length)) : targetElement.focus()
  78. }, FastClick.prototype.updateScrollParent = function(targetElement) {
  79. "use strict";
  80. var scrollParent, parentElement;
  81. if (scrollParent = targetElement.fastClickScrollParent, !scrollParent || !scrollParent.contains(targetElement)) {
  82. parentElement = targetElement;
  83. do {
  84. if (parentElement.scrollHeight > parentElement.offsetHeight) {
  85. scrollParent = parentElement, targetElement.fastClickScrollParent = parentElement;
  86. break
  87. }
  88. parentElement = parentElement.parentElement
  89. } while (parentElement)
  90. }
  91. scrollParent && (scrollParent.fastClickLastScrollTop = scrollParent.scrollTop)
  92. }, FastClick.prototype.getTargetElementFromEventTarget = function(eventTarget) {
  93. "use strict";
  94. return eventTarget.nodeType === Node.TEXT_NODE ? eventTarget.parentNode : eventTarget
  95. }, FastClick.prototype.onTouchStart = function(event) {
  96. "use strict";
  97. var targetElement, touch, selection;
  98. if (event.targetTouches.length > 1) return !0;
  99. if (targetElement = this.getTargetElementFromEventTarget(event.target), touch = event.targetTouches[0], deviceIsIOS) {
  100. if (selection = window.getSelection(), selection.rangeCount && !selection.isCollapsed) return !0;
  101. if (!deviceIsIOS4) {
  102. if (touch.identifier && touch.identifier === this.lastTouchIdentifier) return event.preventDefault(), !1;
  103. this.lastTouchIdentifier = touch.identifier, this.updateScrollParent(targetElement)
  104. }
  105. }
  106. return this.trackingClick = !0, this.trackingClickStart = event.timeStamp, this.targetElement = targetElement, this.touchStartX = touch.pageX, this.touchStartY = touch.pageY, event.timeStamp - this.lastClickTime < this.tapDelay && event.preventDefault(), !0
  107. }, FastClick.prototype.touchHasMoved = function(event) {
  108. "use strict";
  109. var touch = event.changedTouches[0],
  110. boundary = this.touchBoundary;
  111. return Math.abs(touch.pageX - this.touchStartX) > boundary || Math.abs(touch.pageY - this.touchStartY) > boundary ? !0 : !1
  112. }, FastClick.prototype.onTouchMove = function(event) {
  113. "use strict";
  114. return this.trackingClick ? ((this.targetElement !== this.getTargetElementFromEventTarget(event.target) || this.touchHasMoved(event)) && (this.trackingClick = !1, this.targetElement = null), !0) : !0
  115. }, FastClick.prototype.findControl = function(labelElement) {
  116. "use strict";
  117. return void 0 !== labelElement.control ? labelElement.control : labelElement.htmlFor ? document.getElementById(labelElement.htmlFor) : labelElement.querySelector("button, input:not([type=hidden]), keygen, meter, output, progress, select, textarea")
  118. }, FastClick.prototype.onTouchEnd = function(event) {
  119. "use strict";
  120. var forElement, trackingClickStart, targetTagName, scrollParent, touch, targetElement = this.targetElement;
  121. if (!this.trackingClick) return !0;
  122. if (event.timeStamp - this.lastClickTime < this.tapDelay) return this.cancelNextClick = !0, !0;
  123. if (this.cancelNextClick = !1, this.lastClickTime = event.timeStamp, trackingClickStart = this.trackingClickStart, this.trackingClick = !1, this.trackingClickStart = 0, deviceIsIOSWithBadTarget && (touch = event.changedTouches[0], targetElement = document.elementFromPoint(touch.pageX - window.pageXOffset, touch.pageY - window.pageYOffset) || targetElement, targetElement.fastClickScrollParent = this.targetElement.fastClickScrollParent), targetTagName = targetElement.tagName.toLowerCase(), "label" === targetTagName) {
  124. if (forElement = this.findControl(targetElement)) {
  125. if (this.focus(targetElement), deviceIsAndroid) return !1;
  126. targetElement = forElement
  127. }
  128. } else if (this.needsFocus(targetElement)) return event.timeStamp - trackingClickStart > 100 || deviceIsIOS && window.top !== window && "input" === targetTagName ? (this.targetElement = null, !1) : (this.focus(targetElement), this.sendClick(targetElement, event), deviceIsIOS && "select" === targetTagName || (this.targetElement = null, event.preventDefault()), !1);
  129. return deviceIsIOS && !deviceIsIOS4 && (scrollParent = targetElement.fastClickScrollParent, scrollParent && scrollParent.fastClickLastScrollTop !== scrollParent.scrollTop) ? !0 : (this.needsClick(targetElement) || (event.preventDefault(), this.sendClick(targetElement, event)), !1)
  130. }, FastClick.prototype.onTouchCancel = function() {
  131. "use strict";
  132. this.trackingClick = !1, this.targetElement = null
  133. }, FastClick.prototype.onMouse = function(event) {
  134. "use strict";
  135. return this.targetElement ? event.forwardedTouchEvent ? !0 : event.cancelable && (!this.needsClick(this.targetElement) || this.cancelNextClick) ? (event.stopImmediatePropagation ? event.stopImmediatePropagation() : event.propagationStopped = !0, event.stopPropagation(), event.preventDefault(), !1) : !0 : !0
  136. }, FastClick.prototype.onClick = function(event) {
  137. "use strict";
  138. var permitted;
  139. return this.trackingClick ? (this.targetElement = null, this.trackingClick = !1, !0) : "submit" === event.target.type && 0 === event.detail ? !0 : (permitted = this.onMouse(event), permitted || (this.targetElement = null), permitted)
  140. }, FastClick.prototype.destroy = function() {
  141. "use strict";
  142. var layer = this.layer;
  143. deviceIsAndroid && (layer.removeEventListener("mouseover", this.onMouse, !0), layer.removeEventListener("mousedown", this.onMouse, !0), layer.removeEventListener("mouseup", this.onMouse, !0)), layer.removeEventListener("click", this.onClick, !0), layer.removeEventListener("touchstart", this.onTouchStart, !1), layer.removeEventListener("touchmove", this.onTouchMove, !1), layer.removeEventListener("touchend", this.onTouchEnd, !1), layer.removeEventListener("touchcancel", this.onTouchCancel, !1)
  144. }, FastClick.notNeeded = function(layer) {
  145. "use strict";
  146. var metaViewport, chromeVersion, blackberryVersion;
  147. if ("undefined" == typeof window.ontouchstart) return !0;
  148. if (chromeVersion = +(/Chrome\/([0-9]+)/.exec(navigator.userAgent) || [, 0])[1]) {
  149. if (!deviceIsAndroid) return !0;
  150. if (metaViewport = document.querySelector("meta[name=viewport]")) {
  151. if (-1 !== metaViewport.content.indexOf("user-scalable=no")) return !0;
  152. if (chromeVersion > 31 && document.documentElement.scrollWidth <= window.outerWidth) return !0
  153. }
  154. }
  155. if (deviceIsBlackBerry10 && (blackberryVersion = navigator.userAgent.match(/Version\/([0-9]*)\.([0-9]*)/), blackberryVersion[1] >= 10 && blackberryVersion[2] >= 3 && (metaViewport = document.querySelector("meta[name=viewport]")))) {
  156. if (-1 !== metaViewport.content.indexOf("user-scalable=no")) return !0;
  157. if (document.documentElement.scrollWidth <= window.outerWidth) return !0
  158. }
  159. return "none" === layer.style.msTouchAction ? !0 : !1
  160. }, FastClick.attach = function(layer, options) {
  161. "use strict";
  162. return new FastClick(layer, options)
  163. }, qike.lib.FastClick = FastClick
  164. }();