anima-yocto-touch
Advanced tools
Comparing version 1.0.0 to 1.0.1
@@ -8,1 +8,7 @@ # History | ||
`new` It is the first version of anima-yocto-touch. | ||
## 1.0.1 | ||
+ 基于`fastclick.js`进行重构,去除一些不必要的兼容性代码 | ||
+ 事件触发顺序为touchstart,touchmove,touchend,tap,click | ||
+ 重构新增手势API |
{ | ||
"name": "anima-yocto-touch", | ||
"version": "1.0.0", | ||
"version": "1.0.1", | ||
"description": "the touch from yocto", | ||
@@ -24,4 +24,4 @@ "keywords": [], | ||
"dependencies": { | ||
"anima-yocto-core": "1.0.0", | ||
"anima-yocto-event": "1.0.0" | ||
"anima-yocto-core": "1.1.0", | ||
"anima-yocto-event": "1.0.1" | ||
}, | ||
@@ -28,0 +28,0 @@ "devDependencies": { |
542
src/touch.js
// Thanks to: https://github.com/ftlabs/fastclick | ||
var $ = Yocto = require('anima-yocto-core'), | ||
Gesture = { | ||
init: function(name){ | ||
var gesture = this[name]; | ||
var $ = Yocto = require('anima-yocto-core'); | ||
Object.keys(gesture.handler).forEach(function(prop){ | ||
document.addEventListener(prop, gesture.handler[prop], false); | ||
}); | ||
// 防止引入多个touch文件造成的重复执行问题 | ||
if(!$.gestures){ | ||
var Gesture = { | ||
init: function(name){ | ||
var gesture = this[name]; | ||
gesture.events.forEach(function(eventName){ | ||
Object.keys(gesture.handler).forEach(function(prop){ | ||
document.addEventListener(prop, gesture.handler[prop], false); | ||
}); | ||
$.fn[eventName] = function(callback) { | ||
return this.on(eventName, callback) | ||
}; | ||
}); | ||
} | ||
}; | ||
gesture.events.forEach(function(eventName){ | ||
require('anima-yocto-event') | ||
$.fn[eventName] = function(callback) { | ||
return this.on(eventName, callback) | ||
}; | ||
}); | ||
} | ||
}; | ||
var deviceIsAndroid = navigator.userAgent.toLowerCase().indexOf('android') > 0, | ||
deviceIsIOS = /ip(ad|hone|od)/.test(navigator.userAgent.toLowerCase()); | ||
require('anima-yocto-event') | ||
var yoctoTouch = { | ||
trackingClick: false, | ||
trackingClickStart: 0, | ||
targetElement: null, | ||
touchStartX: 0, | ||
touchStartY: 0, | ||
lastTouchIdentifier: 0, | ||
touchBoundary: 10, | ||
tapDelay: 200, | ||
sendClick: function(targetElement, event){ | ||
// 在click之前触发tap事件 | ||
var tap = $.Event('tap', {animaTap: true}) | ||
$(targetElement).trigger(tap); | ||
var deviceIsAndroid = navigator.userAgent.toLowerCase().indexOf('android') > 0, | ||
deviceIsIOS = /ip(ad|hone|od)/.test(navigator.userAgent.toLowerCase()); | ||
// if(yoctoTouch.isDouleTap){ | ||
// $(targetElement).trigger('doubleTap'); | ||
// yoctoTouch.isDouleTap = false; | ||
// delete yoctoTouch.last; | ||
// } | ||
var yoctoTouch = { | ||
trackingClick: false, | ||
trackingClickStart: 0, | ||
targetElement: null, | ||
touchStartX: 0, | ||
touchStartY: 0, | ||
lastTouchIdentifier: 0, | ||
touchBoundary: 10, | ||
tapDelay: 200, | ||
sendClick: function(targetElement, event){ | ||
// 在click之前触发tap事件 | ||
var tap = $.Event('tap', {animaTap: true}) | ||
$(targetElement).trigger(tap); | ||
var clickEvent, touch; | ||
// if(yoctoTouch.isDouleTap){ | ||
// $(targetElement).trigger('doubleTap'); | ||
// yoctoTouch.isDouleTap = false; | ||
// delete yoctoTouch.last; | ||
// } | ||
// On some Android devices activeElement needs to be blurred otherwise the synthetic click will have no effect (#24) | ||
if (document.activeElement && document.activeElement !== targetElement) { | ||
document.activeElement.blur(); | ||
} | ||
var clickEvent, touch; | ||
touch = event.changedTouches[0]; | ||
// Synthesise a click event, with an extra attribute so it can be tracked | ||
clickEvent = document.createEvent('MouseEvents'); | ||
clickEvent.initMouseEvent('click', true, true, window, 1, touch.screenX, touch.screenY, touch.clientX, touch.clientY, false, false, false, false, 0, null); | ||
clickEvent.animaClick = true; | ||
targetElement.dispatchEvent(clickEvent); | ||
}, | ||
needClick: function(target){ | ||
switch (target.nodeName.toLowerCase()) { | ||
// Don't send a synthetic click to disabled inputs (issue #62) | ||
case 'button': | ||
case 'select': | ||
case 'textarea': | ||
if (target.disabled) { | ||
return true; | ||
// On some Android devices activeElement needs to be blurred otherwise the synthetic click will have no effect (#24) | ||
if (document.activeElement && document.activeElement !== targetElement) { | ||
document.activeElement.blur(); | ||
} | ||
break; | ||
case 'input': | ||
touch = event.changedTouches[0]; | ||
// File inputs need real clicks on iOS 6 due to a browser bug (issue #68) | ||
if ((deviceIsIOS && target.type === 'file') || target.disabled) { | ||
return true; | ||
} | ||
// Synthesise a click event, with an extra attribute so it can be tracked | ||
clickEvent = document.createEvent('MouseEvents'); | ||
clickEvent.initMouseEvent('click', true, true, window, 1, touch.screenX, touch.screenY, touch.clientX, touch.clientY, false, false, false, false, 0, null); | ||
clickEvent.animaClick = true; | ||
targetElement.dispatchEvent(clickEvent); | ||
}, | ||
needClick: function(target){ | ||
switch (target.nodeName.toLowerCase()) { | ||
break; | ||
case 'label': | ||
case 'video': | ||
return true; | ||
} | ||
// Don't send a synthetic click to disabled inputs (issue #62) | ||
case 'button': | ||
case 'select': | ||
case 'textarea': | ||
if (target.disabled) { | ||
return true; | ||
} | ||
return false; | ||
}, | ||
focus: function(targetElement){ | ||
var length; | ||
break; | ||
case 'input': | ||
// on iOS 7, some input elements (e.g. date datetime) throw a vague TypeError on setSelectionRange. These elements don't have an integer value for the selectionStart and selectionEnd properties, but unfortunately that can't be used for detection because accessing the properties also throws a TypeError. Just check the type instead. Filed as Apple bug #15122724. | ||
if (deviceIsIOS && targetElement.setSelectionRange && targetElement.type.indexOf('date') !== 0 && targetElement.type !== 'time') { | ||
length = targetElement.value.length; | ||
targetElement.setSelectionRange(length, length); | ||
} else { | ||
targetElement.focus(); | ||
} | ||
}, | ||
needFocus: function(target){ | ||
switch (target.nodeName.toLowerCase()) { | ||
case 'textarea': | ||
case 'select': //实测android下select也需要 | ||
return true; | ||
case 'input': | ||
switch (target.type) { | ||
case 'button': | ||
case 'checkbox': | ||
case 'file': | ||
case 'image': | ||
case 'radio': | ||
case 'submit': | ||
return false; | ||
// File inputs need real clicks on iOS 6 due to a browser bug (issue #68) | ||
if ((deviceIsIOS && target.type === 'file') || target.disabled) { | ||
return true; | ||
} | ||
// No point in attempting to focus disabled inputs | ||
return !target.disabled && !target.readOnly; | ||
default: | ||
return false; | ||
break; | ||
case 'label': | ||
case 'video': | ||
return true; | ||
} | ||
}, | ||
updateScrollParent: function(targetElement){ | ||
var scrollParent, parentElement; | ||
scrollParent = targetElement.yoctoTouchScrollParent; | ||
return false; | ||
}, | ||
focus: function(targetElement){ | ||
var length; | ||
// Attempt to discover whether the target element is contained within a scrollable layer. Re-check if the | ||
// target element was moved to another parent. | ||
if (!scrollParent || !scrollParent.contains(targetElement)) { | ||
parentElement = targetElement; | ||
do { | ||
if (parentElement.scrollHeight > parentElement.offsetHeight) { | ||
scrollParent = parentElement; | ||
targetElement.yoctoTouchScrollParent = parentElement; | ||
break; | ||
// on iOS 7, some input elements (e.g. date datetime) throw a vague TypeError on setSelectionRange. These elements don't have an integer value for the selectionStart and selectionEnd properties, but unfortunately that can't be used for detection because accessing the properties also throws a TypeError. Just check the type instead. Filed as Apple bug #15122724. | ||
if (deviceIsIOS && targetElement.setSelectionRange && targetElement.type.indexOf('date') !== 0 && targetElement.type !== 'time') { | ||
length = targetElement.value.length; | ||
targetElement.setSelectionRange(length, length); | ||
} else { | ||
targetElement.focus(); | ||
} | ||
}, | ||
needFocus: function(target){ | ||
switch (target.nodeName.toLowerCase()) { | ||
case 'textarea': | ||
case 'select': //实测android下select也需要 | ||
return true; | ||
case 'input': | ||
switch (target.type) { | ||
case 'button': | ||
case 'checkbox': | ||
case 'file': | ||
case 'image': | ||
case 'radio': | ||
case 'submit': | ||
return false; | ||
} | ||
// No point in attempting to focus disabled inputs | ||
return !target.disabled && !target.readOnly; | ||
default: | ||
return false; | ||
} | ||
}, | ||
updateScrollParent: function(targetElement){ | ||
var scrollParent, parentElement; | ||
parentElement = parentElement.parentElement; | ||
} while (parentElement); | ||
} | ||
scrollParent = targetElement.yoctoTouchScrollParent; | ||
// Always update the scroll top tracker if possible. | ||
if (scrollParent) { | ||
scrollParent.yoctoTouchLastScrollTop = scrollParent.scrollTop; | ||
} | ||
}, | ||
findControl: function(labelElement){ | ||
// Fast path for newer browsers supporting the HTML5 control attribute | ||
if (labelElement.control !== undefined) { | ||
return labelElement.control; | ||
} | ||
// Attempt to discover whether the target element is contained within a scrollable layer. Re-check if the | ||
// target element was moved to another parent. | ||
if (!scrollParent || !scrollParent.contains(targetElement)) { | ||
parentElement = targetElement; | ||
do { | ||
if (parentElement.scrollHeight > parentElement.offsetHeight) { | ||
scrollParent = parentElement; | ||
targetElement.yoctoTouchScrollParent = parentElement; | ||
break; | ||
} | ||
// All browsers under test that support touch events also support the HTML5 htmlFor attribute | ||
if (labelElement.htmlFor) { | ||
return document.getElementById(labelElement.htmlFor); | ||
} | ||
parentElement = parentElement.parentElement; | ||
} while (parentElement); | ||
} | ||
// If no for attribute exists, attempt to retrieve the first labellable descendant element | ||
// the list of which is defined here: http://www.w3.org/TR/html5/forms.html#category-label | ||
return labelElement.querySelector('button, input:not([type=hidden]), keygen, meter, output, progress, select, textarea'); | ||
}, | ||
touchHasMoved: function(event){ | ||
var touch = event.changedTouches[0], boundary = yoctoTouch.touchBoundary; | ||
// Always update the scroll top tracker if possible. | ||
if (scrollParent) { | ||
scrollParent.yoctoTouchLastScrollTop = scrollParent.scrollTop; | ||
} | ||
}, | ||
findControl: function(labelElement){ | ||
// Fast path for newer browsers supporting the HTML5 control attribute | ||
if (labelElement.control !== undefined) { | ||
return labelElement.control; | ||
} | ||
if (Math.abs(touch.pageX - yoctoTouch.touchStartX) > boundary || Math.abs(touch.pageY - yoctoTouch.touchStartY) > boundary) { | ||
return true; | ||
} | ||
// All browsers under test that support touch events also support the HTML5 htmlFor attribute | ||
if (labelElement.htmlFor) { | ||
return document.getElementById(labelElement.htmlFor); | ||
} | ||
return false; | ||
} | ||
}; | ||
// If no for attribute exists, attempt to retrieve the first labellable descendant element | ||
// the list of which is defined here: http://www.w3.org/TR/html5/forms.html#category-label | ||
return labelElement.querySelector('button, input:not([type=hidden]), keygen, meter, output, progress, select, textarea'); | ||
}, | ||
touchHasMoved: function(event){ | ||
var touch = event.changedTouches[0], boundary = yoctoTouch.touchBoundary; | ||
Gesture.tap = { | ||
events: ['tap'], | ||
handler: { | ||
touchstart: function(event){ | ||
var targetElement, touch, selection; | ||
// Ignore multiple touches, otherwise pinch-to-zoom is prevented if both fingers are on the yoctoTouch element (issue #111). | ||
if (event.targetTouches.length > 1) { | ||
if (Math.abs(touch.pageX - yoctoTouch.touchStartX) > boundary || Math.abs(touch.pageY - yoctoTouch.touchStartY) > boundary) { | ||
return true; | ||
} | ||
targetElement = event.target; | ||
touch = event.targetTouches[0]; | ||
return false; | ||
} | ||
}; | ||
if (deviceIsIOS) { | ||
Gesture.tap = { | ||
events: ['tap'], | ||
handler: { | ||
touchstart: function(event){ | ||
var targetElement, touch, selection; | ||
// Only trusted events will deselect text on iOS (issue #49) | ||
selection = window.getSelection(); | ||
if (selection.rangeCount && !selection.isCollapsed) { | ||
// Ignore multiple touches, otherwise pinch-to-zoom is prevented if both fingers are on the yoctoTouch element (issue #111). | ||
if (event.targetTouches.length > 1) { | ||
return true; | ||
} | ||
targetElement = event.target; | ||
touch = event.targetTouches[0]; | ||
if (touch.identifier && touch.identifier === yoctoTouch.lastTouchIdentifier) { | ||
event.preventDefault(); | ||
return false; | ||
} | ||
if (deviceIsIOS) { | ||
yoctoTouch.lastTouchIdentifier = touch.identifier; | ||
// Only trusted events will deselect text on iOS (issue #49) | ||
selection = window.getSelection(); | ||
if (selection.rangeCount && !selection.isCollapsed) { | ||
return true; | ||
} | ||
yoctoTouch.updateScrollParent(targetElement); | ||
} | ||
yoctoTouch.trackingClick = true; | ||
yoctoTouch.trackingClickStart = event.timeStamp; | ||
yoctoTouch.targetElement = targetElement; | ||
if (touch.identifier && touch.identifier === yoctoTouch.lastTouchIdentifier) { | ||
event.preventDefault(); | ||
return false; | ||
} | ||
// var now = Date.now(), | ||
// delta = now - (yoctoTouch.last || now); | ||
yoctoTouch.lastTouchIdentifier = touch.identifier; | ||
// if(delta > 0 && delta <= 250){ | ||
// yoctoTouch.isDouleTap = true; | ||
// } | ||
yoctoTouch.updateScrollParent(targetElement); | ||
} | ||
// yoctoTouch.last = now; | ||
yoctoTouch.trackingClick = true; | ||
yoctoTouch.trackingClickStart = event.timeStamp; | ||
yoctoTouch.targetElement = targetElement; | ||
yoctoTouch.touchStartX = touch.pageX; | ||
yoctoTouch.touchStartY = touch.pageY; | ||
// var now = Date.now(), | ||
// delta = now - (yoctoTouch.last || now); | ||
// Prevent phantom clicks on fast double-tap (issue #36) | ||
if ((event.timeStamp - yoctoTouch.lastClickTime) < yoctoTouch.tapDelay) { | ||
event.preventDefault(); | ||
} | ||
// if(delta > 0 && delta <= 250){ | ||
// yoctoTouch.isDouleTap = true; | ||
// } | ||
return true; | ||
}, | ||
touchmove: function(event){ | ||
if (!yoctoTouch.trackingClick) { | ||
return true; | ||
} | ||
// yoctoTouch.last = now; | ||
// If the touch has moved, cancel the click tracking | ||
if (yoctoTouch.targetElement !== event.target || yoctoTouch.touchHasMoved(event)) { | ||
yoctoTouch.trackingClick = false; | ||
yoctoTouch.targetElement = null; | ||
} | ||
yoctoTouch.touchStartX = touch.pageX; | ||
yoctoTouch.touchStartY = touch.pageY; | ||
return true; | ||
}, | ||
touchend: function(event){ | ||
var forElement, trackingClickStart, targetTagName, scrollParent, touch, targetElement = yoctoTouch.targetElement; | ||
// Prevent phantom clicks on fast double-tap (issue #36) | ||
if ((event.timeStamp - yoctoTouch.lastClickTime) < yoctoTouch.tapDelay) { | ||
event.preventDefault(); | ||
} | ||
if (!yoctoTouch.trackingClick) { | ||
return true; | ||
} | ||
}, | ||
touchmove: function(event){ | ||
if (!yoctoTouch.trackingClick) { | ||
return true; | ||
} | ||
// Prevent phantom clicks on fast double-tap (issue #36) | ||
if ((event.timeStamp - yoctoTouch.lastClickTime) < yoctoTouch.tapDelay) { | ||
yoctoTouch.cancelNextClick = true; | ||
// If the touch has moved, cancel the click tracking | ||
if (yoctoTouch.targetElement !== event.target || yoctoTouch.touchHasMoved(event)) { | ||
yoctoTouch.trackingClick = false; | ||
yoctoTouch.targetElement = null; | ||
} | ||
return true; | ||
} | ||
}, | ||
touchend: function(event){ | ||
var forElement, trackingClickStart, targetTagName, scrollParent, touch, targetElement = yoctoTouch.targetElement; | ||
// Reset to prevent wrong click cancel on input (issue #156). | ||
yoctoTouch.cancelNextClick = false; | ||
if (!yoctoTouch.trackingClick) { | ||
return true; | ||
} | ||
yoctoTouch.lastClickTime = event.timeStamp; | ||
// Prevent phantom clicks on fast double-tap (issue #36) | ||
if ((event.timeStamp - yoctoTouch.lastClickTime) < yoctoTouch.tapDelay) { | ||
yoctoTouch.cancelNextClick = true; | ||
return true; | ||
} | ||
trackingClickStart = yoctoTouch.trackingClickStart; | ||
yoctoTouch.trackingClick = false; | ||
yoctoTouch.trackingClickStart = 0; | ||
// Reset to prevent wrong click cancel on input (issue #156). | ||
yoctoTouch.cancelNextClick = false; | ||
targetTagName = targetElement.tagName.toLowerCase(); | ||
if (targetTagName === 'label') { | ||
forElement = yoctoTouch.findControl(targetElement); | ||
if (forElement) { | ||
yoctoTouch.focus(targetElement); | ||
if (deviceIsAndroid) { | ||
yoctoTouch.lastClickTime = event.timeStamp; | ||
trackingClickStart = yoctoTouch.trackingClickStart; | ||
yoctoTouch.trackingClick = false; | ||
yoctoTouch.trackingClickStart = 0; | ||
targetTagName = targetElement.tagName.toLowerCase(); | ||
if (targetTagName === 'label') { | ||
forElement = yoctoTouch.findControl(targetElement); | ||
if (forElement) { | ||
yoctoTouch.focus(targetElement); | ||
if (deviceIsAndroid) { | ||
return false; | ||
} | ||
targetElement = forElement; | ||
} | ||
} else if (yoctoTouch.needFocus(targetElement)) { | ||
// Case 1: If the touch started a while ago (best guess is 100ms based on tests for issue #36) then focus will be triggered anyway. Return early and unset the target element reference so that the subsequent click will be allowed through. | ||
// Case 2: Without this exception for input elements tapped when the document is contained in an iframe, then any inputted text won't be visible even though the value attribute is updated as the user types (issue #37). | ||
if ((event.timeStamp - trackingClickStart) > 100 || (deviceIsIOS && window.top !== window && targetTagName === 'input')) { | ||
yoctoTouch.targetElement = null; | ||
return false; | ||
} | ||
targetElement = forElement; | ||
} | ||
} else if (yoctoTouch.needFocus(targetElement)) { | ||
// Case 1: If the touch started a while ago (best guess is 100ms based on tests for issue #36) then focus will be triggered anyway. Return early and unset the target element reference so that the subsequent click will be allowed through. | ||
// Case 2: Without this exception for input elements tapped when the document is contained in an iframe, then any inputted text won't be visible even though the value attribute is updated as the user types (issue #37). | ||
if ((event.timeStamp - trackingClickStart) > 100 || (deviceIsIOS && window.top !== window && targetTagName === 'input')) { | ||
yoctoTouch.targetElement = null; | ||
return false; | ||
} | ||
yoctoTouch.focus(targetElement); | ||
// input类型元素阻止默认事件 | ||
event.preventDefault(); | ||
yoctoTouch.focus(targetElement); | ||
yoctoTouch.sendClick(targetElement, event); | ||
// input类型元素阻止默认事件 | ||
event.preventDefault(); | ||
// Select elements need the event to go through on iOS 4, otherwise the selector menu won't open. | ||
// Also this breaks opening selects when VoiceOver is active on iOS6, iOS7 (and possibly others) | ||
// if (!deviceIsIOS || targetTagName !== 'select') { | ||
// yoctoTouch.targetElement = null; | ||
// event.preventDefault(); | ||
// } | ||
yoctoTouch.sendClick(targetElement, event); | ||
return false; | ||
} | ||
// Select elements need the event to go through on iOS 4, otherwise the selector menu won't open. | ||
// Also this breaks opening selects when VoiceOver is active on iOS6, iOS7 (and possibly others) | ||
// if (!deviceIsIOS || targetTagName !== 'select') { | ||
// yoctoTouch.targetElement = null; | ||
// event.preventDefault(); | ||
// } | ||
if (deviceIsIOS) { | ||
return false; | ||
} | ||
// Don't send a synthetic click event if the target element is contained within a parent layer that was scrolled | ||
// and this tap is being used to stop the scrolling (usually initiated by a fling - issue #42). | ||
scrollParent = targetElement.yoctoTouchScrollParent; | ||
if (scrollParent && scrollParent.yoctoTouchLastScrollTop !== scrollParent.scrollTop) { | ||
return true; | ||
} | ||
} | ||
if (deviceIsIOS) { | ||
// Don't send a synthetic click event if the target element is contained within a parent layer that was scrolled | ||
// and this tap is being used to stop the scrolling (usually initiated by a fling - issue #42). | ||
scrollParent = targetElement.yoctoTouchScrollParent; | ||
if (scrollParent && scrollParent.yoctoTouchLastScrollTop !== scrollParent.scrollTop) { | ||
return true; | ||
// Prevent the actual click from going though - unless the target node is marked as requiring | ||
// real clicks or if it is in the whitelist in which case only non-programmatic clicks are permitted. | ||
if (!yoctoTouch.needClick(targetElement)) { | ||
event.preventDefault(); | ||
yoctoTouch.sendClick(targetElement, event); | ||
} | ||
} | ||
// Prevent the actual click from going though - unless the target node is marked as requiring | ||
// real clicks or if it is in the whitelist in which case only non-programmatic clicks are permitted. | ||
if (!yoctoTouch.needClick(targetElement)) { | ||
event.preventDefault(); | ||
yoctoTouch.sendClick(targetElement, event); | ||
return false; | ||
}, | ||
touchcancel: function(event){ | ||
yoctoTouch.trackingClick = false; | ||
yoctoTouch.targetElement = null; | ||
} | ||
return false; | ||
}, | ||
touchcancel: function(event){ | ||
yoctoTouch.trackingClick = false; | ||
yoctoTouch.targetElement = null; | ||
} | ||
} | ||
} | ||
Gesture.init('tap') | ||
Gesture.init('tap') | ||
var ua = navigator.userAgent.toLowerCase(), | ||
os = /\bandroid[ \/-]?([0-9.x]+)?/.exec(ua), | ||
isXiaoMi = ua.indexOf('xiaomi') > -1, | ||
isMeizu = (/m[0-9]{3}/gi).test(ua); | ||
var ua = navigator.userAgent.toLowerCase(), | ||
os = /\bandroid[ \/-]?([0-9.x]+)?/.exec(ua), | ||
isXiaoMi = ua.indexOf('xiaomi') > -1, | ||
isMeizu = (/m[0-9]{3}/gi).test(ua); | ||
if(!(deviceIsAndroid && (isXiaoMi || isMeizu) && parseFloat(os[1], 10) < 4.4)){ //解决安卓4.4以下preventDefault失效的问题 | ||
document.addEventListener('click', function(event) { | ||
if(!(deviceIsAndroid && (isXiaoMi || isMeizu) && parseFloat(os[1], 10) < 4.4)){ //解决安卓4.4以下preventDefault失效的问题 | ||
document.addEventListener('click', function(event) { | ||
if (!event.animaClick) {//阻止浏览器自己触发的点击事件 | ||
if (event.stopImmediatePropagation) { | ||
event.stopImmediatePropagation(); | ||
} else { | ||
// Part of the hack for browsers that don't support Event#stopImmediatePropagation (e.g. Android 2) | ||
event.propagationStopped = true; | ||
} | ||
if (event.stopImmediatePropagation) { | ||
event.stopImmediatePropagation(); | ||
} else { | ||
// Part of the hack for browsers that don't support Event#stopImmediatePropagation (e.g. Android 2) | ||
event.propagationStopped = true; | ||
} | ||
event.stopPropagation() | ||
event.preventDefault() | ||
event.stopPropagation() | ||
event.preventDefault() | ||
return false | ||
return false | ||
} | ||
}, true) | ||
}, true) | ||
} | ||
$.gestures = Gesture; | ||
} | ||
$.gestures = Gesture; | ||
module.exports = $; |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 1 instance in 1 package
1
0
15820
6
288
1
+ Addedanima-yocto-core@1.1.0(transitive)
+ Addedanima-yocto-event@1.0.1(transitive)
- Removedanima-yocto-core@1.0.0(transitive)
- Removedanima-yocto-event@1.0.0(transitive)
Updatedanima-yocto-core@1.1.0
Updatedanima-yocto-event@1.0.1