├── GAME.zip ├── LICENSE ├── README.md ├── cover.png ├── index.html ├── ingame.png ├── js-dos-api-3.0.js ├── js-dos.js ├── node_modules └── hammerjs │ ├── .bowerrc │ ├── .jscsrc │ ├── .jshintrc │ ├── .npmignore │ ├── .travis.yml │ ├── CHANGELOG.md │ ├── CONTRIBUTING.md │ ├── Gruntfile.coffee │ ├── LICENSE.md │ ├── README.md │ ├── bower.json │ ├── changelog.js │ ├── component.json │ ├── hammer.js │ ├── hammer.min.js │ ├── hammer.min.js.map │ ├── hammer.min.map │ ├── package.json │ ├── src │ ├── expose.js │ ├── hammer.js │ ├── hammer.prefix.js │ ├── hammer.suffix.js │ ├── input.js │ ├── input │ │ ├── mouse.js │ │ ├── pointerevent.js │ │ ├── singletouch.js │ │ ├── touch.js │ │ └── touchmouse.js │ ├── manager.js │ ├── recognizer.js │ ├── recognizers │ │ ├── attribute.js │ │ ├── pan.js │ │ ├── pinch.js │ │ ├── press.js │ │ ├── rotate.js │ │ ├── swipe.js │ │ └── tap.js │ ├── touchaction.js │ └── utils.js │ └── tests │ ├── manual │ ├── assets │ │ └── style.css │ ├── compute_touch_action.html │ ├── input.html │ ├── log.html │ ├── multiple.html │ ├── nested.html │ ├── simulator-googlemaps.html │ ├── simulator.html │ ├── touchaction.html │ └── visual.html │ └── unit │ ├── assets │ ├── blanket.js │ ├── jquery.min.js │ ├── lodash.compat.js │ ├── qunit.css │ ├── qunit.js │ └── utils.js │ ├── gestures │ ├── test_pan.js │ ├── test_pinch.js │ └── test_swipe.js │ ├── index.html │ ├── test_enable.js │ ├── test_events.js │ ├── test_gestures.js │ ├── test_hammer.js │ ├── test_jquery_plugin.js │ ├── test_multiple_taps.js │ ├── test_nested_gesture_recognizers.js │ ├── test_propagation_bubble.js │ ├── test_require_failure.js │ ├── test_simultaneous_recognition.js │ └── test_utils.js └── package.json /GAME.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mad4j/loderunner-in-a-box/b7a8da177360ad70e24b291bc021912bddfe6419/GAME.zip -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Lode Runner(-in-a-box) 2 | 3 | Play MS-DOS Lode Runner on modern browsers or mobile screens [HERE](https://mad4j.github.io/loderunner-in-a-box/) 4 | 5 | ![cover](cover.png) 6 | 7 | Use the following commands 8 | 9 | | Action | Key | Key Alt | Gesture | 10 | |--------|---------|-------------|-----------------------| 11 | | Up | Keypad8 | Arrow Up | Pan Up | 12 | | Down | Keypad2 | Arrow Down | Pan Down | 13 | | Left | Keypad4 | Arrow Left | Pan Left | 14 | | Right | Keypad6 | Arrow Right | Pan Right | 15 | | Stop | Keypad5 | Space | Tap near center | 16 | | FireL | Keypad7 | Page Up | Tap near left corner | 17 | | FireR | Keypad9 | Page Down | Tap near right corner | 18 | | Menu | Esc | - | - | 19 | 20 | 21 | Made possible using: 22 | 23 | * [DosBox](https://www.dosbox.com/) 24 | * [Em-DosBox](https://github.com/dreamlayers/em-dosbox) 25 | * [JS-Dos](https://js-dos.com/) 26 | * [Emscripten](https://github.com/kripken/emscripten/wiki) 27 | * [HammerJS](https://js-dos.com/) 28 | 29 | see [LICENSE](LICENSE) file. 30 | -------------------------------------------------------------------------------- /cover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mad4j/loderunner-in-a-box/b7a8da177360ad70e24b291bc021912bddfe6419/cover.png -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Lode Runner in a Box 7 | 8 | 9 | 10 | 11 | 25 | 26 | 27 | 28 | 29 |
30 |
31 |
32 | 33 |
34 | 35 | 188 | 189 | 190 | 191 | -------------------------------------------------------------------------------- /ingame.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mad4j/loderunner-in-a-box/b7a8da177360ad70e24b291bc021912bddfe6419/ingame.png -------------------------------------------------------------------------------- /node_modules/hammerjs/.bowerrc: -------------------------------------------------------------------------------- 1 | { 2 | "json": "bower.json" 3 | } -------------------------------------------------------------------------------- /node_modules/hammerjs/.jscsrc: -------------------------------------------------------------------------------- 1 | { 2 | "excludeFiles": [ 3 | "*.js", 4 | "tests/**/assets", 5 | "node_modules/**" 6 | ], 7 | "requireCurlyBraces": [ 8 | "if", 9 | "else", 10 | "for", 11 | "while", 12 | "do", 13 | "try", 14 | "catch" 15 | ], 16 | "requireOperatorBeforeLineBreak": true, 17 | "requireCamelCaseOrUpperCaseIdentifiers": true, 18 | "maximumLineLength": { 19 | "value": 120, 20 | "allowComments": true, 21 | "allowRegex": true 22 | }, 23 | "validateIndentation": 4, 24 | "validateQuoteMarks": "'", 25 | "disallowMultipleLineStrings": true, 26 | "disallowMixedSpacesAndTabs": true, 27 | "disallowTrailingWhitespace": true, 28 | "disallowSpaceAfterPrefixUnaryOperators": true, 29 | "requireSpaceAfterKeywords": [ 30 | "if", 31 | "else", 32 | "for", 33 | "while", 34 | "do", 35 | "switch", 36 | "return", 37 | "try", 38 | "catch" 39 | ], 40 | "requireSpaceBeforeBinaryOperators": [ 41 | "=", 42 | "+=", 43 | "-=", 44 | "*=", 45 | "/=", 46 | "%=", 47 | "<<=", 48 | ">>=", 49 | ">>>=", 50 | "&=", 51 | "|=", 52 | "^=", 53 | "+=", 54 | "+", 55 | "-", 56 | "*", 57 | "/", 58 | "%", 59 | "<<", 60 | ">>", 61 | ">>>", 62 | "&", 63 | "|", 64 | "^", 65 | "&&", 66 | "||", 67 | "===", 68 | "==", 69 | ">=", 70 | "<=", 71 | "<", 72 | ">", 73 | "!=", 74 | "!==" 75 | ], 76 | "requireSpaceAfterBinaryOperators": true, 77 | "requireSpacesInConditionalExpression": true, 78 | "requireSpaceBeforeBlockStatements": true, 79 | "requireLineFeedAtFileEnd": true, 80 | "requireSpacesInFunctionExpression": { 81 | "beforeOpeningCurlyBrace": true 82 | }, 83 | "disallowSpacesInAnonymousFunctionExpression": { 84 | "beforeOpeningRoundBrace": true 85 | }, 86 | "disallowSpacesInsideObjectBrackets": "all", 87 | "disallowSpacesInsideArrayBrackets": "all", 88 | "disallowSpacesInsideParentheses": true, 89 | "validateJSDoc": { 90 | "checkParamNames": true, 91 | "requireParamTypes": true 92 | }, 93 | "disallowMultipleLineBreaks": true, 94 | "disallowNewlineBeforeBlockStatements": true 95 | } -------------------------------------------------------------------------------- /node_modules/hammerjs/.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "browser": true, 3 | "curly": true, 4 | "eqnull": true, 5 | "expr": true, 6 | "maxerr": 100, 7 | "freeze": true, 8 | "newcap": true, 9 | "node": true, 10 | "quotmark": "single", 11 | "strict": true, 12 | "sub": true, 13 | "trailing": true, 14 | "undef": true, 15 | "unused": true, 16 | "camelcase": true, 17 | "indent": 4, 18 | "validthis": true, 19 | "globals": { 20 | "define": false 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /node_modules/hammerjs/.npmignore: -------------------------------------------------------------------------------- 1 | # ide 2 | .idea 3 | .iml 4 | 5 | # node 6 | lib-cov 7 | *.seed 8 | *.log 9 | *.csv 10 | *.dat 11 | *.out 12 | *.pid 13 | *.gz 14 | 15 | pids 16 | logs 17 | results 18 | tests/build.js 19 | 20 | npm-debug.log 21 | node_modules 22 | -------------------------------------------------------------------------------- /node_modules/hammerjs/.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "0.10" 4 | 5 | sudo: false 6 | 7 | before_script: 8 | - npm install -g grunt-cli 9 | 10 | script: 11 | - grunt test-travis -------------------------------------------------------------------------------- /node_modules/hammerjs/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ### 2.0.6, 2015-12-23 4 | - Add Assign method and deprecate merge and extend ([#895](https://github.com/hammerjs/hammer.js/pull/895)[fc01eae](https://github.com/hammerjs/hammer.js/commit/fc01eaea678acc430c664eb374555fbe3d403bdd)) 5 | - Expose Hammer on window or self if either is defined to avoid issues when AMD is present but not used. ( [356f795](https://github.com/hammerjs/hammer.js/commit/356f7955b01f3679c29d6c45931679256b45036e)) 6 | - Add support for PointerEvent instead of MSPointerEvent if supported. ([#754](https://github.com/hammerjs/hammer.js/issues/754), [439c7a6](https://github.com/hammerjs/hammer.js/commit/439c7a6c46978ab387b4b8289399e904d1c49535)) 7 | - Fixed moz-prefix, prefix should be Moz not moz. ([3ea47f3](https://github.com/hammerjs/hammer.js/commit/3ea47f3aebadc9d3bb6bf52bc8402cad135ef8a9)) 8 | - Removed non-existant recognizer ([f1c2d3b](https://github.com/hammerjs/hammer.js/commit/f1c2d3bf05f530ae092ecfc2335fceeff0e9eec9)) 9 | - Fixed config leaking between instances([189098f](https://github.com/hammerjs/hammer.js/commit/189098ff7736f6ed2fce9a3d3e1f5a3afee085ba)) 10 | - Fixed gaps in gesture configs and update tests to match ([70c2902](https://github.com/hammerjs/hammer.js/commit/70c2902d773a750e92ce8c423f8a4165c07eab97)) 11 | - Fixed Manager off method ([#768](https://github.com/hammerjs/hammer.js/issues/768), [da49a27](https://github.com/hammerjs/hammer.js/commit/da49a2730779ecc3b4dd147cc418a0df7c70fad9)) 12 | - Added compatibility with requirejs optimizer namespaces ( [70075f2](https://github.com/hammerjs/hammer.js/commit/70075f2df1b855f7c6d8d3caac49b9276b88c8d6)) 13 | - Made touchaction test zoomable ( [50264a7](https://github.com/hammerjs/hammer.js/commit/50264a70251ca88bbaf7b666401e527eee616de5)) 14 | - Fixed preventing default when for `pan-x pan-y` case ( [95eaafa](https://github.com/hammerjs/hammer.js/commit/95eaafadad27bd1b25d20cf976811a451922f1c4)) 15 | - Fixed incorrect touch action pan direction ( [a81da57](https://github.com/hammerjs/hammer.js/commit/a81da57a82ebf37e695e7c443e4e2715e7f32856)) 16 | - Fixed combined pan-x pan-y to resolve to none ( [fdae07b](https://github.com/hammerjs/hammer.js/commit/fdae07bc2ba3c90aad28da6791b3d5df627bc612)) 17 | - Fixed inverted touch-action for pan recognizer ([#728](https://github.com/hammerjs/hammer.js/issues/728), [605bd3b](https://github.com/hammerjs/hammer.js/commit/605bd3beca780be91dd43f9da8b809d155a43d1a)) 18 | - Fixed dependency on non standard touch list ordering ([#610](https://github.com/hammerjs/hammer.js/issues/610), [#791](https://github.com/hammerjs/hammer.js/issues/791), [287720a](https://github.com/hammerjs/hammer.js/commit/287720a6e5067e7f28be8b8b3b266d22905361c4)) 19 | - Fixed swipe to not trigger after multitouch gesture ([#640](https://github.com/hammerjs/hammer.js/issues/640), [711d8a1](https://github.com/hammerjs/hammer.js/commit/711d8a1df1aa5057ecb536454a36257e3c0d6d91)) 20 | - Fixed swipe recognizer to use overall gesture direction and velocity ( [963fe69](https://github.com/hammerjs/hammer.js/commit/963fe697515273fee508414bc29e2656465cea55)) 21 | - Fixed getDirection returning reversed direction ( [e40dcde](https://github.com/hammerjs/hammer.js/commit/e40dcde43bdac7a74c8ce5c05a4f62121089cd91)) 22 | - Fixed detection of tap when multi touch gestures are present ( [c46cbba](https://github.com/hammerjs/hammer.js/commit/c46cbba1c2cbbf874b59913416858d9dae297e64)) 23 | - Fixed incorrect event order ([#824](https://github.com/hammerjs/hammer.js/issues/824), [92f2d76](https://github.com/hammerjs/hammer.js/commit/92f2d76188480d967e738a19cd508d0b94a31329)) 24 | - Fixed leaking options between recognizer instances ([#813](https://github.com/hammerjs/hammer.js/issues/813), [af32c9b](https://github.com/hammerjs/hammer.js/commit/af32c9bace3f04bb34bee852ff56a33cc8fc27cd)) 25 | - Fixed detection when element has no style attribute ( [5ca6d8c](https://github.com/hammerjs/hammer.js/commit/5ca6d8cbead02c71929a8073e95ddf98e11c0e06)) 26 | 27 | ### 2.0.4, 2014-09-28 28 | - Fix IE pointer issue. [#665](https://github.com/hammerjs/hammer.js/pull/665) 29 | - Fix multi-touch at different elements. [#668](https://github.com/hammerjs/hammer.js/pull/668) 30 | - Added experimental [single-user Touch input handler](src/input/singletouch.js). This to improve performance/ux when only a single user has to be supported. Plans are to release 2.1 with this as default, and a settings to enable the multi-user handler. 31 | 32 | ### 2.0.3, 2014-09-10 33 | - Manager.set improvements. 34 | - Fix requireFailure() call in Manager.options.recognizers. 35 | - Make DIRECTION_ALL for pan and swipe gestures less blocking. 36 | - Fix Swipe recognizer threshold option. 37 | - Expose the Input classes. 38 | - Added the option `inputClass` to set the used input handler. 39 | 40 | ### 2.0.2, 2014-07-26 41 | - Improved mouse and pointer-events input, now able to move outside the window. 42 | - Added the export name (`Hammer`) as an argument to the wrapper. 43 | - Add the option *experimental* `inputTarget` to change the element that receives the events. 44 | - Improved performance when only one touch being active. 45 | - Fixed the jumping deltaXY bug when going from single to multi-touch. 46 | - Improved velocity calculations. 47 | 48 | ### 2.0.1, 2014-07-15 49 | - Fix issue when no document.body is available 50 | - Added pressup event for the press recognizer 51 | - Removed alternative for Object.create 52 | 53 | ### 2.0.0, 2014-07-11 54 | - Full rewrite of the library. 55 | -------------------------------------------------------------------------------- /node_modules/hammerjs/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to Hammer.js 2 | 3 | Looking to contribute something to Hammer.js? **Here's how you can help.** 4 | 5 | 6 | ## Reporting issues 7 | 8 | We only accept issues that are bug reports or feature requests. Bugs must be 9 | isolated and reproducible problems that can be fixed within the Hammer.js. 10 | Please read the following guidelines before opening any issue. 11 | 12 | 1. [**Read the documentation**](https://hammerjs.github.io) 13 | 14 | 2. **Search for existing issues.** We get a lot of duplicate issues, and you'd 15 | help us out a lot by first checking if someone else has reported the same issue. 16 | Moreover, the issue may have already been resolved with a fix available. Also 17 | take a look if your problem is explained at the Wiki. 18 | 19 | 3. **Create an isolated and reproducible test case.** Be sure the problem exists 20 | in Hammer's code with a reduced test case that should be included in each bug 21 | report. 22 | 23 | 4. **Include a live example.** Make use of jsFiddle or jsBin to share your 24 | isolated test cases. Also, a screen capture would work, with tools like LICEcap. 25 | 26 | 5. **Share as much information as possible.** Include operating system and 27 | version, browser and version, version of Hammer.js, customized or vanilla build, 28 | etc. where appropriate. Also include steps to reproduce the bug. 29 | 30 | ## Pull requests 31 | 32 | 1. Changes must be done in `/src` files, never just the compiled files. Also, don't 33 | commit the compiled files. 34 | 35 | 2. Try not to pollute your pull request with unintended changes. Keep them simple 36 | and small 37 | 38 | 3. Try to share which browsers your code has been tested in before submitting a 39 | pull request 40 | 41 | 4. Write tests for your code, these can be found in `/tests`. 42 | -------------------------------------------------------------------------------- /node_modules/hammerjs/Gruntfile.coffee: -------------------------------------------------------------------------------- 1 | module.exports = (grunt) -> 2 | grunt.initConfig 3 | pkg: grunt.file.readJSON 'package.json' 4 | 5 | usebanner: 6 | taskName: 7 | options: 8 | position: 'top' 9 | banner: ' 10 | /*! <%= pkg.title || pkg.name %> - v<%= pkg.version %> - <%= grunt.template.today("yyyy-mm-dd") %>\n 11 | * <%= pkg.homepage %>\n 12 | *\n 13 | * Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author.name %>;\n 14 | * Licensed under the <%= pkg.license %> license */' 15 | linebreak: true 16 | files: 17 | src: ['./hammer.js','./hammer.min.js'] 18 | 19 | concat: 20 | build: 21 | src: [ 22 | 'src/hammer.prefix.js' 23 | 'src/utils.js' 24 | 'src/input.js' 25 | 'src/input/*.js' 26 | 'src/touchaction.js' 27 | 'src/recognizer.js' 28 | 'src/recognizers/*.js' 29 | 'src/hammer.js' 30 | 'src/manager.js' 31 | 'src/expose.js' 32 | 'src/hammer.suffix.js'] 33 | dest: 'hammer.js' 34 | 35 | uglify: 36 | min: 37 | options: 38 | report: 'gzip' 39 | sourceMap: 'hammer.min.map' 40 | files: 41 | 'hammer.min.js': ['hammer.js'] 42 | # special test build that exposes everything so it's testable 43 | test: 44 | options: 45 | wrap: "$H" 46 | comments: 'all' 47 | exportAll: true 48 | mangle: false 49 | beautify: true 50 | compress: 51 | global_defs: 52 | exportName: 'Hammer' 53 | files: 54 | 'tests/build.js': [ 55 | 'src/utils.js' 56 | 'src/input.js' 57 | 'src/input/*.js' 58 | 'src/touchaction.js' 59 | 'src/recognizer.js' 60 | 'src/recognizers/*.js' 61 | 'src/hammer.js' 62 | 'src/manager.js' 63 | 'src/expose.js'] 64 | 65 | 'string-replace': 66 | version: 67 | files: 68 | 'hammer.js': 'hammer.js' 69 | options: 70 | replacements: [ 71 | pattern: '{{PKG_VERSION}}' 72 | replacement: '<%= pkg.version %>' 73 | ] 74 | 75 | jshint: 76 | options: 77 | jshintrc: true 78 | build: 79 | src: ['hammer.js'] 80 | 81 | jscs: 82 | src: [ 83 | 'src/**/*.js', 84 | '!src/hammer.prefix.js', 85 | '!src/hammer.suffix.js' 86 | ] 87 | options: 88 | config: "./.jscsrc" 89 | force: true 90 | 91 | watch: 92 | scripts: 93 | files: ['src/**/*.js'] 94 | tasks: ['concat','string-replace','uglify','jshint','jscs'] 95 | options: 96 | interrupt: true 97 | 98 | connect: 99 | server: 100 | options: 101 | hostname: "0.0.0.0" 102 | port: 8000 103 | 104 | qunit: 105 | all: ['tests/unit/index.html'] 106 | 107 | 108 | # Load tasks 109 | grunt.loadNpmTasks 'grunt-contrib-concat' 110 | grunt.loadNpmTasks 'grunt-contrib-uglify' 111 | grunt.loadNpmTasks 'grunt-contrib-qunit' 112 | grunt.loadNpmTasks 'grunt-contrib-watch' 113 | grunt.loadNpmTasks 'grunt-contrib-jshint' 114 | grunt.loadNpmTasks 'grunt-contrib-connect' 115 | grunt.loadNpmTasks 'grunt-string-replace' 116 | grunt.loadNpmTasks 'grunt-banner' 117 | grunt.loadNpmTasks 'grunt-jscs' 118 | 119 | # Default task(s) 120 | grunt.registerTask 'default', ['connect', 'watch'] 121 | grunt.registerTask 'default-test', ['connect', 'uglify:test', 'watch'] 122 | grunt.registerTask 'build', ['concat', 'string-replace', 'uglify:min', 'usebanner', 'test'] 123 | grunt.registerTask 'test', ['jshint', 'jscs', 'uglify:test', 'qunit'] 124 | grunt.registerTask 'test-travis', ['build'] 125 | -------------------------------------------------------------------------------- /node_modules/hammerjs/LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (C) 2011-2014 by Jorik Tangelder (Eight Media) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /node_modules/hammerjs/README.md: -------------------------------------------------------------------------------- 1 | # Hammer.js 2.0.6 2 | 3 | [![Build Status](https://travis-ci.org/hammerjs/hammer.js.svg)](https://travis-ci.org/hammerjs/hammer.js) 4 | 5 | ## Support, Questions, and Collaboration 6 | 7 | [![Slack Status](https://hammerjs.herokuapp.com/badge.svg)](https://hammerjs.herokuapp.com/) 8 | 9 | ## Documentation 10 | 11 | Visit [hammerjs.github.io](http://hammerjs.github.io) for detailed documentation. 12 | 13 | ```js 14 | // get a reference to an element 15 | var stage = document.getElementById('stage'); 16 | 17 | // create a manager for that element 18 | var mc = new Hammer.Manager(stage); 19 | 20 | // create a recognizer 21 | var Rotate = new Hammer.Rotate(); 22 | 23 | // add the recognizer 24 | mc.add(Rotate); 25 | 26 | // subscribe to events 27 | mc.on('rotate', function(e) { 28 | // do something cool 29 | var rotation = Math.round(e.rotation); 30 | stage.style.transform = 'rotate('+rotation+'deg)'; 31 | }); 32 | ``` 33 | 34 | An advanced demo is available here: [http://codepen.io/runspired/full/ZQBGWd/](http://codepen.io/runspired/full/ZQBGWd/) 35 | 36 | 37 | ## Contributing 38 | 39 | Read the [contributing guidelines](./CONTRIBUTING.md). 40 | 41 | For PRs. 42 | 43 | - Use [Angular Style commit messages](https://github.com/angular/angular.js/blob/v1.4.8/CONTRIBUTING.md#commit) 44 | - Rebase your PR branch when necessary 45 | - If you add a feature or fix a bug, please add or fix any necessary tests. 46 | - If a new feature, open a docs PR to go with. 47 | 48 | ## Building 49 | 50 | You can get the pre-build versions from the Hammer.js website, or do this by yourself running 51 | `npm install -g grunt-cli && npm install && grunt build` 52 | -------------------------------------------------------------------------------- /node_modules/hammerjs/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hammerjs", 3 | "main": "hammer.js", 4 | "ignore": [ 5 | "tests", 6 | "src", 7 | ".bowerrc", 8 | ".gitignore", 9 | ".jscsrc", 10 | ".jshintrc", 11 | ".travis.yml", 12 | "component.json", 13 | "Gruntfile.coffee", 14 | "package.json" 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /node_modules/hammerjs/changelog.js: -------------------------------------------------------------------------------- 1 | var changelog = require( "changelogplease" ); 2 | var gittags = require( "git-tags" ).get( function( error, tags ) { 3 | if ( error ) { 4 | throw error 5 | } 6 | console.log( tags[ 1 ] + ".." + tags[ 0 ] ); 7 | var exclude = [ "Merge", "Whitespace", "Fixup", "Cleanup", "Formatting", "Ignore" ]; 8 | changelog( { 9 | ticketUrl: "https://github.com/hammerjs/hammer.js/issues/{id}", 10 | commitUrl: "https://github.com/hammerjs/hammerjs/commit/{id}", 11 | sort: false, 12 | repo: "./", 13 | committish: tags[ 1 ] + ".." + tags[ 0 ] 14 | }, function( error, log ) { 15 | if ( error ) { 16 | throw error; 17 | } 18 | log = parseLog( log ); 19 | console.log( log ); 20 | } ); 21 | function parseLog( log ) { 22 | var lines = log.split( "\n" ); 23 | var newLog = []; 24 | var log = []; 25 | var currentComponent; 26 | 27 | 28 | lines.shift(); 29 | lines.forEach( function( line ) { 30 | var newLine = parseLine( line ); 31 | if ( newLine ) { 32 | log.push( line ); 33 | } 34 | } ); 35 | var log = log.join( "\n" ); 36 | return log.replace( /\*/g, "-" ).replace( /__TICKETREF__,/g, "" ); 37 | } 38 | function parseLine( line ) { 39 | var parts = getParts( line ); 40 | 41 | if ( exclude.indexOf( parts.component ) > -1 ) { 42 | return false; 43 | } 44 | return parts; 45 | } 46 | function getParts( line ) { 47 | var parts = line.split( ":" ); 48 | var component = ""; 49 | var message; 50 | var commits = line.match( /\{\{([A-Za-z0-9 ]){0,99}\}\}/ ) 51 | 52 | if ( parts.length > 1 && parts[ 0 ].length <= 20 ) { 53 | component = parts[ 0 ]; 54 | parts.shift(); 55 | message = parts.join( ":" ); 56 | } else { 57 | parts = line.split( " " ); 58 | component = parts[ 1 ]; 59 | parts.shift(); 60 | message = parts.join( " " ); 61 | } 62 | 63 | if ( component ) { 64 | component = component.replace( /\* |,/, "" ); 65 | } 66 | return { 67 | component: component, 68 | message: message 69 | }; 70 | } 71 | } ); 72 | -------------------------------------------------------------------------------- /node_modules/hammerjs/component.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hammerjs", 3 | "version": "2.0.6", 4 | "main": "hammer.js", 5 | "scripts": [ 6 | "hammer.js" 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /node_modules/hammerjs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "_args": [ 3 | [ 4 | "hammerjs", 5 | "/mnt/c/Users/danie/Documents/GitHub/loderunner-in-a-box" 6 | ] 7 | ], 8 | "_from": "hammerjs@latest", 9 | "_id": "hammerjs@2.0.8", 10 | "_inCache": true, 11 | "_installable": true, 12 | "_location": "/hammerjs", 13 | "_nodeVersion": "4.3.1", 14 | "_npmOperationalInternal": { 15 | "host": "packages-12-west.internal.npmjs.com", 16 | "tmp": "tmp/hammerjs-2.0.8.tgz_1461341696692_0.5312051954679191" 17 | }, 18 | "_npmUser": { 19 | "email": "arschmitz@gmail.com", 20 | "name": "arschmitz" 21 | }, 22 | "_npmVersion": "2.14.12", 23 | "_phantomChildren": {}, 24 | "_requested": { 25 | "name": "hammerjs", 26 | "raw": "hammerjs", 27 | "rawSpec": "", 28 | "scope": null, 29 | "spec": "latest", 30 | "type": "tag" 31 | }, 32 | "_requiredBy": [ 33 | "/" 34 | ], 35 | "_resolved": "https://registry.npmjs.org/hammerjs/-/hammerjs-2.0.8.tgz", 36 | "_shasum": "04ef77862cff2bb79d30f7692095930222bf60f1", 37 | "_shrinkwrap": null, 38 | "_spec": "hammerjs", 39 | "_where": "/mnt/c/Users/danie/Documents/GitHub/loderunner-in-a-box", 40 | "author": { 41 | "email": "j.tangelder@gmail.com", 42 | "name": "Jorik Tangelder" 43 | }, 44 | "bugs": { 45 | "url": "https://github.com/hammerjs/hammer.js/issues" 46 | }, 47 | "contributors": [ 48 | { 49 | "name": "Alexander Schmitz", 50 | "email": "arschmitz@gmail.com" 51 | }, 52 | { 53 | "name": "Chris Thoburn" 54 | } 55 | ], 56 | "dependencies": {}, 57 | "description": "A javascript library for multi-touch gestures", 58 | "devDependencies": { 59 | "changelogplease": "^1.2.0", 60 | "git-tags": "^0.2.4", 61 | "grunt": "0.4.x", 62 | "grunt-banner": "^0.2.3", 63 | "grunt-contrib-concat": "0.4.x", 64 | "grunt-contrib-connect": "0.7.x", 65 | "grunt-contrib-jshint": "0.10.x", 66 | "grunt-contrib-qunit": "^0.5.1", 67 | "grunt-contrib-uglify": "0.7.x", 68 | "grunt-contrib-watch": "0.6.x", 69 | "grunt-jscs": "^0.8.0", 70 | "grunt-string-replace": "^0.2.7", 71 | "hammer-simulator": "git://github.com/hammerjs/simulator.git#master", 72 | "jquery-hammerjs": "2.0.x" 73 | }, 74 | "directories": {}, 75 | "dist": { 76 | "shasum": "04ef77862cff2bb79d30f7692095930222bf60f1", 77 | "tarball": "https://registry.npmjs.org/hammerjs/-/hammerjs-2.0.8.tgz" 78 | }, 79 | "engines": { 80 | "node": ">=0.8.0" 81 | }, 82 | "gitHead": "49731688380a91be07653ee2491ab48ece7952b5", 83 | "homepage": "http://hammerjs.github.io/", 84 | "keywords": [ 85 | "gestures", 86 | "touch" 87 | ], 88 | "license": "MIT", 89 | "main": "hammer.js", 90 | "maintainers": [ 91 | { 92 | "name": "arschmitz", 93 | "email": "arschmitz@gmail.com" 94 | }, 95 | { 96 | "name": "jtangelder", 97 | "email": "j.tangelder@gmail.com" 98 | } 99 | ], 100 | "name": "hammerjs", 101 | "optionalDependencies": {}, 102 | "readme": "ERROR: No README data found!", 103 | "repository": { 104 | "type": "git", 105 | "url": "git://github.com/hammerjs/hammer.js.git" 106 | }, 107 | "scripts": { 108 | "test": "grunt test" 109 | }, 110 | "title": "Hammer.JS", 111 | "version": "2.0.8" 112 | } 113 | -------------------------------------------------------------------------------- /node_modules/hammerjs/src/expose.js: -------------------------------------------------------------------------------- 1 | assign(Hammer, { 2 | INPUT_START: INPUT_START, 3 | INPUT_MOVE: INPUT_MOVE, 4 | INPUT_END: INPUT_END, 5 | INPUT_CANCEL: INPUT_CANCEL, 6 | 7 | STATE_POSSIBLE: STATE_POSSIBLE, 8 | STATE_BEGAN: STATE_BEGAN, 9 | STATE_CHANGED: STATE_CHANGED, 10 | STATE_ENDED: STATE_ENDED, 11 | STATE_RECOGNIZED: STATE_RECOGNIZED, 12 | STATE_CANCELLED: STATE_CANCELLED, 13 | STATE_FAILED: STATE_FAILED, 14 | 15 | DIRECTION_NONE: DIRECTION_NONE, 16 | DIRECTION_LEFT: DIRECTION_LEFT, 17 | DIRECTION_RIGHT: DIRECTION_RIGHT, 18 | DIRECTION_UP: DIRECTION_UP, 19 | DIRECTION_DOWN: DIRECTION_DOWN, 20 | DIRECTION_HORIZONTAL: DIRECTION_HORIZONTAL, 21 | DIRECTION_VERTICAL: DIRECTION_VERTICAL, 22 | DIRECTION_ALL: DIRECTION_ALL, 23 | 24 | Manager: Manager, 25 | Input: Input, 26 | TouchAction: TouchAction, 27 | 28 | TouchInput: TouchInput, 29 | MouseInput: MouseInput, 30 | PointerEventInput: PointerEventInput, 31 | TouchMouseInput: TouchMouseInput, 32 | SingleTouchInput: SingleTouchInput, 33 | 34 | Recognizer: Recognizer, 35 | AttrRecognizer: AttrRecognizer, 36 | Tap: TapRecognizer, 37 | Pan: PanRecognizer, 38 | Swipe: SwipeRecognizer, 39 | Pinch: PinchRecognizer, 40 | Rotate: RotateRecognizer, 41 | Press: PressRecognizer, 42 | 43 | on: addEventListeners, 44 | off: removeEventListeners, 45 | each: each, 46 | merge: merge, 47 | extend: extend, 48 | assign: assign, 49 | inherit: inherit, 50 | bindFn: bindFn, 51 | prefixed: prefixed 52 | }); 53 | 54 | // this prevents errors when Hammer is loaded in the presence of an AMD 55 | // style loader but by script tag, not by the loader. 56 | var freeGlobal = (typeof window !== 'undefined' ? window : (typeof self !== 'undefined' ? self : {})); // jshint ignore:line 57 | freeGlobal.Hammer = Hammer; 58 | 59 | if (typeof define === 'function' && define.amd) { 60 | define(function() { 61 | return Hammer; 62 | }); 63 | } else if (typeof module != 'undefined' && module.exports) { 64 | module.exports = Hammer; 65 | } else { 66 | window[exportName] = Hammer; 67 | } 68 | -------------------------------------------------------------------------------- /node_modules/hammerjs/src/hammer.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Simple way to create a manager with a default set of recognizers. 3 | * @param {HTMLElement} element 4 | * @param {Object} [options] 5 | * @constructor 6 | */ 7 | function Hammer(element, options) { 8 | options = options || {}; 9 | options.recognizers = ifUndefined(options.recognizers, Hammer.defaults.preset); 10 | return new Manager(element, options); 11 | } 12 | 13 | /** 14 | * @const {string} 15 | */ 16 | Hammer.VERSION = '{{PKG_VERSION}}'; 17 | 18 | /** 19 | * default settings 20 | * @namespace 21 | */ 22 | Hammer.defaults = { 23 | /** 24 | * set if DOM events are being triggered. 25 | * But this is slower and unused by simple implementations, so disabled by default. 26 | * @type {Boolean} 27 | * @default false 28 | */ 29 | domEvents: false, 30 | 31 | /** 32 | * The value for the touchAction property/fallback. 33 | * When set to `compute` it will magically set the correct value based on the added recognizers. 34 | * @type {String} 35 | * @default compute 36 | */ 37 | touchAction: TOUCH_ACTION_COMPUTE, 38 | 39 | /** 40 | * @type {Boolean} 41 | * @default true 42 | */ 43 | enable: true, 44 | 45 | /** 46 | * EXPERIMENTAL FEATURE -- can be removed/changed 47 | * Change the parent input target element. 48 | * If Null, then it is being set the to main element. 49 | * @type {Null|EventTarget} 50 | * @default null 51 | */ 52 | inputTarget: null, 53 | 54 | /** 55 | * force an input class 56 | * @type {Null|Function} 57 | * @default null 58 | */ 59 | inputClass: null, 60 | 61 | /** 62 | * Default recognizer setup when calling `Hammer()` 63 | * When creating a new Manager these will be skipped. 64 | * @type {Array} 65 | */ 66 | preset: [ 67 | // RecognizerClass, options, [recognizeWith, ...], [requireFailure, ...] 68 | [RotateRecognizer, {enable: false}], 69 | [PinchRecognizer, {enable: false}, ['rotate']], 70 | [SwipeRecognizer, {direction: DIRECTION_HORIZONTAL}], 71 | [PanRecognizer, {direction: DIRECTION_HORIZONTAL}, ['swipe']], 72 | [TapRecognizer], 73 | [TapRecognizer, {event: 'doubletap', taps: 2}, ['tap']], 74 | [PressRecognizer] 75 | ], 76 | 77 | /** 78 | * Some CSS properties can be used to improve the working of Hammer. 79 | * Add them to this method and they will be set when creating a new Manager. 80 | * @namespace 81 | */ 82 | cssProps: { 83 | /** 84 | * Disables text selection to improve the dragging gesture. Mainly for desktop browsers. 85 | * @type {String} 86 | * @default 'none' 87 | */ 88 | userSelect: 'none', 89 | 90 | /** 91 | * Disable the Windows Phone grippers when pressing an element. 92 | * @type {String} 93 | * @default 'none' 94 | */ 95 | touchSelect: 'none', 96 | 97 | /** 98 | * Disables the default callout shown when you touch and hold a touch target. 99 | * On iOS, when you touch and hold a touch target such as a link, Safari displays 100 | * a callout containing information about the link. This property allows you to disable that callout. 101 | * @type {String} 102 | * @default 'none' 103 | */ 104 | touchCallout: 'none', 105 | 106 | /** 107 | * Specifies whether zooming is enabled. Used by IE10> 108 | * @type {String} 109 | * @default 'none' 110 | */ 111 | contentZooming: 'none', 112 | 113 | /** 114 | * Specifies that an entire element should be draggable instead of its contents. Mainly for desktop browsers. 115 | * @type {String} 116 | * @default 'none' 117 | */ 118 | userDrag: 'none', 119 | 120 | /** 121 | * Overrides the highlight color shown when the user taps a link or a JavaScript 122 | * clickable element in iOS. This property obeys the alpha value, if specified. 123 | * @type {String} 124 | * @default 'rgba(0,0,0,0)' 125 | */ 126 | tapHighlightColor: 'rgba(0,0,0,0)' 127 | } 128 | }; 129 | -------------------------------------------------------------------------------- /node_modules/hammerjs/src/hammer.prefix.js: -------------------------------------------------------------------------------- 1 | (function(window, document, exportName, undefined) { 2 | 'use strict'; 3 | -------------------------------------------------------------------------------- /node_modules/hammerjs/src/hammer.suffix.js: -------------------------------------------------------------------------------- 1 | })(window, document, 'Hammer'); 2 | -------------------------------------------------------------------------------- /node_modules/hammerjs/src/input.js: -------------------------------------------------------------------------------- 1 | var MOBILE_REGEX = /mobile|tablet|ip(ad|hone|od)|android/i; 2 | 3 | var SUPPORT_TOUCH = ('ontouchstart' in window); 4 | var SUPPORT_POINTER_EVENTS = prefixed(window, 'PointerEvent') !== undefined; 5 | var SUPPORT_ONLY_TOUCH = SUPPORT_TOUCH && MOBILE_REGEX.test(navigator.userAgent); 6 | 7 | var INPUT_TYPE_TOUCH = 'touch'; 8 | var INPUT_TYPE_PEN = 'pen'; 9 | var INPUT_TYPE_MOUSE = 'mouse'; 10 | var INPUT_TYPE_KINECT = 'kinect'; 11 | 12 | var COMPUTE_INTERVAL = 25; 13 | 14 | var INPUT_START = 1; 15 | var INPUT_MOVE = 2; 16 | var INPUT_END = 4; 17 | var INPUT_CANCEL = 8; 18 | 19 | var DIRECTION_NONE = 1; 20 | var DIRECTION_LEFT = 2; 21 | var DIRECTION_RIGHT = 4; 22 | var DIRECTION_UP = 8; 23 | var DIRECTION_DOWN = 16; 24 | 25 | var DIRECTION_HORIZONTAL = DIRECTION_LEFT | DIRECTION_RIGHT; 26 | var DIRECTION_VERTICAL = DIRECTION_UP | DIRECTION_DOWN; 27 | var DIRECTION_ALL = DIRECTION_HORIZONTAL | DIRECTION_VERTICAL; 28 | 29 | var PROPS_XY = ['x', 'y']; 30 | var PROPS_CLIENT_XY = ['clientX', 'clientY']; 31 | 32 | /** 33 | * create new input type manager 34 | * @param {Manager} manager 35 | * @param {Function} callback 36 | * @returns {Input} 37 | * @constructor 38 | */ 39 | function Input(manager, callback) { 40 | var self = this; 41 | this.manager = manager; 42 | this.callback = callback; 43 | this.element = manager.element; 44 | this.target = manager.options.inputTarget; 45 | 46 | // smaller wrapper around the handler, for the scope and the enabled state of the manager, 47 | // so when disabled the input events are completely bypassed. 48 | this.domHandler = function(ev) { 49 | if (boolOrFn(manager.options.enable, [manager])) { 50 | self.handler(ev); 51 | } 52 | }; 53 | 54 | this.init(); 55 | 56 | } 57 | 58 | Input.prototype = { 59 | /** 60 | * should handle the inputEvent data and trigger the callback 61 | * @virtual 62 | */ 63 | handler: function() { }, 64 | 65 | /** 66 | * bind the events 67 | */ 68 | init: function() { 69 | this.evEl && addEventListeners(this.element, this.evEl, this.domHandler); 70 | this.evTarget && addEventListeners(this.target, this.evTarget, this.domHandler); 71 | this.evWin && addEventListeners(getWindowForElement(this.element), this.evWin, this.domHandler); 72 | }, 73 | 74 | /** 75 | * unbind the events 76 | */ 77 | destroy: function() { 78 | this.evEl && removeEventListeners(this.element, this.evEl, this.domHandler); 79 | this.evTarget && removeEventListeners(this.target, this.evTarget, this.domHandler); 80 | this.evWin && removeEventListeners(getWindowForElement(this.element), this.evWin, this.domHandler); 81 | } 82 | }; 83 | 84 | /** 85 | * create new input type manager 86 | * called by the Manager constructor 87 | * @param {Hammer} manager 88 | * @returns {Input} 89 | */ 90 | function createInputInstance(manager) { 91 | var Type; 92 | var inputClass = manager.options.inputClass; 93 | 94 | if (inputClass) { 95 | Type = inputClass; 96 | } else if (SUPPORT_POINTER_EVENTS) { 97 | Type = PointerEventInput; 98 | } else if (SUPPORT_ONLY_TOUCH) { 99 | Type = TouchInput; 100 | } else if (!SUPPORT_TOUCH) { 101 | Type = MouseInput; 102 | } else { 103 | Type = TouchMouseInput; 104 | } 105 | return new (Type)(manager, inputHandler); 106 | } 107 | 108 | /** 109 | * handle input events 110 | * @param {Manager} manager 111 | * @param {String} eventType 112 | * @param {Object} input 113 | */ 114 | function inputHandler(manager, eventType, input) { 115 | var pointersLen = input.pointers.length; 116 | var changedPointersLen = input.changedPointers.length; 117 | var isFirst = (eventType & INPUT_START && (pointersLen - changedPointersLen === 0)); 118 | var isFinal = (eventType & (INPUT_END | INPUT_CANCEL) && (pointersLen - changedPointersLen === 0)); 119 | 120 | input.isFirst = !!isFirst; 121 | input.isFinal = !!isFinal; 122 | 123 | if (isFirst) { 124 | manager.session = {}; 125 | } 126 | 127 | // source event is the normalized value of the domEvents 128 | // like 'touchstart, mouseup, pointerdown' 129 | input.eventType = eventType; 130 | 131 | // compute scale, rotation etc 132 | computeInputData(manager, input); 133 | 134 | // emit secret event 135 | manager.emit('hammer.input', input); 136 | 137 | manager.recognize(input); 138 | manager.session.prevInput = input; 139 | } 140 | 141 | /** 142 | * extend the data with some usable properties like scale, rotate, velocity etc 143 | * @param {Object} manager 144 | * @param {Object} input 145 | */ 146 | function computeInputData(manager, input) { 147 | var session = manager.session; 148 | var pointers = input.pointers; 149 | var pointersLength = pointers.length; 150 | 151 | // store the first input to calculate the distance and direction 152 | if (!session.firstInput) { 153 | session.firstInput = simpleCloneInputData(input); 154 | } 155 | 156 | // to compute scale and rotation we need to store the multiple touches 157 | if (pointersLength > 1 && !session.firstMultiple) { 158 | session.firstMultiple = simpleCloneInputData(input); 159 | } else if (pointersLength === 1) { 160 | session.firstMultiple = false; 161 | } 162 | 163 | var firstInput = session.firstInput; 164 | var firstMultiple = session.firstMultiple; 165 | var offsetCenter = firstMultiple ? firstMultiple.center : firstInput.center; 166 | 167 | var center = input.center = getCenter(pointers); 168 | input.timeStamp = now(); 169 | input.deltaTime = input.timeStamp - firstInput.timeStamp; 170 | 171 | input.angle = getAngle(offsetCenter, center); 172 | input.distance = getDistance(offsetCenter, center); 173 | 174 | computeDeltaXY(session, input); 175 | input.offsetDirection = getDirection(input.deltaX, input.deltaY); 176 | 177 | var overallVelocity = getVelocity(input.deltaTime, input.deltaX, input.deltaY); 178 | input.overallVelocityX = overallVelocity.x; 179 | input.overallVelocityY = overallVelocity.y; 180 | input.overallVelocity = (abs(overallVelocity.x) > abs(overallVelocity.y)) ? overallVelocity.x : overallVelocity.y; 181 | 182 | input.scale = firstMultiple ? getScale(firstMultiple.pointers, pointers) : 1; 183 | input.rotation = firstMultiple ? getRotation(firstMultiple.pointers, pointers) : 0; 184 | 185 | input.maxPointers = !session.prevInput ? input.pointers.length : ((input.pointers.length > 186 | session.prevInput.maxPointers) ? input.pointers.length : session.prevInput.maxPointers); 187 | 188 | computeIntervalInputData(session, input); 189 | 190 | // find the correct target 191 | var target = manager.element; 192 | if (hasParent(input.srcEvent.target, target)) { 193 | target = input.srcEvent.target; 194 | } 195 | input.target = target; 196 | } 197 | 198 | function computeDeltaXY(session, input) { 199 | var center = input.center; 200 | var offset = session.offsetDelta || {}; 201 | var prevDelta = session.prevDelta || {}; 202 | var prevInput = session.prevInput || {}; 203 | 204 | if (input.eventType === INPUT_START || prevInput.eventType === INPUT_END) { 205 | prevDelta = session.prevDelta = { 206 | x: prevInput.deltaX || 0, 207 | y: prevInput.deltaY || 0 208 | }; 209 | 210 | offset = session.offsetDelta = { 211 | x: center.x, 212 | y: center.y 213 | }; 214 | } 215 | 216 | input.deltaX = prevDelta.x + (center.x - offset.x); 217 | input.deltaY = prevDelta.y + (center.y - offset.y); 218 | } 219 | 220 | /** 221 | * velocity is calculated every x ms 222 | * @param {Object} session 223 | * @param {Object} input 224 | */ 225 | function computeIntervalInputData(session, input) { 226 | var last = session.lastInterval || input, 227 | deltaTime = input.timeStamp - last.timeStamp, 228 | velocity, velocityX, velocityY, direction; 229 | 230 | if (input.eventType != INPUT_CANCEL && (deltaTime > COMPUTE_INTERVAL || last.velocity === undefined)) { 231 | var deltaX = input.deltaX - last.deltaX; 232 | var deltaY = input.deltaY - last.deltaY; 233 | 234 | var v = getVelocity(deltaTime, deltaX, deltaY); 235 | velocityX = v.x; 236 | velocityY = v.y; 237 | velocity = (abs(v.x) > abs(v.y)) ? v.x : v.y; 238 | direction = getDirection(deltaX, deltaY); 239 | 240 | session.lastInterval = input; 241 | } else { 242 | // use latest velocity info if it doesn't overtake a minimum period 243 | velocity = last.velocity; 244 | velocityX = last.velocityX; 245 | velocityY = last.velocityY; 246 | direction = last.direction; 247 | } 248 | 249 | input.velocity = velocity; 250 | input.velocityX = velocityX; 251 | input.velocityY = velocityY; 252 | input.direction = direction; 253 | } 254 | 255 | /** 256 | * create a simple clone from the input used for storage of firstInput and firstMultiple 257 | * @param {Object} input 258 | * @returns {Object} clonedInputData 259 | */ 260 | function simpleCloneInputData(input) { 261 | // make a simple copy of the pointers because we will get a reference if we don't 262 | // we only need clientXY for the calculations 263 | var pointers = []; 264 | var i = 0; 265 | while (i < input.pointers.length) { 266 | pointers[i] = { 267 | clientX: round(input.pointers[i].clientX), 268 | clientY: round(input.pointers[i].clientY) 269 | }; 270 | i++; 271 | } 272 | 273 | return { 274 | timeStamp: now(), 275 | pointers: pointers, 276 | center: getCenter(pointers), 277 | deltaX: input.deltaX, 278 | deltaY: input.deltaY 279 | }; 280 | } 281 | 282 | /** 283 | * get the center of all the pointers 284 | * @param {Array} pointers 285 | * @return {Object} center contains `x` and `y` properties 286 | */ 287 | function getCenter(pointers) { 288 | var pointersLength = pointers.length; 289 | 290 | // no need to loop when only one touch 291 | if (pointersLength === 1) { 292 | return { 293 | x: round(pointers[0].clientX), 294 | y: round(pointers[0].clientY) 295 | }; 296 | } 297 | 298 | var x = 0, y = 0, i = 0; 299 | while (i < pointersLength) { 300 | x += pointers[i].clientX; 301 | y += pointers[i].clientY; 302 | i++; 303 | } 304 | 305 | return { 306 | x: round(x / pointersLength), 307 | y: round(y / pointersLength) 308 | }; 309 | } 310 | 311 | /** 312 | * calculate the velocity between two points. unit is in px per ms. 313 | * @param {Number} deltaTime 314 | * @param {Number} x 315 | * @param {Number} y 316 | * @return {Object} velocity `x` and `y` 317 | */ 318 | function getVelocity(deltaTime, x, y) { 319 | return { 320 | x: x / deltaTime || 0, 321 | y: y / deltaTime || 0 322 | }; 323 | } 324 | 325 | /** 326 | * get the direction between two points 327 | * @param {Number} x 328 | * @param {Number} y 329 | * @return {Number} direction 330 | */ 331 | function getDirection(x, y) { 332 | if (x === y) { 333 | return DIRECTION_NONE; 334 | } 335 | 336 | if (abs(x) >= abs(y)) { 337 | return x < 0 ? DIRECTION_LEFT : DIRECTION_RIGHT; 338 | } 339 | return y < 0 ? DIRECTION_UP : DIRECTION_DOWN; 340 | } 341 | 342 | /** 343 | * calculate the absolute distance between two points 344 | * @param {Object} p1 {x, y} 345 | * @param {Object} p2 {x, y} 346 | * @param {Array} [props] containing x and y keys 347 | * @return {Number} distance 348 | */ 349 | function getDistance(p1, p2, props) { 350 | if (!props) { 351 | props = PROPS_XY; 352 | } 353 | var x = p2[props[0]] - p1[props[0]], 354 | y = p2[props[1]] - p1[props[1]]; 355 | 356 | return Math.sqrt((x * x) + (y * y)); 357 | } 358 | 359 | /** 360 | * calculate the angle between two coordinates 361 | * @param {Object} p1 362 | * @param {Object} p2 363 | * @param {Array} [props] containing x and y keys 364 | * @return {Number} angle 365 | */ 366 | function getAngle(p1, p2, props) { 367 | if (!props) { 368 | props = PROPS_XY; 369 | } 370 | var x = p2[props[0]] - p1[props[0]], 371 | y = p2[props[1]] - p1[props[1]]; 372 | return Math.atan2(y, x) * 180 / Math.PI; 373 | } 374 | 375 | /** 376 | * calculate the rotation degrees between two pointersets 377 | * @param {Array} start array of pointers 378 | * @param {Array} end array of pointers 379 | * @return {Number} rotation 380 | */ 381 | function getRotation(start, end) { 382 | return getAngle(end[1], end[0], PROPS_CLIENT_XY) + getAngle(start[1], start[0], PROPS_CLIENT_XY); 383 | } 384 | 385 | /** 386 | * calculate the scale factor between two pointersets 387 | * no scale is 1, and goes down to 0 when pinched together, and bigger when pinched out 388 | * @param {Array} start array of pointers 389 | * @param {Array} end array of pointers 390 | * @return {Number} scale 391 | */ 392 | function getScale(start, end) { 393 | return getDistance(end[0], end[1], PROPS_CLIENT_XY) / getDistance(start[0], start[1], PROPS_CLIENT_XY); 394 | } 395 | -------------------------------------------------------------------------------- /node_modules/hammerjs/src/input/mouse.js: -------------------------------------------------------------------------------- 1 | var MOUSE_INPUT_MAP = { 2 | mousedown: INPUT_START, 3 | mousemove: INPUT_MOVE, 4 | mouseup: INPUT_END 5 | }; 6 | 7 | var MOUSE_ELEMENT_EVENTS = 'mousedown'; 8 | var MOUSE_WINDOW_EVENTS = 'mousemove mouseup'; 9 | 10 | /** 11 | * Mouse events input 12 | * @constructor 13 | * @extends Input 14 | */ 15 | function MouseInput() { 16 | this.evEl = MOUSE_ELEMENT_EVENTS; 17 | this.evWin = MOUSE_WINDOW_EVENTS; 18 | 19 | this.pressed = false; // mousedown state 20 | 21 | Input.apply(this, arguments); 22 | } 23 | 24 | inherit(MouseInput, Input, { 25 | /** 26 | * handle mouse events 27 | * @param {Object} ev 28 | */ 29 | handler: function MEhandler(ev) { 30 | var eventType = MOUSE_INPUT_MAP[ev.type]; 31 | 32 | // on start we want to have the left mouse button down 33 | if (eventType & INPUT_START && ev.button === 0) { 34 | this.pressed = true; 35 | } 36 | 37 | if (eventType & INPUT_MOVE && ev.which !== 1) { 38 | eventType = INPUT_END; 39 | } 40 | 41 | // mouse must be down 42 | if (!this.pressed) { 43 | return; 44 | } 45 | 46 | if (eventType & INPUT_END) { 47 | this.pressed = false; 48 | } 49 | 50 | this.callback(this.manager, eventType, { 51 | pointers: [ev], 52 | changedPointers: [ev], 53 | pointerType: INPUT_TYPE_MOUSE, 54 | srcEvent: ev 55 | }); 56 | } 57 | }); 58 | -------------------------------------------------------------------------------- /node_modules/hammerjs/src/input/pointerevent.js: -------------------------------------------------------------------------------- 1 | var POINTER_INPUT_MAP = { 2 | pointerdown: INPUT_START, 3 | pointermove: INPUT_MOVE, 4 | pointerup: INPUT_END, 5 | pointercancel: INPUT_CANCEL, 6 | pointerout: INPUT_CANCEL 7 | }; 8 | 9 | // in IE10 the pointer types is defined as an enum 10 | var IE10_POINTER_TYPE_ENUM = { 11 | 2: INPUT_TYPE_TOUCH, 12 | 3: INPUT_TYPE_PEN, 13 | 4: INPUT_TYPE_MOUSE, 14 | 5: INPUT_TYPE_KINECT // see https://twitter.com/jacobrossi/status/480596438489890816 15 | }; 16 | 17 | var POINTER_ELEMENT_EVENTS = 'pointerdown'; 18 | var POINTER_WINDOW_EVENTS = 'pointermove pointerup pointercancel'; 19 | 20 | // IE10 has prefixed support, and case-sensitive 21 | if (window.MSPointerEvent && !window.PointerEvent) { 22 | POINTER_ELEMENT_EVENTS = 'MSPointerDown'; 23 | POINTER_WINDOW_EVENTS = 'MSPointerMove MSPointerUp MSPointerCancel'; 24 | } 25 | 26 | /** 27 | * Pointer events input 28 | * @constructor 29 | * @extends Input 30 | */ 31 | function PointerEventInput() { 32 | this.evEl = POINTER_ELEMENT_EVENTS; 33 | this.evWin = POINTER_WINDOW_EVENTS; 34 | 35 | Input.apply(this, arguments); 36 | 37 | this.store = (this.manager.session.pointerEvents = []); 38 | } 39 | 40 | inherit(PointerEventInput, Input, { 41 | /** 42 | * handle mouse events 43 | * @param {Object} ev 44 | */ 45 | handler: function PEhandler(ev) { 46 | var store = this.store; 47 | var removePointer = false; 48 | 49 | var eventTypeNormalized = ev.type.toLowerCase().replace('ms', ''); 50 | var eventType = POINTER_INPUT_MAP[eventTypeNormalized]; 51 | var pointerType = IE10_POINTER_TYPE_ENUM[ev.pointerType] || ev.pointerType; 52 | 53 | var isTouch = (pointerType == INPUT_TYPE_TOUCH); 54 | 55 | // get index of the event in the store 56 | var storeIndex = inArray(store, ev.pointerId, 'pointerId'); 57 | 58 | // start and mouse must be down 59 | if (eventType & INPUT_START && (ev.button === 0 || isTouch)) { 60 | if (storeIndex < 0) { 61 | store.push(ev); 62 | storeIndex = store.length - 1; 63 | } 64 | } else if (eventType & (INPUT_END | INPUT_CANCEL)) { 65 | removePointer = true; 66 | } 67 | 68 | // it not found, so the pointer hasn't been down (so it's probably a hover) 69 | if (storeIndex < 0) { 70 | return; 71 | } 72 | 73 | // update the event in the store 74 | store[storeIndex] = ev; 75 | 76 | this.callback(this.manager, eventType, { 77 | pointers: store, 78 | changedPointers: [ev], 79 | pointerType: pointerType, 80 | srcEvent: ev 81 | }); 82 | 83 | if (removePointer) { 84 | // remove from the store 85 | store.splice(storeIndex, 1); 86 | } 87 | } 88 | }); 89 | -------------------------------------------------------------------------------- /node_modules/hammerjs/src/input/singletouch.js: -------------------------------------------------------------------------------- 1 | var SINGLE_TOUCH_INPUT_MAP = { 2 | touchstart: INPUT_START, 3 | touchmove: INPUT_MOVE, 4 | touchend: INPUT_END, 5 | touchcancel: INPUT_CANCEL 6 | }; 7 | 8 | var SINGLE_TOUCH_TARGET_EVENTS = 'touchstart'; 9 | var SINGLE_TOUCH_WINDOW_EVENTS = 'touchstart touchmove touchend touchcancel'; 10 | 11 | /** 12 | * Touch events input 13 | * @constructor 14 | * @extends Input 15 | */ 16 | function SingleTouchInput() { 17 | this.evTarget = SINGLE_TOUCH_TARGET_EVENTS; 18 | this.evWin = SINGLE_TOUCH_WINDOW_EVENTS; 19 | this.started = false; 20 | 21 | Input.apply(this, arguments); 22 | } 23 | 24 | inherit(SingleTouchInput, Input, { 25 | handler: function TEhandler(ev) { 26 | var type = SINGLE_TOUCH_INPUT_MAP[ev.type]; 27 | 28 | // should we handle the touch events? 29 | if (type === INPUT_START) { 30 | this.started = true; 31 | } 32 | 33 | if (!this.started) { 34 | return; 35 | } 36 | 37 | var touches = normalizeSingleTouches.call(this, ev, type); 38 | 39 | // when done, reset the started state 40 | if (type & (INPUT_END | INPUT_CANCEL) && touches[0].length - touches[1].length === 0) { 41 | this.started = false; 42 | } 43 | 44 | this.callback(this.manager, type, { 45 | pointers: touches[0], 46 | changedPointers: touches[1], 47 | pointerType: INPUT_TYPE_TOUCH, 48 | srcEvent: ev 49 | }); 50 | } 51 | }); 52 | 53 | /** 54 | * @this {TouchInput} 55 | * @param {Object} ev 56 | * @param {Number} type flag 57 | * @returns {undefined|Array} [all, changed] 58 | */ 59 | function normalizeSingleTouches(ev, type) { 60 | var all = toArray(ev.touches); 61 | var changed = toArray(ev.changedTouches); 62 | 63 | if (type & (INPUT_END | INPUT_CANCEL)) { 64 | all = uniqueArray(all.concat(changed), 'identifier', true); 65 | } 66 | 67 | return [all, changed]; 68 | } 69 | -------------------------------------------------------------------------------- /node_modules/hammerjs/src/input/touch.js: -------------------------------------------------------------------------------- 1 | var TOUCH_INPUT_MAP = { 2 | touchstart: INPUT_START, 3 | touchmove: INPUT_MOVE, 4 | touchend: INPUT_END, 5 | touchcancel: INPUT_CANCEL 6 | }; 7 | 8 | var TOUCH_TARGET_EVENTS = 'touchstart touchmove touchend touchcancel'; 9 | 10 | /** 11 | * Multi-user touch events input 12 | * @constructor 13 | * @extends Input 14 | */ 15 | function TouchInput() { 16 | this.evTarget = TOUCH_TARGET_EVENTS; 17 | this.targetIds = {}; 18 | 19 | Input.apply(this, arguments); 20 | } 21 | 22 | inherit(TouchInput, Input, { 23 | handler: function MTEhandler(ev) { 24 | var type = TOUCH_INPUT_MAP[ev.type]; 25 | var touches = getTouches.call(this, ev, type); 26 | if (!touches) { 27 | return; 28 | } 29 | 30 | this.callback(this.manager, type, { 31 | pointers: touches[0], 32 | changedPointers: touches[1], 33 | pointerType: INPUT_TYPE_TOUCH, 34 | srcEvent: ev 35 | }); 36 | } 37 | }); 38 | 39 | /** 40 | * @this {TouchInput} 41 | * @param {Object} ev 42 | * @param {Number} type flag 43 | * @returns {undefined|Array} [all, changed] 44 | */ 45 | function getTouches(ev, type) { 46 | var allTouches = toArray(ev.touches); 47 | var targetIds = this.targetIds; 48 | 49 | // when there is only one touch, the process can be simplified 50 | if (type & (INPUT_START | INPUT_MOVE) && allTouches.length === 1) { 51 | targetIds[allTouches[0].identifier] = true; 52 | return [allTouches, allTouches]; 53 | } 54 | 55 | var i, 56 | targetTouches, 57 | changedTouches = toArray(ev.changedTouches), 58 | changedTargetTouches = [], 59 | target = this.target; 60 | 61 | // get target touches from touches 62 | targetTouches = allTouches.filter(function(touch) { 63 | return hasParent(touch.target, target); 64 | }); 65 | 66 | // collect touches 67 | if (type === INPUT_START) { 68 | i = 0; 69 | while (i < targetTouches.length) { 70 | targetIds[targetTouches[i].identifier] = true; 71 | i++; 72 | } 73 | } 74 | 75 | // filter changed touches to only contain touches that exist in the collected target ids 76 | i = 0; 77 | while (i < changedTouches.length) { 78 | if (targetIds[changedTouches[i].identifier]) { 79 | changedTargetTouches.push(changedTouches[i]); 80 | } 81 | 82 | // cleanup removed touches 83 | if (type & (INPUT_END | INPUT_CANCEL)) { 84 | delete targetIds[changedTouches[i].identifier]; 85 | } 86 | i++; 87 | } 88 | 89 | if (!changedTargetTouches.length) { 90 | return; 91 | } 92 | 93 | return [ 94 | // merge targetTouches with changedTargetTouches so it contains ALL touches, including 'end' and 'cancel' 95 | uniqueArray(targetTouches.concat(changedTargetTouches), 'identifier', true), 96 | changedTargetTouches 97 | ]; 98 | } 99 | -------------------------------------------------------------------------------- /node_modules/hammerjs/src/input/touchmouse.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Combined touch and mouse input 3 | * 4 | * Touch has a higher priority then mouse, and while touching no mouse events are allowed. 5 | * This because touch devices also emit mouse events while doing a touch. 6 | * 7 | * @constructor 8 | * @extends Input 9 | */ 10 | 11 | var DEDUP_TIMEOUT = 2500; 12 | var DEDUP_DISTANCE = 25; 13 | 14 | function TouchMouseInput() { 15 | Input.apply(this, arguments); 16 | 17 | var handler = bindFn(this.handler, this); 18 | this.touch = new TouchInput(this.manager, handler); 19 | this.mouse = new MouseInput(this.manager, handler); 20 | 21 | this.primaryTouch = null; 22 | this.lastTouches = []; 23 | } 24 | 25 | inherit(TouchMouseInput, Input, { 26 | /** 27 | * handle mouse and touch events 28 | * @param {Hammer} manager 29 | * @param {String} inputEvent 30 | * @param {Object} inputData 31 | */ 32 | handler: function TMEhandler(manager, inputEvent, inputData) { 33 | var isTouch = (inputData.pointerType == INPUT_TYPE_TOUCH), 34 | isMouse = (inputData.pointerType == INPUT_TYPE_MOUSE); 35 | 36 | if (isMouse && inputData.sourceCapabilities && inputData.sourceCapabilities.firesTouchEvents) { 37 | return; 38 | } 39 | 40 | // when we're in a touch event, record touches to de-dupe synthetic mouse event 41 | if (isTouch) { 42 | recordTouches.call(this, inputEvent, inputData); 43 | } else if (isMouse && isSyntheticEvent.call(this, inputData)) { 44 | return; 45 | } 46 | 47 | this.callback(manager, inputEvent, inputData); 48 | }, 49 | 50 | /** 51 | * remove the event listeners 52 | */ 53 | destroy: function destroy() { 54 | this.touch.destroy(); 55 | this.mouse.destroy(); 56 | } 57 | }); 58 | 59 | function recordTouches(eventType, eventData) { 60 | if (eventType & INPUT_START) { 61 | this.primaryTouch = eventData.changedPointers[0].identifier; 62 | setLastTouch.call(this, eventData); 63 | } else if (eventType & (INPUT_END | INPUT_CANCEL)) { 64 | setLastTouch.call(this, eventData); 65 | } 66 | } 67 | 68 | function setLastTouch(eventData) { 69 | var touch = eventData.changedPointers[0]; 70 | 71 | if (touch.identifier === this.primaryTouch) { 72 | var lastTouch = {x: touch.clientX, y: touch.clientY}; 73 | this.lastTouches.push(lastTouch); 74 | var lts = this.lastTouches; 75 | var removeLastTouch = function() { 76 | var i = lts.indexOf(lastTouch); 77 | if (i > -1) { 78 | lts.splice(i, 1); 79 | } 80 | }; 81 | setTimeout(removeLastTouch, DEDUP_TIMEOUT); 82 | } 83 | } 84 | 85 | function isSyntheticEvent(eventData) { 86 | var x = eventData.srcEvent.clientX, y = eventData.srcEvent.clientY; 87 | for (var i = 0; i < this.lastTouches.length; i++) { 88 | var t = this.lastTouches[i]; 89 | var dx = Math.abs(x - t.x), dy = Math.abs(y - t.y); 90 | if (dx <= DEDUP_DISTANCE && dy <= DEDUP_DISTANCE) { 91 | return true; 92 | } 93 | } 94 | return false; 95 | } 96 | -------------------------------------------------------------------------------- /node_modules/hammerjs/src/manager.js: -------------------------------------------------------------------------------- 1 | var STOP = 1; 2 | var FORCED_STOP = 2; 3 | 4 | /** 5 | * Manager 6 | * @param {HTMLElement} element 7 | * @param {Object} [options] 8 | * @constructor 9 | */ 10 | function Manager(element, options) { 11 | this.options = assign({}, Hammer.defaults, options || {}); 12 | 13 | this.options.inputTarget = this.options.inputTarget || element; 14 | 15 | this.handlers = {}; 16 | this.session = {}; 17 | this.recognizers = []; 18 | this.oldCssProps = {}; 19 | 20 | this.element = element; 21 | this.input = createInputInstance(this); 22 | this.touchAction = new TouchAction(this, this.options.touchAction); 23 | 24 | toggleCssProps(this, true); 25 | 26 | each(this.options.recognizers, function(item) { 27 | var recognizer = this.add(new (item[0])(item[1])); 28 | item[2] && recognizer.recognizeWith(item[2]); 29 | item[3] && recognizer.requireFailure(item[3]); 30 | }, this); 31 | } 32 | 33 | Manager.prototype = { 34 | /** 35 | * set options 36 | * @param {Object} options 37 | * @returns {Manager} 38 | */ 39 | set: function(options) { 40 | assign(this.options, options); 41 | 42 | // Options that need a little more setup 43 | if (options.touchAction) { 44 | this.touchAction.update(); 45 | } 46 | if (options.inputTarget) { 47 | // Clean up existing event listeners and reinitialize 48 | this.input.destroy(); 49 | this.input.target = options.inputTarget; 50 | this.input.init(); 51 | } 52 | return this; 53 | }, 54 | 55 | /** 56 | * stop recognizing for this session. 57 | * This session will be discarded, when a new [input]start event is fired. 58 | * When forced, the recognizer cycle is stopped immediately. 59 | * @param {Boolean} [force] 60 | */ 61 | stop: function(force) { 62 | this.session.stopped = force ? FORCED_STOP : STOP; 63 | }, 64 | 65 | /** 66 | * run the recognizers! 67 | * called by the inputHandler function on every movement of the pointers (touches) 68 | * it walks through all the recognizers and tries to detect the gesture that is being made 69 | * @param {Object} inputData 70 | */ 71 | recognize: function(inputData) { 72 | var session = this.session; 73 | if (session.stopped) { 74 | return; 75 | } 76 | 77 | // run the touch-action polyfill 78 | this.touchAction.preventDefaults(inputData); 79 | 80 | var recognizer; 81 | var recognizers = this.recognizers; 82 | 83 | // this holds the recognizer that is being recognized. 84 | // so the recognizer's state needs to be BEGAN, CHANGED, ENDED or RECOGNIZED 85 | // if no recognizer is detecting a thing, it is set to `null` 86 | var curRecognizer = session.curRecognizer; 87 | 88 | // reset when the last recognizer is recognized 89 | // or when we're in a new session 90 | if (!curRecognizer || (curRecognizer && curRecognizer.state & STATE_RECOGNIZED)) { 91 | curRecognizer = session.curRecognizer = null; 92 | } 93 | 94 | var i = 0; 95 | while (i < recognizers.length) { 96 | recognizer = recognizers[i]; 97 | 98 | // find out if we are allowed try to recognize the input for this one. 99 | // 1. allow if the session is NOT forced stopped (see the .stop() method) 100 | // 2. allow if we still haven't recognized a gesture in this session, or the this recognizer is the one 101 | // that is being recognized. 102 | // 3. allow if the recognizer is allowed to run simultaneous with the current recognized recognizer. 103 | // this can be setup with the `recognizeWith()` method on the recognizer. 104 | if (session.stopped !== FORCED_STOP && ( // 1 105 | !curRecognizer || recognizer == curRecognizer || // 2 106 | recognizer.canRecognizeWith(curRecognizer))) { // 3 107 | recognizer.recognize(inputData); 108 | } else { 109 | recognizer.reset(); 110 | } 111 | 112 | // if the recognizer has been recognizing the input as a valid gesture, we want to store this one as the 113 | // current active recognizer. but only if we don't already have an active recognizer 114 | if (!curRecognizer && recognizer.state & (STATE_BEGAN | STATE_CHANGED | STATE_ENDED)) { 115 | curRecognizer = session.curRecognizer = recognizer; 116 | } 117 | i++; 118 | } 119 | }, 120 | 121 | /** 122 | * get a recognizer by its event name. 123 | * @param {Recognizer|String} recognizer 124 | * @returns {Recognizer|Null} 125 | */ 126 | get: function(recognizer) { 127 | if (recognizer instanceof Recognizer) { 128 | return recognizer; 129 | } 130 | 131 | var recognizers = this.recognizers; 132 | for (var i = 0; i < recognizers.length; i++) { 133 | if (recognizers[i].options.event == recognizer) { 134 | return recognizers[i]; 135 | } 136 | } 137 | return null; 138 | }, 139 | 140 | /** 141 | * add a recognizer to the manager 142 | * existing recognizers with the same event name will be removed 143 | * @param {Recognizer} recognizer 144 | * @returns {Recognizer|Manager} 145 | */ 146 | add: function(recognizer) { 147 | if (invokeArrayArg(recognizer, 'add', this)) { 148 | return this; 149 | } 150 | 151 | // remove existing 152 | var existing = this.get(recognizer.options.event); 153 | if (existing) { 154 | this.remove(existing); 155 | } 156 | 157 | this.recognizers.push(recognizer); 158 | recognizer.manager = this; 159 | 160 | this.touchAction.update(); 161 | return recognizer; 162 | }, 163 | 164 | /** 165 | * remove a recognizer by name or instance 166 | * @param {Recognizer|String} recognizer 167 | * @returns {Manager} 168 | */ 169 | remove: function(recognizer) { 170 | if (invokeArrayArg(recognizer, 'remove', this)) { 171 | return this; 172 | } 173 | 174 | recognizer = this.get(recognizer); 175 | 176 | // let's make sure this recognizer exists 177 | if (recognizer) { 178 | var recognizers = this.recognizers; 179 | var index = inArray(recognizers, recognizer); 180 | 181 | if (index !== -1) { 182 | recognizers.splice(index, 1); 183 | this.touchAction.update(); 184 | } 185 | } 186 | 187 | return this; 188 | }, 189 | 190 | /** 191 | * bind event 192 | * @param {String} events 193 | * @param {Function} handler 194 | * @returns {EventEmitter} this 195 | */ 196 | on: function(events, handler) { 197 | if (events === undefined) { 198 | return; 199 | } 200 | if (handler === undefined) { 201 | return; 202 | } 203 | 204 | var handlers = this.handlers; 205 | each(splitStr(events), function(event) { 206 | handlers[event] = handlers[event] || []; 207 | handlers[event].push(handler); 208 | }); 209 | return this; 210 | }, 211 | 212 | /** 213 | * unbind event, leave emit blank to remove all handlers 214 | * @param {String} events 215 | * @param {Function} [handler] 216 | * @returns {EventEmitter} this 217 | */ 218 | off: function(events, handler) { 219 | if (events === undefined) { 220 | return; 221 | } 222 | 223 | var handlers = this.handlers; 224 | each(splitStr(events), function(event) { 225 | if (!handler) { 226 | delete handlers[event]; 227 | } else { 228 | handlers[event] && handlers[event].splice(inArray(handlers[event], handler), 1); 229 | } 230 | }); 231 | return this; 232 | }, 233 | 234 | /** 235 | * emit event to the listeners 236 | * @param {String} event 237 | * @param {Object} data 238 | */ 239 | emit: function(event, data) { 240 | // we also want to trigger dom events 241 | if (this.options.domEvents) { 242 | triggerDomEvent(event, data); 243 | } 244 | 245 | // no handlers, so skip it all 246 | var handlers = this.handlers[event] && this.handlers[event].slice(); 247 | if (!handlers || !handlers.length) { 248 | return; 249 | } 250 | 251 | data.type = event; 252 | data.preventDefault = function() { 253 | data.srcEvent.preventDefault(); 254 | }; 255 | 256 | var i = 0; 257 | while (i < handlers.length) { 258 | handlers[i](data); 259 | i++; 260 | } 261 | }, 262 | 263 | /** 264 | * destroy the manager and unbinds all events 265 | * it doesn't unbind dom events, that is the user own responsibility 266 | */ 267 | destroy: function() { 268 | this.element && toggleCssProps(this, false); 269 | 270 | this.handlers = {}; 271 | this.session = {}; 272 | this.input.destroy(); 273 | this.element = null; 274 | } 275 | }; 276 | 277 | /** 278 | * add/remove the css properties as defined in manager.options.cssProps 279 | * @param {Manager} manager 280 | * @param {Boolean} add 281 | */ 282 | function toggleCssProps(manager, add) { 283 | var element = manager.element; 284 | if (!element.style) { 285 | return; 286 | } 287 | var prop; 288 | each(manager.options.cssProps, function(value, name) { 289 | prop = prefixed(element.style, name); 290 | if (add) { 291 | manager.oldCssProps[prop] = element.style[prop]; 292 | element.style[prop] = value; 293 | } else { 294 | element.style[prop] = manager.oldCssProps[prop] || ''; 295 | } 296 | }); 297 | if (!add) { 298 | manager.oldCssProps = {}; 299 | } 300 | } 301 | 302 | /** 303 | * trigger dom event 304 | * @param {String} event 305 | * @param {Object} data 306 | */ 307 | function triggerDomEvent(event, data) { 308 | var gestureEvent = document.createEvent('Event'); 309 | gestureEvent.initEvent(event, true, true); 310 | gestureEvent.gesture = data; 311 | data.target.dispatchEvent(gestureEvent); 312 | } 313 | -------------------------------------------------------------------------------- /node_modules/hammerjs/src/recognizer.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Recognizer flow explained; * 3 | * All recognizers have the initial state of POSSIBLE when a input session starts. 4 | * The definition of a input session is from the first input until the last input, with all it's movement in it. * 5 | * Example session for mouse-input: mousedown -> mousemove -> mouseup 6 | * 7 | * On each recognizing cycle (see Manager.recognize) the .recognize() method is executed 8 | * which determines with state it should be. 9 | * 10 | * If the recognizer has the state FAILED, CANCELLED or RECOGNIZED (equals ENDED), it is reset to 11 | * POSSIBLE to give it another change on the next cycle. 12 | * 13 | * Possible 14 | * | 15 | * +-----+---------------+ 16 | * | | 17 | * +-----+-----+ | 18 | * | | | 19 | * Failed Cancelled | 20 | * +-------+------+ 21 | * | | 22 | * Recognized Began 23 | * | 24 | * Changed 25 | * | 26 | * Ended/Recognized 27 | */ 28 | var STATE_POSSIBLE = 1; 29 | var STATE_BEGAN = 2; 30 | var STATE_CHANGED = 4; 31 | var STATE_ENDED = 8; 32 | var STATE_RECOGNIZED = STATE_ENDED; 33 | var STATE_CANCELLED = 16; 34 | var STATE_FAILED = 32; 35 | 36 | /** 37 | * Recognizer 38 | * Every recognizer needs to extend from this class. 39 | * @constructor 40 | * @param {Object} options 41 | */ 42 | function Recognizer(options) { 43 | this.options = assign({}, this.defaults, options || {}); 44 | 45 | this.id = uniqueId(); 46 | 47 | this.manager = null; 48 | 49 | // default is enable true 50 | this.options.enable = ifUndefined(this.options.enable, true); 51 | 52 | this.state = STATE_POSSIBLE; 53 | 54 | this.simultaneous = {}; 55 | this.requireFail = []; 56 | } 57 | 58 | Recognizer.prototype = { 59 | /** 60 | * @virtual 61 | * @type {Object} 62 | */ 63 | defaults: {}, 64 | 65 | /** 66 | * set options 67 | * @param {Object} options 68 | * @return {Recognizer} 69 | */ 70 | set: function(options) { 71 | assign(this.options, options); 72 | 73 | // also update the touchAction, in case something changed about the directions/enabled state 74 | this.manager && this.manager.touchAction.update(); 75 | return this; 76 | }, 77 | 78 | /** 79 | * recognize simultaneous with an other recognizer. 80 | * @param {Recognizer} otherRecognizer 81 | * @returns {Recognizer} this 82 | */ 83 | recognizeWith: function(otherRecognizer) { 84 | if (invokeArrayArg(otherRecognizer, 'recognizeWith', this)) { 85 | return this; 86 | } 87 | 88 | var simultaneous = this.simultaneous; 89 | otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this); 90 | if (!simultaneous[otherRecognizer.id]) { 91 | simultaneous[otherRecognizer.id] = otherRecognizer; 92 | otherRecognizer.recognizeWith(this); 93 | } 94 | return this; 95 | }, 96 | 97 | /** 98 | * drop the simultaneous link. it doesnt remove the link on the other recognizer. 99 | * @param {Recognizer} otherRecognizer 100 | * @returns {Recognizer} this 101 | */ 102 | dropRecognizeWith: function(otherRecognizer) { 103 | if (invokeArrayArg(otherRecognizer, 'dropRecognizeWith', this)) { 104 | return this; 105 | } 106 | 107 | otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this); 108 | delete this.simultaneous[otherRecognizer.id]; 109 | return this; 110 | }, 111 | 112 | /** 113 | * recognizer can only run when an other is failing 114 | * @param {Recognizer} otherRecognizer 115 | * @returns {Recognizer} this 116 | */ 117 | requireFailure: function(otherRecognizer) { 118 | if (invokeArrayArg(otherRecognizer, 'requireFailure', this)) { 119 | return this; 120 | } 121 | 122 | var requireFail = this.requireFail; 123 | otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this); 124 | if (inArray(requireFail, otherRecognizer) === -1) { 125 | requireFail.push(otherRecognizer); 126 | otherRecognizer.requireFailure(this); 127 | } 128 | return this; 129 | }, 130 | 131 | /** 132 | * drop the requireFailure link. it does not remove the link on the other recognizer. 133 | * @param {Recognizer} otherRecognizer 134 | * @returns {Recognizer} this 135 | */ 136 | dropRequireFailure: function(otherRecognizer) { 137 | if (invokeArrayArg(otherRecognizer, 'dropRequireFailure', this)) { 138 | return this; 139 | } 140 | 141 | otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this); 142 | var index = inArray(this.requireFail, otherRecognizer); 143 | if (index > -1) { 144 | this.requireFail.splice(index, 1); 145 | } 146 | return this; 147 | }, 148 | 149 | /** 150 | * has require failures boolean 151 | * @returns {boolean} 152 | */ 153 | hasRequireFailures: function() { 154 | return this.requireFail.length > 0; 155 | }, 156 | 157 | /** 158 | * if the recognizer can recognize simultaneous with an other recognizer 159 | * @param {Recognizer} otherRecognizer 160 | * @returns {Boolean} 161 | */ 162 | canRecognizeWith: function(otherRecognizer) { 163 | return !!this.simultaneous[otherRecognizer.id]; 164 | }, 165 | 166 | /** 167 | * You should use `tryEmit` instead of `emit` directly to check 168 | * that all the needed recognizers has failed before emitting. 169 | * @param {Object} input 170 | */ 171 | emit: function(input) { 172 | var self = this; 173 | var state = this.state; 174 | 175 | function emit(event) { 176 | self.manager.emit(event, input); 177 | } 178 | 179 | // 'panstart' and 'panmove' 180 | if (state < STATE_ENDED) { 181 | emit(self.options.event + stateStr(state)); 182 | } 183 | 184 | emit(self.options.event); // simple 'eventName' events 185 | 186 | if (input.additionalEvent) { // additional event(panleft, panright, pinchin, pinchout...) 187 | emit(input.additionalEvent); 188 | } 189 | 190 | // panend and pancancel 191 | if (state >= STATE_ENDED) { 192 | emit(self.options.event + stateStr(state)); 193 | } 194 | }, 195 | 196 | /** 197 | * Check that all the require failure recognizers has failed, 198 | * if true, it emits a gesture event, 199 | * otherwise, setup the state to FAILED. 200 | * @param {Object} input 201 | */ 202 | tryEmit: function(input) { 203 | if (this.canEmit()) { 204 | return this.emit(input); 205 | } 206 | // it's failing anyway 207 | this.state = STATE_FAILED; 208 | }, 209 | 210 | /** 211 | * can we emit? 212 | * @returns {boolean} 213 | */ 214 | canEmit: function() { 215 | var i = 0; 216 | while (i < this.requireFail.length) { 217 | if (!(this.requireFail[i].state & (STATE_FAILED | STATE_POSSIBLE))) { 218 | return false; 219 | } 220 | i++; 221 | } 222 | return true; 223 | }, 224 | 225 | /** 226 | * update the recognizer 227 | * @param {Object} inputData 228 | */ 229 | recognize: function(inputData) { 230 | // make a new copy of the inputData 231 | // so we can change the inputData without messing up the other recognizers 232 | var inputDataClone = assign({}, inputData); 233 | 234 | // is is enabled and allow recognizing? 235 | if (!boolOrFn(this.options.enable, [this, inputDataClone])) { 236 | this.reset(); 237 | this.state = STATE_FAILED; 238 | return; 239 | } 240 | 241 | // reset when we've reached the end 242 | if (this.state & (STATE_RECOGNIZED | STATE_CANCELLED | STATE_FAILED)) { 243 | this.state = STATE_POSSIBLE; 244 | } 245 | 246 | this.state = this.process(inputDataClone); 247 | 248 | // the recognizer has recognized a gesture 249 | // so trigger an event 250 | if (this.state & (STATE_BEGAN | STATE_CHANGED | STATE_ENDED | STATE_CANCELLED)) { 251 | this.tryEmit(inputDataClone); 252 | } 253 | }, 254 | 255 | /** 256 | * return the state of the recognizer 257 | * the actual recognizing happens in this method 258 | * @virtual 259 | * @param {Object} inputData 260 | * @returns {Const} STATE 261 | */ 262 | process: function(inputData) { }, // jshint ignore:line 263 | 264 | /** 265 | * return the preferred touch-action 266 | * @virtual 267 | * @returns {Array} 268 | */ 269 | getTouchAction: function() { }, 270 | 271 | /** 272 | * called when the gesture isn't allowed to recognize 273 | * like when another is being recognized or it is disabled 274 | * @virtual 275 | */ 276 | reset: function() { } 277 | }; 278 | 279 | /** 280 | * get a usable string, used as event postfix 281 | * @param {Const} state 282 | * @returns {String} state 283 | */ 284 | function stateStr(state) { 285 | if (state & STATE_CANCELLED) { 286 | return 'cancel'; 287 | } else if (state & STATE_ENDED) { 288 | return 'end'; 289 | } else if (state & STATE_CHANGED) { 290 | return 'move'; 291 | } else if (state & STATE_BEGAN) { 292 | return 'start'; 293 | } 294 | return ''; 295 | } 296 | 297 | /** 298 | * direction cons to string 299 | * @param {Const} direction 300 | * @returns {String} 301 | */ 302 | function directionStr(direction) { 303 | if (direction == DIRECTION_DOWN) { 304 | return 'down'; 305 | } else if (direction == DIRECTION_UP) { 306 | return 'up'; 307 | } else if (direction == DIRECTION_LEFT) { 308 | return 'left'; 309 | } else if (direction == DIRECTION_RIGHT) { 310 | return 'right'; 311 | } 312 | return ''; 313 | } 314 | 315 | /** 316 | * get a recognizer by name if it is bound to a manager 317 | * @param {Recognizer|String} otherRecognizer 318 | * @param {Recognizer} recognizer 319 | * @returns {Recognizer} 320 | */ 321 | function getRecognizerByNameIfManager(otherRecognizer, recognizer) { 322 | var manager = recognizer.manager; 323 | if (manager) { 324 | return manager.get(otherRecognizer); 325 | } 326 | return otherRecognizer; 327 | } 328 | -------------------------------------------------------------------------------- /node_modules/hammerjs/src/recognizers/attribute.js: -------------------------------------------------------------------------------- 1 | /** 2 | * This recognizer is just used as a base for the simple attribute recognizers. 3 | * @constructor 4 | * @extends Recognizer 5 | */ 6 | function AttrRecognizer() { 7 | Recognizer.apply(this, arguments); 8 | } 9 | 10 | inherit(AttrRecognizer, Recognizer, { 11 | /** 12 | * @namespace 13 | * @memberof AttrRecognizer 14 | */ 15 | defaults: { 16 | /** 17 | * @type {Number} 18 | * @default 1 19 | */ 20 | pointers: 1 21 | }, 22 | 23 | /** 24 | * Used to check if it the recognizer receives valid input, like input.distance > 10. 25 | * @memberof AttrRecognizer 26 | * @param {Object} input 27 | * @returns {Boolean} recognized 28 | */ 29 | attrTest: function(input) { 30 | var optionPointers = this.options.pointers; 31 | return optionPointers === 0 || input.pointers.length === optionPointers; 32 | }, 33 | 34 | /** 35 | * Process the input and return the state for the recognizer 36 | * @memberof AttrRecognizer 37 | * @param {Object} input 38 | * @returns {*} State 39 | */ 40 | process: function(input) { 41 | var state = this.state; 42 | var eventType = input.eventType; 43 | 44 | var isRecognized = state & (STATE_BEGAN | STATE_CHANGED); 45 | var isValid = this.attrTest(input); 46 | 47 | // on cancel input and we've recognized before, return STATE_CANCELLED 48 | if (isRecognized && (eventType & INPUT_CANCEL || !isValid)) { 49 | return state | STATE_CANCELLED; 50 | } else if (isRecognized || isValid) { 51 | if (eventType & INPUT_END) { 52 | return state | STATE_ENDED; 53 | } else if (!(state & STATE_BEGAN)) { 54 | return STATE_BEGAN; 55 | } 56 | return state | STATE_CHANGED; 57 | } 58 | return STATE_FAILED; 59 | } 60 | }); 61 | -------------------------------------------------------------------------------- /node_modules/hammerjs/src/recognizers/pan.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Pan 3 | * Recognized when the pointer is down and moved in the allowed direction. 4 | * @constructor 5 | * @extends AttrRecognizer 6 | */ 7 | function PanRecognizer() { 8 | AttrRecognizer.apply(this, arguments); 9 | 10 | this.pX = null; 11 | this.pY = null; 12 | } 13 | 14 | inherit(PanRecognizer, AttrRecognizer, { 15 | /** 16 | * @namespace 17 | * @memberof PanRecognizer 18 | */ 19 | defaults: { 20 | event: 'pan', 21 | threshold: 10, 22 | pointers: 1, 23 | direction: DIRECTION_ALL 24 | }, 25 | 26 | getTouchAction: function() { 27 | var direction = this.options.direction; 28 | var actions = []; 29 | if (direction & DIRECTION_HORIZONTAL) { 30 | actions.push(TOUCH_ACTION_PAN_Y); 31 | } 32 | if (direction & DIRECTION_VERTICAL) { 33 | actions.push(TOUCH_ACTION_PAN_X); 34 | } 35 | return actions; 36 | }, 37 | 38 | directionTest: function(input) { 39 | var options = this.options; 40 | var hasMoved = true; 41 | var distance = input.distance; 42 | var direction = input.direction; 43 | var x = input.deltaX; 44 | var y = input.deltaY; 45 | 46 | // lock to axis? 47 | if (!(direction & options.direction)) { 48 | if (options.direction & DIRECTION_HORIZONTAL) { 49 | direction = (x === 0) ? DIRECTION_NONE : (x < 0) ? DIRECTION_LEFT : DIRECTION_RIGHT; 50 | hasMoved = x != this.pX; 51 | distance = Math.abs(input.deltaX); 52 | } else { 53 | direction = (y === 0) ? DIRECTION_NONE : (y < 0) ? DIRECTION_UP : DIRECTION_DOWN; 54 | hasMoved = y != this.pY; 55 | distance = Math.abs(input.deltaY); 56 | } 57 | } 58 | input.direction = direction; 59 | return hasMoved && distance > options.threshold && direction & options.direction; 60 | }, 61 | 62 | attrTest: function(input) { 63 | return AttrRecognizer.prototype.attrTest.call(this, input) && 64 | (this.state & STATE_BEGAN || (!(this.state & STATE_BEGAN) && this.directionTest(input))); 65 | }, 66 | 67 | emit: function(input) { 68 | 69 | this.pX = input.deltaX; 70 | this.pY = input.deltaY; 71 | 72 | var direction = directionStr(input.direction); 73 | 74 | if (direction) { 75 | input.additionalEvent = this.options.event + direction; 76 | } 77 | this._super.emit.call(this, input); 78 | } 79 | }); 80 | -------------------------------------------------------------------------------- /node_modules/hammerjs/src/recognizers/pinch.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Pinch 3 | * Recognized when two or more pointers are moving toward (zoom-in) or away from each other (zoom-out). 4 | * @constructor 5 | * @extends AttrRecognizer 6 | */ 7 | function PinchRecognizer() { 8 | AttrRecognizer.apply(this, arguments); 9 | } 10 | 11 | inherit(PinchRecognizer, AttrRecognizer, { 12 | /** 13 | * @namespace 14 | * @memberof PinchRecognizer 15 | */ 16 | defaults: { 17 | event: 'pinch', 18 | threshold: 0, 19 | pointers: 2 20 | }, 21 | 22 | getTouchAction: function() { 23 | return [TOUCH_ACTION_NONE]; 24 | }, 25 | 26 | attrTest: function(input) { 27 | return this._super.attrTest.call(this, input) && 28 | (Math.abs(input.scale - 1) > this.options.threshold || this.state & STATE_BEGAN); 29 | }, 30 | 31 | emit: function(input) { 32 | if (input.scale !== 1) { 33 | var inOut = input.scale < 1 ? 'in' : 'out'; 34 | input.additionalEvent = this.options.event + inOut; 35 | } 36 | this._super.emit.call(this, input); 37 | } 38 | }); 39 | -------------------------------------------------------------------------------- /node_modules/hammerjs/src/recognizers/press.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Press 3 | * Recognized when the pointer is down for x ms without any movement. 4 | * @constructor 5 | * @extends Recognizer 6 | */ 7 | function PressRecognizer() { 8 | Recognizer.apply(this, arguments); 9 | 10 | this._timer = null; 11 | this._input = null; 12 | } 13 | 14 | inherit(PressRecognizer, Recognizer, { 15 | /** 16 | * @namespace 17 | * @memberof PressRecognizer 18 | */ 19 | defaults: { 20 | event: 'press', 21 | pointers: 1, 22 | time: 251, // minimal time of the pointer to be pressed 23 | threshold: 9 // a minimal movement is ok, but keep it low 24 | }, 25 | 26 | getTouchAction: function() { 27 | return [TOUCH_ACTION_AUTO]; 28 | }, 29 | 30 | process: function(input) { 31 | var options = this.options; 32 | var validPointers = input.pointers.length === options.pointers; 33 | var validMovement = input.distance < options.threshold; 34 | var validTime = input.deltaTime > options.time; 35 | 36 | this._input = input; 37 | 38 | // we only allow little movement 39 | // and we've reached an end event, so a tap is possible 40 | if (!validMovement || !validPointers || (input.eventType & (INPUT_END | INPUT_CANCEL) && !validTime)) { 41 | this.reset(); 42 | } else if (input.eventType & INPUT_START) { 43 | this.reset(); 44 | this._timer = setTimeoutContext(function() { 45 | this.state = STATE_RECOGNIZED; 46 | this.tryEmit(); 47 | }, options.time, this); 48 | } else if (input.eventType & INPUT_END) { 49 | return STATE_RECOGNIZED; 50 | } 51 | return STATE_FAILED; 52 | }, 53 | 54 | reset: function() { 55 | clearTimeout(this._timer); 56 | }, 57 | 58 | emit: function(input) { 59 | if (this.state !== STATE_RECOGNIZED) { 60 | return; 61 | } 62 | 63 | if (input && (input.eventType & INPUT_END)) { 64 | this.manager.emit(this.options.event + 'up', input); 65 | } else { 66 | this._input.timeStamp = now(); 67 | this.manager.emit(this.options.event, this._input); 68 | } 69 | } 70 | }); 71 | -------------------------------------------------------------------------------- /node_modules/hammerjs/src/recognizers/rotate.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Rotate 3 | * Recognized when two or more pointer are moving in a circular motion. 4 | * @constructor 5 | * @extends AttrRecognizer 6 | */ 7 | function RotateRecognizer() { 8 | AttrRecognizer.apply(this, arguments); 9 | } 10 | 11 | inherit(RotateRecognizer, AttrRecognizer, { 12 | /** 13 | * @namespace 14 | * @memberof RotateRecognizer 15 | */ 16 | defaults: { 17 | event: 'rotate', 18 | threshold: 0, 19 | pointers: 2 20 | }, 21 | 22 | getTouchAction: function() { 23 | return [TOUCH_ACTION_NONE]; 24 | }, 25 | 26 | attrTest: function(input) { 27 | return this._super.attrTest.call(this, input) && 28 | (Math.abs(input.rotation) > this.options.threshold || this.state & STATE_BEGAN); 29 | } 30 | }); 31 | -------------------------------------------------------------------------------- /node_modules/hammerjs/src/recognizers/swipe.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Swipe 3 | * Recognized when the pointer is moving fast (velocity), with enough distance in the allowed direction. 4 | * @constructor 5 | * @extends AttrRecognizer 6 | */ 7 | function SwipeRecognizer() { 8 | AttrRecognizer.apply(this, arguments); 9 | } 10 | 11 | inherit(SwipeRecognizer, AttrRecognizer, { 12 | /** 13 | * @namespace 14 | * @memberof SwipeRecognizer 15 | */ 16 | defaults: { 17 | event: 'swipe', 18 | threshold: 10, 19 | velocity: 0.3, 20 | direction: DIRECTION_HORIZONTAL | DIRECTION_VERTICAL, 21 | pointers: 1 22 | }, 23 | 24 | getTouchAction: function() { 25 | return PanRecognizer.prototype.getTouchAction.call(this); 26 | }, 27 | 28 | attrTest: function(input) { 29 | var direction = this.options.direction; 30 | var velocity; 31 | 32 | if (direction & (DIRECTION_HORIZONTAL | DIRECTION_VERTICAL)) { 33 | velocity = input.overallVelocity; 34 | } else if (direction & DIRECTION_HORIZONTAL) { 35 | velocity = input.overallVelocityX; 36 | } else if (direction & DIRECTION_VERTICAL) { 37 | velocity = input.overallVelocityY; 38 | } 39 | 40 | return this._super.attrTest.call(this, input) && 41 | direction & input.offsetDirection && 42 | input.distance > this.options.threshold && 43 | input.maxPointers == this.options.pointers && 44 | abs(velocity) > this.options.velocity && input.eventType & INPUT_END; 45 | }, 46 | 47 | emit: function(input) { 48 | var direction = directionStr(input.offsetDirection); 49 | if (direction) { 50 | this.manager.emit(this.options.event + direction, input); 51 | } 52 | 53 | this.manager.emit(this.options.event, input); 54 | } 55 | }); 56 | -------------------------------------------------------------------------------- /node_modules/hammerjs/src/recognizers/tap.js: -------------------------------------------------------------------------------- 1 | /** 2 | * A tap is ecognized when the pointer is doing a small tap/click. Multiple taps are recognized if they occur 3 | * between the given interval and position. The delay option can be used to recognize multi-taps without firing 4 | * a single tap. 5 | * 6 | * The eventData from the emitted event contains the property `tapCount`, which contains the amount of 7 | * multi-taps being recognized. 8 | * @constructor 9 | * @extends Recognizer 10 | */ 11 | function TapRecognizer() { 12 | Recognizer.apply(this, arguments); 13 | 14 | // previous time and center, 15 | // used for tap counting 16 | this.pTime = false; 17 | this.pCenter = false; 18 | 19 | this._timer = null; 20 | this._input = null; 21 | this.count = 0; 22 | } 23 | 24 | inherit(TapRecognizer, Recognizer, { 25 | /** 26 | * @namespace 27 | * @memberof PinchRecognizer 28 | */ 29 | defaults: { 30 | event: 'tap', 31 | pointers: 1, 32 | taps: 1, 33 | interval: 300, // max time between the multi-tap taps 34 | time: 250, // max time of the pointer to be down (like finger on the screen) 35 | threshold: 9, // a minimal movement is ok, but keep it low 36 | posThreshold: 10 // a multi-tap can be a bit off the initial position 37 | }, 38 | 39 | getTouchAction: function() { 40 | return [TOUCH_ACTION_MANIPULATION]; 41 | }, 42 | 43 | process: function(input) { 44 | var options = this.options; 45 | 46 | var validPointers = input.pointers.length === options.pointers; 47 | var validMovement = input.distance < options.threshold; 48 | var validTouchTime = input.deltaTime < options.time; 49 | 50 | this.reset(); 51 | 52 | if ((input.eventType & INPUT_START) && (this.count === 0)) { 53 | return this.failTimeout(); 54 | } 55 | 56 | // we only allow little movement 57 | // and we've reached an end event, so a tap is possible 58 | if (validMovement && validTouchTime && validPointers) { 59 | if (input.eventType != INPUT_END) { 60 | return this.failTimeout(); 61 | } 62 | 63 | var validInterval = this.pTime ? (input.timeStamp - this.pTime < options.interval) : true; 64 | var validMultiTap = !this.pCenter || getDistance(this.pCenter, input.center) < options.posThreshold; 65 | 66 | this.pTime = input.timeStamp; 67 | this.pCenter = input.center; 68 | 69 | if (!validMultiTap || !validInterval) { 70 | this.count = 1; 71 | } else { 72 | this.count += 1; 73 | } 74 | 75 | this._input = input; 76 | 77 | // if tap count matches we have recognized it, 78 | // else it has began recognizing... 79 | var tapCount = this.count % options.taps; 80 | if (tapCount === 0) { 81 | // no failing requirements, immediately trigger the tap event 82 | // or wait as long as the multitap interval to trigger 83 | if (!this.hasRequireFailures()) { 84 | return STATE_RECOGNIZED; 85 | } else { 86 | this._timer = setTimeoutContext(function() { 87 | this.state = STATE_RECOGNIZED; 88 | this.tryEmit(); 89 | }, options.interval, this); 90 | return STATE_BEGAN; 91 | } 92 | } 93 | } 94 | return STATE_FAILED; 95 | }, 96 | 97 | failTimeout: function() { 98 | this._timer = setTimeoutContext(function() { 99 | this.state = STATE_FAILED; 100 | }, this.options.interval, this); 101 | return STATE_FAILED; 102 | }, 103 | 104 | reset: function() { 105 | clearTimeout(this._timer); 106 | }, 107 | 108 | emit: function() { 109 | if (this.state == STATE_RECOGNIZED) { 110 | this._input.tapCount = this.count; 111 | this.manager.emit(this.options.event, this._input); 112 | } 113 | } 114 | }); 115 | -------------------------------------------------------------------------------- /node_modules/hammerjs/src/touchaction.js: -------------------------------------------------------------------------------- 1 | var PREFIXED_TOUCH_ACTION = prefixed(TEST_ELEMENT.style, 'touchAction'); 2 | var NATIVE_TOUCH_ACTION = PREFIXED_TOUCH_ACTION !== undefined; 3 | 4 | // magical touchAction value 5 | var TOUCH_ACTION_COMPUTE = 'compute'; 6 | var TOUCH_ACTION_AUTO = 'auto'; 7 | var TOUCH_ACTION_MANIPULATION = 'manipulation'; // not implemented 8 | var TOUCH_ACTION_NONE = 'none'; 9 | var TOUCH_ACTION_PAN_X = 'pan-x'; 10 | var TOUCH_ACTION_PAN_Y = 'pan-y'; 11 | var TOUCH_ACTION_MAP = getTouchActionProps(); 12 | 13 | /** 14 | * Touch Action 15 | * sets the touchAction property or uses the js alternative 16 | * @param {Manager} manager 17 | * @param {String} value 18 | * @constructor 19 | */ 20 | function TouchAction(manager, value) { 21 | this.manager = manager; 22 | this.set(value); 23 | } 24 | 25 | TouchAction.prototype = { 26 | /** 27 | * set the touchAction value on the element or enable the polyfill 28 | * @param {String} value 29 | */ 30 | set: function(value) { 31 | // find out the touch-action by the event handlers 32 | if (value == TOUCH_ACTION_COMPUTE) { 33 | value = this.compute(); 34 | } 35 | 36 | if (NATIVE_TOUCH_ACTION && this.manager.element.style && TOUCH_ACTION_MAP[value]) { 37 | this.manager.element.style[PREFIXED_TOUCH_ACTION] = value; 38 | } 39 | this.actions = value.toLowerCase().trim(); 40 | }, 41 | 42 | /** 43 | * just re-set the touchAction value 44 | */ 45 | update: function() { 46 | this.set(this.manager.options.touchAction); 47 | }, 48 | 49 | /** 50 | * compute the value for the touchAction property based on the recognizer's settings 51 | * @returns {String} value 52 | */ 53 | compute: function() { 54 | var actions = []; 55 | each(this.manager.recognizers, function(recognizer) { 56 | if (boolOrFn(recognizer.options.enable, [recognizer])) { 57 | actions = actions.concat(recognizer.getTouchAction()); 58 | } 59 | }); 60 | return cleanTouchActions(actions.join(' ')); 61 | }, 62 | 63 | /** 64 | * this method is called on each input cycle and provides the preventing of the browser behavior 65 | * @param {Object} input 66 | */ 67 | preventDefaults: function(input) { 68 | var srcEvent = input.srcEvent; 69 | var direction = input.offsetDirection; 70 | 71 | // if the touch action did prevented once this session 72 | if (this.manager.session.prevented) { 73 | srcEvent.preventDefault(); 74 | return; 75 | } 76 | 77 | var actions = this.actions; 78 | var hasNone = inStr(actions, TOUCH_ACTION_NONE) && !TOUCH_ACTION_MAP[TOUCH_ACTION_NONE]; 79 | var hasPanY = inStr(actions, TOUCH_ACTION_PAN_Y) && !TOUCH_ACTION_MAP[TOUCH_ACTION_PAN_Y]; 80 | var hasPanX = inStr(actions, TOUCH_ACTION_PAN_X) && !TOUCH_ACTION_MAP[TOUCH_ACTION_PAN_X]; 81 | 82 | if (hasNone) { 83 | //do not prevent defaults if this is a tap gesture 84 | 85 | var isTapPointer = input.pointers.length === 1; 86 | var isTapMovement = input.distance < 2; 87 | var isTapTouchTime = input.deltaTime < 250; 88 | 89 | if (isTapPointer && isTapMovement && isTapTouchTime) { 90 | return; 91 | } 92 | } 93 | 94 | if (hasPanX && hasPanY) { 95 | // `pan-x pan-y` means browser handles all scrolling/panning, do not prevent 96 | return; 97 | } 98 | 99 | if (hasNone || 100 | (hasPanY && direction & DIRECTION_HORIZONTAL) || 101 | (hasPanX && direction & DIRECTION_VERTICAL)) { 102 | return this.preventSrc(srcEvent); 103 | } 104 | }, 105 | 106 | /** 107 | * call preventDefault to prevent the browser's default behavior (scrolling in most cases) 108 | * @param {Object} srcEvent 109 | */ 110 | preventSrc: function(srcEvent) { 111 | this.manager.session.prevented = true; 112 | srcEvent.preventDefault(); 113 | } 114 | }; 115 | 116 | /** 117 | * when the touchActions are collected they are not a valid value, so we need to clean things up. * 118 | * @param {String} actions 119 | * @returns {*} 120 | */ 121 | function cleanTouchActions(actions) { 122 | // none 123 | if (inStr(actions, TOUCH_ACTION_NONE)) { 124 | return TOUCH_ACTION_NONE; 125 | } 126 | 127 | var hasPanX = inStr(actions, TOUCH_ACTION_PAN_X); 128 | var hasPanY = inStr(actions, TOUCH_ACTION_PAN_Y); 129 | 130 | // if both pan-x and pan-y are set (different recognizers 131 | // for different directions, e.g. horizontal pan but vertical swipe?) 132 | // we need none (as otherwise with pan-x pan-y combined none of these 133 | // recognizers will work, since the browser would handle all panning 134 | if (hasPanX && hasPanY) { 135 | return TOUCH_ACTION_NONE; 136 | } 137 | 138 | // pan-x OR pan-y 139 | if (hasPanX || hasPanY) { 140 | return hasPanX ? TOUCH_ACTION_PAN_X : TOUCH_ACTION_PAN_Y; 141 | } 142 | 143 | // manipulation 144 | if (inStr(actions, TOUCH_ACTION_MANIPULATION)) { 145 | return TOUCH_ACTION_MANIPULATION; 146 | } 147 | 148 | return TOUCH_ACTION_AUTO; 149 | } 150 | 151 | function getTouchActionProps() { 152 | if (!NATIVE_TOUCH_ACTION) { 153 | return false; 154 | } 155 | var touchMap = {}; 156 | var cssSupports = window.CSS && window.CSS.supports; 157 | ['auto', 'manipulation', 'pan-y', 'pan-x', 'pan-x pan-y', 'none'].forEach(function(val) { 158 | 159 | // If css.supports is not supported but there is native touch-action assume it supports 160 | // all values. This is the case for IE 10 and 11. 161 | touchMap[val] = cssSupports ? window.CSS.supports('touch-action', val) : true; 162 | }); 163 | return touchMap; 164 | } 165 | -------------------------------------------------------------------------------- /node_modules/hammerjs/src/utils.js: -------------------------------------------------------------------------------- 1 | var VENDOR_PREFIXES = ['', 'webkit', 'Moz', 'MS', 'ms', 'o']; 2 | var TEST_ELEMENT = document.createElement('div'); 3 | 4 | var TYPE_FUNCTION = 'function'; 5 | 6 | var round = Math.round; 7 | var abs = Math.abs; 8 | var now = Date.now; 9 | 10 | /** 11 | * set a timeout with a given scope 12 | * @param {Function} fn 13 | * @param {Number} timeout 14 | * @param {Object} context 15 | * @returns {number} 16 | */ 17 | function setTimeoutContext(fn, timeout, context) { 18 | return setTimeout(bindFn(fn, context), timeout); 19 | } 20 | 21 | /** 22 | * if the argument is an array, we want to execute the fn on each entry 23 | * if it aint an array we don't want to do a thing. 24 | * this is used by all the methods that accept a single and array argument. 25 | * @param {*|Array} arg 26 | * @param {String} fn 27 | * @param {Object} [context] 28 | * @returns {Boolean} 29 | */ 30 | function invokeArrayArg(arg, fn, context) { 31 | if (Array.isArray(arg)) { 32 | each(arg, context[fn], context); 33 | return true; 34 | } 35 | return false; 36 | } 37 | 38 | /** 39 | * walk objects and arrays 40 | * @param {Object} obj 41 | * @param {Function} iterator 42 | * @param {Object} context 43 | */ 44 | function each(obj, iterator, context) { 45 | var i; 46 | 47 | if (!obj) { 48 | return; 49 | } 50 | 51 | if (obj.forEach) { 52 | obj.forEach(iterator, context); 53 | } else if (obj.length !== undefined) { 54 | i = 0; 55 | while (i < obj.length) { 56 | iterator.call(context, obj[i], i, obj); 57 | i++; 58 | } 59 | } else { 60 | for (i in obj) { 61 | obj.hasOwnProperty(i) && iterator.call(context, obj[i], i, obj); 62 | } 63 | } 64 | } 65 | 66 | /** 67 | * wrap a method with a deprecation warning and stack trace 68 | * @param {Function} method 69 | * @param {String} name 70 | * @param {String} message 71 | * @returns {Function} A new function wrapping the supplied method. 72 | */ 73 | function deprecate(method, name, message) { 74 | var deprecationMessage = 'DEPRECATED METHOD: ' + name + '\n' + message + ' AT \n'; 75 | return function() { 76 | var e = new Error('get-stack-trace'); 77 | var stack = e && e.stack ? e.stack.replace(/^[^\(]+?[\n$]/gm, '') 78 | .replace(/^\s+at\s+/gm, '') 79 | .replace(/^Object.\s*\(/gm, '{anonymous}()@') : 'Unknown Stack Trace'; 80 | 81 | var log = window.console && (window.console.warn || window.console.log); 82 | if (log) { 83 | log.call(window.console, deprecationMessage, stack); 84 | } 85 | return method.apply(this, arguments); 86 | }; 87 | } 88 | 89 | /** 90 | * extend object. 91 | * means that properties in dest will be overwritten by the ones in src. 92 | * @param {Object} target 93 | * @param {...Object} objects_to_assign 94 | * @returns {Object} target 95 | */ 96 | var assign; 97 | if (typeof Object.assign !== 'function') { 98 | assign = function assign(target) { 99 | if (target === undefined || target === null) { 100 | throw new TypeError('Cannot convert undefined or null to object'); 101 | } 102 | 103 | var output = Object(target); 104 | for (var index = 1; index < arguments.length; index++) { 105 | var source = arguments[index]; 106 | if (source !== undefined && source !== null) { 107 | for (var nextKey in source) { 108 | if (source.hasOwnProperty(nextKey)) { 109 | output[nextKey] = source[nextKey]; 110 | } 111 | } 112 | } 113 | } 114 | return output; 115 | }; 116 | } else { 117 | assign = Object.assign; 118 | } 119 | 120 | /** 121 | * extend object. 122 | * means that properties in dest will be overwritten by the ones in src. 123 | * @param {Object} dest 124 | * @param {Object} src 125 | * @param {Boolean} [merge=false] 126 | * @returns {Object} dest 127 | */ 128 | var extend = deprecate(function extend(dest, src, merge) { 129 | var keys = Object.keys(src); 130 | var i = 0; 131 | while (i < keys.length) { 132 | if (!merge || (merge && dest[keys[i]] === undefined)) { 133 | dest[keys[i]] = src[keys[i]]; 134 | } 135 | i++; 136 | } 137 | return dest; 138 | }, 'extend', 'Use `assign`.'); 139 | 140 | /** 141 | * merge the values from src in the dest. 142 | * means that properties that exist in dest will not be overwritten by src 143 | * @param {Object} dest 144 | * @param {Object} src 145 | * @returns {Object} dest 146 | */ 147 | var merge = deprecate(function merge(dest, src) { 148 | return extend(dest, src, true); 149 | }, 'merge', 'Use `assign`.'); 150 | 151 | /** 152 | * simple class inheritance 153 | * @param {Function} child 154 | * @param {Function} base 155 | * @param {Object} [properties] 156 | */ 157 | function inherit(child, base, properties) { 158 | var baseP = base.prototype, 159 | childP; 160 | 161 | childP = child.prototype = Object.create(baseP); 162 | childP.constructor = child; 163 | childP._super = baseP; 164 | 165 | if (properties) { 166 | assign(childP, properties); 167 | } 168 | } 169 | 170 | /** 171 | * simple function bind 172 | * @param {Function} fn 173 | * @param {Object} context 174 | * @returns {Function} 175 | */ 176 | function bindFn(fn, context) { 177 | return function boundFn() { 178 | return fn.apply(context, arguments); 179 | }; 180 | } 181 | 182 | /** 183 | * let a boolean value also be a function that must return a boolean 184 | * this first item in args will be used as the context 185 | * @param {Boolean|Function} val 186 | * @param {Array} [args] 187 | * @returns {Boolean} 188 | */ 189 | function boolOrFn(val, args) { 190 | if (typeof val == TYPE_FUNCTION) { 191 | return val.apply(args ? args[0] || undefined : undefined, args); 192 | } 193 | return val; 194 | } 195 | 196 | /** 197 | * use the val2 when val1 is undefined 198 | * @param {*} val1 199 | * @param {*} val2 200 | * @returns {*} 201 | */ 202 | function ifUndefined(val1, val2) { 203 | return (val1 === undefined) ? val2 : val1; 204 | } 205 | 206 | /** 207 | * addEventListener with multiple events at once 208 | * @param {EventTarget} target 209 | * @param {String} types 210 | * @param {Function} handler 211 | */ 212 | function addEventListeners(target, types, handler) { 213 | each(splitStr(types), function(type) { 214 | target.addEventListener(type, handler, false); 215 | }); 216 | } 217 | 218 | /** 219 | * removeEventListener with multiple events at once 220 | * @param {EventTarget} target 221 | * @param {String} types 222 | * @param {Function} handler 223 | */ 224 | function removeEventListeners(target, types, handler) { 225 | each(splitStr(types), function(type) { 226 | target.removeEventListener(type, handler, false); 227 | }); 228 | } 229 | 230 | /** 231 | * find if a node is in the given parent 232 | * @method hasParent 233 | * @param {HTMLElement} node 234 | * @param {HTMLElement} parent 235 | * @return {Boolean} found 236 | */ 237 | function hasParent(node, parent) { 238 | while (node) { 239 | if (node == parent) { 240 | return true; 241 | } 242 | node = node.parentNode; 243 | } 244 | return false; 245 | } 246 | 247 | /** 248 | * small indexOf wrapper 249 | * @param {String} str 250 | * @param {String} find 251 | * @returns {Boolean} found 252 | */ 253 | function inStr(str, find) { 254 | return str.indexOf(find) > -1; 255 | } 256 | 257 | /** 258 | * split string on whitespace 259 | * @param {String} str 260 | * @returns {Array} words 261 | */ 262 | function splitStr(str) { 263 | return str.trim().split(/\s+/g); 264 | } 265 | 266 | /** 267 | * find if a array contains the object using indexOf or a simple polyFill 268 | * @param {Array} src 269 | * @param {String} find 270 | * @param {String} [findByKey] 271 | * @return {Boolean|Number} false when not found, or the index 272 | */ 273 | function inArray(src, find, findByKey) { 274 | if (src.indexOf && !findByKey) { 275 | return src.indexOf(find); 276 | } else { 277 | var i = 0; 278 | while (i < src.length) { 279 | if ((findByKey && src[i][findByKey] == find) || (!findByKey && src[i] === find)) { 280 | return i; 281 | } 282 | i++; 283 | } 284 | return -1; 285 | } 286 | } 287 | 288 | /** 289 | * convert array-like objects to real arrays 290 | * @param {Object} obj 291 | * @returns {Array} 292 | */ 293 | function toArray(obj) { 294 | return Array.prototype.slice.call(obj, 0); 295 | } 296 | 297 | /** 298 | * unique array with objects based on a key (like 'id') or just by the array's value 299 | * @param {Array} src [{id:1},{id:2},{id:1}] 300 | * @param {String} [key] 301 | * @param {Boolean} [sort=False] 302 | * @returns {Array} [{id:1},{id:2}] 303 | */ 304 | function uniqueArray(src, key, sort) { 305 | var results = []; 306 | var values = []; 307 | var i = 0; 308 | 309 | while (i < src.length) { 310 | var val = key ? src[i][key] : src[i]; 311 | if (inArray(values, val) < 0) { 312 | results.push(src[i]); 313 | } 314 | values[i] = val; 315 | i++; 316 | } 317 | 318 | if (sort) { 319 | if (!key) { 320 | results = results.sort(); 321 | } else { 322 | results = results.sort(function sortUniqueArray(a, b) { 323 | return a[key] > b[key]; 324 | }); 325 | } 326 | } 327 | 328 | return results; 329 | } 330 | 331 | /** 332 | * get the prefixed property 333 | * @param {Object} obj 334 | * @param {String} property 335 | * @returns {String|Undefined} prefixed 336 | */ 337 | function prefixed(obj, property) { 338 | var prefix, prop; 339 | var camelProp = property[0].toUpperCase() + property.slice(1); 340 | 341 | var i = 0; 342 | while (i < VENDOR_PREFIXES.length) { 343 | prefix = VENDOR_PREFIXES[i]; 344 | prop = (prefix) ? prefix + camelProp : property; 345 | 346 | if (prop in obj) { 347 | return prop; 348 | } 349 | i++; 350 | } 351 | return undefined; 352 | } 353 | 354 | /** 355 | * get a unique id 356 | * @returns {number} uniqueId 357 | */ 358 | var _uniqueId = 1; 359 | function uniqueId() { 360 | return _uniqueId++; 361 | } 362 | 363 | /** 364 | * get the window object of an element 365 | * @param {HTMLElement} element 366 | * @returns {DocumentView|Window} 367 | */ 368 | function getWindowForElement(element) { 369 | var doc = element.ownerDocument || element; 370 | return (doc.defaultView || doc.parentWindow || window); 371 | } 372 | -------------------------------------------------------------------------------- /node_modules/hammerjs/tests/manual/assets/style.css: -------------------------------------------------------------------------------- 1 | @import url(http://fonts.googleapis.com/css?family=Open+Sans); 2 | 3 | *, *:after, *:before { 4 | box-sizing: border-box; 5 | -moz-box-sizing: border-box; 6 | } 7 | 8 | html, body { 9 | margin: 0; 10 | padding: 0; 11 | height: 100%; 12 | min-height: 100%; 13 | background: #eee; 14 | font: 13px/1.5em 'Open Sans', Helvetica, Arial, sans-serif; 15 | } 16 | 17 | a { 18 | color: #4986e7; 19 | } 20 | 21 | .bg1, .green { background: #42d692; } 22 | .bg2, .blue { background: #4986e7; } 23 | .bg3, .red { background: #d06b64; } 24 | .bg4, .purple { background: #cd74e6; } 25 | .bg5, .azure { background: #9fe1e7; } 26 | 27 | body { 28 | margin: 20px; 29 | } 30 | 31 | pre { 32 | background: #fff; 33 | padding: 20px; 34 | margin-bottom: 20px; 35 | } 36 | 37 | .container { 38 | max-width: 900px; 39 | margin: 0 auto; 40 | } 41 | 42 | .clear { clear: both; } 43 | -------------------------------------------------------------------------------- /node_modules/hammerjs/tests/manual/compute_touch_action.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Open the inspector and play a bit with the touchAction property. 9 | 10 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /node_modules/hammerjs/tests/manual/input.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Hammer.js 9 | 10 | 11 |
12 |
13 |
14 | 15 |

16 | 
17 |         

18 |     
19 | 20 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /node_modules/hammerjs/tests/manual/log.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Hammer.js 8 | 9 | 10 |
11 | 12 |
13 | 14 |
15 | 16 |

17 | 
18 |         

19 | 
20 |     
21 | 22 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /node_modules/hammerjs/tests/manual/multiple.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Hammer.js 8 | 22 | 23 | 24 |
25 |

26 |         
27 | 
28 |         
29 | 30 |

Multiple instances the same time

31 |

You can run multiple instances of Hammer on your page and they will recognize each completely isolated 32 | from each other. This makes it possible to build multi-user interfaces.

33 | 34 |
35 | 36 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /node_modules/hammerjs/tests/manual/nested.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Hammer.js 9 | 47 | 48 | 49 | 50 | 51 |
52 |
53 |
54 |
1.1
55 |
1.2
56 |
1.3
57 |
1.4
58 |
1.5
59 |
60 |
61 |
62 |
63 |
2.1
64 |
2.2
65 |
2.3
66 |
2.4
67 |
2.5
68 |
69 |
70 |
71 |
72 |
3.1
73 |
3.2
74 |
3.3
75 |
3.4
76 |
3.5
77 |
78 |
79 |
80 |
81 |
4.1
82 |
4.2
83 |
4.3
84 |
4.4
85 |
4.5
86 |
87 |
88 |
89 |
90 |
5.1
91 |
5.2
92 |
5.3
93 |
5.4
94 |
5.5
95 |
96 |
97 |
98 | 99 |
100 |

Nested Pan recognizers

101 | 102 |

Nested recognizers are possible with some threshold and with use of requireFailure().

103 |
104 | 105 | 106 | 215 | 216 | 217 | 218 | -------------------------------------------------------------------------------- /node_modules/hammerjs/tests/manual/simulator-googlemaps.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Hammer.js 7 | 8 | 9 | 10 |
11 |
12 | 13 |

Gestures simulator

14 |

Used for unit-testing Hammer.js. To test it on the Google Maps view, you should open your 15 | 16 | Inspector and emulate a touch-screen. 17 | Or just open it on your touch-device.

18 |

Currently, it only triggers touchEvents.

19 |
20 | 21 | 22 | 23 | 98 | 99 | 100 | 101 | -------------------------------------------------------------------------------- /node_modules/hammerjs/tests/manual/simulator.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Hammer.js 7 | 8 | 9 | 10 |
11 | 12 |
13 |
14 | 15 |

 16 | 
 17 |     

 18 | 
 19 | 
20 | 21 | 22 | 23 | 116 | 117 | 118 | 119 | -------------------------------------------------------------------------------- /node_modules/hammerjs/tests/manual/touchaction.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Hammer.js 7 | 8 | 34 | 35 | 36 | 37 |
38 |

Hammer provides a kind of polyfill 39 | for the browsers that don't support the touch-action property.

40 | 41 |
Your browser has support for the touch-action property!
42 |
Your browser doesn't support the touch-action property, 43 | so we use the polyfill.
44 | 45 |

touch-action: auto

46 |

Should prevent nothing.

47 |
48 | 49 |

touch-action: pan-y

50 |

Should prevent scrolling on horizontal movement. This is set by default when creating a Hammer instance.

51 |
52 | 53 |

touch-action: pan-x

54 |

Should prevent scrolling on vertical movement.

55 |
56 | 57 |

touch-action: pan-x pan-y

58 |

Should not prevent any scrolling on any movement. Horizontal and vertical scrolling handled by the browser directly.

59 |
60 | 61 |

touch-action: none

62 |

Should prevent all.

63 |
64 |
65 | 66 | 86 | 87 |
88 |

hi.

89 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /node_modules/hammerjs/tests/manual/visual.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Hammer.js 7 | 8 | 37 | 38 | 39 | 40 |
41 |
42 | 43 | 44 | 45 | 210 | 211 | 212 | -------------------------------------------------------------------------------- /node_modules/hammerjs/tests/unit/assets/qunit.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * QUnit 1.14.0 3 | * http://qunitjs.com/ 4 | * 5 | * Copyright 2013 jQuery Foundation and other contributors 6 | * Released under the MIT license 7 | * http://jquery.org/license 8 | * 9 | * Date: 2014-01-31T16:40Z 10 | */ 11 | 12 | /** Font Family and Sizes */ 13 | 14 | #qunit-tests, #qunit-header, #qunit-banner, #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult { 15 | font-family: "Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial, sans-serif; 16 | } 17 | 18 | #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult, #qunit-tests li { font-size: small; } 19 | #qunit-tests { font-size: smaller; } 20 | 21 | 22 | /** Resets */ 23 | 24 | #qunit-tests, #qunit-header, #qunit-banner, #qunit-userAgent, #qunit-testresult, #qunit-modulefilter { 25 | margin: 0; 26 | padding: 0; 27 | } 28 | 29 | 30 | /** Header */ 31 | 32 | #qunit-header { 33 | padding: 0.5em 0 0.5em 1em; 34 | 35 | color: #8699A4; 36 | background-color: #0D3349; 37 | 38 | font-size: 1.5em; 39 | line-height: 1em; 40 | font-weight: 400; 41 | 42 | border-radius: 5px 5px 0 0; 43 | } 44 | 45 | #qunit-header a { 46 | text-decoration: none; 47 | color: #C2CCD1; 48 | } 49 | 50 | #qunit-header a:hover, 51 | #qunit-header a:focus { 52 | color: #FFF; 53 | } 54 | 55 | #qunit-testrunner-toolbar label { 56 | display: inline-block; 57 | padding: 0 0.5em 0 0.1em; 58 | } 59 | 60 | #qunit-banner { 61 | height: 5px; 62 | } 63 | 64 | #qunit-testrunner-toolbar { 65 | padding: 0.5em 0 0.5em 2em; 66 | color: #5E740B; 67 | background-color: #EEE; 68 | overflow: hidden; 69 | } 70 | 71 | #qunit-userAgent { 72 | padding: 0.5em 0 0.5em 2.5em; 73 | background-color: #2B81AF; 74 | color: #FFF; 75 | text-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px; 76 | } 77 | 78 | #qunit-modulefilter-container { 79 | float: right; 80 | } 81 | 82 | /** Tests: Pass/Fail */ 83 | 84 | #qunit-tests { 85 | list-style-position: inside; 86 | } 87 | 88 | #qunit-tests li { 89 | padding: 0.4em 0.5em 0.4em 2.5em; 90 | border-bottom: 1px solid #FFF; 91 | list-style-position: inside; 92 | } 93 | 94 | #qunit-tests.hidepass li.pass, #qunit-tests.hidepass li.running { 95 | display: none; 96 | } 97 | 98 | #qunit-tests li strong { 99 | cursor: pointer; 100 | } 101 | 102 | #qunit-tests li a { 103 | padding: 0.5em; 104 | color: #C2CCD1; 105 | text-decoration: none; 106 | } 107 | #qunit-tests li a:hover, 108 | #qunit-tests li a:focus { 109 | color: #000; 110 | } 111 | 112 | #qunit-tests li .runtime { 113 | float: right; 114 | font-size: smaller; 115 | } 116 | 117 | .qunit-assert-list { 118 | margin-top: 0.5em; 119 | padding: 0.5em; 120 | 121 | background-color: #FFF; 122 | 123 | border-radius: 5px; 124 | } 125 | 126 | .qunit-collapsed { 127 | display: none; 128 | } 129 | 130 | #qunit-tests table { 131 | border-collapse: collapse; 132 | margin-top: 0.2em; 133 | } 134 | 135 | #qunit-tests th { 136 | text-align: right; 137 | vertical-align: top; 138 | padding: 0 0.5em 0 0; 139 | } 140 | 141 | #qunit-tests td { 142 | vertical-align: top; 143 | } 144 | 145 | #qunit-tests pre { 146 | margin: 0; 147 | white-space: pre-wrap; 148 | word-wrap: break-word; 149 | } 150 | 151 | #qunit-tests del { 152 | background-color: #E0F2BE; 153 | color: #374E0C; 154 | text-decoration: none; 155 | } 156 | 157 | #qunit-tests ins { 158 | background-color: #FFCACA; 159 | color: #500; 160 | text-decoration: none; 161 | } 162 | 163 | /*** Test Counts */ 164 | 165 | #qunit-tests b.counts { color: #000; } 166 | #qunit-tests b.passed { color: #5E740B; } 167 | #qunit-tests b.failed { color: #710909; } 168 | 169 | #qunit-tests li li { 170 | padding: 5px; 171 | background-color: #FFF; 172 | border-bottom: none; 173 | list-style-position: inside; 174 | } 175 | 176 | /*** Passing Styles */ 177 | 178 | #qunit-tests li li.pass { 179 | color: #3C510C; 180 | background-color: #FFF; 181 | border-left: 10px solid #C6E746; 182 | } 183 | 184 | #qunit-tests .pass { color: #528CE0; background-color: #D2E0E6; } 185 | #qunit-tests .pass .test-name { color: #366097; } 186 | 187 | #qunit-tests .pass .test-actual, 188 | #qunit-tests .pass .test-expected { color: #999; } 189 | 190 | #qunit-banner.qunit-pass { background-color: #C6E746; } 191 | 192 | /*** Failing Styles */ 193 | 194 | #qunit-tests li li.fail { 195 | color: #710909; 196 | background-color: #FFF; 197 | border-left: 10px solid #EE5757; 198 | white-space: pre; 199 | } 200 | 201 | #qunit-tests > li:last-child { 202 | border-radius: 0 0 5px 5px; 203 | } 204 | 205 | #qunit-tests .fail { color: #000; background-color: #EE5757; } 206 | #qunit-tests .fail .test-name, 207 | #qunit-tests .fail .module-name { color: #000; } 208 | 209 | #qunit-tests .fail .test-actual { color: #EE5757; } 210 | #qunit-tests .fail .test-expected { color: #008000; } 211 | 212 | #qunit-banner.qunit-fail { background-color: #EE5757; } 213 | 214 | 215 | /** Result */ 216 | 217 | #qunit-testresult { 218 | padding: 0.5em 0.5em 0.5em 2.5em; 219 | 220 | color: #2B81AF; 221 | background-color: #D2E0E6; 222 | 223 | border-bottom: 1px solid #FFF; 224 | } 225 | #qunit-testresult .module-name { 226 | font-weight: 700; 227 | } 228 | 229 | /** Fixture */ 230 | 231 | #qunit-fixture { 232 | position: absolute; 233 | top: -10000px; 234 | left: -10000px; 235 | width: 1000px; 236 | height: 1000px; 237 | } 238 | -------------------------------------------------------------------------------- /node_modules/hammerjs/tests/unit/assets/utils.js: -------------------------------------------------------------------------------- 1 | var utils = { 2 | /** 3 | * trigger simple dom event 4 | * @param obj 5 | * @param name 6 | */ 7 | triggerDomEvent: function(obj, name) { 8 | var event = document.createEvent('Event'); 9 | event.initEvent(name, true, true); 10 | obj.dispatchEvent(event); 11 | }, 12 | 13 | 14 | createTouchEvent: function(name, x, y, identifier) { 15 | var event = document.createEvent('Event'); 16 | event.initEvent('touch' + name, true, true); 17 | 18 | event.touches = event.targetTouches = [{ 19 | clientX: x, 20 | clientY: y, 21 | identifier: identifier || 0 22 | }]; 23 | 24 | //https://developer.mozilla.org/en-US/docs/Web/API/TouchEvent.changedTouches 25 | event.changedTouches = [{ 26 | clientX: x, 27 | clientY: y, 28 | identifier: identifier || 0 29 | }]; 30 | 31 | return event; 32 | }, 33 | 34 | dispatchTouchEvent: function(el, name, x, y, identifier) { 35 | var event = utils.createTouchEvent(name, x, y, identifier); 36 | el.dispatchEvent(event); 37 | }, 38 | 39 | createHitArea: function(parent) { 40 | if (parent == null) { 41 | parent = document.getElementById('qunit-fixture') 42 | } 43 | var hitArea = document.createElement('div'); 44 | hitArea.style.background = '#eee'; 45 | hitArea.style.height = '300px'; 46 | 47 | parent.appendChild(hitArea); 48 | return hitArea; 49 | } 50 | }; 51 | -------------------------------------------------------------------------------- /node_modules/hammerjs/tests/unit/gestures/test_pan.js: -------------------------------------------------------------------------------- 1 | var el, 2 | hammer; 3 | 4 | module('Pan Gesture', { 5 | setup: function() { 6 | el = document.createElement('div'); 7 | document.body.appendChild(el); 8 | 9 | hammer = new Hammer(el, {recognizers: []}); 10 | }, 11 | teardown: function() { 12 | document.body.removeChild(el); 13 | hammer.destroy(); 14 | } 15 | }); 16 | 17 | test('`panstart` and `panmove` should be recognized', function() { 18 | expect(2); 19 | 20 | var panMoveCount = 0; 21 | var pan = new Hammer.Pan({threshold: 1}); 22 | 23 | hammer.add(pan); 24 | hammer.on('panstart', function() { 25 | ok(true); 26 | }); 27 | hammer.on('panmove', function() { 28 | panMoveCount++; 29 | }); 30 | 31 | utils.dispatchTouchEvent(el, 'start', 50, 50); 32 | utils.dispatchTouchEvent(el, 'move', 70, 50); 33 | utils.dispatchTouchEvent(el, 'move', 90, 50); 34 | 35 | equal(panMoveCount, 1); 36 | }); 37 | 38 | asyncTest('Pan event flow should be start -> left -> end', function() { 39 | expect(1); 40 | var pan = new Hammer.Pan({threshold: 1}); 41 | hammer.add(pan); 42 | 43 | var eventflow = ""; 44 | var isCalledPanleft = false; 45 | hammer.on('panstart', function() { 46 | eventflow += "start"; 47 | }); 48 | hammer.on('panleft', function() { 49 | if(!isCalledPanleft){ 50 | isCalledPanleft = true; 51 | eventflow += "left"; 52 | } 53 | }); 54 | hammer.on('panend', function() { 55 | eventflow += "end"; 56 | isCalledPanleft = true; 57 | }); 58 | 59 | Simulator.gestures.pan(el, { deltaX: -100, deltaY: 0 }, function() { 60 | equal(eventflow,"startleftend"); 61 | start(); 62 | }); 63 | }); 64 | -------------------------------------------------------------------------------- /node_modules/hammerjs/tests/unit/gestures/test_pinch.js: -------------------------------------------------------------------------------- 1 | var el, 2 | hammer; 3 | 4 | module('Pinch Gesture', { 5 | setup: function() { 6 | el = document.createElement('div'); 7 | document.body.appendChild(el); 8 | 9 | hammer = new Hammer(el, {recognizers: []}); 10 | }, 11 | teardown: function() { 12 | document.body.removeChild(el); 13 | hammer.destroy(); 14 | } 15 | }); 16 | 17 | asyncTest('Pinch event flow should be start -> in -> end', function() { 18 | expect(1); 19 | var pinch = new Hammer.Pinch({enable: true, threshold: .1}); 20 | hammer.add(pinch); 21 | 22 | var eventflow = ""; 23 | var isFiredPinchin = false; 24 | hammer.on('pinchstart', function() { 25 | eventflow += "start"; 26 | }); 27 | hammer.on('pinchin', function() { 28 | if(!isFiredPinchin){ 29 | isFiredPinchin = true; 30 | eventflow += "in"; 31 | } 32 | }); 33 | hammer.on('pinchend', function() { 34 | eventflow += "end"; 35 | isFiredPinchin = false; 36 | }); 37 | 38 | Simulator.gestures.pinch(el, { duration: 500, scale: .5 }, function() { 39 | equal(eventflow,"startinend"); 40 | start(); 41 | }); 42 | }); 43 | 44 | -------------------------------------------------------------------------------- /node_modules/hammerjs/tests/unit/gestures/test_swipe.js: -------------------------------------------------------------------------------- 1 | var el, 2 | hammer, 3 | swipeCount = 0; 4 | 5 | module('Swipe Gesture', { 6 | setup: function() { 7 | el = utils.createHitArea(); 8 | hammer = new Hammer(el, {recognizers: []}); 9 | swipeCount = 0; 10 | }, 11 | teardown: function() { 12 | hammer.destroy(); 13 | } 14 | }); 15 | 16 | test('swipe can be recognized', function() { 17 | expect(1); 18 | 19 | var swipe = new Hammer.Swipe({threshold: 1}); 20 | hammer.add(swipe); 21 | hammer.on('swipe', function() { 22 | ok(true); 23 | start(); 24 | }); 25 | 26 | stop(); 27 | 28 | Simulator.gestures.swipe(el); 29 | }); 30 | -------------------------------------------------------------------------------- /node_modules/hammerjs/tests/unit/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Tests 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 19 | 20 | 21 | 22 | 23 |
24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /node_modules/hammerjs/tests/unit/test_enable.js: -------------------------------------------------------------------------------- 1 | var el, 2 | hammer, 3 | counter; 4 | 5 | module('Test recognizer enable', { 6 | setup: function() { 7 | el = utils.createHitArea(); 8 | hammer = new Hammer.Manager(el, {recognizers: []}); 9 | counter = 0; 10 | }, 11 | teardown: function() { 12 | hammer && hammer.destroy(); 13 | } 14 | }); 15 | 16 | test('should disable a recognizer through the `enable` constructor parameter', function() { 17 | expect(1); 18 | hammer.add(new Hammer.Tap({enable: false})); 19 | hammer.on('tap', function() { 20 | counter++; 21 | }); 22 | 23 | stop(); 24 | utils.dispatchTouchEvent(el, 'start', 50, 50); 25 | utils.dispatchTouchEvent(el, 'end', 50, 50); 26 | 27 | setTimeout(function() { 28 | start(); 29 | equal(counter, 0); 30 | }, 100); 31 | }); 32 | 33 | test('should disable recognizing when the manager is disabled.', function() { 34 | expect(1); 35 | hammer.set({ enable: false }); 36 | hammer.add(new Hammer.Tap()); 37 | hammer.on('tap', function() { 38 | counter++; 39 | }); 40 | 41 | stop(); 42 | 43 | utils.dispatchTouchEvent(el, 'start', 50, 50); 44 | utils.dispatchTouchEvent(el, 'end', 50, 50); 45 | 46 | setTimeout(function() { 47 | start(); 48 | equal(counter, 0); 49 | }, 100); 50 | }); 51 | 52 | test('should toggle a recognizer using the `set` call to the recognizer enable property', function() { 53 | expect(2); 54 | 55 | hammer.add(new Hammer.Tap()); 56 | hammer.on('tap', function() { 57 | counter++; 58 | }); 59 | 60 | utils.dispatchTouchEvent(el, 'start', 50, 50); 61 | utils.dispatchTouchEvent(el, 'end', 50, 50); 62 | equal(counter, 1); 63 | 64 | hammer.get('tap').set({ enable: false }); 65 | 66 | utils.dispatchTouchEvent(el, 'start', 50, 50); 67 | utils.dispatchTouchEvent(el, 'end', 50, 50); 68 | equal(counter, 1); 69 | }); 70 | 71 | test('should accept the `enable` constructor parameter as function', function() { 72 | expect(2); 73 | 74 | var canRecognizeTap = false; 75 | 76 | var tap = new Hammer.Tap({ 77 | enable: function() { 78 | return canRecognizeTap; 79 | } 80 | }); 81 | 82 | hammer.add(tap); 83 | hammer.on('tap', function() { 84 | counter++; 85 | }); 86 | 87 | stop(); 88 | utils.dispatchTouchEvent(el, 'start', 50, 50); 89 | utils.dispatchTouchEvent(el, 'end', 50, 50); 90 | 91 | setTimeout(function() { 92 | start(); 93 | equal(counter, 0); 94 | 95 | canRecognizeTap = true; 96 | 97 | utils.dispatchTouchEvent(el, 'start', 50, 50); 98 | utils.dispatchTouchEvent(el, 'end', 50, 50); 99 | 100 | equal(counter, 1); 101 | }, 100); 102 | }); 103 | 104 | test('should accept a function parameter with `set`', function() { 105 | expect(3); 106 | 107 | hammer.add(new Hammer.Tap()); 108 | hammer.on('tap', function() { 109 | counter++; 110 | }); 111 | 112 | utils.dispatchTouchEvent(el, 'start', 50, 50); 113 | utils.dispatchTouchEvent(el, 'end', 50, 50); 114 | equal(counter, 1); 115 | 116 | var canRecognizeTap = false; 117 | hammer.get('tap').set({ enable: function() { 118 | return canRecognizeTap; 119 | }}); 120 | 121 | utils.dispatchTouchEvent(el, 'start', 50, 50); 122 | utils.dispatchTouchEvent(el, 'end', 50, 50); 123 | equal(counter, 1); 124 | 125 | canRecognizeTap = true; 126 | utils.dispatchTouchEvent(el, 'start', 50, 50); 127 | utils.dispatchTouchEvent(el, 'end', 50, 50); 128 | equal(counter, 2); 129 | }); 130 | 131 | test('should pass the recognizer and optional the input parameter to the `enable` callback', function() { 132 | expect(2); 133 | 134 | var tap; 135 | 136 | // the enable function is called initially to setup the touch-action property 137 | // at that moment there isnt any input 138 | var canEnable = function(recognizer, input) { 139 | equal(recognizer, tap); 140 | return true; 141 | }; 142 | tap = new Hammer.Tap({enable: canEnable}); 143 | hammer.add(tap); 144 | 145 | utils.dispatchTouchEvent(el, 'start', 50, 50); 146 | }); 147 | 148 | test('should toggle based on other object method', function() { 149 | expect(2); 150 | 151 | var view = { 152 | state: 0, 153 | canRecognizeTap: function(recognizer, input) { 154 | return this.state !== 0; 155 | } 156 | }; 157 | 158 | hammer.add(new Hammer.Tap({enable: function(rec, input) { return view.canRecognizeTap(rec, input); } })); 159 | hammer.on('tap', function() { 160 | counter++; 161 | }); 162 | 163 | utils.dispatchTouchEvent(el, 'start', 50, 50); 164 | utils.dispatchTouchEvent(el, 'end', 50, 50); 165 | equal(counter, 0); 166 | 167 | view.state = 1; 168 | utils.dispatchTouchEvent(el, 'start', 50, 50); 169 | utils.dispatchTouchEvent(el, 'end', 50, 50); 170 | equal(counter, 1); 171 | }); 172 | -------------------------------------------------------------------------------- /node_modules/hammerjs/tests/unit/test_events.js: -------------------------------------------------------------------------------- 1 | module('eventEmitter'); 2 | 3 | test('test the eventemitter', function() { 4 | expect(6); 5 | 6 | var ee = new Hammer.Manager(utils.createHitArea()); 7 | var inputData = { 8 | target: document.body, 9 | srcEvent: { 10 | preventDefault: function() { 11 | ok(true, 'preventDefault ref'); 12 | }, 13 | target: document.body 14 | } 15 | }; 16 | 17 | function event3Handler() { 18 | ok(true, 'emitted event3'); 19 | } 20 | 21 | ee.on('testEvent1', function() { 22 | ok(true, 'emitted event'); 23 | }); 24 | ee.on('testEvent2', function(ev) { 25 | ok(true, 'emitted event'); 26 | ev.preventDefault(); 27 | ok(ev.target === document.body, 'target is the body'); 28 | }); 29 | ee.on('testEvent3', event3Handler); 30 | 31 | ee.emit('testEvent1', inputData); 32 | ee.emit('testEvent2', inputData); 33 | ee.emit('testEvent3', inputData); 34 | 35 | // unbind testEvent2 36 | ee.off('testEvent2'); 37 | ee.off('testEvent3', event3Handler); 38 | 39 | ee.emit('testEvent1', inputData); // should trigger testEvent1 again 40 | ee.emit('testEvent2', inputData); // doenst trigger a thing 41 | ee.emit('testEvent3', inputData); // doenst trigger a thing 42 | 43 | // destroy 44 | ee.destroy(); 45 | 46 | ee.emit('testEvent1', inputData); // doenst trigger a thing 47 | ee.emit('testEvent2', inputData); // doenst trigger a thing 48 | ee.emit('testEvent3', inputData); // doenst trigger a thing 49 | }); 50 | 51 | /* 52 | * Hammer.Manager.off method : exception handling 53 | */ 54 | test("When Hammer.Manager didn't attach an event, 'off' method is ignored", function() { 55 | var count = 0; 56 | hammer = new Hammer(el, { inputTarget: document.body }); 57 | hammer.off("swipeleft", function(e) { 58 | count++; 59 | }); 60 | ok(true, "nothing"); 61 | }); 62 | -------------------------------------------------------------------------------- /node_modules/hammerjs/tests/unit/test_gestures.js: -------------------------------------------------------------------------------- 1 | // TODO: this tests fails because tapRecognizer changes 2 | // it could be that tapRecognizer setup its BEGAN state and 3 | // disable the other gesture recognition 4 | var el, hammer, events; 5 | var allGestureEvents = [ 6 | 'tap doubletap press', 7 | 'pinch pinchin pinchout pinchstart pinchmove pinchend pinchcancel', 8 | 'rotate rotatestart rotatemove rotateend rotatecancel', 9 | 'pan panstart panmove panup pandown panleft panright panend pancancel', 10 | 'swipe swipeleft swiperight swipeup swipedown' 11 | ].join(' '); 12 | 13 | module('Gesture recognition', { 14 | setup: function() { 15 | el = utils.createHitArea(); 16 | hammer = new Hammer(el); 17 | hammer.get('pinch') 18 | .set({ // some threshold, since the simulator doesnt stays at scale:1 when rotating 19 | enable: true, 20 | threshold: .1 21 | }); 22 | 23 | hammer.get('rotate') 24 | .set({ enable: true }); 25 | 26 | hammer.on(allGestureEvents, function(ev) { 27 | events[ev.type] = true; 28 | }); 29 | events = {}; 30 | }, 31 | teardown: function() { 32 | hammer && hammer.destroy(); 33 | events = null; 34 | } 35 | }); 36 | 37 | asyncTest('recognize pan', function() { 38 | expect(1); 39 | 40 | Simulator.gestures.pan(el, { duration: 500, deltaX: 100, deltaY: 0 }, function() { 41 | start(); 42 | deepEqual(events, { 43 | pan: true, 44 | panstart: true, 45 | panmove: true, 46 | panright: true, 47 | panend: true 48 | }); 49 | }); 50 | }); 51 | 52 | asyncTest('recognize press', function() { 53 | expect(1); 54 | 55 | Simulator.gestures.press(el, null, function() { 56 | start(); 57 | deepEqual(events, { 58 | press: true 59 | }); 60 | }); 61 | }); 62 | 63 | asyncTest('recognize swipe', function() { 64 | expect(1); 65 | 66 | Simulator.gestures.swipe(el, { duration: 300, deltaX: 400, deltaY: 0 }, function() { 67 | start(); 68 | deepEqual(events, { 69 | pan: true, 70 | panstart: true, 71 | panmove: true, 72 | panright: true, 73 | panend: true, 74 | swipe: true, 75 | swiperight: true 76 | }); 77 | }); 78 | }); 79 | 80 | asyncTest('recognize pinch', function() { 81 | expect(1); 82 | 83 | Simulator.gestures.pinch(el, { duration: 500, scale: .5 }, function() { 84 | start(); 85 | deepEqual(events, { 86 | pinch: true, 87 | pinchstart: true, 88 | pinchmove: true, 89 | pinchend: true, 90 | pinchin: true 91 | }); 92 | }); 93 | }); 94 | 95 | asyncTest('recognize children multitouch pinch', function() { 96 | expect(1); 97 | 98 | var el1 = utils.createHitArea(el), 99 | el2 = utils.createHitArea(el); 100 | 101 | Simulator.gestures.pinch([el1, el2], { duration: 500, scale: .5 }, function() { 102 | start(); 103 | deepEqual(events, { 104 | pinch: true, 105 | pinchstart: true, 106 | pinchmove: true, 107 | pinchend: true, 108 | pinchin: true 109 | }); 110 | }); 111 | }); 112 | 113 | asyncTest('recognize parent-child multitouch pinch', function() { 114 | expect(1); 115 | 116 | var el1 = utils.createHitArea(el); 117 | 118 | Simulator.gestures.pinch([el, el1], { duration: 100, scale: .5 }, function() { 119 | start(); 120 | deepEqual(events, { 121 | pinch: true, 122 | pinchstart: true, 123 | pinchmove: true, 124 | pinchend: true, 125 | pinchin: true 126 | }); 127 | }); 128 | }); 129 | 130 | asyncTest('recognize rotate', function() { 131 | expect(1); 132 | 133 | Simulator.gestures.rotate(el, { duration: 500, scale: 1 }, function() { 134 | start(); 135 | deepEqual(events, { 136 | rotate: true, 137 | rotatestart: true, 138 | rotatemove: true, 139 | rotateend: true 140 | }); 141 | }); 142 | }); 143 | 144 | asyncTest('recognize multitouch rotate', function() { 145 | expect(1); 146 | 147 | var el1 = utils.createHitArea(el); 148 | 149 | Simulator.gestures.rotate([el, el1], { duration: 500, scale: 1 }, function() { 150 | start(); 151 | deepEqual(events, { 152 | rotate: true, 153 | rotatestart: true, 154 | rotatemove: true, 155 | rotateend: true 156 | }); 157 | }); 158 | }); 159 | 160 | asyncTest('recognize rotate and pinch simultaneous', function() { 161 | expect(1); 162 | 163 | Simulator.gestures.pinchRotate(el, { duration: 500, scale: 2 }, function() { 164 | start(); 165 | deepEqual(events, { 166 | rotate: true, 167 | rotatestart: true, 168 | rotatemove: true, 169 | rotateend: true, 170 | pinch: true, 171 | pinchstart: true, 172 | pinchmove: true, 173 | pinchend: true, 174 | pinchout: true 175 | }); 176 | }); 177 | }); 178 | 179 | asyncTest('don\'t recognize pan and swipe when moving down, when only horizontal is allowed', function() { 180 | expect(1); 181 | 182 | Simulator.gestures.swipe(el, { duration: 250, deltaX: 0, deltaZ: 200 }, function() { 183 | start(); 184 | deepEqual(events, { }); 185 | }); 186 | }); 187 | 188 | asyncTest('don\'t recognize press if duration is too short.', function() { 189 | expect(1); 190 | 191 | Simulator.gestures.press(el, { duration: 240 }); 192 | 193 | setTimeout(function() { 194 | start(); 195 | deepEqual(events, { tap: true }, 'Tap gesture has been recognized.'); 196 | }, 275); 197 | }); 198 | 199 | asyncTest('don\'t recognize tap if duration is too long.', function() { 200 | expect(1); 201 | 202 | Simulator.gestures.tap(el, { duration: 255 }); 203 | 204 | setTimeout(function() { 205 | start(); 206 | deepEqual(events, { press: true }, 'Press gesture has been recognized.'); 207 | }, 275); 208 | }); 209 | -------------------------------------------------------------------------------- /node_modules/hammerjs/tests/unit/test_hammer.js: -------------------------------------------------------------------------------- 1 | var el, el2, 2 | hammer, hammer2; 3 | 4 | module('Tests', { 5 | setup: function() { 6 | el = utils.createHitArea(); 7 | el2 = utils.createHitArea(); 8 | }, 9 | 10 | teardown: function() { 11 | if (hammer) { 12 | hammer.destroy(); 13 | hammer = null; 14 | } 15 | if (hammer2) { 16 | hammer2.destroy(); 17 | hammer2 = null; 18 | } 19 | } 20 | }); 21 | 22 | test('hammer shortcut', function() { 23 | expect(2); 24 | 25 | Hammer.defaults.touchAction = 'pan-y'; 26 | hammer = Hammer(el); 27 | 28 | ok(hammer instanceof Hammer.Manager, 'returns an instance of Manager'); 29 | ok(hammer.touchAction.actions == Hammer.defaults.touchAction, 'set the default touchAction'); 30 | }); 31 | 32 | test('hammer shortcut with options', function() { 33 | expect(2); 34 | 35 | hammer = Hammer(el, { 36 | touchAction: 'none' 37 | }); 38 | ok(hammer instanceof Hammer.Manager, 'returns an instance of Manager'); 39 | ok(hammer.touchAction.actions == 'none', 'set the default touchAction'); 40 | }); 41 | 42 | /* Creating a hammer instance does not work on the same way 43 | * when using Hammer or Hammer.Manager. 44 | * 45 | * This can confuse developers who read tests to use the library when doc is missing. 46 | */ 47 | test('Hammer and Hammer.Manager constructors work exactly on the same way.', function() { 48 | expect(2); 49 | 50 | hammer = new Hammer(el, {}); 51 | equal(Hammer.defaults.preset.length, hammer.recognizers.length); 52 | 53 | hammer2 = new Hammer.Manager(el, {}); 54 | equal(0, hammer2.recognizers.length); 55 | }); 56 | 57 | /* DOC to disable default recognizers should be added. 58 | * 59 | * - Hammer(el). IMO: Currently, well done. 60 | * - Hammer(el, {}) . IMO: should disable default recognizers 61 | * - Hammer(el, {recognizers: null}). IMO: now, it fails. 62 | * - Hammer(el, {recognizers: []}). It works, but it is likely not intuitive. 63 | */ 64 | test('A Hammer instance can be setup to not having default recognizers.', function() { 65 | expect(1); 66 | 67 | hammer = new Hammer(el, { recognizers: false }); 68 | equal(0, hammer.recognizers.length); 69 | }); 70 | 71 | /* The case was when I added a custom tap event which was added to the default 72 | * recognizers, and my custom tap gesture wasn't working (I do not know exactly the reason), 73 | * but removing the default recognizers solved the issue. 74 | */ 75 | test('Adding the same recognizer type should remove the old recognizer', function() { 76 | expect(4); 77 | 78 | hammer = new Hammer(el); 79 | 80 | ok(!!hammer.get('tap')); 81 | equal(7, hammer.recognizers.length); 82 | 83 | var newTap = new Hammer.Tap({time: 1337}); 84 | hammer.add(newTap); 85 | 86 | equal(7, hammer.recognizers.length); 87 | equal(1337, hammer.get('tap').options.time); 88 | }); 89 | 90 | /* 91 | * Swipe gesture: 92 | * - in this tests, it does not update input.velocity ( always 0) 93 | * - does not fire swipeleft or swiperight events 94 | */ 95 | asyncTest('Swiping to the left should fire swipeleft event', function() { 96 | expect(2); 97 | 98 | hammer = new Hammer(el, {recognizers: []}); 99 | hammer.add(new Hammer.Swipe()); 100 | hammer.on('swipe swipeleft', function() { 101 | ok(true); 102 | }); 103 | 104 | Simulator.gestures.swipe(el, {pos: [300, 300], deltaY: 0, deltaX: -200}, function() { 105 | start(); 106 | }); 107 | }); 108 | 109 | /* 110 | * Input target change 111 | */ 112 | asyncTest('Should detect input while on other element', function() { 113 | expect(1); 114 | 115 | hammer = new Hammer(el, { inputTarget: document.body }); 116 | hammer.on('tap', function() { 117 | ok(true); 118 | }); 119 | 120 | Simulator.gestures.tap(document.body, null, function() { 121 | start(); 122 | }); 123 | }); 124 | 125 | /* Hammer.Manager constructor accepts a "recognizers" option in which each 126 | * element is an array representation of a Recognizer. 127 | */ 128 | test('Hammer.Manager accepts recognizers as arrays.', function() { 129 | expect(4); 130 | 131 | hammer = new Hammer.Manager(el, { 132 | recognizers: [ 133 | [Hammer.Swipe], 134 | [Hammer.Pinch], 135 | [Hammer.Rotate], 136 | [Hammer.Pan, { direction: Hammer.DIRECTION_UP }, ['swipe', 'pinch'], ['rotate']] 137 | ] 138 | }); 139 | equal(4, hammer.recognizers.length); 140 | 141 | var recognizerActual = hammer.recognizers[3]; 142 | equal(recognizerActual.options.direction, Hammer.DIRECTION_UP); 143 | equal(2, Object.keys(recognizerActual.simultaneous).length); 144 | equal(1, recognizerActual.requireFail.length); 145 | }); 146 | 147 | /* 148 | * Removing a recognizer which cannot be found would errantly remove the last recognizer in the 149 | * manager's list. 150 | */ 151 | test('Remove non-existent recognizer.', function() { 152 | expect(1); 153 | 154 | hammer = new Hammer(el, {recognizers: []}); 155 | hammer.add(new Hammer.Swipe()); 156 | hammer.remove('tap'); 157 | 158 | equal(1, hammer.recognizers.length); 159 | }); 160 | 161 | test('check whether Hammer.defaults.cssProps is restored', function() { 162 | var beforeCssProps = { 163 | userSelect: 'text', 164 | touchSelect: 'grippers', 165 | touchCallout: 'default', 166 | contentZooming: 'chained', 167 | userDrag: 'element', 168 | tapHighlightColor: 'rgba(0, 1, 0, 0)' 169 | }; 170 | var prop; 171 | Hammer.each(Hammer.defaults.cssProps, function(value, name) { 172 | prop = Hammer.prefixed(el.style, name); 173 | if (prop) { 174 | el.style[prop] = beforeCssProps[name]; 175 | } 176 | }); 177 | 178 | hammer = Hammer(el); 179 | hammer.destroy(); 180 | hammer = null; 181 | Hammer.each(Hammer.defaults.cssProps, function(value, name) { 182 | prop = Hammer.prefixed(el.style, name); 183 | if (prop) { 184 | equal(el.style[prop], beforeCssProps[name], "check if " + name + " is restored"); 185 | } 186 | }); 187 | }); 188 | -------------------------------------------------------------------------------- /node_modules/hammerjs/tests/unit/test_jquery_plugin.js: -------------------------------------------------------------------------------- 1 | var el, hammer, events; 2 | 3 | var jQueryPluginPath = '../../node_modules/jquery-hammerjs/jquery.hammer.js'; 4 | 5 | module('jQuery plugin', { 6 | setup: function() { 7 | el = utils.createHitArea(); 8 | events = {}; 9 | }, 10 | teardown: function() { 11 | hammer && hammer.destroy(); 12 | } 13 | }); 14 | 15 | asyncTest('trigger pan with jQuery', function() { 16 | expect(2); 17 | 18 | $.getScript(jQueryPluginPath, function() { 19 | jQuery(el).hammer(); 20 | jQuery(el).bind('panstart pan panmove panright panend', function(ev) { 21 | if (ev.gesture) { 22 | events[ev.type] = true; 23 | } 24 | }); 25 | 26 | Simulator.gestures.pan(el, { deltaX: 50, deltaY: 0 }, function() { 27 | start(); 28 | deepEqual(events, { 29 | pan: true, 30 | panstart: true, 31 | panmove: true, 32 | panright: true, 33 | panend: true 34 | }); 35 | 36 | ok(jQuery(el).data('hammer') instanceof Hammer.Manager, 'data attribute refers to the instance'); 37 | }); 38 | }); 39 | }); 40 | 41 | asyncTest('trigger pan without jQuery should still work', function() { 42 | expect(1); 43 | 44 | var hammer = Hammer(el); 45 | hammer.on('panstart pan panmove panright panend', function(ev) { 46 | events[ev.type] = true; 47 | }); 48 | 49 | Simulator.gestures.pan(el, { deltaX: 50, deltaY: 0 }, function() { 50 | start(); 51 | deepEqual(events, { 52 | pan: true, 53 | panstart: true, 54 | panmove: true, 55 | panright: true, 56 | panend: true 57 | }); 58 | }); 59 | }); 60 | -------------------------------------------------------------------------------- /node_modules/hammerjs/tests/unit/test_multiple_taps.js: -------------------------------------------------------------------------------- 1 | var el, hammer; 2 | 3 | var tripleTapCount = 0, 4 | doubleTapCount = 0, 5 | tapCount = 0; 6 | 7 | module('Tap delay', { 8 | setup: function() { 9 | el = utils.createHitArea(); 10 | hammer = new Hammer(el, {recognizers: []}); 11 | 12 | var tap = new Hammer.Tap(); 13 | var doubleTap = new Hammer.Tap({event: 'doubleTap', taps: 2 }); 14 | var tripleTap = new Hammer.Tap({event: 'tripleTap', taps: 3 }); 15 | 16 | hammer.add([tripleTap, doubleTap, tap]); 17 | 18 | tripleTap.recognizeWith([doubleTap, tap]); 19 | doubleTap.recognizeWith(tap); 20 | 21 | doubleTap.requireFailure(tripleTap); 22 | tap.requireFailure([tripleTap, doubleTap]); 23 | 24 | tripleTapCount = 0; 25 | doubleTapCount = 0; 26 | tapCount = 0; 27 | 28 | hammer.on('tap', function() { 29 | tapCount++; 30 | }); 31 | hammer.on('doubleTap', function() { 32 | doubleTapCount++; 33 | }); 34 | hammer.on('tripleTap', function() { 35 | tripleTapCount++; 36 | }); 37 | }, 38 | teardown: function() { 39 | hammer.destroy(); 40 | } 41 | }); 42 | asyncTest('When a tripleTap is fired, doubleTap and Tap should not be recognized', function() { 43 | expect(3); 44 | 45 | utils.dispatchTouchEvent(el, 'start', 50, 50); 46 | utils.dispatchTouchEvent(el, 'end', 50, 50); 47 | 48 | utils.dispatchTouchEvent(el, 'start', 50, 50); 49 | utils.dispatchTouchEvent(el, 'end', 50, 50); 50 | 51 | utils.dispatchTouchEvent(el, 'start', 50, 50); 52 | utils.dispatchTouchEvent(el, 'end', 50, 50); 53 | 54 | setTimeout(function() { 55 | start(); 56 | equal(tripleTapCount, 1, 'one tripletap event'); 57 | equal(doubleTapCount, 0, 'no doubletap event'); 58 | equal(tapCount, 0, 'no singletap event'); 59 | }, 350); 60 | }); 61 | asyncTest('When a doubleTap is fired, tripleTap and Tap should not be recognized', function() { 62 | expect(3); 63 | 64 | utils.dispatchTouchEvent(el, 'start', 50, 50); 65 | utils.dispatchTouchEvent(el, 'end', 50, 50); 66 | 67 | utils.dispatchTouchEvent(el, 'start', 50, 50); 68 | utils.dispatchTouchEvent(el, 'end', 50, 50); 69 | 70 | setTimeout(function() { 71 | start(); 72 | equal(tripleTapCount, 0); 73 | equal(doubleTapCount, 1); 74 | equal(tapCount, 0); 75 | }, 350); 76 | }); 77 | 78 | asyncTest('When a tap is fired, tripleTap and doubleTap should not be recognized', function() { 79 | expect(3); 80 | 81 | utils.dispatchTouchEvent(el, 'start', 50, 50); 82 | utils.dispatchTouchEvent(el, 'end', 50, 50); 83 | 84 | setTimeout(function() { 85 | start(); 86 | equal(tripleTapCount, 0); 87 | equal(doubleTapCount, 0); 88 | equal(tapCount, 1); 89 | }, 350); 90 | }); 91 | -------------------------------------------------------------------------------- /node_modules/hammerjs/tests/unit/test_nested_gesture_recognizers.js: -------------------------------------------------------------------------------- 1 | var parent, 2 | child, 3 | hammerChild, 4 | hammerParent; 5 | 6 | module('Nested gesture recognizers (Tap Child + Pan Parent)', { 7 | setup: function() { 8 | parent = document.createElement('div'); 9 | child = document.createElement('div'); 10 | 11 | document.getElementById('qunit-fixture').appendChild(parent); 12 | parent.appendChild(child); 13 | 14 | hammerParent = new Hammer.Manager(parent, { 15 | touchAction: 'none' 16 | }); 17 | hammerChild = new Hammer.Manager(child, { 18 | touchAction: 'none' 19 | }); 20 | 21 | hammerChild.add(new Hammer.Tap()); 22 | hammerParent.add(new Hammer.Pan({threshold: 5, pointers: 1})); 23 | }, 24 | teardown: function() { 25 | hammerChild.destroy(); 26 | hammerParent.destroy(); 27 | } 28 | }); 29 | 30 | test('Tap on the child', function() { 31 | expect(1); 32 | 33 | hammerChild.on('tap', function() { 34 | ok(true); 35 | }); 36 | hammerParent.on('tap', function() { 37 | throw new Error('tap should not fire on parent'); 38 | }); 39 | 40 | utils.dispatchTouchEvent(child, 'start', 0, 10); 41 | utils.dispatchTouchEvent(child, 'end', 0, 10); 42 | }); 43 | 44 | test('Panning on the child should fire parent pan and should not fire child tap event', function() { 45 | expect(1); 46 | 47 | hammerChild.on('tap', function() { 48 | throw new Error('tap should not fire on parent'); 49 | }); 50 | hammerParent.on('panend', function() { 51 | ok(true); 52 | }); 53 | 54 | utils.dispatchTouchEvent(child, 'start', 10, 0); 55 | utils.dispatchTouchEvent(child, 'move', 20, 0); 56 | utils.dispatchTouchEvent(child, 'end', 30, 0); 57 | 58 | }); 59 | 60 | /* 61 | // test (optional pointers validation) 62 | test('Panning with one finger down on child, other on parent', function () { 63 | expect(1); 64 | 65 | var event, 66 | touches; 67 | 68 | hammerParent.on('panend', function () { 69 | ok(true); 70 | }); 71 | 72 | // one finger one child 73 | utils.dispatchTouchEvent(child, 'start', 10, 0, 0); 74 | utils.dispatchTouchEvent(parent, 'start', 12, 0, 1); 75 | 76 | touches = [ 77 | {clientX: 20, clientY: 0, identifier: 0 }, 78 | {clientX: 20, clientY: 0, identifier: 1 } 79 | ]; 80 | 81 | event = document.createEvent('Event'); 82 | event.initEvent('touchmove', true, true); 83 | event.touches = touches; 84 | event.changedTouches = touches; 85 | 86 | parent.dispatchEvent(event); 87 | 88 | touches = [ 89 | {clientX: 30, clientY: 0, identifier: 0 }, 90 | {clientX: 30, clientY: 0, identifier: 1 } 91 | ]; 92 | 93 | event = document.createEvent('Event'); 94 | event.initEvent('touchend', true, true); 95 | event.touches = touches; 96 | event.changedTouches = touches; 97 | 98 | parent.dispatchEvent(event); 99 | }); 100 | */ 101 | 102 | var pressPeriod = 600; 103 | module('Nested gesture recognizers (Press Child + Pan Parent)', { 104 | setup: function() { 105 | parent = document.createElement('div'); 106 | child = document.createElement('div'); 107 | 108 | document.getElementById('qunit-fixture').appendChild(parent); 109 | parent.appendChild(child); 110 | 111 | hammerParent = new Hammer.Manager(parent, { 112 | touchAction: 'none' 113 | }); 114 | hammerChild = new Hammer.Manager(child, { 115 | touchAction: 'none' 116 | }); 117 | 118 | hammerChild.add(new Hammer.Press({time: pressPeriod})); 119 | hammerParent.add(new Hammer.Pan({threshold: 5, pointers: 1})); 120 | }, 121 | teardown: function() { 122 | hammerChild.destroy(); 123 | hammerParent.destroy(); 124 | } 125 | }); 126 | 127 | test('Press on the child', function() { 128 | expect(1); 129 | 130 | hammerChild.on('press', function() { 131 | ok(true); 132 | }); 133 | hammerParent.on('press', function() { 134 | throw new Error('press should not fire on parent'); 135 | }); 136 | 137 | utils.dispatchTouchEvent(child, 'start', 0, 10); 138 | 139 | stop(); 140 | 141 | setTimeout(function() { 142 | start(); 143 | }, pressPeriod); 144 | }); 145 | 146 | test('When Press is followed by Pan on the same element, both gestures are recognized', function() { 147 | expect(2); 148 | hammerChild.on('press', function() { 149 | ok(true); 150 | }); 151 | hammerParent.on('panend', function() { 152 | ok(true); 153 | }); 154 | 155 | utils.dispatchTouchEvent(child, 'start', 0, 10); 156 | stop(); 157 | 158 | setTimeout(function() { 159 | start(); 160 | 161 | utils.dispatchTouchEvent(child, 'move', 10, 10); 162 | utils.dispatchTouchEvent(child, 'move', 20, 10); 163 | utils.dispatchTouchEvent(child, 'move', 30, 10); 164 | utils.dispatchTouchEvent(child, 'end', 30, 10); 165 | 166 | }, pressPeriod); 167 | }); 168 | -------------------------------------------------------------------------------- /node_modules/hammerjs/tests/unit/test_propagation_bubble.js: -------------------------------------------------------------------------------- 1 | var parent, 2 | child, 3 | hammerChild, 4 | hammerParent; 5 | 6 | module('Propagation (Tap in Child and Parent)', { 7 | setup: function() { 8 | parent = document.createElement('div'); 9 | child = document.createElement('div'); 10 | 11 | document.getElementById('qunit-fixture').appendChild(parent); 12 | parent.appendChild(child); 13 | 14 | hammerParent = new Hammer.Manager(parent); 15 | hammerChild = new Hammer.Manager(child); 16 | 17 | hammerChild.add(new Hammer.Tap()); 18 | hammerParent.add(new Hammer.Tap()); 19 | }, 20 | teardown: function() { 21 | hammerChild.destroy(); 22 | hammerParent.destroy(); 23 | } 24 | }); 25 | 26 | test('Tap on the child, fires also the tap event to the parent', function() { 27 | expect(2); 28 | 29 | hammerChild.on('tap', function() { 30 | ok(true); 31 | }); 32 | hammerParent.on('tap', function() { 33 | ok(true); 34 | }); 35 | 36 | utils.dispatchTouchEvent(child, 'start', 0, 10); 37 | utils.dispatchTouchEvent(child, 'end', 0, 10); 38 | }); 39 | 40 | test('When tap on the child and the child stops the input event propagation, the tap event does not get fired in the parent', function() { 41 | expect(1); 42 | 43 | hammerChild.on('tap', function() { 44 | ok(true); 45 | }); 46 | hammerParent.on('tap', function() { 47 | throw new Error('parent tap gesture should not be recognized'); 48 | }); 49 | 50 | child.addEventListener('touchend', function(ev) { 51 | ev.stopPropagation(); 52 | }); 53 | 54 | utils.dispatchTouchEvent(child, 'start', 0, 10); 55 | utils.dispatchTouchEvent(child, 'end', 0, 10); 56 | }); 57 | -------------------------------------------------------------------------------- /node_modules/hammerjs/tests/unit/test_require_failure.js: -------------------------------------------------------------------------------- 1 | var el, 2 | hammer, 3 | pressPeriod = 200, 4 | pressThreshold = 20, 5 | pressCount = 0, 6 | panStartCount = 0, 7 | swipeCount = 0; 8 | 9 | module('Require Failure ( Swipe & Press )', { 10 | setup: function() { 11 | el = utils.createHitArea(); 12 | hammer = new Hammer(el, {recognizers: []}); 13 | 14 | var swipe = new Hammer.Swipe({threshold: 1}); 15 | var press = new Hammer.Press({time: pressPeriod, threshold: pressThreshold}); 16 | 17 | hammer.add(swipe); 18 | hammer.add(press); 19 | 20 | swipe.recognizeWith(press); 21 | press.requireFailure(swipe); 22 | 23 | pressCount = 0; 24 | swipeCount = 0; 25 | hammer.on('press', function() { 26 | pressCount++; 27 | }); 28 | hammer.on('swipe', function() { 29 | swipeCount++; 30 | }); 31 | }, 32 | teardown: function() { 33 | hammer.destroy(); 34 | } 35 | }); 36 | 37 | asyncTest('When swipe does not recognize the gesture, a press gesture can be fired', function() { 38 | expect(1); 39 | 40 | utils.dispatchTouchEvent(el, 'start', 50, 50); 41 | 42 | setTimeout(function() { 43 | start(); 44 | equal(pressCount, 1); 45 | }, pressPeriod + 100); 46 | }); 47 | 48 | asyncTest('When swipe does recognize the gesture, a press gesture cannot be fired', function() { 49 | expect(2); 50 | 51 | Simulator.gestures.swipe(el, null, function() { 52 | start(); 53 | 54 | ok(swipeCount > 0, 'swipe gesture should be recognizing'); 55 | equal(pressCount, 0, 'press gesture should not be recognized because swipe gesture is recognizing'); 56 | }); 57 | }); 58 | module('Require Failure ( Pan & Press )', { 59 | setup: function() { 60 | el = document.createElement('div'); 61 | document.body.appendChild(el); 62 | 63 | hammer = new Hammer(el, {recognizers: []}); 64 | 65 | var pan = new Hammer.Pan({threshold: 1}); 66 | var press = new Hammer.Press({time: pressPeriod, threshold: pressThreshold}); 67 | 68 | hammer.add([pan, press]); 69 | 70 | pan.recognizeWith(press); 71 | press.requireFailure(pan); 72 | 73 | pressCount = 0; 74 | panStartCount = 0; 75 | hammer.on('press', function() { 76 | pressCount++; 77 | }); 78 | hammer.on('panstart', function() { 79 | panStartCount++; 80 | }); 81 | }, 82 | teardown: function() { 83 | document.body.removeChild(el); 84 | hammer.destroy(); 85 | } 86 | }); 87 | 88 | asyncTest('When pan does not recognize the gesture, a press gesture can be fired', function() { 89 | expect(1); 90 | 91 | utils.dispatchTouchEvent(el, 'start', 50, 50); 92 | 93 | setTimeout(function() { 94 | start(); 95 | equal(pressCount, 1); 96 | }, pressPeriod + 100); 97 | }); 98 | 99 | asyncTest('When pan recognizes the gesture, a press gesture cannot be fired', function() { 100 | expect(2); 101 | 102 | utils.dispatchTouchEvent(el, 'start', 50, 50); 103 | utils.dispatchTouchEvent(el, 'move', 50 + pressThreshold / 4, 50); 104 | 105 | setTimeout(function() { 106 | start(); 107 | 108 | ok(panStartCount > 0, 'pan gesture should be recognizing'); 109 | equal(pressCount, 0, 'press gesture should not be recognized because pan gesture is recognizing'); 110 | }, pressPeriod + 100); 111 | }); 112 | -------------------------------------------------------------------------------- /node_modules/hammerjs/tests/unit/test_simultaneous_recognition.js: -------------------------------------------------------------------------------- 1 | var el, 2 | hammer; 3 | 4 | module('Simultaenous recognition', { 5 | setup: function() { 6 | el = utils.createHitArea() 7 | }, 8 | teardown: function() { 9 | hammer && hammer.destroy(); 10 | } 11 | }); 12 | 13 | asyncTest('should pinch and pan simultaneously be recognized when enabled', function() { 14 | expect(4); 15 | 16 | var panCount = 0, 17 | pinchCount = 0; 18 | 19 | hammer = new Hammer.Manager(el, { 20 | touchAction: 'none' 21 | }); 22 | 23 | hammer.add(new Hammer.Pan({threshold: 5, pointers: 2})); 24 | 25 | var pinch = new Hammer.Pinch({ threshold: 0, pointers: 2}); 26 | hammer.add(pinch); 27 | pinch.recognizeWith(hammer.get('pan')); 28 | 29 | hammer.on('panend', function() { 30 | panCount++; 31 | }); 32 | hammer.on('pinchend', function() { 33 | pinchCount++; 34 | }); 35 | 36 | var executeGesture = function(cb) { 37 | var event, touches; 38 | 39 | touches = [ 40 | {clientX: 0, clientY: 10, identifier: 0, target: el }, 41 | {clientX: 10, clientY: 10, identifier: 1, target: el } 42 | ]; 43 | 44 | event = document.createEvent('Event'); 45 | event.initEvent('touchstart', true, true); 46 | event.touches = touches; 47 | event.targetTouches = touches; 48 | event.changedTouches = touches; 49 | el.dispatchEvent(event); 50 | 51 | setTimeout(function() { 52 | touches = [ 53 | {clientX: 10, clientY: 20, identifier: 0, target: el }, 54 | {clientX: 20, clientY: 20, identifier: 1, target: el } 55 | ]; 56 | 57 | event = document.createEvent('Event'); 58 | event.initEvent('touchmove', true, true); 59 | event.touches = touches; 60 | event.targetTouches = touches; 61 | event.changedTouches = touches; 62 | 63 | el.dispatchEvent(event); 64 | }, 100); 65 | 66 | setTimeout(function() { 67 | touches = [ 68 | {clientX: 20, clientY: 30, identifier: 0, target: el }, 69 | {clientX: 40, clientY: 30, identifier: 1, target: el } 70 | ]; 71 | 72 | event = document.createEvent('Event'); 73 | event.initEvent('touchmove', true, true); 74 | event.touches = touches; 75 | event.targetTouches = touches; 76 | event.changedTouches = touches; 77 | el.dispatchEvent(event); 78 | 79 | event = document.createEvent('Event'); 80 | event.initEvent('touchend', true, true); 81 | event.touches = touches; 82 | event.targetTouches = touches; 83 | event.changedTouches = touches; 84 | el.dispatchEvent(event); 85 | 86 | cb(); 87 | }, 200); 88 | }; 89 | 90 | // 2 gesture will be recognized 91 | executeGesture(function() { 92 | equal(panCount, 1); 93 | equal(pinchCount, 1); 94 | 95 | pinch.dropRecognizeWith(hammer.get('pan')); 96 | 97 | // only the pan gesture will be recognized 98 | executeGesture(function() { 99 | equal(panCount, 2); 100 | equal(pinchCount, 1); 101 | 102 | start(); 103 | }); 104 | }); 105 | }); 106 | 107 | test('the first gesture should block the following gestures (Tap & DoubleTap)', function() { 108 | expect(4); 109 | 110 | var tapCount = 0, 111 | doubleTapCount = 0; 112 | 113 | hammer = new Hammer.Manager(el, { 114 | touchAction: 'none' 115 | }); 116 | 117 | var tap = new Hammer.Tap(); 118 | var doubleTap = new Hammer.Tap({event: 'doubletap', taps: 2}); 119 | 120 | hammer.add(tap); 121 | hammer.add(doubleTap); 122 | 123 | hammer.on('tap', function() { 124 | tapCount++; 125 | }); 126 | hammer.on('doubletap', function() { 127 | doubleTapCount++; 128 | }); 129 | 130 | utils.dispatchTouchEvent(el, 'start', 0, 10); 131 | utils.dispatchTouchEvent(el, 'end', 0, 10); 132 | utils.dispatchTouchEvent(el, 'start', 0, 10); 133 | utils.dispatchTouchEvent(el, 'end', 0, 10); 134 | 135 | equal(tapCount, 2, 'on a double tap gesture, the tap gesture is recognized twice'); 136 | equal(doubleTapCount, 0, 'double tap gesture is not recognized because the prior tap gesture does not recognize it simultaneously'); 137 | 138 | doubleTap.recognizeWith(hammer.get('tap')); 139 | 140 | utils.dispatchTouchEvent(el, 'start', 0, 10); 141 | utils.dispatchTouchEvent(el, 'end', 0, 10); 142 | utils.dispatchTouchEvent(el, 'start', 0, 10); 143 | utils.dispatchTouchEvent(el, 'end', 0, 10); 144 | 145 | equal(tapCount, 4); 146 | equal(doubleTapCount, 1, 'when the tap gesture is configured to work simultaneously, tap & doubleTap can be recognized simultaneously'); 147 | }); 148 | 149 | test('when disabled, the first gesture should not block gestures (Tap & DoubleTap )', function() { 150 | expect(4); 151 | 152 | var tapCount = 0, 153 | doubleTapCount = 0; 154 | 155 | hammer = new Hammer.Manager(el, { 156 | touchAction: 'none' 157 | }); 158 | 159 | var tap = new Hammer.Tap(); 160 | var doubleTap = new Hammer.Tap({event: 'doubletap', taps: 2}); 161 | 162 | hammer.add(tap); 163 | hammer.add(doubleTap); 164 | 165 | hammer.on('tap', function() { 166 | tapCount++; 167 | }); 168 | hammer.on('doubletap', function() { 169 | doubleTapCount++; 170 | }); 171 | 172 | utils.dispatchTouchEvent(el, 'start', 0, 10); 173 | utils.dispatchTouchEvent(el, 'end', 0, 10); 174 | utils.dispatchTouchEvent(el, 'start', 0, 10); 175 | utils.dispatchTouchEvent(el, 'end', 0, 10); 176 | 177 | equal(tapCount, 2, 'on a double tap gesture, the tap gesture is recognized twice'); 178 | equal(doubleTapCount, 0, 'double tap gesture is not recognized because the prior tap gesture does not recognize it simultaneously'); 179 | 180 | hammer.get('tap').set({ enable: false }); 181 | 182 | utils.dispatchTouchEvent(el, 'start', 0, 10); 183 | utils.dispatchTouchEvent(el, 'end', 0, 10); 184 | utils.dispatchTouchEvent(el, 'start', 0, 10); 185 | utils.dispatchTouchEvent(el, 'end', 0, 10); 186 | 187 | equal(tapCount, 2, 'tap gesture should not be recognized when the recognizer is disabled'); 188 | equal(doubleTapCount, 1, 'when the tap gesture is disabled, doubleTap can be recognized'); 189 | }); 190 | 191 | test('the first gesture should block the following gestures (DoubleTap & Tap)', function() { 192 | expect(4); 193 | 194 | var tapCount = 0, 195 | doubleTapCount = 0; 196 | 197 | hammer = new Hammer.Manager(el, { 198 | touchAction: 'none' 199 | }); 200 | 201 | var tap = new Hammer.Tap(); 202 | var doubleTap = new Hammer.Tap({event: 'doubletap', taps: 2}); 203 | 204 | hammer.add(doubleTap); 205 | hammer.add(tap); 206 | 207 | hammer.on('tap', function() { 208 | tapCount++; 209 | }); 210 | hammer.on('doubletap', function() { 211 | doubleTapCount++; 212 | }); 213 | 214 | utils.dispatchTouchEvent(el, 'start', 0, 10); 215 | utils.dispatchTouchEvent(el, 'end', 0, 10); 216 | utils.dispatchTouchEvent(el, 'start', 0, 10); 217 | utils.dispatchTouchEvent(el, 'end', 0, 10); 218 | 219 | equal(doubleTapCount, 1, 'double tap is recognized'); 220 | equal(tapCount, 1, 'tap is detected, the doubletap is only catched by the doubletap recognizer'); 221 | 222 | // doubletap and tap together 223 | doubleTap.recognizeWith(hammer.get('tap')); 224 | doubleTapCount = 0; 225 | tapCount = 0; 226 | 227 | utils.dispatchTouchEvent(el, 'start', 0, 10); 228 | utils.dispatchTouchEvent(el, 'end', 0, 10); 229 | utils.dispatchTouchEvent(el, 'start', 0, 10); 230 | utils.dispatchTouchEvent(el, 'end', 0, 10); 231 | 232 | equal(doubleTapCount, 1); 233 | equal(tapCount, 2, 'when the tap gesture is configured to work simultaneously, tap & doubleTap can be recognized simultaneously'); 234 | }); 235 | -------------------------------------------------------------------------------- /node_modules/hammerjs/tests/unit/test_utils.js: -------------------------------------------------------------------------------- 1 | module('utils'); 2 | 3 | // for the tests, all hammer properties and methods of Hammer are exposed to window.$H 4 | 5 | test('get/set prefixed util', function() { 6 | ok(_.isUndefined($H.prefixed(window, 'FakeProperty')), 'non existent property returns undefined'); 7 | 8 | window.webkitFakeProperty = 1337; 9 | ok($H.prefixed(window, 'FakeProperty') == 'webkitFakeProperty', 'existent prefixed property returns the prefixed name'); 10 | 11 | delete window.webkitFakeProperty; 12 | }); 13 | 14 | test('fnBind', function() { 15 | var context = { a: true }; 16 | 17 | $H.bindFn(function(b) { 18 | ok(this.a === true, 'bindFn scope'); 19 | ok(b === 123, 'bindFn argument'); 20 | }, context)(123); 21 | }); 22 | 23 | test('Inherit objects', function() { 24 | function Base() { 25 | this.name = true; 26 | } 27 | 28 | function Child() { 29 | Base.call(this); 30 | } 31 | 32 | $H.inherit(Child, Base, { 33 | newMethod: function() { 34 | } 35 | }); 36 | 37 | var inst = new Child(); 38 | 39 | ok(inst.name == true, 'child has extended from base'); 40 | ok(inst.newMethod, 'child has a new method'); 41 | ok(Child.prototype.newMethod, 'child has a new prototype method'); 42 | ok(inst instanceof Child, 'is instanceof Child'); 43 | ok(inst instanceof Base, 'is instanceof Base'); 44 | ok(inst._super === Base.prototype, '_super is ref to prototype of Base'); 45 | }); 46 | 47 | test('toArray', function() { 48 | ok(_.isArray($H.toArray({ 0: true, 1: 'second', length: 2 })), 'converted an array-like object to an array'); 49 | ok(_.isArray($H.toArray([true, true])), 'array stays an array'); 50 | }); 51 | 52 | test('inArray', function() { 53 | ok($H.inArray([1, 2, 3, 4, 'hammer'], 'hammer') === 4, 'found item and returned the index'); 54 | ok($H.inArray([1, 2, 3, 4, 'hammer'], 'notfound') === -1, 'not found an item and returned -1'); 55 | ok($H.inArray([ 56 | {id: 2}, 57 | {id: 24} 58 | ], '24', 'id') === 1, 'find by key and return the index'); 59 | ok($H.inArray([ 60 | {id: 2}, 61 | {id: 24} 62 | ], '22', 'id') === -1, 'not found by key and return -1'); 63 | }); 64 | 65 | test('splitStr', function() { 66 | deepEqual($H.splitStr(' a b c d '), ['a', 'b', 'c', 'd'], 'str split valid'); 67 | }); 68 | 69 | test('uniqueArray', function() { 70 | deepEqual($H.uniqueArray([ 71 | {id: 1}, 72 | {id: 2}, 73 | {id: 2} 74 | ], 'id'), [ 75 | {id: 1}, 76 | {id: 2} 77 | ], 'remove duplicate ids') 78 | }); 79 | 80 | test('boolOrFn', function() { 81 | equal($H.boolOrFn(true), true, 'Passing an boolean'); 82 | equal($H.boolOrFn(false), false, 'Passing an boolean'); 83 | equal($H.boolOrFn(function() { 84 | return true; 85 | }), true, 'Passing an boolean'); 86 | equal($H.boolOrFn(1), true, 'Passing an integer'); 87 | }); 88 | 89 | test('hasParent', function() { 90 | var parent = document.createElement('div'), 91 | child = document.createElement('div'); 92 | 93 | document.body.appendChild(parent); 94 | parent.appendChild(child); 95 | 96 | equal($H.hasParent(child, parent), true, 'Found parent'); 97 | equal($H.hasParent(parent, child), false, 'Not in parent'); 98 | 99 | document.body.removeChild(parent); 100 | }); 101 | 102 | test('each', function() { 103 | var object = { hi: true }; 104 | var array = ['a', 'b', 'c']; 105 | var loop; 106 | 107 | loop = false; 108 | $H.each(object, function(value, key) { 109 | if (key == 'hi' && value === true) { 110 | loop = true; 111 | } 112 | }); 113 | ok(loop, 'object loop'); 114 | 115 | loop = 0; 116 | $H.each(array, function(value, key) { 117 | if (value) { 118 | loop++; 119 | } 120 | }); 121 | ok(loop == 3, 'array loop'); 122 | 123 | loop = 0; 124 | array.forEach = null; 125 | $H.each(array, function(value, key) { 126 | if (value) { 127 | loop++; 128 | } 129 | }); 130 | ok(loop == 3, 'array loop without Array.forEach'); 131 | }); 132 | 133 | test('assign', function() { 134 | expect(2); 135 | deepEqual( 136 | $H.assign( 137 | {a: 1, b: 3}, 138 | {b: 2, c: 3} 139 | ), 140 | {a: 1, b: 2, c: 3}, 141 | 'Simple extend' 142 | ); 143 | 144 | var src = { foo: true }; 145 | var dest = $H.assign({}, src); 146 | src.foo = false; 147 | deepEqual(dest, {foo: true}, 'Clone reference'); 148 | }); 149 | 150 | test('test add/removeEventListener', function() { 151 | function handleEvent() { 152 | ok(true, 'triggered event'); 153 | } 154 | 155 | expect(2); 156 | 157 | $H.addEventListeners(window, 'testEvent1 testEvent2 ', handleEvent); 158 | utils.triggerDomEvent(window, 'testEvent1'); 159 | utils.triggerDomEvent(window, 'testEvent2'); 160 | 161 | $H.removeEventListeners(window, ' testEvent1 testEvent2 ', handleEvent); 162 | utils.triggerDomEvent(window, 'testEvent1'); 163 | utils.triggerDomEvent(window, 'testEvent2'); 164 | }); 165 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "loderunner-in-a-box", 3 | "version": "1.1.0", 4 | "description": "Play MS-DOS Lode Runner on modern browsers or mobile screens", 5 | "main": "index.html", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/mad4j/loderunner-in-a-box.git" 12 | }, 13 | "keywords": [ 14 | "dosbox", 15 | "msdos", 16 | "arcade" 17 | ], 18 | "author": { 19 | "name": "Daniele Olmisani", 20 | "email": "daniele.olmisani@gmail.com" 21 | }, 22 | "license": "GPL-3.0", 23 | "bugs": { 24 | "url": "https://github.com/mad4j/loderunner-in-a-box/issues" 25 | }, 26 | "homepage": "https://github.com/mad4j/loderunner-in-a-box#readme", 27 | "dependencies": { 28 | "hammerjs": "^2.0.8" 29 | } 30 | } 31 | --------------------------------------------------------------------------------