123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841 |
- ;(function () {
- 'use strict';
-
-
-
-
- function FastClick(layer, options) {
- var oldOnClick;
- options = options || {};
-
- this.trackingClick = false;
-
- 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;
-
- this.tapTimeout = options.tapTimeout || 700;
- 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;
- }
- }
-
- var deviceIsWindowsPhone = navigator.userAgent.indexOf("Windows Phone") >= 0;
-
- var deviceIsAndroid = navigator.userAgent.indexOf('Android') > 0 && !deviceIsWindowsPhone;
-
- var deviceIsIOS = /iP(ad|hone|od)/.test(navigator.userAgent) && !deviceIsWindowsPhone;
-
- var deviceIsIOS4 = deviceIsIOS && (/OS 4_\d(_\d)?/).test(navigator.userAgent);
-
- var deviceIsIOSWithBadTarget = deviceIsIOS && (/OS [6-7]_\d/).test(navigator.userAgent);
-
- var deviceIsBlackBerry10 = navigator.userAgent.indexOf('BB10') > 0;
-
- FastClick.prototype.needsClick = function(target) {
- 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 'iframe':
- case 'video':
- return true;
- }
- return (/\bneedsclick\b/).test(target.className);
- };
-
- FastClick.prototype.needsFocus = function(target) {
- 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);
- }
- };
-
- FastClick.prototype.sendClick = function(targetElement, event) {
- 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) {
-
- if (deviceIsAndroid && targetElement.tagName.toLowerCase() === 'select') {
- return 'mousedown';
- }
- return 'click';
- };
-
- FastClick.prototype.focus = function(targetElement) {
- var length;
-
- if (deviceIsIOS && targetElement.setSelectionRange && targetElement.type.indexOf('date') !== 0 && targetElement.type !== 'time' && targetElement.type !== 'month') {
- length = targetElement.value.length;
- targetElement.setSelectionRange(length, length);
- } else {
- targetElement.focus();
- }
- };
-
- FastClick.prototype.updateScrollParent = function(targetElement) {
- 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;
- }
- };
-
- FastClick.prototype.getTargetElementFromEventTarget = function(eventTarget) {
-
- if (eventTarget.nodeType === Node.TEXT_NODE) {
- return eventTarget.parentNode;
- }
- return eventTarget;
- };
-
- FastClick.prototype.onTouchStart = function(event) {
- 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;
- };
-
- FastClick.prototype.touchHasMoved = function(event) {
- 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;
- };
-
- FastClick.prototype.onTouchMove = function(event) {
- if (!this.trackingClick) {
- return true;
- }
-
- if (this.targetElement !== this.getTargetElementFromEventTarget(event.target) || this.touchHasMoved(event)) {
- this.trackingClick = false;
- this.targetElement = null;
- }
- return true;
- };
-
- FastClick.prototype.findControl = function(labelElement) {
-
- 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');
- };
-
- FastClick.prototype.onTouchEnd = function(event) {
- 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;
- }
- if ((event.timeStamp - this.trackingClickStart) > this.tapTimeout) {
- 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;
- };
-
- FastClick.prototype.onTouchCancel = function() {
- this.trackingClick = false;
- this.targetElement = null;
- };
-
- FastClick.prototype.onMouse = function(event) {
-
- 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;
- };
-
- FastClick.prototype.onClick = function(event) {
- 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;
- };
-
- FastClick.prototype.destroy = function() {
- 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);
- };
-
- FastClick.notNeeded = function(layer) {
- var metaViewport;
- var chromeVersion;
- var blackberryVersion;
- var firefoxVersion;
-
- 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' || layer.style.touchAction === 'manipulation') {
- return true;
- }
-
- firefoxVersion = +(/Firefox\/([0-9]+)/.exec(navigator.userAgent) || [,0])[1];
- if (firefoxVersion >= 27) {
-
- metaViewport = document.querySelector('meta[name=viewport]');
- if (metaViewport && (metaViewport.content.indexOf('user-scalable=no') !== -1 || document.documentElement.scrollWidth <= window.outerWidth)) {
- return true;
- }
- }
-
-
- if (layer.style.touchAction === 'none' || layer.style.touchAction === 'manipulation') {
- return true;
- }
- return false;
- };
-
- FastClick.attach = function(layer, options) {
- return new FastClick(layer, options);
- };
- if (typeof define === 'function' && typeof define.amd === 'object' && define.amd) {
-
- define(function() {
- return FastClick;
- });
- } else if (typeof module !== 'undefined' && module.exports) {
- module.exports = FastClick.attach;
- module.exports.FastClick = FastClick;
- } else {
- window.FastClick = FastClick;
- }
- }());
|