|
@@ -1,821 +0,0 @@
|
|
|
-
|
|
|
- * @preserve FastClick: polyfill to remove click delays on browsers with touch UIs.
|
|
|
- *
|
|
|
- * @version 1.0.3
|
|
|
- * @codingstandard ftlabs-jsv2
|
|
|
- * @copyright The Financial Times Limited [All Rights Reserved]
|
|
|
- * @license MIT License (see LICENSE.txt)
|
|
|
- */
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- * Instantiate fast-clicking listeners on the specified layer.
|
|
|
- *
|
|
|
- * @constructor
|
|
|
- * @param {Element} layer The layer to listen on
|
|
|
- * @param {Object} options The options to override the defaults
|
|
|
- */
|
|
|
-function FastClick(layer, options) {
|
|
|
- 'use strict';
|
|
|
- var oldOnClick;
|
|
|
-
|
|
|
- options = options || {};
|
|
|
-
|
|
|
-
|
|
|
- * Whether a click is currently being tracked.
|
|
|
- *
|
|
|
- * @type boolean
|
|
|
- */
|
|
|
- this.trackingClick = false;
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- * Timestamp for when click tracking started.
|
|
|
- *
|
|
|
- * @type number
|
|
|
- */
|
|
|
- this.trackingClickStart = 0;
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- * The element being tracked for a click.
|
|
|
- *
|
|
|
- * @type EventTarget
|
|
|
- */
|
|
|
- this.targetElement = null;
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- * X-coordinate of touch start event.
|
|
|
- *
|
|
|
- * @type number
|
|
|
- */
|
|
|
- this.touchStartX = 0;
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- * Y-coordinate of touch start event.
|
|
|
- *
|
|
|
- * @type number
|
|
|
- */
|
|
|
- this.touchStartY = 0;
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- * ID of the last touch, retrieved from Touch.identifier.
|
|
|
- *
|
|
|
- * @type number
|
|
|
- */
|
|
|
- this.lastTouchIdentifier = 0;
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- * Touchmove boundary, beyond which a click will be cancelled.
|
|
|
- *
|
|
|
- * @type number
|
|
|
- */
|
|
|
- this.touchBoundary = options.touchBoundary || 10;
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- * The FastClick layer.
|
|
|
- *
|
|
|
- * @type Element
|
|
|
- */
|
|
|
- this.layer = layer;
|
|
|
-
|
|
|
-
|
|
|
- * The minimum time between tap(touchstart and touchend) events
|
|
|
- *
|
|
|
- * @type number
|
|
|
- */
|
|
|
- this.tapDelay = options.tapDelay || 200;
|
|
|
-
|
|
|
- if (FastClick.notNeeded(layer)) {
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- function bind(method, context) {
|
|
|
- return function() { return method.apply(context, arguments); };
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- var methods = ['onMouse', 'onClick', 'onTouchStart', 'onTouchMove', 'onTouchEnd', 'onTouchCancel'];
|
|
|
- var context = this;
|
|
|
- for (var i = 0, l = methods.length; i < l; i++) {
|
|
|
- context[methods[i]] = bind(context[methods[i]], context);
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- if (deviceIsAndroid) {
|
|
|
- layer.addEventListener('mouseover', this.onMouse, true);
|
|
|
- layer.addEventListener('mousedown', this.onMouse, true);
|
|
|
- layer.addEventListener('mouseup', this.onMouse, true);
|
|
|
- }
|
|
|
-
|
|
|
- layer.addEventListener('click', this.onClick, true);
|
|
|
- layer.addEventListener('touchstart', this.onTouchStart, false);
|
|
|
- layer.addEventListener('touchmove', this.onTouchMove, false);
|
|
|
- layer.addEventListener('touchend', this.onTouchEnd, false);
|
|
|
- layer.addEventListener('touchcancel', this.onTouchCancel, false);
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- if (!Event.prototype.stopImmediatePropagation) {
|
|
|
- layer.removeEventListener = function(type, callback, capture) {
|
|
|
- var rmv = Node.prototype.removeEventListener;
|
|
|
- if (type === 'click') {
|
|
|
- rmv.call(layer, type, callback.hijacked || callback, capture);
|
|
|
- } else {
|
|
|
- rmv.call(layer, type, callback, capture);
|
|
|
- }
|
|
|
- };
|
|
|
-
|
|
|
- layer.addEventListener = function(type, callback, capture) {
|
|
|
- var adv = Node.prototype.addEventListener;
|
|
|
- if (type === 'click') {
|
|
|
- adv.call(layer, type, callback.hijacked || (callback.hijacked = function(event) {
|
|
|
- if (!event.propagationStopped) {
|
|
|
- callback(event);
|
|
|
- }
|
|
|
- }), capture);
|
|
|
- } else {
|
|
|
- adv.call(layer, type, callback, capture);
|
|
|
- }
|
|
|
- };
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- if (typeof layer.onclick === 'function') {
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- oldOnClick = layer.onclick;
|
|
|
- layer.addEventListener('click', function(event) {
|
|
|
- oldOnClick(event);
|
|
|
- }, false);
|
|
|
- layer.onclick = null;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- * Android requires exceptions.
|
|
|
- *
|
|
|
- * @type boolean
|
|
|
- */
|
|
|
-var deviceIsAndroid = navigator.userAgent.indexOf('Android') > 0;
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- * iOS requires exceptions.
|
|
|
- *
|
|
|
- * @type boolean
|
|
|
- */
|
|
|
-var deviceIsIOS = /iP(ad|hone|od)/.test(navigator.userAgent);
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- * iOS 4 requires an exception for select elements.
|
|
|
- *
|
|
|
- * @type boolean
|
|
|
- */
|
|
|
-var deviceIsIOS4 = deviceIsIOS && (/OS 4_\d(_\d)?/).test(navigator.userAgent);
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- * iOS 6.0(+?) requires the target element to be manually derived
|
|
|
- *
|
|
|
- * @type boolean
|
|
|
- */
|
|
|
-var deviceIsIOSWithBadTarget = deviceIsIOS && (/OS ([6-9]|\d{2})_\d/).test(navigator.userAgent);
|
|
|
-
|
|
|
-
|
|
|
- * BlackBerry requires exceptions.
|
|
|
- *
|
|
|
- * @type boolean
|
|
|
- */
|
|
|
-var deviceIsBlackBerry10 = navigator.userAgent.indexOf('BB10') > 0;
|
|
|
-
|
|
|
-
|
|
|
- * Determine whether a given element requires a native click.
|
|
|
- *
|
|
|
- * @param {EventTarget|Element} target Target DOM element
|
|
|
- * @returns {boolean} Returns true if the element needs a native click
|
|
|
- */
|
|
|
-FastClick.prototype.needsClick = function(target) {
|
|
|
- 'use strict';
|
|
|
- switch (target.nodeName.toLowerCase()) {
|
|
|
-
|
|
|
-
|
|
|
- case 'button':
|
|
|
- case 'select':
|
|
|
- case 'textarea':
|
|
|
- if (target.disabled) {
|
|
|
- return true;
|
|
|
- }
|
|
|
-
|
|
|
- break;
|
|
|
- case 'input':
|
|
|
-
|
|
|
-
|
|
|
- if ((deviceIsIOS && target.type === 'file') || target.disabled) {
|
|
|
- return true;
|
|
|
- }
|
|
|
-
|
|
|
- break;
|
|
|
- case 'label':
|
|
|
- case 'video':
|
|
|
- return true;
|
|
|
- }
|
|
|
-
|
|
|
- return (/\bneedsclick\b/).test(target.className);
|
|
|
-};
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- * Determine whether a given element requires a call to focus to simulate click into element.
|
|
|
- *
|
|
|
- * @param {EventTarget|Element} target Target DOM element
|
|
|
- * @returns {boolean} Returns true if the element requires a call to focus to simulate native click.
|
|
|
- */
|
|
|
-FastClick.prototype.needsFocus = function(target) {
|
|
|
- 'use strict';
|
|
|
- switch (target.nodeName.toLowerCase()) {
|
|
|
- case 'textarea':
|
|
|
- return true;
|
|
|
- case 'select':
|
|
|
- return !deviceIsAndroid;
|
|
|
- case 'input':
|
|
|
- switch (target.type) {
|
|
|
- case 'button':
|
|
|
- case 'checkbox':
|
|
|
- case 'file':
|
|
|
- case 'image':
|
|
|
- case 'radio':
|
|
|
- case 'submit':
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- return !target.disabled && !target.readOnly;
|
|
|
- default:
|
|
|
- return (/\bneedsfocus\b/).test(target.className);
|
|
|
- }
|
|
|
-};
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- * Send a click event to the specified element.
|
|
|
- *
|
|
|
- * @param {EventTarget|Element} targetElement
|
|
|
- * @param {Event} event
|
|
|
- */
|
|
|
-FastClick.prototype.sendClick = function(targetElement, event) {
|
|
|
- 'use strict';
|
|
|
- var clickEvent, touch;
|
|
|
-
|
|
|
-
|
|
|
- if (document.activeElement && document.activeElement !== targetElement) {
|
|
|
- document.activeElement.blur();
|
|
|
- }
|
|
|
-
|
|
|
- touch = event.changedTouches[0];
|
|
|
-
|
|
|
-
|
|
|
- clickEvent = document.createEvent('MouseEvents');
|
|
|
- clickEvent.initMouseEvent(this.determineEventType(targetElement), true, true, window, 1, touch.screenX, touch.screenY, touch.clientX, touch.clientY, false, false, false, false, 0, null);
|
|
|
- clickEvent.forwardedTouchEvent = true;
|
|
|
- targetElement.dispatchEvent(clickEvent);
|
|
|
-};
|
|
|
-
|
|
|
-FastClick.prototype.determineEventType = function(targetElement) {
|
|
|
- 'use strict';
|
|
|
-
|
|
|
-
|
|
|
- if (deviceIsAndroid && targetElement.tagName.toLowerCase() === 'select') {
|
|
|
- return 'mousedown';
|
|
|
- }
|
|
|
-
|
|
|
- return 'click';
|
|
|
-};
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- * @param {EventTarget|Element} targetElement
|
|
|
- */
|
|
|
-FastClick.prototype.focus = function(targetElement) {
|
|
|
- 'use strict';
|
|
|
- var length;
|
|
|
-
|
|
|
-
|
|
|
- if (deviceIsIOS && targetElement.setSelectionRange && targetElement.type.indexOf('date') !== 0 && targetElement.type !== 'time') {
|
|
|
- length = targetElement.value.length;
|
|
|
- targetElement.setSelectionRange(length, length);
|
|
|
- } else {
|
|
|
- targetElement.focus();
|
|
|
- }
|
|
|
-};
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- * Check whether the given target element is a child of a scrollable layer and if so, set a flag on it.
|
|
|
- *
|
|
|
- * @param {EventTarget|Element} targetElement
|
|
|
- */
|
|
|
-FastClick.prototype.updateScrollParent = function(targetElement) {
|
|
|
- 'use strict';
|
|
|
- var scrollParent, parentElement;
|
|
|
-
|
|
|
- scrollParent = targetElement.fastClickScrollParent;
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- if (!scrollParent || !scrollParent.contains(targetElement)) {
|
|
|
- parentElement = targetElement;
|
|
|
- do {
|
|
|
- if (parentElement.scrollHeight > parentElement.offsetHeight) {
|
|
|
- scrollParent = parentElement;
|
|
|
- targetElement.fastClickScrollParent = parentElement;
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- parentElement = parentElement.parentElement;
|
|
|
- } while (parentElement);
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- if (scrollParent) {
|
|
|
- scrollParent.fastClickLastScrollTop = scrollParent.scrollTop;
|
|
|
- }
|
|
|
-};
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- * @param {EventTarget} targetElement
|
|
|
- * @returns {Element|EventTarget}
|
|
|
- */
|
|
|
-FastClick.prototype.getTargetElementFromEventTarget = function(eventTarget) {
|
|
|
- 'use strict';
|
|
|
-
|
|
|
-
|
|
|
- if (eventTarget.nodeType === Node.TEXT_NODE) {
|
|
|
- return eventTarget.parentNode;
|
|
|
- }
|
|
|
-
|
|
|
- return eventTarget;
|
|
|
-};
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- * On touch start, record the position and scroll offset.
|
|
|
- *
|
|
|
- * @param {Event} event
|
|
|
- * @returns {boolean}
|
|
|
- */
|
|
|
-FastClick.prototype.onTouchStart = function(event) {
|
|
|
- 'use strict';
|
|
|
- var targetElement, touch, selection;
|
|
|
-
|
|
|
-
|
|
|
- if (event.targetTouches.length > 1) {
|
|
|
- return true;
|
|
|
- }
|
|
|
-
|
|
|
- targetElement = this.getTargetElementFromEventTarget(event.target);
|
|
|
- touch = event.targetTouches[0];
|
|
|
-
|
|
|
- if (deviceIsIOS) {
|
|
|
-
|
|
|
-
|
|
|
- selection = window.getSelection();
|
|
|
- if (selection.rangeCount && !selection.isCollapsed) {
|
|
|
- return true;
|
|
|
- }
|
|
|
-
|
|
|
- if (!deviceIsIOS4) {
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- if (touch.identifier && touch.identifier === this.lastTouchIdentifier) {
|
|
|
- event.preventDefault();
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- this.lastTouchIdentifier = touch.identifier;
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- this.updateScrollParent(targetElement);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- this.trackingClick = true;
|
|
|
- this.trackingClickStart = event.timeStamp;
|
|
|
- this.targetElement = targetElement;
|
|
|
-
|
|
|
- this.touchStartX = touch.pageX;
|
|
|
- this.touchStartY = touch.pageY;
|
|
|
-
|
|
|
-
|
|
|
- if ((event.timeStamp - this.lastClickTime) < this.tapDelay) {
|
|
|
- event.preventDefault();
|
|
|
- }
|
|
|
-
|
|
|
- return true;
|
|
|
-};
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- * Based on a touchmove event object, check whether the touch has moved past a boundary since it started.
|
|
|
- *
|
|
|
- * @param {Event} event
|
|
|
- * @returns {boolean}
|
|
|
- */
|
|
|
-FastClick.prototype.touchHasMoved = function(event) {
|
|
|
- 'use strict';
|
|
|
- var touch = event.changedTouches[0], boundary = this.touchBoundary;
|
|
|
-
|
|
|
- if (Math.abs(touch.pageX - this.touchStartX) > boundary || Math.abs(touch.pageY - this.touchStartY) > boundary) {
|
|
|
- return true;
|
|
|
- }
|
|
|
-
|
|
|
- return false;
|
|
|
-};
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- * Update the last position.
|
|
|
- *
|
|
|
- * @param {Event} event
|
|
|
- * @returns {boolean}
|
|
|
- */
|
|
|
-FastClick.prototype.onTouchMove = function(event) {
|
|
|
- 'use strict';
|
|
|
- if (!this.trackingClick) {
|
|
|
- return true;
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- if (this.targetElement !== this.getTargetElementFromEventTarget(event.target) || this.touchHasMoved(event)) {
|
|
|
- this.trackingClick = false;
|
|
|
- this.targetElement = null;
|
|
|
- }
|
|
|
-
|
|
|
- return true;
|
|
|
-};
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- * Attempt to find the labelled control for the given label element.
|
|
|
- *
|
|
|
- * @param {EventTarget|HTMLLabelElement} labelElement
|
|
|
- * @returns {Element|null}
|
|
|
- */
|
|
|
-FastClick.prototype.findControl = function(labelElement) {
|
|
|
- 'use strict';
|
|
|
-
|
|
|
-
|
|
|
- if (labelElement.control !== undefined) {
|
|
|
- return labelElement.control;
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- if (labelElement.htmlFor) {
|
|
|
- return document.getElementById(labelElement.htmlFor);
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- return labelElement.querySelector('button, input:not([type=hidden]), keygen, meter, output, progress, select, textarea');
|
|
|
-};
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- * On touch end, determine whether to send a click event at once.
|
|
|
- *
|
|
|
- * @param {Event} event
|
|
|
- * @returns {boolean}
|
|
|
- */
|
|
|
-FastClick.prototype.onTouchEnd = function(event) {
|
|
|
- 'use strict';
|
|
|
- var forElement, trackingClickStart, targetTagName, scrollParent, touch, targetElement = this.targetElement;
|
|
|
-
|
|
|
- if (!this.trackingClick) {
|
|
|
- return true;
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- if ((event.timeStamp - this.lastClickTime) < this.tapDelay) {
|
|
|
- this.cancelNextClick = true;
|
|
|
- return true;
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- this.cancelNextClick = false;
|
|
|
-
|
|
|
- this.lastClickTime = event.timeStamp;
|
|
|
-
|
|
|
- trackingClickStart = this.trackingClickStart;
|
|
|
- this.trackingClick = false;
|
|
|
- this.trackingClickStart = 0;
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- if (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();
|
|
|
- if (targetTagName === 'label') {
|
|
|
- forElement = this.findControl(targetElement);
|
|
|
- if (forElement) {
|
|
|
- this.focus(targetElement);
|
|
|
- if (deviceIsAndroid) {
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- targetElement = forElement;
|
|
|
- }
|
|
|
- } else if (this.needsFocus(targetElement)) {
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- if ((event.timeStamp - trackingClickStart) > 100 || (deviceIsIOS && window.top !== window && targetTagName === 'input')) {
|
|
|
- this.targetElement = null;
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- this.focus(targetElement);
|
|
|
- this.sendClick(targetElement, event);
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- if (!deviceIsIOS || targetTagName !== 'select') {
|
|
|
- this.targetElement = null;
|
|
|
- event.preventDefault();
|
|
|
- }
|
|
|
-
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- if (deviceIsIOS && !deviceIsIOS4) {
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- scrollParent = targetElement.fastClickScrollParent;
|
|
|
- if (scrollParent && scrollParent.fastClickLastScrollTop !== scrollParent.scrollTop) {
|
|
|
- return true;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- if (!this.needsClick(targetElement)) {
|
|
|
- event.preventDefault();
|
|
|
- this.sendClick(targetElement, event);
|
|
|
- }
|
|
|
-
|
|
|
- return false;
|
|
|
-};
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- * On touch cancel, stop tracking the click.
|
|
|
- *
|
|
|
- * @returns {void}
|
|
|
- */
|
|
|
-FastClick.prototype.onTouchCancel = function() {
|
|
|
- 'use strict';
|
|
|
- this.trackingClick = false;
|
|
|
- this.targetElement = null;
|
|
|
-};
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- * Determine mouse events which should be permitted.
|
|
|
- *
|
|
|
- * @param {Event} event
|
|
|
- * @returns {boolean}
|
|
|
- */
|
|
|
-FastClick.prototype.onMouse = function(event) {
|
|
|
- 'use strict';
|
|
|
-
|
|
|
-
|
|
|
- if (!this.targetElement) {
|
|
|
- return true;
|
|
|
- }
|
|
|
-
|
|
|
- if (event.forwardedTouchEvent) {
|
|
|
- return true;
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- if (!event.cancelable) {
|
|
|
- return true;
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- if (!this.needsClick(this.targetElement) || this.cancelNextClick) {
|
|
|
-
|
|
|
-
|
|
|
- if (event.stopImmediatePropagation) {
|
|
|
- event.stopImmediatePropagation();
|
|
|
- } else {
|
|
|
-
|
|
|
-
|
|
|
- event.propagationStopped = true;
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- event.stopPropagation();
|
|
|
- event.preventDefault();
|
|
|
-
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- return true;
|
|
|
-};
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- * On actual clicks, determine whether this is a touch-generated click, a click action occurring
|
|
|
- * naturally after a delay after a touch (which needs to be cancelled to avoid duplication), or
|
|
|
- * an actual click which should be permitted.
|
|
|
- *
|
|
|
- * @param {Event} event
|
|
|
- * @returns {boolean}
|
|
|
- */
|
|
|
-FastClick.prototype.onClick = function(event) {
|
|
|
- 'use strict';
|
|
|
- var permitted;
|
|
|
-
|
|
|
-
|
|
|
- if (this.trackingClick) {
|
|
|
- this.targetElement = null;
|
|
|
- this.trackingClick = false;
|
|
|
- return true;
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- if (event.target.type === 'submit' && event.detail === 0) {
|
|
|
- return true;
|
|
|
- }
|
|
|
-
|
|
|
- permitted = this.onMouse(event);
|
|
|
-
|
|
|
-
|
|
|
- if (!permitted) {
|
|
|
- this.targetElement = null;
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- return permitted;
|
|
|
-};
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- * Remove all FastClick's event listeners.
|
|
|
- *
|
|
|
- * @returns {void}
|
|
|
- */
|
|
|
-FastClick.prototype.destroy = function() {
|
|
|
- 'use strict';
|
|
|
- var layer = this.layer;
|
|
|
-
|
|
|
- if (deviceIsAndroid) {
|
|
|
- layer.removeEventListener('mouseover', this.onMouse, true);
|
|
|
- layer.removeEventListener('mousedown', this.onMouse, true);
|
|
|
- layer.removeEventListener('mouseup', this.onMouse, true);
|
|
|
- }
|
|
|
-
|
|
|
- layer.removeEventListener('click', this.onClick, true);
|
|
|
- layer.removeEventListener('touchstart', this.onTouchStart, false);
|
|
|
- layer.removeEventListener('touchmove', this.onTouchMove, false);
|
|
|
- layer.removeEventListener('touchend', this.onTouchEnd, false);
|
|
|
- layer.removeEventListener('touchcancel', this.onTouchCancel, false);
|
|
|
-};
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- * Check whether FastClick is needed.
|
|
|
- *
|
|
|
- * @param {Element} layer The layer to listen on
|
|
|
- */
|
|
|
-FastClick.notNeeded = function(layer) {
|
|
|
- 'use strict';
|
|
|
- var metaViewport;
|
|
|
- var chromeVersion;
|
|
|
- var blackberryVersion;
|
|
|
-
|
|
|
-
|
|
|
- if (typeof window.ontouchstart === 'undefined') {
|
|
|
- return true;
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- chromeVersion = +(/Chrome\/([0-9]+)/.exec(navigator.userAgent) || [,0])[1];
|
|
|
-
|
|
|
- if (chromeVersion) {
|
|
|
-
|
|
|
- if (deviceIsAndroid) {
|
|
|
- metaViewport = document.querySelector('meta[name=viewport]');
|
|
|
-
|
|
|
- if (metaViewport) {
|
|
|
-
|
|
|
- if (metaViewport.content.indexOf('user-scalable=no') !== -1) {
|
|
|
- return true;
|
|
|
- }
|
|
|
-
|
|
|
- if (chromeVersion > 31 && document.documentElement.scrollWidth <= window.outerWidth) {
|
|
|
- return true;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- } else {
|
|
|
- return true;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (deviceIsBlackBerry10) {
|
|
|
- blackberryVersion = navigator.userAgent.match(/Version\/([0-9]*)\.([0-9]*)/);
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- if (blackberryVersion[1] >= 10 && blackberryVersion[2] >= 3) {
|
|
|
- metaViewport = document.querySelector('meta[name=viewport]');
|
|
|
-
|
|
|
- if (metaViewport) {
|
|
|
-
|
|
|
- if (metaViewport.content.indexOf('user-scalable=no') !== -1) {
|
|
|
- return true;
|
|
|
- }
|
|
|
-
|
|
|
- if (document.documentElement.scrollWidth <= window.outerWidth) {
|
|
|
- return true;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- if (layer.style.msTouchAction === 'none') {
|
|
|
- return true;
|
|
|
- }
|
|
|
-
|
|
|
- return false;
|
|
|
-};
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- * Factory method for creating a FastClick object
|
|
|
- *
|
|
|
- * @param {Element} layer The layer to listen on
|
|
|
- * @param {Object} options The options to override the defaults
|
|
|
- */
|
|
|
-FastClick.attach = function(layer, options) {
|
|
|
- 'use strict';
|
|
|
- return new FastClick(layer, options);
|
|
|
-};
|
|
|
-
|
|
|
-
|
|
|
-if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) {
|
|
|
-
|
|
|
-
|
|
|
- define(function() {
|
|
|
- 'use strict';
|
|
|
- return FastClick;
|
|
|
- });
|
|
|
-} else if (typeof module !== 'undefined' && module.exports) {
|
|
|
- module.exports = FastClick.attach;
|
|
|
- module.exports.FastClick = FastClick;
|
|
|
-} else {
|
|
|
- window.FastClick = FastClick;
|
|
|
-}
|