├── .gitignore ├── README.md ├── bower.json ├── package.json └── unipointer.js /.gitignore: -------------------------------------------------------------------------------- 1 | bower_components/ 2 | node_modules/ 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Deprecated 2 | 3 | Unipointer code has been merged into [Unidragger v3](https://github.com/metafizzy/unidragger). Unipointer will no longer be maintained as its own package. 4 | 5 | # Unipointer 6 | 7 | Base class for doing one thing with pointer event 8 | 9 | Used with [Unidragger](https://github.com/metafizzy/unidragger) 10 | 11 | ## Install 12 | 13 | Bower: `bower install unipointer` 14 | 15 | npm: `npm install unipointer` 16 | 17 | ## Usage 18 | 19 | ``` js 20 | // create new class 21 | function PointerFun( elem ) { 22 | this.element = elem; 23 | // binds mousedown/touchstart/pointerdown event 24 | this._bindStartEvent( this.element, true ); 25 | } 26 | // inherit Unipointer 27 | PointerFun.prototype = new Unipointer(); 28 | 29 | // overwrite public pointer methods 30 | PointerFun.prototype.pointerDown = function( event, pointer ) { 31 | console.log('pointer down'); 32 | }; 33 | 34 | PointerFun.prototype.pointerMove = function( event, pointer ) { 35 | console.log('pointer move'); 36 | }; 37 | 38 | PointerFun.prototype.pointerUp = function( event, pointer ) { 39 | console.log('pointer up'); 40 | }; 41 | 42 | PointerFun.prototype.pointerCancel = function( event, pointer ) { 43 | console.log('pointer cancel'); 44 | }; 45 | 46 | // triggered on pointerUp and pointerCancel 47 | PointerFun.prototype.pointerDone = function( event, pointer ) { 48 | console.log('pointer done'); 49 | }; 50 | ``` 51 | 52 | --- 53 | 54 | MIT license 55 | 56 | By [Metafizzy](https://metafizzy.co) 57 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "unipointer", 3 | "main": "unipointer.js", 4 | "dependencies": { 5 | "ev-emitter": "^1.0.1" 6 | }, 7 | "homepage": "https://github.com/metafizzy/unipointer", 8 | "authors": [ 9 | "David DeSandro " 10 | ], 11 | "description": "Do one thing with one pointer", 12 | "moduleType": [ 13 | "amd", 14 | "globals", 15 | "node" 16 | ], 17 | "keywords": [ 18 | "pointer", 19 | "touch", 20 | "mouse" 21 | ], 22 | "license": "MIT", 23 | "ignore": [ 24 | "**/.*", 25 | "node_modules", 26 | "bower_components", 27 | "test", 28 | "tests", 29 | "package.json" 30 | ] 31 | } 32 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "unipointer", 3 | "version": "2.4.0", 4 | "description": "Do one thing with one pointer", 5 | "main": "unipointer.js", 6 | "dependencies": { 7 | "ev-emitter": "^1.0.1" 8 | }, 9 | "scripts": { 10 | "test": "echo \"Error: no test specified\" && exit 1" 11 | }, 12 | "repository": { 13 | "type": "git", 14 | "url": "git://github.com/metafizzy/unipointer.git" 15 | }, 16 | "keywords": [ 17 | "pointer", 18 | "touch", 19 | "mouse", 20 | "browser", 21 | "DOM" 22 | ], 23 | "author": "David DeSandro", 24 | "license": "MIT", 25 | "bugs": { 26 | "url": "https://github.com/metafizzy/unipointer/issues" 27 | }, 28 | "homepage": "https://github.com/metafizzy/unipointer" 29 | } 30 | -------------------------------------------------------------------------------- /unipointer.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Unipointer v2.4.0 3 | * base class for doing one thing with pointer event 4 | * MIT license 5 | */ 6 | 7 | /*jshint browser: true, undef: true, unused: true, strict: true */ 8 | 9 | ( function( window, factory ) { 10 | // universal module definition 11 | /* jshint strict: false */ /*global define, module, require */ 12 | if ( typeof define == 'function' && define.amd ) { 13 | // AMD 14 | define( [ 15 | 'ev-emitter/ev-emitter' 16 | ], function( EvEmitter ) { 17 | return factory( window, EvEmitter ); 18 | }); 19 | } else if ( typeof module == 'object' && module.exports ) { 20 | // CommonJS 21 | module.exports = factory( 22 | window, 23 | require('ev-emitter') 24 | ); 25 | } else { 26 | // browser global 27 | window.Unipointer = factory( 28 | window, 29 | window.EvEmitter 30 | ); 31 | } 32 | 33 | }( window, function factory( window, EvEmitter ) { 34 | 35 | 'use strict'; 36 | 37 | function noop() {} 38 | 39 | function Unipointer() {} 40 | 41 | // inherit EvEmitter 42 | var proto = Unipointer.prototype = Object.create( EvEmitter.prototype ); 43 | 44 | proto.bindStartEvent = function( elem ) { 45 | this._bindStartEvent( elem, true ); 46 | }; 47 | 48 | proto.unbindStartEvent = function( elem ) { 49 | this._bindStartEvent( elem, false ); 50 | }; 51 | 52 | /** 53 | * Add or remove start event 54 | * @param {Boolean} isAdd - remove if falsey 55 | */ 56 | proto._bindStartEvent = function( elem, isAdd ) { 57 | // munge isAdd, default to true 58 | isAdd = isAdd === undefined ? true : isAdd; 59 | var bindMethod = isAdd ? 'addEventListener' : 'removeEventListener'; 60 | 61 | // default to mouse events 62 | var startEvent = 'mousedown'; 63 | if ( 'ontouchstart' in window ) { 64 | // HACK prefer Touch Events as you can preventDefault on touchstart to 65 | // disable scroll in iOS & mobile Chrome metafizzy/flickity#1177 66 | startEvent = 'touchstart'; 67 | } else if ( window.PointerEvent ) { 68 | // Pointer Events 69 | startEvent = 'pointerdown'; 70 | } 71 | elem[ bindMethod ]( startEvent, this ); 72 | }; 73 | 74 | // trigger handler methods for events 75 | proto.handleEvent = function( event ) { 76 | var method = 'on' + event.type; 77 | if ( this[ method ] ) { 78 | this[ method ]( event ); 79 | } 80 | }; 81 | 82 | // returns the touch that we're keeping track of 83 | proto.getTouch = function( touches ) { 84 | for ( var i=0; i < touches.length; i++ ) { 85 | var touch = touches[i]; 86 | if ( touch.identifier == this.pointerIdentifier ) { 87 | return touch; 88 | } 89 | } 90 | }; 91 | 92 | // ----- start event ----- // 93 | 94 | proto.onmousedown = function( event ) { 95 | // dismiss clicks from right or middle buttons 96 | var button = event.button; 97 | if ( button && ( button !== 0 && button !== 1 ) ) { 98 | return; 99 | } 100 | this._pointerDown( event, event ); 101 | }; 102 | 103 | proto.ontouchstart = function( event ) { 104 | this._pointerDown( event, event.changedTouches[0] ); 105 | }; 106 | 107 | proto.onpointerdown = function( event ) { 108 | this._pointerDown( event, event ); 109 | }; 110 | 111 | /** 112 | * pointer start 113 | * @param {Event} event 114 | * @param {Event or Touch} pointer 115 | */ 116 | proto._pointerDown = function( event, pointer ) { 117 | // dismiss right click and other pointers 118 | // button = 0 is okay, 1-4 not 119 | if ( event.button || this.isPointerDown ) { 120 | return; 121 | } 122 | 123 | this.isPointerDown = true; 124 | // save pointer identifier to match up touch events 125 | this.pointerIdentifier = pointer.pointerId !== undefined ? 126 | // pointerId for pointer events, touch.indentifier for touch events 127 | pointer.pointerId : pointer.identifier; 128 | 129 | this.pointerDown( event, pointer ); 130 | }; 131 | 132 | proto.pointerDown = function( event, pointer ) { 133 | this._bindPostStartEvents( event ); 134 | this.emitEvent( 'pointerDown', [ event, pointer ] ); 135 | }; 136 | 137 | // hash of events to be bound after start event 138 | var postStartEvents = { 139 | mousedown: [ 'mousemove', 'mouseup' ], 140 | touchstart: [ 'touchmove', 'touchend', 'touchcancel' ], 141 | pointerdown: [ 'pointermove', 'pointerup', 'pointercancel' ], 142 | }; 143 | 144 | proto._bindPostStartEvents = function( event ) { 145 | if ( !event ) { 146 | return; 147 | } 148 | // get proper events to match start event 149 | var events = postStartEvents[ event.type ]; 150 | // bind events to node 151 | events.forEach( function( eventName ) { 152 | window.addEventListener( eventName, this ); 153 | }, this ); 154 | // save these arguments 155 | this._boundPointerEvents = events; 156 | }; 157 | 158 | proto._unbindPostStartEvents = function() { 159 | // check for _boundEvents, in case dragEnd triggered twice (old IE8 bug) 160 | if ( !this._boundPointerEvents ) { 161 | return; 162 | } 163 | this._boundPointerEvents.forEach( function( eventName ) { 164 | window.removeEventListener( eventName, this ); 165 | }, this ); 166 | 167 | delete this._boundPointerEvents; 168 | }; 169 | 170 | // ----- move event ----- // 171 | 172 | proto.onmousemove = function( event ) { 173 | this._pointerMove( event, event ); 174 | }; 175 | 176 | proto.onpointermove = function( event ) { 177 | if ( event.pointerId == this.pointerIdentifier ) { 178 | this._pointerMove( event, event ); 179 | } 180 | }; 181 | 182 | proto.ontouchmove = function( event ) { 183 | var touch = this.getTouch( event.changedTouches ); 184 | if ( touch ) { 185 | this._pointerMove( event, touch ); 186 | } 187 | }; 188 | 189 | /** 190 | * pointer move 191 | * @param {Event} event 192 | * @param {Event or Touch} pointer 193 | * @private 194 | */ 195 | proto._pointerMove = function( event, pointer ) { 196 | this.pointerMove( event, pointer ); 197 | }; 198 | 199 | // public 200 | proto.pointerMove = function( event, pointer ) { 201 | this.emitEvent( 'pointerMove', [ event, pointer ] ); 202 | }; 203 | 204 | // ----- end event ----- // 205 | 206 | 207 | proto.onmouseup = function( event ) { 208 | this._pointerUp( event, event ); 209 | }; 210 | 211 | proto.onpointerup = function( event ) { 212 | if ( event.pointerId == this.pointerIdentifier ) { 213 | this._pointerUp( event, event ); 214 | } 215 | }; 216 | 217 | proto.ontouchend = function( event ) { 218 | var touch = this.getTouch( event.changedTouches ); 219 | if ( touch ) { 220 | this._pointerUp( event, touch ); 221 | } 222 | }; 223 | 224 | /** 225 | * pointer up 226 | * @param {Event} event 227 | * @param {Event or Touch} pointer 228 | * @private 229 | */ 230 | proto._pointerUp = function( event, pointer ) { 231 | this._pointerDone(); 232 | this.pointerUp( event, pointer ); 233 | }; 234 | 235 | // public 236 | proto.pointerUp = function( event, pointer ) { 237 | this.emitEvent( 'pointerUp', [ event, pointer ] ); 238 | }; 239 | 240 | // ----- pointer done ----- // 241 | 242 | // triggered on pointer up & pointer cancel 243 | proto._pointerDone = function() { 244 | this._pointerReset(); 245 | this._unbindPostStartEvents(); 246 | this.pointerDone(); 247 | }; 248 | 249 | proto._pointerReset = function() { 250 | // reset properties 251 | this.isPointerDown = false; 252 | delete this.pointerIdentifier; 253 | }; 254 | 255 | proto.pointerDone = noop; 256 | 257 | // ----- pointer cancel ----- // 258 | 259 | proto.onpointercancel = function( event ) { 260 | if ( event.pointerId == this.pointerIdentifier ) { 261 | this._pointerCancel( event, event ); 262 | } 263 | }; 264 | 265 | proto.ontouchcancel = function( event ) { 266 | var touch = this.getTouch( event.changedTouches ); 267 | if ( touch ) { 268 | this._pointerCancel( event, touch ); 269 | } 270 | }; 271 | 272 | /** 273 | * pointer cancel 274 | * @param {Event} event 275 | * @param {Event or Touch} pointer 276 | * @private 277 | */ 278 | proto._pointerCancel = function( event, pointer ) { 279 | this._pointerDone(); 280 | this.pointerCancel( event, pointer ); 281 | }; 282 | 283 | // public 284 | proto.pointerCancel = function( event, pointer ) { 285 | this.emitEvent( 'pointerCancel', [ event, pointer ] ); 286 | }; 287 | 288 | // ----- ----- // 289 | 290 | // utility function for getting x/y coords from event 291 | Unipointer.getPointerPoint = function( pointer ) { 292 | return { 293 | x: pointer.pageX, 294 | y: pointer.pageY 295 | }; 296 | }; 297 | 298 | // ----- ----- // 299 | 300 | return Unipointer; 301 | 302 | })); 303 | --------------------------------------------------------------------------------