[
  {
    "path": ".bowerrc",
    "content": "{\n  \"json\": \"bower.json\"\n}"
  },
  {
    "path": ".editorconfig",
    "content": "# EditorConfig helps developers define and maintain consistent\n# coding styles between different editors and IDEs\n# editorconfig.org\n\nroot = true\n\n[*]\nend_of_line = lf\ncharset = utf-8\ntrim_trailing_whitespace = true\ninsert_final_newline = true\nindent_style = space\nindent_size = 2\n\n[*.js]\nindent_style = space\nindent_size = 2\n\n[*.md]\ntrim_trailing_whitespace = false\n"
  },
  {
    "path": ".gitignore",
    "content": "# ide\n.idea\n.iml\n\n# node\nlib-cov\n*.seed\n*.log\n*.csv\n*.dat\n*.out\n*.pid\n*.gz\n\npids\nlogs\nresults\ntests/build.js\n\nnpm-debug.log\nnode_modules\n"
  },
  {
    "path": ".jscsrc",
    "content": "{\n  \"preset\": \"ember-suave\",\n  \"excludeFiles\": [\n    \"tests/**/assets\",\n    \"node_modules/**\"\n  ],\n  \"disallowConstOutsideModuleScope\": false,\n  \"requireArrowFunctions\": true,\n  \"disallowEmptyBlocks\": false\n}\n"
  },
  {
    "path": ".jshintrc",
    "content": "{\n  \"maxerr\": 100,\n  \"freeze\": true,\n  \"node\": false,\n  \"indent\": 2,\n  \"predef\": [\n    \"document\",\n    \"window\"\n  ],\n  \"browser\": true,\n  \"boss\": true,\n  \"curly\": true,\n  \"debug\": false,\n  \"devel\": true,\n  \"eqeqeq\": true,\n  \"expr\": true,\n  \"validthis\": true,\n  \"evil\": true,\n  \"forin\": false,\n  \"immed\": false,\n  \"laxbreak\": false,\n  \"newcap\": true,\n  \"noarg\": true,\n  \"node\": true,\n  \"noempty\": false,\n  \"nonew\": false,\n  \"nomen\": false,\n  \"onevar\": false,\n  \"plusplus\": false,\n  \"regexp\": false,\n  \"undef\": true,\n  \"sub\": true,\n  \"strict\": false,\n  \"white\": false,\n  \"eqnull\": true,\n  \"esversion\": 6,\n  \"unused\": true,\n  \"-W116\": true,\n  \"-W080\": true,\n  \"-W038\": true,\n  \"proto\": true\n}\n"
  },
  {
    "path": ".travis.yml",
    "content": "language: node_js\nnode_js:\n  - \"6.3.0\"\n\nsudo: false\n\nscript:\n  - npm run test\n"
  },
  {
    "path": "CHANGELOG.md",
    "content": "# Changelog\n\n### 2.0.8, 2016-04-22\n\n##### Manager\n- Added check to ensure that the required parameters are present ([#908](https://github.com/hammerjs/hammer.js/issues/908), [085d3a8](https://github.com/hammer.js/hammerjs/commit/085d3a87eab8674c45e9d3a14c4ca44ad7b97e26))\n- Fixed restoration of Hammer.defaults.cssProps on destory ([#904theregttr5ki](https://github.com/hammerjs/hammer.js/issues/904), [7d0e60f](https://github.com/hammer.js/hammerjs/commit/7d0e60f6743517db3c05a38e966fb9fb5052fa03))\n\n##### Input\n- Fixed de-duping of mouse events on mouse touch combo devices ([#917](https://github.com/hammer.js/hammer.js/issues/917), [#863](https://github.com/hammerjs/hammer.js/issues/863), [bfeb89a](https://github.com/hammerjs/hammerjs/commit/bfeb89a77f778c527f771150d1e9687bd318ce8d))\n\n##### Touch-action\n- Added support map for specific values of touch-action ([#952](https://github.com/hammer.js/hammer.js/issues/952), [fbe9fd7](https://github.com/hammerjs/hammer.js/commit/fbe9fd775fe8cb3d43faa9428bfa56b61b16edc7))\n\n### 2.0.6, 2015-12-23\n- 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))\n- 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))\n- 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))\n- Fixed moz-prefix, prefix should be Moz not moz. ([3ea47f3](https://github.com/hammerjs/hammer.js/commit/3ea47f3aebadc9d3bb6bf52bc8402cad135ef8a9))\n- Removed non-existant recognizer ([f1c2d3b](https://github.com/hammerjs/hammer.js/commit/f1c2d3bf05f530ae092ecfc2335fceeff0e9eec9))\n- Fixed config leaking between instances([189098f](https://github.com/hammerjs/hammer.js/commit/189098ff7736f6ed2fce9a3d3e1f5a3afee085ba))\n- Fixed gaps in gesture configs and update tests to match ([70c2902](https://github.com/hammerjs/hammer.js/commit/70c2902d773a750e92ce8c423f8a4165c07eab97))\n- Fixed Manager off method ([#768](https://github.com/hammerjs/hammer.js/issues/768), [da49a27](https://github.com/hammerjs/hammer.js/commit/da49a2730779ecc3b4dd147cc418a0df7c70fad9))\n- Added compatibility with requirejs optimizer namespaces ( [70075f2](https://github.com/hammerjs/hammer.js/commit/70075f2df1b855f7c6d8d3caac49b9276b88c8d6))\n- Made touchaction test zoomable ( [50264a7](https://github.com/hammerjs/hammer.js/commit/50264a70251ca88bbaf7b666401e527eee616de5))\n- Fixed preventing default when for `pan-x pan-y` case ( [95eaafa](https://github.com/hammerjs/hammer.js/commit/95eaafadad27bd1b25d20cf976811a451922f1c4))\n- Fixed incorrect touch action pan direction ( [a81da57](https://github.com/hammerjs/hammer.js/commit/a81da57a82ebf37e695e7c443e4e2715e7f32856))\n- Fixed combined pan-x pan-y to resolve to none ( [fdae07b](https://github.com/hammerjs/hammer.js/commit/fdae07bc2ba3c90aad28da6791b3d5df627bc612))\n- 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))\n- 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))\n- 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))\n- Fixed swipe recognizer to use overall gesture direction and velocity ( [963fe69](https://github.com/hammerjs/hammer.js/commit/963fe697515273fee508414bc29e2656465cea55))\n- Fixed getDirection returning reversed direction ( [e40dcde](https://github.com/hammerjs/hammer.js/commit/e40dcde43bdac7a74c8ce5c05a4f62121089cd91))\n- Fixed detection of tap when multi touch gestures are present ( [c46cbba](https://github.com/hammerjs/hammer.js/commit/c46cbba1c2cbbf874b59913416858d9dae297e64))\n- Fixed incorrect event order ([#824](https://github.com/hammerjs/hammer.js/issues/824), [92f2d76](https://github.com/hammerjs/hammer.js/commit/92f2d76188480d967e738a19cd508d0b94a31329))\n- Fixed leaking options between recognizer instances ([#813](https://github.com/hammerjs/hammer.js/issues/813), [af32c9b](https://github.com/hammerjs/hammer.js/commit/af32c9bace3f04bb34bee852ff56a33cc8fc27cd))\n- Fixed detection when element has no style attribute ( [5ca6d8c](https://github.com/hammerjs/hammer.js/commit/5ca6d8cbead02c71929a8073e95ddf98e11c0e06))\n\n### 2.0.4, 2014-09-28\n- Fix IE pointer issue. [#665](https://github.com/hammerjs/hammer.js/pull/665)\n- Fix multi-touch at different elements. [#668](https://github.com/hammerjs/hammer.js/pull/668)\n- 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.\n\n### 2.0.3, 2014-09-10\n- Manager.set improvements. \n- Fix requireFailure() call in Manager.options.recognizers. \n- Make DIRECTION_ALL for pan and swipe gestures less blocking.\n- Fix Swipe recognizer threshold option.\n- Expose the Input classes.\n- Added the option `inputClass` to set the used input handler.\n\n### 2.0.2, 2014-07-26\n- Improved mouse and pointer-events input, now able to move outside the window.\n- Added the export name (`Hammer`) as an argument to the wrapper.\n- Add the option *experimental* `inputTarget` to change the element that receives the events.\n- Improved performance when only one touch being active.\n- Fixed the jumping deltaXY bug when going from single to multi-touch.\n- Improved velocity calculations.\n\n### 2.0.1, 2014-07-15\n- Fix issue when no document.body is available\n- Added pressup event for the press recognizer\n- Removed alternative for Object.create\n\n### 2.0.0, 2014-07-11\n- Full rewrite of the library.\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# Contributing to Hammer.js\n\nLooking to contribute something to Hammer.js? **Here's how you can help.**\n\n\n## Reporting issues\n\nWe only accept issues that are bug reports or feature requests. Bugs must be\nisolated and reproducible problems that can be fixed within the Hammer.js.\nPlease read the following guidelines before opening any issue.\n\n1. [**Read the documentation**](https://hammerjs.github.io)\n\n2. **Search for existing issues.** We get a lot of duplicate issues, and you'd\nhelp us out a lot by first checking if someone else has reported the same issue.\nMoreover, the issue may have already been resolved with a fix available. Also\ntake a look if your problem is explained at the Wiki.\n\n3. **Create an isolated and reproducible test case.** Be sure the problem exists\nin Hammer's code with a reduced test case that should be included in each bug\nreport.\n\n4. **Include a live example.** Make use of jsFiddle or jsBin to share your\nisolated test cases. Also, a screen capture would work, with tools like LICEcap.\n\n5. **Share as much information as possible.** Include operating system and\nversion, browser and version, version of Hammer.js, customized or vanilla build,\netc. where appropriate. Also include steps to reproduce the bug.\n\n## Pull requests\n\n1. Changes must be done in `/src` files, never just the compiled files. Also, don't \ncommit the compiled files.\n\n2. Try not to pollute your pull request with unintended changes. Keep them simple\nand small\n\n3. Try to share which browsers your code has been tested in before submitting a\npull request\n\n4. Write tests for your code, these can be found in `/tests`.\n"
  },
  {
    "path": "LICENSE.md",
    "content": "The MIT License (MIT)\n\nCopyright (C) 2011-2017 by Jorik Tangelder (Eight Media)\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# [hammer.js][hammerjs-url]  [![NPM Version][npm-image]][npm-url]  [![NPM Downloads][downloads-image]][downloads-url]  [![Build Status][travis-image]][travis-url]\n> A JavaScript library for detecting touch gestures.\n\n\n## Installation\n### NPM\n```sh\nnpm install --save hammerjs\n```\n\n**or**\n\n### Yarn\n```sh\nyarn add hammerjs\n```\n\n**or**\n\n### CDN\n[https://cdnjs.com/libraries/hammer.js/](https://cdnjs.com/libraries/hammer.js/)\n\n\n## Usage\nhammer.js has a quick start option for gestures it already recognizes.\n```js\n// Get a reference to an element.\nvar square = document.querySelector('.square');\n\n// Create an instance of Hammer with the reference.\nvar hammer = new Hammer(square);\n\n// Subscribe to a quick start event: press, tap, or doubletap.\n// For a full list of quick start events, read the documentation.\nhammer.on('press', function(e) {\n  e.target.classList.toggle('expand');\n  console.log(\"You're pressing me!\");\n  console.log(e);\n});\n```\n\nIf you want to recognize your own gestures, such as `tripletap`, then you'll have to use these steps:\n```js\n// Get a reference to an element.\nvar square = document.querySelector('.square');\n\n// Create a manager to manage the element.\nvar manager = new Hammer.Manager(square);\n\n// Create a recognizer.\nvar TripleTap = new Hammer.Tap({\n  event: 'tripletap',\n  taps: 3\n});\n\n// Add the recognizer to the manager.\nmanager.add(TripleTap);\n\n// Subscribe to the event.\nmanager.on('tripletap', function(e) {\n  e.target.classList.toggle('expand');\n  console.log(\"You're triple tapping me!\");\n  console.log(e);\n});\n```\n\n\n## Examples\n- [tap][tap]\n- [double tap][double-tap]\n- [press][press]\n- [swipe][swipe]\n\n\n## Documentation\nFor further information regarding hammer.js, please read our [documentation][hammerjs-url].\n\n\n## Contributions  [![Github Issues][issues-image]][issues-url]  [![Github PRs][pulls-image]][pulls-url]  [![Slack][slack-image]][slack-url]\nFeel encouraged to report issues or submit pull requests. When you're ready to do either, read our [contribution guidelines][contribution-guidelines]. If you're looking for another form of contribution, we love help answering questions on our [slack channel][slack-url].\n\n\n## License\n[MIT][license]\n\n[hammerjs-url]: http://hammerjs.github.io\n\n[npm-image]: https://img.shields.io/npm/v/hammerjs.svg\n[npm-url]: https://npmjs.org/package/hammerjs\n\n[travis-image]: https://img.shields.io/travis/stream-utils/raw-body/master.svg\n[travis-url]: https://travis-ci.org/hammerjs/hammer.js\n\n[downloads-image]: https://img.shields.io/npm/dm/hammerjs.svg\n[downloads-url]: https://npmjs.org/package/hammerjs\n\n\n<!-- Examples -->\n[tap]: https://codepen.io/choskim/pen/WZggmg\n[double-tap]: https://codepen.io/choskim/pen/vezzwZ\n[press]: https://codepen.io/choskim/pen/RLYebL\n[pan]: ''\n[swipe]: https://codepen.io/choskim/pen/rGZqxa\n[pinch]: ''\n[rotate]: ''\n\n\n<!-- Contributions -->\n[issues-image]: https://img.shields.io/github/issues/hammerjs/hammer.js.svg\n[issues-url]: https://github.com/hammerjs/hammer.js/issues\n\n[pulls-image]: https://img.shields.io/github/issues-pr/hammerjs/hammer.js.svg\n[pulls-url]: https://github.com/hammerjs/hammer.js/pulls\n\n[slack-image]: https://hammerjs.herokuapp.com/badge.svg\n[slack-url]: https://hammerjs.herokuapp.com/\n\n[contribution-guidelines]: ./CONTRIBUTING.md\n\n[license]: ./LICENSE.md\n"
  },
  {
    "path": "banner.ejs",
    "content": "/*! <%= pkg.title || pkg.name %> - v<%= pkg.version %> - <%= [ date.getFullYear(), ('0' + (date.getMonth() + 1)).slice(-2), ('0' + date.getDate()).slice(-2)].join('-') %>\n * <%= pkg.homepage %>\n *\n * Copyright (c) <%= %> <%= pkg.author.name %>;\n * Licensed under the <%= pkg.license %> license */\n\n"
  },
  {
    "path": "bower.json",
    "content": "{\n    \"name\": \"hammerjs\",\n    \"license\": \"MIT\",\n    \"main\": \"hammer.js\",\n    \"ignore\": [\n        \"tests\",\n        \"src\",\n        \".bowerrc\",\n        \".gitignore\",\n        \".jscsrc\",\n        \".jshintrc\",\n        \".travis.yml\",\n        \"component.json\",\n        \"package.json\"\n    ]\n}\n"
  },
  {
    "path": "changelog.js",
    "content": "var changelog = require( \"changelogplease\" );\nvar gittags = require( \"git-tags\" ).get( function( error, tags ) {\n\tif ( error ) {\n\t\tthrow error\n\t}\n\tconsole.log( tags[ 2 ] + \"..\" + tags[ 0 ] );\n\tvar exclude = [ \"Merge\", \"Whitespace\", \"Fixup\", \"Cleanup\", \"Formatting\", \"Ignore\" ];\n\tchangelog( {\n\t\tticketUrl: \"https://github.com/hammerjs/hammer.js/issues/{id}\",\n\t\tcommitUrl: \"https://github.com/hammerjs/hammerjs/commit/{id}\",\n\t\tsort: false,\n\t\trepo: \"./\",\n\t\tcommittish: tags[ 2 ] + \"..\" + tags[ 0 ]\n\t}, function( error, log ) {\n\t\tif ( error ) {\n\t\t\tthrow error;\n\t\t}\n\t\tlog = parseLog( log );\n\t\tconsole.log( log );\n\t} );\n\tfunction parseLog( log ) {\n\t\tvar lines = log.split( \"\\n\" );\n\t\tvar newLog = [];\n\t\tvar log = [];\n\t\tvar currentComponent;\n\n\t\t\n\t\tlines.shift();\n\t\tlines.forEach( function( line ) {\n\t\t\tvar newLine = parseLine( line );\n\t\t\tif ( newLine ) {\n\t\t\t\tlog.push( line );\n\t\t\t}\n\t\t} );\n\t\tvar log = log.join( \"\\n\" );\n\t\treturn log.replace( /\\*/g, \"-\" ).replace( /__TICKETREF__,/g, \"\" );\n\t}\n\tfunction parseLine( line ) {\n\t\tvar parts = getParts( line );\n\n\t\tif ( exclude.indexOf( parts.component ) > -1 ) {\n\t\t\treturn false;\n\t\t}\n\t\treturn parts;\n\t}\n\tfunction getParts( line ) {\n\t\tvar parts = line.split( \":\" );\n\t\tvar component = \"\";\n\t\tvar message;\n\t\tvar commits = line.match( /\\{\\{([A-Za-z0-9 ]){0,99}\\}\\}/ )\n\n\t\tif ( parts.length > 1 && parts[ 0 ].length <= 20 ) {\n\t\t\tcomponent = parts[ 0 ];\n\t\t\tparts.shift();\n\t\t\tmessage = parts.join( \":\" );\n\t\t} else {\n\t\t\tparts = line.split( \" \" );\n\t\t\tcomponent = parts[ 1 ];\n\t\t\tparts.shift();\n\t\t\tmessage = parts.join( \" \" );\n\t\t}\n\n\t\tif ( component ) {\n\t\t\tcomponent = component.replace( /\\* |,/, \"\" );\n\t\t}\n\t\treturn {\n\t\t\tcomponent: component,\n\t\t\tmessage: message\n\t\t};\n\t}\n} );\n"
  },
  {
    "path": "component.json",
    "content": "{\n    \"name\": \"hammerjs\",\n    \"version\": \"2.0.6\",\n    \"main\": \"hammer.js\",\n    \"scripts\": [\n      \"hammer.js\"\n    ]\n}\n"
  },
  {
    "path": "hammer.js",
    "content": "/*! Hammer.JS - v2.0.8 - 2016-09-30\n * http://hammerjs.github.io/\n *\n * Copyright (c)  Jorik Tangelder;\n * Licensed under the MIT license */\n(function(window, document, exportName, undefined) { \n'use strict';\n/**\n * @private\n * use the val2 when val1 is undefined\n * @param {*} val1\n * @param {*} val2\n * @returns {*}\n */\nfunction ifUndefined(val1, val2) {\n  return val1 === undefined ? val2 : val1;\n}\n\nvar VENDOR_PREFIXES = ['', 'webkit', 'Moz', 'MS', 'ms', 'o'];\nvar TEST_ELEMENT = document.createElement('div');\n\nvar TYPE_FUNCTION = 'function';\n\nvar round = Math.round;\nvar abs = Math.abs;\nvar now = Date.now;\n\n/**\n * @private\n * get the prefixed property\n * @param {Object} obj\n * @param {String} property\n * @returns {String|Undefined} prefixed\n */\nfunction prefixed(obj, property) {\n  var prefix = void 0;\n  var prop = void 0;\n  var camelProp = property[0].toUpperCase() + property.slice(1);\n\n  var i = 0;\n  while (i < VENDOR_PREFIXES.length) {\n    prefix = VENDOR_PREFIXES[i];\n    prop = prefix ? prefix + camelProp : property;\n\n    if (prop in obj) {\n      return prop;\n    }\n    i++;\n  }\n  return undefined;\n}\n\nfunction getTouchActionProps() {\n  if (!NATIVE_TOUCH_ACTION) {\n    return false;\n  }\n  var touchMap = {};\n  var cssSupports = window.CSS && window.CSS.supports;\n  ['auto', 'manipulation', 'pan-y', 'pan-x', 'pan-x pan-y', 'none'].forEach(function (val) {\n\n    // If css.supports is not supported but there is native touch-action assume it supports\n    // all values. This is the case for IE 10 and 11.\n    return touchMap[val] = cssSupports ? window.CSS.supports('touch-action', val) : true;\n  });\n  return touchMap;\n}\n\nvar PREFIXED_TOUCH_ACTION = prefixed(TEST_ELEMENT.style, 'touchAction');\nvar NATIVE_TOUCH_ACTION = PREFIXED_TOUCH_ACTION !== undefined;\n\n// magical touchAction value\nvar TOUCH_ACTION_COMPUTE = 'compute';\nvar TOUCH_ACTION_AUTO = 'auto';\nvar TOUCH_ACTION_MANIPULATION = 'manipulation'; // not implemented\nvar TOUCH_ACTION_NONE = 'none';\nvar TOUCH_ACTION_PAN_X = 'pan-x';\nvar TOUCH_ACTION_PAN_Y = 'pan-y';\nvar TOUCH_ACTION_MAP = getTouchActionProps();\n\nvar MOBILE_REGEX = /mobile|tablet|ip(ad|hone|od)|android/i;\n\nvar SUPPORT_TOUCH = 'ontouchstart' in window;\nvar SUPPORT_POINTER_EVENTS = prefixed(window, 'PointerEvent') !== undefined;\nvar SUPPORT_ONLY_TOUCH = SUPPORT_TOUCH && MOBILE_REGEX.test(navigator.userAgent);\n\nvar INPUT_TYPE_TOUCH = 'touch';\nvar INPUT_TYPE_PEN = 'pen';\nvar INPUT_TYPE_MOUSE = 'mouse';\nvar INPUT_TYPE_KINECT = 'kinect';\n\nvar COMPUTE_INTERVAL = 25;\n\nvar INPUT_START = 1;\nvar INPUT_MOVE = 2;\nvar INPUT_END = 4;\nvar INPUT_CANCEL = 8;\n\nvar DIRECTION_NONE = 1;\nvar DIRECTION_LEFT = 2;\nvar DIRECTION_RIGHT = 4;\nvar DIRECTION_UP = 8;\nvar DIRECTION_DOWN = 16;\n\nvar DIRECTION_HORIZONTAL = DIRECTION_LEFT | DIRECTION_RIGHT;\nvar DIRECTION_VERTICAL = DIRECTION_UP | DIRECTION_DOWN;\nvar DIRECTION_ALL = DIRECTION_HORIZONTAL | DIRECTION_VERTICAL;\n\nvar PROPS_XY = ['x', 'y'];\nvar PROPS_CLIENT_XY = ['clientX', 'clientY'];\n\nvar STATE_POSSIBLE = 1;\nvar STATE_BEGAN = 2;\nvar STATE_CHANGED = 4;\nvar STATE_ENDED = 8;\nvar STATE_RECOGNIZED = STATE_ENDED;\nvar STATE_CANCELLED = 16;\nvar STATE_FAILED = 32;\n\n/**\n * @private\n * extend object.\n * means that properties in dest will be overwritten by the ones in src.\n * @param {Object} target\n * @param {...Object} objects_to_assign\n * @returns {Object} target\n */\nvar assign = void 0;\nif (typeof Object.assign !== 'function') {\n  assign = function assign(target) {\n    if (target === undefined || target === null) {\n      throw new TypeError('Cannot convert undefined or null to object');\n    }\n\n    var output = Object(target);\n    for (var index = 1; index < arguments.length; index++) {\n      var source = arguments[index];\n      if (source !== undefined && source !== null) {\n        for (var nextKey in source) {\n          if (source.hasOwnProperty(nextKey)) {\n            output[nextKey] = source[nextKey];\n          }\n        }\n      }\n    }\n    return output;\n  };\n} else {\n  assign = Object.assign;\n}\n\nvar assign$1 = assign;\n\n/**\n * @private\n * get a unique id\n * @returns {number} uniqueId\n */\nvar _uniqueId = 1;\nfunction uniqueId() {\n  return _uniqueId++;\n}\n\n/**\n * @private\n * walk objects and arrays\n * @param {Object} obj\n * @param {Function} iterator\n * @param {Object} context\n */\nfunction each(obj, iterator, context) {\n  var i = void 0;\n\n  if (!obj) {\n    return;\n  }\n\n  if (obj.forEach) {\n    obj.forEach(iterator, context);\n  } else if (obj.length !== undefined) {\n    i = 0;\n    while (i < obj.length) {\n      iterator.call(context, obj[i], i, obj);\n      i++;\n    }\n  } else {\n    for (i in obj) {\n      obj.hasOwnProperty(i) && iterator.call(context, obj[i], i, obj);\n    }\n  }\n}\n\n/**\n * @private\n * if the argument is an array, we want to execute the fn on each entry\n * if it aint an array we don't want to do a thing.\n * this is used by all the methods that accept a single and array argument.\n * @param {*|Array} arg\n * @param {String} fn\n * @param {Object} [context]\n * @returns {Boolean}\n */\nfunction invokeArrayArg(arg, fn, context) {\n  if (Array.isArray(arg)) {\n    each(arg, context[fn], context);\n    return true;\n  }\n  return false;\n}\n\n/**\n * @private\n * find if a array contains the object using indexOf or a simple polyFill\n * @param {Array} src\n * @param {String} find\n * @param {String} [findByKey]\n * @return {number} -1 when not found, or the index\n */\nfunction inArray(src, find, findByKey) {\n  if (src.indexOf && !findByKey) {\n    return src.indexOf(find);\n  } else {\n    var i = 0;\n    while (i < src.length) {\n      if (findByKey && src[i][findByKey] == find || !findByKey && src[i] === find) {\n        // do not use === here, test fails\n        return i;\n      }\n      i++;\n    }\n    return -1;\n  }\n}\n\nvar _typeof = typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\" ? function (obj) {\n  return typeof obj;\n} : function (obj) {\n  return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj;\n};\n\nvar asyncGenerator = function () {\n  function AwaitValue(value) {\n    this.value = value;\n  }\n\n  function AsyncGenerator(gen) {\n    var front, back;\n\n    function send(key, arg) {\n      return new Promise(function (resolve, reject) {\n        var request = {\n          key: key,\n          arg: arg,\n          resolve: resolve,\n          reject: reject,\n          next: null\n        };\n\n        if (back) {\n          back = back.next = request;\n        } else {\n          front = back = request;\n          resume(key, arg);\n        }\n      });\n    }\n\n    function resume(key, arg) {\n      try {\n        var result = gen[key](arg);\n        var value = result.value;\n\n        if (value instanceof AwaitValue) {\n          Promise.resolve(value.value).then(function (arg) {\n            resume(\"next\", arg);\n          }, function (arg) {\n            resume(\"throw\", arg);\n          });\n        } else {\n          settle(result.done ? \"return\" : \"normal\", result.value);\n        }\n      } catch (err) {\n        settle(\"throw\", err);\n      }\n    }\n\n    function settle(type, value) {\n      switch (type) {\n        case \"return\":\n          front.resolve({\n            value: value,\n            done: true\n          });\n          break;\n\n        case \"throw\":\n          front.reject(value);\n          break;\n\n        default:\n          front.resolve({\n            value: value,\n            done: false\n          });\n          break;\n      }\n\n      front = front.next;\n\n      if (front) {\n        resume(front.key, front.arg);\n      } else {\n        back = null;\n      }\n    }\n\n    this._invoke = send;\n\n    if (typeof gen.return !== \"function\") {\n      this.return = undefined;\n    }\n  }\n\n  if (typeof Symbol === \"function\" && Symbol.asyncIterator) {\n    AsyncGenerator.prototype[Symbol.asyncIterator] = function () {\n      return this;\n    };\n  }\n\n  AsyncGenerator.prototype.next = function (arg) {\n    return this._invoke(\"next\", arg);\n  };\n\n  AsyncGenerator.prototype.throw = function (arg) {\n    return this._invoke(\"throw\", arg);\n  };\n\n  AsyncGenerator.prototype.return = function (arg) {\n    return this._invoke(\"return\", arg);\n  };\n\n  return {\n    wrap: function (fn) {\n      return function () {\n        return new AsyncGenerator(fn.apply(this, arguments));\n      };\n    },\n    await: function (value) {\n      return new AwaitValue(value);\n    }\n  };\n}();\n\nvar classCallCheck = function (instance, Constructor) {\n  if (!(instance instanceof Constructor)) {\n    throw new TypeError(\"Cannot call a class as a function\");\n  }\n};\n\nvar createClass = function () {\n  function defineProperties(target, props) {\n    for (var i = 0; i < props.length; i++) {\n      var descriptor = props[i];\n      descriptor.enumerable = descriptor.enumerable || false;\n      descriptor.configurable = true;\n      if (\"value\" in descriptor) descriptor.writable = true;\n      Object.defineProperty(target, descriptor.key, descriptor);\n    }\n  }\n\n  return function (Constructor, protoProps, staticProps) {\n    if (protoProps) defineProperties(Constructor.prototype, protoProps);\n    if (staticProps) defineProperties(Constructor, staticProps);\n    return Constructor;\n  };\n}();\n\nvar get = function get(object, property, receiver) {\n  if (object === null) object = Function.prototype;\n  var desc = Object.getOwnPropertyDescriptor(object, property);\n\n  if (desc === undefined) {\n    var parent = Object.getPrototypeOf(object);\n\n    if (parent === null) {\n      return undefined;\n    } else {\n      return get(parent, property, receiver);\n    }\n  } else if (\"value\" in desc) {\n    return desc.value;\n  } else {\n    var getter = desc.get;\n\n    if (getter === undefined) {\n      return undefined;\n    }\n\n    return getter.call(receiver);\n  }\n};\n\nvar inherits = function (subClass, superClass) {\n  if (typeof superClass !== \"function\" && superClass !== null) {\n    throw new TypeError(\"Super expression must either be null or a function, not \" + typeof superClass);\n  }\n\n  subClass.prototype = Object.create(superClass && superClass.prototype, {\n    constructor: {\n      value: subClass,\n      enumerable: false,\n      writable: true,\n      configurable: true\n    }\n  });\n  if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;\n};\n\nvar possibleConstructorReturn = function (self, call) {\n  if (!self) {\n    throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");\n  }\n\n  return call && (typeof call === \"object\" || typeof call === \"function\") ? call : self;\n};\n\nvar slicedToArray = function () {\n  function sliceIterator(arr, i) {\n    var _arr = [];\n    var _n = true;\n    var _d = false;\n    var _e = undefined;\n\n    try {\n      for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {\n        _arr.push(_s.value);\n\n        if (i && _arr.length === i) break;\n      }\n    } catch (err) {\n      _d = true;\n      _e = err;\n    } finally {\n      try {\n        if (!_n && _i[\"return\"]) _i[\"return\"]();\n      } finally {\n        if (_d) throw _e;\n      }\n    }\n\n    return _arr;\n  }\n\n  return function (arr, i) {\n    if (Array.isArray(arr)) {\n      return arr;\n    } else if (Symbol.iterator in Object(arr)) {\n      return sliceIterator(arr, i);\n    } else {\n      throw new TypeError(\"Invalid attempt to destructure non-iterable instance\");\n    }\n  };\n}();\n\n/**\n * @private\n * let a boolean value also be a function that must return a boolean\n * this first item in args will be used as the context\n * @param {Boolean|Function} val\n * @param {Array} [args]\n * @returns {Boolean}\n */\nfunction boolOrFn(val, args) {\n  if ((typeof val === 'undefined' ? 'undefined' : _typeof(val)) === TYPE_FUNCTION) {\n    return val.apply(args ? args[0] || undefined : undefined, args);\n  }\n  return val;\n}\n\n/**\n * @private\n * get a recognizer by name if it is bound to a manager\n * @param {Recognizer|String} otherRecognizer\n * @param {Recognizer} recognizer\n * @returns {Recognizer}\n */\nfunction getRecognizerByNameIfManager(otherRecognizer, recognizer) {\n  var manager = recognizer.manager;\n\n  if (manager) {\n    return manager.get(otherRecognizer);\n  }\n  return otherRecognizer;\n}\n\n/**\n * @private\n * get a usable string, used as event postfix\n * @param {constant} state\n * @returns {String} state\n */\nfunction stateStr(state) {\n  if (state & STATE_CANCELLED) {\n    return 'cancel';\n  } else if (state & STATE_ENDED) {\n    return 'end';\n  } else if (state & STATE_CHANGED) {\n    return 'move';\n  } else if (state & STATE_BEGAN) {\n    return 'start';\n  }\n  return '';\n}\n\n/**\n * @private\n * Recognizer flow explained; *\n * All recognizers have the initial state of POSSIBLE when a input session starts.\n * The definition of a input session is from the first input until the last input, with all it's movement in it. *\n * Example session for mouse-input: mousedown -> mousemove -> mouseup\n *\n * On each recognizing cycle (see Manager.recognize) the .recognize() method is executed\n * which determines with state it should be.\n *\n * If the recognizer has the state FAILED, CANCELLED or RECOGNIZED (equals ENDED), it is reset to\n * POSSIBLE to give it another change on the next cycle.\n *\n *               Possible\n *                  |\n *            +-----+---------------+\n *            |                     |\n *      +-----+-----+               |\n *      |           |               |\n *   Failed      Cancelled          |\n *                          +-------+------+\n *                          |              |\n *                      Recognized       Began\n *                                         |\n *                                      Changed\n *                                         |\n *                                  Ended/Recognized\n */\n\n/**\n * @private\n * Recognizer\n * Every recognizer needs to extend from this class.\n * @constructor\n * @param {Object} options\n */\n\nvar Recognizer = function () {\n  function Recognizer(options) {\n    classCallCheck(this, Recognizer);\n\n    this.options = assign$1({}, this.defaults, options || {});\n\n    this.id = uniqueId();\n\n    this.manager = null;\n\n    // default is enable true\n    this.options.enable = ifUndefined(this.options.enable, true);\n\n    this.state = STATE_POSSIBLE;\n    this.simultaneous = {};\n    this.requireFail = [];\n  }\n\n  /**\n   * @private\n   * set options\n   * @param {Object} options\n   * @return {Recognizer}\n   */\n\n\n  createClass(Recognizer, [{\n    key: 'set',\n    value: function set(options) {\n      assign$1(this.options, options);\n\n      // also update the touchAction, in case something changed about the directions/enabled state\n      this.manager && this.manager.touchAction.update();\n      return this;\n    }\n\n    /**\n     * @private\n     * recognize simultaneous with an other recognizer.\n     * @param {Recognizer} otherRecognizer\n     * @returns {Recognizer} this\n     */\n\n  }, {\n    key: 'recognizeWith',\n    value: function recognizeWith(otherRecognizer) {\n      if (invokeArrayArg(otherRecognizer, 'recognizeWith', this)) {\n        return this;\n      }\n\n      var simultaneous = this.simultaneous;\n\n      otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this);\n      if (!simultaneous[otherRecognizer.id]) {\n        simultaneous[otherRecognizer.id] = otherRecognizer;\n        otherRecognizer.recognizeWith(this);\n      }\n      return this;\n    }\n\n    /**\n     * @private\n     * drop the simultaneous link. it doesnt remove the link on the other recognizer.\n     * @param {Recognizer} otherRecognizer\n     * @returns {Recognizer} this\n     */\n\n  }, {\n    key: 'dropRecognizeWith',\n    value: function dropRecognizeWith(otherRecognizer) {\n      if (invokeArrayArg(otherRecognizer, 'dropRecognizeWith', this)) {\n        return this;\n      }\n\n      otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this);\n      delete this.simultaneous[otherRecognizer.id];\n      return this;\n    }\n\n    /**\n     * @private\n     * recognizer can only run when an other is failing\n     * @param {Recognizer} otherRecognizer\n     * @returns {Recognizer} this\n     */\n\n  }, {\n    key: 'requireFailure',\n    value: function requireFailure(otherRecognizer) {\n      if (invokeArrayArg(otherRecognizer, 'requireFailure', this)) {\n        return this;\n      }\n\n      var requireFail = this.requireFail;\n\n      otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this);\n      if (inArray(requireFail, otherRecognizer) === -1) {\n        requireFail.push(otherRecognizer);\n        otherRecognizer.requireFailure(this);\n      }\n      return this;\n    }\n\n    /**\n     * @private\n     * drop the requireFailure link. it does not remove the link on the other recognizer.\n     * @param {Recognizer} otherRecognizer\n     * @returns {Recognizer} this\n     */\n\n  }, {\n    key: 'dropRequireFailure',\n    value: function dropRequireFailure(otherRecognizer) {\n      if (invokeArrayArg(otherRecognizer, 'dropRequireFailure', this)) {\n        return this;\n      }\n\n      otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this);\n      var index = inArray(this.requireFail, otherRecognizer);\n      if (index > -1) {\n        this.requireFail.splice(index, 1);\n      }\n      return this;\n    }\n\n    /**\n     * @private\n     * has require failures boolean\n     * @returns {boolean}\n     */\n\n  }, {\n    key: 'hasRequireFailures',\n    value: function hasRequireFailures() {\n      return this.requireFail.length > 0;\n    }\n\n    /**\n     * @private\n     * if the recognizer can recognize simultaneous with an other recognizer\n     * @param {Recognizer} otherRecognizer\n     * @returns {Boolean}\n     */\n\n  }, {\n    key: 'canRecognizeWith',\n    value: function canRecognizeWith(otherRecognizer) {\n      return !!this.simultaneous[otherRecognizer.id];\n    }\n\n    /**\n     * @private\n     * You should use `tryEmit` instead of `emit` directly to check\n     * that all the needed recognizers has failed before emitting.\n     * @param {Object} input\n     */\n\n  }, {\n    key: 'emit',\n    value: function emit(input) {\n      var self = this;\n      var state = this.state;\n\n\n      function emit(event) {\n        self.manager.emit(event, input);\n      }\n\n      // 'panstart' and 'panmove'\n      if (state < STATE_ENDED) {\n        emit(self.options.event + stateStr(state));\n      }\n\n      emit(self.options.event); // simple 'eventName' events\n\n      if (input.additionalEvent) {\n        // additional event(panleft, panright, pinchin, pinchout...)\n        emit(input.additionalEvent);\n      }\n\n      // panend and pancancel\n      if (state >= STATE_ENDED) {\n        emit(self.options.event + stateStr(state));\n      }\n    }\n\n    /**\n     * @private\n     * Check that all the require failure recognizers has failed,\n     * if true, it emits a gesture event,\n     * otherwise, setup the state to FAILED.\n     * @param {Object} input\n     */\n\n  }, {\n    key: 'tryEmit',\n    value: function tryEmit(input) {\n      if (this.canEmit()) {\n        return this.emit(input);\n      }\n      // it's failing anyway\n      this.state = STATE_FAILED;\n    }\n\n    /**\n     * @private\n     * can we emit?\n     * @returns {boolean}\n     */\n\n  }, {\n    key: 'canEmit',\n    value: function canEmit() {\n      var i = 0;\n      while (i < this.requireFail.length) {\n        if (!(this.requireFail[i].state & (STATE_FAILED | STATE_POSSIBLE))) {\n          return false;\n        }\n        i++;\n      }\n      return true;\n    }\n\n    /**\n     * @private\n     * update the recognizer\n     * @param {Object} inputData\n     */\n\n  }, {\n    key: 'recognize',\n    value: function recognize(inputData) {\n      // make a new copy of the inputData\n      // so we can change the inputData without messing up the other recognizers\n      var inputDataClone = assign$1({}, inputData);\n\n      // is is enabled and allow recognizing?\n      if (!boolOrFn(this.options.enable, [this, inputDataClone])) {\n        this.reset();\n        this.state = STATE_FAILED;\n        return;\n      }\n\n      // reset when we've reached the end\n      if (this.state & (STATE_RECOGNIZED | STATE_CANCELLED | STATE_FAILED)) {\n        this.state = STATE_POSSIBLE;\n      }\n\n      this.state = this.process(inputDataClone);\n\n      // the recognizer has recognized a gesture\n      // so trigger an event\n      if (this.state & (STATE_BEGAN | STATE_CHANGED | STATE_ENDED | STATE_CANCELLED)) {\n        this.tryEmit(inputDataClone);\n      }\n    }\n\n    /**\n     * @private\n     * return the state of the recognizer\n     * the actual recognizing happens in this method\n     * @virtual\n     * @param {Object} inputData\n     * @returns {constant} STATE\n     */\n\n    /* jshint ignore:start */\n\n  }, {\n    key: 'process',\n    value: function process(inputData) {}\n    /* jshint ignore:end */\n\n    /**\n     * @private\n     * return the preferred touch-action\n     * @virtual\n     * @returns {Array}\n     */\n\n  }, {\n    key: 'getTouchAction',\n    value: function getTouchAction() {}\n\n    /**\n     * @private\n     * called when the gesture isn't allowed to recognize\n     * like when another is being recognized or it is disabled\n     * @virtual\n     */\n\n  }, {\n    key: 'reset',\n    value: function reset() {}\n  }]);\n  return Recognizer;\n}();\n\nRecognizer.prototype.defaults = {};\n\n/**\n * @private\n * This recognizer is just used as a base for the simple attribute recognizers.\n * @constructor\n * @extends Recognizer\n */\n\nvar AttrRecognizer = function (_Recognizer) {\n  inherits(AttrRecognizer, _Recognizer);\n\n  function AttrRecognizer() {\n    classCallCheck(this, AttrRecognizer);\n    return possibleConstructorReturn(this, (AttrRecognizer.__proto__ || Object.getPrototypeOf(AttrRecognizer)).apply(this, arguments));\n  }\n\n  /**\n   * @private\n   * Used to check if it the recognizer receives valid input, like input.distance > 10.\n   * @memberof AttrRecognizer\n   * @param {Object} input\n   * @returns {Boolean} recognized\n   */\n\n\n  createClass(AttrRecognizer, [{\n    key: 'attrTest',\n    value: function attrTest(input) {\n      var optionPointers = this.options.pointers;\n      return optionPointers === 0 || input.pointers.length === optionPointers;\n    }\n\n    /**\n     * @private\n     * Process the input and return the state for the recognizer\n     * @memberof AttrRecognizer\n     * @param {Object} input\n     * @returns {*} State\n     */\n\n  }, {\n    key: 'process',\n    value: function process(input) {\n      var state = this.state;\n      var eventType = input.eventType;\n\n\n      var isRecognized = state & (STATE_BEGAN | STATE_CHANGED);\n      var isValid = this.attrTest(input);\n\n      // on cancel input and we've recognized before, return STATE_CANCELLED\n      if (isRecognized && (eventType & INPUT_CANCEL || !isValid)) {\n        return state | STATE_CANCELLED;\n      } else if (isRecognized || isValid) {\n        if (eventType & INPUT_END) {\n          return state | STATE_ENDED;\n        } else if (!(state & STATE_BEGAN)) {\n          return STATE_BEGAN;\n        }\n        return state | STATE_CHANGED;\n      }\n      return STATE_FAILED;\n    }\n  }]);\n  return AttrRecognizer;\n}(Recognizer);\n\nAttrRecognizer.prototype.defaults = {\n  /**\n   * @private\n   * @type {Number}\n   * @default 1\n   */\n  pointers: 1\n};\n\n/**\n * @private\n * Rotate\n * Recognized when two or more pointer are moving in a circular motion.\n * @constructor\n * @extends AttrRecognizer\n */\n\nvar RotateRecognizer = function (_AttrRecognizer) {\n  inherits(RotateRecognizer, _AttrRecognizer);\n\n  function RotateRecognizer() {\n    classCallCheck(this, RotateRecognizer);\n    return possibleConstructorReturn(this, (RotateRecognizer.__proto__ || Object.getPrototypeOf(RotateRecognizer)).apply(this, arguments));\n  }\n\n  createClass(RotateRecognizer, [{\n    key: 'getTouchAction',\n    value: function getTouchAction() {\n      return [TOUCH_ACTION_NONE];\n    }\n  }, {\n    key: 'attrTest',\n    value: function attrTest(input) {\n      return get(RotateRecognizer.prototype.__proto__ || Object.getPrototypeOf(RotateRecognizer.prototype), 'attrTest', this).call(this, input) && (Math.abs(input.rotation) > this.options.threshold || this.state & STATE_BEGAN);\n    }\n  }]);\n  return RotateRecognizer;\n}(AttrRecognizer);\n\nRotateRecognizer.prototype.defaults = {\n  event: 'rotate',\n  threshold: 0,\n  pointers: 2\n};\n\n/**\n * @private\n * Pinch\n * Recognized when two or more pointers are moving toward (zoom-in) or away from each other (zoom-out).\n * @constructor\n * @extends AttrRecognizer\n */\n\nvar PinchRecognizer = function (_AttrRecognizer) {\n  inherits(PinchRecognizer, _AttrRecognizer);\n\n  function PinchRecognizer() {\n    classCallCheck(this, PinchRecognizer);\n    return possibleConstructorReturn(this, (PinchRecognizer.__proto__ || Object.getPrototypeOf(PinchRecognizer)).apply(this, arguments));\n  }\n\n  createClass(PinchRecognizer, [{\n    key: 'getTouchAction',\n    value: function getTouchAction() {\n      return [TOUCH_ACTION_NONE];\n    }\n  }, {\n    key: 'attrTest',\n    value: function attrTest(input) {\n      return get(PinchRecognizer.prototype.__proto__ || Object.getPrototypeOf(PinchRecognizer.prototype), 'attrTest', this).call(this, input) && (Math.abs(input.scale - 1) > this.options.threshold || this.state & STATE_BEGAN);\n    }\n  }, {\n    key: 'emit',\n    value: function emit(input) {\n      if (input.scale !== 1) {\n        var inOut = input.scale < 1 ? 'in' : 'out';\n        input.additionalEvent = this.options.event + inOut;\n      }\n      get(PinchRecognizer.prototype.__proto__ || Object.getPrototypeOf(PinchRecognizer.prototype), 'emit', this).call(this, input);\n    }\n  }]);\n  return PinchRecognizer;\n}(AttrRecognizer);\n\nPinchRecognizer.prototype.defaults = {\n  event: 'pinch',\n  threshold: 0,\n  pointers: 2\n};\n\n/**\n * @private\n * direction cons to string\n * @param {constant} direction\n * @returns {String}\n */\nfunction directionStr(direction) {\n  if (direction === DIRECTION_DOWN) {\n    return 'down';\n  } else if (direction === DIRECTION_UP) {\n    return 'up';\n  } else if (direction === DIRECTION_LEFT) {\n    return 'left';\n  } else if (direction === DIRECTION_RIGHT) {\n    return 'right';\n  }\n  return '';\n}\n\n/**\n * @private\n * Pan\n * Recognized when the pointer is down and moved in the allowed direction.\n * @constructor\n * @extends AttrRecognizer\n */\n\nvar PanRecognizer = function (_AttrRecognizer) {\n  inherits(PanRecognizer, _AttrRecognizer);\n\n  function PanRecognizer() {\n    classCallCheck(this, PanRecognizer);\n\n    var _this = possibleConstructorReturn(this, (PanRecognizer.__proto__ || Object.getPrototypeOf(PanRecognizer)).apply(this, arguments));\n\n    _this.pX = null;\n    _this.pY = null;\n    return _this;\n  }\n\n  createClass(PanRecognizer, [{\n    key: 'getTouchAction',\n    value: function getTouchAction() {\n      var direction = this.options.direction;\n\n      var actions = [];\n      if (direction & DIRECTION_HORIZONTAL) {\n        actions.push(TOUCH_ACTION_PAN_Y);\n      }\n      if (direction & DIRECTION_VERTICAL) {\n        actions.push(TOUCH_ACTION_PAN_X);\n      }\n      return actions;\n    }\n  }, {\n    key: 'directionTest',\n    value: function directionTest(input) {\n      var options = this.options;\n\n      var hasMoved = true;\n      var distance = input.distance;\n      var direction = input.direction;\n\n      var x = input.deltaX;\n      var y = input.deltaY;\n\n      // lock to axis?\n      if (!(direction & options.direction)) {\n        if (options.direction & DIRECTION_HORIZONTAL) {\n          direction = x === 0 ? DIRECTION_NONE : x < 0 ? DIRECTION_LEFT : DIRECTION_RIGHT;\n          hasMoved = x !== this.pX;\n          distance = Math.abs(input.deltaX);\n        } else {\n          direction = y === 0 ? DIRECTION_NONE : y < 0 ? DIRECTION_UP : DIRECTION_DOWN;\n          hasMoved = y !== this.pY;\n          distance = Math.abs(input.deltaY);\n        }\n      }\n      input.direction = direction;\n      return hasMoved && distance > options.threshold && direction & options.direction;\n    }\n  }, {\n    key: 'attrTest',\n    value: function attrTest(input) {\n      return AttrRecognizer.prototype.attrTest.call(this, input) && ( // replace with a super call\n      this.state & STATE_BEGAN || !(this.state & STATE_BEGAN) && this.directionTest(input));\n    }\n  }, {\n    key: 'emit',\n    value: function emit(input) {\n\n      this.pX = input.deltaX;\n      this.pY = input.deltaY;\n\n      var direction = directionStr(input.direction);\n\n      if (direction) {\n        input.additionalEvent = this.options.event + direction;\n      }\n      get(PanRecognizer.prototype.__proto__ || Object.getPrototypeOf(PanRecognizer.prototype), 'emit', this).call(this, input);\n    }\n  }]);\n  return PanRecognizer;\n}(AttrRecognizer);\n\nPanRecognizer.prototype.defaults = {\n  event: 'pan',\n  threshold: 10,\n  pointers: 1,\n  direction: DIRECTION_ALL\n};\n\n/**\n * @private\n * Swipe\n * Recognized when the pointer is moving fast (velocity), with enough distance in the allowed direction.\n * @constructor\n * @extends AttrRecognizer\n */\n\nvar SwipeRecognizer = function (_AttrRecognizer) {\n  inherits(SwipeRecognizer, _AttrRecognizer);\n\n  function SwipeRecognizer() {\n    classCallCheck(this, SwipeRecognizer);\n    return possibleConstructorReturn(this, (SwipeRecognizer.__proto__ || Object.getPrototypeOf(SwipeRecognizer)).apply(this, arguments));\n  }\n\n  createClass(SwipeRecognizer, [{\n    key: 'getTouchAction',\n    value: function getTouchAction() {\n      return PanRecognizer.prototype.getTouchAction.call(this);\n    }\n  }, {\n    key: 'attrTest',\n    value: function attrTest(input) {\n      var direction = this.options.direction;\n\n      var velocity = void 0;\n\n      if (direction & (DIRECTION_HORIZONTAL | DIRECTION_VERTICAL)) {\n        velocity = input.overallVelocity;\n      } else if (direction & DIRECTION_HORIZONTAL) {\n        velocity = input.overallVelocityX;\n      } else if (direction & DIRECTION_VERTICAL) {\n        velocity = input.overallVelocityY;\n      }\n\n      return get(SwipeRecognizer.prototype.__proto__ || Object.getPrototypeOf(SwipeRecognizer.prototype), 'attrTest', this).call(this, input) && direction & input.offsetDirection && input.distance > this.options.threshold && input.maxPointers === this.options.pointers && abs(velocity) > this.options.velocity && input.eventType & INPUT_END;\n    }\n  }, {\n    key: 'emit',\n    value: function emit(input) {\n      var direction = directionStr(input.offsetDirection);\n      if (direction) {\n        this.manager.emit(this.options.event + direction, input);\n      }\n\n      this.manager.emit(this.options.event, input);\n    }\n  }]);\n  return SwipeRecognizer;\n}(AttrRecognizer);\n\nSwipeRecognizer.prototype.defaults = {\n  event: 'swipe',\n  threshold: 10,\n  velocity: 0.3,\n  direction: DIRECTION_HORIZONTAL | DIRECTION_VERTICAL,\n  pointers: 1\n};\n\n/**\n * @private\n * simple function bind\n * @param {Function} fn\n * @param {Object} context\n * @returns {Function}\n */\nfunction bindFn(fn, context) {\n  return function boundFn() {\n    return fn.apply(context, arguments);\n  };\n}\n\n/**\n * @private\n * set a timeout with a given scope\n * @param {Function} fn\n * @param {Number} timeout\n * @param {Object} context\n * @returns {number}\n */\nfunction setTimeoutContext(fn, timeout, context) {\n  return setTimeout(bindFn(fn, context), timeout);\n}\n\n/**\n * @private\n * calculate the absolute distance between two points\n * @param {Object} p1 {x, y}\n * @param {Object} p2 {x, y}\n * @param {Array} [props] containing x and y keys\n * @return {Number} distance\n */\nfunction getDistance(p1, p2, props) {\n  if (!props) {\n    props = PROPS_XY;\n  }\n  var x = p2[props[0]] - p1[props[0]];\n  var y = p2[props[1]] - p1[props[1]];\n\n  return Math.sqrt(x * x + y * y);\n}\n\n/**\n * @private\n * A tap is recognized when the pointer is doing a small tap/click. Multiple taps are recognized if they occur\n * between the given interval and position. The delay option can be used to recognize multi-taps without firing\n * a single tap.\n *\n * The eventData from the emitted event contains the property `tapCount`, which contains the amount of\n * multi-taps being recognized.\n * @constructor\n * @extends Recognizer\n */\n\nvar TapRecognizer = function (_Recognizer) {\n  inherits(TapRecognizer, _Recognizer);\n\n  function TapRecognizer() {\n    classCallCheck(this, TapRecognizer);\n\n    // previous time and center,\n    // used for tap counting\n    var _this = possibleConstructorReturn(this, (TapRecognizer.__proto__ || Object.getPrototypeOf(TapRecognizer)).apply(this, arguments));\n\n    _this.pTime = false;\n    _this.pCenter = false;\n\n    _this._timer = null;\n    _this._input = null;\n    _this.count = 0;\n    return _this;\n  }\n\n  createClass(TapRecognizer, [{\n    key: 'getTouchAction',\n    value: function getTouchAction() {\n      return [TOUCH_ACTION_MANIPULATION];\n    }\n  }, {\n    key: 'process',\n    value: function process(input) {\n      var _this2 = this;\n\n      var options = this.options;\n\n\n      var validPointers = input.pointers.length === options.pointers;\n      var validMovement = input.distance < options.threshold;\n      var validTouchTime = input.deltaTime < options.time;\n\n      this.reset();\n\n      if (input.eventType & INPUT_START && this.count === 0) {\n        return this.failTimeout();\n      }\n\n      // we only allow little movement\n      // and we've reached an end event, so a tap is possible\n      if (validMovement && validTouchTime && validPointers) {\n        if (input.eventType !== INPUT_END) {\n          return this.failTimeout();\n        }\n\n        var validInterval = this.pTime ? input.timeStamp - this.pTime < options.interval : true;\n        var validMultiTap = !this.pCenter || getDistance(this.pCenter, input.center) < options.posThreshold;\n\n        this.pTime = input.timeStamp;\n        this.pCenter = input.center;\n\n        if (!validMultiTap || !validInterval) {\n          this.count = 1;\n        } else {\n          this.count += 1;\n        }\n\n        this._input = input;\n\n        // if tap count matches we have recognized it,\n        // else it has began recognizing...\n        var tapCount = this.count % options.taps;\n        if (tapCount === 0) {\n          // no failing requirements, immediately trigger the tap event\n          // or wait as long as the multitap interval to trigger\n          if (!this.hasRequireFailures()) {\n            return STATE_RECOGNIZED;\n          } else {\n            this._timer = setTimeoutContext(function () {\n              _this2.state = STATE_RECOGNIZED;\n              _this2.tryEmit();\n            }, options.interval, this);\n            return STATE_BEGAN;\n          }\n        }\n      }\n      return STATE_FAILED;\n    }\n  }, {\n    key: 'failTimeout',\n    value: function failTimeout() {\n      var _this3 = this;\n\n      this._timer = setTimeoutContext(function () {\n        _this3.state = STATE_FAILED;\n      }, this.options.interval, this);\n      return STATE_FAILED;\n    }\n  }, {\n    key: 'reset',\n    value: function reset() {\n      clearTimeout(this._timer);\n    }\n  }, {\n    key: 'emit',\n    value: function emit() {\n      if (this.state === STATE_RECOGNIZED) {\n        this._input.tapCount = this.count;\n        this.manager.emit(this.options.event, this._input);\n      }\n    }\n  }]);\n  return TapRecognizer;\n}(Recognizer);\n\nTapRecognizer.prototype.defaults = {\n  event: 'tap',\n  pointers: 1,\n  taps: 1,\n  interval: 300, // max time between the multi-tap taps\n  time: 250, // max time of the pointer to be down (like finger on the screen)\n  threshold: 9, // a minimal movement is ok, but keep it low\n  posThreshold: 10 // a multi-tap can be a bit off the initial position\n};\n\n/**\n * @private\n * Press\n * Recognized when the pointer is down for x ms without any movement.\n * @constructor\n * @extends Recognizer\n */\n\nvar PressRecognizer = function (_Recognizer) {\n  inherits(PressRecognizer, _Recognizer);\n\n  function PressRecognizer() {\n    classCallCheck(this, PressRecognizer);\n\n    var _this = possibleConstructorReturn(this, (PressRecognizer.__proto__ || Object.getPrototypeOf(PressRecognizer)).apply(this, arguments));\n\n    _this._timer = null;\n    _this._input = null;\n    return _this;\n  }\n\n  createClass(PressRecognizer, [{\n    key: 'getTouchAction',\n    value: function getTouchAction() {\n      return [TOUCH_ACTION_AUTO];\n    }\n  }, {\n    key: 'process',\n    value: function process(input) {\n      var _this2 = this;\n\n      var options = this.options;\n\n      var validPointers = input.pointers.length === options.pointers;\n      var validMovement = input.distance < options.threshold;\n      var validTime = input.deltaTime > options.time;\n\n      this._input = input;\n\n      // we only allow little movement\n      // and we've reached an end event, so a tap is possible\n      if (!validMovement || !validPointers || input.eventType & (INPUT_END | INPUT_CANCEL) && !validTime) {\n        this.reset();\n      } else if (input.eventType & INPUT_START) {\n        this.reset();\n        this._timer = setTimeoutContext(function () {\n          _this2.state = STATE_RECOGNIZED;\n          _this2.tryEmit();\n        }, options.time, this);\n      } else if (input.eventType & INPUT_END) {\n        return STATE_RECOGNIZED;\n      }\n      return STATE_FAILED;\n    }\n  }, {\n    key: 'reset',\n    value: function reset() {\n      clearTimeout(this._timer);\n    }\n  }, {\n    key: 'emit',\n    value: function emit(input) {\n      if (this.state !== STATE_RECOGNIZED) {\n        return;\n      }\n\n      if (input && input.eventType & INPUT_END) {\n        this.manager.emit(this.options.event + 'up', input);\n      } else {\n        this._input.timeStamp = now();\n        this.manager.emit(this.options.event, this._input);\n      }\n    }\n  }]);\n  return PressRecognizer;\n}(Recognizer);\n\nPressRecognizer.prototype.defaults = {\n  event: 'press',\n  pointers: 1,\n  time: 251, // minimal time of the pointer to be pressed\n  threshold: 9 // a minimal movement is ok, but keep it low\n};\n\n/**\n * @private\n * small indexOf wrapper\n * @param {String} str\n * @param {String} find\n * @returns {Boolean} found\n */\nfunction inStr(str, find) {\n  return str.indexOf(find) > -1;\n}\n\n/**\n * @private\n * when the touchActions are collected they are not a valid value, so we need to clean things up. *\n * @param {String} actions\n * @returns {*}\n */\nfunction cleanTouchActions(actions) {\n  // none\n  if (inStr(actions, TOUCH_ACTION_NONE)) {\n    return TOUCH_ACTION_NONE;\n  }\n\n  var hasPanX = inStr(actions, TOUCH_ACTION_PAN_X);\n  var hasPanY = inStr(actions, TOUCH_ACTION_PAN_Y);\n\n  // if both pan-x and pan-y are set (different recognizers\n  // for different directions, e.g. horizontal pan but vertical swipe?)\n  // we need none (as otherwise with pan-x pan-y combined none of these\n  // recognizers will work, since the browser would handle all panning\n  if (hasPanX && hasPanY) {\n    return TOUCH_ACTION_NONE;\n  }\n\n  // pan-x OR pan-y\n  if (hasPanX || hasPanY) {\n    return hasPanX ? TOUCH_ACTION_PAN_X : TOUCH_ACTION_PAN_Y;\n  }\n\n  // manipulation\n  if (inStr(actions, TOUCH_ACTION_MANIPULATION)) {\n    return TOUCH_ACTION_MANIPULATION;\n  }\n\n  return TOUCH_ACTION_AUTO;\n}\n\n/**\n * @private\n * Touch Action\n * sets the touchAction property or uses the js alternative\n * @param {Manager} manager\n * @param {String} value\n * @constructor\n */\n\nvar TouchAction = function () {\n  function TouchAction(manager, value) {\n    classCallCheck(this, TouchAction);\n\n    this.manager = manager;\n    this.set(value);\n  }\n\n  /**\n   * @private\n   * set the touchAction value on the element or enable the polyfill\n   * @param {String} value\n   */\n\n\n  createClass(TouchAction, [{\n    key: 'set',\n    value: function set(value) {\n      // find out the touch-action by the event handlers\n      if (value === TOUCH_ACTION_COMPUTE) {\n        value = this.compute();\n      }\n\n      if (NATIVE_TOUCH_ACTION && this.manager.element.style && TOUCH_ACTION_MAP[value]) {\n        this.manager.element.style[PREFIXED_TOUCH_ACTION] = value;\n      }\n      this.actions = value.toLowerCase().trim();\n    }\n\n    /**\n     * @private\n     * just re-set the touchAction value\n     */\n\n  }, {\n    key: 'update',\n    value: function update() {\n      this.set(this.manager.options.touchAction);\n    }\n\n    /**\n     * @private\n     * compute the value for the touchAction property based on the recognizer's settings\n     * @returns {String} value\n     */\n\n  }, {\n    key: 'compute',\n    value: function compute() {\n      var actions = [];\n      each(this.manager.recognizers, function (recognizer) {\n        if (boolOrFn(recognizer.options.enable, [recognizer])) {\n          actions = actions.concat(recognizer.getTouchAction());\n        }\n      });\n      return cleanTouchActions(actions.join(' '));\n    }\n\n    /**\n     * @private\n     * this method is called on each input cycle and provides the preventing of the browser behavior\n     * @param {Object} input\n     */\n\n  }, {\n    key: 'preventDefaults',\n    value: function preventDefaults(input) {\n      var srcEvent = input.srcEvent;\n\n      var direction = input.offsetDirection;\n\n      // if the touch action did prevented once this session\n      if (this.manager.session.prevented) {\n        srcEvent.preventDefault();\n        return;\n      }\n\n      var actions = this.actions;\n\n      var hasNone = inStr(actions, TOUCH_ACTION_NONE) && !TOUCH_ACTION_MAP[TOUCH_ACTION_NONE];\n      var hasPanY = inStr(actions, TOUCH_ACTION_PAN_Y) && !TOUCH_ACTION_MAP[TOUCH_ACTION_PAN_Y];\n      var hasPanX = inStr(actions, TOUCH_ACTION_PAN_X) && !TOUCH_ACTION_MAP[TOUCH_ACTION_PAN_X];\n\n      if (hasNone) {\n        // do not prevent defaults if this is a tap gesture\n        var isTapPointer = input.pointers.length === 1;\n        var isTapMovement = input.distance < 2;\n        var isTapTouchTime = input.deltaTime < 250;\n\n        if (isTapPointer && isTapMovement && isTapTouchTime) {\n          return;\n        }\n      }\n\n      if (hasPanX && hasPanY) {\n        // `pan-x pan-y` means browser handles all scrolling/panning, do not prevent\n        return;\n      }\n\n      if (hasNone || hasPanY && direction & DIRECTION_HORIZONTAL || hasPanX && direction & DIRECTION_VERTICAL) {\n        return this.preventSrc(srcEvent);\n      }\n    }\n\n    /**\n     * @private\n     * call preventDefault to prevent the browser's default behavior (scrolling in most cases)\n     * @param {Object} srcEvent\n     */\n\n  }, {\n    key: 'preventSrc',\n    value: function preventSrc(srcEvent) {\n      this.manager.session.prevented = true;\n      srcEvent.preventDefault();\n    }\n  }]);\n  return TouchAction;\n}();\n\n/**\n * @private\n * find if a node is in the given parent\n * @method hasParent\n * @param {HTMLElement} node\n * @param {HTMLElement} parent\n * @return {Boolean} found\n */\nfunction hasParent(node, parent) {\n  while (node) {\n    if (node === parent) {\n      return true;\n    }\n    node = node.parentNode;\n  }\n  return false;\n}\n\n/**\n * @private\n * get the center of all the pointers\n * @param {Array} pointers\n * @return {Object} center contains `x` and `y` properties\n */\nfunction getCenter(pointers) {\n  var pointersLength = pointers.length;\n\n  // no need to loop when only one touch\n  if (pointersLength === 1) {\n    return {\n      x: round(pointers[0].clientX),\n      y: round(pointers[0].clientY)\n    };\n  }\n\n  var x = 0;\n  var y = 0;\n  var i = 0;\n  while (i < pointersLength) {\n    x += pointers[i].clientX;\n    y += pointers[i].clientY;\n    i++;\n  }\n\n  return {\n    x: round(x / pointersLength),\n    y: round(y / pointersLength)\n  };\n}\n\n/**\n * @private\n * create a simple clone from the input used for storage of firstInput and firstMultiple\n * @param {Object} input\n * @returns {Object} clonedInputData\n */\nfunction simpleCloneInputData(input) {\n  // make a simple copy of the pointers because we will get a reference if we don't\n  // we only need clientXY for the calculations\n  var pointers = [];\n  var i = 0;\n  while (i < input.pointers.length) {\n    pointers[i] = {\n      clientX: round(input.pointers[i].clientX),\n      clientY: round(input.pointers[i].clientY)\n    };\n    i++;\n  }\n\n  return {\n    timeStamp: now(),\n    pointers: pointers,\n    center: getCenter(pointers),\n    deltaX: input.deltaX,\n    deltaY: input.deltaY\n  };\n}\n\n/**\n * @private\n * calculate the angle between two coordinates\n * @param {Object} p1\n * @param {Object} p2\n * @param {Array} [props] containing x and y keys\n * @return {Number} angle\n */\nfunction getAngle(p1, p2, props) {\n  if (!props) {\n    props = PROPS_XY;\n  }\n  var x = p2[props[0]] - p1[props[0]];\n  var y = p2[props[1]] - p1[props[1]];\n  return Math.atan2(y, x) * 180 / Math.PI;\n}\n\n/**\n * @private\n * get the direction between two points\n * @param {Number} x\n * @param {Number} y\n * @return {Number} direction\n */\nfunction getDirection(x, y) {\n  if (x === y) {\n    return DIRECTION_NONE;\n  }\n\n  if (abs(x) >= abs(y)) {\n    return x < 0 ? DIRECTION_LEFT : DIRECTION_RIGHT;\n  }\n  return y < 0 ? DIRECTION_UP : DIRECTION_DOWN;\n}\n\nfunction computeDeltaXY(session, input) {\n  var center = input.center;\n  // let { offsetDelta:offset = {}, prevDelta = {}, prevInput = {} } = session;\n  // jscs throwing error on defalut destructured values and without defaults tests fail\n\n  var offset = session.offsetDelta || {};\n  var prevDelta = session.prevDelta || {};\n  var prevInput = session.prevInput || {};\n\n  if (input.eventType === INPUT_START || prevInput.eventType === INPUT_END) {\n    prevDelta = session.prevDelta = {\n      x: prevInput.deltaX || 0,\n      y: prevInput.deltaY || 0\n    };\n\n    offset = session.offsetDelta = {\n      x: center.x,\n      y: center.y\n    };\n  }\n\n  input.deltaX = prevDelta.x + (center.x - offset.x);\n  input.deltaY = prevDelta.y + (center.y - offset.y);\n}\n\n/**\n * @private\n * calculate the velocity between two points. unit is in px per ms.\n * @param {Number} deltaTime\n * @param {Number} x\n * @param {Number} y\n * @return {Object} velocity `x` and `y`\n */\nfunction getVelocity(deltaTime, x, y) {\n  return {\n    x: x / deltaTime || 0,\n    y: y / deltaTime || 0\n  };\n}\n\n/**\n * @private\n * calculate the scale factor between two pointersets\n * no scale is 1, and goes down to 0 when pinched together, and bigger when pinched out\n * @param {Array} start array of pointers\n * @param {Array} end array of pointers\n * @return {Number} scale\n */\nfunction getScale(start, end) {\n  return getDistance(end[0], end[1], PROPS_CLIENT_XY) / getDistance(start[0], start[1], PROPS_CLIENT_XY);\n}\n\n/**\n * @private\n * calculate the rotation degrees between two pointersets\n * @param {Array} start array of pointers\n * @param {Array} end array of pointers\n * @return {Number} rotation\n */\nfunction getRotation(start, end) {\n  return getAngle(end[1], end[0], PROPS_CLIENT_XY) + getAngle(start[1], start[0], PROPS_CLIENT_XY);\n}\n\n/**\n * @private\n * velocity is calculated every x ms\n * @param {Object} session\n * @param {Object} input\n */\nfunction computeIntervalInputData(session, input) {\n  var last = session.lastInterval || input;\n  var deltaTime = input.timeStamp - last.timeStamp;\n  var velocity = void 0;\n  var velocityX = void 0;\n  var velocityY = void 0;\n  var direction = void 0;\n\n  if (input.eventType !== INPUT_CANCEL && (deltaTime > COMPUTE_INTERVAL || last.velocity === undefined)) {\n    var deltaX = input.deltaX - last.deltaX;\n    var deltaY = input.deltaY - last.deltaY;\n\n    var v = getVelocity(deltaTime, deltaX, deltaY);\n    velocityX = v.x;\n    velocityY = v.y;\n    velocity = abs(v.x) > abs(v.y) ? v.x : v.y;\n    direction = getDirection(deltaX, deltaY);\n\n    session.lastInterval = input;\n  } else {\n    // use latest velocity info if it doesn't overtake a minimum period\n    velocity = last.velocity;\n    velocityX = last.velocityX;\n    velocityY = last.velocityY;\n    direction = last.direction;\n  }\n\n  input.velocity = velocity;\n  input.velocityX = velocityX;\n  input.velocityY = velocityY;\n  input.direction = direction;\n}\n\n/**\n* @private\n * extend the data with some usable properties like scale, rotate, velocity etc\n * @param {Object} manager\n * @param {Object} input\n */\nfunction computeInputData(manager, input) {\n  var session = manager.session;\n  var pointers = input.pointers;\n  var pointersLength = pointers.length;\n\n  // store the first input to calculate the distance and direction\n\n  if (!session.firstInput) {\n    session.firstInput = simpleCloneInputData(input);\n  }\n\n  // to compute scale and rotation we need to store the multiple touches\n  if (pointersLength > 1 && !session.firstMultiple) {\n    session.firstMultiple = simpleCloneInputData(input);\n  } else if (pointersLength === 1) {\n    session.firstMultiple = false;\n  }\n\n  var firstInput = session.firstInput;\n  var firstMultiple = session.firstMultiple;\n\n  var offsetCenter = firstMultiple ? firstMultiple.center : firstInput.center;\n\n  var center = input.center = getCenter(pointers);\n  input.timeStamp = now();\n  input.deltaTime = input.timeStamp - firstInput.timeStamp;\n\n  input.angle = getAngle(offsetCenter, center);\n  input.distance = getDistance(offsetCenter, center);\n\n  computeDeltaXY(session, input);\n  input.offsetDirection = getDirection(input.deltaX, input.deltaY);\n\n  var overallVelocity = getVelocity(input.deltaTime, input.deltaX, input.deltaY);\n  input.overallVelocityX = overallVelocity.x;\n  input.overallVelocityY = overallVelocity.y;\n  input.overallVelocity = abs(overallVelocity.x) > abs(overallVelocity.y) ? overallVelocity.x : overallVelocity.y;\n\n  input.scale = firstMultiple ? getScale(firstMultiple.pointers, pointers) : 1;\n  input.rotation = firstMultiple ? getRotation(firstMultiple.pointers, pointers) : 0;\n\n  input.maxPointers = !session.prevInput ? input.pointers.length : input.pointers.length > session.prevInput.maxPointers ? input.pointers.length : session.prevInput.maxPointers;\n\n  computeIntervalInputData(session, input);\n\n  // find the correct target\n  var target = manager.element;\n  if (hasParent(input.srcEvent.target, target)) {\n    target = input.srcEvent.target;\n  }\n  input.target = target;\n}\n\n/**\n * @private\n * handle input events\n * @param {Manager} manager\n * @param {String} eventType\n * @param {Object} input\n */\nfunction inputHandler(manager, eventType, input) {\n  var pointersLen = input.pointers.length;\n  var changedPointersLen = input.changedPointers.length;\n  var isFirst = eventType & INPUT_START && pointersLen - changedPointersLen === 0;\n  var isFinal = eventType & (INPUT_END | INPUT_CANCEL) && pointersLen - changedPointersLen === 0;\n\n  input.isFirst = !!isFirst;\n  input.isFinal = !!isFinal;\n\n  if (isFirst) {\n    manager.session = {};\n  }\n\n  // source event is the normalized value of the domEvents\n  // like 'touchstart, mouseup, pointerdown'\n  input.eventType = eventType;\n\n  // compute scale, rotation etc\n  computeInputData(manager, input);\n\n  // emit secret event\n  manager.emit('hammer.input', input);\n\n  manager.recognize(input);\n  manager.session.prevInput = input;\n}\n\n/**\n * @private\n * split string on whitespace\n * @param {String} str\n * @returns {Array} words\n */\n\nfunction splitStr(str) {\n  return str.trim().split(/\\s+/g);\n}\n\n/**\n * @private\n * addEventListener with multiple events at once\n * @param {EventTarget} target\n * @param {String} types\n * @param {Function} handler\n */\nfunction addEventListeners(target, types, handler) {\n  each(splitStr(types), function (type) {\n    target.addEventListener(type, handler, false);\n  });\n}\n\n/**\n * @private\n * removeEventListener with multiple events at once\n * @param {EventTarget} target\n * @param {String} types\n * @param {Function} handler\n */\nfunction removeEventListeners(target, types, handler) {\n  each(splitStr(types), function (type) {\n    target.removeEventListener(type, handler, false);\n  });\n}\n\n/**\n * @private\n * get the window object of an element\n * @param {HTMLElement} element\n * @returns {DocumentView|Window}\n */\nfunction getWindowForElement(element) {\n  var doc = element.ownerDocument || element;\n  return doc.defaultView || doc.parentWindow || window;\n}\n\n/**\n * @private\n * create new input type manager\n * @param {Manager} manager\n * @param {Function} callback\n * @returns {Input}\n * @constructor\n */\n\nvar Input = function () {\n  function Input(manager, callback) {\n    classCallCheck(this, Input);\n\n    var self = this;\n    this.manager = manager;\n    this.callback = callback;\n    this.element = manager.element;\n    this.target = manager.options.inputTarget;\n\n    // smaller wrapper around the handler, for the scope and the enabled state of the manager,\n    // so when disabled the input events are completely bypassed.\n    this.domHandler = function (ev) {\n      if (boolOrFn(manager.options.enable, [manager])) {\n        self.handler(ev);\n      }\n    };\n\n    this.init();\n  }\n  /**\n   * @private\n   * should handle the inputEvent data and trigger the callback\n   * @virtual\n   */\n\n\n  createClass(Input, [{\n    key: 'handler',\n    value: function handler() {}\n\n    /**\n     * @private\n     * bind the events\n     */\n\n  }, {\n    key: 'init',\n    value: function init() {\n      this.evEl && addEventListeners(this.element, this.evEl, this.domHandler);\n      this.evTarget && addEventListeners(this.target, this.evTarget, this.domHandler);\n      this.evWin && addEventListeners(getWindowForElement(this.element), this.evWin, this.domHandler);\n    }\n\n    /**\n     * @private\n     * unbind the events\n     */\n\n  }, {\n    key: 'destroy',\n    value: function destroy() {\n      this.evEl && removeEventListeners(this.element, this.evEl, this.domHandler);\n      this.evTarget && removeEventListeners(this.target, this.evTarget, this.domHandler);\n      this.evWin && removeEventListeners(getWindowForElement(this.element), this.evWin, this.domHandler);\n    }\n  }]);\n  return Input;\n}();\n\nvar POINTER_INPUT_MAP = {\n  pointerdown: INPUT_START,\n  pointermove: INPUT_MOVE,\n  pointerup: INPUT_END,\n  pointercancel: INPUT_CANCEL,\n  pointerout: INPUT_CANCEL\n};\n\n// in IE10 the pointer types is defined as an enum\nvar IE10_POINTER_TYPE_ENUM = {\n  2: INPUT_TYPE_TOUCH,\n  3: INPUT_TYPE_PEN,\n  4: INPUT_TYPE_MOUSE,\n  5: INPUT_TYPE_KINECT // see https://twitter.com/jacobrossi/status/480596438489890816\n};\n\nvar POINTER_ELEMENT_EVENTS = 'pointerdown';\nvar POINTER_WINDOW_EVENTS = 'pointermove pointerup pointercancel';\n\n// IE10 has prefixed support, and case-sensitive\nif (window.MSPointerEvent && !window.PointerEvent) {\n  POINTER_ELEMENT_EVENTS = 'MSPointerDown';\n  POINTER_WINDOW_EVENTS = 'MSPointerMove MSPointerUp MSPointerCancel';\n}\n\n/**\n * @private\n * Pointer events input\n * @constructor\n * @extends Input\n */\n\nvar PointerEventInput = function (_Input) {\n  inherits(PointerEventInput, _Input);\n\n  function PointerEventInput() {\n    classCallCheck(this, PointerEventInput);\n\n    var _this = possibleConstructorReturn(this, (PointerEventInput.__proto__ || Object.getPrototypeOf(PointerEventInput)).apply(this, arguments));\n\n    _this.evEl = POINTER_ELEMENT_EVENTS;\n    _this.evWin = POINTER_WINDOW_EVENTS;\n\n    _this.store = _this.manager.session.pointerEvents = [];\n    return _this;\n  }\n\n  /**\n   * @private\n   * handle mouse events\n   * @param {Object} ev\n   */\n\n\n  createClass(PointerEventInput, [{\n    key: 'handler',\n    value: function handler(ev) {\n      var store = this.store;\n\n      var removePointer = false;\n\n      var eventTypeNormalized = ev.type.toLowerCase().replace('ms', '');\n      var eventType = POINTER_INPUT_MAP[eventTypeNormalized];\n      var pointerType = IE10_POINTER_TYPE_ENUM[ev.pointerType] || ev.pointerType;\n\n      var isTouch = pointerType === INPUT_TYPE_TOUCH;\n\n      // get index of the event in the store\n      var storeIndex = inArray(store, ev.pointerId, 'pointerId');\n\n      // start and mouse must be down\n      if (eventType & INPUT_START && (ev.button === 0 || isTouch)) {\n        if (storeIndex < 0) {\n          store.push(ev);\n          storeIndex = store.length - 1;\n        }\n      } else if (eventType & (INPUT_END | INPUT_CANCEL)) {\n        removePointer = true;\n      }\n\n      // it not found, so the pointer hasn't been down (so it's probably a hover)\n      if (storeIndex < 0) {\n        return;\n      }\n\n      // update the event in the store\n      store[storeIndex] = ev;\n\n      this.callback(this.manager, eventType, {\n        pointers: store,\n        changedPointers: [ev],\n        pointerType: pointerType,\n        srcEvent: ev\n      });\n\n      if (removePointer) {\n        // remove from the store\n        store.splice(storeIndex, 1);\n      }\n    }\n  }]);\n  return PointerEventInput;\n}(Input);\n\n/**\n * @private\n * convert array-like objects to real arrays\n * @param {Object} obj\n * @returns {Array}\n */\nfunction toArray$1(obj) {\n  return Array.prototype.slice.call(obj, 0);\n}\n\n/**\n * @private\n * unique array with objects based on a key (like 'id') or just by the array's value\n * @param {Array} src [{id:1},{id:2},{id:1}]\n * @param {String} [key]\n * @param {Boolean} [sort=False]\n * @returns {Array} [{id:1},{id:2}]\n */\nfunction uniqueArray(src, key, sort) {\n  var results = [];\n  var values = [];\n  var i = 0;\n\n  while (i < src.length) {\n    var val = key ? src[i][key] : src[i];\n    if (inArray(values, val) < 0) {\n      results.push(src[i]);\n    }\n    values[i] = val;\n    i++;\n  }\n\n  if (sort) {\n    if (!key) {\n      results = results.sort();\n    } else {\n      results = results.sort(function (a, b) {\n        return a[key] > b[key];\n      });\n    }\n  }\n\n  return results;\n}\n\nvar TOUCH_INPUT_MAP = {\n  touchstart: INPUT_START,\n  touchmove: INPUT_MOVE,\n  touchend: INPUT_END,\n  touchcancel: INPUT_CANCEL\n};\n\nvar TOUCH_TARGET_EVENTS = 'touchstart touchmove touchend touchcancel';\n\n/**\n * @private\n * Multi-user touch events input\n * @constructor\n * @extends Input\n */\n\nvar TouchInput = function (_Input) {\n  inherits(TouchInput, _Input);\n\n  function TouchInput() {\n    classCallCheck(this, TouchInput);\n\n    TouchInput.prototype.evTarget = TOUCH_TARGET_EVENTS;\n    TouchInput.prototype.targetIds = {};\n\n    var _this = possibleConstructorReturn(this, (TouchInput.__proto__ || Object.getPrototypeOf(TouchInput)).apply(this, arguments));\n\n    _this.evTarget = TOUCH_TARGET_EVENTS;\n    _this.targetIds = {};\n    return _this;\n  }\n\n  createClass(TouchInput, [{\n    key: 'handler',\n    value: function handler(ev) {\n      var type = TOUCH_INPUT_MAP[ev.type];\n      var touches = getTouches.call(this, ev, type);\n      if (!touches) {\n        return;\n      }\n\n      this.callback(this.manager, type, {\n        pointers: touches[0],\n        changedPointers: touches[1],\n        pointerType: INPUT_TYPE_TOUCH,\n        srcEvent: ev\n      });\n    }\n  }]);\n  return TouchInput;\n}(Input);\n\nfunction getTouches(ev, type) {\n  var allTouches = toArray$1(ev.touches);\n  var targetIds = this.targetIds;\n\n  // when there is only one touch, the process can be simplified\n\n  if (type & (INPUT_START | INPUT_MOVE) && allTouches.length === 1) {\n    targetIds[allTouches[0].identifier] = true;\n    return [allTouches, allTouches];\n  }\n\n  var i = void 0;\n  var targetTouches = void 0;\n  var changedTouches = toArray$1(ev.changedTouches);\n  var changedTargetTouches = [];\n  var target = this.target;\n\n  // get target touches from touches\n\n  targetTouches = allTouches.filter(function (touch) {\n    return hasParent(touch.target, target);\n  });\n\n  // collect touches\n  if (type === INPUT_START) {\n    i = 0;\n    while (i < targetTouches.length) {\n      targetIds[targetTouches[i].identifier] = true;\n      i++;\n    }\n  }\n\n  // filter changed touches to only contain touches that exist in the collected target ids\n  i = 0;\n  while (i < changedTouches.length) {\n    if (targetIds[changedTouches[i].identifier]) {\n      changedTargetTouches.push(changedTouches[i]);\n    }\n\n    // cleanup removed touches\n    if (type & (INPUT_END | INPUT_CANCEL)) {\n      delete targetIds[changedTouches[i].identifier];\n    }\n    i++;\n  }\n\n  if (!changedTargetTouches.length) {\n    return;\n  }\n\n  return [\n  // merge targetTouches with changedTargetTouches so it contains ALL touches, including 'end' and 'cancel'\n  uniqueArray(targetTouches.concat(changedTargetTouches), 'identifier', true), changedTargetTouches];\n}\n\nvar MOUSE_INPUT_MAP = {\n  mousedown: INPUT_START,\n  mousemove: INPUT_MOVE,\n  mouseup: INPUT_END\n};\n\nvar MOUSE_ELEMENT_EVENTS = 'mousedown';\nvar MOUSE_WINDOW_EVENTS = 'mousemove mouseup';\n\n/**\n * @private\n * Mouse events input\n * @constructor\n * @extends Input\n */\n\nvar MouseInput = function (_Input) {\n  inherits(MouseInput, _Input);\n\n  function MouseInput() {\n    classCallCheck(this, MouseInput);\n\n    var _this = possibleConstructorReturn(this, (MouseInput.__proto__ || Object.getPrototypeOf(MouseInput)).apply(this, arguments));\n\n    _this.evEl = MOUSE_ELEMENT_EVENTS;\n    _this.evWin = MOUSE_WINDOW_EVENTS;\n\n    _this.pressed = false; // mousedown state\n    return _this;\n  }\n\n  /**\n   * @private\n   * handle mouse events\n   * @param {Object} ev\n   */\n\n\n  createClass(MouseInput, [{\n    key: 'handler',\n    value: function handler(ev) {\n      var eventType = MOUSE_INPUT_MAP[ev.type];\n\n      // on start we want to have the left mouse button down\n      if (eventType & INPUT_START && ev.button === 0) {\n        this.pressed = true;\n      }\n\n      if (eventType & INPUT_MOVE && ev.which !== 1) {\n        eventType = INPUT_END;\n      }\n\n      // mouse must be down\n      if (!this.pressed) {\n        return;\n      }\n\n      if (eventType & INPUT_END) {\n        this.pressed = false;\n      }\n\n      this.callback(this.manager, eventType, {\n        pointers: [ev],\n        changedPointers: [ev],\n        pointerType: INPUT_TYPE_MOUSE,\n        srcEvent: ev\n      });\n    }\n  }]);\n  return MouseInput;\n}(Input);\n\n/**\n * @private\n * Combined touch and mouse input\n *\n * Touch has a higher priority then mouse, and while touching no mouse events are allowed.\n * This because touch devices also emit mouse events while doing a touch.\n *\n * @constructor\n * @extends Input\n */\n\nvar DEDUP_TIMEOUT = 2500;\nvar DEDUP_DISTANCE = 25;\n\nvar TouchMouseInput = function (_Input) {\n  inherits(TouchMouseInput, _Input);\n\n  function TouchMouseInput() {\n    classCallCheck(this, TouchMouseInput);\n\n    var _this = possibleConstructorReturn(this, (TouchMouseInput.__proto__ || Object.getPrototypeOf(TouchMouseInput)).apply(this, arguments));\n\n    var handler = bindFn(_this.handler, _this);\n    _this.touch = new TouchInput(_this.manager, handler);\n    _this.mouse = new MouseInput(_this.manager, handler);\n\n    _this.primaryTouch = null;\n    _this.lastTouches = [];\n    return _this;\n  }\n\n  /**\n   * @private\n   * handle mouse and touch events\n   * @param {Hammer} manager\n   * @param {String} inputEvent\n   * @param {Object} inputData\n   */\n\n\n  createClass(TouchMouseInput, [{\n    key: 'handler',\n    value: function handler(manager, inputEvent, inputData) {\n      var isTouch = inputData.pointerType === INPUT_TYPE_TOUCH;\n      var isMouse = inputData.pointerType === INPUT_TYPE_MOUSE;\n\n      if (isMouse && inputData.sourceCapabilities && inputData.sourceCapabilities.firesTouchEvents) {\n        return;\n      }\n\n      // when we're in a touch event, record touches to  de-dupe synthetic mouse event\n      if (isTouch) {\n        recordTouches.call(this, inputEvent, inputData);\n      } else if (isMouse && isSyntheticEvent.call(this, inputData)) {\n        return;\n      }\n\n      this.callback(manager, inputEvent, inputData);\n    }\n\n    /**\n     * @private\n     * remove the event listeners\n     */\n\n  }, {\n    key: 'destroy',\n    value: function destroy() {\n      this.touch.destroy();\n      this.mouse.destroy();\n    }\n  }]);\n  return TouchMouseInput;\n}(Input);\n\nfunction recordTouches(eventType, eventData) {\n  if (eventType & INPUT_START) {\n    this.primaryTouch = eventData.changedPointers[0].identifier;\n    setLastTouch.call(this, eventData);\n  } else if (eventType & (INPUT_END | INPUT_CANCEL)) {\n    setLastTouch.call(this, eventData);\n  }\n}\n\nfunction setLastTouch(eventData) {\n  var _this2 = this;\n\n  var _eventData$changedPoi = slicedToArray(eventData.changedPointers, 1);\n\n  var touch = _eventData$changedPoi[0];\n\n  if (touch.identifier === this.primaryTouch) {\n    (function () {\n      var lastTouch = { x: touch.clientX, y: touch.clientY };\n      _this2.lastTouches.push(lastTouch);\n      var lts = _this2.lastTouches;\n      var removeLastTouch = function removeLastTouch() {\n        var i = lts.indexOf(lastTouch);\n        if (i > -1) {\n          lts.splice(i, 1);\n        }\n      };\n      setTimeout(removeLastTouch, DEDUP_TIMEOUT);\n    })();\n  }\n}\n\nfunction isSyntheticEvent(eventData) {\n  var x = eventData.srcEvent.clientX;\n  var y = eventData.srcEvent.clientY;\n  for (var i = 0; i < this.lastTouches.length; i++) {\n    var t = this.lastTouches[i];\n    var dx = Math.abs(x - t.x);\n    var dy = Math.abs(y - t.y);\n    if (dx <= DEDUP_DISTANCE && dy <= DEDUP_DISTANCE) {\n      return true;\n    }\n  }\n  return false;\n}\n\n/**\n * @private\n * create new input type manager\n * called by the Manager constructor\n * @param {Hammer} manager\n * @returns {Input}\n */\nfunction createInputInstance(manager) {\n  var Type = void 0;\n  // let inputClass = manager.options.inputClass;\n  var inputClass = manager.options.inputClass;\n\n  if (inputClass) {\n    Type = inputClass;\n  } else if (SUPPORT_POINTER_EVENTS) {\n    Type = PointerEventInput;\n  } else if (SUPPORT_ONLY_TOUCH) {\n    Type = TouchInput;\n  } else if (!SUPPORT_TOUCH) {\n    Type = MouseInput;\n  } else {\n    Type = TouchMouseInput;\n  }\n  return new Type(manager, inputHandler);\n}\n\nvar STOP = 1;\nvar FORCED_STOP = 2;\n\n/**\n* @private\n * Manager\n * @param {HTMLElement} element\n * @param {Object} [options]\n * @constructor\n */\n\nvar Manager = function () {\n  function Manager(element, options) {\n    var _this = this;\n\n    classCallCheck(this, Manager);\n\n    this.options = assign$1({}, Hammer.defaults, options || {});\n\n    this.options.inputTarget = this.options.inputTarget || element;\n\n    this.handlers = {};\n    this.session = {};\n    this.recognizers = [];\n    this.oldCssProps = {};\n\n    this.element = element;\n    this.input = createInputInstance(this);\n    this.touchAction = new TouchAction(this, this.options.touchAction);\n\n    toggleCssProps(this, true);\n\n    each(this.options.recognizers, function (item) {\n      var recognizer = _this.add(new item[0](item[1]));\n      item[2] && recognizer.recognizeWith(item[2]);\n      item[3] && recognizer.requireFailure(item[3]);\n    }, this);\n  }\n\n  /**\n   * @private\n   * set options\n   * @param {Object} options\n   * @returns {Manager}\n   */\n\n\n  createClass(Manager, [{\n    key: 'set',\n    value: function set(options) {\n      assign$1(this.options, options);\n\n      // Options that need a little more setup\n      if (options.touchAction) {\n        this.touchAction.update();\n      }\n      if (options.inputTarget) {\n        // Clean up existing event listeners and reinitialize\n        this.input.destroy();\n        this.input.target = options.inputTarget;\n        this.input.init();\n      }\n      return this;\n    }\n\n    /**\n     * @private\n     * stop recognizing for this session.\n     * This session will be discarded, when a new [input]start event is fired.\n     * When forced, the recognizer cycle is stopped immediately.\n     * @param {Boolean} [force]\n     */\n\n  }, {\n    key: 'stop',\n    value: function stop(force) {\n      this.session.stopped = force ? FORCED_STOP : STOP;\n    }\n\n    /**\n     * @private\n     * run the recognizers!\n     * called by the inputHandler function on every movement of the pointers (touches)\n     * it walks through all the recognizers and tries to detect the gesture that is being made\n     * @param {Object} inputData\n     */\n\n  }, {\n    key: 'recognize',\n    value: function recognize(inputData) {\n      var session = this.session;\n\n      if (session.stopped) {\n        return;\n      }\n\n      // run the touch-action polyfill\n      this.touchAction.preventDefaults(inputData);\n\n      var recognizer = void 0;\n      var recognizers = this.recognizers;\n\n      // this holds the recognizer that is being recognized.\n      // so the recognizer's state needs to be BEGAN, CHANGED, ENDED or RECOGNIZED\n      // if no recognizer is detecting a thing, it is set to `null`\n\n      var curRecognizer = session.curRecognizer;\n\n      // reset when the last recognizer is recognized\n      // or when we're in a new session\n\n      if (!curRecognizer || curRecognizer && curRecognizer.state & STATE_RECOGNIZED) {\n        curRecognizer = session.curRecognizer = null;\n      }\n\n      var i = 0;\n      while (i < recognizers.length) {\n        recognizer = recognizers[i];\n\n        // find out if we are allowed try to recognize the input for this one.\n        // 1.   allow if the session is NOT forced stopped (see the .stop() method)\n        // 2.   allow if we still haven't recognized a gesture in this session, or the this recognizer is the one\n        //      that is being recognized.\n        // 3.   allow if the recognizer is allowed to run simultaneous with the current recognized recognizer.\n        //      this can be setup with the `recognizeWith()` method on the recognizer.\n        if (session.stopped !== FORCED_STOP && ( // 1\n        !curRecognizer || recognizer === curRecognizer || // 2\n        recognizer.canRecognizeWith(curRecognizer))) {\n          // 3\n          recognizer.recognize(inputData);\n        } else {\n          recognizer.reset();\n        }\n\n        // if the recognizer has been recognizing the input as a valid gesture, we want to store this one as the\n        // current active recognizer. but only if we don't already have an active recognizer\n        if (!curRecognizer && recognizer.state & (STATE_BEGAN | STATE_CHANGED | STATE_ENDED)) {\n          curRecognizer = session.curRecognizer = recognizer;\n        }\n        i++;\n      }\n    }\n\n    /**\n     * @private\n     * get a recognizer by its event name.\n     * @param {Recognizer|String} recognizer\n     * @returns {Recognizer|Null}\n     */\n\n  }, {\n    key: 'get',\n    value: function get(recognizer) {\n      if (recognizer instanceof Recognizer) {\n        return recognizer;\n      }\n\n      var recognizers = this.recognizers;\n\n      for (var i = 0; i < recognizers.length; i++) {\n        if (recognizers[i].options.event === recognizer) {\n          return recognizers[i];\n        }\n      }\n      return null;\n    }\n\n    /**\n     * @private add a recognizer to the manager\n     * existing recognizers with the same event name will be removed\n     * @param {Recognizer} recognizer\n     * @returns {Recognizer|Manager}\n     */\n\n  }, {\n    key: 'add',\n    value: function add(recognizer) {\n      if (invokeArrayArg(recognizer, 'add', this)) {\n        return this;\n      }\n\n      // remove existing\n      var existing = this.get(recognizer.options.event);\n      if (existing) {\n        this.remove(existing);\n      }\n\n      this.recognizers.push(recognizer);\n      recognizer.manager = this;\n\n      this.touchAction.update();\n      return recognizer;\n    }\n\n    /**\n     * @private\n     * remove a recognizer by name or instance\n     * @param {Recognizer|String} recognizer\n     * @returns {Manager}\n     */\n\n  }, {\n    key: 'remove',\n    value: function remove(recognizer) {\n      if (invokeArrayArg(recognizer, 'remove', this)) {\n        return this;\n      }\n\n      recognizer = this.get(recognizer);\n\n      // let's make sure this recognizer exists\n      if (recognizer) {\n        var recognizers = this.recognizers;\n\n        var index = inArray(recognizers, recognizer);\n\n        if (index !== -1) {\n          recognizers.splice(index, 1);\n          this.touchAction.update();\n        }\n      }\n\n      return this;\n    }\n\n    /**\n     * @private\n     * bind event\n     * @param {String} events\n     * @param {Function} handler\n     * @returns {EventEmitter} this\n     */\n\n  }, {\n    key: 'on',\n    value: function on(events, handler) {\n      if (events === undefined) {\n        return;\n      }\n      if (handler === undefined) {\n        return;\n      }\n\n      var handlers = this.handlers;\n\n      each(splitStr(events), function (event) {\n        handlers[event] = handlers[event] || [];\n        handlers[event].push(handler);\n      });\n      return this;\n    }\n\n    /**\n     * @private unbind event, leave emit blank to remove all handlers\n     * @param {String} events\n     * @param {Function} [handler]\n     * @returns {EventEmitter} this\n     */\n\n  }, {\n    key: 'off',\n    value: function off(events, handler) {\n      if (events === undefined) {\n        return;\n      }\n\n      var handlers = this.handlers;\n\n      each(splitStr(events), function (event) {\n        if (!handler) {\n          delete handlers[event];\n        } else {\n          handlers[event] && handlers[event].splice(inArray(handlers[event], handler), 1);\n        }\n      });\n      return this;\n    }\n\n    /**\n     * @private emit event to the listeners\n     * @param {String} event\n     * @param {Object} data\n     */\n\n  }, {\n    key: 'emit',\n    value: function emit(event, data) {\n      // we also want to trigger dom events\n      if (this.options.domEvents) {\n        triggerDomEvent(event, data);\n      }\n\n      // no handlers, so skip it all\n      var handlers = this.handlers[event] && this.handlers[event].slice();\n      if (!handlers || !handlers.length) {\n        return;\n      }\n\n      data.type = event;\n      data.preventDefault = function () {\n        data.srcEvent.preventDefault();\n      };\n\n      var i = 0;\n      while (i < handlers.length) {\n        handlers[i](data);\n        i++;\n      }\n    }\n\n    /**\n     * @private\n     * destroy the manager and unbinds all events\n     * it doesn't unbind dom events, that is the user own responsibility\n     */\n\n  }, {\n    key: 'destroy',\n    value: function destroy() {\n      this.element && toggleCssProps(this, false);\n\n      this.handlers = {};\n      this.session = {};\n      this.input.destroy();\n      this.element = null;\n    }\n  }]);\n  return Manager;\n}();\n\nfunction toggleCssProps(manager, add) {\n  var element = manager.element;\n\n  if (!element.style) {\n    return;\n  }\n  var prop = void 0;\n  each(manager.options.cssProps, function (value, name) {\n    prop = prefixed(element.style, name);\n    if (add) {\n      manager.oldCssProps[prop] = element.style[prop];\n      element.style[prop] = value;\n    } else {\n      element.style[prop] = manager.oldCssProps[prop] || '';\n    }\n  });\n  if (!add) {\n    manager.oldCssProps = {};\n  }\n}\n\n/**\n * @private\n * trigger dom event\n * @param {String} event\n * @param {Object} data\n */\nfunction triggerDomEvent(event, data) {\n  var gestureEvent = document.createEvent('Event');\n  gestureEvent.initEvent(event, true, true);\n  gestureEvent.gesture = data;\n  data.target.dispatchEvent(gestureEvent);\n}\n\n/**\n * @private\n * Simple way to create a manager with a default set of recognizers.\n * @param {HTMLElement} element\n * @param {Object} [options]\n * @constructor\n */\n\nvar Hammer = function Hammer(element, options) {\n  classCallCheck(this, Hammer);\n\n  options = options || {};\n  options.recognizers = ifUndefined(options.recognizers, Hammer.defaults.preset);\n  return new Manager(element, options);\n};\n\nHammer.VERSION = '2.0.8';\n\n/**\n * @private\n * default settings\n * @namespace\n */\nHammer.defaults = {\n  /**\n   * @private\n   * set if DOM events are being triggered.\n   * But this is slower and unused by simple implementations, so disabled by default.\n   * @type {Boolean}\n   * @default false\n   */\n  domEvents: false,\n\n  /**\n   * @private\n   * The value for the touchAction property/fallback.\n   * When set to `compute` it will magically set the correct value based on the added recognizers.\n   * @type {String}\n   * @default compute\n   */\n  touchAction: TOUCH_ACTION_COMPUTE,\n\n  /**\n   * @private\n   * @type {Boolean}\n   * @default true\n   */\n  enable: true,\n\n  /**\n   * @private\n   * EXPERIMENTAL FEATURE -- can be removed/changed\n   * Change the parent input target element.\n   * If Null, then it is being set the to main element.\n   * @type {Null|EventTarget}\n   * @default null\n   */\n  inputTarget: null,\n\n  /**\n   * @private\n   * force an input class\n   * @type {Null|Function}\n   * @default null\n   */\n  inputClass: null,\n\n  /**\n   * @private\n   * Default recognizer setup when calling `Hammer()`\n   * When creating a new Manager these will be skipped.\n   * @type {Array}\n   */\n  preset: [\n  // RecognizerClass, options, [recognizeWith, ...], [requireFailure, ...]\n  [RotateRecognizer, { enable: false }], [PinchRecognizer, { enable: false }, ['rotate']], [SwipeRecognizer, { direction: DIRECTION_HORIZONTAL }], [PanRecognizer, { direction: DIRECTION_HORIZONTAL }, ['swipe']], [TapRecognizer], [TapRecognizer, { event: 'doubletap', taps: 2 }, ['tap']], [PressRecognizer]],\n\n  /**\n   * @private\n   * Some CSS properties can be used to improve the working of Hammer.\n   * Add them to this method and they will be set when creating a new Manager.\n   * @namespace\n   */\n  cssProps: {\n    /**\n     * @private\n     * Disables text selection to improve the dragging gesture. Mainly for desktop browsers.\n     * @type {String}\n     * @default 'none'\n     */\n    userSelect: 'none',\n\n    /**\n     * @private\n     * Disable the Windows Phone grippers when pressing an element.\n     * @type {String}\n     * @default 'none'\n     */\n    touchSelect: 'none',\n\n    /**\n     * @private\n     * Disables the default callout shown when you touch and hold a touch target.\n     * On iOS, when you touch and hold a touch target such as a link, Safari displays\n     * a callout containing information about the link. This property allows you to disable that callout.\n     * @type {String}\n     * @default 'none'\n     */\n    touchCallout: 'none',\n\n    /**\n     * @private\n     * Specifies whether zooming is enabled. Used by IE10>\n     * @type {String}\n     * @default 'none'\n     */\n    contentZooming: 'none',\n\n    /**\n     * @private\n     * Specifies that an entire element should be draggable instead of its contents. Mainly for desktop browsers.\n     * @type {String}\n     * @default 'none'\n     */\n    userDrag: 'none',\n\n    /**\n     * @private\n     * Overrides the highlight color shown when the user taps a link or a JavaScript\n     * clickable element in iOS. This property obeys the alpha value, if specified.\n     * @type {String}\n     * @default 'rgba(0,0,0,0)'\n     */\n    tapHighlightColor: 'rgba(0,0,0,0)'\n  }\n};\n\nvar SINGLE_TOUCH_INPUT_MAP = {\n  touchstart: INPUT_START,\n  touchmove: INPUT_MOVE,\n  touchend: INPUT_END,\n  touchcancel: INPUT_CANCEL\n};\n\nvar SINGLE_TOUCH_TARGET_EVENTS = 'touchstart';\nvar SINGLE_TOUCH_WINDOW_EVENTS = 'touchstart touchmove touchend touchcancel';\n\n/**\n * @private\n * Touch events input\n * @constructor\n * @extends Input\n */\n\nvar SingleTouchInput = function (_Input) {\n  inherits(SingleTouchInput, _Input);\n\n  function SingleTouchInput() {\n    classCallCheck(this, SingleTouchInput);\n\n    var _this = possibleConstructorReturn(this, (SingleTouchInput.__proto__ || Object.getPrototypeOf(SingleTouchInput)).apply(this, arguments));\n\n    _this.evTarget = SINGLE_TOUCH_TARGET_EVENTS;\n    _this.evWin = SINGLE_TOUCH_WINDOW_EVENTS;\n    _this.started = false;\n\n    Input.apply(_this, arguments);\n    return _this;\n  }\n\n  createClass(SingleTouchInput, [{\n    key: 'handler',\n    value: function handler(ev) {\n      var type = SINGLE_TOUCH_INPUT_MAP[ev.type];\n\n      // should we handle the touch events?\n      if (type === INPUT_START) {\n        this.started = true;\n      }\n\n      if (!this.started) {\n        return;\n      }\n\n      var touches = normalizeSingleTouches.call(this, ev, type);\n\n      // when done, reset the started state\n      if (type & (INPUT_END | INPUT_CANCEL) && touches[0].length - touches[1].length === 0) {\n        this.started = false;\n      }\n\n      this.callback(this.manager, type, {\n        pointers: touches[0],\n        changedPointers: touches[1],\n        pointerType: INPUT_TYPE_TOUCH,\n        srcEvent: ev\n      });\n    }\n  }]);\n  return SingleTouchInput;\n}(Input);\n\nfunction normalizeSingleTouches(ev, type) {\n  var all = toArray$1(ev.touches);\n  var changed = toArray$1(ev.changedTouches);\n\n  if (type & (INPUT_END | INPUT_CANCEL)) {\n    all = uniqueArray(all.concat(changed), 'identifier', true);\n  }\n\n  return [all, changed];\n}\n\n/**\n * @private\n * wrap a method with a deprecation warning and stack trace\n * @param {Function} method\n * @param {String} name\n * @param {String} message\n * @returns {Function} A new function wrapping the supplied method.\n */\nfunction deprecate(method, name, message) {\n  var deprecationMessage = 'DEPRECATED METHOD: ' + name + '\\n' + message + ' AT \\n';\n  return function () {\n    var e = new Error('get-stack-trace');\n    var stack = e && e.stack ? e.stack.replace(/^[^\\(]+?[\\n$]/gm, '').replace(/^\\s+at\\s+/gm, '').replace(/^Object.<anonymous>\\s*\\(/gm, '{anonymous}()@') : 'Unknown Stack Trace';\n\n    var log = window.console && (window.console.warn || window.console.log);\n    if (log) {\n      log.call(window.console, deprecationMessage, stack);\n    }\n    return method.apply(this, arguments);\n  };\n}\n\n/**\n * @private\n * extend object.\n * means that properties in dest will be overwritten by the ones in src.\n * @param {Object} dest\n * @param {Object} src\n * @param {Boolean} [merge=false]\n * @returns {Object} dest\n */\nvar extend = deprecate(function (dest, src, merge) {\n  var keys = Object.keys(src);\n  var i = 0;\n  while (i < keys.length) {\n    if (!merge || merge && dest[keys[i]] === undefined) {\n      dest[keys[i]] = src[keys[i]];\n    }\n    i++;\n  }\n  return dest;\n}, 'extend', 'Use `assign`.');\n\n/**\n * @private\n * merge the values from src in the dest.\n * means that properties that exist in dest will not be overwritten by src\n * @param {Object} dest\n * @param {Object} src\n * @returns {Object} dest\n */\nvar merge = deprecate(function (dest, src) {\n  return extend(dest, src, true);\n}, 'merge', 'Use `assign`.');\n\n/**\n * @private\n * simple class inheritance\n * @param {Function} child\n * @param {Function} base\n * @param {Object} [properties]\n */\nfunction inherit(child, base, properties) {\n  var baseP = base.prototype;\n  var childP = void 0;\n\n  childP = child.prototype = Object.create(baseP);\n  childP.constructor = child;\n  childP._super = baseP;\n\n  if (properties) {\n    assign$1(childP, properties);\n  }\n}\n\n// this prevents errors when Hammer is loaded in the presence of an AMD\n//  style loader but by script tag, not by the loader.\n\nassign$1(Hammer, {\n  INPUT_START: INPUT_START,\n  INPUT_MOVE: INPUT_MOVE,\n  INPUT_END: INPUT_END,\n  INPUT_CANCEL: INPUT_CANCEL,\n\n  STATE_POSSIBLE: STATE_POSSIBLE,\n  STATE_BEGAN: STATE_BEGAN,\n  STATE_CHANGED: STATE_CHANGED,\n  STATE_ENDED: STATE_ENDED,\n  STATE_RECOGNIZED: STATE_RECOGNIZED,\n  STATE_CANCELLED: STATE_CANCELLED,\n  STATE_FAILED: STATE_FAILED,\n\n  DIRECTION_NONE: DIRECTION_NONE,\n  DIRECTION_LEFT: DIRECTION_LEFT,\n  DIRECTION_RIGHT: DIRECTION_RIGHT,\n  DIRECTION_UP: DIRECTION_UP,\n  DIRECTION_DOWN: DIRECTION_DOWN,\n  DIRECTION_HORIZONTAL: DIRECTION_HORIZONTAL,\n  DIRECTION_VERTICAL: DIRECTION_VERTICAL,\n  DIRECTION_ALL: DIRECTION_ALL,\n\n  Manager: Manager,\n  Input: Input,\n  TouchAction: TouchAction,\n\n  TouchInput: TouchInput,\n  MouseInput: MouseInput,\n  PointerEventInput: PointerEventInput,\n  TouchMouseInput: TouchMouseInput,\n  SingleTouchInput: SingleTouchInput,\n\n  Recognizer: Recognizer,\n  AttrRecognizer: AttrRecognizer,\n  Tap: TapRecognizer,\n  Pan: PanRecognizer,\n  Swipe: SwipeRecognizer,\n  Pinch: PinchRecognizer,\n  Rotate: RotateRecognizer,\n  Press: PressRecognizer,\n\n  on: addEventListeners,\n  off: removeEventListeners,\n  each: each,\n  merge: merge,\n  extend: extend,\n  assign: assign$1,\n  inherit: inherit,\n  bindFn: bindFn,\n  prefixed: prefixed,\n  toArray: toArray$1,\n  inArray: inArray,\n  uniqueArray: uniqueArray,\n  splitStr: splitStr,\n  boolOrFn: boolOrFn,\n  hasParent: hasParent,\n  addEventListeners: addEventListeners,\n  removeEventListeners: removeEventListeners\n});\n\n/* jshint ignore:start */\nif (typeof define === 'function' && define.amd) {\n  define(function () {\n    return Hammer;\n  });\n} else if (typeof module !== 'undefined' && module.exports) {\n  module.exports = Hammer;\n} else {\n  window[exportName] = Hammer;\n}\n/* jshint ignore:end */\n})(window, document, 'Hammer');\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"hammerjs\",\n  \"title\": \"Hammer.JS\",\n  \"description\": \"A javascript library for multi-touch gestures\",\n  \"version\": \"2.0.8\",\n  \"homepage\": \"http://hammerjs.github.io/\",\n  \"license\": \"MIT\",\n  \"keywords\": [\n    \"touch\",\n    \"gestures\"\n  ],\n  \"author\": {\n    \"name\": \"Jorik Tangelder\",\n    \"email\": \"j.tangelder@gmail.com\"\n  },\n  \"contributors\": [\n    {\n      \"name\": \"Alexander Schmitz\",\n      \"email\": \"arschmitz@gmail.com\"\n    },\n    {\n      \"name\": \"Chris Thoburn\",\n      \"email\": \"\"\n    }\n  ],\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git://github.com/hammerjs/hammer.js.git\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/hammerjs/hammer.js/issues\"\n  },\n  \"dependencies\": {},\n  \"devDependencies\": {\n    \"babel-core\": \"^6.26.3\",\n    \"babel-plugin-external-helpers\": \"^6.22.0\",\n    \"babel-preset-env\": \"^1.7.0\",\n    \"bannerize\": \"^1.0.2\",\n    \"blanket\": \"^1.2.3\",\n    \"changelogplease\": \"^1.2.0\",\n    \"ember-suave\": \"^4.0.0\",\n    \"git-tags\": \"^0.2.4\",\n    \"hammer-simulator\": \"git://github.com/hammerjs/simulator#master\",\n    \"jquery\": \"^3.1.0\",\n    \"jquery-hammerjs\": \"2.0.x\",\n    \"jscs\": \"^3.0.7\",\n    \"jshint\": \"^2.9.2\",\n    \"jshint-stylish\": \"^2.2.0\",\n    \"lodash-compat\": \"^3.10.2\",\n    \"node-qunit-phantomjs\": \"^1.4.0\",\n    \"qunitjs\": \"^2.0.0\",\n    \"rollup\": \"^0.59.4\",\n    \"rollup-plugin-babel\": \"^3.0.4\",\n    \"run-when-changed\": \"^2.1.0\",\n    \"serve\": \"^1.4.0\",\n    \"uglify-js\": \"^3.4.0\"\n  },\n  \"main\": \"hammer.js\",\n  \"engines\": {\n    \"node\": \">=0.8.0\"\n  },\n  \"scripts\": {\n    \"bannerize\": \"bannerize hammer.js hammer.min.js\",\n    \"connect\": \"serve -p 8000 ./\",\n    \"rollup\": \"rollup -c\",\n    \"uglify\": \"uglifyjs hammer.js --source-map \\\"filename=hammer.min.js.map\\\" -o hammer.min.js --timings\",\n    \"string-replace\": \"node string-replace.js\",\n    \"jshint\": \"jshint src/**/*.js tests/unit/*.js tests/unit/gestures/*.js --config .jshintrc --verbose --reporter=node_modules/jshint-stylish\",\n    \"jscs\": \" jscs src/**/*.js tests/unit/*.js tests/unit/gestures/*.js --config=./.jscsrc\",\n    \"qunit\": \"phantomjs node_modules/qunit-phantomjs-runner/runner-list.js tests/unit/index.html 15\",\n    \"watch\": \"run-when-changed --watch 'src/**/*.js' --watch 'tests/unit/*.js' --watch 'tests/unit/gestures/*.js' --exec 'npm run watch-tasks'\",\n    \"watch-tasks\": \"npm run rollup && npm run string-replace && npm run uglify && npm run jshint && npm run jscs\",\n    \"build\": \"npm run rollup && npm run string-replace && npm run uglify && npm run bannerize\",\n    \"test\": \"npm run build && npm run jshint && npm run jscs && npm run qunit\"\n  }\n}\n"
  },
  {
    "path": "rollup.config.js",
    "content": "import babel from 'rollup-plugin-babel';\n\nexport default {\n  entry: 'src/main.js',\n  format: 'es',\n  plugins: [ babel({ exclude: 'node_modules/**' }) ],\n  dest: 'hammer.js',\n  intro: \" (function(window, document, exportName, undefined) { \\n'use strict';\",\n  outro: \"})(window, document, 'Hammer');\"\n};\n"
  },
  {
    "path": "src/.babelrc",
    "content": "{\n  \"presets\": [\n    [\n      \"env\",\n      {\n        \"modules\": false\n      }\n    ]\n  ],\n  \"plugins\": [\n    \"external-helpers\"\n  ]\n}"
  },
  {
    "path": "src/hammer.js",
    "content": "import ifUndefined from './utils/if-undefined';\nimport { TOUCH_ACTION_COMPUTE } from './touchactionjs/touchaction-Consts';\nimport { DIRECTION_HORIZONTAL } from './inputjs/input-consts';\nimport RotateRecognizer from './recognizers/rotate';\nimport PinchRecognizer from './recognizers/pinch';\nimport SwipeRecognizer from './recognizers/swipe';\nimport PanRecognizer from './recognizers/pan';\nimport TapRecognizer from './recognizers/tap';\nimport PressRecognizer from './recognizers/press';\nimport  Manager  from './manager';\n\n/**\n * @private\n * Simple way to create a manager with a default set of recognizers.\n * @param {HTMLElement} element\n * @param {Object} [options]\n * @constructor\n */\nexport default class Hammer {\n  constructor(element, options) {\n    options = options || {};\n    options.recognizers = ifUndefined(options.recognizers, Hammer.defaults.preset);\n    return new Manager(element, options);\n  }\n}\n\n/**\n * @private\n * @const {string}\n */\nHammer.VERSION = '{{PKG_VERSION}}';\n\n/**\n * @private\n * default settings\n * @namespace\n */\nHammer.defaults = {\n  /**\n   * @private\n   * set if DOM events are being triggered.\n   * But this is slower and unused by simple implementations, so disabled by default.\n   * @type {Boolean}\n   * @default false\n   */\n  domEvents: false,\n\n  /**\n   * @private\n   * The value for the touchAction property/fallback.\n   * When set to `compute` it will magically set the correct value based on the added recognizers.\n   * @type {String}\n   * @default compute\n   */\n  touchAction: TOUCH_ACTION_COMPUTE,\n\n  /**\n   * @private\n   * @type {Boolean}\n   * @default true\n   */\n  enable: true,\n\n  /**\n   * @private\n   * EXPERIMENTAL FEATURE -- can be removed/changed\n   * Change the parent input target element.\n   * If Null, then it is being set the to main element.\n   * @type {Null|EventTarget}\n   * @default null\n   */\n  inputTarget: null,\n\n  /**\n   * @private\n   * force an input class\n   * @type {Null|Function}\n   * @default null\n   */\n  inputClass: null,\n\n  /**\n   * @private\n   * Default recognizer setup when calling `Hammer()`\n   * When creating a new Manager these will be skipped.\n   * @type {Array}\n   */\n  preset: [\n      // RecognizerClass, options, [recognizeWith, ...], [requireFailure, ...]\n      [RotateRecognizer, { enable: false }],\n      [PinchRecognizer, { enable: false }, ['rotate']],\n      [SwipeRecognizer, { direction: DIRECTION_HORIZONTAL }],\n      [PanRecognizer, { direction: DIRECTION_HORIZONTAL }, ['swipe']],\n      [TapRecognizer],\n      [TapRecognizer, { event: 'doubletap', taps: 2 }, ['tap']],\n      [PressRecognizer]\n  ],\n\n  /**\n   * @private\n   * Some CSS properties can be used to improve the working of Hammer.\n   * Add them to this method and they will be set when creating a new Manager.\n   * @namespace\n   */\n  cssProps: {\n    /**\n     * @private\n     * Disables text selection to improve the dragging gesture. Mainly for desktop browsers.\n     * @type {String}\n     * @default 'none'\n     */\n    userSelect: 'none',\n\n    /**\n     * @private\n     * Disable the Windows Phone grippers when pressing an element.\n     * @type {String}\n     * @default 'none'\n     */\n    touchSelect: 'none',\n\n    /**\n     * @private\n     * Disables the default callout shown when you touch and hold a touch target.\n     * On iOS, when you touch and hold a touch target such as a link, Safari displays\n     * a callout containing information about the link. This property allows you to disable that callout.\n     * @type {String}\n     * @default 'none'\n     */\n    touchCallout: 'none',\n\n    /**\n     * @private\n     * Specifies whether zooming is enabled. Used by IE10>\n     * @type {String}\n     * @default 'none'\n     */\n    contentZooming: 'none',\n\n    /**\n     * @private\n     * Specifies that an entire element should be draggable instead of its contents. Mainly for desktop browsers.\n     * @type {String}\n     * @default 'none'\n     */\n    userDrag: 'none',\n\n    /**\n     * @private\n     * Overrides the highlight color shown when the user taps a link or a JavaScript\n     * clickable element in iOS. This property obeys the alpha value, if specified.\n     * @type {String}\n     * @default 'rgba(0,0,0,0)'\n     */\n    tapHighlightColor: 'rgba(0,0,0,0)'\n  }\n};\n"
  },
  {
    "path": "src/input/mouse.js",
    "content": "import {\n    INPUT_START,\n    INPUT_MOVE,\n    INPUT_END,\n    INPUT_TYPE_MOUSE\n} from '../inputjs/input-consts';\nimport Input from '../inputjs/input-constructor';\n\nconst MOUSE_INPUT_MAP = {\n  mousedown: INPUT_START,\n  mousemove: INPUT_MOVE,\n  mouseup: INPUT_END\n};\n\nconst MOUSE_ELEMENT_EVENTS = 'mousedown';\nconst MOUSE_WINDOW_EVENTS = 'mousemove mouseup';\n\n/**\n * @private\n * Mouse events input\n * @constructor\n * @extends Input\n */\nexport default class MouseInput extends Input {\n  constructor() {\n    super(...arguments);\n\n    this.evEl = MOUSE_ELEMENT_EVENTS;\n    this.evWin = MOUSE_WINDOW_EVENTS;\n\n    this.pressed = false; // mousedown state\n  }\n\n  /**\n   * @private\n   * handle mouse events\n   * @param {Object} ev\n   */\n  handler(ev) {\n    let eventType = MOUSE_INPUT_MAP[ev.type];\n\n    // on start we want to have the left mouse button down\n    if (eventType & INPUT_START && ev.button === 0) {\n      this.pressed = true;\n    }\n\n    if (eventType & INPUT_MOVE && ev.which !== 1) {\n      eventType = INPUT_END;\n    }\n\n    // mouse must be down\n    if (!this.pressed) {\n      return;\n    }\n\n    if (eventType & INPUT_END) {\n      this.pressed = false;\n    }\n\n    this.callback(this.manager, eventType, {\n      pointers: [ev],\n      changedPointers: [ev],\n      pointerType: INPUT_TYPE_MOUSE,\n      srcEvent: ev\n    });\n  }\n}\n"
  },
  {
    "path": "src/input/pointerevent.js",
    "content": "import {\n    INPUT_START,\n    INPUT_END,\n    INPUT_CANCEL,\n    INPUT_MOVE,\n    INPUT_TYPE_TOUCH,\n    INPUT_TYPE_MOUSE,\n    INPUT_TYPE_PEN,\n    INPUT_TYPE_KINECT\n} from '../inputjs/input-consts';\nimport Input from '../inputjs/input-constructor';\nimport inArray from '../utils/in-array';\n\nconst POINTER_INPUT_MAP = {\n  pointerdown: INPUT_START,\n  pointermove: INPUT_MOVE,\n  pointerup: INPUT_END,\n  pointercancel: INPUT_CANCEL,\n  pointerout: INPUT_CANCEL\n};\n\n// in IE10 the pointer types is defined as an enum\nconst IE10_POINTER_TYPE_ENUM = {\n  2: INPUT_TYPE_TOUCH,\n  3: INPUT_TYPE_PEN,\n  4: INPUT_TYPE_MOUSE,\n  5: INPUT_TYPE_KINECT // see https://twitter.com/jacobrossi/status/480596438489890816\n};\n\nlet POINTER_ELEMENT_EVENTS = 'pointerdown';\nlet POINTER_WINDOW_EVENTS = 'pointermove pointerup pointercancel';\n\n// IE10 has prefixed support, and case-sensitive\nif (window.MSPointerEvent && !window.PointerEvent) {\n  POINTER_ELEMENT_EVENTS = 'MSPointerDown';\n  POINTER_WINDOW_EVENTS = 'MSPointerMove MSPointerUp MSPointerCancel';\n}\n\n/**\n * @private\n * Pointer events input\n * @constructor\n * @extends Input\n */\nexport default class PointerEventInput extends Input {\n  constructor() {\n    super(...arguments);\n    this.evEl = POINTER_ELEMENT_EVENTS;\n    this.evWin = POINTER_WINDOW_EVENTS;\n\n    this.store = (this.manager.session.pointerEvents = []);\n  }\n\n  /**\n   * @private\n   * handle mouse events\n   * @param {Object} ev\n   */\n  handler(ev) {\n    let { store } = this;\n    let removePointer = false;\n\n    let eventTypeNormalized = ev.type.toLowerCase().replace('ms', '');\n    let eventType = POINTER_INPUT_MAP[eventTypeNormalized];\n    let pointerType = IE10_POINTER_TYPE_ENUM[ev.pointerType] || ev.pointerType;\n\n    let isTouch = (pointerType === INPUT_TYPE_TOUCH);\n\n    // get index of the event in the store\n    let storeIndex = inArray(store, ev.pointerId, 'pointerId');\n\n    // start and mouse must be down\n    if (eventType & INPUT_START && (ev.button === 0 || isTouch)) {\n      if (storeIndex < 0) {\n        store.push(ev);\n        storeIndex = store.length - 1;\n      }\n    } else if (eventType & (INPUT_END | INPUT_CANCEL)) {\n      removePointer = true;\n    }\n\n    // it not found, so the pointer hasn't been down (so it's probably a hover)\n    if (storeIndex < 0) {\n      return;\n    }\n\n    // update the event in the store\n    store[storeIndex] = ev;\n\n    this.callback(this.manager, eventType, {\n      pointers: store,\n      changedPointers: [ev],\n      pointerType,\n      srcEvent: ev\n    });\n\n    if (removePointer) {\n      // remove from the store\n      store.splice(storeIndex, 1);\n    }\n  }\n}\n"
  },
  {
    "path": "src/input/singletouch.js",
    "content": "import {\n    INPUT_START,\n    INPUT_MOVE,\n    INPUT_END,\n    INPUT_CANCEL,\n    INPUT_TYPE_TOUCH\n} from '../inputjs/input-consts';\nimport Input from '../inputjs/input-constructor';\nimport toArray from '../utils/to-array';\nimport uniqueArray from '../utils/unique-array';\n\nconst SINGLE_TOUCH_INPUT_MAP = {\n  touchstart: INPUT_START,\n  touchmove: INPUT_MOVE,\n  touchend: INPUT_END,\n  touchcancel: INPUT_CANCEL\n};\n\nconst SINGLE_TOUCH_TARGET_EVENTS = 'touchstart';\nconst SINGLE_TOUCH_WINDOW_EVENTS = 'touchstart touchmove touchend touchcancel';\n\n/**\n * @private\n * Touch events input\n * @constructor\n * @extends Input\n */\nexport default class SingleTouchInput extends Input {\n  constructor() {\n    super(...arguments);\n    this.evTarget = SINGLE_TOUCH_TARGET_EVENTS;\n    this.evWin = SINGLE_TOUCH_WINDOW_EVENTS;\n    this.started = false;\n\n    Input.apply(this, arguments);\n  }\n\n  handler(ev) {\n    let type = SINGLE_TOUCH_INPUT_MAP[ev.type];\n\n    // should we handle the touch events?\n    if (type === INPUT_START) {\n      this.started = true;\n    }\n\n    if (!this.started) {\n      return;\n    }\n\n    let touches = normalizeSingleTouches.call(this, ev, type);\n\n    // when done, reset the started state\n    if (type & (INPUT_END | INPUT_CANCEL) && touches[0].length - touches[1].length === 0) {\n      this.started = false;\n    }\n\n    this.callback(this.manager, type, {\n      pointers: touches[0],\n      changedPointers: touches[1],\n      pointerType: INPUT_TYPE_TOUCH,\n      srcEvent: ev\n    });\n  }\n}\n\n/**\n * @private\n * @this {TouchInput}\n * @param {Object} ev\n * @param {Number} type flag\n * @returns {undefined|Array} [all, changed]\n */\nfunction normalizeSingleTouches(ev, type) {\n  let all = toArray(ev.touches);\n  let changed = toArray(ev.changedTouches);\n\n  if (type & (INPUT_END | INPUT_CANCEL)) {\n    all = uniqueArray(all.concat(changed), 'identifier', true);\n  }\n\n  return [all, changed];\n}\n"
  },
  {
    "path": "src/input/touch.js",
    "content": "import {\n    INPUT_START,\n    INPUT_MOVE,\n    INPUT_END,\n    INPUT_CANCEL,\n    INPUT_TYPE_TOUCH\n} from '../inputjs/input-consts';\nimport Input from '../inputjs/input-constructor';\nimport toArray from '../utils/to-array';\nimport hasParent from '../utils/has-parent';\nimport uniqueArray from '../utils/unique-array';\n\nconst TOUCH_INPUT_MAP = {\n  touchstart: INPUT_START,\n  touchmove: INPUT_MOVE,\n  touchend: INPUT_END,\n  touchcancel: INPUT_CANCEL\n};\n\nconst TOUCH_TARGET_EVENTS = 'touchstart touchmove touchend touchcancel';\n\n/**\n * @private\n * Multi-user touch events input\n * @constructor\n * @extends Input\n */\nexport default class TouchInput extends Input {\n\n  constructor() {\n    TouchInput.prototype.evTarget = TOUCH_TARGET_EVENTS;\n    TouchInput.prototype.targetIds = {};\n    super(...arguments);\n\n    this.evTarget = TOUCH_TARGET_EVENTS;\n    this.targetIds = {};\n  }\n\n  handler(ev) {\n    let type = TOUCH_INPUT_MAP[ev.type];\n    let touches = getTouches.call(this, ev, type);\n    if (!touches) {\n      return;\n    }\n\n    this.callback(this.manager, type, {\n      pointers: touches[0],\n      changedPointers: touches[1],\n      pointerType: INPUT_TYPE_TOUCH,\n      srcEvent: ev\n    });\n  }\n}\n\n/**\n * @private\n * @this {TouchInput}\n * @param {Object} ev\n * @param {Number} type flag\n * @returns {undefined|Array} [all, changed]\n */\nfunction getTouches(ev, type) {\n  let allTouches = toArray(ev.touches);\n  let { targetIds } = this;\n\n  // when there is only one touch, the process can be simplified\n  if (type & (INPUT_START | INPUT_MOVE) && allTouches.length === 1) {\n    targetIds[allTouches[0].identifier] = true;\n    return [allTouches, allTouches];\n  }\n\n  let i;\n  let targetTouches;\n  let changedTouches = toArray(ev.changedTouches);\n  let changedTargetTouches = [];\n  let { target } = this;\n\n  // get target touches from touches\n  targetTouches = allTouches.filter((touch) => {\n    return hasParent(touch.target, target);\n  });\n\n  // collect touches\n  if (type === INPUT_START) {\n    i = 0;\n    while (i < targetTouches.length) {\n      targetIds[targetTouches[i].identifier] = true;\n      i++;\n    }\n  }\n\n  // filter changed touches to only contain touches that exist in the collected target ids\n  i = 0;\n  while (i < changedTouches.length) {\n    if (targetIds[changedTouches[i].identifier]) {\n      changedTargetTouches.push(changedTouches[i]);\n    }\n\n    // cleanup removed touches\n    if (type & (INPUT_END | INPUT_CANCEL)) {\n      delete targetIds[changedTouches[i].identifier];\n    }\n    i++;\n  }\n\n  if (!changedTargetTouches.length) {\n    return;\n  }\n\n  return [\n      // merge targetTouches with changedTargetTouches so it contains ALL touches, including 'end' and 'cancel'\n      uniqueArray(targetTouches.concat(changedTargetTouches), 'identifier', true),\n      changedTargetTouches\n  ];\n}\n"
  },
  {
    "path": "src/input/touchmouse.js",
    "content": "import Input from '../inputjs/input-constructor';\nimport bindFn from '../utils/bind-fn';\nimport  TouchInput  from './touch';\nimport  MouseInput  from './mouse';\nimport {\n    INPUT_START,\n    INPUT_END,\n    INPUT_CANCEL,\n    INPUT_TYPE_TOUCH,\n    INPUT_TYPE_MOUSE\n} from '../inputjs/input-consts';\n\n/**\n * @private\n * Combined touch and mouse input\n *\n * Touch has a higher priority then mouse, and while touching no mouse events are allowed.\n * This because touch devices also emit mouse events while doing a touch.\n *\n * @constructor\n * @extends Input\n */\n\nconst DEDUP_TIMEOUT = 2500;\nconst DEDUP_DISTANCE = 25;\n\nexport default class TouchMouseInput extends Input {\n  constructor() {\n    super(...arguments);\n\n    let handler = bindFn(this.handler, this);\n    this.touch = new TouchInput(this.manager, handler);\n    this.mouse = new MouseInput(this.manager, handler);\n\n    this.primaryTouch = null;\n    this.lastTouches = [];\n  }\n\n  /**\n   * @private\n   * handle mouse and touch events\n   * @param {Hammer} manager\n   * @param {String} inputEvent\n   * @param {Object} inputData\n   */\n  handler(manager, inputEvent, inputData) {\n    let isTouch = (inputData.pointerType === INPUT_TYPE_TOUCH);\n    let isMouse = (inputData.pointerType === INPUT_TYPE_MOUSE);\n\n    if (isMouse && inputData.sourceCapabilities && inputData.sourceCapabilities.firesTouchEvents) {\n      return;\n    }\n\n    // when we're in a touch event, record touches to  de-dupe synthetic mouse event\n    if (isTouch) {\n      recordTouches.call(this, inputEvent, inputData);\n    } else if (isMouse && isSyntheticEvent.call(this, inputData)) {\n      return;\n    }\n\n    this.callback(manager, inputEvent, inputData);\n  }\n\n  /**\n   * @private\n   * remove the event listeners\n   */\n  destroy() {\n    this.touch.destroy();\n    this.mouse.destroy();\n  }\n}\n\nfunction recordTouches(eventType, eventData) {\n  if (eventType & INPUT_START) {\n    this.primaryTouch = eventData.changedPointers[0].identifier;\n    setLastTouch.call(this, eventData);\n  } else if (eventType & (INPUT_END | INPUT_CANCEL)) {\n    setLastTouch.call(this, eventData);\n  }\n}\n\nfunction setLastTouch(eventData) {\n  let { changedPointers:[touch] } = eventData;\n  if (touch.identifier === this.primaryTouch) {\n    let lastTouch = { x: touch.clientX, y: touch.clientY };\n    this.lastTouches.push(lastTouch);\n    let lts = this.lastTouches;\n    let removeLastTouch = function() {\n      let i = lts.indexOf(lastTouch);\n      if (i > -1) {\n        lts.splice(i, 1);\n      }\n    };\n    setTimeout(removeLastTouch, DEDUP_TIMEOUT);\n  }\n}\n\nfunction isSyntheticEvent(eventData) {\n  let x = eventData.srcEvent.clientX;\n  let y = eventData.srcEvent.clientY;\n  for (let i = 0; i < this.lastTouches.length; i++) {\n    let t = this.lastTouches[i];\n    let dx = Math.abs(x - t.x);\n    let dy = Math.abs(y - t.y);\n    if (dx <= DEDUP_DISTANCE && dy <= DEDUP_DISTANCE) {\n      return true;\n    }\n  }\n  return false;\n}\n"
  },
  {
    "path": "src/inputjs/compute-delta-xy.js",
    "content": "import { INPUT_START, INPUT_END } from './input-consts';\n\nexport default function computeDeltaXY(session, input) {\n  let { center } = input;\n  // let { offsetDelta:offset = {}, prevDelta = {}, prevInput = {} } = session;\n  // jscs throwing error on defalut destructured values and without defaults tests fail\n  let offset = session.offsetDelta || {};\n  let prevDelta = session.prevDelta || {};\n  let prevInput = session.prevInput || {};\n\n  if (input.eventType === INPUT_START || prevInput.eventType === INPUT_END) {\n    prevDelta = session.prevDelta = {\n      x: prevInput.deltaX || 0,\n      y: prevInput.deltaY || 0\n    };\n\n    offset = session.offsetDelta = {\n      x: center.x,\n      y: center.y\n    };\n  }\n\n  input.deltaX = prevDelta.x + (center.x - offset.x);\n  input.deltaY = prevDelta.y + (center.y - offset.y);\n}\n"
  },
  {
    "path": "src/inputjs/compute-input-data.js",
    "content": "import { now } from '../utils/utils-consts';\nimport { abs } from '../utils/utils-consts';\nimport hasParent from '../utils/has-parent';\nimport simpleCloneInputData from './simple-clone-input-data';\nimport getCenter from './get-center';\nimport getDistance from './get-distance';\nimport getAngle from './get-angle';\nimport getDirection from './get-direction';\nimport computeDeltaXY from './compute-delta-xy';\nimport getVelocity from './get-velocity';\nimport getScale from './get-scale';\nimport getRotation from './get-rotation';\nimport computeIntervalInputData from './compute-interval-input-data';\n\n/**\n* @private\n * extend the data with some usable properties like scale, rotate, velocity etc\n * @param {Object} manager\n * @param {Object} input\n */\nexport default function computeInputData(manager, input) {\n  let { session } = manager;\n  let { pointers } = input;\n  let { length:pointersLength } = pointers;\n\n  // store the first input to calculate the distance and direction\n  if (!session.firstInput) {\n    session.firstInput = simpleCloneInputData(input);\n  }\n\n  // to compute scale and rotation we need to store the multiple touches\n  if (pointersLength > 1 && !session.firstMultiple) {\n    session.firstMultiple = simpleCloneInputData(input);\n  } else if (pointersLength === 1) {\n    session.firstMultiple = false;\n  }\n\n  let { firstInput, firstMultiple } = session;\n  let offsetCenter = firstMultiple ? firstMultiple.center : firstInput.center;\n\n  let center = input.center = getCenter(pointers);\n  input.timeStamp = now();\n  input.deltaTime = input.timeStamp - firstInput.timeStamp;\n\n  input.angle = getAngle(offsetCenter, center);\n  input.distance = getDistance(offsetCenter, center);\n\n  computeDeltaXY(session, input);\n  input.offsetDirection = getDirection(input.deltaX, input.deltaY);\n\n  let overallVelocity = getVelocity(input.deltaTime, input.deltaX, input.deltaY);\n  input.overallVelocityX = overallVelocity.x;\n  input.overallVelocityY = overallVelocity.y;\n  input.overallVelocity = (abs(overallVelocity.x) > abs(overallVelocity.y)) ? overallVelocity.x : overallVelocity.y;\n\n  input.scale = firstMultiple ? getScale(firstMultiple.pointers, pointers) : 1;\n  input.rotation = firstMultiple ? getRotation(firstMultiple.pointers, pointers) : 0;\n\n  input.maxPointers = !session.prevInput ? input.pointers.length : ((input.pointers.length >\n  session.prevInput.maxPointers) ? input.pointers.length : session.prevInput.maxPointers);\n\n  computeIntervalInputData(session, input);\n\n  // find the correct target\n  let target = manager.element;\n  if (hasParent(input.srcEvent.target, target)) {\n    target = input.srcEvent.target;\n  }\n  input.target = target;\n}\n"
  },
  {
    "path": "src/inputjs/compute-interval-input-data.js",
    "content": "import { INPUT_CANCEL,COMPUTE_INTERVAL } from './input-consts';\nimport { abs } from '../utils/utils-consts';\nimport getVelocity from './get-velocity';\nimport getDirection from './get-direction';\n\n/**\n * @private\n * velocity is calculated every x ms\n * @param {Object} session\n * @param {Object} input\n */\nexport default function computeIntervalInputData(session, input) {\n  let last = session.lastInterval || input;\n  let deltaTime = input.timeStamp - last.timeStamp;\n  let velocity;\n  let velocityX;\n  let velocityY;\n  let direction;\n\n  if (input.eventType !== INPUT_CANCEL && (deltaTime > COMPUTE_INTERVAL || last.velocity === undefined)) {\n    let deltaX = input.deltaX - last.deltaX;\n    let deltaY = input.deltaY - last.deltaY;\n\n    let v = getVelocity(deltaTime, deltaX, deltaY);\n    velocityX = v.x;\n    velocityY = v.y;\n    velocity = (abs(v.x) > abs(v.y)) ? v.x : v.y;\n    direction = getDirection(deltaX, deltaY);\n\n    session.lastInterval = input;\n  } else {\n    // use latest velocity info if it doesn't overtake a minimum period\n    velocity = last.velocity;\n    velocityX = last.velocityX;\n    velocityY = last.velocityY;\n    direction = last.direction;\n  }\n\n  input.velocity = velocity;\n  input.velocityX = velocityX;\n  input.velocityY = velocityY;\n  input.direction = direction;\n}\n"
  },
  {
    "path": "src/inputjs/create-input-instance.js",
    "content": "import { SUPPORT_POINTER_EVENTS,SUPPORT_ONLY_TOUCH,SUPPORT_TOUCH } from './input-consts';\nimport inputHandler from './input-handler';\nimport PointerEventInput from '../input/pointerevent';\nimport TouchInput from '../input/touch';\nimport MouseInput from '../input/mouse';\nimport TouchMouseInput from '../input/touchmouse';\n\n/**\n * @private\n * create new input type manager\n * called by the Manager constructor\n * @param {Hammer} manager\n * @returns {Input}\n */\nexport default function createInputInstance(manager) {\n  let Type;\n  // let inputClass = manager.options.inputClass;\n  let { options:{ inputClass } } = manager;\n  if (inputClass) {\n    Type = inputClass;\n  } else if (SUPPORT_POINTER_EVENTS) {\n    Type = PointerEventInput;\n  } else if (SUPPORT_ONLY_TOUCH) {\n    Type = TouchInput;\n  } else if (!SUPPORT_TOUCH) {\n    Type = MouseInput;\n  } else {\n    Type = TouchMouseInput;\n  }\n  return new (Type)(manager, inputHandler);\n}\n"
  },
  {
    "path": "src/inputjs/get-angle.js",
    "content": "import { PROPS_XY } from './input-consts';\n\n/**\n * @private\n * calculate the angle between two coordinates\n * @param {Object} p1\n * @param {Object} p2\n * @param {Array} [props] containing x and y keys\n * @return {Number} angle\n */\nexport default function getAngle(p1, p2, props) {\n  if (!props) {\n    props = PROPS_XY;\n  }\n  let x = p2[props[0]] - p1[props[0]];\n  let y = p2[props[1]] - p1[props[1]];\n  return Math.atan2(y, x) * 180 / Math.PI;\n}\n"
  },
  {
    "path": "src/inputjs/get-center.js",
    "content": "import { round } from '../utils/utils-consts';\n\n/**\n * @private\n * get the center of all the pointers\n * @param {Array} pointers\n * @return {Object} center contains `x` and `y` properties\n */\nexport default function getCenter(pointers) {\n  let pointersLength = pointers.length;\n\n  // no need to loop when only one touch\n  if (pointersLength === 1) {\n    return {\n      x: round(pointers[0].clientX),\n      y: round(pointers[0].clientY)\n    };\n  }\n\n  let x = 0;\n  let y = 0;\n  let i = 0;\n  while (i < pointersLength) {\n    x += pointers[i].clientX;\n    y += pointers[i].clientY;\n    i++;\n  }\n\n  return {\n    x: round(x / pointersLength),\n    y: round(y / pointersLength)\n  };\n}\n"
  },
  {
    "path": "src/inputjs/get-direction.js",
    "content": "import { abs } from '../utils/utils-consts';\nimport { DIRECTION_NONE,DIRECTION_LEFT,DIRECTION_RIGHT,DIRECTION_UP,DIRECTION_DOWN } from './input-consts';\n\n/**\n * @private\n * get the direction between two points\n * @param {Number} x\n * @param {Number} y\n * @return {Number} direction\n */\nexport default function getDirection(x, y) {\n  if (x === y) {\n    return DIRECTION_NONE;\n  }\n\n  if (abs(x) >= abs(y)) {\n    return x < 0 ? DIRECTION_LEFT : DIRECTION_RIGHT;\n  }\n  return y < 0 ? DIRECTION_UP : DIRECTION_DOWN;\n}\n"
  },
  {
    "path": "src/inputjs/get-distance.js",
    "content": "import { PROPS_XY } from './input-consts';\n\n/**\n * @private\n * calculate the absolute distance between two points\n * @param {Object} p1 {x, y}\n * @param {Object} p2 {x, y}\n * @param {Array} [props] containing x and y keys\n * @return {Number} distance\n */\nexport default function getDistance(p1, p2, props) {\n  if (!props) {\n    props = PROPS_XY;\n  }\n  let x = p2[props[0]] - p1[props[0]];\n  let y = p2[props[1]] - p1[props[1]];\n\n  return Math.sqrt((x * x) + (y * y));\n}\n"
  },
  {
    "path": "src/inputjs/get-rotation.js",
    "content": "import getAngle from './get-angle';\nimport { PROPS_CLIENT_XY } from './input-consts';\n\n/**\n * @private\n * calculate the rotation degrees between two pointersets\n * @param {Array} start array of pointers\n * @param {Array} end array of pointers\n * @return {Number} rotation\n */\nexport default function getRotation(start, end) {\n  return getAngle(end[1], end[0], PROPS_CLIENT_XY) + getAngle(start[1], start[0], PROPS_CLIENT_XY);\n}\n"
  },
  {
    "path": "src/inputjs/get-scale.js",
    "content": "import { PROPS_CLIENT_XY } from './input-consts';\nimport getDistance from './get-distance';\n/**\n * @private\n * calculate the scale factor between two pointersets\n * no scale is 1, and goes down to 0 when pinched together, and bigger when pinched out\n * @param {Array} start array of pointers\n * @param {Array} end array of pointers\n * @return {Number} scale\n */\nexport default function getScale(start, end) {\n  return getDistance(end[0], end[1], PROPS_CLIENT_XY) / getDistance(start[0], start[1], PROPS_CLIENT_XY);\n}\n"
  },
  {
    "path": "src/inputjs/get-velocity.js",
    "content": "/**\n * @private\n * calculate the velocity between two points. unit is in px per ms.\n * @param {Number} deltaTime\n * @param {Number} x\n * @param {Number} y\n * @return {Object} velocity `x` and `y`\n */\nexport default function getVelocity(deltaTime, x, y) {\n  return {\n    x: x / deltaTime || 0,\n    y: y / deltaTime || 0\n  };\n}\n"
  },
  {
    "path": "src/inputjs/input-constructor.js",
    "content": "import boolOrFn from '../utils/bool-or-fn';\nimport addEventListeners from '../utils/add-event-listeners';\nimport removeEventListeners from '../utils/remove-event-listeners';\nimport getWindowForElement from '../utils/get-window-for-element';\n\n/**\n * @private\n * create new input type manager\n * @param {Manager} manager\n * @param {Function} callback\n * @returns {Input}\n * @constructor\n */\nexport default class Input {\n  constructor(manager, callback) {\n    let self = this;\n    this.manager = manager;\n    this.callback = callback;\n    this.element = manager.element;\n    this.target = manager.options.inputTarget;\n\n    // smaller wrapper around the handler, for the scope and the enabled state of the manager,\n    // so when disabled the input events are completely bypassed.\n    this.domHandler = function(ev) {\n      if (boolOrFn(manager.options.enable, [manager])) {\n        self.handler(ev);\n      }\n    };\n\n    this.init();\n\n  }\n  /**\n   * @private\n   * should handle the inputEvent data and trigger the callback\n   * @virtual\n   */\n  handler() { }\n\n  /**\n   * @private\n   * bind the events\n   */\n  init() {\n    this.evEl && addEventListeners(this.element, this.evEl, this.domHandler);\n    this.evTarget && addEventListeners(this.target, this.evTarget, this.domHandler);\n    this.evWin && addEventListeners(getWindowForElement(this.element), this.evWin, this.domHandler);\n  }\n\n  /**\n   * @private\n   * unbind the events\n   */\n  destroy() {\n    this.evEl && removeEventListeners(this.element, this.evEl, this.domHandler);\n    this.evTarget && removeEventListeners(this.target, this.evTarget, this.domHandler);\n    this.evWin && removeEventListeners(getWindowForElement(this.element), this.evWin, this.domHandler);\n  }\n}\n"
  },
  {
    "path": "src/inputjs/input-consts.js",
    "content": "import prefixed from '../utils/prefixed';\n\nconst MOBILE_REGEX = /mobile|tablet|ip(ad|hone|od)|android/i;\n\nconst SUPPORT_TOUCH = ('ontouchstart' in window);\nconst SUPPORT_POINTER_EVENTS = prefixed(window, 'PointerEvent') !== undefined;\nconst SUPPORT_ONLY_TOUCH = SUPPORT_TOUCH && MOBILE_REGEX.test(navigator.userAgent);\n\nconst INPUT_TYPE_TOUCH = 'touch';\nconst INPUT_TYPE_PEN = 'pen';\nconst INPUT_TYPE_MOUSE = 'mouse';\nconst INPUT_TYPE_KINECT = 'kinect';\n\nconst COMPUTE_INTERVAL = 25;\n\nconst INPUT_START = 1;\nconst INPUT_MOVE = 2;\nconst INPUT_END = 4;\nconst INPUT_CANCEL = 8;\n\nconst DIRECTION_NONE = 1;\nconst DIRECTION_LEFT = 2;\nconst DIRECTION_RIGHT = 4;\nconst DIRECTION_UP = 8;\nconst DIRECTION_DOWN = 16;\n\nconst DIRECTION_HORIZONTAL = DIRECTION_LEFT | DIRECTION_RIGHT;\nconst DIRECTION_VERTICAL = DIRECTION_UP | DIRECTION_DOWN;\nconst DIRECTION_ALL = DIRECTION_HORIZONTAL | DIRECTION_VERTICAL;\n\nconst PROPS_XY = ['x', 'y'];\nconst PROPS_CLIENT_XY = ['clientX', 'clientY'];\n\nexport {\n    MOBILE_REGEX,\n    SUPPORT_ONLY_TOUCH,\n    SUPPORT_POINTER_EVENTS,\n    SUPPORT_TOUCH,\n    INPUT_TYPE_KINECT,\n    INPUT_TYPE_MOUSE,\n    INPUT_TYPE_PEN,\n    INPUT_TYPE_TOUCH,\n    COMPUTE_INTERVAL,\n    INPUT_START,\n    INPUT_MOVE,\n    INPUT_END,\n    INPUT_CANCEL,\n    DIRECTION_NONE,\n    DIRECTION_LEFT,\n    DIRECTION_RIGHT,\n    DIRECTION_UP,\n    DIRECTION_DOWN,\n    DIRECTION_HORIZONTAL,\n    DIRECTION_VERTICAL,\n    DIRECTION_ALL,\n    PROPS_XY,\n    PROPS_CLIENT_XY\n};\n"
  },
  {
    "path": "src/inputjs/input-handler.js",
    "content": "import { INPUT_START,INPUT_END,INPUT_CANCEL } from './input-consts';\nimport computeInputData from './compute-input-data';\n\n/**\n * @private\n * handle input events\n * @param {Manager} manager\n * @param {String} eventType\n * @param {Object} input\n */\nexport default function inputHandler(manager, eventType, input) {\n  let pointersLen = input.pointers.length;\n  let changedPointersLen = input.changedPointers.length;\n  let isFirst = (eventType & INPUT_START && (pointersLen - changedPointersLen === 0));\n  let isFinal = (eventType & (INPUT_END | INPUT_CANCEL) && (pointersLen - changedPointersLen === 0));\n\n  input.isFirst = !!isFirst;\n  input.isFinal = !!isFinal;\n\n  if (isFirst) {\n    manager.session = {};\n  }\n\n  // source event is the normalized value of the domEvents\n  // like 'touchstart, mouseup, pointerdown'\n  input.eventType = eventType;\n\n  // compute scale, rotation etc\n  computeInputData(manager, input);\n\n  // emit secret event\n  manager.emit('hammer.input', input);\n\n  manager.recognize(input);\n  manager.session.prevInput = input;\n}\n"
  },
  {
    "path": "src/inputjs/simple-clone-input-data.js",
    "content": "import { now,round } from '../utils/utils-consts';\nimport getCenter from './get-center';\n\n/**\n * @private\n * create a simple clone from the input used for storage of firstInput and firstMultiple\n * @param {Object} input\n * @returns {Object} clonedInputData\n */\nexport default function simpleCloneInputData(input) {\n  // make a simple copy of the pointers because we will get a reference if we don't\n  // we only need clientXY for the calculations\n  let pointers = [];\n  let i = 0;\n  while (i < input.pointers.length) {\n    pointers[i] = {\n      clientX: round(input.pointers[i].clientX),\n      clientY: round(input.pointers[i].clientY)\n    };\n    i++;\n  }\n\n  return {\n    timeStamp: now(),\n    pointers,\n    center: getCenter(pointers),\n    deltaX: input.deltaX,\n    deltaY: input.deltaY\n  };\n}\n"
  },
  {
    "path": "src/main.js",
    "content": "import Hammer from './hammer';\nimport assign from './utils/assign';\nimport {\n    INPUT_START,\n    INPUT_MOVE,\n    INPUT_END,\n    INPUT_CANCEL\n} from './inputjs/input-consts';\nimport {\n    STATE_POSSIBLE,\n    STATE_BEGAN,\n    STATE_CHANGED,\n    STATE_ENDED,\n    STATE_RECOGNIZED,\n    STATE_CANCELLED,\n    STATE_FAILED\n} from './recognizerjs/recognizer-consts';\nimport {\n    DIRECTION_NONE,\n    DIRECTION_LEFT,\n    DIRECTION_RIGHT,\n    DIRECTION_UP,\n    DIRECTION_DOWN,\n    DIRECTION_HORIZONTAL,\n    DIRECTION_VERTICAL,\n    DIRECTION_ALL\n} from './inputjs/input-consts';\n\nimport Manager from './manager';\nimport Input from './inputjs/input-constructor';\nimport TouchAction from './touchactionjs/touchaction-constructor';\nimport TouchInput from './input/touch';\nimport MouseInput from './input/mouse';\nimport PointerEventInput from './input/pointerevent';\nimport SingleTouchInput from './input/singletouch';\nimport TouchMouseInput from './input/touchmouse';\n\nimport Recognizer from  './recognizerjs/recognizer-constructor';\nimport AttrRecognizer from './recognizers/attribute';\nimport TapRecognizer from './recognizers/tap';\nimport PanRecognizer from './recognizers/pan';\nimport SwipeRecognizer from './recognizers/swipe';\nimport PinchRecognizer from './recognizers/pinch';\nimport RotateRecognizer from './recognizers/rotate';\nimport PressRecognizer from './recognizers/press';\n\nimport addEventListeners from './utils/add-event-listeners';\nimport removeEventListeners from './utils/remove-event-listeners';\nimport each from './utils/each';\nimport merge from './utils/merge';\nimport extend from './utils/extend';\nimport inherit from './utils/inherit';\nimport bindFn from './utils/bind-fn';\nimport prefixed from './utils/prefixed';\nimport toArray from'./utils/to-array';\nimport uniqueArray from'./utils/unique-array';\nimport splitStr from'./utils/split-str';\nimport inArray from'./utils/in-array';\nimport boolOrFn from'./utils/bool-or-fn';\nimport hasParent from'./utils/has-parent';\n\n// this prevents errors when Hammer is loaded in the presence of an AMD\n//  style loader but by script tag, not by the loader.\n\nassign(Hammer, {\n  INPUT_START,\n  INPUT_MOVE,\n  INPUT_END,\n  INPUT_CANCEL,\n\n  STATE_POSSIBLE,\n  STATE_BEGAN,\n  STATE_CHANGED,\n  STATE_ENDED,\n  STATE_RECOGNIZED,\n  STATE_CANCELLED,\n  STATE_FAILED,\n\n  DIRECTION_NONE,\n  DIRECTION_LEFT,\n  DIRECTION_RIGHT,\n  DIRECTION_UP,\n  DIRECTION_DOWN,\n  DIRECTION_HORIZONTAL,\n  DIRECTION_VERTICAL,\n  DIRECTION_ALL,\n\n  Manager,\n  Input,\n  TouchAction,\n\n  TouchInput,\n  MouseInput,\n  PointerEventInput,\n  TouchMouseInput,\n  SingleTouchInput,\n\n  Recognizer,\n  AttrRecognizer,\n  Tap: TapRecognizer,\n  Pan: PanRecognizer,\n  Swipe: SwipeRecognizer,\n  Pinch: PinchRecognizer,\n  Rotate: RotateRecognizer,\n  Press: PressRecognizer,\n\n  on: addEventListeners,\n  off: removeEventListeners,\n  each,\n  merge,\n  extend,\n  assign,\n  inherit,\n  bindFn,\n  prefixed,\n  toArray,\n  inArray,\n  uniqueArray,\n  splitStr,\n  boolOrFn,\n  hasParent,\n  addEventListeners,\n  removeEventListeners\n});\n\nlet freeGlobal = (typeof window !== 'undefined' ? window : (typeof self !== 'undefined' ? self : {})); // jshint ignore:line\nfreeGlobal.Hammer = Hammer;\n\n/* jshint ignore:start */\nif (typeof define === 'function' && define.amd) {\n  define(() => {\n    return Hammer;\n  });\n} else if (typeof module !== 'undefined' && module.exports) {\n  module.exports = Hammer;\n} else {\n  window[exportName] = Hammer;\n}\n/* jshint ignore:end */\n"
  },
  {
    "path": "src/manager.js",
    "content": "import assign from './utils/assign';\nimport  Hammer  from './hammer';\nimport TouchAction from './touchactionjs/touchaction-constructor';\nimport createInputInstance from './inputjs/create-input-instance';\nimport each from './utils/each';\nimport inArray from './utils/in-array';\nimport invokeArrayArg from './utils/invoke-array-arg';\nimport splitStr from './utils/split-str';\nimport prefixed from './utils/prefixed';\nimport Recognizer from './recognizerjs/recognizer-constructor';\nimport {\n    STATE_BEGAN,\n    STATE_ENDED,\n    STATE_CHANGED,\n    STATE_RECOGNIZED\n} from './recognizerjs/recognizer-consts';\n\nconst STOP = 1;\nconst FORCED_STOP = 2;\n\n/**\n* @private\n * Manager\n * @param {HTMLElement} element\n * @param {Object} [options]\n * @constructor\n */\nexport default class Manager {\n  constructor(element, options) {\n    this.options = assign({}, Hammer.defaults, options || {});\n\n    this.options.inputTarget = this.options.inputTarget || element;\n\n    this.handlers = {};\n    this.session = {};\n    this.recognizers = [];\n    this.oldCssProps = {};\n\n    this.element = element;\n    this.input = createInputInstance(this);\n    this.touchAction = new TouchAction(this, this.options.touchAction);\n\n    toggleCssProps(this, true);\n\n    each(this.options.recognizers, (item) => {\n      let recognizer = this.add(new (item[0])(item[1]));\n      item[2] && recognizer.recognizeWith(item[2]);\n      item[3] && recognizer.requireFailure(item[3]);\n    }, this);\n  }\n\n  /**\n   * @private\n   * set options\n   * @param {Object} options\n   * @returns {Manager}\n   */\n  set(options) {\n    assign(this.options, options);\n\n    // Options that need a little more setup\n    if (options.touchAction) {\n      this.touchAction.update();\n    }\n    if (options.inputTarget) {\n      // Clean up existing event listeners and reinitialize\n      this.input.destroy();\n      this.input.target = options.inputTarget;\n      this.input.init();\n    }\n    return this;\n  }\n\n  /**\n   * @private\n   * stop recognizing for this session.\n   * This session will be discarded, when a new [input]start event is fired.\n   * When forced, the recognizer cycle is stopped immediately.\n   * @param {Boolean} [force]\n   */\n  stop(force) {\n    this.session.stopped = force ? FORCED_STOP : STOP;\n  }\n\n  /**\n   * @private\n   * run the recognizers!\n   * called by the inputHandler function on every movement of the pointers (touches)\n   * it walks through all the recognizers and tries to detect the gesture that is being made\n   * @param {Object} inputData\n   */\n  recognize(inputData) {\n    let { session } = this;\n    if (session.stopped) {\n      return;\n    }\n\n    // run the touch-action polyfill\n    this.touchAction.preventDefaults(inputData);\n\n    let recognizer;\n    let { recognizers } = this;\n\n    // this holds the recognizer that is being recognized.\n    // so the recognizer's state needs to be BEGAN, CHANGED, ENDED or RECOGNIZED\n    // if no recognizer is detecting a thing, it is set to `null`\n    let { curRecognizer } = session;\n\n    // reset when the last recognizer is recognized\n    // or when we're in a new session\n    if (!curRecognizer || (curRecognizer && curRecognizer.state & STATE_RECOGNIZED)) {\n      curRecognizer = session.curRecognizer = null;\n    }\n\n    let i = 0;\n    while (i < recognizers.length) {\n      recognizer = recognizers[i];\n\n      // find out if we are allowed try to recognize the input for this one.\n      // 1.   allow if the session is NOT forced stopped (see the .stop() method)\n      // 2.   allow if we still haven't recognized a gesture in this session, or the this recognizer is the one\n      //      that is being recognized.\n      // 3.   allow if the recognizer is allowed to run simultaneous with the current recognized recognizer.\n      //      this can be setup with the `recognizeWith()` method on the recognizer.\n      if (session.stopped !== FORCED_STOP && (// 1\n              !curRecognizer || recognizer === curRecognizer || // 2\n              recognizer.canRecognizeWith(curRecognizer))) { // 3\n        recognizer.recognize(inputData);\n      } else {\n        recognizer.reset();\n      }\n\n      // if the recognizer has been recognizing the input as a valid gesture, we want to store this one as the\n      // current active recognizer. but only if we don't already have an active recognizer\n      if (!curRecognizer && recognizer.state & (STATE_BEGAN | STATE_CHANGED | STATE_ENDED)) {\n        curRecognizer = session.curRecognizer = recognizer;\n      }\n      i++;\n    }\n  }\n\n  /**\n   * @private\n   * get a recognizer by its event name.\n   * @param {Recognizer|String} recognizer\n   * @returns {Recognizer|Null}\n   */\n  get(recognizer) {\n    if (recognizer instanceof Recognizer) {\n      return recognizer;\n    }\n\n    let { recognizers } = this;\n    for (let i = 0; i < recognizers.length; i++) {\n      if (recognizers[i].options.event === recognizer) {\n        return recognizers[i];\n      }\n    }\n    return null;\n  }\n\n  /**\n   * @private add a recognizer to the manager\n   * existing recognizers with the same event name will be removed\n   * @param {Recognizer} recognizer\n   * @returns {Recognizer|Manager}\n   */\n  add(recognizer) {\n    if (invokeArrayArg(recognizer, 'add', this)) {\n      return this;\n    }\n\n    // remove existing\n    let existing = this.get(recognizer.options.event);\n    if (existing) {\n      this.remove(existing);\n    }\n\n    this.recognizers.push(recognizer);\n    recognizer.manager = this;\n\n    this.touchAction.update();\n    return recognizer;\n  }\n\n  /**\n   * @private\n   * remove a recognizer by name or instance\n   * @param {Recognizer|String} recognizer\n   * @returns {Manager}\n   */\n  remove(recognizer) {\n    if (invokeArrayArg(recognizer, 'remove', this)) {\n      return this;\n    }\n\n    recognizer = this.get(recognizer);\n\n    // let's make sure this recognizer exists\n    if (recognizer) {\n      let { recognizers } = this;\n      let index = inArray(recognizers, recognizer);\n\n      if (index !== -1) {\n        recognizers.splice(index, 1);\n        this.touchAction.update();\n      }\n    }\n\n    return this;\n  }\n\n  /**\n   * @private\n   * bind event\n   * @param {String} events\n   * @param {Function} handler\n   * @returns {EventEmitter} this\n   */\n  on(events, handler) {\n    if (events === undefined) {\n      return;\n    }\n    if (handler === undefined) {\n      return;\n    }\n\n    let { handlers } = this;\n    each(splitStr(events), (event) => {\n      handlers[event] = handlers[event] || [];\n      handlers[event].push(handler);\n    });\n    return this;\n  }\n\n  /**\n   * @private unbind event, leave emit blank to remove all handlers\n   * @param {String} events\n   * @param {Function} [handler]\n   * @returns {EventEmitter} this\n   */\n  off(events, handler) {\n    if (events === undefined) {\n      return;\n    }\n\n    let { handlers } = this;\n    each(splitStr(events), (event) => {\n      if (!handler) {\n        delete handlers[event];\n      } else {\n        handlers[event] && handlers[event].splice(inArray(handlers[event], handler), 1);\n      }\n    });\n    return this;\n  }\n\n  /**\n   * @private emit event to the listeners\n   * @param {String} event\n   * @param {Object} data\n   */\n  emit(event, data) {\n    // we also want to trigger dom events\n    if (this.options.domEvents) {\n      triggerDomEvent(event, data);\n    }\n\n    // no handlers, so skip it all\n    let handlers = this.handlers[event] && this.handlers[event].slice();\n    if (!handlers || !handlers.length) {\n      return;\n    }\n\n    data.type = event;\n    data.preventDefault = function() {\n      data.srcEvent.preventDefault();\n    };\n\n    let i = 0;\n    while (i < handlers.length) {\n      handlers[i](data);\n      i++;\n    }\n  }\n\n  /**\n   * @private\n   * destroy the manager and unbinds all events\n   * it doesn't unbind dom events, that is the user own responsibility\n   */\n  destroy() {\n    this.element && toggleCssProps(this, false);\n\n    this.handlers = {};\n    this.session = {};\n    this.input.destroy();\n    this.element = null;\n  }\n}\n\n/**\n * @private\n * add/remove the css properties as defined in manager.options.cssProps\n * @param {Manager} manager\n * @param {Boolean} add\n */\nfunction toggleCssProps(manager, add) {\n  let { element } = manager;\n  if (!element.style) {\n    return;\n  }\n  let prop;\n  each(manager.options.cssProps, (value, name) => {\n    prop = prefixed(element.style, name);\n    if (add) {\n      manager.oldCssProps[prop] = element.style[prop];\n      element.style[prop] = value;\n    } else {\n      element.style[prop] = manager.oldCssProps[prop] || '';\n    }\n  });\n  if (!add) {\n    manager.oldCssProps = {};\n  }\n}\n\n/**\n * @private\n * trigger dom event\n * @param {String} event\n * @param {Object} data\n */\nfunction triggerDomEvent(event, data) {\n  let gestureEvent = document.createEvent('Event');\n  gestureEvent.initEvent(event, true, true);\n  gestureEvent.gesture = data;\n  data.target.dispatchEvent(gestureEvent);\n}\n"
  },
  {
    "path": "src/recognizerjs/direction-str.js",
    "content": "import {\n    DIRECTION_LEFT,\n    DIRECTION_RIGHT,\n    DIRECTION_UP,\n    DIRECTION_DOWN\n} from '../inputjs/input-consts';\n\n/**\n * @private\n * direction cons to string\n * @param {constant} direction\n * @returns {String}\n */\nexport default function directionStr(direction) {\n  if (direction === DIRECTION_DOWN) {\n    return 'down';\n  } else if (direction === DIRECTION_UP) {\n    return 'up';\n  } else if (direction === DIRECTION_LEFT) {\n    return 'left';\n  } else if (direction === DIRECTION_RIGHT) {\n    return 'right';\n  }\n  return '';\n}\n"
  },
  {
    "path": "src/recognizerjs/get-recognizer-by-name-if-manager.js",
    "content": "/**\n * @private\n * get a recognizer by name if it is bound to a manager\n * @param {Recognizer|String} otherRecognizer\n * @param {Recognizer} recognizer\n * @returns {Recognizer}\n */\nexport default function getRecognizerByNameIfManager(otherRecognizer, recognizer) {\n  let { manager } = recognizer;\n  if (manager) {\n    return manager.get(otherRecognizer);\n  }\n  return otherRecognizer;\n}\n"
  },
  {
    "path": "src/recognizerjs/recognizer-constructor.js",
    "content": "import {\n    STATE_POSSIBLE,\n    STATE_ENDED,\n    STATE_FAILED,\n    STATE_RECOGNIZED,\n    STATE_CANCELLED,\n    STATE_BEGAN,\n    STATE_CHANGED\n} from './recognizer-consts';\nimport assign from '../utils/assign';\nimport uniqueId from '../utils/unique-id';\nimport ifUndefined from '../utils/if-undefined';\nimport invokeArrayArg from '../utils/invoke-array-arg';\nimport inArray from '../utils/in-array';\nimport boolOrFn from '../utils/bool-or-fn';\nimport getRecognizerByNameIfManager from './get-recognizer-by-name-if-manager';\nimport stateStr from './state-str';\n\n/**\n * @private\n * Recognizer flow explained; *\n * All recognizers have the initial state of POSSIBLE when a input session starts.\n * The definition of a input session is from the first input until the last input, with all it's movement in it. *\n * Example session for mouse-input: mousedown -> mousemove -> mouseup\n *\n * On each recognizing cycle (see Manager.recognize) the .recognize() method is executed\n * which determines with state it should be.\n *\n * If the recognizer has the state FAILED, CANCELLED or RECOGNIZED (equals ENDED), it is reset to\n * POSSIBLE to give it another change on the next cycle.\n *\n *               Possible\n *                  |\n *            +-----+---------------+\n *            |                     |\n *      +-----+-----+               |\n *      |           |               |\n *   Failed      Cancelled          |\n *                          +-------+------+\n *                          |              |\n *                      Recognized       Began\n *                                         |\n *                                      Changed\n *                                         |\n *                                  Ended/Recognized\n */\n\n/**\n * @private\n * Recognizer\n * Every recognizer needs to extend from this class.\n * @constructor\n * @param {Object} options\n */\nexport default class Recognizer {\n  constructor(options) {\n    this.options = assign({}, this.defaults, options || {});\n\n    this.id = uniqueId();\n\n    this.manager = null;\n\n    // default is enable true\n    this.options.enable = ifUndefined(this.options.enable, true);\n\n    this.state = STATE_POSSIBLE;\n    this.simultaneous = {};\n    this.requireFail = [];\n  }\n\n  /**\n   * @private\n   * set options\n   * @param {Object} options\n   * @return {Recognizer}\n   */\n  set(options) {\n    assign(this.options, options);\n\n    // also update the touchAction, in case something changed about the directions/enabled state\n    this.manager && this.manager.touchAction.update();\n    return this;\n  }\n\n  /**\n   * @private\n   * recognize simultaneous with an other recognizer.\n   * @param {Recognizer} otherRecognizer\n   * @returns {Recognizer} this\n   */\n  recognizeWith(otherRecognizer) {\n    if (invokeArrayArg(otherRecognizer, 'recognizeWith', this)) {\n      return this;\n    }\n\n    let { simultaneous } = this;\n    otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this);\n    if (!simultaneous[otherRecognizer.id]) {\n      simultaneous[otherRecognizer.id] = otherRecognizer;\n      otherRecognizer.recognizeWith(this);\n    }\n    return this;\n  }\n\n  /**\n   * @private\n   * drop the simultaneous link. it doesnt remove the link on the other recognizer.\n   * @param {Recognizer} otherRecognizer\n   * @returns {Recognizer} this\n   */\n  dropRecognizeWith(otherRecognizer) {\n    if (invokeArrayArg(otherRecognizer, 'dropRecognizeWith', this)) {\n      return this;\n    }\n\n    otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this);\n    delete this.simultaneous[otherRecognizer.id];\n    return this;\n  }\n\n  /**\n   * @private\n   * recognizer can only run when an other is failing\n   * @param {Recognizer} otherRecognizer\n   * @returns {Recognizer} this\n   */\n  requireFailure(otherRecognizer) {\n    if (invokeArrayArg(otherRecognizer, 'requireFailure', this)) {\n      return this;\n    }\n\n    let { requireFail } = this;\n    otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this);\n    if (inArray(requireFail, otherRecognizer) === -1) {\n      requireFail.push(otherRecognizer);\n      otherRecognizer.requireFailure(this);\n    }\n    return this;\n  }\n\n  /**\n   * @private\n   * drop the requireFailure link. it does not remove the link on the other recognizer.\n   * @param {Recognizer} otherRecognizer\n   * @returns {Recognizer} this\n   */\n  dropRequireFailure(otherRecognizer) {\n    if (invokeArrayArg(otherRecognizer, 'dropRequireFailure', this)) {\n      return this;\n    }\n\n    otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this);\n    let index = inArray(this.requireFail, otherRecognizer);\n    if (index > -1) {\n      this.requireFail.splice(index, 1);\n    }\n    return this;\n  }\n\n  /**\n   * @private\n   * has require failures boolean\n   * @returns {boolean}\n   */\n  hasRequireFailures() {\n    return this.requireFail.length > 0;\n  }\n\n  /**\n   * @private\n   * if the recognizer can recognize simultaneous with an other recognizer\n   * @param {Recognizer} otherRecognizer\n   * @returns {Boolean}\n   */\n  canRecognizeWith(otherRecognizer) {\n    return !!this.simultaneous[otherRecognizer.id];\n  }\n\n  /**\n   * @private\n   * You should use `tryEmit` instead of `emit` directly to check\n   * that all the needed recognizers has failed before emitting.\n   * @param {Object} input\n   */\n  emit(input) {\n    let self = this;\n    let { state } = this;\n\n    function emit(event) {\n      self.manager.emit(event, input);\n    }\n\n    // 'panstart' and 'panmove'\n    if (state < STATE_ENDED) {\n      emit(self.options.event + stateStr(state));\n    }\n\n    emit(self.options.event); // simple 'eventName' events\n\n    if (input.additionalEvent) { // additional event(panleft, panright, pinchin, pinchout...)\n      emit(input.additionalEvent);\n    }\n\n    // panend and pancancel\n    if (state >= STATE_ENDED) {\n      emit(self.options.event + stateStr(state));\n    }\n  }\n\n  /**\n   * @private\n   * Check that all the require failure recognizers has failed,\n   * if true, it emits a gesture event,\n   * otherwise, setup the state to FAILED.\n   * @param {Object} input\n   */\n  tryEmit(input) {\n    if (this.canEmit()) {\n      return this.emit(input);\n    }\n    // it's failing anyway\n    this.state = STATE_FAILED;\n  }\n\n  /**\n   * @private\n   * can we emit?\n   * @returns {boolean}\n   */\n  canEmit() {\n    let i = 0;\n    while (i < this.requireFail.length) {\n      if (!(this.requireFail[i].state & (STATE_FAILED | STATE_POSSIBLE))) {\n        return false;\n      }\n      i++;\n    }\n    return true;\n  }\n\n  /**\n   * @private\n   * update the recognizer\n   * @param {Object} inputData\n   */\n  recognize(inputData) {\n    // make a new copy of the inputData\n    // so we can change the inputData without messing up the other recognizers\n    let inputDataClone = assign({}, inputData);\n\n    // is is enabled and allow recognizing?\n    if (!boolOrFn(this.options.enable, [this, inputDataClone])) {\n      this.reset();\n      this.state = STATE_FAILED;\n      return;\n    }\n\n    // reset when we've reached the end\n    if (this.state & (STATE_RECOGNIZED | STATE_CANCELLED | STATE_FAILED)) {\n      this.state = STATE_POSSIBLE;\n    }\n\n    this.state = this.process(inputDataClone);\n\n    // the recognizer has recognized a gesture\n    // so trigger an event\n    if (this.state & (STATE_BEGAN | STATE_CHANGED | STATE_ENDED | STATE_CANCELLED)) {\n      this.tryEmit(inputDataClone);\n    }\n  }\n\n  /**\n   * @private\n   * return the state of the recognizer\n   * the actual recognizing happens in this method\n   * @virtual\n   * @param {Object} inputData\n   * @returns {constant} STATE\n   */\n\n  /* jshint ignore:start */\n  process(inputData) { }\n  /* jshint ignore:end */\n\n  /**\n   * @private\n   * return the preferred touch-action\n   * @virtual\n   * @returns {Array}\n   */\n  getTouchAction() { }\n\n  /**\n   * @private\n   * called when the gesture isn't allowed to recognize\n   * like when another is being recognized or it is disabled\n   * @virtual\n   */\n  reset() { }\n}\n\nRecognizer.prototype.defaults = {};\n"
  },
  {
    "path": "src/recognizerjs/recognizer-consts.js",
    "content": "const STATE_POSSIBLE = 1;\nconst STATE_BEGAN = 2;\nconst STATE_CHANGED = 4;\nconst STATE_ENDED = 8;\nconst STATE_RECOGNIZED = STATE_ENDED;\nconst STATE_CANCELLED = 16;\nconst STATE_FAILED = 32;\n\nexport {\n    STATE_POSSIBLE,\n    STATE_BEGAN,\n    STATE_CHANGED,\n    STATE_ENDED,\n    STATE_RECOGNIZED,\n    STATE_CANCELLED,\n    STATE_FAILED\n};\n"
  },
  {
    "path": "src/recognizerjs/state-str.js",
    "content": "import {\n    STATE_CANCELLED,\n    STATE_ENDED,\n    STATE_CHANGED,\n    STATE_BEGAN\n} from './recognizer-consts';\n\n/**\n * @private\n * get a usable string, used as event postfix\n * @param {constant} state\n * @returns {String} state\n */\nexport default function stateStr(state) {\n  if (state & STATE_CANCELLED) {\n    return 'cancel';\n  } else if (state & STATE_ENDED) {\n    return 'end';\n  } else if (state & STATE_CHANGED) {\n    return 'move';\n  } else if (state & STATE_BEGAN) {\n    return 'start';\n  }\n  return '';\n}\n"
  },
  {
    "path": "src/recognizers/attribute.js",
    "content": "import Recognizer from '../recognizerjs/recognizer-constructor';\nimport {\n    STATE_BEGAN,\n    STATE_CHANGED,\n    STATE_CANCELLED,\n    STATE_ENDED,\n    STATE_FAILED\n} from '../recognizerjs/recognizer-consts';\nimport {\n    INPUT_CANCEL,\n    INPUT_END\n} from '../inputjs/input-consts';\n\n/**\n * @private\n * This recognizer is just used as a base for the simple attribute recognizers.\n * @constructor\n * @extends Recognizer\n */\nexport default class AttrRecognizer extends Recognizer {\n  constructor() {\n    super(...arguments);\n  }\n\n  /**\n   * @private\n   * Used to check if it the recognizer receives valid input, like input.distance > 10.\n   * @memberof AttrRecognizer\n   * @param {Object} input\n   * @returns {Boolean} recognized\n   */\n  attrTest(input) {\n    let optionPointers = this.options.pointers;\n    return optionPointers === 0 || input.pointers.length === optionPointers;\n  }\n\n  /**\n   * @private\n   * Process the input and return the state for the recognizer\n   * @memberof AttrRecognizer\n   * @param {Object} input\n   * @returns {*} State\n   */\n  process(input) {\n    let { state } = this;\n    let { eventType } = input;\n\n    let isRecognized = state & (STATE_BEGAN | STATE_CHANGED);\n    let isValid = this.attrTest(input);\n\n    // on cancel input and we've recognized before, return STATE_CANCELLED\n    if (isRecognized && (eventType & INPUT_CANCEL || !isValid)) {\n      return state | STATE_CANCELLED;\n    } else if (isRecognized || isValid) {\n      if (eventType & INPUT_END) {\n        return state | STATE_ENDED;\n      } else if (!(state & STATE_BEGAN)) {\n        return STATE_BEGAN;\n      }\n      return state | STATE_CHANGED;\n    }\n    return STATE_FAILED;\n  }\n}\n\nAttrRecognizer.prototype.defaults = {\n  /**\n   * @private\n   * @type {Number}\n   * @default 1\n   */\n  pointers: 1\n};\n"
  },
  {
    "path": "src/recognizers/pan.js",
    "content": "import  AttrRecognizer from './attribute';\nimport {\n    DIRECTION_ALL,\n    DIRECTION_HORIZONTAL,\n    DIRECTION_VERTICAL,\n    DIRECTION_NONE,\n    DIRECTION_UP,\n    DIRECTION_DOWN,\n    DIRECTION_LEFT,\n    DIRECTION_RIGHT\n} from '../inputjs/input-consts';\nimport { STATE_BEGAN } from '../recognizerjs/recognizer-consts';\nimport { TOUCH_ACTION_PAN_X,TOUCH_ACTION_PAN_Y } from '../touchactionjs/touchaction-Consts';\nimport directionStr from '../recognizerjs/direction-str';\n\n/**\n * @private\n * Pan\n * Recognized when the pointer is down and moved in the allowed direction.\n * @constructor\n * @extends AttrRecognizer\n */\nexport default class PanRecognizer extends AttrRecognizer {\n  constructor() {\n    super(...arguments);\n    this.pX = null;\n    this.pY = null;\n  }\n\n  getTouchAction() {\n    let { options:{ direction } } = this;\n    let actions = [];\n    if (direction & DIRECTION_HORIZONTAL) {\n      actions.push(TOUCH_ACTION_PAN_Y);\n    }\n    if (direction & DIRECTION_VERTICAL) {\n      actions.push(TOUCH_ACTION_PAN_X);\n    }\n    return actions;\n  }\n\n  directionTest(input) {\n    let { options } = this;\n    let hasMoved = true;\n    let { distance } = input;\n    let { direction } = input;\n    let x = input.deltaX;\n    let y = input.deltaY;\n\n    // lock to axis?\n    if (!(direction & options.direction)) {\n      if (options.direction & DIRECTION_HORIZONTAL) {\n        direction = (x === 0) ? DIRECTION_NONE : (x < 0) ? DIRECTION_LEFT : DIRECTION_RIGHT;\n        hasMoved = x !== this.pX;\n        distance = Math.abs(input.deltaX);\n      } else {\n        direction = (y === 0) ? DIRECTION_NONE : (y < 0) ? DIRECTION_UP : DIRECTION_DOWN;\n        hasMoved = y !== this.pY;\n        distance = Math.abs(input.deltaY);\n      }\n    }\n    input.direction = direction;\n    return hasMoved && distance > options.threshold && direction & options.direction;\n  }\n\n  attrTest(input) {\n    return AttrRecognizer.prototype.attrTest.call(this, input) && // replace with a super call\n        (this.state & STATE_BEGAN || (!(this.state & STATE_BEGAN) && this.directionTest(input)));\n  }\n\n  emit(input) {\n\n    this.pX = input.deltaX;\n    this.pY = input.deltaY;\n\n    let direction = directionStr(input.direction);\n\n    if (direction) {\n      input.additionalEvent = this.options.event + direction;\n    }\n    super.emit(input);\n  }\n}\n\nPanRecognizer.prototype.defaults = {\n  event: 'pan',\n  threshold: 10,\n  pointers: 1,\n  direction: DIRECTION_ALL\n};\n"
  },
  {
    "path": "src/recognizers/pinch.js",
    "content": "import AttrRecognizer from './attribute';\nimport { TOUCH_ACTION_NONE } from '../touchactionjs/touchaction-Consts';\nimport { STATE_BEGAN } from '../recognizerjs/recognizer-consts';\n\n/**\n * @private\n * Pinch\n * Recognized when two or more pointers are moving toward (zoom-in) or away from each other (zoom-out).\n * @constructor\n * @extends AttrRecognizer\n */\nexport default class PinchRecognizer extends AttrRecognizer {\n  constructor() {\n    super(...arguments);\n  }\n\n  getTouchAction() {\n    return [TOUCH_ACTION_NONE];\n  }\n\n  attrTest(input) {\n    return super.attrTest(input) &&\n        (Math.abs(input.scale - 1) > this.options.threshold || this.state & STATE_BEGAN);\n  }\n\n  emit(input) {\n    if (input.scale !== 1) {\n      let inOut = input.scale < 1 ? 'in' : 'out';\n      input.additionalEvent = this.options.event + inOut;\n    }\n    super.emit(input);\n  }\n}\n\nPinchRecognizer.prototype.defaults = {\n  event: 'pinch',\n  threshold: 0,\n  pointers: 2\n};\n"
  },
  {
    "path": "src/recognizers/press.js",
    "content": "import Recognizer from '../recognizerjs/recognizer-constructor';\nimport {\n    STATE_RECOGNIZED,\n    STATE_FAILED\n} from '../recognizerjs/recognizer-consts';\nimport { now } from '../utils/utils-consts';\nimport setTimeoutContext from '../utils/set-timeout-context';\nimport { TOUCH_ACTION_AUTO } from '../touchactionjs/touchaction-Consts';\nimport {\n    INPUT_START,\n    INPUT_END,\n    INPUT_CANCEL\n} from '../inputjs/input-consts';\n\n/**\n * @private\n * Press\n * Recognized when the pointer is down for x ms without any movement.\n * @constructor\n * @extends Recognizer\n */\nexport default class PressRecognizer extends Recognizer {\n  constructor() {\n    super(...arguments);\n    this._timer = null;\n    this._input = null;\n  }\n\n  getTouchAction() {\n    return [TOUCH_ACTION_AUTO];\n  }\n\n  process(input) {\n    let { options } = this;\n    let validPointers = input.pointers.length === options.pointers;\n    let validMovement = input.distance < options.threshold;\n    let validTime = input.deltaTime > options.time;\n\n    this._input = input;\n\n    // we only allow little movement\n    // and we've reached an end event, so a tap is possible\n    if (!validMovement || !validPointers || (input.eventType & (INPUT_END | INPUT_CANCEL) && !validTime)) {\n      this.reset();\n    } else if (input.eventType & INPUT_START) {\n      this.reset();\n      this._timer = setTimeoutContext(() => {\n        this.state = STATE_RECOGNIZED;\n        this.tryEmit();\n      }, options.time, this);\n    } else if (input.eventType & INPUT_END) {\n      return STATE_RECOGNIZED;\n    }\n    return STATE_FAILED;\n  }\n\n  reset() {\n    clearTimeout(this._timer);\n  }\n\n  emit(input) {\n    if (this.state !== STATE_RECOGNIZED) {\n      return;\n    }\n\n    if (input && (input.eventType & INPUT_END)) {\n      this.manager.emit(`${this.options.event}up`, input);\n    } else {\n      this._input.timeStamp = now();\n      this.manager.emit(this.options.event, this._input);\n    }\n  }\n}\n\nPressRecognizer.prototype.defaults = {\n  event: 'press',\n  pointers: 1,\n  time: 251, // minimal time of the pointer to be pressed\n  threshold: 9 // a minimal movement is ok, but keep it low\n};\n"
  },
  {
    "path": "src/recognizers/rotate.js",
    "content": "import AttrRecognizer from './attribute';\nimport { TOUCH_ACTION_NONE } from '../touchactionjs/touchaction-Consts';\nimport { STATE_BEGAN } from '../recognizerjs/recognizer-consts';\n\n/**\n * @private\n * Rotate\n * Recognized when two or more pointer are moving in a circular motion.\n * @constructor\n * @extends AttrRecognizer\n */\nexport default class RotateRecognizer extends AttrRecognizer {\n  constructor() {\n    super(...arguments);\n  }\n\n  getTouchAction() {\n    return [TOUCH_ACTION_NONE];\n  }\n\n  attrTest(input) {\n    return super.attrTest(input) &&\n        (Math.abs(input.rotation) > this.options.threshold || this.state & STATE_BEGAN);\n  }\n}\n\nRotateRecognizer.prototype.defaults = {\n  event: 'rotate',\n  threshold: 0,\n  pointers: 2\n};\n"
  },
  {
    "path": "src/recognizers/swipe.js",
    "content": "import AttrRecognizer from '../recognizers/attribute';\nimport { abs } from '../utils/utils-consts';\nimport { DIRECTION_HORIZONTAL,DIRECTION_VERTICAL } from '../inputjs/input-consts';\nimport PanRecognizer from './pan';\nimport { INPUT_END } from '../inputjs/input-consts';\nimport directionStr from '../recognizerjs/direction-str';\n\n/**\n * @private\n * Swipe\n * Recognized when the pointer is moving fast (velocity), with enough distance in the allowed direction.\n * @constructor\n * @extends AttrRecognizer\n */\nexport default class SwipeRecognizer extends AttrRecognizer {\n  constructor() {\n    super(...arguments);\n  }\n\n  getTouchAction() {\n    return PanRecognizer.prototype.getTouchAction.call(this);\n  }\n\n  attrTest(input) {\n    let { direction } = this.options;\n    let velocity;\n\n    if (direction & (DIRECTION_HORIZONTAL | DIRECTION_VERTICAL)) {\n      velocity = input.overallVelocity;\n    } else if (direction & DIRECTION_HORIZONTAL) {\n      velocity = input.overallVelocityX;\n    } else if (direction & DIRECTION_VERTICAL) {\n      velocity = input.overallVelocityY;\n    }\n\n    return super.attrTest(input) &&\n        direction & input.offsetDirection &&\n        input.distance > this.options.threshold &&\n        input.maxPointers === this.options.pointers &&\n        abs(velocity) > this.options.velocity && input.eventType & INPUT_END;\n  }\n\n  emit(input) {\n    let direction = directionStr(input.offsetDirection);\n    if (direction) {\n      this.manager.emit(this.options.event + direction, input);\n    }\n\n    this.manager.emit(this.options.event, input);\n  }\n}\n\nSwipeRecognizer.prototype.defaults = {\n  event: 'swipe',\n  threshold: 10,\n  velocity: 0.3,\n  direction: DIRECTION_HORIZONTAL | DIRECTION_VERTICAL,\n  pointers: 1\n};\n"
  },
  {
    "path": "src/recognizers/tap.js",
    "content": "import setTimeoutContext from '../utils/set-timeout-context';\nimport Recognizer from '../recognizerjs/recognizer-constructor';\nimport { TOUCH_ACTION_MANIPULATION } from '../touchactionjs/touchaction-Consts';\nimport {INPUT_START,INPUT_END } from '../inputjs/input-consts';\nimport {\n    STATE_RECOGNIZED,\n    STATE_BEGAN,\n    STATE_FAILED\n} from '../recognizerjs/recognizer-consts';\nimport getDistance from '../inputjs/get-distance';\n\n/**\n * @private\n * A tap is recognized when the pointer is doing a small tap/click. Multiple taps are recognized if they occur\n * between the given interval and position. The delay option can be used to recognize multi-taps without firing\n * a single tap.\n *\n * The eventData from the emitted event contains the property `tapCount`, which contains the amount of\n * multi-taps being recognized.\n * @constructor\n * @extends Recognizer\n */\nexport default class TapRecognizer extends Recognizer {\n  constructor() {\n    super(...arguments);\n\n    // previous time and center,\n    // used for tap counting\n    this.pTime = false;\n    this.pCenter = false;\n\n    this._timer = null;\n    this._input = null;\n    this.count = 0;\n  }\n\n  getTouchAction() {\n    return [TOUCH_ACTION_MANIPULATION];\n  }\n\n  process(input) {\n    let { options } = this;\n\n    let validPointers = input.pointers.length === options.pointers;\n    let validMovement = input.distance < options.threshold;\n    let validTouchTime = input.deltaTime < options.time;\n\n    this.reset();\n\n    if ((input.eventType & INPUT_START) && (this.count === 0)) {\n      return this.failTimeout();\n    }\n\n    // we only allow little movement\n    // and we've reached an end event, so a tap is possible\n    if (validMovement && validTouchTime && validPointers) {\n      if (input.eventType !== INPUT_END) {\n        return this.failTimeout();\n      }\n\n      let validInterval = this.pTime ? (input.timeStamp - this.pTime < options.interval) : true;\n      let validMultiTap = !this.pCenter || getDistance(this.pCenter, input.center) < options.posThreshold;\n\n      this.pTime = input.timeStamp;\n      this.pCenter = input.center;\n\n      if (!validMultiTap || !validInterval) {\n        this.count = 1;\n      } else {\n        this.count += 1;\n      }\n\n      this._input = input;\n\n      // if tap count matches we have recognized it,\n      // else it has began recognizing...\n      let tapCount = this.count % options.taps;\n      if (tapCount === 0) {\n        // no failing requirements, immediately trigger the tap event\n        // or wait as long as the multitap interval to trigger\n        if (!this.hasRequireFailures()) {\n          return STATE_RECOGNIZED;\n        } else {\n          this._timer = setTimeoutContext(() => {\n            this.state = STATE_RECOGNIZED;\n            this.tryEmit();\n          }, options.interval, this);\n          return STATE_BEGAN;\n        }\n      }\n    }\n    return STATE_FAILED;\n  }\n\n  failTimeout() {\n    this._timer = setTimeoutContext(() => {\n      this.state = STATE_FAILED;\n    }, this.options.interval, this);\n    return STATE_FAILED;\n  }\n\n  reset() {\n    clearTimeout(this._timer);\n  }\n\n  emit() {\n    if (this.state === STATE_RECOGNIZED) {\n      this._input.tapCount = this.count;\n      this.manager.emit(this.options.event, this._input);\n    }\n  }\n}\n\nTapRecognizer.prototype.defaults = {\n  event: 'tap',\n  pointers: 1,\n  taps: 1,\n  interval: 300, // max time between the multi-tap taps\n  time: 250, // max time of the pointer to be down (like finger on the screen)\n  threshold: 9, // a minimal movement is ok, but keep it low\n  posThreshold: 10 // a multi-tap can be a bit off the initial position\n};\n"
  },
  {
    "path": "src/touchactionjs/clean-touch-actions.js",
    "content": "import inStr from '../utils/in-str';\nimport {\n    TOUCH_ACTION_NONE,\n    TOUCH_ACTION_PAN_X,\n    TOUCH_ACTION_PAN_Y,\n    TOUCH_ACTION_MANIPULATION,\n    TOUCH_ACTION_AUTO\n} from './touchaction-Consts';\n\n/**\n * @private\n * when the touchActions are collected they are not a valid value, so we need to clean things up. *\n * @param {String} actions\n * @returns {*}\n */\nexport default function cleanTouchActions(actions) {\n  // none\n  if (inStr(actions, TOUCH_ACTION_NONE)) {\n    return TOUCH_ACTION_NONE;\n  }\n\n  let hasPanX = inStr(actions, TOUCH_ACTION_PAN_X);\n  let hasPanY = inStr(actions, TOUCH_ACTION_PAN_Y);\n\n  // if both pan-x and pan-y are set (different recognizers\n  // for different directions, e.g. horizontal pan but vertical swipe?)\n  // we need none (as otherwise with pan-x pan-y combined none of these\n  // recognizers will work, since the browser would handle all panning\n  if (hasPanX && hasPanY) {\n    return TOUCH_ACTION_NONE;\n  }\n\n  // pan-x OR pan-y\n  if (hasPanX || hasPanY) {\n    return hasPanX ? TOUCH_ACTION_PAN_X : TOUCH_ACTION_PAN_Y;\n  }\n\n  // manipulation\n  if (inStr(actions, TOUCH_ACTION_MANIPULATION)) {\n    return TOUCH_ACTION_MANIPULATION;\n  }\n\n  return TOUCH_ACTION_AUTO;\n}\n"
  },
  {
    "path": "src/touchactionjs/get-touchaction-props.js",
    "content": "import { NATIVE_TOUCH_ACTION } from './touchaction-Consts';\n\nexport default function getTouchActionProps() {\n  if (!NATIVE_TOUCH_ACTION) {\n    return false;\n  }\n  let touchMap = {};\n  let cssSupports = window.CSS && window.CSS.supports;\n  ['auto', 'manipulation', 'pan-y', 'pan-x', 'pan-x pan-y', 'none'].forEach((val) => {\n\n    // If css.supports is not supported but there is native touch-action assume it supports\n    // all values. This is the case for IE 10 and 11.\n    return touchMap[val] = cssSupports ? window.CSS.supports('touch-action', val) : true;\n  });\n  return touchMap;\n}\n"
  },
  {
    "path": "src/touchactionjs/touchaction-Consts.js",
    "content": "import prefixed from '../utils/prefixed';\nimport { TEST_ELEMENT } from '../utils/utils-consts';\nimport getTouchActionProps from './get-touchaction-props';\n\nconst PREFIXED_TOUCH_ACTION = prefixed(TEST_ELEMENT.style, 'touchAction');\nconst NATIVE_TOUCH_ACTION = PREFIXED_TOUCH_ACTION !== undefined;\n\n// magical touchAction value\nconst TOUCH_ACTION_COMPUTE = 'compute';\nconst TOUCH_ACTION_AUTO = 'auto';\nconst TOUCH_ACTION_MANIPULATION = 'manipulation'; // not implemented\nconst TOUCH_ACTION_NONE = 'none';\nconst TOUCH_ACTION_PAN_X = 'pan-x';\nconst TOUCH_ACTION_PAN_Y = 'pan-y';\nconst TOUCH_ACTION_MAP = getTouchActionProps();\n\nexport {\n    PREFIXED_TOUCH_ACTION,\n    NATIVE_TOUCH_ACTION,\n    TOUCH_ACTION_AUTO,\n    TOUCH_ACTION_COMPUTE,\n    TOUCH_ACTION_MANIPULATION,\n    TOUCH_ACTION_NONE,\n    TOUCH_ACTION_PAN_X,\n    TOUCH_ACTION_PAN_Y,\n    TOUCH_ACTION_MAP\n};\n"
  },
  {
    "path": "src/touchactionjs/touchaction-constructor.js",
    "content": "import {\n    TOUCH_ACTION_COMPUTE,\n    TOUCH_ACTION_MAP,\n    NATIVE_TOUCH_ACTION,\n    PREFIXED_TOUCH_ACTION,\n    TOUCH_ACTION_NONE,\n    TOUCH_ACTION_PAN_X,\n    TOUCH_ACTION_PAN_Y\n} from './touchaction-Consts';\nimport {\n    DIRECTION_VERTICAL,\n    DIRECTION_HORIZONTAL\n} from '../inputjs/input-consts';\nimport each from '../utils/each';\nimport boolOrFn from '../utils/bool-or-fn';\nimport inStr from '../utils/in-str';\nimport cleanTouchActions from './clean-touch-actions';\n\n/**\n * @private\n * Touch Action\n * sets the touchAction property or uses the js alternative\n * @param {Manager} manager\n * @param {String} value\n * @constructor\n */\nexport default class TouchAction {\n  constructor(manager, value) {\n    this.manager = manager;\n    this.set(value);\n  }\n\n  /**\n   * @private\n   * set the touchAction value on the element or enable the polyfill\n   * @param {String} value\n   */\n  set(value) {\n    // find out the touch-action by the event handlers\n    if (value === TOUCH_ACTION_COMPUTE) {\n      value = this.compute();\n    }\n\n    if (NATIVE_TOUCH_ACTION && this.manager.element.style && TOUCH_ACTION_MAP[value]) {\n      this.manager.element.style[PREFIXED_TOUCH_ACTION] = value;\n    }\n    this.actions = value.toLowerCase().trim();\n  }\n\n  /**\n   * @private\n   * just re-set the touchAction value\n   */\n  update() {\n    this.set(this.manager.options.touchAction);\n  }\n\n  /**\n   * @private\n   * compute the value for the touchAction property based on the recognizer's settings\n   * @returns {String} value\n   */\n  compute() {\n    let actions = [];\n    each(this.manager.recognizers, (recognizer) => {\n      if (boolOrFn(recognizer.options.enable, [recognizer])) {\n        actions = actions.concat(recognizer.getTouchAction());\n      }\n    });\n    return cleanTouchActions(actions.join(' '));\n  }\n\n  /**\n   * @private\n   * this method is called on each input cycle and provides the preventing of the browser behavior\n   * @param {Object} input\n   */\n  preventDefaults(input) {\n    let { srcEvent } = input;\n    let direction = input.offsetDirection;\n\n    // if the touch action did prevented once this session\n    if (this.manager.session.prevented) {\n      srcEvent.preventDefault();\n      return;\n    }\n\n    let { actions } = this;\n    let hasNone = inStr(actions, TOUCH_ACTION_NONE) && !TOUCH_ACTION_MAP[TOUCH_ACTION_NONE];\n    let hasPanY = inStr(actions, TOUCH_ACTION_PAN_Y) && !TOUCH_ACTION_MAP[TOUCH_ACTION_PAN_Y];\n    let hasPanX = inStr(actions, TOUCH_ACTION_PAN_X) && !TOUCH_ACTION_MAP[TOUCH_ACTION_PAN_X];\n\n    if (hasNone) {\n      // do not prevent defaults if this is a tap gesture\n      let isTapPointer = input.pointers.length === 1;\n      let isTapMovement = input.distance < 2;\n      let isTapTouchTime = input.deltaTime < 250;\n\n      if (isTapPointer && isTapMovement && isTapTouchTime) {\n        return;\n      }\n    }\n\n    if (hasPanX && hasPanY) {\n      // `pan-x pan-y` means browser handles all scrolling/panning, do not prevent\n      return;\n    }\n\n    if (hasNone ||\n        (hasPanY && direction & DIRECTION_HORIZONTAL) ||\n        (hasPanX && direction & DIRECTION_VERTICAL)) {\n      return this.preventSrc(srcEvent);\n    }\n  }\n\n  /**\n   * @private\n   * call preventDefault to prevent the browser's default behavior (scrolling in most cases)\n   * @param {Object} srcEvent\n   */\n  preventSrc(srcEvent) {\n    this.manager.session.prevented = true;\n    srcEvent.preventDefault();\n  }\n}\n"
  },
  {
    "path": "src/utils/add-event-listeners.js",
    "content": "import each from './each';\nimport splitStr from './split-str';\n/**\n * @private\n * addEventListener with multiple events at once\n * @param {EventTarget} target\n * @param {String} types\n * @param {Function} handler\n */\nexport default function addEventListeners(target, types, handler) {\n  each(splitStr(types), (type) => {\n    target.addEventListener(type, handler, false);\n  });\n}\n"
  },
  {
    "path": "src/utils/assign.js",
    "content": "/**\n * @private\n * extend object.\n * means that properties in dest will be overwritten by the ones in src.\n * @param {Object} target\n * @param {...Object} objects_to_assign\n * @returns {Object} target\n */\nlet assign;\nif (typeof Object.assign !== 'function') {\n  assign = function assign(target) {\n    if (target === undefined || target === null) {\n      throw new TypeError('Cannot convert undefined or null to object');\n    }\n\n    let output = Object(target);\n    for (let index = 1; index < arguments.length; index++) {\n      const source = arguments[index];\n      if (source !== undefined && source !== null) {\n        for (const nextKey in source) {\n          if (source.hasOwnProperty(nextKey)) {\n            output[nextKey] = source[nextKey];\n          }\n        }\n      }\n    }\n    return output;\n  };\n} else {\n  assign = Object.assign;\n}\n\nexport default assign;\n"
  },
  {
    "path": "src/utils/bind-fn.js",
    "content": "/**\n * @private\n * simple function bind\n * @param {Function} fn\n * @param {Object} context\n * @returns {Function}\n */\nexport default function bindFn(fn, context) {\n  return function boundFn() {\n    return fn.apply(context, arguments);\n  };\n}\n"
  },
  {
    "path": "src/utils/bool-or-fn.js",
    "content": "import { TYPE_FUNCTION } from './utils-consts';\n/**\n * @private\n * let a boolean value also be a function that must return a boolean\n * this first item in args will be used as the context\n * @param {Boolean|Function} val\n * @param {Array} [args]\n * @returns {Boolean}\n */\nexport default function boolOrFn(val, args) {\n  if (typeof val === TYPE_FUNCTION) {\n    return val.apply(args ? args[0] || undefined : undefined, args);\n  }\n  return val;\n}\n"
  },
  {
    "path": "src/utils/deprecate.js",
    "content": "/**\n * @private\n * wrap a method with a deprecation warning and stack trace\n * @param {Function} method\n * @param {String} name\n * @param {String} message\n * @returns {Function} A new function wrapping the supplied method.\n */\nexport default function deprecate(method, name, message) {\n  let deprecationMessage = `DEPRECATED METHOD: ${name}\\n${message} AT \\n`;\n  return function() {\n    let e = new Error('get-stack-trace');\n    let stack = e && e.stack ? e.stack.replace(/^[^\\(]+?[\\n$]/gm, '')\n        .replace(/^\\s+at\\s+/gm, '')\n        .replace(/^Object.<anonymous>\\s*\\(/gm, '{anonymous}()@') : 'Unknown Stack Trace';\n\n    let log = window.console && (window.console.warn || window.console.log);\n    if (log) {\n      log.call(window.console, deprecationMessage, stack);\n    }\n    return method.apply(this, arguments);\n  };\n}\n"
  },
  {
    "path": "src/utils/each.js",
    "content": "/**\n * @private\n * walk objects and arrays\n * @param {Object} obj\n * @param {Function} iterator\n * @param {Object} context\n */\nexport default function each(obj, iterator, context) {\n  let i;\n\n  if (!obj) {\n    return;\n  }\n\n  if (obj.forEach) {\n    obj.forEach(iterator, context);\n  } else if (obj.length !== undefined) {\n    i = 0;\n    while (i < obj.length) {\n      iterator.call(context, obj[i], i, obj);\n      i++;\n    }\n  } else {\n    for (i in obj) {\n      obj.hasOwnProperty(i) && iterator.call(context, obj[i], i, obj);\n    }\n  }\n}\n"
  },
  {
    "path": "src/utils/extend.js",
    "content": "import deprecate from './deprecate';\n/**\n * @private\n * extend object.\n * means that properties in dest will be overwritten by the ones in src.\n * @param {Object} dest\n * @param {Object} src\n * @param {Boolean} [merge=false]\n * @returns {Object} dest\n */\nconst extend = deprecate((dest, src, merge) => {\n  let keys = Object.keys(src);\n  let i = 0;\n  while (i < keys.length) {\n    if (!merge || (merge && dest[keys[i]] === undefined)) {\n      dest[keys[i]] = src[keys[i]];\n    }\n    i++;\n  }\n  return dest;\n}, 'extend', 'Use `assign`.');\n\nexport default extend;\n"
  },
  {
    "path": "src/utils/get-window-for-element.js",
    "content": "/**\n * @private\n * get the window object of an element\n * @param {HTMLElement} element\n * @returns {DocumentView|Window}\n */\nexport default function getWindowForElement(element) {\n  let doc = element.ownerDocument || element;\n  return (doc.defaultView || doc.parentWindow || window);\n}\n"
  },
  {
    "path": "src/utils/has-parent.js",
    "content": "/**\n * @private\n * find if a node is in the given parent\n * @method hasParent\n * @param {HTMLElement} node\n * @param {HTMLElement} parent\n * @return {Boolean} found\n */\nexport default function hasParent(node, parent) {\n  while (node) {\n    if (node === parent) {\n      return true;\n    }\n    node = node.parentNode;\n  }\n  return false;\n}\n"
  },
  {
    "path": "src/utils/if-undefined.js",
    "content": "/**\n * @private\n * use the val2 when val1 is undefined\n * @param {*} val1\n * @param {*} val2\n * @returns {*}\n */\nexport default function ifUndefined(val1, val2) {\n  return (val1 === undefined) ? val2 : val1;\n}\n"
  },
  {
    "path": "src/utils/in-array.js",
    "content": "/**\n * @private\n * find if a array contains the object using indexOf or a simple polyFill\n * @param {Array} src\n * @param {String} find\n * @param {String} [findByKey]\n * @return {Boolean|Number} false when not found, or the index\n */\nexport default function inArray(src, find, findByKey) {\n  if (src.indexOf && !findByKey) {\n    return src.indexOf(find);\n  } else {\n    let i = 0;\n    while (i < src.length) {\n      if ((findByKey && src[i][findByKey] == find) || (!findByKey && src[i] === find)) {// do not use === here, test fails\n        return i;\n      }\n      i++;\n    }\n    return -1;\n  }\n}\n"
  },
  {
    "path": "src/utils/in-str.js",
    "content": "/**\n * @private\n * small indexOf wrapper\n * @param {String} str\n * @param {String} find\n * @returns {Boolean} found\n */\nexport default function inStr(str, find) {\n  return str.indexOf(find) > -1;\n}\n"
  },
  {
    "path": "src/utils/inherit.js",
    "content": "import assign from './assign';\n/**\n * @private\n * simple class inheritance\n * @param {Function} child\n * @param {Function} base\n * @param {Object} [properties]\n */\nexport default function inherit(child, base, properties) {\n  let baseP = base.prototype;\n  let childP;\n\n  childP = child.prototype = Object.create(baseP);\n  childP.constructor = child;\n  childP._super = baseP;\n\n  if (properties) {\n    assign(childP, properties);\n  }\n}\n"
  },
  {
    "path": "src/utils/invoke-array-arg.js",
    "content": "import each from './each';\n/**\n * @private\n * if the argument is an array, we want to execute the fn on each entry\n * if it aint an array we don't want to do a thing.\n * this is used by all the methods that accept a single and array argument.\n * @param {*|Array} arg\n * @param {String} fn\n * @param {Object} [context]\n * @returns {Boolean}\n */\nexport default function invokeArrayArg(arg, fn, context) {\n  if (Array.isArray(arg)) {\n    each(arg, context[fn], context);\n    return true;\n  }\n  return false;\n}\n"
  },
  {
    "path": "src/utils/merge.js",
    "content": "import deprecate from './deprecate';\nimport extend from './extend';\n/**\n * @private\n * merge the values from src in the dest.\n * means that properties that exist in dest will not be overwritten by src\n * @param {Object} dest\n * @param {Object} src\n * @returns {Object} dest\n */\nconst merge = deprecate((dest, src) => {\n  return extend(dest, src, true);\n}, 'merge', 'Use `assign`.');\n\nexport default merge;\n"
  },
  {
    "path": "src/utils/prefixed.js",
    "content": "import { VENDOR_PREFIXES } from './utils-consts';\n/**\n * @private\n * get the prefixed property\n * @param {Object} obj\n * @param {String} property\n * @returns {String|Undefined} prefixed\n */\nexport default function prefixed(obj, property) {\n  let prefix;\n  let prop;\n  let camelProp = property[0].toUpperCase() + property.slice(1);\n\n  let i = 0;\n  while (i < VENDOR_PREFIXES.length) {\n    prefix = VENDOR_PREFIXES[i];\n    prop = (prefix) ? prefix + camelProp : property;\n\n    if (prop in obj) {\n      return prop;\n    }\n    i++;\n  }\n  return undefined;\n}\n"
  },
  {
    "path": "src/utils/remove-event-listeners.js",
    "content": "import each from './each';\nimport splitStr from './split-str';\n/**\n * @private\n * removeEventListener with multiple events at once\n * @param {EventTarget} target\n * @param {String} types\n * @param {Function} handler\n */\nexport default function removeEventListeners(target, types, handler) {\n  each(splitStr(types), (type) => {\n    target.removeEventListener(type, handler, false);\n  });\n}\n"
  },
  {
    "path": "src/utils/set-timeout-context.js",
    "content": "import bindFn from './bind-fn';\n\n/**\n * @private\n * set a timeout with a given scope\n * @param {Function} fn\n * @param {Number} timeout\n * @param {Object} context\n * @returns {number}\n */\nexport default function setTimeoutContext(fn, timeout, context) {\n  return setTimeout(bindFn(fn, context), timeout);\n}\n"
  },
  {
    "path": "src/utils/split-str.js",
    "content": "/**\n * @private\n * split string on whitespace\n * @param {String} str\n * @returns {Array} words\n */\n\nexport default function splitStr(str) {\n  return str.trim().split(/\\s+/g);\n}\n"
  },
  {
    "path": "src/utils/to-array.js",
    "content": "/**\n * @private\n * convert array-like objects to real arrays\n * @param {Object} obj\n * @returns {Array}\n */\nexport default function toArray(obj) {\n  return Array.prototype.slice.call(obj, 0);\n}\n"
  },
  {
    "path": "src/utils/unique-array.js",
    "content": "import inArray from './in-array';\n\n/**\n * @private\n * unique array with objects based on a key (like 'id') or just by the array's value\n * @param {Array} src [{id:1},{id:2},{id:1}]\n * @param {String} [key]\n * @param {Boolean} [sort=False]\n * @returns {Array} [{id:1},{id:2}]\n */\nexport default function uniqueArray(src, key, sort) {\n  let results = [];\n  let values = [];\n  let i = 0;\n\n  while (i < src.length) {\n    let val = key ? src[i][key] : src[i];\n    if (inArray(values, val) < 0) {\n      results.push(src[i]);\n    }\n    values[i] = val;\n    i++;\n  }\n\n  if (sort) {\n    if (!key) {\n      results = results.sort();\n    } else {\n      results = results.sort((a, b) => {\n        return a[key] > b[key];\n      });\n    }\n  }\n\n  return results;\n}\n"
  },
  {
    "path": "src/utils/unique-id.js",
    "content": "/**\n * @private\n * get a unique id\n * @returns {number} uniqueId\n */\nlet _uniqueId = 1;\nexport default function uniqueId() {\n  return _uniqueId++;\n}\n"
  },
  {
    "path": "src/utils/utils-consts.js",
    "content": "const VENDOR_PREFIXES = ['', 'webkit', 'Moz', 'MS', 'ms', 'o'];\nconst TEST_ELEMENT = document.createElement('div');\n\nconst TYPE_FUNCTION = 'function';\n\nconst { round, abs } = Math;\nconst { now } = Date;\n\nexport {\n    VENDOR_PREFIXES,\n    TEST_ELEMENT,\n    TYPE_FUNCTION,\n    round,\n    abs,\n    now\n};\n"
  },
  {
    "path": "string-replace.js",
    "content": "const fs = require('fs');\nconst pkg = require('./package.json');\n\nlet hammer = fs.readFileSync('hammer.js', 'utf8');\nhammer = hammer.replace(/{{PKG_VERSION}}/g, pkg.version);\n\nfs.writeFile('hammer.js', hammer, 'utf8', (err) => {\n  if (err) {\n    throw err;\n  }\n  console.log('String Replaced!');\n});\n"
  },
  {
    "path": "tests/manual/assets/style.css",
    "content": "@import url(http://fonts.googleapis.com/css?family=Open+Sans);\n\n*, *:after, *:before {\n    box-sizing: border-box;\n    -moz-box-sizing: border-box;\n}\n\nhtml, body {\n    margin: 0;\n    padding: 0;\n    height: 100%;\n    min-height: 100%;\n    background: #eee;\n    font: 13px/1.5em 'Open Sans', Helvetica, Arial, sans-serif;\n}\n\na {\n    color: #4986e7;\n}\n\n.bg1, .green { background: #42d692; }\n.bg2, .blue { background: #4986e7; }\n.bg3, .red { background: #d06b64; }\n.bg4, .purple { background: #cd74e6; }\n.bg5, .azure { background: #9fe1e7; }\n\nbody {\n    margin: 20px;\n}\n\npre {\n    background: #fff;\n    padding: 20px;\n    margin-bottom: 20px;\n}\n\n.container {\n    max-width: 900px;\n    margin: 0 auto;\n}\n\n.clear { clear: both; }\n"
  },
  {
    "path": "tests/manual/compute_touch_action.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n    <meta name=\"viewport\" content=\"width=device-width, user-scalable=no\">\n    <title></title>\n</head>\n<body>\n    Open the inspector and play a bit with the touchAction property.\n    <script src=\"../../hammer.min.js\"></script>\n    <script>\n        var mc = new Hammer(document.body);\n        mc.add(new Hammer.Swipe({ direction: Hammer.DIRECTION_HORIZONTAL }));\n        mc.add(new Hammer.Pan({ direction: Hammer.DIRECTION_HORIZONTAL }));\n\n        console.log(document.body.style.touchAction)\n    </script>\n</body>\n</html>\n"
  },
  {
    "path": "tests/manual/input.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n    <meta charset=\"UTF-8\">\n    <meta name=\"viewport\" content=\"width=device-width, user-scalable=no, initial-scale=1, maximum-scale=1\">\n    <meta name=\"msapplication-tap-highlight\" content=\"no\"/>\n    <link rel=\"stylesheet\" href=\"assets/style.css\">\n    <title>Hammer.js</title>\n</head>\n<body>\n    <div class=\"container\">\n        <div id=\"hit\" class=\"bg1\" style=\"padding: 30px; height: 200px;\">\n        </div>\n\n        <pre id=\"debug\" style=\"overflow:hidden; background: #eee; padding: 15px;\"></pre>\n\n        <pre id=\"log\" style=\"overflow:hidden;\"></pre>\n    </div>\n    <script src=\"../../hammer.js\"></script>\n    <script>\n\n        Object.prototype.toDirString = function() {\n            var output = [];\n            for(var key in this) {\n                if(this.hasOwnProperty(key)) {\n                    var value = this[key];\n                    if(Array.isArray(value)) {\n                        value = \"Array(\"+ value.length +\"):\"+ value;\n                    } else if(value instanceof HTMLElement) {\n                        value = value +\" (\"+ value.outerHTML.substring(0, 50) +\"...)\";\n                    }\n                    output.push(key +\": \"+ value);\n                }\n            }\n            return output.join(\"\\n\")\n        };\n\n        var el = document.querySelector(\"#hit\");\n        var log = document.querySelector(\"#log\");\n        var debug = document.querySelector(\"#debug\");\n\n        var mc = new Hammer(el);\n        mc.get('pinch').set({ enable: true });\n\n        mc.on(\"hammer.input\", function(ev) {\n            debug.innerHTML = [ev.srcEvent.type, ev.pointers.length, ev.isFinal, ev.deltaX, ev.deltaY].join(\"<br>\");\n        });\n\n    </script>\n</body>\n</html>\n"
  },
  {
    "path": "tests/manual/log.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n    <meta charset=\"UTF-8\">\n    <meta name=\"viewport\" content=\"width=device-width, user-scalable=no, initial-scale=1, maximum-scale=1\">\n    <link rel=\"stylesheet\" href=\"assets/style.css\">\n    <title>Hammer.js</title>\n</head>\n<body>\n    <div class=\"container\">\n\n        <div id=\"hit\" class=\"bg1\" style=\"padding: 30px;\">\n            <span id=\"target\" class=\"bg5\" style=\"display: block; height: 100px;\"></span>\n        </div>\n\n        <pre id=\"debug\" style=\"overflow:hidden; background: #eee; padding: 15px;\"></pre>\n\n        <pre id=\"log\" style=\"overflow:hidden;\"></pre>\n\n    </div>\n    <script src=\"../../hammer.min.js\"></script>\n    <script>\n\n        Object.prototype.toDirString = function() {\n            var output = [];\n            for(var key in this) {\n                if(this.hasOwnProperty(key)) {\n                    var value = this[key];\n                    if(Array.isArray(value)) {\n                        value = \"Array(\"+ value.length +\"):\"+ value;\n                    } else if(value instanceof HTMLElement) {\n                        value = value +\" (\"+ value.outerHTML.substring(0, 50) +\"...)\";\n                    }\n                    output.push(key +\": \"+ value);\n                }\n            }\n            return output.join(\"\\n\")\n        };\n\n\n        var el = document.querySelector(\"#hit\");\n        var log = document.querySelector(\"#log\");\n        var debug = document.querySelector(\"#debug\");\n\n        var mc = new Hammer(el);\n        mc.get('pinch').set({ enable: true });\n        mc.get('rotate').set({ enable: true });\n        mc.on(\"swipe pan panstart panmove panend pancancel multipan press pressup pinch rotate tap doubletap\",\n                logGesture);\n\n        function DEBUG(str) {\n            debug.textContent = str;\n        }\n        function logGesture(ev) {\n            console.log(ev.timeStamp, ev.type, ev);\n            log.textContent = ev.toDirString();\n        }\n\n    </script>\n</body>\n</html>\n"
  },
  {
    "path": "tests/manual/multiple.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n    <meta charset=\"UTF-8\">\n    <meta name=\"viewport\" content=\"width=device-width, user-scalable=no, initial-scale=1, maximum-scale=1\">\n    <link rel=\"stylesheet\" href=\"assets/style.css\">\n    <title>Hammer.js</title>\n    <style>\n\n        #right,\n        #left {\n            display: block;\n            width: 50%;\n            height: 500px;\n            overflow: hidden;\n        }\n\n        #left { float: left; }\n        #right { float: right; }\n\n    </style>\n</head>\n<body>\n    <div class=\"container\">\n        <pre id=\"left\" class=\"bg1\"></pre>\n        <pre id=\"right\" class=\"bg5\"></pre>\n\n        <div class=\"clear\"></div>\n\n        <h1>Multiple instances the same time</h1>\n        <p>You can run multiple instances of Hammer on your page and they will recognize each completely isolated\n            from each other. This makes it possible to build multi-user interfaces.</p>\n\n    </div>\n    <script src=\"../../hammer.min.js\"></script>\n    <script>\n\n        Object.prototype.toDirString = function() {\n            var output = [];\n            for(var key in this) {\n                if(this.hasOwnProperty(key)) {\n                    var value = this[key];\n                    if(Array.isArray(value)) {\n                        value = \"Array(\"+ value.length +\"):\"+ value;\n                    } else if(value instanceof HTMLElement) {\n                        value = value +\" (\"+ value.outerHTML.substring(0, 50) +\"...)\";\n                    }\n                    output.push(key +\": \"+ value);\n                }\n            }\n            return output.join(\"\\n\")\n        };\n\n\n        function addHammer(el) {\n            var mc = new Hammer(el, { multiUser: true });\n            mc.get('pan').set({ direction: Hammer.DIRECTION_ALL });\n            mc.get('swipe').set({ direction: Hammer.DIRECTION_ALL });\n            mc.get('pinch').set({ enable: true });\n            mc.get('rotate').set({ enable: true });\n\n            mc.on(\"swipe pan press pinch rotate tap doubletap\", function (ev) {\n                ev.preventDefault();\n                el.innerText = ev.toDirString();\n            });\n        }\n\n        addHammer(document.querySelector(\"#left\"));\n        addHammer(document.querySelector(\"#right\"));\n\n    </script>\n</body>\n</html>\n"
  },
  {
    "path": "tests/manual/nested.html",
    "content": "<!DOCTYPE html>\n<html>\n<head lang=\"en\">\n    <meta charset=\"UTF-8\">\n    <meta name=\"viewport\" content=\"width=device-width, user-scalable=no, initial-scale=1, maximum-scale=1\">\n    <meta name=\"msapplication-tap-highlight\" content=\"no\"/>\n    <link rel=\"stylesheet\" href=\"assets/style.css\">\n    <title>Hammer.js</title>\n    <style>\n\n        .container {\n            max-width: 900px;\n            margin: 0 auto;\n        }\n\n        .panes.wrapper {\n            max-height: 400px;\n            max-width: 800px;\n            background: #666;\n            margin: 40px auto;\n        }\n\n        .panes {\n            width: 100%;\n            height: 100%;\n            overflow: hidden;\n            position: relative;\n        }\n\n        .pane {\n            width: 100%;\n            height: 100%;\n            position: absolute;\n            left: 0;\n            top: 0;\n            text-align: center;\n            font: bold 60px/250px 'Open Sans', Helvetica, Arial, sans-serif;\n            color: #fff;\n        }\n\n        .panes.animate > .pane {\n            transition: all .3s;\n            -webkit-transition: all .3s;\n        }\n\n    </style>\n\n</head>\n<body>\n\n    <div class=\"panes wrapper\">\n        <div class=\"pane bg1\">\n            <div class=\"panes\">\n                <div class=\"pane\" style=\"background: rgba(0,0,0,0);\">1.1</div>\n                <div class=\"pane\" style=\"background: rgba(0,0,0,.2);\">1.2</div>\n                <div class=\"pane\" style=\"background: rgba(0,0,0,.4);\">1.3</div>\n                <div class=\"pane\" style=\"background: rgba(0,0,0,.6);\">1.4</div>\n                <div class=\"pane\" style=\"background: rgba(0,0,0,.8);\">1.5</div>\n            </div>\n        </div>\n        <div class=\"pane bg2\">\n            <div class=\"panes\">\n                <div class=\"pane\" style=\"background: rgba(0,0,0,0);\">2.1</div>\n                <div class=\"pane\" style=\"background: rgba(0,0,0,.2);\">2.2</div>\n                <div class=\"pane\" style=\"background: rgba(0,0,0,.4);\">2.3</div>\n                <div class=\"pane\" style=\"background: rgba(0,0,0,.6);\">2.4</div>\n                <div class=\"pane\" style=\"background: rgba(0,0,0,.8);\">2.5</div>\n            </div>\n        </div>\n        <div class=\"pane bg3\">\n            <div class=\"panes\">\n                <div class=\"pane\" style=\"background: rgba(0,0,0,0);\">3.1</div>\n                <div class=\"pane\" style=\"background: rgba(0,0,0,.2);\">3.2</div>\n                <div class=\"pane\" style=\"background: rgba(0,0,0,.4);\">3.3</div>\n                <div class=\"pane\" style=\"background: rgba(0,0,0,.6);\">3.4</div>\n                <div class=\"pane\" style=\"background: rgba(0,0,0,.8);\">3.5</div>\n            </div>\n        </div>\n        <div class=\"pane bg4\">\n            <div class=\"panes\">\n                <div class=\"pane\" style=\"background: rgba(0,0,0,0);\">4.1</div>\n                <div class=\"pane\" style=\"background: rgba(0,0,0,.2);\">4.2</div>\n                <div class=\"pane\" style=\"background: rgba(0,0,0,.4);\">4.3</div>\n                <div class=\"pane\" style=\"background: rgba(0,0,0,.6);\">4.4</div>\n                <div class=\"pane\" style=\"background: rgba(0,0,0,.8);\">4.5</div>\n            </div>\n        </div>\n        <div class=\"pane bg5\">\n            <div class=\"panes\">\n                <div class=\"pane\" style=\"background: rgba(0,0,0,0);\">5.1</div>\n                <div class=\"pane\" style=\"background: rgba(0,0,0,.2);\">5.2</div>\n                <div class=\"pane\" style=\"background: rgba(0,0,0,.4);\">5.3</div>\n                <div class=\"pane\" style=\"background: rgba(0,0,0,.6);\">5.4</div>\n                <div class=\"pane\" style=\"background: rgba(0,0,0,.8);\">5.5</div>\n            </div>\n        </div>\n    </div>\n\n    <div class=\"container\">\n        <h1>Nested Pan recognizers</h1>\n\n        <p>Nested recognizers are possible with some threshold and with use of <code>requireFailure()</code>.</p>\n    </div>\n\n    <script src=\"../../hammer.js\"></script>\n    <script>\n\n        var reqAnimationFrame = (function() {\n            return window[Hammer.prefixed(window, \"requestAnimationFrame\")] || function(callback) {\n                setTimeout(callback, 1000 / 60);\n            }\n        })();\n\n        function dirProp(direction, hProp, vProp) {\n            return (direction & Hammer.DIRECTION_HORIZONTAL) ? hProp : vProp\n        }\n\n\n        /**\n         * Carousel\n         * @param container\n         * @param direction\n         * @constructor\n         */\n        function HammerCarousel(container, direction) {\n            this.container = container;\n            this.direction = direction;\n\n            this.panes = Array.prototype.slice.call(this.container.children, 0);\n            this.containerSize = this.container[dirProp(direction, 'offsetWidth', 'offsetHeight')];\n\n            this.currentIndex = 0;\n\n            this.hammer = new Hammer.Manager(this.container);\n            this.hammer.add(new Hammer.Pan({ direction: this.direction, threshold: 10 }));\n            this.hammer.on(\"panstart panmove panend pancancel\", Hammer.bindFn(this.onPan, this));\n\n            this.show(this.currentIndex);\n        }\n\n\n        HammerCarousel.prototype = {\n            /**\n             * show a pane\n             * @param {Number} showIndex\n             * @param {Number} [percent] percentage visible\n             * @param {Boolean} [animate]\n             */\n            show: function(showIndex, percent, animate){\n                showIndex = Math.max(0, Math.min(showIndex, this.panes.length - 1));\n                percent = percent || 0;\n\n                var className = this.container.className;\n                if(animate) {\n                    if(className.indexOf('animate') === -1) {\n                        this.container.className += ' animate';\n                    }\n                } else {\n                    if(className.indexOf('animate') !== -1) {\n                        this.container.className = className.replace('animate', '').trim();\n                    }\n                }\n\n                var paneIndex, pos, translate;\n                for (paneIndex = 0; paneIndex < this.panes.length; paneIndex++) {\n                    pos = (this.containerSize / 100) * (((paneIndex - showIndex) * 100) + percent);\n                    if(this.direction & Hammer.DIRECTION_HORIZONTAL) {\n                        translate = 'translate3d(' + pos + 'px, 0, 0)';\n                    } else {\n                        translate = 'translate3d(0, ' + pos + 'px, 0)'\n                    }\n                     this.panes[paneIndex].style.transform = translate;\n                     this.panes[paneIndex].style.mozTransform = translate;\n                     this.panes[paneIndex].style.webkitTransform = translate;\n                }\n\n                this.currentIndex = showIndex;\n            },\n\n            /**\n             * handle pan\n             * @param {Object} ev\n             */\n            onPan : function (ev) {\n                var delta = dirProp(this.direction, ev.deltaX, ev.deltaY);\n                var percent = (100 / this.containerSize) * delta;\n                var animate = false;\n\n                if (ev.type == 'panend' || ev.type == 'pancancel') {\n                    if (Math.abs(percent) > 20 && ev.type == 'panend') {\n                        this.currentIndex += (percent < 0) ? 1 : -1;\n                    }\n                    percent = 0;\n                    animate = true;\n                }\n\n                this.show(this.currentIndex, percent, animate);\n            }\n        };\n\n        // the horizontal pane scroller\n        var outer = new HammerCarousel(document.querySelector(\".panes.wrapper\"), Hammer.DIRECTION_HORIZONTAL);\n\n        // each pane should contain a vertical pane scroller\n        Hammer.each(document.querySelectorAll(\".pane .panes\"), function(container) {\n            // setup the inner scroller\n            var inner = new HammerCarousel(container, Hammer.DIRECTION_VERTICAL);\n\n            // only recognize the inner pan when the outer is failing.\n            // they both have a threshold of some px\n            outer.hammer.get('pan').requireFailure(inner.hammer.get('pan'));\n        });\n\n    </script>\n\n</body>\n</html>\n"
  },
  {
    "path": "tests/manual/simulator-googlemaps.html",
    "content": "<!DOCTYPE html>\n<html>\n<head lang=\"en\">\n    <meta name=\"viewport\" content=\"width=device-width, user-scalable=no, initial-scale=1, maximum-scale=1\">\n    <link rel=\"stylesheet\" href=\"assets/style.css\">\n    <title>Hammer.js</title>\n</head>\n<body>\n\n<div class=\"container\">\n    <div id=\"maps\" style=\"height: 500px; margin-bottom: 20px;\"></div>\n\n    <h1>Gestures simulator</h1>\n    <p>Used for unit-testing Hammer.js. To test it on the Google Maps view, you should open your\n        <a href=\"https://developer.chrome.com/devtools/docs/mobile-emulation#emulate-touch-events\">\n        Inspector and emulate a touch-screen.</a>\n        Or just open it on your touch-device.</p>\n    <p>Currently, it only triggers touchEvents.</p>\n</div>\n\n<script src=\"../../node_modules/hammer-simulator/index.js\"></script>\n<script src=\"https://maps.googleapis.com/maps/api/js?v=3.exp\"></script>\n<script>\n\n    Simulator.events.touch.fakeSupport();\n\n    var el, map;\n    var container = document.getElementById('maps');\n    var program = [\n        ['pan', ['deltaX','deltaY']],\n        ['pinch', ['scale']],\n        ['tap', ['pos']],\n        ['swipe', ['deltaX','deltaY']],\n        ['pinch', ['pos','scale']],\n        ['pan', ['pos']],\n        ['rotate', ['pos','rotation']],\n        ['doubleTap', ['pos']],\n        ['pinchRotate', ['pos','scale','rotation']],\n    ];\n\n    function randomRange(min, max) {\n        return Math.random() * (max - min) + min;\n    }\n\n    function randomRangeInt(min, max) {\n        return Math.round(randomRange(min, max));\n    }\n\n    function gestureOption(name) {\n        var max = map.getDiv().offsetWidth * .9;\n        switch(name) {\n            case 'deltaY':\n            case 'deltaX':\n                return randomRangeInt(10, max * .5);\n            case 'pos':\n                return [randomRangeInt(10, max), randomRangeInt(10, max)];\n            case 'scale':\n                return randomRange(.2, 2);\n            case 'rotation':\n                return randomRange(-180, 180);\n        }\n    }\n\n    function walkProgram(done) {\n        var clone = [].concat(program);\n        (function next() {\n            if(clone.length) {\n                var entry = clone.shift();\n                var options = {};\n                for(var i=0; i<entry[1].length; i++) {\n                    options[entry[1][i]] = gestureOption(entry[1][i]);\n                }\n                Simulator.gestures[entry[0]](el, options, next);\n            } else {\n                done();\n            }\n        }());\n    }\n\n    function startSimulator() {\n        walkProgram(startSimulator);\n    }\n\n    (function setupGoogleMaps() {\n        map = new google.maps.Map(container, {\n            zoom: 14,\n            center: new google.maps.LatLng(51.98, 5.91)\n        });\n\n        // collect the target element\n        google.maps.event.addListenerOnce(map, 'idle', function(){\n            el = container.childNodes[0].childNodes[0];\n            startSimulator();\n        });\n    })();\n\n</script>\n\n</body>\n</html>\n"
  },
  {
    "path": "tests/manual/simulator.html",
    "content": "<!DOCTYPE html>\n<html>\n<head lang=\"en\">\n    <meta name=\"viewport\" content=\"width=device-width, user-scalable=no, initial-scale=1, maximum-scale=1\">\n    <link rel=\"stylesheet\" href=\"assets/style.css\">\n    <title>Hammer.js</title>\n</head>\n<body>\n\n<div class=\"container\">\n\n    <div id=\"hit\" class=\"bg4\" style=\"padding: 30px; height: 300px; position: relative;\">\n    </div>\n\n    <pre id=\"debug\" style=\"overflow:hidden; background: #eee; padding: 15px;\"></pre>\n\n    <pre id=\"log\" style=\"overflow:hidden;\"></pre>\n\n</div>\n\n<script src=\"../../node_modules/hammer-simulator/index.js\"></script>\n<script src=\"../../hammer.js\"></script>\n<script>\n\n    var program = [\n        ['pan', ['deltaX','deltaY']],\n        ['pinch', ['scale']],\n        ['tap', ['pos']],\n        ['swipe', ['deltaX','deltaY']],\n        ['pinch', ['pos','scale']],\n        ['pan', ['pos']],\n        ['rotate', ['pos','rotation']],\n        ['doubleTap', ['pos']],\n        ['pinchRotate', ['pos','scale','rotation']],\n    ];\n\n    function randomRange(min, max) {\n        return Math.random() * (max - min) + min;\n    }\n\n    function randomRangeInt(min, max) {\n        return Math.round(randomRange(min, max));\n    }\n\n    function gestureOption(name) {\n        var max = el.offsetWidth * .9;\n        switch(name) {\n            case 'deltaY':\n            case 'deltaX':\n                return randomRangeInt(10, max * .5);\n            case 'pos':\n                return [randomRangeInt(10, max), randomRangeInt(10, max)];\n            case 'scale':\n                return randomRange(.2, 2);\n            case 'rotation':\n                return randomRange(-180, 180);\n        }\n    }\n\n    function walkProgram(done) {\n        var clone = [].concat(program);\n        (function next() {\n            if(clone.length) {\n                var entry = clone.shift();\n                var options = {};\n                for(var i=0; i<entry[1].length; i++) {\n                    options[entry[1][i]] = gestureOption(entry[1][i]);\n                }\n                setTimeout(function() {\n                    log.innerHTML = '';\n                    Simulator.gestures[entry[0]](el, options, next);\n                }, 1000);\n            } else {\n                done();\n            }\n        }());\n    }\n\n    function startSimulator() {\n        walkProgram(startSimulator);\n    }\n\n\n    var el = document.querySelector(\"#hit\");\n    var log = document.querySelector(\"#log\");\n    var debug = document.querySelector(\"#debug\");\n\n    var mc = new Hammer(el);\n    mc.get('pinch').set({ enable: true, threshold:.1 });\n    mc.get('rotate').set({ enable: true });\n    mc.on(\"swipe pan multipan press pinch rotate tap doubletap\", logGesture);\n\n    function logGesture(ev) {\n        log.textContent = ev.toDirString();\n    }\n\n    Object.prototype.toDirString = function() {\n        var output = [];\n        for(var key in this) {\n            if(this.hasOwnProperty(key)) {\n                var value = this[key];\n                if(Array.isArray(value)) {\n                    value = \"Array(\"+ value.length +\"):\"+ value;\n                } else if(value instanceof HTMLElement) {\n                    value = value +\" (\"+ value.outerHTML.substring(0, 50) +\"...)\";\n                }\n                output.push(key +\": \"+ value);\n            }\n        }\n        return output.join(\"\\n\")\n    };\n\n    startSimulator();\n\n</script>\n\n</body>\n</html>\n"
  },
  {
    "path": "tests/manual/touchaction.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n    <meta name=\"viewport\" content=\"width=device-width\">\n    <link rel=\"stylesheet\" href=\"assets/style.css\">\n    <title>Hammer.js</title>\n\n    <style>\n        .tester {\n            margin: 20px 0;\n            padding: 10px;\n            height: 200px;\n            overflow: hidden;\n        }\n\n        .scroll-space {\n            height: 9000px;\n        }\n\n        #native, #no-native {\n            color: #fff;\n            font-weight: bold;\n            font-size: 1.1em;\n            padding: 10px 20px;\n            display: none;\n            margin: 25px 0;\n        }\n\n        .show {\n            display: block !important;\n        }\n\n    </style>\n</head>\n<body>\n\n    <div class=\"container\">\n        <p>Hammer provides a <a href=\"../../src/touchaction.js\">kind of polyfill</a>\n            for the browsers that don't support the <a href=\"http://www.w3.org/TR/pointerevents/#the-touch-action-css-property\">touch-action</a> property.</p>\n\n        <div id=\"native\" class=\"green\">Your browser has support for the touch-action property!</div>\n        <div id=\"no-native\" class=\"red\">Your browser doesn't support the touch-action property,\n            so we use the polyfill.</div>\n\n        <h2>touch-action: auto</h2>\n        <p>Should prevent nothing.</p>\n        <div class=\"tester azure\" id=\"auto\"></div>\n\n        <h2>touch-action: pan-y</h2>\n        <p>Should prevent scrolling on horizontal movement. This is set by default when creating a Hammer instance.</p>\n        <div class=\"tester azure\" id=\"pan-y\"></div>\n\n        <h2>touch-action: pan-x</h2>\n        <p>Should prevent scrolling on vertical movement.</p>\n        <div class=\"tester azure\" id=\"pan-x\"></div>\n\n        <h2>touch-action: pan-x pan-y</h2>\n        <p>Should <strong>not</strong> prevent any scrolling on any movement. Horizontal and vertical scrolling handled by the browser directly.</p>\n        <div class=\"tester azure\" id=\"pan-x-pan-y\"></div>\n\n        <h2>touch-action: none</h2>\n        <p>Should prevent all.</p>\n        <div class=\"tester azure\" id=\"none\"></div>\n    </div>\n    <script src=\"../../hammer.js\"></script>\n    <script>\n        var support = Hammer.prefixed(document.body.style, 'touchAction');\n        document.getElementById(support ? 'native' : 'no-native').className += ' show';\n\n        var touchActions = ['auto', 'pan-y', 'pan-x', 'pan-x pan-y', 'none'];\n        Hammer.each(touchActions, function(touchAction) {\n            var el = document.getElementById(touchAction.replace(\" \", \"-\"));\n\n            var mc = Hammer(el, {\n                touchAction: touchAction\n            });\n            mc.get('pan').set({ direction: Hammer.DIRECTION_ALL });\n            mc.get('pinch').set({ enable: true });\n            mc.get('rotate').set({ enable: true });\n\n            mc.on(\"pan swipe rotate pinch tap doubletap press\", function(ev) {\n                el.textContent = ev.type +\" \"+ el.textContent;\n            });\n        });\n    </script>\n\n    <div class=\"scroll-space\"></div>\n    <p>hi.</p>\n\n</body>\n</html>\n"
  },
  {
    "path": "tests/manual/visual.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n    <meta name=\"viewport\" content=\"width=device-width, user-scalable=no, initial-scale=1, maximum-scale=1\">\n    <link rel=\"stylesheet\" href=\"assets/style.css\">\n    <title>Hammer.js</title>\n\n    <style>\n\n        html, body {\n            overflow: hidden;\n            margin: 0;\n        }\n\n        body {\n            -webkit-perspective: 500;\n            -moz-perspective: 500;\n            perspective: 500;\n        }\n\n        .animate {\n            -webkit-transition: all .3s;\n            -moz-transition: all .3s;\n            transition: all .3s;\n        }\n\n        #hit {\n            padding: 10px;\n        }\n\n        #log {\n            position: absolute;\n            padding: 10px;\n        }\n\n    </style>\n</head>\n<body>\n\n<div id=\"log\"></div>\n<div id=\"hit\" style=\"background: #42d692; width: 150px; height: 150px;\"></div>\n\n\n<script src=\"../../hammer.js\"></script>\n<script>\n\n    var reqAnimationFrame = (function () {\n        return window[Hammer.prefixed(window, 'requestAnimationFrame')] || function (callback) {\n            window.setTimeout(callback, 1000 / 60);\n        };\n    })();\n\n    var log = document.querySelector(\"#log\");\n    var el = document.querySelector(\"#hit\");\n\n    var START_X = Math.round((window.innerWidth - el.offsetWidth) / 2);\n    var START_Y = Math.round((window.innerHeight - el.offsetHeight) / 2);\n\n    var ticking = false;\n    var transform;\n    var timer;\n\n    var mc = new Hammer.Manager(el);\n\n    mc.add(new Hammer.Pan({ threshold: 0, pointers: 0 }));\n\n    mc.add(new Hammer.Swipe()).recognizeWith(mc.get('pan'));\n    mc.add(new Hammer.Rotate({ threshold: 0 })).recognizeWith(mc.get('pan'));\n    mc.add(new Hammer.Pinch({ threshold: 0 })).recognizeWith([mc.get('pan'), mc.get('rotate')]);\n\n    mc.add(new Hammer.Tap({ event: 'doubletap', taps: 2 }));\n    mc.add(new Hammer.Tap());\n\n    mc.on(\"panstart panmove\", onPan);\n    mc.on(\"rotatestart rotatemove\", onRotate);\n    mc.on(\"pinchstart pinchmove\", onPinch);\n    mc.on(\"swipe\", onSwipe);\n    mc.on(\"tap\", onTap);\n    mc.on(\"doubletap\", onDoubleTap);\n\n    mc.on(\"hammer.input\", function(ev) {\n        if(ev.isFinal) {\n            resetElement();\n        }\n    });\n\n\n    function resetElement() {\n        el.className = 'animate';\n        transform = {\n            translate: { x: START_X, y: START_Y },\n            scale: 1,\n            angle: 0,\n            rx: 0,\n            ry: 0,\n            rz: 0\n        };\n\n        requestElementUpdate();\n\n        if (log.textContent.length > 2000) {\n            log.textContent = log.textContent.substring(0, 2000) + \"...\";\n        }\n    }\n\n    function updateElementTransform() {\n        var value = [\n                    'translate3d(' + transform.translate.x + 'px, ' + transform.translate.y + 'px, 0)',\n                    'scale(' + transform.scale + ', ' + transform.scale + ')',\n                    'rotate3d('+ transform.rx +','+ transform.ry +','+ transform.rz +','+  transform.angle + 'deg)'\n        ];\n\n        value = value.join(\" \");\n        el.textContent = value;\n        el.style.webkitTransform = value;\n        el.style.mozTransform = value;\n        el.style.transform = value;\n        ticking = false;\n    }\n\n    function requestElementUpdate() {\n        if(!ticking) {\n            reqAnimationFrame(updateElementTransform);\n            ticking = true;\n        }\n    }\n\n    function logEvent(str) {\n        //log.insertBefore(document.createTextNode(str +\"\\n\"), log.firstChild);\n    }\n\n    function onPan(ev) {\n        el.className = '';\n        transform.translate = {\n            x: START_X + ev.deltaX,\n            y: START_Y + ev.deltaY\n        };\n\n        requestElementUpdate();\n        logEvent(ev.type);\n    }\n\n    var initScale = 1;\n    function onPinch(ev) {\n        if(ev.type == 'pinchstart') {\n            initScale = transform.scale || 1;\n        }\n\n        el.className = '';\n        transform.scale = initScale * ev.scale;\n\n        requestElementUpdate();\n        logEvent(ev.type);\n    }\n\n    var initAngle = 0;\n    function onRotate(ev) {\n        if(ev.type == 'rotatestart') {\n            initAngle = transform.angle || 0;\n        }\n\n        el.className = '';\n        transform.rz = 1;\n        transform.angle = initAngle + ev.rotation;\n        requestElementUpdate();\n        logEvent(ev.type);\n    }\n\n    function onSwipe(ev) {\n        var angle = 50;\n        transform.ry = (ev.direction & Hammer.DIRECTION_HORIZONTAL) ? 1 : 0;\n        transform.rx = (ev.direction & Hammer.DIRECTION_VERTICAL) ? 1 : 0;\n        transform.angle = (ev.direction & (Hammer.DIRECTION_RIGHT | Hammer.DIRECTION_UP)) ? angle : -angle;\n\n        clearTimeout(timer);\n        timer = setTimeout(function () {\n            resetElement();\n        }, 300);\n        requestElementUpdate();\n        logEvent(ev.type);\n    }\n\n    function onTap(ev) {\n        transform.rx = 1;\n        transform.angle = 25;\n\n        clearTimeout(timer);\n        timer = setTimeout(function () {\n            resetElement();\n        }, 200);\n        requestElementUpdate();\n        logEvent(ev.type);\n    }\n\n    function onDoubleTap(ev) {\n        transform.rx = 1;\n        transform.angle = 80;\n\n        clearTimeout(timer);\n        timer = setTimeout(function () {\n            resetElement();\n        }, 500);\n        requestElementUpdate();\n        logEvent(ev.type);\n    }\n\n    resetElement();\n\n</script>\n</body>\n</html>\n"
  },
  {
    "path": "tests/unit/assets/utils.js",
    "content": "var utils = {\n    /**\n     * trigger simple dom event\n     * @param obj\n     * @param name\n     */\n    triggerDomEvent: function(obj, name) {\n        var event = document.createEvent('Event');\n        event.initEvent(name, true, true);\n        obj.dispatchEvent(event);\n    },\n\n\n    createTouchEvent: function(name, x, y, identifier) {\n        var event = document.createEvent('Event');\n        event.initEvent('touch' + name, true, true);\n\n        event.touches = event.targetTouches = [{\n            clientX: x,\n            clientY: y,\n            identifier: identifier || 0\n        }];\n\n        //https://developer.mozilla.org/en-US/docs/Web/API/TouchEvent.changedTouches\n        event.changedTouches = [{\n            clientX: x,\n            clientY: y,\n            identifier: identifier || 0\n        }];\n\n        return event;\n    },\n\n    dispatchTouchEvent: function(el, name, x, y, identifier) {\n        var event = utils.createTouchEvent(name, x, y, identifier);\n        el.dispatchEvent(event);\n    },\n\n    createHitArea: function(parent) {\n        if (parent == null) {\n            parent = document.getElementById('qunit-fixture')\n        }\n        var hitArea = document.createElement('div');\n        hitArea.style.background = '#eee';\n        hitArea.style.height = '300px';\n\n        parent.appendChild(hitArea);\n        return hitArea;\n    }\n};\n"
  },
  {
    "path": "tests/unit/gestures/test_pan.js",
    "content": "// jscs:disable requireArrowFunctions,disallowVar,requireEnhancedObjectLiterals\n/* globals QUnit,Hammer,utils,Simulator */\n\nvar el;\nvar hammer;\n\nQUnit.module('Pan Gesture', {\n    beforeEach: function() {\n        el = document.createElement('div');\n        document.body.appendChild(el);\n\n        hammer = new Hammer(el, { recognizers: [] });\n      },\n    afterEach: function() {\n        document.body.removeChild(el);\n        hammer.destroy();\n      }\n  });\n\nQUnit.test('`panstart` and `panmove` should be recognized', function(assert) {\n    assert.expect(2);\n\n    var panMoveCount = 0;\n    var pan = new Hammer.Pan({ threshold: 1 });\n\n    hammer.add(pan);\n    hammer.on('panstart', function() {\n      assert.ok(true, 'Pan start triggered');\n    });\n    hammer.on('panmove', function() {\n      panMoveCount++;\n    });\n\n    utils.dispatchTouchEvent(el, 'start', 50, 50);\n    utils.dispatchTouchEvent(el, 'move', 70, 50);\n    utils.dispatchTouchEvent(el, 'move', 90, 50);\n\n    assert.equal(panMoveCount, 1, 'exactly one panMove triggered');\n  });\n\nQUnit.test('Pan event flow should be start -> left -> end', function(assert) {\n    var done = assert.async();\n    assert.expect(1);\n    var pan = new Hammer.Pan({ threshold: 1 });\n    hammer.add(pan);\n\n    var eventflow = '';\n    var isCalledPanleft = false;\n    hammer.on('panstart', function() {\n        eventflow += 'start';\n      });\n    hammer.on('panleft', function() {\n        if (!isCalledPanleft) {\n          isCalledPanleft = true;\n          eventflow += 'left';\n        }\n      });\n    hammer.on('panend', function() {\n        eventflow += 'end';\n        isCalledPanleft = true;\n      });\n\n    Simulator.gestures.pan(el, { deltaX: -100, deltaY: 0 }, function() {\n        assert.equal(eventflow, 'startleftend', 'correct event flow');\n        done();\n      });\n  });\n"
  },
  {
    "path": "tests/unit/gestures/test_pinch.js",
    "content": "// jscs:disable requireArrowFunctions,disallowVar,requireEnhancedObjectLiterals\n/* globals QUnit,Hammer,Simulator */\n\nvar el;\nvar hammer;\n\nQUnit.module('Pinch Gesture', {\n    beforeEach: function() {\n        el = document.createElement('div');\n        document.body.appendChild(el);\n\n        hammer = new Hammer(el, { recognizers: [] });\n      },\n    afterEach: function() {\n        document.body.removeChild(el);\n        hammer.destroy();\n      }\n  });\n\nQUnit.test('Pinch event flow should be start -> in -> end', function(assert) {\n    var done = assert.async();\n    assert.expect(1);\n    var pinch = new Hammer.Pinch({ enable: true, threshold: 0.1 });\n    hammer.add(pinch);\n\n    var eventflow = '';\n    var isFiredPinchin = false;\n    hammer.on('pinchstart', function() {\n        eventflow += 'start';\n      });\n    hammer.on('pinchin', function() {\n        if (!isFiredPinchin) {\n          isFiredPinchin = true;\n          eventflow += 'in';\n        }\n      });\n    hammer.on('pinchend', function() {\n        eventflow += 'end';\n        isFiredPinchin = false;\n      });\n\n    Simulator.gestures.pinch(el, { duration: 500, scale: 0.5 }, function() {\n        assert.equal(eventflow, 'startinend', 'correct event flow');\n        done();\n      });\n  });\n"
  },
  {
    "path": "tests/unit/gestures/test_swipe.js",
    "content": "// jscs:disable requireArrowFunctions,disallowVar,requireEnhancedObjectLiterals\n/* globals QUnit,Hammer,utils,Simulator */\n\nvar el;\nvar hammer;\nvar swipeCount = 0;\n\nQUnit.module('Swipe Gesture', {\n    beforeEach: function() {\n        el = utils.createHitArea();\n        hammer = new Hammer(el, { recognizers: [] });\n        swipeCount = 0;\n      },\n    afterEach: function() {\n        hammer.destroy();\n      }\n  });\n\nQUnit.test('swipe can be recognized', function(assert) {\n    assert.expect(1);\n    var done = assert.async();\n    var swipe = new Hammer.Swipe({ threshold: 1 });\n    hammer.add(swipe);\n    hammer.on('swipe', function() {\n        assert.ok(true);\n        done();\n      });\n    Simulator.gestures.swipe(el);\n  });\n"
  },
  {
    "path": "tests/unit/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head lang=\"en\">\n    <meta charset=\"UTF-8\">\n    <title>Tests</title>\n    <link rel=\"stylesheet\" href=\"../../node_modules/qunitjs/qunit/qunit.css\">\n\n    <script src=\"../../node_modules/jquery/dist/jquery.min.js\"></script>\n    <script src=\"../../node_modules/lodash-compat/index.js\"></script>\n    <script src=\"../../node_modules/qunitjs/qunit/qunit.js\"></script>\n    <!--[if !IE]> --><script src=\"../../node_modules/blanket/dist/qunit/blanket.js\"></script><!-- <![endif]-->\n    <script src=\"assets/utils.js\"></script>\n\n    <script src=\"../../node_modules/hammer-simulator/index.js\"></script>\n    <script>\n        Simulator.setType('touch');\n        Simulator.events.touch.fakeSupport();\n    </script>\n\n    <script src=\"../../hammer.js\" data-cover></script>\n</head>\n<body>\n<div id=\"qunit\"></div>\n<div id=\"qunit-fixture\"></div>\n\n<script src=\"test_utils.js\"></script>\n<script src=\"test_enable.js\"></script>\n<script src=\"test_hammer.js\"></script>\n<script src=\"test_events.js\"></script>\n<script src=\"test_nested_gesture_recognizers.js\"></script>\n<script src=\"test_simultaneous_recognition.js\"></script>\n<script src=\"test_propagation_bubble.js\"></script>\n<script src=\"test_gestures.js\"></script>\n<script src=\"test_multiple_taps.js\"></script>\n<script src=\"test_require_failure.js\"></script>\n\n<script src=\"test_jquery_plugin.js\"></script>\n<script src=\"gestures/test_pan.js\"></script>\n<script src=\"gestures/test_pinch.js\"></script>\n<script src=\"gestures/test_swipe.js\"></script>\n\n</body>\n</html>\n"
  },
  {
    "path": "tests/unit/test_enable.js",
    "content": "// jscs:disable requireArrowFunctions,disallowVar,requireEnhancedObjectLiterals\n/* globals QUnit,Hammer,utils */\n/* jshint unused:false */\n\nvar el,\n    hammer,\n    counter;\n\nQUnit.module('Test recognizer enable', {\n    beforeEach: function() {\n        el = utils.createHitArea();\n        hammer = new Hammer.Manager(el, { recognizers: [] });\n        counter = 0;\n      },\n    afterEach: function() {\n        hammer && hammer.destroy();\n      }\n  });\n\nQUnit.test('should disable a recognizer through the `enable` constructor parameter', function(assert) {\n    assert.expect(1);\n    hammer.add(new Hammer.Tap({ enable: false }));\n    hammer.on('tap', function() {\n        counter++;\n      });\n\n    var done = assert.async();\n\n    utils.dispatchTouchEvent(el, 'start', 50, 50);\n    utils.dispatchTouchEvent(el, 'end', 50, 50);\n\n    setTimeout(function() {\n\n      assert.equal(counter, 0, 'counter is zero');\n      done();\n    }, 100);\n  });\n\nQUnit.test('should disable recognizing when the manager is disabled.', function(assert) {\n    assert.expect(1);\n    hammer.set({ enable: false });\n    hammer.add(new Hammer.Tap());\n    hammer.on('tap', function() {\n        counter++;\n      });\n\n    var done = assert.async();\n\n    utils.dispatchTouchEvent(el, 'start', 50, 50);\n    utils.dispatchTouchEvent(el, 'end', 50, 50);\n\n    setTimeout(function() {\n        assert.equal(counter, 0, 'counter is zero');\n        done();\n      }, 100);\n  });\n\nQUnit.test('should toggle a recognizer using the `set` call to the recognizer enable property', function(assert) {\n    assert.expect(2);\n\n    hammer.add(new Hammer.Tap());\n    hammer.on('tap', function() {\n        counter++;\n      });\n\n    utils.dispatchTouchEvent(el, 'start', 50, 50);\n    utils.dispatchTouchEvent(el, 'end', 50, 50);\n    assert.equal(counter, 1);\n\n    hammer.get('tap').set({ enable: false });\n\n    utils.dispatchTouchEvent(el, 'start', 50, 50);\n    utils.dispatchTouchEvent(el, 'end', 50, 50);\n    assert.equal(counter, 1, 'counter is 1');\n  });\n\nQUnit.test('should accept the `enable` constructor parameter as function', function(assert) {\n    assert.expect(2);\n\n    var canRecognizeTap = false;\n\n    var tap = new Hammer.Tap({\n        enable: function() {\n            return canRecognizeTap;\n          }\n      });\n\n    hammer.add(tap);\n    hammer.on('tap', function() {\n        counter++;\n      });\n\n    var done = assert.async();\n    utils.dispatchTouchEvent(el, 'start', 50, 50);\n    utils.dispatchTouchEvent(el, 'end', 50, 50);\n\n    setTimeout(function() {\n        assert.equal(counter, 0, 'counter is zero');\n\n        canRecognizeTap = true;\n\n        utils.dispatchTouchEvent(el, 'start', 50, 50);\n        utils.dispatchTouchEvent(el, 'end', 50, 50);\n\n        assert.equal(counter, 1, 'counter is 1');\n        done();\n      }, 100);\n  });\n\nQUnit.test('should accept a function parameter with `set`', function(assert) {\n    assert.expect(3);\n\n    hammer.add(new Hammer.Tap());\n    hammer.on('tap', function() {\n        counter++;\n      });\n\n    utils.dispatchTouchEvent(el, 'start', 50, 50);\n    utils.dispatchTouchEvent(el, 'end', 50, 50);\n    assert.equal(counter, 1, 'counter is 1');\n\n    var canRecognizeTap = false;\n    hammer.get('tap').set({ enable: function() {\n        return canRecognizeTap;\n      } });\n\n    utils.dispatchTouchEvent(el, 'start', 50, 50);\n    utils.dispatchTouchEvent(el, 'end', 50, 50);\n    assert.equal(counter, 1, 'counter is 1');\n\n    canRecognizeTap = true;\n    utils.dispatchTouchEvent(el, 'start', 50, 50);\n    utils.dispatchTouchEvent(el, 'end', 50, 50);\n    assert.equal(counter, 2, 'counter is 2');\n  });\n\nQUnit.test('should pass the recognizer and optional the input parameter to the `enable` callback', function(assert) {\n    assert.expect(2);\n\n    var tap;\n\n    // The enable function is called initially to setup the touch-action property\n    // at that moment there isn't any input\n    var canEnable = function(recognizer, input) {\n        assert.equal(recognizer, tap, 'recognizer is tap');\n        return true;\n      };\n    tap = new Hammer.Tap({ enable: canEnable });\n    hammer.add(tap);\n\n    utils.dispatchTouchEvent(el, 'start', 50, 50);\n  });\n\nQUnit.test('should toggle based on other object method', function(assert) {\n    assert.expect(2);\n\n    var view = {\n        state: 0,\n        canRecognizeTap: function(recognizer, input) {\n            return this.state !== 0;\n          }\n      };\n\n    hammer.add(new Hammer.Tap({ enable: function(rec, input) {\n        return view.canRecognizeTap(rec, input);\n      } }));\n    hammer.on('tap', function() {\n        counter++;\n      });\n\n    utils.dispatchTouchEvent(el, 'start', 50, 50);\n    utils.dispatchTouchEvent(el, 'end', 50, 50);\n    assert.equal(counter, 0, 'counter is 0');\n\n    view.state = 1;\n    utils.dispatchTouchEvent(el, 'start', 50, 50);\n    utils.dispatchTouchEvent(el, 'end', 50, 50);\n    assert.equal(counter, 1, 'counter is 1');\n  });\n"
  },
  {
    "path": "tests/unit/test_events.js",
    "content": "// jscs:disable requireArrowFunctions,disallowVar,requireEnhancedObjectLiterals\n/* globals QUnit,Hammer,utils,el */\n\nQUnit.module('eventEmitter');\n\nQUnit.test('test the eventemitter', function(assert) {\n    assert.expect(6);\n\n    var ee = new Hammer.Manager(utils.createHitArea());\n    var inputData = {\n        target: document.body,\n        srcEvent: {\n            preventDefault: function() {\n                assert.ok(true, 'preventDefault ref');\n              },\n            target: document.body\n          }\n      };\n\n    function event3Handler() {\n      assert.ok(true, 'emitted event3');\n    }\n\n    ee.on('testEvent1', function() {\n        assert.ok(true, 'emitted event');\n      });\n    ee.on('testEvent2', function(ev) {\n        assert.ok(true, 'emitted event');\n        ev.preventDefault();\n        assert.ok(ev.target === document.body, 'target is the body');\n      });\n    ee.on('testEvent3', event3Handler);\n\n    ee.emit('testEvent1', inputData);\n    ee.emit('testEvent2', inputData);\n    ee.emit('testEvent3', inputData);\n\n    // Unbind testEvent2\n    ee.off('testEvent2');\n    ee.off('testEvent3', event3Handler);\n\n    ee.emit('testEvent1', inputData); // Should trigger testEvent1 again\n    ee.emit('testEvent2', inputData); // Doenst trigger a thing\n    ee.emit('testEvent3', inputData); // Doenst trigger a thing\n\n    // Destroy\n    ee.destroy();\n\n    ee.emit('testEvent1', inputData); // Doenst trigger a thing\n    ee.emit('testEvent2', inputData); // Doenst trigger a thing\n    ee.emit('testEvent3', inputData); // Doenst trigger a thing\n  });\n\n/*\n * Hammer.Manager.off method : exception handling\n */\nQUnit.test('When Hammer.Manager didnt attach an event, `off` method is ignored', function(assert) {\n    var count = 0;\n    var hammer = new Hammer(el, { inputTarget: document.body });\n    hammer.off('swipeleft', function() {\n        count++;\n      });\n    assert.ok(true, 'nothing');\n  });\n"
  },
  {
    "path": "tests/unit/test_gestures.js",
    "content": "// jscs:disable requireArrowFunctions,disallowVar,requireEnhancedObjectLiterals\n/* globals QUnit,Hammer,utils,Simulator */\n\n// TODO: this tests fails because tapRecognizer changes\n// it could be that tapRecognizer setup its BEGAN state and\n// disable the other gesture recognition\nvar el;\nvar hammer;\nvar events;\nvar allGestureEvents = [\n    'tap doubletap press',\n    'pinch pinchin pinchout pinchstart pinchmove pinchend pinchcancel',\n    'rotate rotatestart rotatemove rotateend rotatecancel',\n    'pan panstart panmove panup pandown panleft panright panend pancancel',\n    'swipe swipeleft swiperight swipeup swipedown'\n].join(' ');\n\nQUnit.module('Gesture recognition', {\n    beforeEach: function() {\n        el = utils.createHitArea();\n        hammer = new Hammer(el);\n        hammer.get('pinch')\n            .set({ // Some threshold, since the simulator doesnt stays at scale:1 when rotating\n                enable: true,\n                threshold: 0.1\n              });\n\n        hammer.get('rotate')\n            .set({ enable: true });\n\n        hammer.on(allGestureEvents, function(ev) {\n            events[ ev.type ] = true;\n          });\n        events = {};\n      },\n    afterEach: function() {\n        hammer && hammer.destroy();\n        events = null;\n      }\n  });\n\nQUnit.test('recognize pan', function(assert) {\n    var done = assert.async();\n    assert.expect(1);\n\n    Simulator.gestures.pan(el, { duration: 500, deltaX: 100, deltaY: 0 }, function() {\n        assert.deepEqual(events, {\n            pan: true,\n            panstart: true,\n            panmove: true,\n            panright: true,\n            panend: true\n          }, 'Pan events recognized');\n        done();\n      });\n  });\n\nQUnit.test('recognize press', function(assert) {\n    var done = assert.async();\n    assert.expect(1);\n\n    Simulator.gestures.press(el, null, function() {\n        assert.deepEqual(events, {\n            press: true\n          });\n        done();\n      }, 'only press was recognized');\n  });\n\nQUnit.test('recognize swipe', function(assert) {\n    var done = assert.async();\n    assert.expect(1);\n\n    Simulator.gestures.swipe(el, { duration: 300, deltaX: 400, deltaY: 0 }, function() {\n        assert.deepEqual(events, {\n            pan: true,\n            panstart: true,\n            panmove: true,\n            panright: true,\n            panend: true,\n            swipe: true,\n            swiperight: true\n          }, 'pan and swipe events were recognized');\n        done();\n      });\n  });\n\nQUnit.test('recognize pinch', function(assert) {\n    var done = assert.async();\n    assert.expect(1);\n\n    Simulator.gestures.pinch(el, { duration: 500, scale: 0.5 }, function() {\n        assert.deepEqual(events, {\n            pinch: true,\n            pinchstart: true,\n            pinchmove: true,\n            pinchend: true,\n            pinchin: true\n          }, 'pinch events were recognized');\n        done();\n      });\n  });\n\nQUnit.test('recognize children multitouch pinch', function(assert) {\n    var done = assert.async();\n    assert.expect(1);\n\n    var el1 = utils.createHitArea(el);\n    var el2 = utils.createHitArea(el);\n\n    Simulator.gestures.pinch([ el1, el2 ], { duration: 500, scale: 0.5 }, function() {\n        assert.deepEqual(events, {\n            pinch: true,\n            pinchstart: true,\n            pinchmove: true,\n            pinchend: true,\n            pinchin: true\n          }, 'pinch events on child were recognized');\n        done();\n      });\n  });\n\nQUnit.test('recognize parent-child multitouch pinch', function(assert) {\n    var done = assert.async();\n    assert.expect(1);\n\n    var el1 = utils.createHitArea(el);\n\n    Simulator.gestures.pinch([ el, el1 ], { duration: 100, scale: 0.5 }, function() {\n        assert.deepEqual(events, {\n            pinch: true,\n            pinchstart: true,\n            pinchmove: true,\n            pinchend: true,\n            pinchin: true\n          }, 'Pinch events on parent were recognized');\n        done();\n      });\n  });\n\nQUnit.test('recognize rotate', function(assert) {\n    var done = assert.async();\n    assert.expect(1);\n\n    Simulator.gestures.rotate(el, { duration: 500, scale: 1 }, function() {\n        assert.deepEqual(events, {\n            rotate: true,\n            rotatestart: true,\n            rotatemove: true,\n            rotateend: true\n          }, 'Rotate events recognized');\n        done();\n      });\n  });\n\nQUnit.test('recognize multitouch rotate', function(assert) {\n    var done = assert.async();\n    assert.expect(1);\n\n    var el1 = utils.createHitArea(el);\n\n    Simulator.gestures.rotate([ el, el1 ], { duration: 500, scale: 1 }, function() {\n        assert.deepEqual(events, {\n            rotate: true,\n            rotatestart: true,\n            rotatemove: true,\n            rotateend: true\n          }, 'Rotate events were recognized');\n        done();\n      });\n  });\n\nQUnit.test('recognize rotate and pinch simultaneous', function(assert) {\n    var done = assert.async();\n    assert.expect(1);\n\n    Simulator.gestures.pinchRotate(el, { duration: 500, scale: 2 }, function() {\n        assert.deepEqual(events, {\n            rotate: true,\n            rotatestart: true,\n            rotatemove: true,\n            rotateend: true,\n            pinch: true,\n            pinchstart: true,\n            pinchmove: true,\n            pinchend: true,\n            pinchout: true\n          }, 'Rotate and pinch were recognized together');\n        done();\n      });\n  });\n\nQUnit.test(\"don't recognize pan and swipe when moving down, when only horizontal is allowed\", function(assert) {\n    var done = assert.async();\n    assert.expect(1);\n\n    Simulator.gestures.swipe(el, { duration: 250, deltaX: 0, deltaZ: 200 }, function() {\n        assert.deepEqual(events, { }, 'No events were recognized');\n        done();\n      });\n  });\n\nQUnit.test(\"don't recognize press if duration is too short.\", function(assert) {\n    var done = assert.async();\n    assert.expect(1);\n\n    Simulator.gestures.press(el, { duration: 240 });\n\n    setTimeout(function() {\n        assert.deepEqual(events, { tap: true }, 'Tap gesture has been recognized.');\n        done();\n      }, 275);\n  });\n\nQUnit.test(\"don't recognize tap if duration is too long.\", function(assert) {\n    var done = assert.async();\n    assert.expect(1);\n\n    Simulator.gestures.tap(el, { duration: 255 });\n\n    setTimeout(function() {\n        assert.deepEqual(events, { press: true }, 'Press gesture has been recognized.');\n        done();\n      }, 275);\n  });\n"
  },
  {
    "path": "tests/unit/test_hammer.js",
    "content": "// jscs:disable requireArrowFunctions,disallowVar,requireEnhancedObjectLiterals,requireTemplateStringsForConcatenation,requireArrayDestructuring\n/* globals QUnit,Hammer,utils,Simulator */\n\nvar el, el2,\n    hammer, hammer2;\n\nQUnit.module('Tests', {\n    beforeEach: function() {\n        el = utils.createHitArea();\n        el2 = utils.createHitArea();\n      },\n\n    afterEach: function() {\n        if (hammer) {\n          hammer.destroy();\n          hammer = null;\n        }\n        if (hammer2) {\n          hammer2.destroy();\n          hammer2 = null;\n        }\n      }\n  });\n\n//  since Hammer is now a ES6 Class and we cannot call a class as a function,\n//  it needs a `new` keyword prefixed that makes this Shortcut test kinda Redundant.\n\n// QUnit.test( \"hammer shortcut\", function( assert ) {\n//     assert.expect( 2 );\n//\n//     Hammer.defaults.touchAction = \"pan-y\";\n//     hammer = Hammer( el );\n//\n//     assert.ok( hammer instanceof Hammer.Manager, \"returns an instance of Manager\" );\n//     assert.ok( hammer.touchAction.actions == Hammer.defaults.touchAction, \"set the default touchAction\" );\n// } );\n//\n// QUnit.test( \"hammer shortcut with options\", function( assert ) {\n//     assert.expect( 2 );\n//\n//     hammer = Hammer( el, {\n//         touchAction: \"none\"\n//     } );\n//     assert.ok( hammer instanceof Hammer.Manager, \"returns an instance of Manager\" );\n//     assert.ok( hammer.touchAction.actions == \"none\", \"set the default touchAction\" );\n// } );\n\n/* Creating a hammer instance does not work on the same way\n * when using Hammer or Hammer.Manager.\n *\n * This can confuse developers who read tests to use the library when doc is missing.\n */\nQUnit.test('Hammer and Hammer.Manager constructors work exactly on the same way.', function(assert) {\n    assert.expect(2);\n\n    hammer = new Hammer(el, {});\n    assert.equal(Hammer.defaults.preset.length, hammer.recognizers.length,\n      'Correct number of recognizers by default');\n\n    hammer2 = new Hammer.Manager(el, {});\n    assert.equal(0, hammer2.recognizers.length, 'No default recognizers with manager and empty object');\n  });\n\n/* DOC to disable default recognizers should be added.\n *\n * - Hammer(el).      IMO: Currently, well done.\n * - Hammer(el, {}) . IMO: should disable default recognizers\n * - Hammer(el, {recognizers: null}).      IMO: now, it fails.\n * - Hammer(el, {recognizers: []}).  It works, but it is likely not intuitive.\n */\nQUnit.test('A Hammer instance can be setup to not having default recognizers.', function(assert) {\n    assert.expect(1);\n\n    hammer = new Hammer(el, { recognizers: false });\n    assert.equal(0, hammer.recognizers.length, 'No default recognizers with recognizers false');\n  });\n\n/* The case was when I added a custom tap event which was added to the default\n * recognizers, and my custom tap gesture wasn't working (I do not know exactly the reason),\n * but removing the default recognizers solved the issue.\n */\nQUnit.test('Adding the same recognizer type should remove the old recognizer', function(assert) {\n    assert.expect(4);\n\n    hammer = new Hammer(el);\n\n    assert.ok(!!hammer.get('tap'));\n    assert.equal(7, hammer.recognizers.length, '7 recognizers found');\n\n    var newTap = new Hammer.Tap({ time: 1337 });\n    hammer.add(newTap);\n\n    assert.equal(7, hammer.recognizers.length, '7 recognizers found after adding tap');\n    assert.equal(1337, hammer.get('tap').options.time, 'Time has been updated to reflect new tap');\n  });\n\n/*\n * Swipe gesture:\n * - in this tests, it does not update input.velocity ( always 0)\n * - does not fire swipeleft or swiperight events\n */\nQUnit.test('Swiping to the left should fire swipeleft event', function(assert) {\n    var done = assert.async();\n    assert.expect(2);\n\n    hammer = new Hammer(el, { recognizers: [] });\n    hammer.add(new Hammer.Swipe());\n    hammer.on('swipe swipeleft', function() {\n        assert.ok(true);\n      });\n\n    Simulator.gestures.swipe(el, { pos: [ 300, 300 ], deltaY: 0, deltaX: -200 }, function() {\n        done();\n      });\n  });\n\n/*\n * Input target change\n */\nQUnit.test('Should detect input while on other element', function(assert) {\n    var done = assert.async();\n    assert.expect(1);\n\n    hammer = new Hammer(el, { inputTarget: document.body });\n    hammer.on('tap', function() {\n        assert.ok(true);\n      });\n\n    Simulator.gestures.tap(document.body, null, function() {\n        done();\n      });\n  });\n\n/* Hammer.Manager constructor accepts a \"recognizers\" option in which each\n * element is an array representation of a Recognizer.\n */\nQUnit.test('Hammer.Manager accepts recognizers as arrays.', function(assert) {\n    assert.expect(4);\n\n    hammer = new Hammer.Manager(el, {\n        recognizers: [\n            [ Hammer.Swipe ],\n            [ Hammer.Pinch ],\n            [ Hammer.Rotate ],\n            [ Hammer.Pan, { direction: Hammer.DIRECTION_UP }, [ 'swipe', 'pinch' ], [ 'rotate' ] ]\n        ]\n      });\n    assert.equal(4, hammer.recognizers.length, '4 recognizers found');\n\n    var recognizerActual = hammer.recognizers[ 3 ];\n    assert.equal(recognizerActual.options.direction, Hammer.DIRECTION_UP,\n      'Recognize direction from options');\n    assert.equal(2, Object.keys(recognizerActual.simultaneous).length, '2 simultanious recognizers found');\n    assert.equal(1, recognizerActual.requireFail.length, '1 require failing recognizer found');\n  });\n\n/*\n * Removing a recognizer which cannot be found would errantly remove the last recognizer in the\n * manager's list.\n */\nQUnit.test('Remove non-existent recognizer.', function(assert) {\n    assert.expect(1);\n\n    hammer = new Hammer(el, { recognizers: [] });\n    hammer.add(new Hammer.Swipe());\n    hammer.remove('tap');\n\n    assert.equal(1, hammer.recognizers.length, '1 recognizer found');\n  });\n\nQUnit.test('check whether Hammer.defaults.cssProps is restored', function(assert) {\n    var beforeCssProps = {\n        userSelect: 'text',\n        touchSelect: 'grippers',\n        touchCallout: 'default',\n        contentZooming: 'chained',\n        userDrag: 'element',\n        tapHighlightColor: 'rgba(0, 1, 0, 0)'\n      };\n    var prop;\n    Hammer.each(Hammer.defaults.cssProps, function(value, name) {\n        prop = Hammer.prefixed(el.style, name);\n        if (prop) {\n          el.style[ prop ] = beforeCssProps[ name ];\n        }\n      });\n\n    hammer = new Hammer(el);\n    hammer.destroy();\n    hammer = null;\n    Hammer.each(Hammer.defaults.cssProps, function(value, name) {\n        prop = Hammer.prefixed(el.style, name);\n        if (prop) {\n          assert.equal(el.style[ prop ], beforeCssProps[ name ], 'check if ' + name + ' is restored');\n        }\n      });\n  });\n"
  },
  {
    "path": "tests/unit/test_jquery_plugin.js",
    "content": "// jscs:disable requireArrowFunctions,disallowVar,requireEnhancedObjectLiterals\n/* globals QUnit,Hammer,utils,Simulator,$,jQuery */\n\nvar el, hammer, events;\n\nvar jQueryPluginPath = '../../node_modules/jquery-hammerjs/jquery.hammer.js';\n\nQUnit.module('jQuery plugin', {\n    beforeEach: function() {\n        el = utils.createHitArea();\n        events = {};\n      },\n    afterEach: function() {\n        hammer && hammer.destroy();\n      }\n  });\n\nQUnit.test('trigger pan with jQuery', function(assert) {\n    var done = assert.async();\n    assert.expect(2);\n\n    $.getScript(jQueryPluginPath, function() {\n        jQuery(el).hammer();\n        jQuery(el).bind('panstart pan panmove panright panend', function(ev) {\n            if (ev.gesture) {\n              events[ ev.type ] = true;\n            }\n          });\n\n        Simulator.gestures.pan(el, { deltaX: 50, deltaY: 0 }, function() {\n\n            assert.deepEqual(events, {\n                pan: true,\n                panstart: true,\n                panmove: true,\n                panright: true,\n                panend: true\n              }, 'Pan events recognized');\n\n            assert.ok(jQuery(el).data('hammer') instanceof Hammer.Manager, 'data attribute refers to the instance');\n            done();\n          });\n      });\n  });\n\nQUnit.test('trigger pan without jQuery should still work', function(assert) {\n    var done = assert.async();\n    assert.expect(1);\n    var hammer = new Hammer(el);\n    hammer.on('panstart pan panmove panright panend', function(ev) {\n        events[ev.type] = true;\n      });\n    Simulator.gestures.pan(el, { deltaX: 50, deltaY: 0 }, function() {\n        assert.deepEqual(events, {\n            pan: true,\n            panstart: true,\n            panmove: true,\n            panright: true,\n            panend: true\n          }, 'Pan events recognized');\n        done();\n      });\n  });\n"
  },
  {
    "path": "tests/unit/test_multiple_taps.js",
    "content": "// jscs:disable requireArrowFunctions,disallowVar,requireEnhancedObjectLiterals\n/* globals QUnit,Hammer,utils*/\n\nvar el;\nvar hammer;\n\nvar tripleTapCount = 0;\nvar doubleTapCount = 0;\nvar tapCount = 0;\n\nQUnit.module('Tap delay', {\n    beforeEach: function() {\n        el = utils.createHitArea();\n        hammer = new Hammer(el, { recognizers: [] });\n\n        var tap = new Hammer.Tap();\n        var doubleTap = new Hammer.Tap({ event: 'doubleTap', taps: 2 });\n        var tripleTap = new Hammer.Tap({ event: 'tripleTap', taps: 3 });\n\n        hammer.add([ tripleTap, doubleTap, tap ]);\n\n        tripleTap.recognizeWith([ doubleTap, tap ]);\n        doubleTap.recognizeWith(tap);\n\n        doubleTap.requireFailure(tripleTap);\n        tap.requireFailure([ tripleTap, doubleTap ]);\n\n        tripleTapCount = 0;\n        doubleTapCount = 0;\n        tapCount = 0;\n\n        hammer.on('tap', function() {\n            tapCount++;\n          });\n        hammer.on('doubleTap', function() {\n            doubleTapCount++;\n          });\n        hammer.on('tripleTap', function() {\n            tripleTapCount++;\n          });\n      },\n    afterEach: function() {\n        hammer.destroy();\n      }\n  });\nQUnit.test('When a tripleTap is fired, doubleTap and Tap should not be recognized', function(assert) {\n    var done = assert.async();\n    assert.expect(3);\n\n    utils.dispatchTouchEvent(el, 'start', 50, 50);\n    utils.dispatchTouchEvent(el, 'end', 50, 50);\n\n    utils.dispatchTouchEvent(el, 'start', 50, 50);\n    utils.dispatchTouchEvent(el, 'end', 50, 50);\n\n    utils.dispatchTouchEvent(el, 'start', 50, 50);\n    utils.dispatchTouchEvent(el, 'end', 50, 50);\n\n    setTimeout(function() {\n        assert.equal(tripleTapCount, 1, 'one tripletap event');\n        assert.equal(doubleTapCount, 0, 'no doubletap event');\n        assert.equal(tapCount, 0, 'no singletap event');\n        done();\n      }, 350);\n  });\nQUnit.test('When a doubleTap is fired, tripleTap and Tap should not be recognized', function(assert) {\n    var done = assert.async();\n    assert.expect(3);\n\n    utils.dispatchTouchEvent(el, 'start', 50, 50);\n    utils.dispatchTouchEvent(el, 'end', 50, 50);\n\n    utils.dispatchTouchEvent(el, 'start', 50, 50);\n    utils.dispatchTouchEvent(el, 'end', 50, 50);\n\n    setTimeout(function() {\n        assert.equal(tripleTapCount, 0, 'No tripple taps recognized');\n        assert.equal(doubleTapCount, 1, '1 double tap recognized');\n        assert.equal(tapCount, 0, 'No single taps recognized');\n        done();\n      }, 350);\n  });\n\nQUnit.test('When a tap is fired, tripleTap and doubleTap should not be recognized', function(assert) {\n    var done = assert.async();\n    assert.expect(3);\n\n    utils.dispatchTouchEvent(el, 'start', 50, 50);\n    utils.dispatchTouchEvent(el, 'end', 50, 50);\n\n    setTimeout(function() {\n        assert.equal(tripleTapCount, 0, 'No tripple taps recognized');\n        assert.equal(doubleTapCount, 0, 'No double taps recognized');\n        assert.equal(tapCount, 1, '1 single tap recognized');\n        done();\n      }, 350);\n  });\n"
  },
  {
    "path": "tests/unit/test_nested_gesture_recognizers.js",
    "content": "// jscs:disable requireArrowFunctions,disallowVar,requireEnhancedObjectLiterals\n/* globals QUnit,Hammer,utils*/\n/*jshint -W079 */\n\nvar parent,\n    child,\n    hammerChild,\n    hammerParent;\n\nQUnit.module('Nested gesture recognizers (Tap Child + Pan Parent)', {\n    beforeEach: function() {\n        parent = document.createElement('div');\n        child = document.createElement('div');\n\n        document.getElementById('qunit-fixture').appendChild(parent);\n        parent.appendChild(child);\n\n        hammerParent = new Hammer.Manager(parent, {\n            touchAction: 'none'\n          });\n        hammerChild = new Hammer.Manager(child, {\n            touchAction: 'none'\n          });\n\n        hammerChild.add(new Hammer.Tap());\n        hammerParent.add(new Hammer.Pan({ threshold: 5, pointers: 1 }));\n      },\n    afterEach: function() {\n        hammerChild.destroy();\n        hammerParent.destroy();\n      }\n  });\n\nQUnit.test('Tap on the child', function(assert) {\n    assert.expect(1);\n\n    hammerChild.on('tap', function() {\n        assert.ok(true);\n      });\n    hammerParent.on('tap', function() {\n        throw new Error('tap should not fire on parent');\n      });\n\n    utils.dispatchTouchEvent(child, 'start', 0, 10);\n    utils.dispatchTouchEvent(child, 'end', 0, 10);\n  });\n\nQUnit.test('Panning on the child should fire parent pan and should not fire child tap event', function(assert) {\n    assert.expect(1);\n\n    hammerChild.on('tap', function() {\n        throw new Error('tap should not fire on parent');\n      });\n    hammerParent.on('panend', function() {\n        assert.ok(true);\n      });\n\n    utils.dispatchTouchEvent(child, 'start', 10, 0);\n    utils.dispatchTouchEvent(child, 'move', 20, 0);\n    utils.dispatchTouchEvent(child, 'end', 30, 0);\n\n  });\n\n/*\n // test (optional pointers validation)\n test('Panning with one finger down on child, other on parent', function () {\n expect(1);\n\n var event,\n touches;\n\n hammerParent.on('panend', function () {\n ok(true);\n });\n\n // one finger one child\n utils.dispatchTouchEvent(child, 'start', 10, 0, 0);\n utils.dispatchTouchEvent(parent, 'start', 12, 0, 1);\n\n touches = [\n {clientX: 20, clientY: 0, identifier: 0 },\n {clientX: 20, clientY: 0, identifier: 1 }\n ];\n\n event = document.createEvent('Event');\n event.initEvent('touchmove', true, true);\n event.touches = touches;\n event.changedTouches = touches;\n\n parent.dispatchEvent(event);\n\n touches = [\n {clientX: 30, clientY: 0, identifier: 0 },\n {clientX: 30, clientY: 0, identifier: 1 }\n ];\n\n event = document.createEvent('Event');\n event.initEvent('touchend', true, true);\n event.touches = touches;\n event.changedTouches = touches;\n\n parent.dispatchEvent(event);\n });\n */\n\nvar pressPeriod = 600;\nQUnit.module('Nested gesture recognizers (Press Child + Pan Parent)', {\n    beforeEach: function() {\n        parent = document.createElement('div');\n        child = document.createElement('div');\n\n        document.getElementById('qunit-fixture').appendChild(parent);\n        parent.appendChild(child);\n\n        hammerParent = new Hammer.Manager(parent, {\n            touchAction: 'none'\n          });\n        hammerChild = new Hammer.Manager(child, {\n            touchAction: 'none'\n          });\n\n        hammerChild.add(new Hammer.Press({ time: pressPeriod }));\n        hammerParent.add(new Hammer.Pan({ threshold: 5, pointers: 1 }));\n      },\n    afterEach: function() {\n        hammerChild.destroy();\n        hammerParent.destroy();\n      }\n  });\n\nQUnit.test('Press on the child', function(assert) {\n    assert.expect(1);\n\n    hammerChild.on('press', function() {\n        assert.ok(true);\n      });\n    hammerParent.on('press', function() {\n        throw new Error('press should not fire on parent');\n      });\n\n    utils.dispatchTouchEvent(child, 'start', 0, 10);\n\n    var done = assert.async();\n\n    setTimeout(function() {\n        done();\n      }, pressPeriod);\n  });\n\nQUnit.test('When Press is followed by Pan on the same element, both gestures are recognized', function(assert) {\n    assert.expect(2);\n    hammerChild.on('press', function() {\n        assert.ok(true);\n      });\n    hammerParent.on('panend', function() {\n        assert.ok(true);\n      });\n\n    utils.dispatchTouchEvent(child, 'start', 0, 10);\n    var done = assert.async();\n\n    setTimeout(function() {\n        utils.dispatchTouchEvent(child, 'move', 10, 10);\n        utils.dispatchTouchEvent(child, 'move', 20, 10);\n        utils.dispatchTouchEvent(child, 'move', 30, 10);\n        utils.dispatchTouchEvent(child, 'end', 30, 10);\n\n        done();\n      }, pressPeriod);\n  });\n"
  },
  {
    "path": "tests/unit/test_propagation_bubble.js",
    "content": "// jscs:disable requireArrowFunctions,disallowVar,requireEnhancedObjectLiterals\n/* globals QUnit,Hammer,utils*/\n/*jshint -W079 */\n\nvar parent;\nvar child;\nvar hammerChild;\nvar hammerParent;\n\nQUnit.module('Propagation (Tap in Child and Parent)', {\n    beforeEach: function() {\n        parent = document.createElement('div');\n        child = document.createElement('div');\n\n        document.getElementById('qunit-fixture').appendChild(parent);\n        parent.appendChild(child);\n\n        hammerParent = new Hammer.Manager(parent);\n        hammerChild = new Hammer.Manager(child);\n\n        hammerChild.add(new Hammer.Tap());\n        hammerParent.add(new Hammer.Tap());\n      },\n    afterEach: function() {\n        hammerChild.destroy();\n        hammerParent.destroy();\n      }\n  });\n\nQUnit.test('Tap on the child, fires also the tap event to the parent', function(assert) {\n    assert.expect(2);\n\n    hammerChild.on('tap', function() {\n        assert.ok(true);\n      });\n    hammerParent.on('tap', function() {\n        assert.ok(true);\n      });\n\n    utils.dispatchTouchEvent(child, 'start', 0, 10);\n    utils.dispatchTouchEvent(child, 'end', 0, 10);\n  });\n\nQUnit.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(assert) {\n    assert.expect(1);\n\n    hammerChild.on('tap', function() {\n        assert.ok(true);\n      });\n    hammerParent.on('tap', function() {\n        throw new Error('parent tap gesture should not be recognized');\n      });\n\n    child.addEventListener('touchend', function(ev) {\n        ev.stopPropagation();\n      });\n\n    utils.dispatchTouchEvent(child, 'start', 0, 10);\n    utils.dispatchTouchEvent(child, 'end', 0, 10);\n  });\n"
  },
  {
    "path": "tests/unit/test_require_failure.js",
    "content": "// jscs:disable requireArrowFunctions,disallowVar,requireEnhancedObjectLiterals\n/* globals QUnit,Hammer,utils,Simulator */\n\nvar el;\nvar hammer;\nvar pressPeriod = 200;\nvar pressThreshold = 20;\nvar pressCount = 0;\nvar panStartCount = 0;\nvar swipeCount = 0;\n\nQUnit.module('Require Failure ( Swipe & Press )', {\n    beforeEach: function() {\n        el = utils.createHitArea();\n        hammer = new Hammer(el, { recognizers: [] });\n\n        var swipe = new Hammer.Swipe({ threshold: 1 });\n        var press = new Hammer.Press({ time: pressPeriod, threshold: pressThreshold });\n\n        hammer.add(swipe);\n        hammer.add(press);\n\n        swipe.recognizeWith(press);\n        press.requireFailure(swipe);\n\n        pressCount = 0;\n        swipeCount = 0;\n        hammer.on('press', function() {\n            pressCount++;\n          });\n        hammer.on('swipe', function() {\n            swipeCount++;\n          });\n      },\n    afterEach: function() {\n        hammer.destroy();\n      }\n  });\n\nQUnit.test('When swipe does not recognize the gesture, a press gesture can be fired', function(assert) {\n    var done = assert.async();\n    assert.expect(1);\n\n    utils.dispatchTouchEvent(el, 'start', 50, 50);\n\n    setTimeout(function() {\n        assert.equal(pressCount, 1, '1 press recognized');\n        done();\n      }, pressPeriod + 100);\n  });\n\nQUnit.test('When swipe does recognize the gesture, a press gesture cannot be fired', function(assert) {\n    var done = assert.async();\n    assert.expect(2);\n\n    Simulator.gestures.swipe(el, null, function() {\n      assert.ok(swipeCount > 0, 'swipe gesture should be recognizing');\n\n      assert.equal(pressCount, 0, 'press gesture should not be recognized because swipe gesture is recognizing');\n      done();\n    });\n  });\nQUnit.module('Require Failure ( Pan & Press )', {\n    beforeEach: function() {\n        el = document.createElement('div');\n        document.body.appendChild(el);\n\n        hammer = new Hammer(el, { recognizers: [] });\n\n        var pan = new Hammer.Pan({ threshold: 1 });\n        var press = new Hammer.Press({ time: pressPeriod, threshold: pressThreshold });\n\n        hammer.add([ pan, press ]);\n\n        pan.recognizeWith(press);\n        press.requireFailure(pan);\n\n        pressCount = 0;\n        panStartCount = 0;\n        hammer.on('press', function() {\n            pressCount++;\n          });\n        hammer.on('panstart', function() {\n            panStartCount++;\n          });\n      },\n    afterEach: function() {\n        document.body.removeChild(el);\n        hammer.destroy();\n      }\n  });\n\nQUnit.test('When pan does not recognize the gesture, a press gesture can be fired', function(assert) {\n    var done = assert.async();\n    assert.expect(1);\n\n    utils.dispatchTouchEvent(el, 'start', 50, 50);\n\n    setTimeout(function() {\n      assert.equal(pressCount, 1, '1 press recognized');\n      done();\n    }, pressPeriod + 100);\n  });\n\nQUnit.test('When pan recognizes the gesture, a press gesture cannot be fired', function(assert) {\n    var done = assert.async();\n    assert.expect(2);\n\n    utils.dispatchTouchEvent(el, 'start', 50, 50);\n    utils.dispatchTouchEvent(el, 'move', 50 + pressThreshold / 4, 50);\n\n    setTimeout(function() {\n      assert.ok(panStartCount > 0, 'pan gesture should be recognizing');\n\n      assert.equal(pressCount, 0, 'press gesture should not be recognized because pan gesture is recognizing');\n      done();\n    }, pressPeriod + 100);\n  });\n"
  },
  {
    "path": "tests/unit/test_simultaneous_recognition.js",
    "content": "// jscs:disable requireArrowFunctions,disallowVar,requireEnhancedObjectLiterals\n/* globals QUnit,Hammer,utils*/\n\nvar el;\nvar hammer;\n\nQUnit.module('Simultaenous recognition', {\n    beforeEach: function() {\n        el = utils.createHitArea();\n      },\n    afterEach: function() {\n        hammer && hammer.destroy();\n      }\n  });\n\nQUnit.test('should pinch and pan simultaneously be recognized when enabled', function(assert) {\n    var done = assert.async();\n    assert.expect(4);\n\n    var panCount = 0;\n    var pinchCount = 0;\n\n    hammer = new Hammer.Manager(el, {\n        touchAction: 'none'\n      });\n\n    hammer.add(new Hammer.Pan({ threshold: 5, pointers: 2 }));\n\n    var pinch = new Hammer.Pinch({ threshold: 0, pointers: 2 });\n    hammer.add(pinch);\n    pinch.recognizeWith(hammer.get('pan'));\n\n    hammer.on('panend', function() {\n        panCount++;\n      });\n    hammer.on('pinchend', function() {\n        pinchCount++;\n      });\n\n    var executeGesture = function(cb) {\n        var event, touches;\n\n        touches = [\n            { clientX: 0, clientY: 10, identifier: 0, target: el },\n            { clientX: 10, clientY: 10, identifier: 1, target: el }\n        ];\n\n        event = document.createEvent('Event');\n        event.initEvent('touchstart', true, true);\n        event.touches = touches;\n        event.targetTouches = touches;\n        event.changedTouches = touches;\n        el.dispatchEvent(event);\n\n        setTimeout(function() {\n            touches = [\n                { clientX: 10, clientY: 20, identifier: 0, target: el },\n                { clientX: 20, clientY: 20, identifier: 1, target: el }\n            ];\n\n            event = document.createEvent('Event');\n            event.initEvent('touchmove', true, true);\n            event.touches = touches;\n            event.targetTouches = touches;\n            event.changedTouches = touches;\n\n            el.dispatchEvent(event);\n          }, 100);\n\n        setTimeout(function() {\n            touches = [\n                { clientX: 20, clientY: 30, identifier: 0, target: el },\n                { clientX: 40, clientY: 30, identifier: 1, target: el }\n            ];\n\n            event = document.createEvent('Event');\n            event.initEvent('touchmove', true, true);\n            event.touches = touches;\n            event.targetTouches = touches;\n            event.changedTouches = touches;\n            el.dispatchEvent(event);\n\n            event = document.createEvent('Event');\n            event.initEvent('touchend', true, true);\n            event.touches = touches;\n            event.targetTouches = touches;\n            event.changedTouches = touches;\n            el.dispatchEvent(event);\n\n            cb();\n          }, 200);\n      };\n\n    // 2 gesture will be recognized\n    executeGesture(function() {\n        assert.equal(panCount, 1, '1 pan event recognized');\n        assert.equal(pinchCount, 1, '1 pinch event recognized');\n\n        pinch.dropRecognizeWith(hammer.get('pan'));\n\n        // Only the pan gesture will be recognized\n        executeGesture(function() {\n            assert.equal(panCount, 2, '2 pan events recognized');\n            assert.equal(pinchCount, 1, 'One pinch event recognized');\n\n            done();\n          });\n      });\n  });\n\nQUnit.test('the first gesture should block the following gestures (Tap & DoubleTap)', function(assert) {\n    assert.expect(4);\n\n    var tapCount = 0;\n    var doubleTapCount = 0;\n\n    hammer = new Hammer.Manager(el, {\n        touchAction: 'none'\n      });\n\n    var tap = new Hammer.Tap();\n    var doubleTap = new Hammer.Tap({ event: 'doubletap', taps: 2 });\n\n    hammer.add(tap);\n    hammer.add(doubleTap);\n\n    hammer.on('tap', function() {\n        tapCount++;\n      });\n    hammer.on('doubletap', function() {\n        doubleTapCount++;\n      });\n\n    utils.dispatchTouchEvent(el, 'start', 0, 10);\n    utils.dispatchTouchEvent(el, 'end', 0, 10);\n    utils.dispatchTouchEvent(el, 'start', 0, 10);\n    utils.dispatchTouchEvent(el, 'end', 0, 10);\n\n    assert.equal(tapCount, 2, 'on a double tap gesture, the tap gesture is recognized twice');\n    assert.equal(doubleTapCount, 0, 'double tap gesture is not recognized because the prior tap gesture does not recognize it simultaneously');\n\n    doubleTap.recognizeWith(hammer.get('tap'));\n\n    utils.dispatchTouchEvent(el, 'start', 0, 10);\n    utils.dispatchTouchEvent(el, 'end', 0, 10);\n    utils.dispatchTouchEvent(el, 'start', 0, 10);\n    utils.dispatchTouchEvent(el, 'end', 0, 10);\n\n    assert.equal(tapCount, 4, '4 tap events recognized');\n    assert.equal(doubleTapCount, 1, 'when the tap gesture is configured to work simultaneously, tap & doubleTap can be recognized simultaneously');\n  });\n\nQUnit.test('when disabled, the first gesture should not block gestures  (Tap & DoubleTap )', function(assert) {\n    assert.expect(4);\n\n    var tapCount = 0;\n    var doubleTapCount = 0;\n\n    hammer = new Hammer.Manager(el, {\n        touchAction: 'none'\n      });\n\n    var tap = new Hammer.Tap();\n    var doubleTap = new Hammer.Tap({ event: 'doubletap', taps: 2 });\n\n    hammer.add(tap);\n    hammer.add(doubleTap);\n\n    hammer.on('tap', function() {\n        tapCount++;\n      });\n    hammer.on('doubletap', function() {\n        doubleTapCount++;\n      });\n\n    utils.dispatchTouchEvent(el, 'start', 0, 10);\n    utils.dispatchTouchEvent(el, 'end', 0, 10);\n    utils.dispatchTouchEvent(el, 'start', 0, 10);\n    utils.dispatchTouchEvent(el, 'end', 0, 10);\n\n    assert.equal(tapCount, 2, 'on a double tap gesture, the tap gesture is recognized twice');\n    assert.equal(doubleTapCount, 0, 'double tap gesture is not recognized because the prior tap gesture does not recognize it simultaneously');\n\n    hammer.get('tap').set({ enable: false });\n\n    utils.dispatchTouchEvent(el, 'start', 0, 10);\n    utils.dispatchTouchEvent(el, 'end', 0, 10);\n    utils.dispatchTouchEvent(el, 'start', 0, 10);\n    utils.dispatchTouchEvent(el, 'end', 0, 10);\n\n    assert.equal(tapCount, 2, 'tap gesture should not be recognized when the recognizer is disabled');\n    assert.equal(doubleTapCount, 1, 'when the tap gesture is disabled, doubleTap can be recognized');\n  });\n\nQUnit.test('the first gesture should block the following gestures (DoubleTap & Tap)', function(assert) {\n    assert.expect(4);\n\n    var tapCount = 0;\n    var doubleTapCount = 0;\n\n    hammer = new Hammer.Manager(el, {\n        touchAction: 'none'\n      });\n\n    var tap = new Hammer.Tap();\n    var doubleTap = new Hammer.Tap({ event: 'doubletap', taps: 2 });\n\n    hammer.add(doubleTap);\n    hammer.add(tap);\n\n    hammer.on('tap', function() {\n        tapCount++;\n      });\n    hammer.on('doubletap', function() {\n        doubleTapCount++;\n      });\n\n    utils.dispatchTouchEvent(el, 'start', 0, 10);\n    utils.dispatchTouchEvent(el, 'end', 0, 10);\n    utils.dispatchTouchEvent(el, 'start', 0, 10);\n    utils.dispatchTouchEvent(el, 'end', 0, 10);\n\n    assert.equal(doubleTapCount, 1, 'double tap is recognized');\n    assert.equal(tapCount, 1, 'tap is detected, the doubletap is only catched by the doubletap recognizer');\n\n    // Doubletap and tap together\n    doubleTap.recognizeWith(hammer.get('tap'));\n    doubleTapCount = 0;\n    tapCount = 0;\n\n    utils.dispatchTouchEvent(el, 'start', 0, 10);\n    utils.dispatchTouchEvent(el, 'end', 0, 10);\n    utils.dispatchTouchEvent(el, 'start', 0, 10);\n    utils.dispatchTouchEvent(el, 'end', 0, 10);\n\n    assert.equal(doubleTapCount, 1, '1 double tap recognized');\n    assert.equal(tapCount, 2, 'when the tap gesture is configured to work simultaneously, tap & doubleTap can be recognized simultaneously');\n  });\n"
  },
  {
    "path": "tests/unit/test_utils.js",
    "content": "// jscs:disable requireArrowFunctions,disallowVar,requireEnhancedObjectLiterals\n/* globals QUnit,Hammer,utils,_*/\n\nQUnit.module('utils');\n\n// For the tests, all hammer properties and methods of Hammer are exposed to window.Hammer\n\nQUnit.test('get/set prefixed util', function(assert) {\n    assert.ok(_.isUndefined(Hammer.prefixed(window, 'FakeProperty')), 'non existent property returns undefined');\n\n    window.webkitFakeProperty = 1337;\n    assert.ok(Hammer.prefixed(window, 'FakeProperty') == 'webkitFakeProperty', 'existent prefixed property returns the prefixed name');\n\n    delete window.webkitFakeProperty;\n  });\n\nQUnit.test('fnBind', function(assert) {\n    var context = { a: true };\n\n    Hammer.bindFn(function(b) {\n        assert.ok(this.a === true, 'bindFn scope');\n        assert.ok(b === 123, 'bindFn argument');\n      }, context)(123);\n  });\n\nQUnit.test('Inherit objects', function(assert) {\n    function Base() {\n      this.name = true;\n    }\n\n    function Child() {\n      Base.call(this);\n    }\n\n    Hammer.inherit(Child, Base, {\n        newMethod: function() {\n        }\n      });\n\n    var inst = new Child();\n\n    assert.ok(inst.name == true, 'child has extended from base');\n    assert.ok(inst.newMethod, 'child has a new method');\n    assert.ok(Child.prototype.newMethod, 'child has a new prototype method');\n    assert.ok(inst instanceof Child, 'is instanceof Child');\n    assert.ok(inst instanceof Base, 'is instanceof Base');\n    assert.ok(inst._super === Base.prototype, '_super is ref to prototype of Base');\n  });\n\nQUnit.test('toArray', function(assert) {\n    assert.ok(_.isArray(Hammer.toArray({ 0: true, 1: 'second', length: 2 })), 'converted an array-like object to an array');\n    assert.ok(_.isArray(Hammer.toArray([ true, true ])), 'array stays an array');\n  });\n\nQUnit.test('inArray', function(assert) {\n    assert.ok(Hammer.inArray([ 1, 2, 3, 4, 'hammer' ], 'hammer') === 4, 'found item and returned the index');\n    assert.ok(Hammer.inArray([ 1, 2, 3, 4, 'hammer' ], 'notfound') === -1, 'not found an item and returned -1');\n    assert.ok(Hammer.inArray([\n        { id: 2 },\n        { id: 24 }\n    ], '24', 'id') === 1, 'find by key and return the index');\n    assert.ok(Hammer.inArray([\n        { id: 2 },\n        { id: 24 }\n    ], '22', 'id') === -1, 'not found by key and return -1');\n  });\n\nQUnit.test('splitStr', function(assert) {\n    assert.deepEqual(Hammer.splitStr(' a  b  c d   '), [ 'a', 'b', 'c', 'd' ], 'str split valid');\n  });\n\nQUnit.test('uniqueArray', function(assert) {\n    assert.deepEqual(Hammer.uniqueArray([\n        { id: 1 },\n        { id: 2 },\n        { id: 2 }\n    ], 'id'), [\n        { id: 1 },\n        { id: 2 }\n    ], 'remove duplicate ids');\n  });\n\nQUnit.test('boolOrFn', function(assert) {\n    assert.equal(Hammer.boolOrFn(true), true, 'Passing an boolean');\n    assert.equal(Hammer.boolOrFn(false), false, 'Passing an boolean');\n    assert.equal(Hammer.boolOrFn(function() {\n        return true;\n      }), true, 'Passing an boolean');\n    assert.equal(Hammer.boolOrFn(1), true, 'Passing an integer');\n  });\n\nQUnit.test('hasParent', function(assert) {\n    var parent = document.createElement('div');\n    var child = document.createElement('div');\n\n    document.body.appendChild(parent);\n    parent.appendChild(child);\n\n    assert.equal(Hammer.hasParent(child, parent), true, 'Found parent');\n    assert.equal(Hammer.hasParent(parent, child), false, 'Not in parent');\n\n    document.body.removeChild(parent);\n  });\n\nQUnit.test('each', function(assert) {\n    var object = { hi: true };\n    var array = [ 'a', 'b', 'c' ];\n    var loop;\n\n    loop = false;\n    Hammer.each(object, function(value, key) {\n        if (key == 'hi' && value === true) {\n          loop = true;\n        }\n      });\n    assert.ok(loop, 'object loop');\n\n    loop = 0;\n    Hammer.each(array, function(value) {\n        if (value) {\n          loop++;\n        }\n      });\n    assert.ok(loop == 3, 'array loop');\n\n    loop = 0;\n    array.forEach = null;\n    Hammer.each(array, function(value) {\n        if (value) {\n          loop++;\n        }\n      });\n    assert.ok(loop == 3, 'array loop without Array.forEach');\n  });\n\nQUnit.test('assign', function(assert) {\n    assert.expect(2);\n    assert.deepEqual(\n        Hammer.assign(\n            { a: 1, b: 3 },\n            { b: 2, c: 3 }\n        ),\n        { a: 1, b: 2, c: 3 },\n        'Simple extend'\n    );\n\n    var src = { foo: true };\n    var dest = Hammer.assign({}, src);\n    src.foo = false;\n    assert.deepEqual(dest, { foo: true }, 'Clone reference');\n  });\n\nQUnit.test('test add/removeEventListener', function(assert) {\n    function handleEvent() {\n      assert.ok(true, 'triggered event');\n    }\n\n    assert.expect(2);\n\n    Hammer.addEventListeners(window, 'testEvent1  testEvent2  ', handleEvent);\n    utils.triggerDomEvent(window, 'testEvent1');\n    utils.triggerDomEvent(window, 'testEvent2');\n\n    Hammer.removeEventListeners(window, ' testEvent1 testEvent2 ', handleEvent);\n    utils.triggerDomEvent(window, 'testEvent1');\n    utils.triggerDomEvent(window, 'testEvent2');\n  });\n"
  }
]