├── .gitignore ├── .npmignore ├── LICENSE.md ├── README.md ├── demo.js ├── index.html ├── index.js └── package.json /.gitignore: -------------------------------------------------------------------------------- 1 | bower_components 2 | node_modules 3 | *.log 4 | .DS_Store 5 | bundle.js 6 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | bower_components 2 | node_modules 3 | *.log 4 | .DS_Store 5 | bundle.js 6 | test 7 | demo.js 8 | test.js 9 | demo/ 10 | .npmignore 11 | index.html 12 | LICENSE.md -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | Copyright (c) 2015 Jam3 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 17 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 18 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 19 | OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE 20 | OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # touches 2 | 3 | [](http://github.com/badges/stability-badges) 4 | 5 | [(click for demo)](http://jam3.github.io/touches/) - [(source)](demo.js) 6 | 7 | Normalizes touch and mouse events to provide a simpler interface. Simplest case: 8 | 9 | ```js 10 | //get mouse/touch events on window 11 | require('touches')() 12 | .on('start', mouseDown) //-> mousedown / touchstart 13 | .on('move', mouseMove) //-> mousemove / touchmove 14 | .on('end', mouseEnd) //-> mouseup / touchend 15 | 16 | ... 17 | ``` 18 | 19 | A common pattern for drag events is to listen for events on a parent element (like the `window`), and use a different element as the `target` for client offset calculation. The second argument to the event listener is a `[x, y]` vector representing the calculated client offset (relative to top left of target element). 20 | 21 | ```js 22 | var touch = require('touches') 23 | touch(window, { target: button }) 24 | .on('move', function (ev, position) { 25 | console.log('relative pos', position[0], position[1]) 26 | }) 27 | ``` 28 | 29 | Another common pattern, especially with drag events, is filtering touch input to a single finger. Below; the events will only get fired for the first finger placed on the screen. Subsequent fingers will be ignored until after the first finger has been lifted. 30 | 31 | ```js 32 | touch(window, { target: button, filtered: true }) 33 | .on('start', dragStart) 34 | .on('move', dragMove) 35 | .on('end', dragEnd) 36 | ``` 37 | 38 | ## Usage 39 | 40 | [](https://www.npmjs.com/package/touches) 41 | 42 | #### `emitter = require('touches')([element, opt])` 43 | 44 | Creates a new drag emitter by attaching listeners to `element`, which defaults to `window`. 45 | 46 | The `opt` options can be: 47 | 48 | - `target` the element to use when calculating the `position` parameter passed to event listeners. The clientX/clientY of the event will be relative to this target 49 | - `filtered` whether the touch events should be filtered to the first placed finger 50 | - `type` can be a string, either `"mouse"` or `"touch"` if listening to only one or the other event is desired. If any other value, will listen for both mouse and touch. 51 | - `preventSimulated` (default `true`) if true, prevents simulated touch events by running `ev.preventDefault()` on `'touchend'` events 52 | 53 | 54 | If the events are not filtered, the `position` for an event will be the first changed touch associated with the `target`. 55 | 56 | #### `emitter.disable()` 57 | 58 | Disables the events associated with this emitter by removing them from the DOM element. Returns the emitter for chaining. 59 | 60 | #### `emitter.enable()` 61 | 62 | Enables the events associated with this emitter by adding them to the DOM element. The emitter is enabled by default. Returns the emitter for chaining. 63 | 64 | #### `emitter.target` 65 | 66 | The current target for position offset calculation. 67 | 68 | #### `emitter.on('start', listener)` 69 | #### `emitter.on('move', listener)` 70 | #### `emitter.on('end', listener)` 71 | 72 | The mousedown/touchstart, mousemove/touchmove, and mouseup/touchend events, respectively. Listeners are called with two parameters: `(ev, position)` where `ev` is the event and `position` is an `[x, y]` array of the client offset, relative to the target's top left. 73 | 74 | ## demo 75 | 76 | To run the demo from source, first `git clone` this repo, then: 77 | 78 | ```sh 79 | cd touches 80 | npm install 81 | npm start 82 | ``` 83 | 84 | And open `localhost:9966` in your browser. 85 | 86 | To generate a distribution bundle: 87 | 88 | ```sh 89 | npm run build 90 | ``` 91 | 92 | ## License 93 | 94 | MIT, see [LICENSE.md](http://github.com/Jam3/touches/blob/master/LICENSE.md) for details. 95 | -------------------------------------------------------------------------------- /demo.js: -------------------------------------------------------------------------------- 1 | var touches = require('./') 2 | var css = require('dom-css') 3 | var xtend = require('xtend') 4 | 5 | require('domready')(function () { 6 | var body = document.body 7 | 8 | // create a simple box element 9 | var div = create() 10 | div.textContent = 'drag me!' 11 | body.appendChild(div) 12 | 13 | var child = create({ left: 250, background: 'red' }) 14 | body.appendChild(child) 15 | 16 | // start listening for drag events on window 17 | // but use the div as our target element for position 18 | var dragging = false 19 | touches(window, { target: div, filtered: true }) 20 | .on('start', function (ev, pos) { 21 | ev.preventDefault() 22 | dragging = within(pos, div) 23 | if (dragging) write('start', pos) 24 | }) 25 | .on('end', function (ev, pos) { 26 | if (dragging) write('end', pos) 27 | dragging = false 28 | }) 29 | .on('move', function (ev, pos) { 30 | if (dragging) write('move', pos) 31 | }) 32 | 33 | function write (msg, pos) { 34 | div.textContent = [msg, pos.map(Math.round).join(', ')].join(' ') 35 | } 36 | }) 37 | 38 | function within (pos, element) { 39 | var rect = element.getBoundingClientRect() 40 | return pos[0] >= 0 && pos[1] >= 0 && 41 | pos[0] < rect.width && pos[1] < rect.height 42 | } 43 | 44 | function create (opt) { 45 | var div = document.createElement('div') 46 | css(div, xtend({ 47 | position: 'absolute', 48 | top: 20, 49 | left: 20, 50 | background: 'gray', 51 | width: 200, 52 | height: 200, 53 | color: 'white', 54 | fontSize: '30px', 55 | lineHeight: '200px', 56 | textAlign: 'center' 57 | }, opt)) 58 | return div 59 | } 60 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 | 6 |