forceify
Version:
Simple, yet powerful touch-force handler
1 lines • 8.4 kB
JavaScript
!function(e){"function"==typeof define&&define.amd?define([],e):"undefined"!=typeof module&&module.exports?module.exports=e():"undefined"!=typeof exports?(exports.default=e(),exports.__esModule=!0):"undefined"!=typeof window&&window.document?(window.Forceify=e(),window.Forceify.__esModule=!0):(this.Forceify=e(),this.Forceify.__esModule=!0)}(function(){let e=[],t={},s=Date.now(),i="undefined"!=typeof requestAnimationFrame?requestAnimationFrame:e=>setTimeout(()=>e(Date.now()-s),50),o="undefined"!=typeof cancelAnimationFrame?cancelAnimationFrame:e=>clearTimeout(e);"object"!=typeof performance||performance.now||(performance.now=(()=>Date.now()-s));let n=()=>"undefined"!=typeof performance&&performance.now?performance.now():Date.now()-s,r="undefined"!=typeof global?global:"undefined"!=typeof window?window:"undefined"!=typeof exports?exports:this;function a(e,t){return null==e?t:e}i(function t(s){i(t);let o=0;for(;o<e.length;){e[o].update(s)?o++:e.splice(o,1)}});let h=0;class u{constructor(e,t,s){this._queueID=e,this._onUpdate=null,this._duration=200,this._delayTime=0,this._startTime=null,this._id=h++,this.startValue=0,this.currentValue={force:0,target:t},this.__self=s,this.endValue=1,this.callElem=t}duration(e){return this._duration=e,this}start(){const{_queueID:s,currentValue:i}=this;let o=t[s];if(o){let t,s=0;for(;t=o.shift();){e.indexOf(t)>-1&&e.splice(s,1)}}else o=t[s]=[];return this.startValue=i.force,this.endValue=1,o.push(this),e.push(this),this._startTime=n()+this._delayTime,this}delay(e){return this._delayTime=e,this}onUpdate(e){return this._onUpdate=e,this}restart(t){let{_delayTime:s,currentValue:i}=this;return-1===e.indexOf(this)?this.start():this._startTime=n()+s,t&&(this.startValue=i.force,this.endValue=0),this}update(e){let{_startTime:t,_duration:s,_onUpdate:i,currentValue:o,startValue:n,endValue:r,callElem:a,__self:h}=this;if(e<t)return!0;let u=(e-t)/s;return u=u>1?1:u,o.force=void 0!==h.__force&&0!==h.__force&&1!==h.__force?h.__force:n+(r-n)*u,i&&i.call(a,o),1!==u}}let l="undefined"!=typeof navigator?navigator:{userAgent:"",maxTouchPoints:0,msMaxTouchPoints:0},c=l.userAgent,d=-1!==c.indexOf("; CPU")&&-1!==c.indexOf(" like Mac"),f=r.document?r.document:{},_=f.body&&"ontouchend"in f.body||r.DocumentTouch||l.maxTouchPoints>0||l.msMaxTouchPoints>0,m=f.body&&"ontouchforcechange"in f.body&&d;return class{constructor(e,t={}){let s=0;return s=e.forceifyQueueId?e.forceifyQueueId:e.forceifyQueueId=Math.floor(Date.now()+1e3*Math.random()),this.id=s,this._callback=null,this.el=e,this._pressDuration=a(t.pressDuration,200),this._leaveDurationTolerance=a(t.leaveDurationTolerance,.35),this._leaveDuration=this._pressDuration*this._leaveDurationTolerance,this._delay=a(t.delay,0),this._eventPress=null,this._eventLeave=null,this._eventUp=null,this._checkResult=null,this._useSameDurInLeave=a(t.useSameDurInLeave,!1),this._resetOnLeave=a(t.resetOnLeave,!0),this.el=e,this.polyfill=a(t.polyfill,!0),this._touchTicks=0,this.tick=null,this}getEnv(){return this._checkResult}resetOnLeave(e=!0){return this._resetOnLeave=e,this}useLongPressEqualDuration(e=!0){return this._useSameDurInLeave=e,this}setLongPressLeaveTolerance(e){return this._leaveDurationTolerance=e,this._leaveDuration=this._pressDuration*e,this}setLongPressDelay(e){return this._delay=e,this}setLongPressDuration(e){return this._pressDuration=e,this._leaveDuration=e*this._leaveDurationTolerance,this}onForce(e){return this._callback=e,this.init()}on(e,t,s){return r.addEventListener&&this.el.addEventListener(e,t,s),this}off(e,t,s){return r.removeEventListener&&this.el.removeEventListener(e,t,s),this}preventTouchCallout(){const e=this.el,t=["webkitTouchCallout","MozTouchCallout","msTouchCallout","touchCallout","webkitUserSelect","MozUserSelect","msUserSelect","userSelect","webkitUserDrag","MozUserDrag","msUserDrag","userDrag"];for(let s of t)s in e.style&&(e.style[s]="none");const s=["webkitTouchAction","mozTouchAction","msTouchAction","touchAction"];for(let t of s)t in e.style&&(e.style[t]="manipulation");return this}handleForceChange(e){e.preventDefault&&e.preventDefault(),e.stopPropagation&&e.stopPropagation(),this._iterateOfHandleForceChange++;let t=void 0!==e.webkitForce?e.webkitForce>1?(e.webkitForce-1)/2:0:void 0!==e.force?e.force:void 0;if(t>.999?t=1:t<.003&&(t=0),void 0===t){let s=function(e,t,s){let i=s?e.touches:e.changedTouches;if(i){let s=0;const o=i.length;if(o>1&&e.scale&&1!==e.scale)return null;for(e&&e.preventDefault&&e.preventDefault();s<o;){if(i[s]&&i[s].target===t)return i[s];s++}}return null}(e,this.el,!0);s?void 0!==s.force?t=s.force:s.webkitForce&&(t=s.force):t=0}const{type:s}=e;return t>0&&t<1&&!this.nativeAPIExists&&("touchforcechange"===s||"webkitmouseforcechanged"===s)&&(this.nativeAPIExists=!0),e.force=t,this.__force=t,this._calledTimeout=!0,this._callback.call(this,e),!1}init(){const{el:e,polyfill:t}=this,s="onpointerdown"in e,n=this;let a,h,u;this._iterateOfHandleForceChange=0,this.handleForceChange=this.handleForceChange.bind(this);const l=e=>{const{__force:t}=this;let s=(1-Math.min((e-h)/this._leaveDuration,1))*t;s>0?a=i(l):0===s&&o(a),u.force=s,this.__force=s,this.handleForceChange(u)};if(this.preventTouchCallout(),!m&&"onwebkitmouseforcechanged"in e)return this.on("webkitmouseforcechanged",this.handleForceChange),this.on("mousedown",function e(){n.nativeAPIExists?n.off("mousedown",e):(0===n._touchTicks&&t&&(m=!1,n._eventPress="mousedown",n._eventLeave="mouseleave",n._eventUp="mouseup",n._checkResult=r.chrome?"macOS Chrome":"macOS Safari",n.isPressed=!0,n.handleSimulate(),n.handlePress()),n.off("mousedown",e))}),this.on("mouseup",function e(t){if(n.nativeAPIExists)n.off("mouseup",e);else{const{__force:s,_iterateOfHandleForceChange:o}=n;u=t,s>0&&o>1?(h=performance.now(),a=i(l)):n.off("mouseup",e)}}),this._checkResult="macOSForce",this;if(m){let e=()=>{this.nativeAPIExists?this.off("touchstart",e):(0===this._touchTicks&&t&&(m=!1,this._eventPress="touchstart",this._eventLeave="touchleave",this._eventUp="touchend",this._checkResult=r.chrome?"ChromeMobile":"Touch",this.isPressed=!0,this.handleSimulate(),this.handlePress()),this.off("touchstart",e))};const s=e=>{if(this.nativeAPIExists)this.off("touchend",s);else{const{__force:t,_iterateOfHandleForceChange:o}=this;u=e,t>0&&o>1?(h=performance.now(),a=i(l)):this.off("touchend",s)}};return this.on("touchforcechange",this.handleForceChange),this.on("touchstart",e),this.on("touchend",s),this._checkResult="iOSForce",this}return t&&s?(this._eventPress="pointerdown",this._eventLeave="pointerleave",this._eventUp="pointerup",this._checkResult=r.chrome?"Chrome":"Modern"):t&&"onmspointerdown"in e?(this._eventPress="mspointerdown",this._eventLeave="mspointerleave",this._eventUp="mspointerup",this._checkResult=r.chrome?"Chrome":"Modern"):t&&_?(this._eventPress="touchstart",this._eventLeave="touchleave",this._eventUp="touchend",this._checkResult=r.chrome?"ChromeMobile":"Touch"):t&&"onmousedown"in e&&(this._eventPress="mousedown",this._eventLeave="mouseup",this._eventUp="mouseleave",this._checkResult=r.chrome?"Chrome":"Desktop"),this.isPressed=!1,this.handleSimulate()}handleLeave(){let{_simulatedCallback:e,_useSameDurInLeave:t,_pressDuration:s,_leaveDuration:i}=this;return e&&e.duration(t?s:i).delay(0).restart(!0),this}handlePress(){let{_simulatedCallback:e,_pressDuration:t,_delay:s,nativeAPIExists:i}=this;return e&&!i&&e.duration(t).delay(s).start(),this}handleSimulate(){let{_simulatedCallback:e,_eventPress:t,_eventUp:s,_eventLeave:i,isPressed:o,_callback:n,id:r,el:a}=this;e||(e=this._simulatedCallback=new u(r,a,this)),e&&e.onUpdate(n);const h=e=>{if(!this.nativeAPIExists)return o||m||e.type===t&&(e.preventDefault&&e.preventDefault(),e.stopPropagation&&e.stopPropagation(),this.handlePress(),o=this.isPressed=!0),!1;this.off(t,h)};this.on(t,h);const l=e=>this.nativeAPIExists?(this.off(s,l),void this.off(i,l)):(o&&(e.type===s||e.type===i&&this._resetOnLeave)&&(e.preventDefault&&e.preventDefault(),e.stopPropagation&&e.stopPropagation(),this.handleLeave(),o=this.isPressed=!1),!1);return this.on("contextmenu",e=>e.preventDefault()),this.on(s,l),this.on(i,l),this}isChrome(){return"Chrome"===this._checkResult||"ChromeMobile"===this._checkResult}isMacOSForceTouch(){return"macOSForce"===this._checkResult}isIOS3DTouch(){return"iOSForce"===this._checkResult}isTouch(){return"Touch"===this._checkResult}isMouse(){return"Desktop"===this._checkResult}}});