From c1c5aa7aee0d26069102661fbb8518d22e9b5f80 Mon Sep 17 00:00:00 2001 From: Arjun Kathuria Date: Fri, 20 May 2016 00:45:43 +0530 Subject: [PATCH 01/61] broke down utils.js into idividual modules with explicit import exports --- src/inputjs/computeInputData.js | 61 +++++++++++++++++++++++++++++ src/inputjs/inputConstructor.js | 3 ++ src/utilsjs/addEventListeners.js | 17 ++++++++ src/utilsjs/assign.js | 36 +++++++++++++++++ src/utilsjs/bindFn.js | 18 +++++++++ src/utilsjs/boolOrFn.js | 19 +++++++++ src/utilsjs/deprecate.js | 28 +++++++++++++ src/utilsjs/each.js | 33 ++++++++++++++++ src/utilsjs/extend.js | 25 ++++++++++++ src/utilsjs/getWindowForElement.js | 10 +++++ src/utilsjs/hasParent.js | 22 +++++++++++ src/utilsjs/inArray.js | 27 +++++++++++++ src/utilsjs/inStr.js | 15 +++++++ src/utilsjs/inherit.js | 24 ++++++++++++ src/utilsjs/invokeArrayArg.js | 22 +++++++++++ src/utilsjs/merge.js | 18 +++++++++ src/utilsjs/prefixed.js | 28 +++++++++++++ src/utilsjs/removeEventListeners.js | 18 +++++++++ src/utilsjs/setTimeoutContext.js | 16 ++++++++ src/utilsjs/splitStr.js | 14 +++++++ src/utilsjs/toArray.js | 14 +++++++ src/utilsjs/uniqueArray.js | 39 ++++++++++++++++++ src/utilsjs/uniqueId.js | 14 +++++++ src/utilsjs/utilsConsts.js | 14 +++++++ 24 files changed, 535 insertions(+) create mode 100644 src/inputjs/computeInputData.js create mode 100644 src/inputjs/inputConstructor.js create mode 100644 src/utilsjs/addEventListeners.js create mode 100644 src/utilsjs/assign.js create mode 100644 src/utilsjs/bindFn.js create mode 100644 src/utilsjs/boolOrFn.js create mode 100644 src/utilsjs/deprecate.js create mode 100644 src/utilsjs/each.js create mode 100644 src/utilsjs/extend.js create mode 100644 src/utilsjs/getWindowForElement.js create mode 100644 src/utilsjs/hasParent.js create mode 100644 src/utilsjs/inArray.js create mode 100644 src/utilsjs/inStr.js create mode 100644 src/utilsjs/inherit.js create mode 100644 src/utilsjs/invokeArrayArg.js create mode 100644 src/utilsjs/merge.js create mode 100644 src/utilsjs/prefixed.js create mode 100644 src/utilsjs/removeEventListeners.js create mode 100644 src/utilsjs/setTimeoutContext.js create mode 100644 src/utilsjs/splitStr.js create mode 100644 src/utilsjs/toArray.js create mode 100644 src/utilsjs/uniqueArray.js create mode 100644 src/utilsjs/uniqueId.js create mode 100644 src/utilsjs/utilsConsts.js diff --git a/src/inputjs/computeInputData.js b/src/inputjs/computeInputData.js new file mode 100644 index 000000000..535c9e543 --- /dev/null +++ b/src/inputjs/computeInputData.js @@ -0,0 +1,61 @@ +/** + * + * Created by arjun on 19/05/16. + */ + +/** + * extend the data with some usable properties like scale, rotate, velocity etc + * @param {Object} manager + * @param {Object} input + */ +function computeInputData(manager, input) { + var session = manager.session; + var pointers = input.pointers; + var pointersLength = pointers.length; + + // store the first input to calculate the distance and direction + if (!session.firstInput) { + session.firstInput = simpleCloneInputData(input); + } + + // to compute scale and rotation we need to store the multiple touches + if (pointersLength > 1 && !session.firstMultiple) { + session.firstMultiple = simpleCloneInputData(input); + } else if (pointersLength === 1) { + session.firstMultiple = false; + } + + var firstInput = session.firstInput; + var firstMultiple = session.firstMultiple; + var offsetCenter = firstMultiple ? firstMultiple.center : firstInput.center; + + var center = input.center = getCenter(pointers); + input.timeStamp = now(); + input.deltaTime = input.timeStamp - firstInput.timeStamp; + + input.angle = getAngle(offsetCenter, center); + input.distance = getDistance(offsetCenter, center); + + computeDeltaXY(session, input); + input.offsetDirection = getDirection(input.deltaX, input.deltaY); + + var overallVelocity = getVelocity(input.deltaTime, input.deltaX, input.deltaY); + input.overallVelocityX = overallVelocity.x; + input.overallVelocityY = overallVelocity.y; + input.overallVelocity = (abs(overallVelocity.x) > abs(overallVelocity.y)) ? overallVelocity.x : overallVelocity.y; + + input.scale = firstMultiple ? getScale(firstMultiple.pointers, pointers) : 1; + input.rotation = firstMultiple ? getRotation(firstMultiple.pointers, pointers) : 0; + + input.maxPointers = !session.prevInput ? input.pointers.length : ((input.pointers.length > + session.prevInput.maxPointers) ? input.pointers.length : session.prevInput.maxPointers); + + computeIntervalInputData(session, input); + + // find the correct target + var target = manager.element; + if (hasParent(input.srcEvent.target, target)) { + target = input.srcEvent.target; + } + input.target = target; +} diff --git a/src/inputjs/inputConstructor.js b/src/inputjs/inputConstructor.js new file mode 100644 index 000000000..2c0931954 --- /dev/null +++ b/src/inputjs/inputConstructor.js @@ -0,0 +1,3 @@ +/** + * Created by arjun on 18/05/16. + */ diff --git a/src/utilsjs/addEventListeners.js b/src/utilsjs/addEventListeners.js new file mode 100644 index 000000000..a01fd039f --- /dev/null +++ b/src/utilsjs/addEventListeners.js @@ -0,0 +1,17 @@ +/** + * Created by arjun on 20/05/16. + */ +import {each} from './each' +/** + * addEventListener with multiple events at once + * @param {EventTarget} target + * @param {String} types + * @param {Function} handler + */ +function addEventListeners(target, types, handler) { + each(splitStr(types), function(type) { + target.addEventListener(type, handler, false); + }); +} + +export {addEventListeners}; diff --git a/src/utilsjs/assign.js b/src/utilsjs/assign.js new file mode 100644 index 000000000..b4ba35bfa --- /dev/null +++ b/src/utilsjs/assign.js @@ -0,0 +1,36 @@ +/** + * Created by arjun on 19/05/16. + */ + +/** + * extend object. + * means that properties in dest will be overwritten by the ones in src. + * @param {Object} target + * @param {...Object} objects_to_assign + * @returns {Object} target + */ +var assign; +if (typeof Object.assign !== 'function') { + assign = function assign(target) { + if (target === undefined || target === null) { + throw new TypeError('Cannot convert undefined or null to object'); + } + + var output = Object(target); + for (var index = 1; index < arguments.length; index++) { + var source = arguments[index]; + if (source !== undefined && source !== null) { + for (var nextKey in source) { + if (source.hasOwnProperty(nextKey)) { + output[nextKey] = source[nextKey]; + } + } + } + } + return output; + }; +} else { + assign = Object.assign; +} + +export {assign} \ No newline at end of file diff --git a/src/utilsjs/bindFn.js b/src/utilsjs/bindFn.js new file mode 100644 index 000000000..404b4ee2e --- /dev/null +++ b/src/utilsjs/bindFn.js @@ -0,0 +1,18 @@ +/** + * + * Created by arjun on 20/05/16. + */ + +/** + * simple function bind + * @param {Function} fn + * @param {Object} context + * @returns {Function} + */ +function bindFn(fn, context) { + return function boundFn() { + return fn.apply(context, arguments); + }; +} + +export {bindFn} diff --git a/src/utilsjs/boolOrFn.js b/src/utilsjs/boolOrFn.js new file mode 100644 index 000000000..d6a4409da --- /dev/null +++ b/src/utilsjs/boolOrFn.js @@ -0,0 +1,19 @@ +/** + * Created by arjun on 20/05/16. + */ +import {TYPE_FUNCTION} from './utilsConsts' +/** + * let a boolean value also be a function that must return a boolean + * this first item in args will be used as the context + * @param {Boolean|Function} val + * @param {Array} [args] + * @returns {Boolean} + */ +function boolOrFn(val, args) { + if (typeof val == TYPE_FUNCTION) { + return val.apply(args ? args[0] || undefined : undefined, args); + } + return val; +} + +export {boolOrFn}; \ No newline at end of file diff --git a/src/utilsjs/deprecate.js b/src/utilsjs/deprecate.js new file mode 100644 index 000000000..0fd903b00 --- /dev/null +++ b/src/utilsjs/deprecate.js @@ -0,0 +1,28 @@ +/** + * Created by arjun on 19/05/16. + */ + +/** + * wrap a method with a deprecation warning and stack trace + * @param {Function} method + * @param {String} name + * @param {String} message + * @returns {Function} A new function wrapping the supplied method. + */ +function deprecate(method, name, message) { + var deprecationMessage = 'DEPRECATED METHOD: ' + name + '\n' + message + ' AT \n'; + return function() { + var e = new Error('get-stack-trace'); + var stack = e && e.stack ? e.stack.replace(/^[^\(]+?[\n$]/gm, '') + .replace(/^\s+at\s+/gm, '') + .replace(/^Object.\s*\(/gm, '{anonymous}()@') : 'Unknown Stack Trace'; + + var log = window.console && (window.console.warn || window.console.log); + if (log) { + log.call(window.console, deprecationMessage, stack); + } + return method.apply(this, arguments); + }; +} + +export {deprecate}; \ No newline at end of file diff --git a/src/utilsjs/each.js b/src/utilsjs/each.js new file mode 100644 index 000000000..a807da408 --- /dev/null +++ b/src/utilsjs/each.js @@ -0,0 +1,33 @@ +/** + * Created by arjun on 19/05/16. + */ + +/** + * walk objects and arrays + * @param {Object} obj + * @param {Function} iterator + * @param {Object} context + */ +function each(obj, iterator, context) { + var i; + + if (!obj) { + return; + } + + if (obj.forEach) { + obj.forEach(iterator, context); + } else if (obj.length !== undefined) { + i = 0; + while (i < obj.length) { + iterator.call(context, obj[i], i, obj); + i++; + } + } else { + for (i in obj) { + obj.hasOwnProperty(i) && iterator.call(context, obj[i], i, obj); + } + } +} + +export {each} \ No newline at end of file diff --git a/src/utilsjs/extend.js b/src/utilsjs/extend.js new file mode 100644 index 000000000..dfdb4c80b --- /dev/null +++ b/src/utilsjs/extend.js @@ -0,0 +1,25 @@ +/** + * Created by arjun on 19/05/16. + */ +import {deprecate} from './deprecate' +/** + * extend object. + * means that properties in dest will be overwritten by the ones in src. + * @param {Object} dest + * @param {Object} src + * @param {Boolean} [merge=false] + * @returns {Object} dest + */ +var extend = deprecate(function extend(dest, src, merge) { + var keys = Object.keys(src); + var i = 0; + while (i < keys.length) { + if (!merge || (merge && dest[keys[i]] === undefined)) { + dest[keys[i]] = src[keys[i]]; + } + i++; + } + return dest; +}, 'extend', 'Use `assign`.'); + +export {extend}; \ No newline at end of file diff --git a/src/utilsjs/getWindowForElement.js b/src/utilsjs/getWindowForElement.js new file mode 100644 index 000000000..5e6ed882e --- /dev/null +++ b/src/utilsjs/getWindowForElement.js @@ -0,0 +1,10 @@ +/** + * get the window object of an element + * @param {HTMLElement} element + * @returns {DocumentView|Window} + */ +function getWindowForElement(element) { + var doc = element.ownerDocument || element; + return (doc.defaultView || doc.parentWindow || window); +} +export {getWindowForElement}; \ No newline at end of file diff --git a/src/utilsjs/hasParent.js b/src/utilsjs/hasParent.js new file mode 100644 index 000000000..a4ae0dcf1 --- /dev/null +++ b/src/utilsjs/hasParent.js @@ -0,0 +1,22 @@ +/** + * Created by arjun on 20/05/16. + */ + +/** + * find if a node is in the given parent + * @method hasParent + * @param {HTMLElement} node + * @param {HTMLElement} parent + * @return {Boolean} found + */ +function hasParent(node, parent) { + while (node) { + if (node == parent) { + return true; + } + node = node.parentNode; + } + return false; +} + +export {hasParent}; diff --git a/src/utilsjs/inArray.js b/src/utilsjs/inArray.js new file mode 100644 index 000000000..2c513f8b1 --- /dev/null +++ b/src/utilsjs/inArray.js @@ -0,0 +1,27 @@ +/** + * Created by arjun on 20/05/16. + */ + +/** + * find if a array contains the object using indexOf or a simple polyFill + * @param {Array} src + * @param {String} find + * @param {String} [findByKey] + * @return {Boolean|Number} false when not found, or the index + */ +function inArray(src, find, findByKey) { + if (src.indexOf && !findByKey) { + return src.indexOf(find); + } else { + var i = 0; + while (i < src.length) { + if ((findByKey && src[i][findByKey] == find) || (!findByKey && src[i] === find)) { + return i; + } + i++; + } + return -1; + } +} + +export {inArray}; \ No newline at end of file diff --git a/src/utilsjs/inStr.js b/src/utilsjs/inStr.js new file mode 100644 index 000000000..1de483bca --- /dev/null +++ b/src/utilsjs/inStr.js @@ -0,0 +1,15 @@ +/** + * Created by arjun on 20/05/16. + */ + +/** + * small indexOf wrapper + * @param {String} str + * @param {String} find + * @returns {Boolean} found + */ +function inStr(str, find) { + return str.indexOf(find) > -1; +} + +export {inStr}; \ No newline at end of file diff --git a/src/utilsjs/inherit.js b/src/utilsjs/inherit.js new file mode 100644 index 000000000..e077ab89d --- /dev/null +++ b/src/utilsjs/inherit.js @@ -0,0 +1,24 @@ +/** + * Created by arjun on 19/05/16. + */ +import {assign} from './assign' +/** + * simple class inheritance + * @param {Function} child + * @param {Function} base + * @param {Object} [properties] + */ +function inherit(child, base, properties) { + var baseP = base.prototype, + childP; + + childP = child.prototype = Object.create(baseP); + childP.constructor = child; + childP._super = baseP; + + if (properties) { + assign(childP, properties); + } +} + +export {inherit} \ No newline at end of file diff --git a/src/utilsjs/invokeArrayArg.js b/src/utilsjs/invokeArrayArg.js new file mode 100644 index 000000000..b4d43f1f6 --- /dev/null +++ b/src/utilsjs/invokeArrayArg.js @@ -0,0 +1,22 @@ +/** + * Created by arjun on 19/05/16. + */ + +/** + * if the argument is an array, we want to execute the fn on each entry + * if it aint an array we don't want to do a thing. + * this is used by all the methods that accept a single and array argument. + * @param {*|Array} arg + * @param {String} fn + * @param {Object} [context] + * @returns {Boolean} + */ +function invokeArrayArg(arg, fn, context) { + if (Array.isArray(arg)) { + each(arg, context[fn], context); + return true; + } + return false; +} + +export {invokeArrayArg}; \ No newline at end of file diff --git a/src/utilsjs/merge.js b/src/utilsjs/merge.js new file mode 100644 index 000000000..a48c32221 --- /dev/null +++ b/src/utilsjs/merge.js @@ -0,0 +1,18 @@ +/** + * Created by arjun on 19/05/16. + */ + +import {deprecate} from './deprecate' +import {extend} from './extend' +/** + * merge the values from src in the dest. + * means that properties that exist in dest will not be overwritten by src + * @param {Object} dest + * @param {Object} src + * @returns {Object} dest + */ +var merge = deprecate(function merge(dest, src) { + return extend(dest, src, true); +}, 'merge', 'Use `assign`.'); + +export {merge}; \ No newline at end of file diff --git a/src/utilsjs/prefixed.js b/src/utilsjs/prefixed.js new file mode 100644 index 000000000..1eb14fa8e --- /dev/null +++ b/src/utilsjs/prefixed.js @@ -0,0 +1,28 @@ +/** + * Created by arjun on 20/05/16. + */ +import {VENDOR_PREFIXES} from './utilsConsts'; +/** + * get the prefixed property + * @param {Object} obj + * @param {String} property + * @returns {String|Undefined} prefixed + */ +function prefixed(obj, property) { + var prefix, prop; + var camelProp = property[0].toUpperCase() + property.slice(1); + + var i = 0; + while (i < VENDOR_PREFIXES.length) { + prefix = VENDOR_PREFIXES[i]; + prop = (prefix) ? prefix + camelProp : property; + + if (prop in obj) { + return prop; + } + i++; + } + return undefined; +} + +export {prefixed}; \ No newline at end of file diff --git a/src/utilsjs/removeEventListeners.js b/src/utilsjs/removeEventListeners.js new file mode 100644 index 000000000..034398aae --- /dev/null +++ b/src/utilsjs/removeEventListeners.js @@ -0,0 +1,18 @@ +/** + * + * Created by arjun on 20/05/16. + */ +import {each} from './each' +/** + * removeEventListener with multiple events at once + * @param {EventTarget} target + * @param {String} types + * @param {Function} handler + */ +function removeEventListeners(target, types, handler) { + each(splitStr(types), function(type) { + target.removeEventListener(type, handler, false); + }); +} + +export {removeEventListeners}; diff --git a/src/utilsjs/setTimeoutContext.js b/src/utilsjs/setTimeoutContext.js new file mode 100644 index 000000000..50dd4d161 --- /dev/null +++ b/src/utilsjs/setTimeoutContext.js @@ -0,0 +1,16 @@ +/** + * Created by arjun on 19/05/16. + */ + +/** + * set a timeout with a given scope + * @param {Function} fn + * @param {Number} timeout + * @param {Object} context + * @returns {number} + */ +function setTimeoutContext(fn, timeout, context) { + return setTimeout(bindFn(fn, context), timeout); +} + +export {setTimeoutContext}; \ No newline at end of file diff --git a/src/utilsjs/splitStr.js b/src/utilsjs/splitStr.js new file mode 100644 index 000000000..d0c510e11 --- /dev/null +++ b/src/utilsjs/splitStr.js @@ -0,0 +1,14 @@ +/** + * Created by arjun on 20/05/16. + */ + +/** + * split string on whitespace + * @param {String} str + * @returns {Array} words + */ +function splitStr(str) { + return str.trim().split(/\s+/g); +} + +export {splitStr}; \ No newline at end of file diff --git a/src/utilsjs/toArray.js b/src/utilsjs/toArray.js new file mode 100644 index 000000000..f5d6503a3 --- /dev/null +++ b/src/utilsjs/toArray.js @@ -0,0 +1,14 @@ +/** + * Created by arjun on 20/05/16. + */ + +/** + * convert array-like objects to real arrays + * @param {Object} obj + * @returns {Array} + */ +function toArray(obj) { + return Array.prototype.slice.call(obj, 0); +} + +export {toArray} \ No newline at end of file diff --git a/src/utilsjs/uniqueArray.js b/src/utilsjs/uniqueArray.js new file mode 100644 index 000000000..1a6b5e497 --- /dev/null +++ b/src/utilsjs/uniqueArray.js @@ -0,0 +1,39 @@ +/** + * Created by arjun on 20/05/16. + */ +import {inArray} from './inArray'; +/** + * unique array with objects based on a key (like 'id') or just by the array's value + * @param {Array} src [{id:1},{id:2},{id:1}] + * @param {String} [key] + * @param {Boolean} [sort=False] + * @returns {Array} [{id:1},{id:2}] + */ +function uniqueArray(src, key, sort) { + var results = []; + var values = []; + var i = 0; + + while (i < src.length) { + var val = key ? src[i][key] : src[i]; + if (inArray(values, val) < 0) { + results.push(src[i]); + } + values[i] = val; + i++; + } + + if (sort) { + if (!key) { + results = results.sort(); + } else { + results = results.sort(function sortUniqueArray(a, b) { + return a[key] > b[key]; + }); + } + } + + return results; +} + +export {uniqueArray}; \ No newline at end of file diff --git a/src/utilsjs/uniqueId.js b/src/utilsjs/uniqueId.js new file mode 100644 index 000000000..ece3fd158 --- /dev/null +++ b/src/utilsjs/uniqueId.js @@ -0,0 +1,14 @@ +/** + * Created by arjun on 20/05/16. + */ + +/** + * get a unique id + * @returns {number} uniqueId + */ +var _uniqueId = 1; +function uniqueId() { + return _uniqueId++; +} + +export {uniqueId}; \ No newline at end of file diff --git a/src/utilsjs/utilsConsts.js b/src/utilsjs/utilsConsts.js new file mode 100644 index 000000000..4b68844cf --- /dev/null +++ b/src/utilsjs/utilsConsts.js @@ -0,0 +1,14 @@ +/** + * Created by arjun on 19/05/16. + */ + +var VENDOR_PREFIXES = ['', 'webkit', 'Moz', 'MS', 'ms', 'o']; +var TEST_ELEMENT = document.createElement('div'); + +var TYPE_FUNCTION = 'function'; + +var round = Math.round; +var abs = Math.abs; +var now = Date.now; + +export {VENDOR_PREFIXES,TEST_ELEMENT,TYPE_FUNCTION,round,abs,now} \ No newline at end of file From eb7c63c834777872fade2e39fcfab3c4992eef23 Mon Sep 17 00:00:00 2001 From: Tomster Date: Mon, 23 May 2016 18:06:54 -0500 Subject: [PATCH 02/61] Initial Commit from Ember CLI v2.6.0-beta.2 _..., ,:^;,...; -+===;. ,,--++====++-,,, .: /....., :::::~+++++#:,+#++++++++++++++++++#*..: /,...... (,,,,,,::=+++##++++++++++++++++++++++#. :....../ ...,,,,,::++++++++++++++++++++++++++++++*..,...: *..+...,#@@@@@@@@@++++++++++++++++++++++#*....* @#,;##############@@@+*+#@@@@@@@@@@#*++#..< *@##@@+,-*^^^*-+@####@@@######@@@#####@@,,,+ @#@* @#@@@@#@@+--*^^*--#@@@@@@# @#@. @# @##+++@#, .@@#@@ #@# @@ +@@++++#@@ @@ :@@ :@#* @#@++++++@#* #@ @@+ :*+@@#;,.__.+@#@+,-^^.++@# @@++ ;* :*@@@##@@@@;++r._j^.+@##@+,.__,,@@++. /* ........+++++++++++++#@@@@@###@@#++++, ,: ...,@@@#++===----==@@@####,,....+++++ .: ......@@##@\ ; :@####@,,...... +++. ; .........@###, ; ;xx#@;,,..... *;+, | ........,*;xxxx--^--=xxx,........ :+#; ; ......,,;xxxxxxxxxxxxx;,..... *+# ; ......,::xxxx;. ...... +. . *; ......... +### .... / ,. /:| ,. .+: ... ;##++##, . ,#. (..v..;*./ ** ## ###* .:*&&&+. \.,....<, #&+**==-..,,__ ;## ### :,*+&&&&&&&v+#&,,.._/ #&&&&*...,::,,. ##; ,##* .*****;:&&&&&&&&& ,+*+;~*..*** *.* ### ###* ******* *+#&;* ##,;## **** :, ** ##### ## ### ###, ######## .##### ;## ## ####### ;## #### ,###. ########## ######## ### #### ### ### ### ########## #### #### ,## ### #######* ### ,### ##############: ## ### #### ,## :#### ### ##; ########## ########### ## .## ,### ####### ##### :###### ###### .###### #### ## ### ### ######* :##### #### ############# #### ################ ######## ### #####* *#* #: :### *###* *#### #* --- .bowerrc | 4 ++ .editorconfig | 34 ++++++++++++ .ember-cli | 9 +++ .gitignore | 17 ++++++ .jshintrc | 32 +++++++++++ .npmignore | 16 ++++++ .travis.yml | 36 ++++++++++++ .watchmanconfig | 3 + LICENSE.md | 9 +++ README.md | 26 +++++++++ addon/.gitkeep | 0 app/.gitkeep | 0 bower.json | 9 +++ config/ember-try.js | 55 +++++++++++++++++++ config/environment.js | 6 ++ ember-cli-build.js | 18 ++++++ index.js | 6 ++ package.json | 51 +++++++++++++++++ testem.js | 13 +++++ tests/.jshintrc | 52 ++++++++++++++++++ tests/dummy/app/app.js | 18 ++++++ tests/dummy/app/components/.gitkeep | 0 tests/dummy/app/controllers/.gitkeep | 0 tests/dummy/app/helpers/.gitkeep | 0 tests/dummy/app/index.html | 25 +++++++++ tests/dummy/app/models/.gitkeep | 0 tests/dummy/app/resolver.js | 3 + tests/dummy/app/router.js | 12 ++++ tests/dummy/app/routes/.gitkeep | 0 tests/dummy/app/styles/app.css | 0 tests/dummy/app/templates/components/.gitkeep | 0 tests/dummy/config/environment.js | 46 ++++++++++++++++ tests/dummy/public/crossdomain.xml | 15 +++++ tests/dummy/public/robots.txt | 3 + tests/helpers/destroy-app.js | 5 ++ tests/helpers/module-for-acceptance.js | 23 ++++++++ tests/helpers/resolver.js | 11 ++++ tests/helpers/start-app.js | 18 ++++++ tests/index.html | 34 ++++++++++++ tests/integration/.gitkeep | 0 tests/test-helper.js | 6 ++ tests/unit/.gitkeep | 0 vendor/.gitkeep | 0 43 files changed, 615 insertions(+) create mode 100644 .bowerrc create mode 100644 .editorconfig create mode 100644 .ember-cli create mode 100644 .gitignore create mode 100644 .jshintrc create mode 100644 .npmignore create mode 100644 .travis.yml create mode 100644 .watchmanconfig create mode 100644 LICENSE.md create mode 100644 README.md create mode 100644 addon/.gitkeep create mode 100644 app/.gitkeep create mode 100644 bower.json create mode 100644 config/ember-try.js create mode 100644 config/environment.js create mode 100644 ember-cli-build.js create mode 100644 index.js create mode 100644 package.json create mode 100644 testem.js create mode 100644 tests/.jshintrc create mode 100644 tests/dummy/app/app.js create mode 100644 tests/dummy/app/components/.gitkeep create mode 100644 tests/dummy/app/controllers/.gitkeep create mode 100644 tests/dummy/app/helpers/.gitkeep create mode 100644 tests/dummy/app/index.html create mode 100644 tests/dummy/app/models/.gitkeep create mode 100644 tests/dummy/app/resolver.js create mode 100644 tests/dummy/app/router.js create mode 100644 tests/dummy/app/routes/.gitkeep create mode 100644 tests/dummy/app/styles/app.css create mode 100644 tests/dummy/app/templates/components/.gitkeep create mode 100644 tests/dummy/config/environment.js create mode 100644 tests/dummy/public/crossdomain.xml create mode 100644 tests/dummy/public/robots.txt create mode 100644 tests/helpers/destroy-app.js create mode 100644 tests/helpers/module-for-acceptance.js create mode 100644 tests/helpers/resolver.js create mode 100644 tests/helpers/start-app.js create mode 100644 tests/index.html create mode 100644 tests/integration/.gitkeep create mode 100644 tests/test-helper.js create mode 100644 tests/unit/.gitkeep create mode 100644 vendor/.gitkeep diff --git a/.bowerrc b/.bowerrc new file mode 100644 index 000000000..959e1696e --- /dev/null +++ b/.bowerrc @@ -0,0 +1,4 @@ +{ + "directory": "bower_components", + "analytics": false +} diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 000000000..47c543840 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,34 @@ +# EditorConfig helps developers define and maintain consistent +# coding styles between different editors and IDEs +# editorconfig.org + +root = true + + +[*] +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true +indent_style = space +indent_size = 2 + +[*.js] +indent_style = space +indent_size = 2 + +[*.hbs] +insert_final_newline = false +indent_style = space +indent_size = 2 + +[*.css] +indent_style = space +indent_size = 2 + +[*.html] +indent_style = space +indent_size = 2 + +[*.{diff,md}] +trim_trailing_whitespace = false diff --git a/.ember-cli b/.ember-cli new file mode 100644 index 000000000..ee64cfed2 --- /dev/null +++ b/.ember-cli @@ -0,0 +1,9 @@ +{ + /** + Ember CLI sends analytics information by default. The data is completely + anonymous, but there are times when you might want to disable this behavior. + + Setting `disableAnalytics` to true will prevent any data from being sent. + */ + "disableAnalytics": false +} diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..86fceae7a --- /dev/null +++ b/.gitignore @@ -0,0 +1,17 @@ +# See http://help.github.com/ignore-files/ for more about ignoring files. + +# compiled output +/dist +/tmp + +# dependencies +/node_modules +/bower_components + +# misc +/.sass-cache +/connect.lock +/coverage/* +/libpeerconnection.log +npm-debug.log +testem.log diff --git a/.jshintrc b/.jshintrc new file mode 100644 index 000000000..08096effa --- /dev/null +++ b/.jshintrc @@ -0,0 +1,32 @@ +{ + "predef": [ + "document", + "window", + "-Promise" + ], + "browser": true, + "boss": true, + "curly": true, + "debug": false, + "devel": true, + "eqeqeq": true, + "evil": true, + "forin": false, + "immed": false, + "laxbreak": false, + "newcap": true, + "noarg": true, + "noempty": false, + "nonew": false, + "nomen": false, + "onevar": false, + "plusplus": false, + "regexp": false, + "undef": true, + "sub": true, + "strict": false, + "white": false, + "eqnull": true, + "esnext": true, + "unused": true +} diff --git a/.npmignore b/.npmignore new file mode 100644 index 000000000..fa8b147ae --- /dev/null +++ b/.npmignore @@ -0,0 +1,16 @@ +/bower_components +/config/ember-try.js +/dist +/tests +/tmp +**/.gitkeep +.bowerrc +.editorconfig +.ember-cli +.gitignore +.jshintrc +.watchmanconfig +.travis.yml +bower.json +ember-cli-build.js +testem.js diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 000000000..00c582286 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,36 @@ +--- +language: node_js +node_js: + - "4" + +sudo: false + +cache: + directories: + - node_modules + +env: + - EMBER_TRY_SCENARIO=default + - EMBER_TRY_SCENARIO=ember-1.13 + - EMBER_TRY_SCENARIO=ember-release + - EMBER_TRY_SCENARIO=ember-beta + - EMBER_TRY_SCENARIO=ember-canary + +matrix: + fast_finish: true + allow_failures: + - env: EMBER_TRY_SCENARIO=ember-canary + +before_install: + - npm config set spin false + - npm install -g bower + - npm install phantomjs-prebuilt + +install: + - npm install + - bower install + +script: + # Usually, it's ok to finish the test scenario without reverting + # to the addon's original dependency state, skipping "cleanup". + - ember try $EMBER_TRY_SCENARIO test --skip-cleanup diff --git a/.watchmanconfig b/.watchmanconfig new file mode 100644 index 000000000..e7834e3e4 --- /dev/null +++ b/.watchmanconfig @@ -0,0 +1,3 @@ +{ + "ignore_dirs": ["tmp", "dist"] +} diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 000000000..02000b56e --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,9 @@ +The MIT License (MIT) + +Copyright (c) 2016 + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 000000000..b9b3ba474 --- /dev/null +++ b/README.md @@ -0,0 +1,26 @@ +# History + +This README outlines the details of collaborating on this Ember addon. + +## Installation + +* `git clone` this repository +* `npm install` +* `bower install` + +## Running + +* `ember server` +* Visit your app at http://localhost:4200. + +## Running Tests + +* `npm test` (Runs `ember try:testall` to test your addon against multiple Ember versions) +* `ember test` +* `ember test --server` + +## Building + +* `ember build` + +For more information on using ember-cli, visit [http://ember-cli.com/](http://ember-cli.com/). diff --git a/addon/.gitkeep b/addon/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/app/.gitkeep b/app/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/bower.json b/bower.json new file mode 100644 index 000000000..5724b2d04 --- /dev/null +++ b/bower.json @@ -0,0 +1,9 @@ +{ + "name": "history", + "dependencies": { + "ember": "~2.6.0-beta.2", + "ember-cli-shims": "0.1.1", + "ember-cli-test-loader": "0.2.2", + "ember-qunit-notifications": "0.1.0" + } +} diff --git a/config/ember-try.js b/config/ember-try.js new file mode 100644 index 000000000..014f603d6 --- /dev/null +++ b/config/ember-try.js @@ -0,0 +1,55 @@ +/*jshint node:true*/ +module.exports = { + scenarios: [ + { + name: 'default', + bower: { + dependencies: { } + } + }, + { + name: 'ember-1.13', + bower: { + dependencies: { + 'ember': '~1.13.0' + }, + resolutions: { + 'ember': '~1.13.0' + } + } + }, + { + name: 'ember-release', + bower: { + dependencies: { + 'ember': 'components/ember#release' + }, + resolutions: { + 'ember': 'release' + } + } + }, + { + name: 'ember-beta', + bower: { + dependencies: { + 'ember': 'components/ember#beta' + }, + resolutions: { + 'ember': 'beta' + } + } + }, + { + name: 'ember-canary', + bower: { + dependencies: { + 'ember': 'components/ember#canary' + }, + resolutions: { + 'ember': 'canary' + } + } + } + ] +}; diff --git a/config/environment.js b/config/environment.js new file mode 100644 index 000000000..28a787b62 --- /dev/null +++ b/config/environment.js @@ -0,0 +1,6 @@ +/*jshint node:true*/ +'use strict'; + +module.exports = function(/* environment, appConfig */) { + return { }; +}; diff --git a/ember-cli-build.js b/ember-cli-build.js new file mode 100644 index 000000000..4ac391379 --- /dev/null +++ b/ember-cli-build.js @@ -0,0 +1,18 @@ +/*jshint node:true*/ +/* global require, module */ +var EmberAddon = require('ember-cli/lib/broccoli/ember-addon'); + +module.exports = function(defaults) { + var app = new EmberAddon(defaults, { + // Add options here + }); + + /* + This build file specifies the options for the dummy test app of this + addon, located in `/tests/dummy` + This build file does *not* influence how the addon or the app using it + behave. You most likely want to be modifying `./index.js` or app's build file + */ + + return app.toTree(); +}; diff --git a/index.js b/index.js new file mode 100644 index 000000000..026832032 --- /dev/null +++ b/index.js @@ -0,0 +1,6 @@ +/* jshint node: true */ +'use strict'; + +module.exports = { + name: 'history' +}; diff --git a/package.json b/package.json new file mode 100644 index 000000000..c154bc9a9 --- /dev/null +++ b/package.json @@ -0,0 +1,51 @@ +{ + "name": "history", + "version": "0.0.0", + "description": "The default blueprint for ember-cli addons.", + "directories": { + "doc": "doc", + "test": "tests" + }, + "scripts": { + "build": "ember build", + "start": "ember server", + "test": "ember try:each" + }, + "repository": "", + "engines": { + "node": ">= 0.10.0" + }, + "author": "", + "license": "MIT", + "devDependencies": { + "broccoli-asset-rev": "^2.4.2", + "ember-ajax": "^2.0.1", + "ember-cli": "2.6.0-beta.2", + "ember-cli-app-version": "^1.0.0", + "ember-cli-dependency-checker": "^1.2.0", + "ember-cli-htmlbars": "^1.0.3", + "ember-cli-htmlbars-inline-precompile": "^0.3.1", + "ember-cli-inject-live-reload": "^1.4.0", + "ember-cli-jshint": "^1.0.0", + "ember-cli-qunit": "^1.4.0", + "ember-cli-release": "0.2.8", + "ember-cli-sri": "^2.1.0", + "ember-cli-uglify": "^1.2.0", + "ember-data": "^2.6.0-beta.1", + "ember-disable-prototype-extensions": "^1.1.0", + "ember-export-application-global": "^1.0.5", + "ember-load-initializers": "^0.5.1", + "ember-resolver": "^2.0.3", + "ember-welcome-page": "^1.0.1", + "loader.js": "^4.0.1" + }, + "keywords": [ + "ember-addon" + ], + "dependencies": { + "ember-cli-babel": "^5.1.6" + }, + "ember-addon": { + "configPath": "tests/dummy/config" + } +} diff --git a/testem.js b/testem.js new file mode 100644 index 000000000..26044b2f8 --- /dev/null +++ b/testem.js @@ -0,0 +1,13 @@ +/*jshint node:true*/ +module.exports = { + "framework": "qunit", + "test_page": "tests/index.html?hidepassed", + "disable_watching": true, + "launch_in_ci": [ + "PhantomJS" + ], + "launch_in_dev": [ + "PhantomJS", + "Chrome" + ] +}; diff --git a/tests/.jshintrc b/tests/.jshintrc new file mode 100644 index 000000000..6ec0b7c15 --- /dev/null +++ b/tests/.jshintrc @@ -0,0 +1,52 @@ +{ + "predef": [ + "document", + "window", + "location", + "setTimeout", + "$", + "-Promise", + "define", + "console", + "visit", + "exists", + "fillIn", + "click", + "keyEvent", + "triggerEvent", + "find", + "findWithAssert", + "wait", + "DS", + "andThen", + "currentURL", + "currentPath", + "currentRouteName" + ], + "node": false, + "browser": false, + "boss": true, + "curly": true, + "debug": false, + "devel": false, + "eqeqeq": true, + "evil": true, + "forin": false, + "immed": false, + "laxbreak": false, + "newcap": true, + "noarg": true, + "noempty": false, + "nonew": false, + "nomen": false, + "onevar": false, + "plusplus": false, + "regexp": false, + "undef": true, + "sub": true, + "strict": false, + "white": false, + "eqnull": true, + "esnext": true, + "unused": true +} diff --git a/tests/dummy/app/app.js b/tests/dummy/app/app.js new file mode 100644 index 000000000..831ad6106 --- /dev/null +++ b/tests/dummy/app/app.js @@ -0,0 +1,18 @@ +import Ember from 'ember'; +import Resolver from './resolver'; +import loadInitializers from 'ember-load-initializers'; +import config from './config/environment'; + +let App; + +Ember.MODEL_FACTORY_INJECTIONS = true; + +App = Ember.Application.extend({ + modulePrefix: config.modulePrefix, + podModulePrefix: config.podModulePrefix, + Resolver +}); + +loadInitializers(App, config.modulePrefix); + +export default App; diff --git a/tests/dummy/app/components/.gitkeep b/tests/dummy/app/components/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/tests/dummy/app/controllers/.gitkeep b/tests/dummy/app/controllers/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/tests/dummy/app/helpers/.gitkeep b/tests/dummy/app/helpers/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/tests/dummy/app/index.html b/tests/dummy/app/index.html new file mode 100644 index 000000000..5120bd73f --- /dev/null +++ b/tests/dummy/app/index.html @@ -0,0 +1,25 @@ + + + + + + Dummy + + + + {{content-for "head"}} + + + + + {{content-for "head-footer"}} + + + {{content-for "body"}} + + + + + {{content-for "body-footer"}} + + diff --git a/tests/dummy/app/models/.gitkeep b/tests/dummy/app/models/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/tests/dummy/app/resolver.js b/tests/dummy/app/resolver.js new file mode 100644 index 000000000..2fb563d6c --- /dev/null +++ b/tests/dummy/app/resolver.js @@ -0,0 +1,3 @@ +import Resolver from 'ember-resolver'; + +export default Resolver; diff --git a/tests/dummy/app/router.js b/tests/dummy/app/router.js new file mode 100644 index 000000000..cdc257875 --- /dev/null +++ b/tests/dummy/app/router.js @@ -0,0 +1,12 @@ +import Ember from 'ember'; +import config from './config/environment'; + +const Router = Ember.Router.extend({ + location: config.locationType, + rootURL: config.rootURL +}); + +Router.map(function() { +}); + +export default Router; diff --git a/tests/dummy/app/routes/.gitkeep b/tests/dummy/app/routes/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/tests/dummy/app/styles/app.css b/tests/dummy/app/styles/app.css new file mode 100644 index 000000000..e69de29bb diff --git a/tests/dummy/app/templates/components/.gitkeep b/tests/dummy/app/templates/components/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/tests/dummy/config/environment.js b/tests/dummy/config/environment.js new file mode 100644 index 000000000..2529939c5 --- /dev/null +++ b/tests/dummy/config/environment.js @@ -0,0 +1,46 @@ +/* jshint node: true */ + +module.exports = function(environment) { + var ENV = { + modulePrefix: 'dummy', + environment: environment, + rootURL: '/', + locationType: 'auto', + EmberENV: { + FEATURES: { + // Here you can enable experimental features on an ember canary build + // e.g. 'with-controller': true + } + }, + + APP: { + // Here you can pass flags/options to your application instance + // when it is created + } + }; + + if (environment === 'development') { + // ENV.APP.LOG_RESOLVER = true; + // ENV.APP.LOG_ACTIVE_GENERATION = true; + // ENV.APP.LOG_TRANSITIONS = true; + // ENV.APP.LOG_TRANSITIONS_INTERNAL = true; + // ENV.APP.LOG_VIEW_LOOKUPS = true; + } + + if (environment === 'test') { + // Testem prefers this... + ENV.locationType = 'none'; + + // keep test console output quieter + ENV.APP.LOG_ACTIVE_GENERATION = false; + ENV.APP.LOG_VIEW_LOOKUPS = false; + + ENV.APP.rootElement = '#ember-testing'; + } + + if (environment === 'production') { + + } + + return ENV; +}; diff --git a/tests/dummy/public/crossdomain.xml b/tests/dummy/public/crossdomain.xml new file mode 100644 index 000000000..0c16a7a07 --- /dev/null +++ b/tests/dummy/public/crossdomain.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + diff --git a/tests/dummy/public/robots.txt b/tests/dummy/public/robots.txt new file mode 100644 index 000000000..f5916452e --- /dev/null +++ b/tests/dummy/public/robots.txt @@ -0,0 +1,3 @@ +# http://www.robotstxt.org +User-agent: * +Disallow: diff --git a/tests/helpers/destroy-app.js b/tests/helpers/destroy-app.js new file mode 100644 index 000000000..c3d4d1abb --- /dev/null +++ b/tests/helpers/destroy-app.js @@ -0,0 +1,5 @@ +import Ember from 'ember'; + +export default function destroyApp(application) { + Ember.run(application, 'destroy'); +} diff --git a/tests/helpers/module-for-acceptance.js b/tests/helpers/module-for-acceptance.js new file mode 100644 index 000000000..76996fd04 --- /dev/null +++ b/tests/helpers/module-for-acceptance.js @@ -0,0 +1,23 @@ +import { module } from 'qunit'; +import Ember from 'ember'; +import startApp from '../helpers/start-app'; +import destroyApp from '../helpers/destroy-app'; + +const { RSVP: { Promise } } = Ember; + +export default function(name, options = {}) { + module(name, { + beforeEach() { + this.application = startApp(); + + if (options.beforeEach) { + return options.beforeEach.apply(this, arguments); + } + }, + + afterEach() { + let afterEach = options.afterEach && options.afterEach.apply(this, arguments); + return Promise.resolve(afterEach).then(() => destroyApp(this.application)); + } + }); +} diff --git a/tests/helpers/resolver.js b/tests/helpers/resolver.js new file mode 100644 index 000000000..b208d38d0 --- /dev/null +++ b/tests/helpers/resolver.js @@ -0,0 +1,11 @@ +import Resolver from '../../resolver'; +import config from '../../config/environment'; + +const resolver = Resolver.create(); + +resolver.namespace = { + modulePrefix: config.modulePrefix, + podModulePrefix: config.podModulePrefix +}; + +export default resolver; diff --git a/tests/helpers/start-app.js b/tests/helpers/start-app.js new file mode 100644 index 000000000..e098f1d5b --- /dev/null +++ b/tests/helpers/start-app.js @@ -0,0 +1,18 @@ +import Ember from 'ember'; +import Application from '../../app'; +import config from '../../config/environment'; + +export default function startApp(attrs) { + let application; + + let attributes = Ember.merge({}, config.APP); + attributes = Ember.merge(attributes, attrs); // use defaults, but you can override; + + Ember.run(() => { + application = Application.create(attributes); + application.setupForTesting(); + application.injectTestHelpers(); + }); + + return application; +} diff --git a/tests/index.html b/tests/index.html new file mode 100644 index 000000000..1c34853da --- /dev/null +++ b/tests/index.html @@ -0,0 +1,34 @@ + + + + + + Dummy Tests + + + + {{content-for "head"}} + {{content-for "test-head"}} + + + + + + {{content-for "head-footer"}} + {{content-for "test-head-footer"}} + + + {{content-for "body"}} + {{content-for "test-body"}} + + + + + + + + + {{content-for "body-footer"}} + {{content-for "test-body-footer"}} + + diff --git a/tests/integration/.gitkeep b/tests/integration/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/tests/test-helper.js b/tests/test-helper.js new file mode 100644 index 000000000..e6cfb70fe --- /dev/null +++ b/tests/test-helper.js @@ -0,0 +1,6 @@ +import resolver from './helpers/resolver'; +import { + setResolver +} from 'ember-qunit'; + +setResolver(resolver); diff --git a/tests/unit/.gitkeep b/tests/unit/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/vendor/.gitkeep b/vendor/.gitkeep new file mode 100644 index 000000000..e69de29bb From eada1262d4b99cda00cc54ed3dd802db7cd18c7d Mon Sep 17 00:00:00 2001 From: Arjun Kathuria Date: Tue, 24 May 2016 23:56:22 +0530 Subject: [PATCH 03/61] Broke down input.js into individual modules with explicit import exports --- src/inputjs/computeDeltaXY.js | 27 ++++++++++++ src/inputjs/computeInputData.js | 16 +++++++ src/inputjs/computeIntervalInputData.js | 43 ++++++++++++++++++ src/inputjs/createInputInstance.js | 31 +++++++++++++ src/inputjs/getAngle.js | 21 +++++++++ src/inputjs/getCenter.js | 34 +++++++++++++++ src/inputjs/getDirection.js | 23 ++++++++++ src/inputjs/getDistance.js | 22 ++++++++++ src/inputjs/getRotation.js | 16 +++++++ src/inputjs/getScale.js | 18 ++++++++ src/inputjs/getVelocity.js | 19 ++++++++ src/inputjs/inputConstructor.js | 58 +++++++++++++++++++++++++ src/inputjs/inputConsts.js | 38 ++++++++++++++++ src/inputjs/inputHandler.js | 40 +++++++++++++++++ src/inputjs/simpleCloneInputData.js | 33 ++++++++++++++ 15 files changed, 439 insertions(+) create mode 100644 src/inputjs/computeDeltaXY.js create mode 100644 src/inputjs/computeIntervalInputData.js create mode 100644 src/inputjs/createInputInstance.js create mode 100644 src/inputjs/getAngle.js create mode 100644 src/inputjs/getCenter.js create mode 100644 src/inputjs/getDirection.js create mode 100644 src/inputjs/getDistance.js create mode 100644 src/inputjs/getRotation.js create mode 100644 src/inputjs/getScale.js create mode 100644 src/inputjs/getVelocity.js create mode 100644 src/inputjs/inputConsts.js create mode 100644 src/inputjs/inputHandler.js create mode 100644 src/inputjs/simpleCloneInputData.js diff --git a/src/inputjs/computeDeltaXY.js b/src/inputjs/computeDeltaXY.js new file mode 100644 index 000000000..967be7af5 --- /dev/null +++ b/src/inputjs/computeDeltaXY.js @@ -0,0 +1,27 @@ +/** + * Created by arjun on 20/05/16. + */ +import {INPUT_START,INPUT_END} from './inputConsts' +function computeDeltaXY(session, input) { + var center = input.center; + var offset = session.offsetDelta || {}; + var prevDelta = session.prevDelta || {}; + var prevInput = session.prevInput || {}; + + if (input.eventType === INPUT_START || prevInput.eventType === INPUT_END) { + prevDelta = session.prevDelta = { + x: prevInput.deltaX || 0, + y: prevInput.deltaY || 0 + }; + + offset = session.offsetDelta = { + x: center.x, + y: center.y + }; + } + + input.deltaX = prevDelta.x + (center.x - offset.x); + input.deltaY = prevDelta.y + (center.y - offset.y); +} + +export {computeDeltaXY}; \ No newline at end of file diff --git a/src/inputjs/computeInputData.js b/src/inputjs/computeInputData.js index 535c9e543..d075f77a7 100644 --- a/src/inputjs/computeInputData.js +++ b/src/inputjs/computeInputData.js @@ -2,6 +2,20 @@ * * Created by arjun on 19/05/16. */ +import {now} from '../utilsjs/utilsConsts'; +import {abs} from '../utilsjs/utilsConsts'; +import {hasParent} from '../utilsjs/hasParent'; +import {simpleCloneInputData} from './simpleCloneInputData'; +import {getCenter} from './getCenter'; +import {getDistance} from './getDistance'; +import {getAngle} from './getAngle'; +import {getDirection} from './getDirection'; +import {computeDeltaXY} from './computeDeltaXY'; +import {getVelocity} from './getVelocity'; +import {getScale} from './getScale'; +import {getRotation} from './getRotation'; +import {computeIntervalInputData} from './computeIntervalInputData'; + /** * extend the data with some usable properties like scale, rotate, velocity etc @@ -59,3 +73,5 @@ function computeInputData(manager, input) { } input.target = target; } + +export {computeInputData}; \ No newline at end of file diff --git a/src/inputjs/computeIntervalInputData.js b/src/inputjs/computeIntervalInputData.js new file mode 100644 index 000000000..dd65a72ec --- /dev/null +++ b/src/inputjs/computeIntervalInputData.js @@ -0,0 +1,43 @@ +/** + * Created by arjun on 20/05/16. + */ +import {INPUT_CANCEL,COMPUTE_INTERVAL} from './inputConsts' +import {abs} from '../utilsjs/utilsConsts' +import {getVelocity} from './getVelocity' +import {getDirection} from './getDirection' +/** + * velocity is calculated every x ms + * @param {Object} session + * @param {Object} input + */ +function computeIntervalInputData(session, input) { + var last = session.lastInterval || input, + deltaTime = input.timeStamp - last.timeStamp, + velocity, velocityX, velocityY, direction; + + if (input.eventType != INPUT_CANCEL && (deltaTime > COMPUTE_INTERVAL || last.velocity === undefined)) { + var deltaX = input.deltaX - last.deltaX; + var deltaY = input.deltaY - last.deltaY; + + var v = getVelocity(deltaTime, deltaX, deltaY); + velocityX = v.x; + velocityY = v.y; + velocity = (abs(v.x) > abs(v.y)) ? v.x : v.y; + direction = getDirection(deltaX, deltaY); + + session.lastInterval = input; + } else { + // use latest velocity info if it doesn't overtake a minimum period + velocity = last.velocity; + velocityX = last.velocityX; + velocityY = last.velocityY; + direction = last.direction; + } + + input.velocity = velocity; + input.velocityX = velocityX; + input.velocityY = velocityY; + input.direction = direction; +} + +export {computeIntervalInputData}; diff --git a/src/inputjs/createInputInstance.js b/src/inputjs/createInputInstance.js new file mode 100644 index 000000000..818639067 --- /dev/null +++ b/src/inputjs/createInputInstance.js @@ -0,0 +1,31 @@ +/** + * Created by arjun on 19/05/16. + * Remember to import PointerEventInout + */ +import {SUPPORT_POINTER_EVENTS,SUPPORT_ONLY_TOUCH,SUPPORT_TOUCH} from './inputConsts' +import {inputHandler} from './inputHandler' +/** + * create new input type manager + * called by the Manager constructor + * @param {Hammer} manager + * @returns {Input} + */ +function createInputInstance(manager) { + var Type; + var inputClass = manager.options.inputClass; + + if (inputClass) { + Type = inputClass; + } else if (SUPPORT_POINTER_EVENTS) { + Type = PointerEventInput; + } else if (SUPPORT_ONLY_TOUCH) { + Type = TouchInput; + } else if (!SUPPORT_TOUCH) { + Type = MouseInput; + } else { + Type = TouchMouseInput; + } + return new (Type)(manager, inputHandler); +} + +export {createInputInstance} \ No newline at end of file diff --git a/src/inputjs/getAngle.js b/src/inputjs/getAngle.js new file mode 100644 index 000000000..1d7cb7e27 --- /dev/null +++ b/src/inputjs/getAngle.js @@ -0,0 +1,21 @@ +/** + * Created by arjun on 20/05/16. + */ +import {PROPS_XY} from './inputConsts' +/** + * calculate the angle between two coordinates + * @param {Object} p1 + * @param {Object} p2 + * @param {Array} [props] containing x and y keys + * @return {Number} angle + */ +function getAngle(p1, p2, props) { + if (!props) { + props = PROPS_XY; + } + var x = p2[props[0]] - p1[props[0]], + y = p2[props[1]] - p1[props[1]]; + return Math.atan2(y, x) * 180 / Math.PI; +} + +export {getAngle}; \ No newline at end of file diff --git a/src/inputjs/getCenter.js b/src/inputjs/getCenter.js new file mode 100644 index 000000000..ca62995f3 --- /dev/null +++ b/src/inputjs/getCenter.js @@ -0,0 +1,34 @@ +/** + * Created by arjun on 20/05/16. + */ +import {round} from '../utilsjs/utilsConsts' +/** + * get the center of all the pointers + * @param {Array} pointers + * @return {Object} center contains `x` and `y` properties + */ +function getCenter(pointers) { + var pointersLength = pointers.length; + + // no need to loop when only one touch + if (pointersLength === 1) { + return { + x: round(pointers[0].clientX), + y: round(pointers[0].clientY) + }; + } + + var x = 0, y = 0, i = 0; + while (i < pointersLength) { + x += pointers[i].clientX; + y += pointers[i].clientY; + i++; + } + + return { + x: round(x / pointersLength), + y: round(y / pointersLength) + }; +} + +export {getCenter}; diff --git a/src/inputjs/getDirection.js b/src/inputjs/getDirection.js new file mode 100644 index 000000000..cf02ebbd3 --- /dev/null +++ b/src/inputjs/getDirection.js @@ -0,0 +1,23 @@ +/** + * Created by arjun on 20/05/16. + */ +import {abs} from '../utilsjs/utilsConsts'; +import {DIRECTION_NONE,DIRECTION_LEFT,DIRECTION_RIGHT,DIRECTION_UP,DIRECTION_DOWN} from './inputConsts'; +/** + * get the direction between two points + * @param {Number} x + * @param {Number} y + * @return {Number} direction + */ +function getDirection(x, y) { + if (x === y) { + return DIRECTION_NONE; + } + + if (abs(x) >= abs(y)) { + return x < 0 ? DIRECTION_LEFT : DIRECTION_RIGHT; + } + return y < 0 ? DIRECTION_UP : DIRECTION_DOWN; +} + +export {getDirection}; diff --git a/src/inputjs/getDistance.js b/src/inputjs/getDistance.js new file mode 100644 index 000000000..8c466fc3b --- /dev/null +++ b/src/inputjs/getDistance.js @@ -0,0 +1,22 @@ +/** + * Created by arjun on 20/05/16. + */ +import {PROPS_XY} from './inputConsts' +/** + * calculate the absolute distance between two points + * @param {Object} p1 {x, y} + * @param {Object} p2 {x, y} + * @param {Array} [props] containing x and y keys + * @return {Number} distance + */ +function getDistance(p1, p2, props) { + if (!props) { + props = PROPS_XY; + } + var x = p2[props[0]] - p1[props[0]], + y = p2[props[1]] - p1[props[1]]; + + return Math.sqrt((x * x) + (y * y)); +} + +export {getDistance}; \ No newline at end of file diff --git a/src/inputjs/getRotation.js b/src/inputjs/getRotation.js new file mode 100644 index 000000000..d293c9df6 --- /dev/null +++ b/src/inputjs/getRotation.js @@ -0,0 +1,16 @@ +/** + * Created by arjun on 20/05/16. + */ +import {getAngle} from './getAngle' +import {PROPS_CLIENT_XY} from './inputConsts' +/** + * calculate the rotation degrees between two pointersets + * @param {Array} start array of pointers + * @param {Array} end array of pointers + * @return {Number} rotation + */ +function getRotation(start, end) { + return getAngle(end[1], end[0], PROPS_CLIENT_XY) + getAngle(start[1], start[0], PROPS_CLIENT_XY); +} + +export {getRotation}; diff --git a/src/inputjs/getScale.js b/src/inputjs/getScale.js new file mode 100644 index 000000000..8a137a3f5 --- /dev/null +++ b/src/inputjs/getScale.js @@ -0,0 +1,18 @@ +/** + * + * Created by arjun on 20/05/16. + */ +import {PROPS_CLIENT_XY} from './inputConsts'; +import {getDistance} from './getDistance'; +/** + * calculate the scale factor between two pointersets + * no scale is 1, and goes down to 0 when pinched together, and bigger when pinched out + * @param {Array} start array of pointers + * @param {Array} end array of pointers + * @return {Number} scale + */ +function getScale(start, end) { + return getDistance(end[0], end[1], PROPS_CLIENT_XY) / getDistance(start[0], start[1], PROPS_CLIENT_XY); +} + +export {getScale}; \ No newline at end of file diff --git a/src/inputjs/getVelocity.js b/src/inputjs/getVelocity.js new file mode 100644 index 000000000..e02f40953 --- /dev/null +++ b/src/inputjs/getVelocity.js @@ -0,0 +1,19 @@ +/** + * Created by arjun on 20/05/16. + */ + +/** + * calculate the velocity between two points. unit is in px per ms. + * @param {Number} deltaTime + * @param {Number} x + * @param {Number} y + * @return {Object} velocity `x` and `y` + */ +function getVelocity(deltaTime, x, y) { + return { + x: x / deltaTime || 0, + y: y / deltaTime || 0 + }; +} + +export {getVelocity}; \ No newline at end of file diff --git a/src/inputjs/inputConstructor.js b/src/inputjs/inputConstructor.js index 2c0931954..b63499b5d 100644 --- a/src/inputjs/inputConstructor.js +++ b/src/inputjs/inputConstructor.js @@ -1,3 +1,61 @@ /** + * * Created by arjun on 18/05/16. */ +import {boolOrFn} from './../utilsjs/boolOrFn'; +import {addEventListeners} from './../utilsjs/addEventListeners'; +import {removeEventListeners} from './../utilsjs/removeEventListeners'; +import {getWindowForElement} from './../utilsjs/getWindowForElement'; +/** + * create new input type manager + * @param {Manager} manager + * @param {Function} callback + * @returns {Input} + * @constructor + */ +function Input(manager, callback) { + var self = this; + this.manager = manager; + this.callback = callback; + this.element = manager.element; + this.target = manager.options.inputTarget; + + // smaller wrapper around the handler, for the scope and the enabled state of the manager, + // so when disabled the input events are completely bypassed. + this.domHandler = function(ev) { + if (boolOrFn(manager.options.enable, [manager])) { + self.handler(ev); + } + }; + + this.init(); + +} + +Input.prototype = { + /** + * should handle the inputEvent data and trigger the callback + * @virtual + */ + handler: function() { }, + + /** + * bind the events + */ + init: function() { + this.evEl && addEventListeners(this.element, this.evEl, this.domHandler); + this.evTarget && addEventListeners(this.target, this.evTarget, this.domHandler); + this.evWin && addEventListeners(getWindowForElement(this.element), this.evWin, this.domHandler); + }, + + /** + * unbind the events + */ + destroy: function() { + this.evEl && removeEventListeners(this.element, this.evEl, this.domHandler); + this.evTarget && removeEventListeners(this.target, this.evTarget, this.domHandler); + this.evWin && removeEventListeners(getWindowForElement(this.element), this.evWin, this.domHandler); + } +}; + +export {Input} \ No newline at end of file diff --git a/src/inputjs/inputConsts.js b/src/inputjs/inputConsts.js new file mode 100644 index 000000000..44a1c20bb --- /dev/null +++ b/src/inputjs/inputConsts.js @@ -0,0 +1,38 @@ +/** + * Created by arjun on 19/05/16. + */ + +var MOBILE_REGEX = /mobile|tablet|ip(ad|hone|od)|android/i; + +var SUPPORT_TOUCH = ('ontouchstart' in window); +var SUPPORT_POINTER_EVENTS = prefixed(window, 'PointerEvent') !== undefined; +var SUPPORT_ONLY_TOUCH = SUPPORT_TOUCH && MOBILE_REGEX.test(navigator.userAgent); + +var INPUT_TYPE_TOUCH = 'touch'; +var INPUT_TYPE_PEN = 'pen'; +var INPUT_TYPE_MOUSE = 'mouse'; +var INPUT_TYPE_KINECT = 'kinect'; + +var COMPUTE_INTERVAL = 25; + +var INPUT_START = 1; +var INPUT_MOVE = 2; +var INPUT_END = 4; +var INPUT_CANCEL = 8; + +var DIRECTION_NONE = 1; +var DIRECTION_LEFT = 2; +var DIRECTION_RIGHT = 4; +var DIRECTION_UP = 8; +var DIRECTION_DOWN = 16; + +var DIRECTION_HORIZONTAL = DIRECTION_LEFT | DIRECTION_RIGHT; +var DIRECTION_VERTICAL = DIRECTION_UP | DIRECTION_DOWN; +var DIRECTION_ALL = DIRECTION_HORIZONTAL | DIRECTION_VERTICAL; + +var PROPS_XY = ['x', 'y']; +var PROPS_CLIENT_XY = ['clientX', 'clientY']; + +export {MOBILE_REGEX,SUPPORT_ONLY_TOUCH,SUPPORT_POINTER_EVENTS,SUPPORT_TOUCH,INPUT_TYPE_KINECT,INPUT_TYPE_MOUSE,INPUT_TYPE_PEN, + INPUT_TYPE_TOUCH,COMPUTE_INTERVAL,INPUT_START,INPUT_MOVE,INPUT_END,INPUT_CANCEL,DIRECTION_NONE,DIRECTION_LEFT,DIRECTION_RIGHT, + DIRECTION_UP,DIRECTION_DOWN,DIRECTION_HORIZONTAL,DIRECTION_VERTICAL,DIRECTION_ALL,PROPS_XY,PROPS_CLIENT_XY} \ No newline at end of file diff --git a/src/inputjs/inputHandler.js b/src/inputjs/inputHandler.js new file mode 100644 index 000000000..83c95190b --- /dev/null +++ b/src/inputjs/inputHandler.js @@ -0,0 +1,40 @@ +/** + * Created by arjun on 19/05/16. + */ +import {INPUT_START,INPUT_END,INPUT_CANCEL} from './inputConsts'; +import {computeInputData} from './computeInputData'; + +/** + * handle input events + * @param {Manager} manager + * @param {String} eventType + * @param {Object} input + */ +function inputHandler(manager, eventType, input) { + var pointersLen = input.pointers.length; + var changedPointersLen = input.changedPointers.length; + var isFirst = (eventType & INPUT_START && (pointersLen - changedPointersLen === 0)); + var isFinal = (eventType & (INPUT_END | INPUT_CANCEL) && (pointersLen - changedPointersLen === 0)); + + input.isFirst = !!isFirst; + input.isFinal = !!isFinal; + + if (isFirst) { + manager.session = {}; + } + + // source event is the normalized value of the domEvents + // like 'touchstart, mouseup, pointerdown' + input.eventType = eventType; + + // compute scale, rotation etc + computeInputData(manager, input); + + // emit secret event + manager.emit('hammer.input', input); + + manager.recognize(input); + manager.session.prevInput = input; +} + +export {inputHandler} \ No newline at end of file diff --git a/src/inputjs/simpleCloneInputData.js b/src/inputjs/simpleCloneInputData.js new file mode 100644 index 000000000..109f947d6 --- /dev/null +++ b/src/inputjs/simpleCloneInputData.js @@ -0,0 +1,33 @@ +/** + * Created by arjun on 20/05/16. + */ +import {now,round} from '../utilsjs/utilsConsts'; +import {getCenter} from './getCenter'; +/** + * create a simple clone from the input used for storage of firstInput and firstMultiple + * @param {Object} input + * @returns {Object} clonedInputData + */ +function simpleCloneInputData(input) { + // make a simple copy of the pointers because we will get a reference if we don't + // we only need clientXY for the calculations + var pointers = []; + var i = 0; + while (i < input.pointers.length) { + pointers[i] = { + clientX: round(input.pointers[i].clientX), + clientY: round(input.pointers[i].clientY) + }; + i++; + } + + return { + timeStamp: now(), + pointers: pointers, + center: getCenter(pointers), + deltaX: input.deltaX, + deltaY: input.deltaY + }; +} + +export {simpleCloneInputData}; From 4a6f81947088cb3eb0fce5710d4735b73f6b594a Mon Sep 17 00:00:00 2001 From: Arjun Kathuria Date: Wed, 25 May 2016 00:01:02 +0530 Subject: [PATCH 04/61] modulazied all files under src/input, import exports code --- src/input/mouse.js | 5 +++++ src/input/pointerevent.js | 7 +++++++ src/input/singletouch.js | 7 +++++++ src/input/touch.js | 9 +++++++++ src/input/touchmouse.js | 9 +++++++++ 5 files changed, 37 insertions(+) diff --git a/src/input/mouse.js b/src/input/mouse.js index 6e27ef5ff..f9b36d9ff 100644 --- a/src/input/mouse.js +++ b/src/input/mouse.js @@ -1,3 +1,6 @@ +import {INPUT_START,INPUT_MOVE,INPUT_END,INPUT_TYPE_MOUSE} from '../inputjs/inputConsts' +import {Input} from '../inputjs/inputConstructor'; +import {inherit} from '../utilsjs/inherit'; var MOUSE_INPUT_MAP = { mousedown: INPUT_START, mousemove: INPUT_MOVE, @@ -55,3 +58,5 @@ inherit(MouseInput, Input, { }); } }); + +export {MouseInput}; diff --git a/src/input/pointerevent.js b/src/input/pointerevent.js index ec810b5fb..8ec1b2262 100644 --- a/src/input/pointerevent.js +++ b/src/input/pointerevent.js @@ -1,3 +1,8 @@ +import {INPUT_START,INPUT_END,INPUT_CANCEL,INPUT_MOVE,INPUT_TYPE_TOUCH,INPUT_TYPE_MOUSE,INPUT_TYPE_PEN,INPUT_TYPE_KINECT} from '../inputjs/inputConsts' +import {Input} from '../inputjs/inputConstructor'; +import {inherit} from '../utilsjs/inherit'; +import {inArray} from '../utilsjs/inArray' + var POINTER_INPUT_MAP = { pointerdown: INPUT_START, pointermove: INPUT_MOVE, @@ -86,3 +91,5 @@ inherit(PointerEventInput, Input, { } } }); + +export {PointerEventInput} \ No newline at end of file diff --git a/src/input/singletouch.js b/src/input/singletouch.js index cbe9ec086..ce8d68b94 100644 --- a/src/input/singletouch.js +++ b/src/input/singletouch.js @@ -1,3 +1,8 @@ +import {INPUT_START,INPUT_MOVE,INPUT_END,INPUT_CANCEL,INPUT_TYPE_TOUCH} from '../inputjs/inputConsts' +import {Input} from '../inputjs/inputConstructor' +import {inherit} from '../utilsjs/inherit' +import {toArray} from '../utilsjs/toArray' +import {uniqueArray} from '../utilsjs/uniqueArray' var SINGLE_TOUCH_INPUT_MAP = { touchstart: INPUT_START, touchmove: INPUT_MOVE, @@ -66,3 +71,5 @@ function normalizeSingleTouches(ev, type) { return [all, changed]; } + +export {SingleTouchInput} diff --git a/src/input/touch.js b/src/input/touch.js index 4ac2dd598..3bbaacd18 100644 --- a/src/input/touch.js +++ b/src/input/touch.js @@ -1,3 +1,10 @@ +import {INPUT_START,INPUT_MOVE,INPUT_END,INPUT_CANCEL,INPUT_TYPE_TOUCH} from '../inputjs/inputConsts' +import {Input} from '../inputjs/inputConstructor' +import {inherit} from '../utilsjs/inherit'; +import {toArray} from '../utilsjs/toArray'; +import {hasParent} from '../utilsjs/hasParent'; +import {uniqueArray} from '../utilsjs/uniqueArray'; + var TOUCH_INPUT_MAP = { touchstart: INPUT_START, touchmove: INPUT_MOVE, @@ -96,3 +103,5 @@ function getTouches(ev, type) { changedTargetTouches ]; } + +export {TouchInput}; \ No newline at end of file diff --git a/src/input/touchmouse.js b/src/input/touchmouse.js index b110d2397..78f35ceff 100644 --- a/src/input/touchmouse.js +++ b/src/input/touchmouse.js @@ -1,3 +1,10 @@ +import {Input} from '../inputjs/inputConstructor' +import {inherit} from '../utilsjs/inherit'; +import {bindFn} from '../utilsjs/bindFn'; +import {TouchInput} from './touch'; +import {MouseInput} from './mouse'; +import {INPUT_START,INPUT_END,INPUT_CANCEL,INPUT_TYPE_TOUCH,INPUT_TYPE_MOUSE} from '../inputjs/inputConsts' + /** * Combined touch and mouse input * @@ -93,3 +100,5 @@ function isSyntheticEvent(eventData) { } return false; } + +export {TouchMouseInput} \ No newline at end of file From 706132cde6cc8ba1f99b8c2931342b1511e13e91 Mon Sep 17 00:00:00 2001 From: Chris Thoburn Date: Fri, 27 May 2016 16:02:23 -0700 Subject: [PATCH 05/61] spike --- addon/gestures/layer.js | 0 addon/gestures/manager.js | 82 ++++++++++++++++++++++ addon/gestures/recognizer.js | 0 addon/gestures/stream-event.js | 81 +++++++++++++++++++++ addon/gestures/stream.js | 0 addon/styles/addon.scss | 0 package.json | 5 +- server/.jshintrc | 3 + server/index.js | 24 +++++++ server/mocks/items.js | 47 +++++++++++++ tests/dummy/app/adapters/application.js | 4 ++ tests/dummy/app/models/item.js | 7 ++ tests/dummy/app/serializers/application.js | 4 ++ tests/dummy/config/environment.js | 1 + tests/index.html | 2 +- 15 files changed, 258 insertions(+), 2 deletions(-) create mode 100644 addon/gestures/layer.js create mode 100644 addon/gestures/manager.js create mode 100644 addon/gestures/recognizer.js create mode 100644 addon/gestures/stream-event.js create mode 100644 addon/gestures/stream.js create mode 100644 addon/styles/addon.scss create mode 100644 server/.jshintrc create mode 100644 server/index.js create mode 100644 server/mocks/items.js create mode 100644 tests/dummy/app/adapters/application.js create mode 100644 tests/dummy/app/models/item.js create mode 100644 tests/dummy/app/serializers/application.js diff --git a/addon/gestures/layer.js b/addon/gestures/layer.js new file mode 100644 index 000000000..e69de29bb diff --git a/addon/gestures/manager.js b/addon/gestures/manager.js new file mode 100644 index 000000000..69c758266 --- /dev/null +++ b/addon/gestures/manager.js @@ -0,0 +1,82 @@ +import { TouchStream, MouseStream } from './stream'; + +export default class Manager { + + constructor(rootElement) { + this.rootElement = rootElement || window; + this._setup(); + } + + register(layer) { + this.layers.set(layer.element, layer); + layer.parent = this._findParentLayer(layer.element); + + // insert into linked layer list + if (layer.parent) { + layer.child = layer.parent.child; + layer.parent.child = layer; + } + } + + forget(layer) { + this.layers.delete(layer.element); + + // join parent/child + if (layer.parent && layer.child) { + layer.parent.child = layer.child; + + // unlink parent/child + } else { + if (layer.parent) { + layer.parent.child = null; + } + if (layer.child) { + layer.child.parent = null; + } + } + } + + private _findParentLayer(element) { + do { + if (element.hasAttribute('gesture-layer')) { + let layer = this.layers.get(element); + + if (layer) { + return layer; + } + } + } while (element = element.parentNode); + + return null; + } + + + private _setup() { + this.layers = new WeakMap(); + + this.streams = { + touch: new TouchStream(this.rootElement), + mouse: new MouseStream(this.rootElement) + }; + } + + private _teardown() { + this.streams.touch.destroy(); + this.streams.mouse.destroy(); + + this.layers.forEach((layer) => { + layer.destroy(); + }); + + this.layers = null; + } + + static create() { + return new Manager(); + } + + destroy() { + this._teardown(); + } + +} diff --git a/addon/gestures/recognizer.js b/addon/gestures/recognizer.js new file mode 100644 index 000000000..e69de29bb diff --git a/addon/gestures/stream-event.js b/addon/gestures/stream-event.js new file mode 100644 index 000000000..988e2759d --- /dev/null +++ b/addon/gestures/stream-event.js @@ -0,0 +1,81 @@ +/* global performance */ + +class StreamEvent { + + constructor(name, options, event, prev) { + this.name = name; + this.source = event; + this.silenced = false; + this.prev = prev; + + // time + this.time = performance.now(); + this.dT = prev ? this.time - prev.time : 0; + + // current position (clientX/Y) + this.x = options.x; + this.y = options.y; + + // deltas off of origin event + this.totalX = options.x - options.originX; + this.totalY = options.y - options.originY; + + // deltas off of last event + this.dX = prev ? options.x - prev.x : 0; + this.dY = prev ? options.y - prev.y : 0; + + // prediction values + this.acceleration = 0; + this.aX = 0; + this.aY = 0; + + this.velocity = 0; + this.vX = 0; + this.vY = 0; + + this.nextX = 0; + this.nextY = 0; + } + + getAcceleration() { + const { dT, prev } = this; + const { vX, vY } = this.getVelocity(); + const { vX: _vX, vY: _vY } = prev; + + // acceleration + let aX = this.aX = (vX - _vX) / dT; + let aY = this.aY = (vY - _vY) / dT; + let acceleration = this.acceleration = Math.sqrt(aX * aX + aY * aY); + + return { aX, aY, acceleration }; + } + + getVelocity() { + const { dX, dY, dT } = this; + + let vX = this.vX = dX / dT; + let vY = this.vY = dY / dT; + let velocity = this.velocity = Math.sqrt(vX * vX + vY * vY); + + return { vX, vY, velocity }; + } + + predict() { + const { aX, aY } = this.getAcceleration(); + const { x, y, vX, vY, dT } = this; + + // distance = initial distance + velocity * time + 1/2 acceleration * time^2 + let nextX = this.nextX = x + (vX * dT) + (.5 * aX * dT * dT); + let nextY = this.nextY = y + (vY * dT) + (.5 * aY * dT * dT); + + return { x: nextX, y: nextY }; + } + + // cancel any default behaviors from this event + silence() { + this.source.preventDefault(); + this.source.stopPropagation(); + this.silenced = true; + } + +} diff --git a/addon/gestures/stream.js b/addon/gestures/stream.js new file mode 100644 index 000000000..e69de29bb diff --git a/addon/styles/addon.scss b/addon/styles/addon.scss new file mode 100644 index 000000000..e69de29bb diff --git a/package.json b/package.json index c154bc9a9..31cf4104c 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,10 @@ "ember-load-initializers": "^0.5.1", "ember-resolver": "^2.0.3", "ember-welcome-page": "^1.0.1", - "loader.js": "^4.0.1" + "express": "^4.13.4", + "glob": "^4.5.3", + "loader.js": "^4.0.1", + "morgan": "^1.7.0" }, "keywords": [ "ember-addon" diff --git a/server/.jshintrc b/server/.jshintrc new file mode 100644 index 000000000..c1f2978bc --- /dev/null +++ b/server/.jshintrc @@ -0,0 +1,3 @@ +{ + "node": true +} diff --git a/server/index.js b/server/index.js new file mode 100644 index 000000000..8068c75eb --- /dev/null +++ b/server/index.js @@ -0,0 +1,24 @@ +/*jshint node:true*/ + +// To use it create some files under `mocks/` +// e.g. `server/mocks/ember-hamsters.js` +// +// module.exports = function(app) { +// app.get('/ember-hamsters', function(req, res) { +// res.send('hello'); +// }); +// }; + +module.exports = function(app) { + var globSync = require('glob').sync; + var mocks = globSync('./mocks/**/*.js', { cwd: __dirname }).map(require); + var proxies = globSync('./proxies/**/*.js', { cwd: __dirname }).map(require); + + // Log proxy requests + var morgan = require('morgan'); + app.use(morgan('dev')); + + mocks.forEach(function(route) { route(app); }); + proxies.forEach(function(route) { route(app); }); + +}; diff --git a/server/mocks/items.js b/server/mocks/items.js new file mode 100644 index 000000000..531c932cc --- /dev/null +++ b/server/mocks/items.js @@ -0,0 +1,47 @@ +/*jshint node:true*/ +module.exports = function(app) { + var express = require('express'); + var itemsRouter = express.Router(); + + itemsRouter.get('/', function(req, res) { + res.send({ + 'items': [] + }); + }); + + itemsRouter.post('/', function(req, res) { + res.status(201).end(); + }); + + itemsRouter.get('/:id', function(req, res) { + res.send({ + 'items': { + id: req.params.id + } + }); + }); + + itemsRouter.put('/:id', function(req, res) { + res.send({ + 'items': { + id: req.params.id + } + }); + }); + + itemsRouter.delete('/:id', function(req, res) { + res.status(204).end(); + }); + + // The POST and PUT call will not contain a request body + // because the body-parser is not included by default. + // To use req.body, run: + + // npm install --save-dev body-parser + + // After installing, you need to `use` the body-parser for + // this mock uncommenting the following line: + // + //app.use('/api/items', require('body-parser').json()); + app.use('/api/items', itemsRouter); +}; diff --git a/tests/dummy/app/adapters/application.js b/tests/dummy/app/adapters/application.js new file mode 100644 index 000000000..03e214724 --- /dev/null +++ b/tests/dummy/app/adapters/application.js @@ -0,0 +1,4 @@ +import JSONAPIAdapter from 'ember-data/adapters/json-api'; + +export default JSONAPIAdapter.extend({ +}); diff --git a/tests/dummy/app/models/item.js b/tests/dummy/app/models/item.js new file mode 100644 index 000000000..1246b0de1 --- /dev/null +++ b/tests/dummy/app/models/item.js @@ -0,0 +1,7 @@ +import Model from 'ember-data/model'; +// import attr from 'ember-data/attr'; +// import { belongsTo, hasMany } from 'ember-data/relationships'; + +export default Model.extend({ + +}); diff --git a/tests/dummy/app/serializers/application.js b/tests/dummy/app/serializers/application.js new file mode 100644 index 000000000..4678cc2c3 --- /dev/null +++ b/tests/dummy/app/serializers/application.js @@ -0,0 +1,4 @@ +import JSONAPISerializer from 'ember-data/serializers/json-api'; + +export default JSONAPISerializer.extend({ +}); diff --git a/tests/dummy/config/environment.js b/tests/dummy/config/environment.js index 2529939c5..c7000dbb4 100644 --- a/tests/dummy/config/environment.js +++ b/tests/dummy/config/environment.js @@ -3,6 +3,7 @@ module.exports = function(environment) { var ENV = { modulePrefix: 'dummy', + podModulePrefix: 'dummy/routes', environment: environment, rootURL: '/', locationType: 'auto', diff --git a/tests/index.html b/tests/index.html index 1c34853da..9ce2d7e5e 100644 --- a/tests/index.html +++ b/tests/index.html @@ -5,7 +5,7 @@ Dummy Tests - + {{content-for "head"}} {{content-for "test-head"}} From 6c7c4ac992218148f00a08c368f329fa2b27bc99 Mon Sep 17 00:00:00 2001 From: Arjun Kathuria Date: Sat, 28 May 2016 21:27:59 +0530 Subject: [PATCH 06/61] Long commit, adds all files required in src, basic rollup build up and running --- bundle.js | 2503 +++++++++++++++++ rollup.config.js | 16 + src/.babelrc | 3 + src/hammer.js | 13 + src/hammer.prefix.js | 2 - src/hammer.suffix.js | 1 - src/input.js | 394 --- src/inputjs/computeDeltaXY.js | 1 + src/inputjs/createInputInstance.js | 4 + src/inputjs/inputConsts.js | 1 + src/main.js | 1 + src/manager.js | 15 + src/recognizerjs/directionStr.js | 23 + .../getRecognizerByNameIfManager.js | 20 + .../recognizerConstructor.js} | 71 +- src/recognizerjs/recognizerConsts.js | 14 + src/recognizerjs/stateStr.js | 23 + src/recognizers/attribute.js | 7 + src/recognizers/pan.js | 10 + src/recognizers/pinch.js | 6 + src/recognizers/press.js | 10 + src/recognizers/rotate.js | 6 + src/recognizers/swipe.js | 10 + src/recognizers/tap.js | 9 + src/touchactionjs/cleanTouchActions.js | 43 + src/touchactionjs/getTouchActionProps.js | 20 + .../touchActionConstructor.js} | 71 +- src/touchactionjs/touchactionConsts.js | 22 + src/utils.js | 371 --- src/utilsjs/addEventListeners.js | 3 +- src/utilsjs/ifUndefined.js | 15 + src/utilsjs/invokeArrayArg.js | 2 +- src/utilsjs/removeEventListeners.js | 1 + src/utilsjs/setTimeoutContext.js | 2 +- 34 files changed, 2825 insertions(+), 888 deletions(-) create mode 100644 bundle.js create mode 100644 rollup.config.js create mode 100644 src/.babelrc delete mode 100644 src/hammer.prefix.js delete mode 100644 src/hammer.suffix.js delete mode 100644 src/input.js create mode 100644 src/main.js create mode 100644 src/recognizerjs/directionStr.js create mode 100644 src/recognizerjs/getRecognizerByNameIfManager.js rename src/{recognizer.js => recognizerjs/recognizerConstructor.js} (85%) create mode 100644 src/recognizerjs/recognizerConsts.js create mode 100644 src/recognizerjs/stateStr.js create mode 100644 src/touchactionjs/cleanTouchActions.js create mode 100644 src/touchactionjs/getTouchActionProps.js rename src/{touchaction.js => touchactionjs/touchActionConstructor.js} (61%) create mode 100644 src/touchactionjs/touchactionConsts.js delete mode 100644 src/utils.js create mode 100644 src/utilsjs/ifUndefined.js diff --git a/bundle.js b/bundle.js new file mode 100644 index 000000000..bd6750b18 --- /dev/null +++ b/bundle.js @@ -0,0 +1,2503 @@ +(function(window, document, exportName, undefined) { +'use strict' + +var babelHelpers = {}; +babelHelpers.typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { + return typeof obj; +} : function (obj) { + return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj; +}; +babelHelpers; + +/** + * Created by arjun on 25/05/16. + */ + +/** + * use the val2 when val1 is undefined + * @param {*} val1 + * @param {*} val2 + * @returns {*} + */ +function ifUndefined(val1, val2) { + return val1 === undefined ? val2 : val1; +} + +/** + * Created by arjun on 19/05/16. + */ + +var VENDOR_PREFIXES = ['', 'webkit', 'Moz', 'MS', 'ms', 'o']; +var TEST_ELEMENT = document.createElement('div'); + +var TYPE_FUNCTION = 'function'; + +var round = Math.round; +var abs = Math.abs; +var now = Date.now; + +/** + * get the prefixed property + * @param {Object} obj + * @param {String} property + * @returns {String|Undefined} prefixed + */ +function prefixed(obj, property) { + var prefix, prop; + var camelProp = property[0].toUpperCase() + property.slice(1); + + var i = 0; + while (i < VENDOR_PREFIXES.length) { + prefix = VENDOR_PREFIXES[i]; + prop = prefix ? prefix + camelProp : property; + + if (prop in obj) { + return prop; + } + i++; + } + return undefined; +} + +function getTouchActionProps() { + if (!NATIVE_TOUCH_ACTION) { + return false; + } + var touchMap = {}; + var cssSupports = window.CSS && window.CSS.supports; + ['auto', 'manipulation', 'pan-y', 'pan-x', 'pan-x pan-y', 'none'].forEach(function (val) { + + // If css.supports is not supported but there is native touch-action assume it supports + // all values. This is the case for IE 10 and 11. + touchMap[val] = cssSupports ? window.CSS.supports('touch-action', val) : true; + }); + return touchMap; +} + +var PREFIXED_TOUCH_ACTION = prefixed(TEST_ELEMENT.style, 'touchAction'); +var NATIVE_TOUCH_ACTION = PREFIXED_TOUCH_ACTION !== undefined; + +// magical touchAction value +var TOUCH_ACTION_COMPUTE = 'compute'; +var TOUCH_ACTION_AUTO = 'auto'; +var TOUCH_ACTION_MANIPULATION = 'manipulation'; // not implemented +var TOUCH_ACTION_NONE = 'none'; +var TOUCH_ACTION_PAN_X = 'pan-x'; +var TOUCH_ACTION_PAN_Y = 'pan-y'; +var TOUCH_ACTION_MAP = getTouchActionProps(); + +var MOBILE_REGEX = /mobile|tablet|ip(ad|hone|od)|android/i; + +var SUPPORT_TOUCH = 'ontouchstart' in window; +var SUPPORT_POINTER_EVENTS = prefixed(window, 'PointerEvent') !== undefined; +var SUPPORT_ONLY_TOUCH = SUPPORT_TOUCH && MOBILE_REGEX.test(navigator.userAgent); + +var INPUT_TYPE_TOUCH = 'touch'; +var INPUT_TYPE_PEN = 'pen'; +var INPUT_TYPE_MOUSE = 'mouse'; +var INPUT_TYPE_KINECT = 'kinect'; + +var COMPUTE_INTERVAL = 25; + +var INPUT_START = 1; +var INPUT_MOVE = 2; +var INPUT_END = 4; +var INPUT_CANCEL = 8; + +var DIRECTION_NONE = 1; +var DIRECTION_LEFT = 2; +var DIRECTION_RIGHT = 4; +var DIRECTION_UP = 8; +var DIRECTION_DOWN = 16; + +var DIRECTION_HORIZONTAL = DIRECTION_LEFT | DIRECTION_RIGHT; +var DIRECTION_VERTICAL = DIRECTION_UP | DIRECTION_DOWN; +var DIRECTION_ALL = DIRECTION_HORIZONTAL | DIRECTION_VERTICAL; + +var PROPS_XY = ['x', 'y']; +var PROPS_CLIENT_XY = ['clientX', 'clientY']; + +/** + * Created by arjun on 19/05/16. + */ + +/** + * extend object. + * means that properties in dest will be overwritten by the ones in src. + * @param {Object} target + * @param {...Object} objects_to_assign + * @returns {Object} target + */ +var assign; +if (typeof Object.assign !== 'function') { + assign = function assign(target) { + if (target === undefined || target === null) { + throw new TypeError('Cannot convert undefined or null to object'); + } + + var output = Object(target); + for (var index = 1; index < arguments.length; index++) { + var source = arguments[index]; + if (source !== undefined && source !== null) { + for (var nextKey in source) { + if (source.hasOwnProperty(nextKey)) { + output[nextKey] = source[nextKey]; + } + } + } + } + return output; + }; +} else { + assign = Object.assign; +} + +/** + * simple class inheritance + * @param {Function} child + * @param {Function} base + * @param {Object} [properties] + */ +function inherit(child, base, properties) { + var baseP = base.prototype, + childP; + + childP = child.prototype = Object.create(baseP); + childP.constructor = child; + childP._super = baseP; + + if (properties) { + assign(childP, properties); + } +} + +/** + * Created by arjun on 25/05/16. + */ + +var STATE_POSSIBLE = 1; +var STATE_BEGAN = 2; +var STATE_CHANGED = 4; +var STATE_ENDED = 8; +var STATE_RECOGNIZED = STATE_ENDED; +var STATE_CANCELLED = 16; +var STATE_FAILED = 32; + +/** + * Created by arjun on 20/05/16. + */ + +/** + * get a unique id + * @returns {number} uniqueId + */ +var _uniqueId = 1; +function uniqueId() { + return _uniqueId++; +} + +/** + * Created by arjun on 19/05/16. + */ + +/** + * walk objects and arrays + * @param {Object} obj + * @param {Function} iterator + * @param {Object} context + */ +function each(obj, iterator, context) { + var i; + + if (!obj) { + return; + } + + if (obj.forEach) { + obj.forEach(iterator, context); + } else if (obj.length !== undefined) { + i = 0; + while (i < obj.length) { + iterator.call(context, obj[i], i, obj); + i++; + } + } else { + for (i in obj) { + obj.hasOwnProperty(i) && iterator.call(context, obj[i], i, obj); + } + } +} + +/** + * if the argument is an array, we want to execute the fn on each entry + * if it aint an array we don't want to do a thing. + * this is used by all the methods that accept a single and array argument. + * @param {*|Array} arg + * @param {String} fn + * @param {Object} [context] + * @returns {Boolean} + */ +function invokeArrayArg(arg, fn, context) { + if (Array.isArray(arg)) { + each(arg, context[fn], context); + return true; + } + return false; +} + +/** + * Created by arjun on 20/05/16. + */ + +/** + * find if a array contains the object using indexOf or a simple polyFill + * @param {Array} src + * @param {String} find + * @param {String} [findByKey] + * @return {Boolean|Number} false when not found, or the index + */ +function inArray(src, find, findByKey) { + if (src.indexOf && !findByKey) { + return src.indexOf(find); + } else { + var i = 0; + while (i < src.length) { + if (findByKey && src[i][findByKey] == find || !findByKey && src[i] === find) { + return i; + } + i++; + } + return -1; + } +} + +/** + * let a boolean value also be a function that must return a boolean + * this first item in args will be used as the context + * @param {Boolean|Function} val + * @param {Array} [args] + * @returns {Boolean} + */ +function boolOrFn(val, args) { + if ((typeof val === 'undefined' ? 'undefined' : babelHelpers.typeof(val)) == TYPE_FUNCTION) { + return val.apply(args ? args[0] || undefined : undefined, args); + } + return val; +} + +/** + * Created by arjun on 25/05/16. + */ + +/** + * get a recognizer by name if it is bound to a manager + * @param {Recognizer|String} otherRecognizer + * @param {Recognizer} recognizer + * @returns {Recognizer} + */ +function getRecognizerByNameIfManager(otherRecognizer, recognizer) { + var manager = recognizer.manager; + if (manager) { + return manager.get(otherRecognizer); + } + return otherRecognizer; +} + +/** + * get a usable string, used as event postfix + * @param {constant} state + * @returns {String} state + */ +function stateStr(state) { + if (state & STATE_CANCELLED) { + return 'cancel'; + } else if (state & STATE_ENDED) { + return 'end'; + } else if (state & STATE_CHANGED) { + return 'move'; + } else if (state & STATE_BEGAN) { + return 'start'; + } + return ''; +} + +/** + * Recognizer flow explained; * + * All recognizers have the initial state of POSSIBLE when a input session starts. + * The definition of a input session is from the first input until the last input, with all it's movement in it. * + * Example session for mouse-input: mousedown -> mousemove -> mouseup + * + * On each recognizing cycle (see Manager.recognize) the .recognize() method is executed + * which determines with state it should be. + * + * If the recognizer has the state FAILED, CANCELLED or RECOGNIZED (equals ENDED), it is reset to + * POSSIBLE to give it another change on the next cycle. + * + * Possible + * | + * +-----+---------------+ + * | | + * +-----+-----+ | + * | | | + * Failed Cancelled | + * +-------+------+ + * | | + * Recognized Began + * | + * Changed + * | + * Ended/Recognized + */ + +/** + * Recognizer + * Every recognizer needs to extend from this class. + * @constructor + * @param {Object} options + */ +function Recognizer(options) { + this.options = assign({}, this.defaults, options || {}); + + this.id = uniqueId(); + + this.manager = null; + + // default is enable true + this.options.enable = ifUndefined(this.options.enable, true); + + this.state = STATE_POSSIBLE; + + this.simultaneous = {}; + this.requireFail = []; +} + +Recognizer.prototype = { + /** + * @virtual + * @type {Object} + */ + defaults: {}, + + /** + * set options + * @param {Object} options + * @return {Recognizer} + */ + set: function set(options) { + assign(this.options, options); + + // also update the touchAction, in case something changed about the directions/enabled state + this.manager && this.manager.touchAction.update(); + return this; + }, + + /** + * recognize simultaneous with an other recognizer. + * @param {Recognizer} otherRecognizer + * @returns {Recognizer} this + */ + recognizeWith: function recognizeWith(otherRecognizer) { + if (invokeArrayArg(otherRecognizer, 'recognizeWith', this)) { + return this; + } + + var simultaneous = this.simultaneous; + otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this); + if (!simultaneous[otherRecognizer.id]) { + simultaneous[otherRecognizer.id] = otherRecognizer; + otherRecognizer.recognizeWith(this); + } + return this; + }, + + /** + * drop the simultaneous link. it doesnt remove the link on the other recognizer. + * @param {Recognizer} otherRecognizer + * @returns {Recognizer} this + */ + dropRecognizeWith: function dropRecognizeWith(otherRecognizer) { + if (invokeArrayArg(otherRecognizer, 'dropRecognizeWith', this)) { + return this; + } + + otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this); + delete this.simultaneous[otherRecognizer.id]; + return this; + }, + + /** + * recognizer can only run when an other is failing + * @param {Recognizer} otherRecognizer + * @returns {Recognizer} this + */ + requireFailure: function requireFailure(otherRecognizer) { + if (invokeArrayArg(otherRecognizer, 'requireFailure', this)) { + return this; + } + + var requireFail = this.requireFail; + otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this); + if (inArray(requireFail, otherRecognizer) === -1) { + requireFail.push(otherRecognizer); + otherRecognizer.requireFailure(this); + } + return this; + }, + + /** + * drop the requireFailure link. it does not remove the link on the other recognizer. + * @param {Recognizer} otherRecognizer + * @returns {Recognizer} this + */ + dropRequireFailure: function dropRequireFailure(otherRecognizer) { + if (invokeArrayArg(otherRecognizer, 'dropRequireFailure', this)) { + return this; + } + + otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this); + var index = inArray(this.requireFail, otherRecognizer); + if (index > -1) { + this.requireFail.splice(index, 1); + } + return this; + }, + + /** + * has require failures boolean + * @returns {boolean} + */ + hasRequireFailures: function hasRequireFailures() { + return this.requireFail.length > 0; + }, + + /** + * if the recognizer can recognize simultaneous with an other recognizer + * @param {Recognizer} otherRecognizer + * @returns {Boolean} + */ + canRecognizeWith: function canRecognizeWith(otherRecognizer) { + return !!this.simultaneous[otherRecognizer.id]; + }, + + /** + * You should use `tryEmit` instead of `emit` directly to check + * that all the needed recognizers has failed before emitting. + * @param {Object} input + */ + emit: function emit(input) { + var self = this; + var state = this.state; + + function emit(event) { + self.manager.emit(event, input); + } + + // 'panstart' and 'panmove' + if (state < STATE_ENDED) { + emit(self.options.event + stateStr(state)); + } + + emit(self.options.event); // simple 'eventName' events + + if (input.additionalEvent) { + // additional event(panleft, panright, pinchin, pinchout...) + emit(input.additionalEvent); + } + + // panend and pancancel + if (state >= STATE_ENDED) { + emit(self.options.event + stateStr(state)); + } + }, + + /** + * Check that all the require failure recognizers has failed, + * if true, it emits a gesture event, + * otherwise, setup the state to FAILED. + * @param {Object} input + */ + tryEmit: function tryEmit(input) { + if (this.canEmit()) { + return this.emit(input); + } + // it's failing anyway + this.state = STATE_FAILED; + }, + + /** + * can we emit? + * @returns {boolean} + */ + canEmit: function canEmit() { + var i = 0; + while (i < this.requireFail.length) { + if (!(this.requireFail[i].state & (STATE_FAILED | STATE_POSSIBLE))) { + return false; + } + i++; + } + return true; + }, + + /** + * update the recognizer + * @param {Object} inputData + */ + recognize: function recognize(inputData) { + // make a new copy of the inputData + // so we can change the inputData without messing up the other recognizers + var inputDataClone = assign({}, inputData); + + // is is enabled and allow recognizing? + if (!boolOrFn(this.options.enable, [this, inputDataClone])) { + this.reset(); + this.state = STATE_FAILED; + return; + } + + // reset when we've reached the end + if (this.state & (STATE_RECOGNIZED | STATE_CANCELLED | STATE_FAILED)) { + this.state = STATE_POSSIBLE; + } + + this.state = this.process(inputDataClone); + + // the recognizer has recognized a gesture + // so trigger an event + if (this.state & (STATE_BEGAN | STATE_CHANGED | STATE_ENDED | STATE_CANCELLED)) { + this.tryEmit(inputDataClone); + } + }, + + /** + * return the state of the recognizer + * the actual recognizing happens in this method + * @virtual + * @param {Object} inputData + * @returns {constant} STATE + */ + process: function process(inputData) {}, // jshint ignore:line + + /** + * return the preferred touch-action + * @virtual + * @returns {Array} + */ + getTouchAction: function getTouchAction() {}, + + /** + * called when the gesture isn't allowed to recognize + * like when another is being recognized or it is disabled + * @virtual + */ + reset: function reset() {} +}; + +/** + * This recognizer is just used as a base for the simple attribute recognizers. + * @constructor + * @extends Recognizer + */ +function AttrRecognizer() { + Recognizer.apply(this, arguments); +} + +inherit(AttrRecognizer, Recognizer, { + /** + * @namespace + * @memberof AttrRecognizer + */ + defaults: { + /** + * @type {Number} + * @default 1 + */ + pointers: 1 + }, + + /** + * Used to check if it the recognizer receives valid input, like input.distance > 10. + * @memberof AttrRecognizer + * @param {Object} input + * @returns {Boolean} recognized + */ + attrTest: function attrTest(input) { + var optionPointers = this.options.pointers; + return optionPointers === 0 || input.pointers.length === optionPointers; + }, + + /** + * Process the input and return the state for the recognizer + * @memberof AttrRecognizer + * @param {Object} input + * @returns {*} State + */ + process: function process(input) { + var state = this.state; + var eventType = input.eventType; + + var isRecognized = state & (STATE_BEGAN | STATE_CHANGED); + var isValid = this.attrTest(input); + + // on cancel input and we've recognized before, return STATE_CANCELLED + if (isRecognized && (eventType & INPUT_CANCEL || !isValid)) { + return state | STATE_CANCELLED; + } else if (isRecognized || isValid) { + if (eventType & INPUT_END) { + return state | STATE_ENDED; + } else if (!(state & STATE_BEGAN)) { + return STATE_BEGAN; + } + return state | STATE_CHANGED; + } + return STATE_FAILED; + } +}); + +/** + * Rotate + * Recognized when two or more pointer are moving in a circular motion. + * @constructor + * @extends AttrRecognizer + */ +function RotateRecognizer() { + AttrRecognizer.apply(this, arguments); +} + +inherit(RotateRecognizer, AttrRecognizer, { + /** + * @namespace + * @memberof RotateRecognizer + */ + defaults: { + event: 'rotate', + threshold: 0, + pointers: 2 + }, + + getTouchAction: function getTouchAction() { + return [TOUCH_ACTION_NONE]; + }, + + attrTest: function attrTest(input) { + return this._super.attrTest.call(this, input) && (Math.abs(input.rotation) > this.options.threshold || this.state & STATE_BEGAN); + } +}); + +/** + * Pinch + * Recognized when two or more pointers are moving toward (zoom-in) or away from each other (zoom-out). + * @constructor + * @extends AttrRecognizer + */ +function PinchRecognizer() { + AttrRecognizer.apply(this, arguments); +} + +inherit(PinchRecognizer, AttrRecognizer, { + /** + * @namespace + * @memberof PinchRecognizer + */ + defaults: { + event: 'pinch', + threshold: 0, + pointers: 2 + }, + + getTouchAction: function getTouchAction() { + return [TOUCH_ACTION_NONE]; + }, + + attrTest: function attrTest(input) { + return this._super.attrTest.call(this, input) && (Math.abs(input.scale - 1) > this.options.threshold || this.state & STATE_BEGAN); + }, + + emit: function emit(input) { + if (input.scale !== 1) { + var inOut = input.scale < 1 ? 'in' : 'out'; + input.additionalEvent = this.options.event + inOut; + } + this._super.emit.call(this, input); + } +}); + +/** + * direction cons to string + * @param {constant} direction + * @returns {String} + */ +function directionStr(direction) { + if (direction == DIRECTION_DOWN) { + return 'down'; + } else if (direction == DIRECTION_UP) { + return 'up'; + } else if (direction == DIRECTION_LEFT) { + return 'left'; + } else if (direction == DIRECTION_RIGHT) { + return 'right'; + } + return ''; +} + +/** + * Pan + * Recognized when the pointer is down and moved in the allowed direction. + * @constructor + * @extends AttrRecognizer + */ +function PanRecognizer() { + AttrRecognizer.apply(this, arguments); + + this.pX = null; + this.pY = null; +} + +inherit(PanRecognizer, AttrRecognizer, { + /** + * @namespace + * @memberof PanRecognizer + */ + defaults: { + event: 'pan', + threshold: 10, + pointers: 1, + direction: DIRECTION_ALL + }, + + getTouchAction: function getTouchAction() { + var direction = this.options.direction; + var actions = []; + if (direction & DIRECTION_HORIZONTAL) { + actions.push(TOUCH_ACTION_PAN_Y); + } + if (direction & DIRECTION_VERTICAL) { + actions.push(TOUCH_ACTION_PAN_X); + } + return actions; + }, + + directionTest: function directionTest(input) { + var options = this.options; + var hasMoved = true; + var distance = input.distance; + var direction = input.direction; + var x = input.deltaX; + var y = input.deltaY; + + // lock to axis? + if (!(direction & options.direction)) { + if (options.direction & DIRECTION_HORIZONTAL) { + direction = x === 0 ? DIRECTION_NONE : x < 0 ? DIRECTION_LEFT : DIRECTION_RIGHT; + hasMoved = x != this.pX; + distance = Math.abs(input.deltaX); + } else { + direction = y === 0 ? DIRECTION_NONE : y < 0 ? DIRECTION_UP : DIRECTION_DOWN; + hasMoved = y != this.pY; + distance = Math.abs(input.deltaY); + } + } + input.direction = direction; + return hasMoved && distance > options.threshold && direction & options.direction; + }, + + attrTest: function attrTest(input) { + return AttrRecognizer.prototype.attrTest.call(this, input) && (this.state & STATE_BEGAN || !(this.state & STATE_BEGAN) && this.directionTest(input)); + }, + + emit: function emit(input) { + + this.pX = input.deltaX; + this.pY = input.deltaY; + + var direction = directionStr(input.direction); + + if (direction) { + input.additionalEvent = this.options.event + direction; + } + this._super.emit.call(this, input); + } +}); + +/** + * Swipe + * Recognized when the pointer is moving fast (velocity), with enough distance in the allowed direction. + * @constructor + * @extends AttrRecognizer + */ +function SwipeRecognizer() { + AttrRecognizer.apply(this, arguments); +} + +inherit(SwipeRecognizer, AttrRecognizer, { + /** + * @namespace + * @memberof SwipeRecognizer + */ + defaults: { + event: 'swipe', + threshold: 10, + velocity: 0.3, + direction: DIRECTION_HORIZONTAL | DIRECTION_VERTICAL, + pointers: 1 + }, + + getTouchAction: function getTouchAction() { + return PanRecognizer.prototype.getTouchAction.call(this); + }, + + attrTest: function attrTest(input) { + var direction = this.options.direction; + var velocity; + + if (direction & (DIRECTION_HORIZONTAL | DIRECTION_VERTICAL)) { + velocity = input.overallVelocity; + } else if (direction & DIRECTION_HORIZONTAL) { + velocity = input.overallVelocityX; + } else if (direction & DIRECTION_VERTICAL) { + velocity = input.overallVelocityY; + } + + return this._super.attrTest.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; + }, + + emit: function emit(input) { + var direction = directionStr(input.offsetDirection); + if (direction) { + this.manager.emit(this.options.event + direction, input); + } + + this.manager.emit(this.options.event, input); + } +}); + +/** + * + * Created by arjun on 20/05/16. + */ + +/** + * simple function bind + * @param {Function} fn + * @param {Object} context + * @returns {Function} + */ +function bindFn(fn, context) { + return function boundFn() { + return fn.apply(context, arguments); + }; +} + +/** + * set a timeout with a given scope + * @param {Function} fn + * @param {Number} timeout + * @param {Object} context + * @returns {number} + */ +function setTimeoutContext(fn, timeout, context) { + return setTimeout(bindFn(fn, context), timeout); +} + +/** + * calculate the absolute distance between two points + * @param {Object} p1 {x, y} + * @param {Object} p2 {x, y} + * @param {Array} [props] containing x and y keys + * @return {Number} distance + */ +function getDistance(p1, p2, props) { + if (!props) { + props = PROPS_XY; + } + var x = p2[props[0]] - p1[props[0]], + y = p2[props[1]] - p1[props[1]]; + + return Math.sqrt(x * x + y * y); +} + +/** + * A tap is ecognized when the pointer is doing a small tap/click. Multiple taps are recognized if they occur + * between the given interval and position. The delay option can be used to recognize multi-taps without firing + * a single tap. + * + * The eventData from the emitted event contains the property `tapCount`, which contains the amount of + * multi-taps being recognized. + * @constructor + * @extends Recognizer + */ +function TapRecognizer() { + Recognizer.apply(this, arguments); + + // previous time and center, + // used for tap counting + this.pTime = false; + this.pCenter = false; + + this._timer = null; + this._input = null; + this.count = 0; +} + +inherit(TapRecognizer, Recognizer, { + /** + * @namespace + * @memberof PinchRecognizer + */ + defaults: { + event: 'tap', + pointers: 1, + taps: 1, + interval: 300, // max time between the multi-tap taps + time: 250, // max time of the pointer to be down (like finger on the screen) + threshold: 9, // a minimal movement is ok, but keep it low + posThreshold: 10 // a multi-tap can be a bit off the initial position + }, + + getTouchAction: function getTouchAction() { + return [TOUCH_ACTION_MANIPULATION]; + }, + + process: function process(input) { + var options = this.options; + + var validPointers = input.pointers.length === options.pointers; + var validMovement = input.distance < options.threshold; + var validTouchTime = input.deltaTime < options.time; + + this.reset(); + + if (input.eventType & INPUT_START && this.count === 0) { + return this.failTimeout(); + } + + // we only allow little movement + // and we've reached an end event, so a tap is possible + if (validMovement && validTouchTime && validPointers) { + if (input.eventType != INPUT_END) { + return this.failTimeout(); + } + + var validInterval = this.pTime ? input.timeStamp - this.pTime < options.interval : true; + var validMultiTap = !this.pCenter || getDistance(this.pCenter, input.center) < options.posThreshold; + + this.pTime = input.timeStamp; + this.pCenter = input.center; + + if (!validMultiTap || !validInterval) { + this.count = 1; + } else { + this.count += 1; + } + + this._input = input; + + // if tap count matches we have recognized it, + // else it has began recognizing... + var tapCount = this.count % options.taps; + if (tapCount === 0) { + // no failing requirements, immediately trigger the tap event + // or wait as long as the multitap interval to trigger + if (!this.hasRequireFailures()) { + return STATE_RECOGNIZED; + } else { + this._timer = setTimeoutContext(function () { + this.state = STATE_RECOGNIZED; + this.tryEmit(); + }, options.interval, this); + return STATE_BEGAN; + } + } + } + return STATE_FAILED; + }, + + failTimeout: function failTimeout() { + this._timer = setTimeoutContext(function () { + this.state = STATE_FAILED; + }, this.options.interval, this); + return STATE_FAILED; + }, + + reset: function reset() { + clearTimeout(this._timer); + }, + + emit: function emit() { + if (this.state == STATE_RECOGNIZED) { + this._input.tapCount = this.count; + this.manager.emit(this.options.event, this._input); + } + } +}); + +/** + * Press + * Recognized when the pointer is down for x ms without any movement. + * @constructor + * @extends Recognizer + */ +function PressRecognizer() { + Recognizer.apply(this, arguments); + + this._timer = null; + this._input = null; +} + +inherit(PressRecognizer, Recognizer, { + /** + * @namespace + * @memberof PressRecognizer + */ + defaults: { + event: 'press', + pointers: 1, + time: 251, // minimal time of the pointer to be pressed + threshold: 9 // a minimal movement is ok, but keep it low + }, + + getTouchAction: function getTouchAction() { + return [TOUCH_ACTION_AUTO]; + }, + + process: function process(input) { + var options = this.options; + var validPointers = input.pointers.length === options.pointers; + var validMovement = input.distance < options.threshold; + var validTime = input.deltaTime > options.time; + + this._input = input; + + // we only allow little movement + // and we've reached an end event, so a tap is possible + if (!validMovement || !validPointers || input.eventType & (INPUT_END | INPUT_CANCEL) && !validTime) { + this.reset(); + } else if (input.eventType & INPUT_START) { + this.reset(); + this._timer = setTimeoutContext(function () { + this.state = STATE_RECOGNIZED; + this.tryEmit(); + }, options.time, this); + } else if (input.eventType & INPUT_END) { + return STATE_RECOGNIZED; + } + return STATE_FAILED; + }, + + reset: function reset() { + clearTimeout(this._timer); + }, + + emit: function emit(input) { + if (this.state !== STATE_RECOGNIZED) { + return; + } + + if (input && input.eventType & INPUT_END) { + this.manager.emit(this.options.event + 'up', input); + } else { + this._input.timeStamp = now(); + this.manager.emit(this.options.event, this._input); + } + } +}); + +/** + * Created by arjun on 20/05/16. + */ + +/** + * small indexOf wrapper + * @param {String} str + * @param {String} find + * @returns {Boolean} found + */ +function inStr(str, find) { + return str.indexOf(find) > -1; +} + +/** + * when the touchActions are collected they are not a valid value, so we need to clean things up. * + * @param {String} actions + * @returns {*} + */ +function cleanTouchActions(actions) { + // none + if (inStr(actions, TOUCH_ACTION_NONE)) { + return TOUCH_ACTION_NONE; + } + + var hasPanX = inStr(actions, TOUCH_ACTION_PAN_X); + var hasPanY = inStr(actions, TOUCH_ACTION_PAN_Y); + + // if both pan-x and pan-y are set (different recognizers + // for different directions, e.g. horizontal pan but vertical swipe?) + // we need none (as otherwise with pan-x pan-y combined none of these + // recognizers will work, since the browser would handle all panning + if (hasPanX && hasPanY) { + return TOUCH_ACTION_NONE; + } + + // pan-x OR pan-y + if (hasPanX || hasPanY) { + return hasPanX ? TOUCH_ACTION_PAN_X : TOUCH_ACTION_PAN_Y; + } + + // manipulation + if (inStr(actions, TOUCH_ACTION_MANIPULATION)) { + return TOUCH_ACTION_MANIPULATION; + } + + return TOUCH_ACTION_AUTO; +} + +/** + * Touch Action + * sets the touchAction property or uses the js alternative + * @param {Manager} manager + * @param {String} value + * @constructor + */ +function TouchAction(manager, value) { + this.manager = manager; + this.set(value); +} + +TouchAction.prototype = { + /** + * set the touchAction value on the element or enable the polyfill + * @param {String} value + */ + set: function set(value) { + // find out the touch-action by the event handlers + if (value == TOUCH_ACTION_COMPUTE) { + value = this.compute(); + } + + if (NATIVE_TOUCH_ACTION && this.manager.element.style && TOUCH_ACTION_MAP[value]) { + this.manager.element.style[PREFIXED_TOUCH_ACTION] = value; + } + this.actions = value.toLowerCase().trim(); + }, + + /** + * just re-set the touchAction value + */ + update: function update() { + this.set(this.manager.options.touchAction); + }, + + /** + * compute the value for the touchAction property based on the recognizer's settings + * @returns {String} value + */ + compute: function compute() { + var actions = []; + each(this.manager.recognizers, function (recognizer) { + if (boolOrFn(recognizer.options.enable, [recognizer])) { + actions = actions.concat(recognizer.getTouchAction()); + } + }); + return cleanTouchActions(actions.join(' ')); + }, + + /** + * this method is called on each input cycle and provides the preventing of the browser behavior + * @param {Object} input + */ + preventDefaults: function preventDefaults(input) { + var srcEvent = input.srcEvent; + var direction = input.offsetDirection; + + // if the touch action did prevented once this session + if (this.manager.session.prevented) { + srcEvent.preventDefault(); + return; + } + + var actions = this.actions; + var hasNone = inStr(actions, TOUCH_ACTION_NONE) && !TOUCH_ACTION_MAP[TOUCH_ACTION_NONE]; + var hasPanY = inStr(actions, TOUCH_ACTION_PAN_Y) && !TOUCH_ACTION_MAP[TOUCH_ACTION_PAN_Y]; + var hasPanX = inStr(actions, TOUCH_ACTION_PAN_X) && !TOUCH_ACTION_MAP[TOUCH_ACTION_PAN_X]; + + if (hasNone) { + //do not prevent defaults if this is a tap gesture + + var isTapPointer = input.pointers.length === 1; + var isTapMovement = input.distance < 2; + var isTapTouchTime = input.deltaTime < 250; + + if (isTapPointer && isTapMovement && isTapTouchTime) { + return; + } + } + + if (hasPanX && hasPanY) { + // `pan-x pan-y` means browser handles all scrolling/panning, do not prevent + return; + } + + if (hasNone || hasPanY && direction & DIRECTION_HORIZONTAL || hasPanX && direction & DIRECTION_VERTICAL) { + return this.preventSrc(srcEvent); + } + }, + + /** + * call preventDefault to prevent the browser's default behavior (scrolling in most cases) + * @param {Object} srcEvent + */ + preventSrc: function preventSrc(srcEvent) { + this.manager.session.prevented = true; + srcEvent.preventDefault(); + } +}; + +/** + * Created by arjun on 20/05/16. + */ + +/** + * find if a node is in the given parent + * @method hasParent + * @param {HTMLElement} node + * @param {HTMLElement} parent + * @return {Boolean} found + */ +function hasParent(node, parent) { + while (node) { + if (node == parent) { + return true; + } + node = node.parentNode; + } + return false; +} + +/** + * get the center of all the pointers + * @param {Array} pointers + * @return {Object} center contains `x` and `y` properties + */ +function getCenter(pointers) { + var pointersLength = pointers.length; + + // no need to loop when only one touch + if (pointersLength === 1) { + return { + x: round(pointers[0].clientX), + y: round(pointers[0].clientY) + }; + } + + var x = 0, + y = 0, + i = 0; + while (i < pointersLength) { + x += pointers[i].clientX; + y += pointers[i].clientY; + i++; + } + + return { + x: round(x / pointersLength), + y: round(y / pointersLength) + }; +} + +/** + * create a simple clone from the input used for storage of firstInput and firstMultiple + * @param {Object} input + * @returns {Object} clonedInputData + */ +function simpleCloneInputData(input) { + // make a simple copy of the pointers because we will get a reference if we don't + // we only need clientXY for the calculations + var pointers = []; + var i = 0; + while (i < input.pointers.length) { + pointers[i] = { + clientX: round(input.pointers[i].clientX), + clientY: round(input.pointers[i].clientY) + }; + i++; + } + + return { + timeStamp: now(), + pointers: pointers, + center: getCenter(pointers), + deltaX: input.deltaX, + deltaY: input.deltaY + }; +} + +/** + * calculate the angle between two coordinates + * @param {Object} p1 + * @param {Object} p2 + * @param {Array} [props] containing x and y keys + * @return {Number} angle + */ +function getAngle(p1, p2, props) { + if (!props) { + props = PROPS_XY; + } + var x = p2[props[0]] - p1[props[0]], + y = p2[props[1]] - p1[props[1]]; + return Math.atan2(y, x) * 180 / Math.PI; +} + +/** + * get the direction between two points + * @param {Number} x + * @param {Number} y + * @return {Number} direction + */ +function getDirection(x, y) { + if (x === y) { + return DIRECTION_NONE; + } + + if (abs(x) >= abs(y)) { + return x < 0 ? DIRECTION_LEFT : DIRECTION_RIGHT; + } + return y < 0 ? DIRECTION_UP : DIRECTION_DOWN; +} + +function computeDeltaXY(session, input) { + var center = input.center; + var offset = session.offsetDelta || {}; + var prevDelta = session.prevDelta || {}; + var prevInput = session.prevInput || {}; + + if (input.eventType === INPUT_START || prevInput.eventType === INPUT_END) { + prevDelta = session.prevDelta = { + x: prevInput.deltaX || 0, + y: prevInput.deltaY || 0 + }; + + offset = session.offsetDelta = { + x: center.x, + y: center.y + }; + } + + input.deltaX = prevDelta.x + (center.x - offset.x); + input.deltaY = prevDelta.y + (center.y - offset.y); +} + +/** + * Created by arjun on 20/05/16. + */ + +/** + * calculate the velocity between two points. unit is in px per ms. + * @param {Number} deltaTime + * @param {Number} x + * @param {Number} y + * @return {Object} velocity `x` and `y` + */ +function getVelocity(deltaTime, x, y) { + return { + x: x / deltaTime || 0, + y: y / deltaTime || 0 + }; +} + +/** + * calculate the scale factor between two pointersets + * no scale is 1, and goes down to 0 when pinched together, and bigger when pinched out + * @param {Array} start array of pointers + * @param {Array} end array of pointers + * @return {Number} scale + */ +function getScale(start, end) { + return getDistance(end[0], end[1], PROPS_CLIENT_XY) / getDistance(start[0], start[1], PROPS_CLIENT_XY); +} + +/** + * calculate the rotation degrees between two pointersets + * @param {Array} start array of pointers + * @param {Array} end array of pointers + * @return {Number} rotation + */ +function getRotation(start, end) { + return getAngle(end[1], end[0], PROPS_CLIENT_XY) + getAngle(start[1], start[0], PROPS_CLIENT_XY); +} + +/** + * velocity is calculated every x ms + * @param {Object} session + * @param {Object} input + */ +function computeIntervalInputData(session, input) { + var last = session.lastInterval || input, + deltaTime = input.timeStamp - last.timeStamp, + velocity, + velocityX, + velocityY, + direction; + + if (input.eventType != INPUT_CANCEL && (deltaTime > COMPUTE_INTERVAL || last.velocity === undefined)) { + var deltaX = input.deltaX - last.deltaX; + var deltaY = input.deltaY - last.deltaY; + + var v = getVelocity(deltaTime, deltaX, deltaY); + velocityX = v.x; + velocityY = v.y; + velocity = abs(v.x) > abs(v.y) ? v.x : v.y; + direction = getDirection(deltaX, deltaY); + + session.lastInterval = input; + } else { + // use latest velocity info if it doesn't overtake a minimum period + velocity = last.velocity; + velocityX = last.velocityX; + velocityY = last.velocityY; + direction = last.direction; + } + + input.velocity = velocity; + input.velocityX = velocityX; + input.velocityY = velocityY; + input.direction = direction; +} + +/** + * extend the data with some usable properties like scale, rotate, velocity etc + * @param {Object} manager + * @param {Object} input + */ +function computeInputData(manager, input) { + var session = manager.session; + var pointers = input.pointers; + var pointersLength = pointers.length; + + // store the first input to calculate the distance and direction + if (!session.firstInput) { + session.firstInput = simpleCloneInputData(input); + } + + // to compute scale and rotation we need to store the multiple touches + if (pointersLength > 1 && !session.firstMultiple) { + session.firstMultiple = simpleCloneInputData(input); + } else if (pointersLength === 1) { + session.firstMultiple = false; + } + + var firstInput = session.firstInput; + var firstMultiple = session.firstMultiple; + var offsetCenter = firstMultiple ? firstMultiple.center : firstInput.center; + + var center = input.center = getCenter(pointers); + input.timeStamp = now(); + input.deltaTime = input.timeStamp - firstInput.timeStamp; + + input.angle = getAngle(offsetCenter, center); + input.distance = getDistance(offsetCenter, center); + + computeDeltaXY(session, input); + input.offsetDirection = getDirection(input.deltaX, input.deltaY); + + var overallVelocity = getVelocity(input.deltaTime, input.deltaX, input.deltaY); + input.overallVelocityX = overallVelocity.x; + input.overallVelocityY = overallVelocity.y; + input.overallVelocity = abs(overallVelocity.x) > abs(overallVelocity.y) ? overallVelocity.x : overallVelocity.y; + + input.scale = firstMultiple ? getScale(firstMultiple.pointers, pointers) : 1; + input.rotation = firstMultiple ? getRotation(firstMultiple.pointers, pointers) : 0; + + input.maxPointers = !session.prevInput ? input.pointers.length : input.pointers.length > session.prevInput.maxPointers ? input.pointers.length : session.prevInput.maxPointers; + + computeIntervalInputData(session, input); + + // find the correct target + var target = manager.element; + if (hasParent(input.srcEvent.target, target)) { + target = input.srcEvent.target; + } + input.target = target; +} + +/** + * handle input events + * @param {Manager} manager + * @param {String} eventType + * @param {Object} input + */ +function inputHandler(manager, eventType, input) { + var pointersLen = input.pointers.length; + var changedPointersLen = input.changedPointers.length; + var isFirst = eventType & INPUT_START && pointersLen - changedPointersLen === 0; + var isFinal = eventType & (INPUT_END | INPUT_CANCEL) && pointersLen - changedPointersLen === 0; + + input.isFirst = !!isFirst; + input.isFinal = !!isFinal; + + if (isFirst) { + manager.session = {}; + } + + // source event is the normalized value of the domEvents + // like 'touchstart, mouseup, pointerdown' + input.eventType = eventType; + + // compute scale, rotation etc + computeInputData(manager, input); + + // emit secret event + manager.emit('hammer.input', input); + + manager.recognize(input); + manager.session.prevInput = input; +} + +/** + * Created by arjun on 20/05/16. + */ + +/** + * split string on whitespace + * @param {String} str + * @returns {Array} words + */ +function splitStr(str) { + return str.trim().split(/\s+/g); +} + +/** + * addEventListener with multiple events at once + * @param {EventTarget} target + * @param {String} types + * @param {Function} handler + */ +function addEventListeners(target, types, handler) { + each(splitStr(types), function (type) { + target.addEventListener(type, handler, false); + }); +} + +/** + * removeEventListener with multiple events at once + * @param {EventTarget} target + * @param {String} types + * @param {Function} handler + */ +function removeEventListeners(target, types, handler) { + each(splitStr(types), function (type) { + target.removeEventListener(type, handler, false); + }); +} + +/** + * get the window object of an element + * @param {HTMLElement} element + * @returns {DocumentView|Window} + */ +function getWindowForElement(element) { + var doc = element.ownerDocument || element; + return doc.defaultView || doc.parentWindow || window; +} + +/** + * create new input type manager + * @param {Manager} manager + * @param {Function} callback + * @returns {Input} + * @constructor + */ +function Input(manager, callback) { + var self = this; + this.manager = manager; + this.callback = callback; + this.element = manager.element; + this.target = manager.options.inputTarget; + + // smaller wrapper around the handler, for the scope and the enabled state of the manager, + // so when disabled the input events are completely bypassed. + this.domHandler = function (ev) { + if (boolOrFn(manager.options.enable, [manager])) { + self.handler(ev); + } + }; + + this.init(); +} + +Input.prototype = { + /** + * should handle the inputEvent data and trigger the callback + * @virtual + */ + handler: function handler() {}, + + /** + * bind the events + */ + init: function init() { + this.evEl && addEventListeners(this.element, this.evEl, this.domHandler); + this.evTarget && addEventListeners(this.target, this.evTarget, this.domHandler); + this.evWin && addEventListeners(getWindowForElement(this.element), this.evWin, this.domHandler); + }, + + /** + * unbind the events + */ + destroy: function destroy() { + this.evEl && removeEventListeners(this.element, this.evEl, this.domHandler); + this.evTarget && removeEventListeners(this.target, this.evTarget, this.domHandler); + this.evWin && removeEventListeners(getWindowForElement(this.element), this.evWin, this.domHandler); + } +}; + +var POINTER_INPUT_MAP = { + pointerdown: INPUT_START, + pointermove: INPUT_MOVE, + pointerup: INPUT_END, + pointercancel: INPUT_CANCEL, + pointerout: INPUT_CANCEL +}; + +// in IE10 the pointer types is defined as an enum +var IE10_POINTER_TYPE_ENUM = { + 2: INPUT_TYPE_TOUCH, + 3: INPUT_TYPE_PEN, + 4: INPUT_TYPE_MOUSE, + 5: INPUT_TYPE_KINECT // see https://twitter.com/jacobrossi/status/480596438489890816 +}; + +var POINTER_ELEMENT_EVENTS = 'pointerdown'; +var POINTER_WINDOW_EVENTS = 'pointermove pointerup pointercancel'; + +// IE10 has prefixed support, and case-sensitive +if (window.MSPointerEvent && !window.PointerEvent) { + POINTER_ELEMENT_EVENTS = 'MSPointerDown'; + POINTER_WINDOW_EVENTS = 'MSPointerMove MSPointerUp MSPointerCancel'; +} + +/** + * Pointer events input + * @constructor + * @extends Input + */ +function PointerEventInput() { + this.evEl = POINTER_ELEMENT_EVENTS; + this.evWin = POINTER_WINDOW_EVENTS; + + Input.apply(this, arguments); + + this.store = this.manager.session.pointerEvents = []; +} + +inherit(PointerEventInput, Input, { + /** + * handle mouse events + * @param {Object} ev + */ + handler: function PEhandler(ev) { + var store = this.store; + var removePointer = false; + + var eventTypeNormalized = ev.type.toLowerCase().replace('ms', ''); + var eventType = POINTER_INPUT_MAP[eventTypeNormalized]; + var pointerType = IE10_POINTER_TYPE_ENUM[ev.pointerType] || ev.pointerType; + + var isTouch = pointerType == INPUT_TYPE_TOUCH; + + // get index of the event in the store + var storeIndex = inArray(store, ev.pointerId, 'pointerId'); + + // start and mouse must be down + if (eventType & INPUT_START && (ev.button === 0 || isTouch)) { + if (storeIndex < 0) { + store.push(ev); + storeIndex = store.length - 1; + } + } else if (eventType & (INPUT_END | INPUT_CANCEL)) { + removePointer = true; + } + + // it not found, so the pointer hasn't been down (so it's probably a hover) + if (storeIndex < 0) { + return; + } + + // update the event in the store + store[storeIndex] = ev; + + this.callback(this.manager, eventType, { + pointers: store, + changedPointers: [ev], + pointerType: pointerType, + srcEvent: ev + }); + + if (removePointer) { + // remove from the store + store.splice(storeIndex, 1); + } + } +}); + +/** + * Created by arjun on 20/05/16. + */ + +/** + * convert array-like objects to real arrays + * @param {Object} obj + * @returns {Array} + */ +function toArray(obj) { + return Array.prototype.slice.call(obj, 0); +} + +/** + * unique array with objects based on a key (like 'id') or just by the array's value + * @param {Array} src [{id:1},{id:2},{id:1}] + * @param {String} [key] + * @param {Boolean} [sort=False] + * @returns {Array} [{id:1},{id:2}] + */ +function uniqueArray(src, key, sort) { + var results = []; + var values = []; + var i = 0; + + while (i < src.length) { + var val = key ? src[i][key] : src[i]; + if (inArray(values, val) < 0) { + results.push(src[i]); + } + values[i] = val; + i++; + } + + if (sort) { + if (!key) { + results = results.sort(); + } else { + results = results.sort(function sortUniqueArray(a, b) { + return a[key] > b[key]; + }); + } + } + + return results; +} + +var TOUCH_INPUT_MAP = { + touchstart: INPUT_START, + touchmove: INPUT_MOVE, + touchend: INPUT_END, + touchcancel: INPUT_CANCEL +}; + +var TOUCH_TARGET_EVENTS = 'touchstart touchmove touchend touchcancel'; + +/** + * Multi-user touch events input + * @constructor + * @extends Input + */ +function TouchInput() { + this.evTarget = TOUCH_TARGET_EVENTS; + this.targetIds = {}; + + Input.apply(this, arguments); +} + +inherit(TouchInput, Input, { + handler: function MTEhandler(ev) { + var type = TOUCH_INPUT_MAP[ev.type]; + var touches = getTouches.call(this, ev, type); + if (!touches) { + return; + } + + this.callback(this.manager, type, { + pointers: touches[0], + changedPointers: touches[1], + pointerType: INPUT_TYPE_TOUCH, + srcEvent: ev + }); + } +}); + +/** + * @this {TouchInput} + * @param {Object} ev + * @param {Number} type flag + * @returns {undefined|Array} [all, changed] + */ +function getTouches(ev, type) { + var allTouches = toArray(ev.touches); + var targetIds = this.targetIds; + + // when there is only one touch, the process can be simplified + if (type & (INPUT_START | INPUT_MOVE) && allTouches.length === 1) { + targetIds[allTouches[0].identifier] = true; + return [allTouches, allTouches]; + } + + var i, + targetTouches, + changedTouches = toArray(ev.changedTouches), + changedTargetTouches = [], + target = this.target; + + // get target touches from touches + targetTouches = allTouches.filter(function (touch) { + return hasParent(touch.target, target); + }); + + // collect touches + if (type === INPUT_START) { + i = 0; + while (i < targetTouches.length) { + targetIds[targetTouches[i].identifier] = true; + i++; + } + } + + // filter changed touches to only contain touches that exist in the collected target ids + i = 0; + while (i < changedTouches.length) { + if (targetIds[changedTouches[i].identifier]) { + changedTargetTouches.push(changedTouches[i]); + } + + // cleanup removed touches + if (type & (INPUT_END | INPUT_CANCEL)) { + delete targetIds[changedTouches[i].identifier]; + } + i++; + } + + if (!changedTargetTouches.length) { + return; + } + + return [ + // merge targetTouches with changedTargetTouches so it contains ALL touches, including 'end' and 'cancel' + uniqueArray(targetTouches.concat(changedTargetTouches), 'identifier', true), changedTargetTouches]; +} + +var MOUSE_INPUT_MAP = { + mousedown: INPUT_START, + mousemove: INPUT_MOVE, + mouseup: INPUT_END +}; + +var MOUSE_ELEMENT_EVENTS = 'mousedown'; +var MOUSE_WINDOW_EVENTS = 'mousemove mouseup'; + +/** + * Mouse events input + * @constructor + * @extends Input + */ +function MouseInput() { + this.evEl = MOUSE_ELEMENT_EVENTS; + this.evWin = MOUSE_WINDOW_EVENTS; + + this.pressed = false; // mousedown state + + Input.apply(this, arguments); +} + +inherit(MouseInput, Input, { + /** + * handle mouse events + * @param {Object} ev + */ + handler: function MEhandler(ev) { + var eventType = MOUSE_INPUT_MAP[ev.type]; + + // on start we want to have the left mouse button down + if (eventType & INPUT_START && ev.button === 0) { + this.pressed = true; + } + + if (eventType & INPUT_MOVE && ev.which !== 1) { + eventType = INPUT_END; + } + + // mouse must be down + if (!this.pressed) { + return; + } + + if (eventType & INPUT_END) { + this.pressed = false; + } + + this.callback(this.manager, eventType, { + pointers: [ev], + changedPointers: [ev], + pointerType: INPUT_TYPE_MOUSE, + srcEvent: ev + }); + } +}); + +/** + * Combined touch and mouse input + * + * Touch has a higher priority then mouse, and while touching no mouse events are allowed. + * This because touch devices also emit mouse events while doing a touch. + * + * @constructor + * @extends Input + */ + +var DEDUP_TIMEOUT = 2500; +var DEDUP_DISTANCE = 25; + +function TouchMouseInput() { + Input.apply(this, arguments); + + var handler = bindFn(this.handler, this); + this.touch = new TouchInput(this.manager, handler); + this.mouse = new MouseInput(this.manager, handler); + + this.primaryTouch = null; + this.lastTouches = []; +} + +inherit(TouchMouseInput, Input, { + /** + * handle mouse and touch events + * @param {Hammer} manager + * @param {String} inputEvent + * @param {Object} inputData + */ + handler: function TMEhandler(manager, inputEvent, inputData) { + var isTouch = inputData.pointerType == INPUT_TYPE_TOUCH, + isMouse = inputData.pointerType == INPUT_TYPE_MOUSE; + + if (isMouse && inputData.sourceCapabilities && inputData.sourceCapabilities.firesTouchEvents) { + return; + } + + // when we're in a touch event, record touches to de-dupe synthetic mouse event + if (isTouch) { + recordTouches.call(this, inputEvent, inputData); + } else if (isMouse && isSyntheticEvent.call(this, inputData)) { + return; + } + + this.callback(manager, inputEvent, inputData); + }, + + /** + * remove the event listeners + */ + destroy: function destroy() { + this.touch.destroy(); + this.mouse.destroy(); + } +}); + +function recordTouches(eventType, eventData) { + if (eventType & INPUT_START) { + this.primaryTouch = eventData.changedPointers[0].identifier; + setLastTouch.call(this, eventData); + } else if (eventType & (INPUT_END | INPUT_CANCEL)) { + setLastTouch.call(this, eventData); + } +} + +function setLastTouch(eventData) { + var touch = eventData.changedPointers[0]; + + if (touch.identifier === this.primaryTouch) { + var lastTouch = { x: touch.clientX, y: touch.clientY }; + this.lastTouches.push(lastTouch); + var lts = this.lastTouches; + var removeLastTouch = function removeLastTouch() { + var i = lts.indexOf(lastTouch); + if (i > -1) { + lts.splice(i, 1); + } + }; + setTimeout(removeLastTouch, DEDUP_TIMEOUT); + } +} + +function isSyntheticEvent(eventData) { + var x = eventData.srcEvent.clientX, + y = eventData.srcEvent.clientY; + for (var i = 0; i < this.lastTouches.length; i++) { + var t = this.lastTouches[i]; + var dx = Math.abs(x - t.x), + dy = Math.abs(y - t.y); + if (dx <= DEDUP_DISTANCE && dy <= DEDUP_DISTANCE) { + return true; + } + } + return false; +} + +/** + * create new input type manager + * called by the Manager constructor + * @param {Hammer} manager + * @returns {Input} + */ +function createInputInstance(manager) { + var Type; + var inputClass = manager.options.inputClass; + + if (inputClass) { + Type = inputClass; + } else if (SUPPORT_POINTER_EVENTS) { + Type = PointerEventInput; + } else if (SUPPORT_ONLY_TOUCH) { + Type = TouchInput; + } else if (!SUPPORT_TOUCH) { + Type = MouseInput; + } else { + Type = TouchMouseInput; + } + return new Type(manager, inputHandler); +} + +var STOP = 1; +var FORCED_STOP = 2; + +/** + * Manager + * @param {HTMLElement} element + * @param {Object} [options] + * @constructor + */ +function Manager(element, options) { + this.options = assign({}, Hammer.defaults, options || {}); + + this.options.inputTarget = this.options.inputTarget || element; + + this.handlers = {}; + this.session = {}; + this.recognizers = []; + this.oldCssProps = {}; + + this.element = element; + this.input = createInputInstance(this); + this.touchAction = new TouchAction(this, this.options.touchAction); + + toggleCssProps(this, true); + + each(this.options.recognizers, function (item) { + var recognizer = this.add(new item[0](item[1])); + item[2] && recognizer.recognizeWith(item[2]); + item[3] && recognizer.requireFailure(item[3]); + }, this); +} + +Manager.prototype = { + /** + * set options + * @param {Object} options + * @returns {Manager} + */ + set: function set(options) { + assign(this.options, options); + + // Options that need a little more setup + if (options.touchAction) { + this.touchAction.update(); + } + if (options.inputTarget) { + // Clean up existing event listeners and reinitialize + this.input.destroy(); + this.input.target = options.inputTarget; + this.input.init(); + } + return this; + }, + + /** + * stop recognizing for this session. + * This session will be discarded, when a new [input]start event is fired. + * When forced, the recognizer cycle is stopped immediately. + * @param {Boolean} [force] + */ + stop: function stop(force) { + this.session.stopped = force ? FORCED_STOP : STOP; + }, + + /** + * run the recognizers! + * called by the inputHandler function on every movement of the pointers (touches) + * it walks through all the recognizers and tries to detect the gesture that is being made + * @param {Object} inputData + */ + recognize: function recognize(inputData) { + var session = this.session; + if (session.stopped) { + return; + } + + // run the touch-action polyfill + this.touchAction.preventDefaults(inputData); + + var recognizer; + var recognizers = this.recognizers; + + // this holds the recognizer that is being recognized. + // so the recognizer's state needs to be BEGAN, CHANGED, ENDED or RECOGNIZED + // if no recognizer is detecting a thing, it is set to `null` + var curRecognizer = session.curRecognizer; + + // reset when the last recognizer is recognized + // or when we're in a new session + if (!curRecognizer || curRecognizer && curRecognizer.state & STATE_RECOGNIZED) { + curRecognizer = session.curRecognizer = null; + } + + var i = 0; + while (i < recognizers.length) { + recognizer = recognizers[i]; + + // find out if we are allowed try to recognize the input for this one. + // 1. allow if the session is NOT forced stopped (see the .stop() method) + // 2. allow if we still haven't recognized a gesture in this session, or the this recognizer is the one + // that is being recognized. + // 3. allow if the recognizer is allowed to run simultaneous with the current recognized recognizer. + // this can be setup with the `recognizeWith()` method on the recognizer. + if (session.stopped !== FORCED_STOP && ( // 1 + !curRecognizer || recognizer == curRecognizer || // 2 + recognizer.canRecognizeWith(curRecognizer))) { + // 3 + recognizer.recognize(inputData); + } else { + recognizer.reset(); + } + + // if the recognizer has been recognizing the input as a valid gesture, we want to store this one as the + // current active recognizer. but only if we don't already have an active recognizer + if (!curRecognizer && recognizer.state & (STATE_BEGAN | STATE_CHANGED | STATE_ENDED)) { + curRecognizer = session.curRecognizer = recognizer; + } + i++; + } + }, + + /** + * get a recognizer by its event name. + * @param {Recognizer|String} recognizer + * @returns {Recognizer|Null} + */ + get: function get(recognizer) { + if (recognizer instanceof Recognizer) { + return recognizer; + } + + var recognizers = this.recognizers; + for (var i = 0; i < recognizers.length; i++) { + if (recognizers[i].options.event == recognizer) { + return recognizers[i]; + } + } + return null; + }, + + /** + * add a recognizer to the manager + * existing recognizers with the same event name will be removed + * @param {Recognizer} recognizer + * @returns {Recognizer|Manager} + */ + add: function add(recognizer) { + if (invokeArrayArg(recognizer, 'add', this)) { + return this; + } + + // remove existing + var existing = this.get(recognizer.options.event); + if (existing) { + this.remove(existing); + } + + this.recognizers.push(recognizer); + recognizer.manager = this; + + this.touchAction.update(); + return recognizer; + }, + + /** + * remove a recognizer by name or instance + * @param {Recognizer|String} recognizer + * @returns {Manager} + */ + remove: function remove(recognizer) { + if (invokeArrayArg(recognizer, 'remove', this)) { + return this; + } + + recognizer = this.get(recognizer); + + // let's make sure this recognizer exists + if (recognizer) { + var recognizers = this.recognizers; + var index = inArray(recognizers, recognizer); + + if (index !== -1) { + recognizers.splice(index, 1); + this.touchAction.update(); + } + } + + return this; + }, + + /** + * bind event + * @param {String} events + * @param {Function} handler + * @returns {EventEmitter} this + */ + on: function on(events, handler) { + if (events === undefined) { + return; + } + if (handler === undefined) { + return; + } + + var handlers = this.handlers; + each(splitStr(events), function (event) { + handlers[event] = handlers[event] || []; + handlers[event].push(handler); + }); + return this; + }, + + /** + * unbind event, leave emit blank to remove all handlers + * @param {String} events + * @param {Function} [handler] + * @returns {EventEmitter} this + */ + off: function off(events, handler) { + if (events === undefined) { + return; + } + + var handlers = this.handlers; + each(splitStr(events), function (event) { + if (!handler) { + delete handlers[event]; + } else { + handlers[event] && handlers[event].splice(inArray(handlers[event], handler), 1); + } + }); + return this; + }, + + /** + * emit event to the listeners + * @param {String} event + * @param {Object} data + */ + emit: function emit(event, data) { + // we also want to trigger dom events + if (this.options.domEvents) { + triggerDomEvent(event, data); + } + + // no handlers, so skip it all + var handlers = this.handlers[event] && this.handlers[event].slice(); + if (!handlers || !handlers.length) { + return; + } + + data.type = event; + data.preventDefault = function () { + data.srcEvent.preventDefault(); + }; + + var i = 0; + while (i < handlers.length) { + handlers[i](data); + i++; + } + }, + + /** + * destroy the manager and unbinds all events + * it doesn't unbind dom events, that is the user own responsibility + */ + destroy: function destroy() { + this.element && toggleCssProps(this, false); + + this.handlers = {}; + this.session = {}; + this.input.destroy(); + this.element = null; + } +}; + +/** + * add/remove the css properties as defined in manager.options.cssProps + * @param {Manager} manager + * @param {Boolean} add + */ +function toggleCssProps(manager, add) { + var element = manager.element; + if (!element.style) { + return; + } + var prop; + each(manager.options.cssProps, function (value, name) { + prop = prefixed(element.style, name); + if (add) { + manager.oldCssProps[prop] = element.style[prop]; + element.style[prop] = value; + } else { + element.style[prop] = manager.oldCssProps[prop] || ''; + } + }); + if (!add) { + manager.oldCssProps = {}; + } +} + +/** + * trigger dom event + * @param {String} event + * @param {Object} data + */ +function triggerDomEvent(event, data) { + var gestureEvent = document.createEvent('Event'); + gestureEvent.initEvent(event, true, true); + gestureEvent.gesture = data; + data.target.dispatchEvent(gestureEvent); +} + +/** + * Simple way to create a manager with a default set of recognizers. + * @param {HTMLElement} element + * @param {Object} [options] + * @constructor + */ +function Hammer(element, options) { + options = options || {}; + options.recognizers = ifUndefined(options.recognizers, Hammer.defaults.preset); + return new Manager(element, options); +} + +/** + * @const {string} + */ +Hammer.VERSION = '{{PKG_VERSION}}'; + +/** + * default settings + * @namespace + */ +Hammer.defaults = { + /** + * set if DOM events are being triggered. + * But this is slower and unused by simple implementations, so disabled by default. + * @type {Boolean} + * @default false + */ + domEvents: false, + + /** + * The value for the touchAction property/fallback. + * When set to `compute` it will magically set the correct value based on the added recognizers. + * @type {String} + * @default compute + */ + touchAction: TOUCH_ACTION_COMPUTE, + + /** + * @type {Boolean} + * @default true + */ + enable: true, + + /** + * EXPERIMENTAL FEATURE -- can be removed/changed + * Change the parent input target element. + * If Null, then it is being set the to main element. + * @type {Null|EventTarget} + * @default null + */ + inputTarget: null, + + /** + * force an input class + * @type {Null|Function} + * @default null + */ + inputClass: null, + + /** + * Default recognizer setup when calling `Hammer()` + * When creating a new Manager these will be skipped. + * @type {Array} + */ + preset: [ + // RecognizerClass, options, [recognizeWith, ...], [requireFailure, ...] + [RotateRecognizer, { enable: false }], [PinchRecognizer, { enable: false }, ['rotate']], [SwipeRecognizer, { direction: DIRECTION_HORIZONTAL }], [PanRecognizer, { direction: DIRECTION_HORIZONTAL }, ['swipe']], [TapRecognizer], [TapRecognizer, { event: 'doubletap', taps: 2 }, ['tap']], [PressRecognizer]], + + /** + * Some CSS properties can be used to improve the working of Hammer. + * Add them to this method and they will be set when creating a new Manager. + * @namespace + */ + cssProps: { + /** + * Disables text selection to improve the dragging gesture. Mainly for desktop browsers. + * @type {String} + * @default 'none' + */ + userSelect: 'none', + + /** + * Disable the Windows Phone grippers when pressing an element. + * @type {String} + * @default 'none' + */ + touchSelect: 'none', + + /** + * Disables the default callout shown when you touch and hold a touch target. + * On iOS, when you touch and hold a touch target such as a link, Safari displays + * a callout containing information about the link. This property allows you to disable that callout. + * @type {String} + * @default 'none' + */ + touchCallout: 'none', + + /** + * Specifies whether zooming is enabled. Used by IE10> + * @type {String} + * @default 'none' + */ + contentZooming: 'none', + + /** + * Specifies that an entire element should be draggable instead of its contents. Mainly for desktop browsers. + * @type {String} + * @default 'none' + */ + userDrag: 'none', + + /** + * Overrides the highlight color shown when the user taps a link or a JavaScript + * clickable element in iOS. This property obeys the alpha value, if specified. + * @type {String} + * @default 'rgba(0,0,0,0)' + */ + tapHighlightColor: 'rgba(0,0,0,0)' + } +}; +})(window, document, 'Hammer'); + +export { Hammer }; \ No newline at end of file diff --git a/rollup.config.js b/rollup.config.js new file mode 100644 index 000000000..026d4c394 --- /dev/null +++ b/rollup.config.js @@ -0,0 +1,16 @@ +/** + * Created by arjun on 28/05/16. + */ + +import babel from 'rollup-plugin-babel'; + +export default { + entry: 'src/main.js', + format: 'es6', + // moduleName: 'HAMMER', + plugins: [ babel({exclude: 'node_modules/**'}) ], + dest: 'bundle.js', + intro: " (function(window, document, exportName, undefined) { \n'use strict' ", + outro: "})(window, document, 'Hammer');" + +}; \ No newline at end of file diff --git a/src/.babelrc b/src/.babelrc new file mode 100644 index 000000000..13b76880d --- /dev/null +++ b/src/.babelrc @@ -0,0 +1,3 @@ +{ + "presets": ["es2015-rollup"] +} \ No newline at end of file diff --git a/src/hammer.js b/src/hammer.js index f3ace1f61..f97581722 100644 --- a/src/hammer.js +++ b/src/hammer.js @@ -1,3 +1,14 @@ +import {ifUndefined} from './utilsjs/ifUndefined'; +import {TOUCH_ACTION_COMPUTE} from './touchactionjs/touchactionConsts'; +import {DIRECTION_HORIZONTAL} from './inputjs/inputConsts' +import {RotateRecognizer} from './recognizers/rotate'; +import {PinchRecognizer} from './recognizers/pinch'; +import {SwipeRecognizer} from './recognizers/swipe'; +import {PanRecognizer} from './recognizers/pan'; +import {TapRecognizer} from './recognizers/tap'; +import {PressRecognizer} from './recognizers/press'; +import {Manager} from './manager'; + /** * Simple way to create a manager with a default set of recognizers. * @param {HTMLElement} element @@ -126,3 +137,5 @@ Hammer.defaults = { tapHighlightColor: 'rgba(0,0,0,0)' } }; + +export {Hammer}; \ No newline at end of file diff --git a/src/hammer.prefix.js b/src/hammer.prefix.js deleted file mode 100644 index debc7fff2..000000000 --- a/src/hammer.prefix.js +++ /dev/null @@ -1,2 +0,0 @@ -(function(window, document, exportName, undefined) { - 'use strict'; diff --git a/src/hammer.suffix.js b/src/hammer.suffix.js deleted file mode 100644 index 41bfecfc2..000000000 --- a/src/hammer.suffix.js +++ /dev/null @@ -1 +0,0 @@ -})(window, document, 'Hammer'); diff --git a/src/input.js b/src/input.js deleted file mode 100644 index e9601ca68..000000000 --- a/src/input.js +++ /dev/null @@ -1,394 +0,0 @@ -var MOBILE_REGEX = /mobile|tablet|ip(ad|hone|od)|android/i; - -var SUPPORT_TOUCH = ('ontouchstart' in window); -var SUPPORT_POINTER_EVENTS = prefixed(window, 'PointerEvent') !== undefined; -var SUPPORT_ONLY_TOUCH = SUPPORT_TOUCH && MOBILE_REGEX.test(navigator.userAgent); - -var INPUT_TYPE_TOUCH = 'touch'; -var INPUT_TYPE_PEN = 'pen'; -var INPUT_TYPE_MOUSE = 'mouse'; -var INPUT_TYPE_KINECT = 'kinect'; - -var COMPUTE_INTERVAL = 25; - -var INPUT_START = 1; -var INPUT_MOVE = 2; -var INPUT_END = 4; -var INPUT_CANCEL = 8; - -var DIRECTION_NONE = 1; -var DIRECTION_LEFT = 2; -var DIRECTION_RIGHT = 4; -var DIRECTION_UP = 8; -var DIRECTION_DOWN = 16; - -var DIRECTION_HORIZONTAL = DIRECTION_LEFT | DIRECTION_RIGHT; -var DIRECTION_VERTICAL = DIRECTION_UP | DIRECTION_DOWN; -var DIRECTION_ALL = DIRECTION_HORIZONTAL | DIRECTION_VERTICAL; - -var PROPS_XY = ['x', 'y']; -var PROPS_CLIENT_XY = ['clientX', 'clientY']; - -/** - * create new input type manager - * @param {Manager} manager - * @param {Function} callback - * @returns {Input} - * @constructor - */ -function Input(manager, callback) { - var self = this; - this.manager = manager; - this.callback = callback; - this.element = manager.element; - this.target = manager.options.inputTarget; - - // smaller wrapper around the handler, for the scope and the enabled state of the manager, - // so when disabled the input events are completely bypassed. - this.domHandler = function(ev) { - if (boolOrFn(manager.options.enable, [manager])) { - self.handler(ev); - } - }; - - this.init(); - -} - -Input.prototype = { - /** - * should handle the inputEvent data and trigger the callback - * @virtual - */ - handler: function() { }, - - /** - * bind the events - */ - init: function() { - this.evEl && addEventListeners(this.element, this.evEl, this.domHandler); - this.evTarget && addEventListeners(this.target, this.evTarget, this.domHandler); - this.evWin && addEventListeners(getWindowForElement(this.element), this.evWin, this.domHandler); - }, - - /** - * unbind the events - */ - destroy: function() { - this.evEl && removeEventListeners(this.element, this.evEl, this.domHandler); - this.evTarget && removeEventListeners(this.target, this.evTarget, this.domHandler); - this.evWin && removeEventListeners(getWindowForElement(this.element), this.evWin, this.domHandler); - } -}; - -/** - * create new input type manager - * called by the Manager constructor - * @param {Hammer} manager - * @returns {Input} - */ -function createInputInstance(manager) { - var Type; - var inputClass = manager.options.inputClass; - - if (inputClass) { - Type = inputClass; - } else if (SUPPORT_POINTER_EVENTS) { - Type = PointerEventInput; - } else if (SUPPORT_ONLY_TOUCH) { - Type = TouchInput; - } else if (!SUPPORT_TOUCH) { - Type = MouseInput; - } else { - Type = TouchMouseInput; - } - return new (Type)(manager, inputHandler); -} - -/** - * handle input events - * @param {Manager} manager - * @param {String} eventType - * @param {Object} input - */ -function inputHandler(manager, eventType, input) { - var pointersLen = input.pointers.length; - var changedPointersLen = input.changedPointers.length; - var isFirst = (eventType & INPUT_START && (pointersLen - changedPointersLen === 0)); - var isFinal = (eventType & (INPUT_END | INPUT_CANCEL) && (pointersLen - changedPointersLen === 0)); - - input.isFirst = !!isFirst; - input.isFinal = !!isFinal; - - if (isFirst) { - manager.session = {}; - } - - // source event is the normalized value of the domEvents - // like 'touchstart, mouseup, pointerdown' - input.eventType = eventType; - - // compute scale, rotation etc - computeInputData(manager, input); - - // emit secret event - manager.emit('hammer.input', input); - - manager.recognize(input); - manager.session.prevInput = input; -} - -/** - * extend the data with some usable properties like scale, rotate, velocity etc - * @param {Object} manager - * @param {Object} input - */ -function computeInputData(manager, input) { - var session = manager.session; - var pointers = input.pointers; - var pointersLength = pointers.length; - - // store the first input to calculate the distance and direction - if (!session.firstInput) { - session.firstInput = simpleCloneInputData(input); - } - - // to compute scale and rotation we need to store the multiple touches - if (pointersLength > 1 && !session.firstMultiple) { - session.firstMultiple = simpleCloneInputData(input); - } else if (pointersLength === 1) { - session.firstMultiple = false; - } - - var firstInput = session.firstInput; - var firstMultiple = session.firstMultiple; - var offsetCenter = firstMultiple ? firstMultiple.center : firstInput.center; - - var center = input.center = getCenter(pointers); - input.timeStamp = now(); - input.deltaTime = input.timeStamp - firstInput.timeStamp; - - input.angle = getAngle(offsetCenter, center); - input.distance = getDistance(offsetCenter, center); - - computeDeltaXY(session, input); - input.offsetDirection = getDirection(input.deltaX, input.deltaY); - - var overallVelocity = getVelocity(input.deltaTime, input.deltaX, input.deltaY); - input.overallVelocityX = overallVelocity.x; - input.overallVelocityY = overallVelocity.y; - input.overallVelocity = (abs(overallVelocity.x) > abs(overallVelocity.y)) ? overallVelocity.x : overallVelocity.y; - - input.scale = firstMultiple ? getScale(firstMultiple.pointers, pointers) : 1; - input.rotation = firstMultiple ? getRotation(firstMultiple.pointers, pointers) : 0; - - input.maxPointers = !session.prevInput ? input.pointers.length : ((input.pointers.length > - session.prevInput.maxPointers) ? input.pointers.length : session.prevInput.maxPointers); - - computeIntervalInputData(session, input); - - // find the correct target - var target = manager.element; - if (hasParent(input.srcEvent.target, target)) { - target = input.srcEvent.target; - } - input.target = target; -} - -function computeDeltaXY(session, input) { - var center = input.center; - var offset = session.offsetDelta || {}; - var prevDelta = session.prevDelta || {}; - var prevInput = session.prevInput || {}; - - if (input.eventType === INPUT_START || prevInput.eventType === INPUT_END) { - prevDelta = session.prevDelta = { - x: prevInput.deltaX || 0, - y: prevInput.deltaY || 0 - }; - - offset = session.offsetDelta = { - x: center.x, - y: center.y - }; - } - - input.deltaX = prevDelta.x + (center.x - offset.x); - input.deltaY = prevDelta.y + (center.y - offset.y); -} - -/** - * velocity is calculated every x ms - * @param {Object} session - * @param {Object} input - */ -function computeIntervalInputData(session, input) { - var last = session.lastInterval || input, - deltaTime = input.timeStamp - last.timeStamp, - velocity, velocityX, velocityY, direction; - - if (input.eventType != INPUT_CANCEL && (deltaTime > COMPUTE_INTERVAL || last.velocity === undefined)) { - var deltaX = input.deltaX - last.deltaX; - var deltaY = input.deltaY - last.deltaY; - - var v = getVelocity(deltaTime, deltaX, deltaY); - velocityX = v.x; - velocityY = v.y; - velocity = (abs(v.x) > abs(v.y)) ? v.x : v.y; - direction = getDirection(deltaX, deltaY); - - session.lastInterval = input; - } else { - // use latest velocity info if it doesn't overtake a minimum period - velocity = last.velocity; - velocityX = last.velocityX; - velocityY = last.velocityY; - direction = last.direction; - } - - input.velocity = velocity; - input.velocityX = velocityX; - input.velocityY = velocityY; - input.direction = direction; -} - -/** - * create a simple clone from the input used for storage of firstInput and firstMultiple - * @param {Object} input - * @returns {Object} clonedInputData - */ -function simpleCloneInputData(input) { - // make a simple copy of the pointers because we will get a reference if we don't - // we only need clientXY for the calculations - var pointers = []; - var i = 0; - while (i < input.pointers.length) { - pointers[i] = { - clientX: round(input.pointers[i].clientX), - clientY: round(input.pointers[i].clientY) - }; - i++; - } - - return { - timeStamp: now(), - pointers: pointers, - center: getCenter(pointers), - deltaX: input.deltaX, - deltaY: input.deltaY - }; -} - -/** - * get the center of all the pointers - * @param {Array} pointers - * @return {Object} center contains `x` and `y` properties - */ -function getCenter(pointers) { - var pointersLength = pointers.length; - - // no need to loop when only one touch - if (pointersLength === 1) { - return { - x: round(pointers[0].clientX), - y: round(pointers[0].clientY) - }; - } - - var x = 0, y = 0, i = 0; - while (i < pointersLength) { - x += pointers[i].clientX; - y += pointers[i].clientY; - i++; - } - - return { - x: round(x / pointersLength), - y: round(y / pointersLength) - }; -} - -/** - * calculate the velocity between two points. unit is in px per ms. - * @param {Number} deltaTime - * @param {Number} x - * @param {Number} y - * @return {Object} velocity `x` and `y` - */ -function getVelocity(deltaTime, x, y) { - return { - x: x / deltaTime || 0, - y: y / deltaTime || 0 - }; -} - -/** - * get the direction between two points - * @param {Number} x - * @param {Number} y - * @return {Number} direction - */ -function getDirection(x, y) { - if (x === y) { - return DIRECTION_NONE; - } - - if (abs(x) >= abs(y)) { - return x < 0 ? DIRECTION_LEFT : DIRECTION_RIGHT; - } - return y < 0 ? DIRECTION_UP : DIRECTION_DOWN; -} - -/** - * calculate the absolute distance between two points - * @param {Object} p1 {x, y} - * @param {Object} p2 {x, y} - * @param {Array} [props] containing x and y keys - * @return {Number} distance - */ -function getDistance(p1, p2, props) { - if (!props) { - props = PROPS_XY; - } - var x = p2[props[0]] - p1[props[0]], - y = p2[props[1]] - p1[props[1]]; - - return Math.sqrt((x * x) + (y * y)); -} - -/** - * calculate the angle between two coordinates - * @param {Object} p1 - * @param {Object} p2 - * @param {Array} [props] containing x and y keys - * @return {Number} angle - */ -function getAngle(p1, p2, props) { - if (!props) { - props = PROPS_XY; - } - var x = p2[props[0]] - p1[props[0]], - y = p2[props[1]] - p1[props[1]]; - return Math.atan2(y, x) * 180 / Math.PI; -} - -/** - * calculate the rotation degrees between two pointersets - * @param {Array} start array of pointers - * @param {Array} end array of pointers - * @return {Number} rotation - */ -function getRotation(start, end) { - return getAngle(end[1], end[0], PROPS_CLIENT_XY) + getAngle(start[1], start[0], PROPS_CLIENT_XY); -} - -/** - * calculate the scale factor between two pointersets - * no scale is 1, and goes down to 0 when pinched together, and bigger when pinched out - * @param {Array} start array of pointers - * @param {Array} end array of pointers - * @return {Number} scale - */ -function getScale(start, end) { - return getDistance(end[0], end[1], PROPS_CLIENT_XY) / getDistance(start[0], start[1], PROPS_CLIENT_XY); -} diff --git a/src/inputjs/computeDeltaXY.js b/src/inputjs/computeDeltaXY.js index 967be7af5..b28718d8f 100644 --- a/src/inputjs/computeDeltaXY.js +++ b/src/inputjs/computeDeltaXY.js @@ -2,6 +2,7 @@ * Created by arjun on 20/05/16. */ import {INPUT_START,INPUT_END} from './inputConsts' + function computeDeltaXY(session, input) { var center = input.center; var offset = session.offsetDelta || {}; diff --git a/src/inputjs/createInputInstance.js b/src/inputjs/createInputInstance.js index 818639067..f1b76e02e 100644 --- a/src/inputjs/createInputInstance.js +++ b/src/inputjs/createInputInstance.js @@ -4,6 +4,10 @@ */ import {SUPPORT_POINTER_EVENTS,SUPPORT_ONLY_TOUCH,SUPPORT_TOUCH} from './inputConsts' import {inputHandler} from './inputHandler' +import {PointerEventInput} from '../input/pointerevent'; +import {TouchInput} from '../input/touch'; +import {MouseInput} from '../input/mouse'; +import {TouchMouseInput} from '../input/touchmouse'; /** * create new input type manager * called by the Manager constructor diff --git a/src/inputjs/inputConsts.js b/src/inputjs/inputConsts.js index 44a1c20bb..d1ff1d735 100644 --- a/src/inputjs/inputConsts.js +++ b/src/inputjs/inputConsts.js @@ -1,6 +1,7 @@ /** * Created by arjun on 19/05/16. */ +import {prefixed} from '../utilsjs/prefixed' var MOBILE_REGEX = /mobile|tablet|ip(ad|hone|od)|android/i; diff --git a/src/main.js b/src/main.js new file mode 100644 index 000000000..8c8652c33 --- /dev/null +++ b/src/main.js @@ -0,0 +1 @@ +export {Hammer} from './hammer'; \ No newline at end of file diff --git a/src/manager.js b/src/manager.js index 5a5e97e4e..ccce800c5 100644 --- a/src/manager.js +++ b/src/manager.js @@ -1,3 +1,16 @@ +import {assign} from './utilsjs/assign'; +import {Hammer} from './hammer'; +import {TouchAction} from './touchactionjs/touchActionConstructor'; +import {createInputInstance} from './inputjs/createInputInstance'; +import {each} from './utilsjs/each'; +import {inArray} from './utilsjs/inArray'; +import {invokeArrayArg} from './utilsjs/invokeArrayArg'; +import {splitStr} from './utilsjs/splitStr'; +import {prefixed} from './utilsjs/prefixed'; +import {Recognizer} from './recognizerjs/recognizerConstructor'; +import {STATE_BEGAN,STATE_ENDED,STATE_CHANGED,STATE_RECOGNIZED} from './recognizerjs/recognizerConsts'; + + var STOP = 1; var FORCED_STOP = 2; @@ -310,3 +323,5 @@ function triggerDomEvent(event, data) { gestureEvent.gesture = data; data.target.dispatchEvent(gestureEvent); } + +export {Manager} \ No newline at end of file diff --git a/src/recognizerjs/directionStr.js b/src/recognizerjs/directionStr.js new file mode 100644 index 000000000..88f61b61b --- /dev/null +++ b/src/recognizerjs/directionStr.js @@ -0,0 +1,23 @@ +/** + * Created by arjun on 25/05/16. + */ +import {DIRECTION_LEFT,DIRECTION_RIGHT,DIRECTION_UP,DIRECTION_DOWN} from '../inputjs/inputConsts' +/** + * direction cons to string + * @param {constant} direction + * @returns {String} + */ +function directionStr(direction) { + if (direction == DIRECTION_DOWN) { + return 'down'; + } else if (direction == DIRECTION_UP) { + return 'up'; + } else if (direction == DIRECTION_LEFT) { + return 'left'; + } else if (direction == DIRECTION_RIGHT) { + return 'right'; + } + return ''; +} + +export {directionStr} \ No newline at end of file diff --git a/src/recognizerjs/getRecognizerByNameIfManager.js b/src/recognizerjs/getRecognizerByNameIfManager.js new file mode 100644 index 000000000..04ae3fe3b --- /dev/null +++ b/src/recognizerjs/getRecognizerByNameIfManager.js @@ -0,0 +1,20 @@ +/** + * Created by arjun on 25/05/16. + */ + + +/** + * get a recognizer by name if it is bound to a manager + * @param {Recognizer|String} otherRecognizer + * @param {Recognizer} recognizer + * @returns {Recognizer} + */ +function getRecognizerByNameIfManager(otherRecognizer, recognizer) { + var manager = recognizer.manager; + if (manager) { + return manager.get(otherRecognizer); + } + return otherRecognizer; +} + +export {getRecognizerByNameIfManager}; \ No newline at end of file diff --git a/src/recognizer.js b/src/recognizerjs/recognizerConstructor.js similarity index 85% rename from src/recognizer.js rename to src/recognizerjs/recognizerConstructor.js index b0dd9fa04..f7696ffc5 100644 --- a/src/recognizer.js +++ b/src/recognizerjs/recognizerConstructor.js @@ -1,3 +1,15 @@ +/** + * Created by arjun on 25/05/16. + */ +import {STATE_POSSIBLE,STATE_ENDED,STATE_FAILED,STATE_RECOGNIZED,STATE_CANCELLED,STATE_BEGAN,STATE_CHANGED} from './recognizerConsts' +import {assign} from '../utilsjs/assign'; +import {uniqueId} from '../utilsjs/uniqueId'; +import {ifUndefined} from '../utilsjs/ifUndefined'; +import {invokeArrayArg} from '../utilsjs/invokeArrayArg'; +import {inArray} from '../utilsjs/inArray'; +import {boolOrFn} from '../utilsjs/boolOrFn'; +import {getRecognizerByNameIfManager} from './getRecognizerByNameIfManager' +import {stateStr} from './stateStr' /** * Recognizer flow explained; * * All recognizers have the initial state of POSSIBLE when a input session starts. @@ -25,13 +37,6 @@ * | * Ended/Recognized */ -var STATE_POSSIBLE = 1; -var STATE_BEGAN = 2; -var STATE_CHANGED = 4; -var STATE_ENDED = 8; -var STATE_RECOGNIZED = STATE_ENDED; -var STATE_CANCELLED = 16; -var STATE_FAILED = 32; /** * Recognizer @@ -257,7 +262,7 @@ Recognizer.prototype = { * the actual recognizing happens in this method * @virtual * @param {Object} inputData - * @returns {Const} STATE + * @returns {constant} STATE */ process: function(inputData) { }, // jshint ignore:line @@ -276,52 +281,4 @@ Recognizer.prototype = { reset: function() { } }; -/** - * get a usable string, used as event postfix - * @param {Const} state - * @returns {String} state - */ -function stateStr(state) { - if (state & STATE_CANCELLED) { - return 'cancel'; - } else if (state & STATE_ENDED) { - return 'end'; - } else if (state & STATE_CHANGED) { - return 'move'; - } else if (state & STATE_BEGAN) { - return 'start'; - } - return ''; -} - -/** - * direction cons to string - * @param {Const} direction - * @returns {String} - */ -function directionStr(direction) { - if (direction == DIRECTION_DOWN) { - return 'down'; - } else if (direction == DIRECTION_UP) { - return 'up'; - } else if (direction == DIRECTION_LEFT) { - return 'left'; - } else if (direction == DIRECTION_RIGHT) { - return 'right'; - } - return ''; -} - -/** - * get a recognizer by name if it is bound to a manager - * @param {Recognizer|String} otherRecognizer - * @param {Recognizer} recognizer - * @returns {Recognizer} - */ -function getRecognizerByNameIfManager(otherRecognizer, recognizer) { - var manager = recognizer.manager; - if (manager) { - return manager.get(otherRecognizer); - } - return otherRecognizer; -} +export {Recognizer} ; \ No newline at end of file diff --git a/src/recognizerjs/recognizerConsts.js b/src/recognizerjs/recognizerConsts.js new file mode 100644 index 000000000..4b3da4cd6 --- /dev/null +++ b/src/recognizerjs/recognizerConsts.js @@ -0,0 +1,14 @@ +/** + * Created by arjun on 25/05/16. + */ + + +var STATE_POSSIBLE = 1; +var STATE_BEGAN = 2; +var STATE_CHANGED = 4; +var STATE_ENDED = 8; +var STATE_RECOGNIZED = STATE_ENDED; +var STATE_CANCELLED = 16; +var STATE_FAILED = 32; + +export {STATE_POSSIBLE,STATE_BEGAN,STATE_CHANGED,STATE_ENDED,STATE_RECOGNIZED,STATE_CANCELLED,STATE_FAILED}; \ No newline at end of file diff --git a/src/recognizerjs/stateStr.js b/src/recognizerjs/stateStr.js new file mode 100644 index 000000000..ffd439399 --- /dev/null +++ b/src/recognizerjs/stateStr.js @@ -0,0 +1,23 @@ +/** + * Created by arjun on 25/05/16. + */ +import {STATE_CANCELLED,STATE_ENDED,STATE_CHANGED,STATE_BEGAN} from './recognizerConsts' +/** + * get a usable string, used as event postfix + * @param {constant} state + * @returns {String} state + */ +function stateStr(state) { + if (state & STATE_CANCELLED) { + return 'cancel'; + } else if (state & STATE_ENDED) { + return 'end'; + } else if (state & STATE_CHANGED) { + return 'move'; + } else if (state & STATE_BEGAN) { + return 'start'; + } + return ''; +} + +export {stateStr} \ No newline at end of file diff --git a/src/recognizers/attribute.js b/src/recognizers/attribute.js index 0d7fff4c6..533f0946c 100644 --- a/src/recognizers/attribute.js +++ b/src/recognizers/attribute.js @@ -1,3 +1,8 @@ +import {inherit} from '../utilsjs/inherit'; +import {Recognizer} from '../recognizerjs/recognizerConstructor' +import {STATE_BEGAN,STATE_CHANGED,STATE_CANCELLED,STATE_ENDED,STATE_FAILED} from '../recognizerjs/recognizerConsts'; +import {INPUT_CANCEL,INPUT_END} from '../inputjs/inputConsts'; + /** * This recognizer is just used as a base for the simple attribute recognizers. * @constructor @@ -58,3 +63,5 @@ inherit(AttrRecognizer, Recognizer, { return STATE_FAILED; } }); + +export {AttrRecognizer} diff --git a/src/recognizers/pan.js b/src/recognizers/pan.js index 8cc3398e4..28f0ea0e7 100644 --- a/src/recognizers/pan.js +++ b/src/recognizers/pan.js @@ -1,3 +1,11 @@ +import {AttrRecognizer} from './attribute' +import {inherit} from '../utilsjs/inherit' +import {DIRECTION_ALL,DIRECTION_HORIZONTAL,DIRECTION_VERTICAL,DIRECTION_NONE,DIRECTION_UP,DIRECTION_DOWN, +DIRECTION_LEFT,DIRECTION_RIGHT} from '../inputjs/inputConsts' +import {STATE_BEGAN} from '../recognizerjs/recognizerConsts' +import {TOUCH_ACTION_PAN_X,TOUCH_ACTION_PAN_Y} from '../touchactionjs/touchactionConsts' +import {directionStr} from '../recognizerjs/directionStr' + /** * Pan * Recognized when the pointer is down and moved in the allowed direction. @@ -77,3 +85,5 @@ inherit(PanRecognizer, AttrRecognizer, { this._super.emit.call(this, input); } }); + +export {PanRecognizer}; \ No newline at end of file diff --git a/src/recognizers/pinch.js b/src/recognizers/pinch.js index cc19b3075..f978cae43 100644 --- a/src/recognizers/pinch.js +++ b/src/recognizers/pinch.js @@ -1,3 +1,7 @@ +import {AttrRecognizer} from './attribute'; +import {inherit} from '../utilsjs/inherit'; +import {TOUCH_ACTION_NONE} from '../touchactionjs/touchactionConsts'; +import {STATE_BEGAN} from '../recognizerjs/recognizerConsts' /** * Pinch * Recognized when two or more pointers are moving toward (zoom-in) or away from each other (zoom-out). @@ -36,3 +40,5 @@ inherit(PinchRecognizer, AttrRecognizer, { this._super.emit.call(this, input); } }); + +export {PinchRecognizer}; \ No newline at end of file diff --git a/src/recognizers/press.js b/src/recognizers/press.js index d52f830cf..bba59bfb2 100644 --- a/src/recognizers/press.js +++ b/src/recognizers/press.js @@ -1,3 +1,11 @@ +import {Recognizer} from '../recognizerjs/recognizerConstructor'; +import {STATE_RECOGNIZED,STATE_FAILED} from '../recognizerjs/recognizerConsts'; +import {inherit} from '../utilsjs/inherit'; +import {now} from '../utilsjs/utilsConsts'; +import {setTimeoutContext} from '../utilsjs/setTimeoutContext'; +import {TOUCH_ACTION_AUTO} from '../touchactionjs/touchactionConsts'; +import {INPUT_START,INPUT_END,INPUT_CANCEL} from '../inputjs/inputConsts' + /** * Press * Recognized when the pointer is down for x ms without any movement. @@ -68,3 +76,5 @@ inherit(PressRecognizer, Recognizer, { } } }); + +export {PressRecognizer}; \ No newline at end of file diff --git a/src/recognizers/rotate.js b/src/recognizers/rotate.js index 207982406..8895a5420 100644 --- a/src/recognizers/rotate.js +++ b/src/recognizers/rotate.js @@ -1,3 +1,7 @@ +import {AttrRecognizer} from './attribute'; +import {inherit} from '../utilsjs/inherit'; +import {TOUCH_ACTION_NONE} from '../touchactionjs/touchactionConsts'; +import {STATE_BEGAN} from '../recognizerjs/recognizerConsts' /** * Rotate * Recognized when two or more pointer are moving in a circular motion. @@ -28,3 +32,5 @@ inherit(RotateRecognizer, AttrRecognizer, { (Math.abs(input.rotation) > this.options.threshold || this.state & STATE_BEGAN); } }); + +export {RotateRecognizer}; \ No newline at end of file diff --git a/src/recognizers/swipe.js b/src/recognizers/swipe.js index fb3d66c77..be429dbee 100644 --- a/src/recognizers/swipe.js +++ b/src/recognizers/swipe.js @@ -1,3 +1,11 @@ +import {AttrRecognizer} from '../recognizers/attribute'; +import {inherit} from '../utilsjs/inherit'; +import {abs} from '../utilsjs/utilsConsts'; +import {DIRECTION_HORIZONTAL,DIRECTION_VERTICAL} from '../inputjs/inputConsts'; +import {PanRecognizer} from './pan'; +import {INPUT_END} from '../inputjs/inputConsts'; +import {directionStr} from '../recognizerjs/directionStr'; + /** * Swipe * Recognized when the pointer is moving fast (velocity), with enough distance in the allowed direction. @@ -53,3 +61,5 @@ inherit(SwipeRecognizer, AttrRecognizer, { this.manager.emit(this.options.event, input); } }); + +export {SwipeRecognizer}; diff --git a/src/recognizers/tap.js b/src/recognizers/tap.js index 072d45c94..9d9b995e5 100644 --- a/src/recognizers/tap.js +++ b/src/recognizers/tap.js @@ -1,3 +1,10 @@ +import {inherit} from '../utilsjs/inherit'; +import {setTimeoutContext} from '../utilsjs/setTimeoutContext'; +import {Recognizer} from '../recognizerjs/recognizerConstructor'; +import {TOUCH_ACTION_MANIPULATION} from '../touchactionjs/touchactionConsts'; +import {INPUT_START,INPUT_END} from '../inputjs/inputConsts'; +import {STATE_RECOGNIZED,STATE_BEGAN,STATE_FAILED} from '../recognizerjs/recognizerConsts' +import {getDistance} from '../inputjs/getDistance'; /** * A tap is ecognized when the pointer is doing a small tap/click. Multiple taps are recognized if they occur * between the given interval and position. The delay option can be used to recognize multi-taps without firing @@ -112,3 +119,5 @@ inherit(TapRecognizer, Recognizer, { } } }); + +export {TapRecognizer}; \ No newline at end of file diff --git a/src/touchactionjs/cleanTouchActions.js b/src/touchactionjs/cleanTouchActions.js new file mode 100644 index 000000000..ed9af1616 --- /dev/null +++ b/src/touchactionjs/cleanTouchActions.js @@ -0,0 +1,43 @@ +/* + * Created by arjun on 28/05/16. + */ +import {inStr} from '../utilsjs/inStr'; +import {TOUCH_ACTION_NONE,TOUCH_ACTION_PAN_X,TOUCH_ACTION_PAN_Y,TOUCH_ACTION_MANIPULATION, +TOUCH_ACTION_AUTO} from './touchactionConsts' + +/** + * when the touchActions are collected they are not a valid value, so we need to clean things up. * + * @param {String} actions + * @returns {*} + */ +function cleanTouchActions(actions) { + // none + if (inStr(actions, TOUCH_ACTION_NONE)) { + return TOUCH_ACTION_NONE; + } + + var hasPanX = inStr(actions, TOUCH_ACTION_PAN_X); + var hasPanY = inStr(actions, TOUCH_ACTION_PAN_Y); + + // if both pan-x and pan-y are set (different recognizers + // for different directions, e.g. horizontal pan but vertical swipe?) + // we need none (as otherwise with pan-x pan-y combined none of these + // recognizers will work, since the browser would handle all panning + if (hasPanX && hasPanY) { + return TOUCH_ACTION_NONE; + } + + // pan-x OR pan-y + if (hasPanX || hasPanY) { + return hasPanX ? TOUCH_ACTION_PAN_X : TOUCH_ACTION_PAN_Y; + } + + // manipulation + if (inStr(actions, TOUCH_ACTION_MANIPULATION)) { + return TOUCH_ACTION_MANIPULATION; + } + + return TOUCH_ACTION_AUTO; +} + +export {cleanTouchActions} \ No newline at end of file diff --git a/src/touchactionjs/getTouchActionProps.js b/src/touchactionjs/getTouchActionProps.js new file mode 100644 index 000000000..1c49843a5 --- /dev/null +++ b/src/touchactionjs/getTouchActionProps.js @@ -0,0 +1,20 @@ +/* + * Created by arjun on 28/05/16. + */ +import {NATIVE_TOUCH_ACTION} from './touchactionConsts' +function getTouchActionProps() { + if (!NATIVE_TOUCH_ACTION) { + return false; + } + var touchMap = {}; + var cssSupports = window.CSS && window.CSS.supports; + ['auto', 'manipulation', 'pan-y', 'pan-x', 'pan-x pan-y', 'none'].forEach(function(val) { + + // If css.supports is not supported but there is native touch-action assume it supports + // all values. This is the case for IE 10 and 11. + touchMap[val] = cssSupports ? window.CSS.supports('touch-action', val) : true; + }); + return touchMap; +} + +export {getTouchActionProps} diff --git a/src/touchaction.js b/src/touchactionjs/touchActionConstructor.js similarity index 61% rename from src/touchaction.js rename to src/touchactionjs/touchActionConstructor.js index 55609012b..0f3375a8e 100644 --- a/src/touchaction.js +++ b/src/touchactionjs/touchActionConstructor.js @@ -1,15 +1,14 @@ -var PREFIXED_TOUCH_ACTION = prefixed(TEST_ELEMENT.style, 'touchAction'); -var NATIVE_TOUCH_ACTION = PREFIXED_TOUCH_ACTION !== undefined; - -// magical touchAction value -var TOUCH_ACTION_COMPUTE = 'compute'; -var TOUCH_ACTION_AUTO = 'auto'; -var TOUCH_ACTION_MANIPULATION = 'manipulation'; // not implemented -var TOUCH_ACTION_NONE = 'none'; -var TOUCH_ACTION_PAN_X = 'pan-x'; -var TOUCH_ACTION_PAN_Y = 'pan-y'; -var TOUCH_ACTION_MAP = getTouchActionProps(); +/** + * Created by arjun on 28/05/16. + */ +import {TOUCH_ACTION_COMPUTE,TOUCH_ACTION_MAP,NATIVE_TOUCH_ACTION,PREFIXED_TOUCH_ACTION,TOUCH_ACTION_NONE, +TOUCH_ACTION_PAN_X,TOUCH_ACTION_PAN_Y} from './touchactionConsts'; +import {DIRECTION_VERTICAL,DIRECTION_HORIZONTAL} from '../inputjs/inputConsts'; +import {each} from '../utilsjs/each'; +import {boolOrFn} from '../utilsjs/boolOrFn'; +import {inStr} from '../utilsjs/inStr'; +import {cleanTouchActions} from './cleanTouchActions'; /** * Touch Action * sets the touchAction property or uses the js alternative @@ -113,52 +112,4 @@ TouchAction.prototype = { } }; -/** - * when the touchActions are collected they are not a valid value, so we need to clean things up. * - * @param {String} actions - * @returns {*} - */ -function cleanTouchActions(actions) { - // none - if (inStr(actions, TOUCH_ACTION_NONE)) { - return TOUCH_ACTION_NONE; - } - - var hasPanX = inStr(actions, TOUCH_ACTION_PAN_X); - var hasPanY = inStr(actions, TOUCH_ACTION_PAN_Y); - - // if both pan-x and pan-y are set (different recognizers - // for different directions, e.g. horizontal pan but vertical swipe?) - // we need none (as otherwise with pan-x pan-y combined none of these - // recognizers will work, since the browser would handle all panning - if (hasPanX && hasPanY) { - return TOUCH_ACTION_NONE; - } - - // pan-x OR pan-y - if (hasPanX || hasPanY) { - return hasPanX ? TOUCH_ACTION_PAN_X : TOUCH_ACTION_PAN_Y; - } - - // manipulation - if (inStr(actions, TOUCH_ACTION_MANIPULATION)) { - return TOUCH_ACTION_MANIPULATION; - } - - return TOUCH_ACTION_AUTO; -} - -function getTouchActionProps() { - if (!NATIVE_TOUCH_ACTION) { - return false; - } - var touchMap = {}; - var cssSupports = window.CSS && window.CSS.supports; - ['auto', 'manipulation', 'pan-y', 'pan-x', 'pan-x pan-y', 'none'].forEach(function(val) { - - // If css.supports is not supported but there is native touch-action assume it supports - // all values. This is the case for IE 10 and 11. - touchMap[val] = cssSupports ? window.CSS.supports('touch-action', val) : true; - }); - return touchMap; -} +export {TouchAction}; \ No newline at end of file diff --git a/src/touchactionjs/touchactionConsts.js b/src/touchactionjs/touchactionConsts.js new file mode 100644 index 000000000..de4bd4964 --- /dev/null +++ b/src/touchactionjs/touchactionConsts.js @@ -0,0 +1,22 @@ +/** + * + * Created by arjun on 28/05/16. + */ +import {prefixed} from '../utilsjs/prefixed'; +import {TEST_ELEMENT} from '../utilsjs/utilsConsts'; +import {getTouchActionProps} from './getTouchActionProps'; + +var PREFIXED_TOUCH_ACTION = prefixed(TEST_ELEMENT.style, 'touchAction'); +var NATIVE_TOUCH_ACTION = PREFIXED_TOUCH_ACTION !== undefined; + +// magical touchAction value +var TOUCH_ACTION_COMPUTE = 'compute'; +var TOUCH_ACTION_AUTO = 'auto'; +var TOUCH_ACTION_MANIPULATION = 'manipulation'; // not implemented +var TOUCH_ACTION_NONE = 'none'; +var TOUCH_ACTION_PAN_X = 'pan-x'; +var TOUCH_ACTION_PAN_Y = 'pan-y'; +var TOUCH_ACTION_MAP = getTouchActionProps(); + +export {PREFIXED_TOUCH_ACTION,NATIVE_TOUCH_ACTION,TOUCH_ACTION_AUTO,TOUCH_ACTION_COMPUTE,TOUCH_ACTION_MANIPULATION,TOUCH_ACTION_NONE, +TOUCH_ACTION_PAN_X,TOUCH_ACTION_PAN_Y,TOUCH_ACTION_MAP} diff --git a/src/utils.js b/src/utils.js deleted file mode 100644 index c923ce533..000000000 --- a/src/utils.js +++ /dev/null @@ -1,371 +0,0 @@ -var VENDOR_PREFIXES = ['', 'webkit', 'Moz', 'MS', 'ms', 'o']; -var TEST_ELEMENT = document.createElement('div'); - -var TYPE_FUNCTION = 'function'; - -var round = Math.round; -var abs = Math.abs; -var now = Date.now; - -/** - * set a timeout with a given scope - * @param {Function} fn - * @param {Number} timeout - * @param {Object} context - * @returns {number} - */ -function setTimeoutContext(fn, timeout, context) { - return setTimeout(bindFn(fn, context), timeout); -} - -/** - * if the argument is an array, we want to execute the fn on each entry - * if it aint an array we don't want to do a thing. - * this is used by all the methods that accept a single and array argument. - * @param {*|Array} arg - * @param {String} fn - * @param {Object} [context] - * @returns {Boolean} - */ -function invokeArrayArg(arg, fn, context) { - if (Array.isArray(arg)) { - each(arg, context[fn], context); - return true; - } - return false; -} - -/** - * walk objects and arrays - * @param {Object} obj - * @param {Function} iterator - * @param {Object} context - */ -function each(obj, iterator, context) { - var i; - - if (!obj) { - return; - } - - if (obj.forEach) { - obj.forEach(iterator, context); - } else if (obj.length !== undefined) { - i = 0; - while (i < obj.length) { - iterator.call(context, obj[i], i, obj); - i++; - } - } else { - for (i in obj) { - obj.hasOwnProperty(i) && iterator.call(context, obj[i], i, obj); - } - } -} - -/** - * wrap a method with a deprecation warning and stack trace - * @param {Function} method - * @param {String} name - * @param {String} message - * @returns {Function} A new function wrapping the supplied method. - */ -function deprecate(method, name, message) { - var deprecationMessage = 'DEPRECATED METHOD: ' + name + '\n' + message + ' AT \n'; - return function() { - var e = new Error('get-stack-trace'); - var stack = e && e.stack ? e.stack.replace(/^[^\(]+?[\n$]/gm, '') - .replace(/^\s+at\s+/gm, '') - .replace(/^Object.\s*\(/gm, '{anonymous}()@') : 'Unknown Stack Trace'; - - var log = window.console && (window.console.warn || window.console.log); - if (log) { - log.call(window.console, deprecationMessage, stack); - } - return method.apply(this, arguments); - }; -} - -/** - * extend object. - * means that properties in dest will be overwritten by the ones in src. - * @param {Object} target - * @param {...Object} objects_to_assign - * @returns {Object} target - */ -var assign; -if (typeof Object.assign !== 'function') { - assign = function assign(target) { - if (target === undefined || target === null) { - throw new TypeError('Cannot convert undefined or null to object'); - } - - var output = Object(target); - for (var index = 1; index < arguments.length; index++) { - var source = arguments[index]; - if (source !== undefined && source !== null) { - for (var nextKey in source) { - if (source.hasOwnProperty(nextKey)) { - output[nextKey] = source[nextKey]; - } - } - } - } - return output; - }; -} else { - assign = Object.assign; -} - -/** - * extend object. - * means that properties in dest will be overwritten by the ones in src. - * @param {Object} dest - * @param {Object} src - * @param {Boolean} [merge=false] - * @returns {Object} dest - */ -var extend = deprecate(function extend(dest, src, merge) { - var keys = Object.keys(src); - var i = 0; - while (i < keys.length) { - if (!merge || (merge && dest[keys[i]] === undefined)) { - dest[keys[i]] = src[keys[i]]; - } - i++; - } - return dest; -}, 'extend', 'Use `assign`.'); - -/** - * merge the values from src in the dest. - * means that properties that exist in dest will not be overwritten by src - * @param {Object} dest - * @param {Object} src - * @returns {Object} dest - */ -var merge = deprecate(function merge(dest, src) { - return extend(dest, src, true); -}, 'merge', 'Use `assign`.'); - -/** - * simple class inheritance - * @param {Function} child - * @param {Function} base - * @param {Object} [properties] - */ -function inherit(child, base, properties) { - var baseP = base.prototype, - childP; - - childP = child.prototype = Object.create(baseP); - childP.constructor = child; - childP._super = baseP; - - if (properties) { - assign(childP, properties); - } -} - -/** - * simple function bind - * @param {Function} fn - * @param {Object} context - * @returns {Function} - */ -function bindFn(fn, context) { - return function boundFn() { - return fn.apply(context, arguments); - }; -} - -/** - * let a boolean value also be a function that must return a boolean - * this first item in args will be used as the context - * @param {Boolean|Function} val - * @param {Array} [args] - * @returns {Boolean} - */ -function boolOrFn(val, args) { - if (typeof val == TYPE_FUNCTION) { - return val.apply(args ? args[0] || undefined : undefined, args); - } - return val; -} - -/** - * use the val2 when val1 is undefined - * @param {*} val1 - * @param {*} val2 - * @returns {*} - */ -function ifUndefined(val1, val2) { - return (val1 === undefined) ? val2 : val1; -} - -/** - * addEventListener with multiple events at once - * @param {EventTarget} target - * @param {String} types - * @param {Function} handler - */ -function addEventListeners(target, types, handler) { - each(splitStr(types), function(type) { - target.addEventListener(type, handler, false); - }); -} - -/** - * removeEventListener with multiple events at once - * @param {EventTarget} target - * @param {String} types - * @param {Function} handler - */ -function removeEventListeners(target, types, handler) { - each(splitStr(types), function(type) { - target.removeEventListener(type, handler, false); - }); -} - -/** - * find if a node is in the given parent - * @method hasParent - * @param {HTMLElement} node - * @param {HTMLElement} parent - * @return {Boolean} found - */ -function hasParent(node, parent) { - while (node) { - if (node == parent) { - return true; - } - node = node.parentNode; - } - return false; -} - -/** - * small indexOf wrapper - * @param {String} str - * @param {String} find - * @returns {Boolean} found - */ -function inStr(str, find) { - return str.indexOf(find) > -1; -} - -/** - * split string on whitespace - * @param {String} str - * @returns {Array} words - */ -function splitStr(str) { - return str.trim().split(/\s+/g); -} - -/** - * find if a array contains the object using indexOf or a simple polyFill - * @param {Array} src - * @param {String} find - * @param {String} [findByKey] - * @return {Boolean|Number} false when not found, or the index - */ -function inArray(src, find, findByKey) { - if (src.indexOf && !findByKey) { - return src.indexOf(find); - } else { - var i = 0; - while (i < src.length) { - if ((findByKey && src[i][findByKey] == find) || (!findByKey && src[i] === find)) { - return i; - } - i++; - } - return -1; - } -} - -/** - * convert array-like objects to real arrays - * @param {Object} obj - * @returns {Array} - */ -function toArray(obj) { - return Array.prototype.slice.call(obj, 0); -} - -/** - * unique array with objects based on a key (like 'id') or just by the array's value - * @param {Array} src [{id:1},{id:2},{id:1}] - * @param {String} [key] - * @param {Boolean} [sort=False] - * @returns {Array} [{id:1},{id:2}] - */ -function uniqueArray(src, key, sort) { - var results = []; - var values = []; - var i = 0; - - while (i < src.length) { - var val = key ? src[i][key] : src[i]; - if (inArray(values, val) < 0) { - results.push(src[i]); - } - values[i] = val; - i++; - } - - if (sort) { - if (!key) { - results = results.sort(); - } else { - results = results.sort(function sortUniqueArray(a, b) { - return a[key] > b[key]; - }); - } - } - - return results; -} - -/** - * get the prefixed property - * @param {Object} obj - * @param {String} property - * @returns {String|Undefined} prefixed - */ -function prefixed(obj, property) { - var prefix, prop; - var camelProp = property[0].toUpperCase() + property.slice(1); - - var i = 0; - while (i < VENDOR_PREFIXES.length) { - prefix = VENDOR_PREFIXES[i]; - prop = (prefix) ? prefix + camelProp : property; - - if (prop in obj) { - return prop; - } - i++; - } - return undefined; -} - -/** - * get a unique id - * @returns {number} uniqueId - */ -var _uniqueId = 1; -function uniqueId() { - return _uniqueId++; -} - -/** - * get the window object of an element - * @param {HTMLElement} element - * @returns {DocumentView|Window} - */ -function getWindowForElement(element) { - var doc = element.ownerDocument || element; - return (doc.defaultView || doc.parentWindow || window); -} diff --git a/src/utilsjs/addEventListeners.js b/src/utilsjs/addEventListeners.js index a01fd039f..22e29a98e 100644 --- a/src/utilsjs/addEventListeners.js +++ b/src/utilsjs/addEventListeners.js @@ -1,7 +1,8 @@ /** * Created by arjun on 20/05/16. */ -import {each} from './each' +import {each} from './each'; +import {splitStr} from './splitStr'; /** * addEventListener with multiple events at once * @param {EventTarget} target diff --git a/src/utilsjs/ifUndefined.js b/src/utilsjs/ifUndefined.js new file mode 100644 index 000000000..ff14ff948 --- /dev/null +++ b/src/utilsjs/ifUndefined.js @@ -0,0 +1,15 @@ +/** + * Created by arjun on 25/05/16. + */ + +/** + * use the val2 when val1 is undefined + * @param {*} val1 + * @param {*} val2 + * @returns {*} + */ +function ifUndefined(val1, val2) { + return (val1 === undefined) ? val2 : val1; +} + +export {ifUndefined}; \ No newline at end of file diff --git a/src/utilsjs/invokeArrayArg.js b/src/utilsjs/invokeArrayArg.js index b4d43f1f6..a83ef5a69 100644 --- a/src/utilsjs/invokeArrayArg.js +++ b/src/utilsjs/invokeArrayArg.js @@ -1,7 +1,7 @@ /** * Created by arjun on 19/05/16. */ - +import {each} from './each'; /** * if the argument is an array, we want to execute the fn on each entry * if it aint an array we don't want to do a thing. diff --git a/src/utilsjs/removeEventListeners.js b/src/utilsjs/removeEventListeners.js index 034398aae..4a44e6d63 100644 --- a/src/utilsjs/removeEventListeners.js +++ b/src/utilsjs/removeEventListeners.js @@ -3,6 +3,7 @@ * Created by arjun on 20/05/16. */ import {each} from './each' +import {splitStr} from './splitStr' /** * removeEventListener with multiple events at once * @param {EventTarget} target diff --git a/src/utilsjs/setTimeoutContext.js b/src/utilsjs/setTimeoutContext.js index 50dd4d161..5f3d7a045 100644 --- a/src/utilsjs/setTimeoutContext.js +++ b/src/utilsjs/setTimeoutContext.js @@ -1,7 +1,7 @@ /** * Created by arjun on 19/05/16. */ - +import {bindFn} from './bindFn'; /** * set a timeout with a given scope * @param {Function} fn From 9146add67ac3d381b856647cf54a960e09a848de Mon Sep 17 00:00:00 2001 From: Arjun Kathuria Date: Sun, 29 May 2016 19:05:21 +0530 Subject: [PATCH 07/61] exposes global --- bundle.js | 12 ++++++++++-- src/main.js | 17 ++++++++++++++++- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/bundle.js b/bundle.js index bd6750b18..1864ffbc1 100644 --- a/bundle.js +++ b/bundle.js @@ -2498,6 +2498,14 @@ Hammer.defaults = { tapHighlightColor: 'rgba(0,0,0,0)' } }; -})(window, document, 'Hammer'); -export { Hammer }; \ No newline at end of file +if (typeof define === 'function' && define.amd) { + define(function () { + return Hammer; + }); +} else if (typeof module != 'undefined' && module.exports) { + module.exports = Hammer; +} else { + window[exportName] = Hammer; +} +})(window, document, 'Hammer'); \ No newline at end of file diff --git a/src/main.js b/src/main.js index 8c8652c33..a05a298c1 100644 --- a/src/main.js +++ b/src/main.js @@ -1 +1,16 @@ -export {Hammer} from './hammer'; \ No newline at end of file +import {Hammer} from './hammer'; + +// this prevents errors when Hammer is loaded in the presence of an AMD +// style loader but by script tag, not by the loader. +var freeGlobal = (typeof window !== 'undefined' ? window : (typeof self !== 'undefined' ? self : {})); // jshint ignore:line +freeGlobal.Hammer = Hammer; + +if (typeof define === 'function' && define.amd) { + define(function() { + return Hammer; + }); +} else if (typeof module != 'undefined' && module.exports) { + module.exports = Hammer; +} else { + window[exportName] = Hammer; +} \ No newline at end of file From 326c0c3e970086f7436e07d4375b208b656c5fdc Mon Sep 17 00:00:00 2001 From: Chris Thoburn Date: Sun, 29 May 2016 07:04:55 -0700 Subject: [PATCH 08/61] update project structure and dependencies --- .../gestures/detection.js} | 0 .../gestures/inputs/input.js} | 0 .../gestures/inputs/mouse.js} | 0 addon/-private/gestures/inputs/pointer.js | 0 addon/-private/gestures/inputs/touch.js | 0 addon/-private/gestures/layer.js | 0 addon/{ => -private}/gestures/manager.js | 2 +- addon/-private/gestures/recognizer.js | 7 +++++ .../gestures/streams}/stream-event.js | 0 addon/-private/gestures/streams/stream.js | 30 +++++++++++++++++++ package.json | 9 ++++-- 11 files changed, 45 insertions(+), 3 deletions(-) rename addon/{gestures/layer.js => -private/gestures/detection.js} (100%) rename addon/{gestures/recognizer.js => -private/gestures/inputs/input.js} (100%) rename addon/{gestures/stream.js => -private/gestures/inputs/mouse.js} (100%) create mode 100644 addon/-private/gestures/inputs/pointer.js create mode 100644 addon/-private/gestures/inputs/touch.js create mode 100644 addon/-private/gestures/layer.js rename addon/{ => -private}/gestures/manager.js (96%) create mode 100644 addon/-private/gestures/recognizer.js rename addon/{gestures => -private/gestures/streams}/stream-event.js (100%) create mode 100644 addon/-private/gestures/streams/stream.js diff --git a/addon/gestures/layer.js b/addon/-private/gestures/detection.js similarity index 100% rename from addon/gestures/layer.js rename to addon/-private/gestures/detection.js diff --git a/addon/gestures/recognizer.js b/addon/-private/gestures/inputs/input.js similarity index 100% rename from addon/gestures/recognizer.js rename to addon/-private/gestures/inputs/input.js diff --git a/addon/gestures/stream.js b/addon/-private/gestures/inputs/mouse.js similarity index 100% rename from addon/gestures/stream.js rename to addon/-private/gestures/inputs/mouse.js diff --git a/addon/-private/gestures/inputs/pointer.js b/addon/-private/gestures/inputs/pointer.js new file mode 100644 index 000000000..e69de29bb diff --git a/addon/-private/gestures/inputs/touch.js b/addon/-private/gestures/inputs/touch.js new file mode 100644 index 000000000..e69de29bb diff --git a/addon/-private/gestures/layer.js b/addon/-private/gestures/layer.js new file mode 100644 index 000000000..e69de29bb diff --git a/addon/gestures/manager.js b/addon/-private/gestures/manager.js similarity index 96% rename from addon/gestures/manager.js rename to addon/-private/gestures/manager.js index 69c758266..4c9871fc1 100644 --- a/addon/gestures/manager.js +++ b/addon/-private/gestures/manager.js @@ -1,4 +1,4 @@ -import { TouchStream, MouseStream } from './stream'; +import { TouchStream, MouseStream } from './streams/stream'; export default class Manager { diff --git a/addon/-private/gestures/recognizer.js b/addon/-private/gestures/recognizer.js new file mode 100644 index 000000000..00cd86c94 --- /dev/null +++ b/addon/-private/gestures/recognizer.js @@ -0,0 +1,7 @@ +export default class Recognizer { + + constructor(name) { + this.name = name; + } + +} diff --git a/addon/gestures/stream-event.js b/addon/-private/gestures/streams/stream-event.js similarity index 100% rename from addon/gestures/stream-event.js rename to addon/-private/gestures/streams/stream-event.js diff --git a/addon/-private/gestures/streams/stream.js b/addon/-private/gestures/streams/stream.js new file mode 100644 index 000000000..8de2d08ca --- /dev/null +++ b/addon/-private/gestures/streams/stream.js @@ -0,0 +1,30 @@ + +export default class Stream { + + constructor(element) { + this.element = element; + this.series = []; + this.handler = null; + } + + start(e) { + + } + + update(e) { + + } + + end(e) { + + } + + vanish(e) { + + } + + timeout(e) { + + } + +} diff --git a/package.json b/package.json index 31cf4104c..d4d0faa28 100644 --- a/package.json +++ b/package.json @@ -18,12 +18,12 @@ "author": "", "license": "MIT", "devDependencies": { + "body-parser": "^1.15.1", "broccoli-asset-rev": "^2.4.2", "ember-ajax": "^2.0.1", "ember-cli": "2.6.0-beta.2", "ember-cli-app-version": "^1.0.0", "ember-cli-dependency-checker": "^1.2.0", - "ember-cli-htmlbars": "^1.0.3", "ember-cli-htmlbars-inline-precompile": "^0.3.1", "ember-cli-inject-live-reload": "^1.4.0", "ember-cli-jshint": "^1.0.0", @@ -38,14 +38,19 @@ "ember-resolver": "^2.0.3", "ember-welcome-page": "^1.0.1", "express": "^4.13.4", + "faker": "^3.1.0", + "flexi": "1.1.9", "glob": "^4.5.3", "loader.js": "^4.0.1", - "morgan": "^1.7.0" + "morgan": "^1.7.0", + "object-assign": "^4.1.0" }, "keywords": [ "ember-addon" ], "dependencies": { + "ember-cli-sass": "5.3.1", + "ember-cli-htmlbars": "^1.0.3", "ember-cli-babel": "^5.1.6" }, "ember-addon": { From 59817dd10b3791e41a37069a393bb6511e3033c2 Mon Sep 17 00:00:00 2001 From: Chris Thoburn Date: Sun, 29 May 2016 07:05:06 -0700 Subject: [PATCH 09/61] create mock server --- server/mocks/items.js | 143 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 128 insertions(+), 15 deletions(-) diff --git a/server/mocks/items.js b/server/mocks/items.js index 531c932cc..23f5e4b24 100644 --- a/server/mocks/items.js +++ b/server/mocks/items.js @@ -1,35 +1,148 @@ /*jshint node:true*/ +var faker = require('faker'); +var assign = require('object-assign'); +var bodyParser = require('body-parser'); + +function between(min, max) { + return Math.floor(Math.random() * (max + 1 - min) + min); +} + +var MODEL_DEFAULTS = { + __deleted: false +}; + +function itemFactory() { + return assign({ + id: null, + title: faker.lorem.words(between(3, 8)), + description: faker.lorem.sentences(between(2, 5)) + }, MODEL_DEFAULTS); +} + +function Store(factory, type) { + this._recordMap = {}; + this._records = []; + this._nextID = 0; + this._schema = factory; + this._type = type; +} + +Store.prototype.clone = function clone(records) { + return records.map(function(record) { + return assign({}, record); + }); +}; + +Store.prototype.serializeOne = function serializeOne(record) { + return { + data: { + id: record.id, + type: this._type, + attributes: assign({}, record) + } + }; +}; + +Store.prototype.normalizeOne = function normalizeOne(record) { + var values = record.data.attributes; + + delete values.id; + + return values; +}; + +Store.prototype.serializeMany = function serializeMany(records) { + var _this = this; + var data = records.map(function(record) { + return _this.serializeOne(record).data; + }); + + return { data: data }; +}; + +Store.prototype.findRecord = function findRecord(id) { + var record = this._recordMap[id]; + + if (!record || record.__deleted) { + throw new Error(404); + } + + return this.serializeOne(record); +}; + +Store.prototype.createRecord = function createRecord(data) { + var record = {}; + + if (!data) { + throw new Error(500); + } + + var values = this.normalizeOne(data); + + assign(record, this._schema(), values, { id: this._nextID++ }); + this._records.push(record); + this._recordMap[record.id] = record; + + return this.serializeOne(record); +}; + +Store.prototype.findAll = function findAll() { + return this.serializeMany(this._records.filter(function(record) { + return !record.__deleted; + })); +}; + +Store.prototype.deleteRecord = function deleteRecord(id) { + let record = this._recordMap[id]; + + if (!record || record.__deleted) { + throw new Error(500); + } + + record.__deleted = true; +}; + +Store.prototype.updateRecord = function updateRecord(id, data) { + var record = this._recordMap[id]; + + if (!data || !record || record.__deleted) { + throw new Error(500); + } + + var values = this.normalizeOne(data); + + assign(record, values); + + return this.serializeOne(record); +}; + module.exports = function(app) { var express = require('express'); var itemsRouter = express.Router(); + var store = new Store(itemFactory, 'items'); + + for (var i = 0; i < 50; i++) { + store.createRecord({}); + } itemsRouter.get('/', function(req, res) { - res.send({ - 'items': [] - }); + res.send(store.findAll()); }); itemsRouter.post('/', function(req, res) { - res.status(201).end(); + res.status(201).send(store.createRecord(req.body);); }); itemsRouter.get('/:id', function(req, res) { - res.send({ - 'items': { - id: req.params.id - } - }); + res.send(store.findRecord(req.params.id)); }); itemsRouter.put('/:id', function(req, res) { - res.send({ - 'items': { - id: req.params.id - } - }); + res.send(store.updateRecord(req.params.id, req.body)); }); itemsRouter.delete('/:id', function(req, res) { + store.deleteRecord(req.params.id); res.status(204).end(); }); @@ -42,6 +155,6 @@ module.exports = function(app) { // After installing, you need to `use` the body-parser for // this mock uncommenting the following line: // - //app.use('/api/items', require('body-parser').json()); + app.use('/api/items', bodyParser.json()); app.use('/api/items', itemsRouter); }; From 37463d6e2782953cae86e8b0d2e9b1d32a097674 Mon Sep 17 00:00:00 2001 From: Chris Thoburn Date: Sun, 29 May 2016 07:05:34 -0700 Subject: [PATCH 10/61] fix mock server --- server/mocks/items.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/mocks/items.js b/server/mocks/items.js index 23f5e4b24..61a1658ec 100644 --- a/server/mocks/items.js +++ b/server/mocks/items.js @@ -130,7 +130,7 @@ module.exports = function(app) { }); itemsRouter.post('/', function(req, res) { - res.status(201).send(store.createRecord(req.body);); + res.status(201).send(store.createRecord(req.body)); }); itemsRouter.get('/:id', function(req, res) { From 5e29e99714e1754fee73bdcc1af6b1441f1a4223 Mon Sep 17 00:00:00 2001 From: Chris Thoburn Date: Sun, 29 May 2016 07:05:57 -0700 Subject: [PATCH 11/61] initial styles spike --- addon/styles/addon.scss | 59 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/addon/styles/addon.scss b/addon/styles/addon.scss index e69de29bb..cc6dbe55b 100644 --- a/addon/styles/addon.scss +++ b/addon/styles/addon.scss @@ -0,0 +1,59 @@ +@mixin off() { + pointer-events: none; + -webkit-overflow-scrolling: touch; + touch-action: none; +} + +.gesture-no-touch { + @include off(); + + * { + @include off(); + } +} + +@mixin fillBlock($position: absolute) { + width: 100%; + height: 100%; + top: 0; + left: 0; + position: $position; + display: block; +} + +@mixin willChange($start: 0) { + will-change: transform; + transform: translateX($start); +} + +history-outlet { + @include fillBlock('relative'); + + left { + @include fillBlock(); + z-index: 0; + willChange(-20%); + } + + right { + @include fillBlock(); + z-index: 0; + willChange(80%); + } + + main { + @include fillBlock(); + z-index: 1; + willChange(); + } + + outlet { + @include fillBlock(); + z-index: 1; + willChange(); + } + + fps { + @include fillBlock(); + } +} From b7e7913f4416aafc0f2c7d928fab764f716c8b80 Mon Sep 17 00:00:00 2001 From: Chris Thoburn Date: Sun, 29 May 2016 07:41:42 -0700 Subject: [PATCH 12/61] initialize gesture recognition --- .../gesture-recognition.js | 8 +++++ .../gesture-recognition.js | 1 + config/flexi.js | 35 +++++++++++++++++++ .../gesture-recognition-test.js | 25 +++++++++++++ 4 files changed, 69 insertions(+) create mode 100644 addon/instance-initializers/gesture-recognition.js create mode 100644 app/instance-initializers/gesture-recognition.js create mode 100644 config/flexi.js create mode 100644 tests/unit/instance-initializers/gesture-recognition-test.js diff --git a/addon/instance-initializers/gesture-recognition.js b/addon/instance-initializers/gesture-recognition.js new file mode 100644 index 000000000..e638bc265 --- /dev/null +++ b/addon/instance-initializers/gesture-recognition.js @@ -0,0 +1,8 @@ +export function initialize(instance) { + instance.lookup('service:gesture-recognition'); +} + +export default { + name: 'gesture-recognition', + initialize +}; diff --git a/app/instance-initializers/gesture-recognition.js b/app/instance-initializers/gesture-recognition.js new file mode 100644 index 000000000..58186eb40 --- /dev/null +++ b/app/instance-initializers/gesture-recognition.js @@ -0,0 +1 @@ +export { default, initialize } from 'history/instance-initializers/gesture-recognition'; diff --git a/config/flexi.js b/config/flexi.js new file mode 100644 index 000000000..c789400bc --- /dev/null +++ b/config/flexi.js @@ -0,0 +1,35 @@ +/* jshint node:true */ +module.exports = { + + // breakpoints, order does not matter, they will be sorted by `begin` + // `name` is used for layout names and booleans on the device/layout service + // `prefix` is used for column classes, column attributes, and container breakpoint classes + // `begin` is the pixel value at which this breakpoint becomes active + breakpoints: [ + { name: 'mobile', prefix: 'xs', begin: 0 }, + { name: 'tablet', prefix: 'sm', begin: 768 }, + { name: 'desktop', prefix: 'md', begin: 992 }, + { name: 'huge', prefix: 'lg', begin: 1200 } + ], + + // the number of columns for the grid + columns: 12, + + // optional, used for column classes: '--' + columnPrefix: 'col', + + // if false, @media css is not included + includeMediaCSS: true, + + // if false, default element styles are not included + includeElementCSS: true, + + // if true, will convert layout attributes on non-layout elements to classes as well + transformAllElementLayoutAttributes: false, + + // grid and layout element gutters + gutterPadding: '.5rem', + + // if false, no styles are included (trumps 'includeMediaCSS' and 'includeElementCSS') + includeCSS: true +}; diff --git a/tests/unit/instance-initializers/gesture-recognition-test.js b/tests/unit/instance-initializers/gesture-recognition-test.js new file mode 100644 index 000000000..62dd97e0a --- /dev/null +++ b/tests/unit/instance-initializers/gesture-recognition-test.js @@ -0,0 +1,25 @@ +import Ember from 'ember'; +import { initialize } from 'dummy/instance-initializers/gesture-recognition'; +import { module, test } from 'qunit'; +import destroyApp from '../../helpers/destroy-app'; + +module('Unit | Instance Initializer | gesture recognition', { + beforeEach: function() { + Ember.run(() => { + this.application = Ember.Application.create(); + this.appInstance = this.application.buildInstance(); + }); + }, + afterEach: function() { + Ember.run(this.appInstance, 'destroy'); + destroyApp(this.application); + } +}); + +// Replace this with your real tests. +test('it works', function(assert) { + initialize(this.appInstance); + + // you would normally confirm the results of the initializer here + assert.ok(true); +}); From 16621cb48198965d2ce2ed63572a849827d5153f Mon Sep 17 00:00:00 2001 From: Chris Thoburn Date: Sun, 29 May 2016 07:43:50 -0700 Subject: [PATCH 13/61] adds gesture service --- addon/services/gesture-recognition.js | 16 ++++++++++++++++ app/services/gesture-recognition.js | 1 + tests/unit/services/gesture-recognition-test.js | 12 ++++++++++++ 3 files changed, 29 insertions(+) create mode 100644 addon/services/gesture-recognition.js create mode 100644 app/services/gesture-recognition.js create mode 100644 tests/unit/services/gesture-recognition-test.js diff --git a/addon/services/gesture-recognition.js b/addon/services/gesture-recognition.js new file mode 100644 index 000000000..517879051 --- /dev/null +++ b/addon/services/gesture-recognition.js @@ -0,0 +1,16 @@ +import Ember from 'ember'; +import Manager from 'history/-private/gestures/manager'; + +const { + Service + } = Ember; + +export default Service.extend({ + + manager: null, + + init() { + this._super(); + this.manager = new Manager(); + } +}); diff --git a/app/services/gesture-recognition.js b/app/services/gesture-recognition.js new file mode 100644 index 000000000..06a7c885b --- /dev/null +++ b/app/services/gesture-recognition.js @@ -0,0 +1 @@ +export { default } from 'history/services/gesture-recognition'; diff --git a/tests/unit/services/gesture-recognition-test.js b/tests/unit/services/gesture-recognition-test.js new file mode 100644 index 000000000..ee24a975d --- /dev/null +++ b/tests/unit/services/gesture-recognition-test.js @@ -0,0 +1,12 @@ +import { moduleFor, test } from 'ember-qunit'; + +moduleFor('service:gesture-recognition', 'Unit | Service | gesture recognition', { + // Specify the other units that are required for this test. + // needs: ['service:foo'] +}); + +// Replace this with your real tests. +test('it exists', function(assert) { + let service = this.subject(); + assert.ok(service); +}); From c8221be9589507787fa899a321ef0cec1a5ef33d Mon Sep 17 00:00:00 2001 From: Chris Thoburn Date: Sun, 29 May 2016 08:24:03 -0700 Subject: [PATCH 14/61] early scaffold of history-outlet --- addon/components/history-outlet/component.js | 42 +++++++++++++++++++ addon/components/history-outlet/template.hbs | 7 ++++ app/components/history-outlet.js | 1 + .../components/history-outlet-test.js | 24 +++++++++++ 4 files changed, 74 insertions(+) create mode 100644 addon/components/history-outlet/component.js create mode 100644 addon/components/history-outlet/template.hbs create mode 100644 app/components/history-outlet.js create mode 100644 tests/integration/components/history-outlet-test.js diff --git a/addon/components/history-outlet/component.js b/addon/components/history-outlet/component.js new file mode 100644 index 000000000..520cd4ff4 --- /dev/null +++ b/addon/components/history-outlet/component.js @@ -0,0 +1,42 @@ +import Ember from 'ember'; +import layout from 'history-outlet'; +import Layer from 'history/-private/gestures/layer'; +import VerticalPan from 'history/-private/gestures/recognizers/vertical-pan'; + +const { + computed, + inject, + Component + } = Ember; + +export default Component.extend({ + layout, + tagName: 'history-outlet', + _left: null, + _main: null, + _right: null, + _outlet: null, + + gestures: inject.service('gesture-recognition'), + + willInsertElement() { + this._left = this.element.children[0]; + this._main = this.element.children[1]; + this._right = this.element.children[2]; + this._outlet = this.element.children[3]; + }, + + setupLayer() { + + }, + + didInsertElement() { + this.get('gestures.manager').registerLayer(this.layer); + }, + + init() { + this._super(); + this.layer = new Layer(this.element); + } + +}); diff --git a/addon/components/history-outlet/template.hbs b/addon/components/history-outlet/template.hbs new file mode 100644 index 000000000..4b271b25c --- /dev/null +++ b/addon/components/history-outlet/template.hbs @@ -0,0 +1,7 @@ + +
+ +{{outlet}} +{{#if debugMode}} + {{debug.fps}} / {{debug.avg}}fps +{{/if}} diff --git a/app/components/history-outlet.js b/app/components/history-outlet.js new file mode 100644 index 000000000..dee074fa5 --- /dev/null +++ b/app/components/history-outlet.js @@ -0,0 +1 @@ +export { default } from 'history/components/history-outlet'; \ No newline at end of file diff --git a/tests/integration/components/history-outlet-test.js b/tests/integration/components/history-outlet-test.js new file mode 100644 index 000000000..337f5a3a7 --- /dev/null +++ b/tests/integration/components/history-outlet-test.js @@ -0,0 +1,24 @@ +import { moduleForComponent, test } from 'ember-qunit'; +import hbs from 'htmlbars-inline-precompile'; + +moduleForComponent('history-outlet', 'Integration | Component | history outlet', { + integration: true +}); + +test('it renders', function(assert) { + // Set any properties with this.set('myProperty', 'value'); + // Handle any actions with this.on('myAction', function(val) { ... }); + + this.render(hbs`{{history-outlet}}`); + + assert.equal(this.$().text().trim(), ''); + + // Template block usage: + this.render(hbs` + {{#history-outlet}} + template block text + {{/history-outlet}} + `); + + assert.equal(this.$().text().trim(), 'template block text'); +}); From c16e4a460347ccf488c80a90278431fa7f9f00c9 Mon Sep 17 00:00:00 2001 From: Chris Thoburn Date: Sun, 29 May 2016 08:24:53 -0700 Subject: [PATCH 15/61] spike mouse input --- addon/-private/gestures/detection.js | 32 +++++++++++++ addon/-private/gestures/inputs/input.js | 61 +++++++++++++++++++++++++ addon/-private/gestures/inputs/mouse.js | 31 +++++++++++++ addon/-private/gestures/manager.js | 45 ++++++++++++------ 4 files changed, 156 insertions(+), 13 deletions(-) diff --git a/addon/-private/gestures/detection.js b/addon/-private/gestures/detection.js index e69de29bb..ce72ac7f9 100644 --- a/addon/-private/gestures/detection.js +++ b/addon/-private/gestures/detection.js @@ -0,0 +1,32 @@ +/* global navigator, window */ +import TouchInput from './inputs/touch'; +import MouseInput from './inputs/mouse'; +// import PointerInput from './inputs/pointer'; + +const MAY_SUPPORT_TOUCH = (('ontouchstart' in window) || // html5 browsers + (navigator.maxTouchPoints > 0) || // future IE + (navigator.msMaxTouchPoints > 0)); // current IE10 + +const MAY_SUPPORT_MOUSE = !!('onmousemove' in window); + +// const SUPPORT_POINTER_EVENTS = prefixed(window, 'PointerEvent') !== undefined; + +function availableInputs() { + let inputs = {}; + + if (MAY_SUPPORT_MOUSE) { + inputs.mouse = MouseInput; + } + + if (MAY_SUPPORT_TOUCH) { + inputs.touch = TouchInput; + } + + return inputs; +} + +export { + availableInputs +} + +export default availableInputs; diff --git a/addon/-private/gestures/inputs/input.js b/addon/-private/gestures/inputs/input.js index e69de29bb..07cb25b8c 100644 --- a/addon/-private/gestures/inputs/input.js +++ b/addon/-private/gestures/inputs/input.js @@ -0,0 +1,61 @@ +import Stream from '../streams/stream'; +import StreamEvent from '../streams/stream-event'; + +export default class input { + + constructor(element) { + this.element = element; + this.streams = []; + this.attached = false; + + this._handlers = { start: null, update: null, end: null, interrupt: null }; + } + + _bind(name) { + const { _handlers } = this; + + return _handlers[name] = this[name].bind(this); + } + + start(event) { + let stream = new Stream(); + + this.streams.push(stream); + stream.open({ + event + }); + } + + update(event) { + let [stream] = this.streams; + + stream.push({ + event + }); + } + + end(event) { + let [stream] = this.streams; + + stream.close({ + event + }); + } + + interrupt(event) { + let [stream] = this.streams; + + stream.close({ + event + }); + } + + attach() { + throw new Error('Interface Method Not Implemented'); + } + + deattach() { + throw new Error('Interface Method Not Implemented'); + } + +} diff --git a/addon/-private/gestures/inputs/mouse.js b/addon/-private/gestures/inputs/mouse.js index e69de29bb..db736d76f 100644 --- a/addon/-private/gestures/inputs/mouse.js +++ b/addon/-private/gestures/inputs/mouse.js @@ -0,0 +1,31 @@ +import Input from './input'; + +export default class MouseInput extends Input { + + attach() { + if (this.attached) { + return; + } + const { element } = this; + + element.addEventListener('mousedown', this._bind('start') , true); + element.addEventListener('mouseup', this._bind('end') , true); + element.addEventListener('mouseexit', this._bind('interrupt') , true); + element.addEventListener('mousemove', this._bind('update') , true); + + this.attached = true; + } + + deattach() { + if (this.attached) { + return; + } + const { element, _handlers } = this; + + element.removeEventListener('mousedown', _handlers.start , true); + element.removeEventListener('mouseup', _handlers.end , true); + element.removeEventListener('mouseexit', _handlers.interrupt , true); + element.removeEventListener('mousemove', _handlers.update , true); + } + +} diff --git a/addon/-private/gestures/manager.js b/addon/-private/gestures/manager.js index 4c9871fc1..0be3d0957 100644 --- a/addon/-private/gestures/manager.js +++ b/addon/-private/gestures/manager.js @@ -1,10 +1,39 @@ -import { TouchStream, MouseStream } from './streams/stream'; +import { availableInputs } from './detection'; + +const assign = Object.assign; +const DEFAULT_OPTIONS = { + inputs: availableInputs() +}; + + + export default class Manager { - constructor(rootElement) { + constructor(rootElement, options) { this.rootElement = rootElement || window; - this._setup(); + this.layers = new WeakMap(); + + this.inputs = {}; + this.options = assign({}, DEFAULT_OPTIONS, options || {}); + + for (let { name, InputClass } of this.options.inputs) { + this.registerInput(name, InputClass); + } + + } + + registerInput(name, InputClass) { + this.inputs[name] = new InputClass(this.rootElement); + } + + unregisterInput(name) { + let input = this.inputs[name]; + + if (input) { + this.inputs[name] = null; + input.destroy(); + } } register(layer) { @@ -50,16 +79,6 @@ export default class Manager { return null; } - - private _setup() { - this.layers = new WeakMap(); - - this.streams = { - touch: new TouchStream(this.rootElement), - mouse: new MouseStream(this.rootElement) - }; - } - private _teardown() { this.streams.touch.destroy(); this.streams.mouse.destroy(); From d521d21af34e06c786533ead6c1da21746d73b7c Mon Sep 17 00:00:00 2001 From: Arjun Kathuria Date: Tue, 31 May 2016 10:06:23 +0530 Subject: [PATCH 16/61] further exposes hammer, adds 'on' 'Tap' etc, build closer to default --- bundle.js | 180 +++++++++++++++++++++++++++++++++++++++++++++++++++ package.json | 5 +- src/main.js | 84 ++++++++++++++++++++++++ 3 files changed, 268 insertions(+), 1 deletion(-) diff --git a/bundle.js b/bundle.js index 1864ffbc1..301757037 100644 --- a/bundle.js +++ b/bundle.js @@ -2499,6 +2499,186 @@ Hammer.defaults = { } }; +var SINGLE_TOUCH_INPUT_MAP = { + touchstart: INPUT_START, + touchmove: INPUT_MOVE, + touchend: INPUT_END, + touchcancel: INPUT_CANCEL +}; + +var SINGLE_TOUCH_TARGET_EVENTS = 'touchstart'; +var SINGLE_TOUCH_WINDOW_EVENTS = 'touchstart touchmove touchend touchcancel'; + +/** + * Touch events input + * @constructor + * @extends Input + */ +function SingleTouchInput() { + this.evTarget = SINGLE_TOUCH_TARGET_EVENTS; + this.evWin = SINGLE_TOUCH_WINDOW_EVENTS; + this.started = false; + + Input.apply(this, arguments); +} + +inherit(SingleTouchInput, Input, { + handler: function TEhandler(ev) { + var type = SINGLE_TOUCH_INPUT_MAP[ev.type]; + + // should we handle the touch events? + if (type === INPUT_START) { + this.started = true; + } + + if (!this.started) { + return; + } + + var touches = normalizeSingleTouches.call(this, ev, type); + + // when done, reset the started state + if (type & (INPUT_END | INPUT_CANCEL) && touches[0].length - touches[1].length === 0) { + this.started = false; + } + + this.callback(this.manager, type, { + pointers: touches[0], + changedPointers: touches[1], + pointerType: INPUT_TYPE_TOUCH, + srcEvent: ev + }); + } +}); + +/** + * @this {TouchInput} + * @param {Object} ev + * @param {Number} type flag + * @returns {undefined|Array} [all, changed] + */ +function normalizeSingleTouches(ev, type) { + var all = toArray(ev.touches); + var changed = toArray(ev.changedTouches); + + if (type & (INPUT_END | INPUT_CANCEL)) { + all = uniqueArray(all.concat(changed), 'identifier', true); + } + + return [all, changed]; +} + +/** + * Created by arjun on 19/05/16. + */ + +/** + * wrap a method with a deprecation warning and stack trace + * @param {Function} method + * @param {String} name + * @param {String} message + * @returns {Function} A new function wrapping the supplied method. + */ +function deprecate(method, name, message) { + var deprecationMessage = 'DEPRECATED METHOD: ' + name + '\n' + message + ' AT \n'; + return function () { + var e = new Error('get-stack-trace'); + var stack = e && e.stack ? e.stack.replace(/^[^\(]+?[\n$]/gm, '').replace(/^\s+at\s+/gm, '').replace(/^Object.\s*\(/gm, '{anonymous}()@') : 'Unknown Stack Trace'; + + var log = window.console && (window.console.warn || window.console.log); + if (log) { + log.call(window.console, deprecationMessage, stack); + } + return method.apply(this, arguments); + }; +} + +/** + * extend object. + * means that properties in dest will be overwritten by the ones in src. + * @param {Object} dest + * @param {Object} src + * @param {Boolean} [merge=false] + * @returns {Object} dest + */ +var extend = deprecate(function extend(dest, src, merge) { + var keys = Object.keys(src); + var i = 0; + while (i < keys.length) { + if (!merge || merge && dest[keys[i]] === undefined) { + dest[keys[i]] = src[keys[i]]; + } + i++; + } + return dest; +}, 'extend', 'Use `assign`.'); + +/** + * merge the values from src in the dest. + * means that properties that exist in dest will not be overwritten by src + * @param {Object} dest + * @param {Object} src + * @returns {Object} dest + */ +var merge = deprecate(function merge(dest, src) { + return extend(dest, src, true); +}, 'merge', 'Use `assign`.'); + +// this prevents errors when Hammer is loaded in the presence of an AMD +// style loader but by script tag, not by the loader. + +assign(Hammer, { + INPUT_START: INPUT_START, + INPUT_MOVE: INPUT_MOVE, + INPUT_END: INPUT_END, + INPUT_CANCEL: INPUT_CANCEL, + + STATE_POSSIBLE: STATE_POSSIBLE, + STATE_BEGAN: STATE_BEGAN, + STATE_CHANGED: STATE_CHANGED, + STATE_ENDED: STATE_ENDED, + STATE_RECOGNIZED: STATE_RECOGNIZED, + STATE_CANCELLED: STATE_CANCELLED, + STATE_FAILED: STATE_FAILED, + + DIRECTION_NONE: DIRECTION_NONE, + DIRECTION_LEFT: DIRECTION_LEFT, + DIRECTION_RIGHT: DIRECTION_RIGHT, + DIRECTION_UP: DIRECTION_UP, + DIRECTION_DOWN: DIRECTION_DOWN, + DIRECTION_HORIZONTAL: DIRECTION_HORIZONTAL, + DIRECTION_VERTICAL: DIRECTION_VERTICAL, + DIRECTION_ALL: DIRECTION_ALL, + + Manager: Manager, + Input: Input, + TouchAction: TouchAction, + + TouchInput: TouchInput, + MouseInput: MouseInput, + PointerEventInput: PointerEventInput, + TouchMouseInput: TouchMouseInput, + SingleTouchInput: SingleTouchInput, + + Recognizer: Recognizer, + AttrRecognizer: AttrRecognizer, + Tap: TapRecognizer, + Pan: PanRecognizer, + Swipe: SwipeRecognizer, + Pinch: PinchRecognizer, + Rotate: RotateRecognizer, + Press: PressRecognizer, + + on: addEventListeners, + off: removeEventListeners, + each: each, + merge: merge, + extend: extend, + assign: assign, + inherit: inherit, + bindFn: bindFn, + prefixed: prefixed +}); if (typeof define === 'function' && define.amd) { define(function () { return Hammer; diff --git a/package.json b/package.json index 43fe7b0fe..9f2d976b0 100644 --- a/package.json +++ b/package.json @@ -32,6 +32,7 @@ }, "dependencies": {}, "devDependencies": { + "babel-preset-es2015-rollup": "^1.1.1", "changelogplease": "^1.2.0", "git-tags": "^0.2.4", "grunt": "0.4.x", @@ -45,7 +46,9 @@ "grunt-jscs": "^0.8.0", "grunt-string-replace": "^0.2.7", "hammer-simulator": "git://github.com/hammerjs/simulator#master", - "jquery-hammerjs": "2.0.x" + "jquery-hammerjs": "2.0.x", + "rollup": "^0.26.3", + "rollup-plugin-babel": "^2.4.0" }, "main": "hammer.js", "engines": { diff --git a/src/main.js b/src/main.js index a05a298c1..cca2807bc 100644 --- a/src/main.js +++ b/src/main.js @@ -1,7 +1,91 @@ import {Hammer} from './hammer'; +import {assign} from './utilsjs/assign'; +import {INPUT_START,INPUT_MOVE,INPUT_END,INPUT_CANCEL} from './inputjs/inputConsts'; +import {STATE_POSSIBLE,STATE_BEGAN,STATE_CHANGED,STATE_ENDED,STATE_RECOGNIZED,STATE_CANCELLED,STATE_FAILED} from './recognizerjs/recognizerConsts'; +import {DIRECTION_NONE,DIRECTION_LEFT,DIRECTION_RIGHT,DIRECTION_UP,DIRECTION_DOWN,DIRECTION_HORIZONTAL,DIRECTION_VERTICAL,DIRECTION_ALL} from './inputjs/inputConsts'; +import {Manager} from './manager'; +import {Input} from './inputjs/inputConstructor'; +import {TouchAction} from './touchactionjs/touchActionConstructor'; +import {TouchInput} from './input/touch'; +import {MouseInput} from './input/mouse'; +import {PointerEventInput} from './input/pointerevent'; +import {SingleTouchInput} from './input/singletouch'; +import {TouchMouseInput} from './input/touchmouse'; + +import {Recognizer} from './recognizerjs/recognizerConstructor'; +import {AttrRecognizer} from './recognizers/attribute'; +import {TapRecognizer} from './recognizers/tap'; +import {PanRecognizer} from './recognizers/pan'; +import {SwipeRecognizer} from './recognizers/swipe'; +import {PinchRecognizer} from './recognizers/pinch'; +import {RotateRecognizer} from './recognizers/rotate'; +import {PressRecognizer} from './recognizers/press'; + +import {addEventListeners} from './utilsjs/addEventListeners'; +import {removeEventListeners} from './utilsjs/removeEventListeners'; +import {each} from './utilsjs/each'; +import {merge} from './utilsjs/merge'; +import {extend} from './utilsjs/extend'; +import {inherit} from './utilsjs/inherit'; +import {bindFn} from './utilsjs/bindFn'; +import {prefixed} from './utilsjs/prefixed'; + // this prevents errors when Hammer is loaded in the presence of an AMD // style loader but by script tag, not by the loader. + +assign(Hammer, { + INPUT_START: INPUT_START, + INPUT_MOVE: INPUT_MOVE, + INPUT_END: INPUT_END, + INPUT_CANCEL: INPUT_CANCEL, + + STATE_POSSIBLE: STATE_POSSIBLE, + STATE_BEGAN: STATE_BEGAN, + STATE_CHANGED: STATE_CHANGED, + STATE_ENDED: STATE_ENDED, + STATE_RECOGNIZED: STATE_RECOGNIZED, + STATE_CANCELLED: STATE_CANCELLED, + STATE_FAILED: STATE_FAILED, + + DIRECTION_NONE: DIRECTION_NONE, + DIRECTION_LEFT: DIRECTION_LEFT, + DIRECTION_RIGHT: DIRECTION_RIGHT, + DIRECTION_UP: DIRECTION_UP, + DIRECTION_DOWN: DIRECTION_DOWN, + DIRECTION_HORIZONTAL: DIRECTION_HORIZONTAL, + DIRECTION_VERTICAL: DIRECTION_VERTICAL, + DIRECTION_ALL: DIRECTION_ALL, + + Manager: Manager, + Input: Input, + TouchAction: TouchAction, + + TouchInput: TouchInput, + MouseInput: MouseInput, + PointerEventInput: PointerEventInput, + TouchMouseInput: TouchMouseInput, + SingleTouchInput: SingleTouchInput, + + Recognizer: Recognizer, + AttrRecognizer: AttrRecognizer, + Tap: TapRecognizer, + Pan: PanRecognizer, + Swipe: SwipeRecognizer, + Pinch: PinchRecognizer, + Rotate: RotateRecognizer, + Press: PressRecognizer, + + on: addEventListeners, + off: removeEventListeners, + each: each, + merge: merge, + extend: extend, + assign: assign, + inherit: inherit, + bindFn: bindFn, + prefixed: prefixed +}); var freeGlobal = (typeof window !== 'undefined' ? window : (typeof self !== 'undefined' ? self : {})); // jshint ignore:line freeGlobal.Hammer = Hammer; From 89f1154a204170fb1af91288090adc500e06db62 Mon Sep 17 00:00:00 2001 From: Arjun Kathuria Date: Sat, 4 Jun 2016 00:14:15 +0530 Subject: [PATCH 17/61] utils properly linted --- src/utilsjs/addEventListeners.js | 3 --- src/utilsjs/assign.js | 6 +----- src/utilsjs/bindFn.js | 7 +------ src/utilsjs/boolOrFn.js | 7 ++----- src/utilsjs/deprecate.js | 6 +----- src/utilsjs/each.js | 6 +----- src/utilsjs/extend.js | 7 ++----- src/utilsjs/getWindowForElement.js | 2 +- src/utilsjs/hasParent.js | 4 ---- src/utilsjs/ifUndefined.js | 6 +----- src/utilsjs/inArray.js | 6 +----- src/utilsjs/inStr.js | 6 +----- src/utilsjs/inherit.js | 7 ++----- src/utilsjs/invokeArrayArg.js | 5 +---- src/utilsjs/merge.js | 10 +++------- src/utilsjs/prefixed.js | 5 +---- src/utilsjs/removeEventListeners.js | 8 ++------ src/utilsjs/setTimeoutContext.js | 5 +---- src/utilsjs/splitStr.js | 6 +----- src/utilsjs/toArray.js | 6 +----- src/utilsjs/uniqueArray.js | 5 +---- src/utilsjs/uniqueId.js | 6 +----- src/utilsjs/utilsConsts.js | 6 +----- 23 files changed, 27 insertions(+), 108 deletions(-) diff --git a/src/utilsjs/addEventListeners.js b/src/utilsjs/addEventListeners.js index 22e29a98e..b4475beea 100644 --- a/src/utilsjs/addEventListeners.js +++ b/src/utilsjs/addEventListeners.js @@ -1,6 +1,3 @@ -/** - * Created by arjun on 20/05/16. - */ import {each} from './each'; import {splitStr} from './splitStr'; /** diff --git a/src/utilsjs/assign.js b/src/utilsjs/assign.js index b4ba35bfa..c002b3d3f 100644 --- a/src/utilsjs/assign.js +++ b/src/utilsjs/assign.js @@ -1,7 +1,3 @@ -/** - * Created by arjun on 19/05/16. - */ - /** * extend object. * means that properties in dest will be overwritten by the ones in src. @@ -33,4 +29,4 @@ if (typeof Object.assign !== 'function') { assign = Object.assign; } -export {assign} \ No newline at end of file +export {assign}; diff --git a/src/utilsjs/bindFn.js b/src/utilsjs/bindFn.js index 404b4ee2e..859a8ff3e 100644 --- a/src/utilsjs/bindFn.js +++ b/src/utilsjs/bindFn.js @@ -1,8 +1,3 @@ -/** - * - * Created by arjun on 20/05/16. - */ - /** * simple function bind * @param {Function} fn @@ -15,4 +10,4 @@ function bindFn(fn, context) { }; } -export {bindFn} +export {bindFn}; diff --git a/src/utilsjs/boolOrFn.js b/src/utilsjs/boolOrFn.js index d6a4409da..aff64a1e3 100644 --- a/src/utilsjs/boolOrFn.js +++ b/src/utilsjs/boolOrFn.js @@ -1,7 +1,4 @@ -/** - * Created by arjun on 20/05/16. - */ -import {TYPE_FUNCTION} from './utilsConsts' +import {TYPE_FUNCTION} from './utilsConsts'; /** * let a boolean value also be a function that must return a boolean * this first item in args will be used as the context @@ -16,4 +13,4 @@ function boolOrFn(val, args) { return val; } -export {boolOrFn}; \ No newline at end of file +export {boolOrFn}; diff --git a/src/utilsjs/deprecate.js b/src/utilsjs/deprecate.js index 0fd903b00..b13340fe4 100644 --- a/src/utilsjs/deprecate.js +++ b/src/utilsjs/deprecate.js @@ -1,7 +1,3 @@ -/** - * Created by arjun on 19/05/16. - */ - /** * wrap a method with a deprecation warning and stack trace * @param {Function} method @@ -25,4 +21,4 @@ function deprecate(method, name, message) { }; } -export {deprecate}; \ No newline at end of file +export {deprecate}; diff --git a/src/utilsjs/each.js b/src/utilsjs/each.js index a807da408..8e8b65b99 100644 --- a/src/utilsjs/each.js +++ b/src/utilsjs/each.js @@ -1,7 +1,3 @@ -/** - * Created by arjun on 19/05/16. - */ - /** * walk objects and arrays * @param {Object} obj @@ -30,4 +26,4 @@ function each(obj, iterator, context) { } } -export {each} \ No newline at end of file +export {each}; diff --git a/src/utilsjs/extend.js b/src/utilsjs/extend.js index dfdb4c80b..17de8c135 100644 --- a/src/utilsjs/extend.js +++ b/src/utilsjs/extend.js @@ -1,7 +1,4 @@ -/** - * Created by arjun on 19/05/16. - */ -import {deprecate} from './deprecate' +import {deprecate} from './deprecate'; /** * extend object. * means that properties in dest will be overwritten by the ones in src. @@ -22,4 +19,4 @@ var extend = deprecate(function extend(dest, src, merge) { return dest; }, 'extend', 'Use `assign`.'); -export {extend}; \ No newline at end of file +export {extend}; diff --git a/src/utilsjs/getWindowForElement.js b/src/utilsjs/getWindowForElement.js index 5e6ed882e..37757b232 100644 --- a/src/utilsjs/getWindowForElement.js +++ b/src/utilsjs/getWindowForElement.js @@ -7,4 +7,4 @@ function getWindowForElement(element) { var doc = element.ownerDocument || element; return (doc.defaultView || doc.parentWindow || window); } -export {getWindowForElement}; \ No newline at end of file +export {getWindowForElement}; diff --git a/src/utilsjs/hasParent.js b/src/utilsjs/hasParent.js index a4ae0dcf1..e4ee0c899 100644 --- a/src/utilsjs/hasParent.js +++ b/src/utilsjs/hasParent.js @@ -1,7 +1,3 @@ -/** - * Created by arjun on 20/05/16. - */ - /** * find if a node is in the given parent * @method hasParent diff --git a/src/utilsjs/ifUndefined.js b/src/utilsjs/ifUndefined.js index ff14ff948..7a96b23f0 100644 --- a/src/utilsjs/ifUndefined.js +++ b/src/utilsjs/ifUndefined.js @@ -1,7 +1,3 @@ -/** - * Created by arjun on 25/05/16. - */ - /** * use the val2 when val1 is undefined * @param {*} val1 @@ -12,4 +8,4 @@ function ifUndefined(val1, val2) { return (val1 === undefined) ? val2 : val1; } -export {ifUndefined}; \ No newline at end of file +export {ifUndefined}; diff --git a/src/utilsjs/inArray.js b/src/utilsjs/inArray.js index 2c513f8b1..58bd456a3 100644 --- a/src/utilsjs/inArray.js +++ b/src/utilsjs/inArray.js @@ -1,7 +1,3 @@ -/** - * Created by arjun on 20/05/16. - */ - /** * find if a array contains the object using indexOf or a simple polyFill * @param {Array} src @@ -24,4 +20,4 @@ function inArray(src, find, findByKey) { } } -export {inArray}; \ No newline at end of file +export {inArray}; diff --git a/src/utilsjs/inStr.js b/src/utilsjs/inStr.js index 1de483bca..c4c93370f 100644 --- a/src/utilsjs/inStr.js +++ b/src/utilsjs/inStr.js @@ -1,7 +1,3 @@ -/** - * Created by arjun on 20/05/16. - */ - /** * small indexOf wrapper * @param {String} str @@ -12,4 +8,4 @@ function inStr(str, find) { return str.indexOf(find) > -1; } -export {inStr}; \ No newline at end of file +export {inStr}; diff --git a/src/utilsjs/inherit.js b/src/utilsjs/inherit.js index e077ab89d..3483ab066 100644 --- a/src/utilsjs/inherit.js +++ b/src/utilsjs/inherit.js @@ -1,7 +1,4 @@ -/** - * Created by arjun on 19/05/16. - */ -import {assign} from './assign' +import {assign} from './assign'; /** * simple class inheritance * @param {Function} child @@ -21,4 +18,4 @@ function inherit(child, base, properties) { } } -export {inherit} \ No newline at end of file +export {inherit}; diff --git a/src/utilsjs/invokeArrayArg.js b/src/utilsjs/invokeArrayArg.js index a83ef5a69..21d400854 100644 --- a/src/utilsjs/invokeArrayArg.js +++ b/src/utilsjs/invokeArrayArg.js @@ -1,6 +1,3 @@ -/** - * Created by arjun on 19/05/16. - */ import {each} from './each'; /** * if the argument is an array, we want to execute the fn on each entry @@ -19,4 +16,4 @@ function invokeArrayArg(arg, fn, context) { return false; } -export {invokeArrayArg}; \ No newline at end of file +export {invokeArrayArg}; diff --git a/src/utilsjs/merge.js b/src/utilsjs/merge.js index a48c32221..6ca144c8b 100644 --- a/src/utilsjs/merge.js +++ b/src/utilsjs/merge.js @@ -1,9 +1,5 @@ -/** - * Created by arjun on 19/05/16. - */ - -import {deprecate} from './deprecate' -import {extend} from './extend' +import {deprecate} from './deprecate'; +import {extend} from './extend'; /** * merge the values from src in the dest. * means that properties that exist in dest will not be overwritten by src @@ -15,4 +11,4 @@ var merge = deprecate(function merge(dest, src) { return extend(dest, src, true); }, 'merge', 'Use `assign`.'); -export {merge}; \ No newline at end of file +export {merge}; diff --git a/src/utilsjs/prefixed.js b/src/utilsjs/prefixed.js index 1eb14fa8e..bd6ea07f9 100644 --- a/src/utilsjs/prefixed.js +++ b/src/utilsjs/prefixed.js @@ -1,6 +1,3 @@ -/** - * Created by arjun on 20/05/16. - */ import {VENDOR_PREFIXES} from './utilsConsts'; /** * get the prefixed property @@ -25,4 +22,4 @@ function prefixed(obj, property) { return undefined; } -export {prefixed}; \ No newline at end of file +export {prefixed}; diff --git a/src/utilsjs/removeEventListeners.js b/src/utilsjs/removeEventListeners.js index 4a44e6d63..5a396b6a6 100644 --- a/src/utilsjs/removeEventListeners.js +++ b/src/utilsjs/removeEventListeners.js @@ -1,9 +1,5 @@ -/** - * - * Created by arjun on 20/05/16. - */ -import {each} from './each' -import {splitStr} from './splitStr' +import {each} from './each'; +import {splitStr} from './splitStr'; /** * removeEventListener with multiple events at once * @param {EventTarget} target diff --git a/src/utilsjs/setTimeoutContext.js b/src/utilsjs/setTimeoutContext.js index 5f3d7a045..3437d4202 100644 --- a/src/utilsjs/setTimeoutContext.js +++ b/src/utilsjs/setTimeoutContext.js @@ -1,6 +1,3 @@ -/** - * Created by arjun on 19/05/16. - */ import {bindFn} from './bindFn'; /** * set a timeout with a given scope @@ -13,4 +10,4 @@ function setTimeoutContext(fn, timeout, context) { return setTimeout(bindFn(fn, context), timeout); } -export {setTimeoutContext}; \ No newline at end of file +export {setTimeoutContext}; diff --git a/src/utilsjs/splitStr.js b/src/utilsjs/splitStr.js index d0c510e11..1897926a9 100644 --- a/src/utilsjs/splitStr.js +++ b/src/utilsjs/splitStr.js @@ -1,7 +1,3 @@ -/** - * Created by arjun on 20/05/16. - */ - /** * split string on whitespace * @param {String} str @@ -11,4 +7,4 @@ function splitStr(str) { return str.trim().split(/\s+/g); } -export {splitStr}; \ No newline at end of file +export {splitStr}; diff --git a/src/utilsjs/toArray.js b/src/utilsjs/toArray.js index f5d6503a3..2de0d7f18 100644 --- a/src/utilsjs/toArray.js +++ b/src/utilsjs/toArray.js @@ -1,7 +1,3 @@ -/** - * Created by arjun on 20/05/16. - */ - /** * convert array-like objects to real arrays * @param {Object} obj @@ -11,4 +7,4 @@ function toArray(obj) { return Array.prototype.slice.call(obj, 0); } -export {toArray} \ No newline at end of file +export {toArray}; diff --git a/src/utilsjs/uniqueArray.js b/src/utilsjs/uniqueArray.js index 1a6b5e497..7c12da9e7 100644 --- a/src/utilsjs/uniqueArray.js +++ b/src/utilsjs/uniqueArray.js @@ -1,6 +1,3 @@ -/** - * Created by arjun on 20/05/16. - */ import {inArray} from './inArray'; /** * unique array with objects based on a key (like 'id') or just by the array's value @@ -36,4 +33,4 @@ function uniqueArray(src, key, sort) { return results; } -export {uniqueArray}; \ No newline at end of file +export {uniqueArray}; diff --git a/src/utilsjs/uniqueId.js b/src/utilsjs/uniqueId.js index ece3fd158..b7f7c4029 100644 --- a/src/utilsjs/uniqueId.js +++ b/src/utilsjs/uniqueId.js @@ -1,7 +1,3 @@ -/** - * Created by arjun on 20/05/16. - */ - /** * get a unique id * @returns {number} uniqueId @@ -11,4 +7,4 @@ function uniqueId() { return _uniqueId++; } -export {uniqueId}; \ No newline at end of file +export {uniqueId}; diff --git a/src/utilsjs/utilsConsts.js b/src/utilsjs/utilsConsts.js index 4b68844cf..5e5b43a17 100644 --- a/src/utilsjs/utilsConsts.js +++ b/src/utilsjs/utilsConsts.js @@ -1,7 +1,3 @@ -/** - * Created by arjun on 19/05/16. - */ - var VENDOR_PREFIXES = ['', 'webkit', 'Moz', 'MS', 'ms', 'o']; var TEST_ELEMENT = document.createElement('div'); @@ -11,4 +7,4 @@ var round = Math.round; var abs = Math.abs; var now = Date.now; -export {VENDOR_PREFIXES,TEST_ELEMENT,TYPE_FUNCTION,round,abs,now} \ No newline at end of file +export {VENDOR_PREFIXES,TEST_ELEMENT,TYPE_FUNCTION,round,abs,now}; From 15cfd9a0877e986564f83ee97682b1057a5e2dea Mon Sep 17 00:00:00 2001 From: Arjun Kathuria Date: Sat, 4 Jun 2016 00:37:21 +0530 Subject: [PATCH 18/61] inputjs files lintered nicely --- src/inputjs/computeDeltaXY.js | 7 ++----- src/inputjs/computeInputData.js | 7 +------ src/inputjs/computeIntervalInputData.js | 11 ++++------- src/inputjs/createInputInstance.js | 11 ++++------- src/inputjs/getAngle.js | 8 +++----- src/inputjs/getCenter.js | 6 ++---- src/inputjs/getDirection.js | 4 +--- src/inputjs/getDistance.js | 8 +++----- src/inputjs/getRotation.js | 8 +++----- src/inputjs/getScale.js | 6 +----- src/inputjs/getVelocity.js | 6 +----- src/inputjs/inputConstructor.js | 7 ++----- src/inputjs/inputConsts.js | 13 ++++++------- src/inputjs/inputHandler.js | 5 +---- src/inputjs/simpleCloneInputData.js | 4 +--- 15 files changed, 35 insertions(+), 76 deletions(-) diff --git a/src/inputjs/computeDeltaXY.js b/src/inputjs/computeDeltaXY.js index b28718d8f..a1d4b8fc2 100644 --- a/src/inputjs/computeDeltaXY.js +++ b/src/inputjs/computeDeltaXY.js @@ -1,7 +1,4 @@ -/** - * Created by arjun on 20/05/16. - */ -import {INPUT_START,INPUT_END} from './inputConsts' +import {INPUT_START,INPUT_END} from './inputConsts'; function computeDeltaXY(session, input) { var center = input.center; @@ -25,4 +22,4 @@ function computeDeltaXY(session, input) { input.deltaY = prevDelta.y + (center.y - offset.y); } -export {computeDeltaXY}; \ No newline at end of file +export {computeDeltaXY}; diff --git a/src/inputjs/computeInputData.js b/src/inputjs/computeInputData.js index d075f77a7..54b4fa99a 100644 --- a/src/inputjs/computeInputData.js +++ b/src/inputjs/computeInputData.js @@ -1,7 +1,3 @@ -/** - * - * Created by arjun on 19/05/16. - */ import {now} from '../utilsjs/utilsConsts'; import {abs} from '../utilsjs/utilsConsts'; import {hasParent} from '../utilsjs/hasParent'; @@ -16,7 +12,6 @@ import {getScale} from './getScale'; import {getRotation} from './getRotation'; import {computeIntervalInputData} from './computeIntervalInputData'; - /** * extend the data with some usable properties like scale, rotate, velocity etc * @param {Object} manager @@ -74,4 +69,4 @@ function computeInputData(manager, input) { input.target = target; } -export {computeInputData}; \ No newline at end of file +export {computeInputData}; diff --git a/src/inputjs/computeIntervalInputData.js b/src/inputjs/computeIntervalInputData.js index dd65a72ec..f102f7258 100644 --- a/src/inputjs/computeIntervalInputData.js +++ b/src/inputjs/computeIntervalInputData.js @@ -1,10 +1,7 @@ -/** - * Created by arjun on 20/05/16. - */ -import {INPUT_CANCEL,COMPUTE_INTERVAL} from './inputConsts' -import {abs} from '../utilsjs/utilsConsts' -import {getVelocity} from './getVelocity' -import {getDirection} from './getDirection' +import {INPUT_CANCEL,COMPUTE_INTERVAL} from './inputConsts'; +import {abs} from '../utilsjs/utilsConsts'; +import {getVelocity} from './getVelocity'; +import {getDirection} from './getDirection'; /** * velocity is calculated every x ms * @param {Object} session diff --git a/src/inputjs/createInputInstance.js b/src/inputjs/createInputInstance.js index f1b76e02e..d9872962e 100644 --- a/src/inputjs/createInputInstance.js +++ b/src/inputjs/createInputInstance.js @@ -1,13 +1,10 @@ -/** - * Created by arjun on 19/05/16. - * Remember to import PointerEventInout - */ -import {SUPPORT_POINTER_EVENTS,SUPPORT_ONLY_TOUCH,SUPPORT_TOUCH} from './inputConsts' -import {inputHandler} from './inputHandler' +import {SUPPORT_POINTER_EVENTS,SUPPORT_ONLY_TOUCH,SUPPORT_TOUCH} from './inputConsts'; +import {inputHandler} from './inputHandler'; import {PointerEventInput} from '../input/pointerevent'; import {TouchInput} from '../input/touch'; import {MouseInput} from '../input/mouse'; import {TouchMouseInput} from '../input/touchmouse'; + /** * create new input type manager * called by the Manager constructor @@ -32,4 +29,4 @@ function createInputInstance(manager) { return new (Type)(manager, inputHandler); } -export {createInputInstance} \ No newline at end of file +export {createInputInstance}; diff --git a/src/inputjs/getAngle.js b/src/inputjs/getAngle.js index 1d7cb7e27..14ed31e71 100644 --- a/src/inputjs/getAngle.js +++ b/src/inputjs/getAngle.js @@ -1,7 +1,5 @@ -/** - * Created by arjun on 20/05/16. - */ -import {PROPS_XY} from './inputConsts' +import {PROPS_XY} from './inputConsts'; + /** * calculate the angle between two coordinates * @param {Object} p1 @@ -18,4 +16,4 @@ function getAngle(p1, p2, props) { return Math.atan2(y, x) * 180 / Math.PI; } -export {getAngle}; \ No newline at end of file +export {getAngle}; diff --git a/src/inputjs/getCenter.js b/src/inputjs/getCenter.js index ca62995f3..9fae4ef09 100644 --- a/src/inputjs/getCenter.js +++ b/src/inputjs/getCenter.js @@ -1,7 +1,5 @@ -/** - * Created by arjun on 20/05/16. - */ -import {round} from '../utilsjs/utilsConsts' +import {round} from '../utilsjs/utilsConsts'; + /** * get the center of all the pointers * @param {Array} pointers diff --git a/src/inputjs/getDirection.js b/src/inputjs/getDirection.js index cf02ebbd3..8879445a4 100644 --- a/src/inputjs/getDirection.js +++ b/src/inputjs/getDirection.js @@ -1,8 +1,6 @@ -/** - * Created by arjun on 20/05/16. - */ import {abs} from '../utilsjs/utilsConsts'; import {DIRECTION_NONE,DIRECTION_LEFT,DIRECTION_RIGHT,DIRECTION_UP,DIRECTION_DOWN} from './inputConsts'; + /** * get the direction between two points * @param {Number} x diff --git a/src/inputjs/getDistance.js b/src/inputjs/getDistance.js index 8c466fc3b..3b1557026 100644 --- a/src/inputjs/getDistance.js +++ b/src/inputjs/getDistance.js @@ -1,7 +1,5 @@ -/** - * Created by arjun on 20/05/16. - */ -import {PROPS_XY} from './inputConsts' +import {PROPS_XY} from './inputConsts'; + /** * calculate the absolute distance between two points * @param {Object} p1 {x, y} @@ -19,4 +17,4 @@ function getDistance(p1, p2, props) { return Math.sqrt((x * x) + (y * y)); } -export {getDistance}; \ No newline at end of file +export {getDistance}; diff --git a/src/inputjs/getRotation.js b/src/inputjs/getRotation.js index d293c9df6..4a1bd303a 100644 --- a/src/inputjs/getRotation.js +++ b/src/inputjs/getRotation.js @@ -1,8 +1,6 @@ -/** - * Created by arjun on 20/05/16. - */ -import {getAngle} from './getAngle' -import {PROPS_CLIENT_XY} from './inputConsts' +import {getAngle} from './getAngle'; +import {PROPS_CLIENT_XY} from './inputConsts'; + /** * calculate the rotation degrees between two pointersets * @param {Array} start array of pointers diff --git a/src/inputjs/getScale.js b/src/inputjs/getScale.js index 8a137a3f5..1c1bc86bb 100644 --- a/src/inputjs/getScale.js +++ b/src/inputjs/getScale.js @@ -1,7 +1,3 @@ -/** - * - * Created by arjun on 20/05/16. - */ import {PROPS_CLIENT_XY} from './inputConsts'; import {getDistance} from './getDistance'; /** @@ -15,4 +11,4 @@ function getScale(start, end) { return getDistance(end[0], end[1], PROPS_CLIENT_XY) / getDistance(start[0], start[1], PROPS_CLIENT_XY); } -export {getScale}; \ No newline at end of file +export {getScale}; diff --git a/src/inputjs/getVelocity.js b/src/inputjs/getVelocity.js index e02f40953..72c4ad6dd 100644 --- a/src/inputjs/getVelocity.js +++ b/src/inputjs/getVelocity.js @@ -1,7 +1,3 @@ -/** - * Created by arjun on 20/05/16. - */ - /** * calculate the velocity between two points. unit is in px per ms. * @param {Number} deltaTime @@ -16,4 +12,4 @@ function getVelocity(deltaTime, x, y) { }; } -export {getVelocity}; \ No newline at end of file +export {getVelocity}; diff --git a/src/inputjs/inputConstructor.js b/src/inputjs/inputConstructor.js index b63499b5d..c41242795 100644 --- a/src/inputjs/inputConstructor.js +++ b/src/inputjs/inputConstructor.js @@ -1,11 +1,8 @@ -/** - * - * Created by arjun on 18/05/16. - */ import {boolOrFn} from './../utilsjs/boolOrFn'; import {addEventListeners} from './../utilsjs/addEventListeners'; import {removeEventListeners} from './../utilsjs/removeEventListeners'; import {getWindowForElement} from './../utilsjs/getWindowForElement'; + /** * create new input type manager * @param {Manager} manager @@ -58,4 +55,4 @@ Input.prototype = { } }; -export {Input} \ No newline at end of file +export {Input}; diff --git a/src/inputjs/inputConsts.js b/src/inputjs/inputConsts.js index d1ff1d735..279149ef0 100644 --- a/src/inputjs/inputConsts.js +++ b/src/inputjs/inputConsts.js @@ -1,7 +1,4 @@ -/** - * Created by arjun on 19/05/16. - */ -import {prefixed} from '../utilsjs/prefixed' +import {prefixed} from '../utilsjs/prefixed'; var MOBILE_REGEX = /mobile|tablet|ip(ad|hone|od)|android/i; @@ -34,6 +31,8 @@ var DIRECTION_ALL = DIRECTION_HORIZONTAL | DIRECTION_VERTICAL; var PROPS_XY = ['x', 'y']; var PROPS_CLIENT_XY = ['clientX', 'clientY']; -export {MOBILE_REGEX,SUPPORT_ONLY_TOUCH,SUPPORT_POINTER_EVENTS,SUPPORT_TOUCH,INPUT_TYPE_KINECT,INPUT_TYPE_MOUSE,INPUT_TYPE_PEN, - INPUT_TYPE_TOUCH,COMPUTE_INTERVAL,INPUT_START,INPUT_MOVE,INPUT_END,INPUT_CANCEL,DIRECTION_NONE,DIRECTION_LEFT,DIRECTION_RIGHT, - DIRECTION_UP,DIRECTION_DOWN,DIRECTION_HORIZONTAL,DIRECTION_VERTICAL,DIRECTION_ALL,PROPS_XY,PROPS_CLIENT_XY} \ No newline at end of file +export {MOBILE_REGEX,SUPPORT_ONLY_TOUCH,SUPPORT_POINTER_EVENTS,SUPPORT_TOUCH, + INPUT_TYPE_KINECT,INPUT_TYPE_MOUSE,INPUT_TYPE_PEN,INPUT_TYPE_TOUCH,COMPUTE_INTERVAL, + INPUT_START,INPUT_MOVE,INPUT_END,INPUT_CANCEL,DIRECTION_NONE,DIRECTION_LEFT, + DIRECTION_RIGHT,DIRECTION_UP,DIRECTION_DOWN,DIRECTION_HORIZONTAL, + DIRECTION_VERTICAL,DIRECTION_ALL,PROPS_XY,PROPS_CLIENT_XY}; diff --git a/src/inputjs/inputHandler.js b/src/inputjs/inputHandler.js index 83c95190b..8022f40c2 100644 --- a/src/inputjs/inputHandler.js +++ b/src/inputjs/inputHandler.js @@ -1,6 +1,3 @@ -/** - * Created by arjun on 19/05/16. - */ import {INPUT_START,INPUT_END,INPUT_CANCEL} from './inputConsts'; import {computeInputData} from './computeInputData'; @@ -37,4 +34,4 @@ function inputHandler(manager, eventType, input) { manager.session.prevInput = input; } -export {inputHandler} \ No newline at end of file +export {inputHandler}; diff --git a/src/inputjs/simpleCloneInputData.js b/src/inputjs/simpleCloneInputData.js index 109f947d6..fbcea8f0f 100644 --- a/src/inputjs/simpleCloneInputData.js +++ b/src/inputjs/simpleCloneInputData.js @@ -1,8 +1,6 @@ -/** - * Created by arjun on 20/05/16. - */ import {now,round} from '../utilsjs/utilsConsts'; import {getCenter} from './getCenter'; + /** * create a simple clone from the input used for storage of firstInput and firstMultiple * @param {Object} input From 17926d306e273aac61fb198ba4960a54122b414f Mon Sep 17 00:00:00 2001 From: Chris Thoburn Date: Fri, 3 Jun 2016 16:36:08 -0500 Subject: [PATCH 19/61] stashing all the work --- addon/-private/gestures/README.md | 12 +++ addon/-private/gestures/inputs/input.js | 89 ++++++++++++++++--- addon/-private/gestures/inputs/touch.js | 31 +++++++ addon/-private/gestures/layer.js | 30 +++++++ addon/-private/gestures/manager.js | 24 +++-- .../gestures/recognizers/vertical-pan.js | 25 ++++++ .../-private/gestures/streams/stream-event.js | 21 ++--- addon/-private/gestures/streams/stream.js | 47 +++++++--- addon/components/history-outlet/component.js | 31 ++++++- server/mocks/items.js | 4 +- tests/dummy/app/routes/application/route.js | 4 + .../dummy/app/routes/application/template.hbs | 1 + 12 files changed, 273 insertions(+), 46 deletions(-) create mode 100644 addon/-private/gestures/README.md create mode 100644 addon/-private/gestures/recognizers/vertical-pan.js create mode 100644 tests/dummy/app/routes/application/route.js create mode 100644 tests/dummy/app/routes/application/template.hbs diff --git a/addon/-private/gestures/README.md b/addon/-private/gestures/README.md new file mode 100644 index 000000000..710fea60b --- /dev/null +++ b/addon/-private/gestures/README.md @@ -0,0 +1,12 @@ +Hammer.js 3.0 +============= + +`-private/gestures` is an initial exploratory spike of the concepts +likely to be used for Hammer.js 3.0 + +So if you reached in, found these, and like them, you should now reach out +finish them, and land them in Hammer ;) + +- Chris + + diff --git a/addon/-private/gestures/inputs/input.js b/addon/-private/gestures/inputs/input.js index 07cb25b8c..bb2bcb7b9 100644 --- a/addon/-private/gestures/inputs/input.js +++ b/addon/-private/gestures/inputs/input.js @@ -1,14 +1,19 @@ import Stream from '../streams/stream'; import StreamEvent from '../streams/stream-event'; -export default class input { +export default class Input { - constructor(element) { + constructor(element, manager) { this.element = element; this.streams = []; this.attached = false; + this.handler = null; + this.handlerStack = []; + this.streaming = false; + this.hasPointer = false; this._handlers = { start: null, update: null, end: null, interrupt: null }; + this.manager = manager; } _bind(name) { @@ -19,35 +24,83 @@ export default class input { start(event) { let stream = new Stream(); + const { streams } = this; - this.streams.push(stream); - stream.open({ + // splice existing streams + for (let s of streams) { + s.split(); + } + + this.streaming = true; + this.hasPointer = true; + + streams.push(stream); + let streamEvent = stream.open({ + x: event.clientX, + y: event.clientY, event }); + + if (this.handler) { + this.handlerStack.push(this.handler); + this.handler = null; + } + + this.manager.recognize(this, streams, streamEvent); } update(event) { - let [stream] = this.streams; + if (!this.streaming) { + return; + } + + let { streams } = this; + let [stream] = streams; - stream.push({ + let streamEvent = stream.push({ + x: event.clientX, + y: event.clientY, event }); + + if (this.handler) { + this.handler.recognize(this, this.streams, streamEvent); + } else { + this.manager.recognize(this, this.streams, streamEvent); + } } - end(event) { - let [stream] = this.streams; + _close(event) { + let { streams } = this; + let stream = streams.pop(); - stream.close({ + this.streaming = false; + + let streamEvent = stream.close({ + x: event.clientX, + y: event.clientY, event }); + + if (this.handler) { + this.handler.recognize(this, this.streams, streamEvent); + this.handler = null; + } else { + this.manager.recognize(this, this.streams, streamEvent); + } } - interrupt(event) { - let [stream] = this.streams; + end(event) { + if (this.hasPointer) { + this._close(event); + this.hasPointer = false; + } + } - stream.close({ - event - }); + interrupt(event) { + if (this.hasPointer) { + this._close(event); + } } attach() { @@ -58,4 +111,12 @@ export default class input { throw new Error('Interface Method Not Implemented'); } + destroy() { + this.deattach(); + this.manager = null; + this.element = null; + this.streams = null; + this.handler = null; + } + } diff --git a/addon/-private/gestures/inputs/touch.js b/addon/-private/gestures/inputs/touch.js index e69de29bb..15bcd1a0d 100644 --- a/addon/-private/gestures/inputs/touch.js +++ b/addon/-private/gestures/inputs/touch.js @@ -0,0 +1,31 @@ +import Input from './input'; + +export default class TouchInput extends Input { + + attach() { + if (this.attached) { + return; + } + const { element } = this; + + element.addEventListener('mousedown', this._bind('start') , true); + element.addEventListener('mouseup', this._bind('end') , true); + element.addEventListener('mouseexit', this._bind('interrupt') , true); + element.addEventListener('mousemove', this._bind('update') , true); + + this.attached = true; + } + + deattach() { + if (this.attached) { + return; + } + const { element, _handlers } = this; + + element.removeEventListener('mousedown', _handlers.start , true); + element.removeEventListener('mouseup', _handlers.end , true); + element.removeEventListener('mouseexit', _handlers.interrupt , true); + element.removeEventListener('mousemove', _handlers.update , true); + } + +} diff --git a/addon/-private/gestures/layer.js b/addon/-private/gestures/layer.js index e69de29bb..21218f4a4 100644 --- a/addon/-private/gestures/layer.js +++ b/addon/-private/gestures/layer.js @@ -0,0 +1,30 @@ + +export default class Layer { + + constructor(element) { + this.element = element; + this.recognizers = []; + this.isRecognizing = false; + } + + recognize(input, streams, streamEvent) { + let { recognizers } = this; + + for (let recognizer of recognizers) { + if (recognizer.recognize(input, streams, streamEvent)) { + this.isRecognizing = true; + input.handler = recognizer; + break; + } + } + + return this.isRecognizing; + } + + addRecognizer(recognizerInstance) { + this.recognizers.push(recognizerInstance); + } + + emit() + +} diff --git a/addon/-private/gestures/manager.js b/addon/-private/gestures/manager.js index 0be3d0957..7a27da19e 100644 --- a/addon/-private/gestures/manager.js +++ b/addon/-private/gestures/manager.js @@ -5,8 +5,7 @@ const DEFAULT_OPTIONS = { inputs: availableInputs() }; - - +const HANDLER_SYMBOL = Symbol('element-gesture-handler'); export default class Manager { @@ -24,7 +23,18 @@ export default class Manager { } registerInput(name, InputClass) { - this.inputs[name] = new InputClass(this.rootElement); + this.inputs[name] = new InputClass(this.rootElement, this); + } + + recognize(input, streams, streamEvent) { + let layer = this._findParentLayer(streamEvent.element); + + while (layer) { + if (layer.recognize(input, streams, streamEvent)) { + break; + } + layer = layer.parent; + } } unregisterInput(name) { @@ -36,7 +46,7 @@ export default class Manager { } } - register(layer) { + registerLayer(layer) { this.layers.set(layer.element, layer); layer.parent = this._findParentLayer(layer.element); @@ -47,7 +57,7 @@ export default class Manager { } } - forget(layer) { + forgetLayer(layer) { this.layers.delete(layer.element); // join parent/child @@ -65,7 +75,7 @@ export default class Manager { } } - private _findParentLayer(element) { + _findParentLayer(element) { do { if (element.hasAttribute('gesture-layer')) { let layer = this.layers.get(element); @@ -79,7 +89,7 @@ export default class Manager { return null; } - private _teardown() { + _teardown() { this.streams.touch.destroy(); this.streams.mouse.destroy(); diff --git a/addon/-private/gestures/recognizers/vertical-pan.js b/addon/-private/gestures/recognizers/vertical-pan.js new file mode 100644 index 000000000..f8958e4a2 --- /dev/null +++ b/addon/-private/gestures/recognizers/vertical-pan.js @@ -0,0 +1,25 @@ + + +export default class VerticalPan { + + constructor(options) { + this.name = 'vertical-pan'; + this.options = options; + this.layer = null; + this.inflow = []; + + this.isRecognizing = false; + } + + recognize(input, streams, streamEvent) { + if (this.isRecognizing || streamEvent.totalY === 0 && streamEvent.totalX !== 0) { + this.isRecognizing = true; + this.layer.emit({ + name: 'pan', + event: streamEvent + }); + console.log('vertical pan!', streamEvent); + } + } + +} diff --git a/addon/-private/gestures/streams/stream-event.js b/addon/-private/gestures/streams/stream-event.js index 988e2759d..1c0a47086 100644 --- a/addon/-private/gestures/streams/stream-event.js +++ b/addon/-private/gestures/streams/stream-event.js @@ -1,10 +1,11 @@ -/* global performance */ +/* global Math, performance */ -class StreamEvent { +export default class StreamEvent { - constructor(name, options, event, prev) { + constructor(name, info, prev) { this.name = name; - this.source = event; + this.element = info.event.target; + this.source = info.event; this.silenced = false; this.prev = prev; @@ -13,16 +14,16 @@ class StreamEvent { this.dT = prev ? this.time - prev.time : 0; // current position (clientX/Y) - this.x = options.x; - this.y = options.y; + this.x = info.x; + this.y = info.y; // deltas off of origin event - this.totalX = options.x - options.originX; - this.totalY = options.y - options.originY; + this.totalX = info.x - info.originX; + this.totalY = info.y - info.originY; // deltas off of last event - this.dX = prev ? options.x - prev.x : 0; - this.dY = prev ? options.y - prev.y : 0; + this.dX = prev ? info.x - prev.x : 0; + this.dY = prev ? info.y - prev.y : 0; // prediction values this.acceleration = 0; diff --git a/addon/-private/gestures/streams/stream.js b/addon/-private/gestures/streams/stream.js index 8de2d08ca..80c7bbb92 100644 --- a/addon/-private/gestures/streams/stream.js +++ b/addon/-private/gestures/streams/stream.js @@ -1,30 +1,57 @@ +import StreamEvent from './stream-event'; export default class Stream { - constructor(element) { - this.element = element; - this.series = []; - this.handler = null; + constructor() { + this.segments = null; + this.series = null; + this.active = false; } - start(e) { + open(info) { + this.active = true; + this.segments = []; + this.series = []; - } + this.segments.push(this.series); - update(e) { + let streamEvent = new StreamEvent('start', info); + this.series.push(streamEvent); + return streamEvent; } - end(e) { + push(info) { + if (this.segments.length > 1 || this.series.length > 2) { + info.cancelable = false; + } + + let lastEvent = this.series[this.series.length - 1]; + let streamEvent = new StreamEvent('move', info, lastEvent); + this.series.push(streamEvent); + return streamEvent; } - vanish(e) { + close(info) { + this.active = false; + let lastEvent = this.series[this.series.length - 1]; + let streamEvent = new StreamEvent('end', info, lastEvent); + this.series.push(streamEvent); + return streamEvent; } - timeout(e) { + silence() { + let [down, initial] = this.segments[0]; + down.silence(); + initial.silence(); + } + + split() { + this.series = []; + this.segments.push(this.series); } } diff --git a/addon/components/history-outlet/component.js b/addon/components/history-outlet/component.js index 520cd4ff4..c5cd1ab08 100644 --- a/addon/components/history-outlet/component.js +++ b/addon/components/history-outlet/component.js @@ -4,7 +4,6 @@ import Layer from 'history/-private/gestures/layer'; import VerticalPan from 'history/-private/gestures/recognizers/vertical-pan'; const { - computed, inject, Component } = Ember; @@ -19,6 +18,26 @@ export default Component.extend({ gestures: inject.service('gesture-recognition'), + pan() { + console.log('pan!'); + }, + + panStart() { + console.log('pan start'); + }, + + panLeft() { + console.log('pan left'); + }, + + panRight() { + console.log('pan right'); + }, + + panEnd() { + console.log('pan end'); + }, + willInsertElement() { this._left = this.element.children[0]; this._main = this.element.children[1]; @@ -27,7 +46,13 @@ export default Component.extend({ }, setupLayer() { - + this.layer = new Layer(this.element); + this.layer.addRecognizer(new VerticalPan()); + this.layer.on('*', ({name, event}) => { + if (this[name]) { + this[name](event); + } + }); }, didInsertElement() { @@ -36,7 +61,7 @@ export default Component.extend({ init() { this._super(); - this.layer = new Layer(this.element); + this.setupLayer(); } }); diff --git a/server/mocks/items.js b/server/mocks/items.js index 61a1658ec..e1b0a8baf 100644 --- a/server/mocks/items.js +++ b/server/mocks/items.js @@ -44,7 +44,7 @@ Store.prototype.serializeOne = function serializeOne(record) { }; Store.prototype.normalizeOne = function normalizeOne(record) { - var values = record.data.attributes; + var values = record.data && record.data.attributes ? record.data.attributes : {}; delete values.id; @@ -93,7 +93,7 @@ Store.prototype.findAll = function findAll() { }; Store.prototype.deleteRecord = function deleteRecord(id) { - let record = this._recordMap[id]; + var record = this._recordMap[id]; if (!record || record.__deleted) { throw new Error(500); diff --git a/tests/dummy/app/routes/application/route.js b/tests/dummy/app/routes/application/route.js new file mode 100644 index 000000000..26d9f3124 --- /dev/null +++ b/tests/dummy/app/routes/application/route.js @@ -0,0 +1,4 @@ +import Ember from 'ember'; + +export default Ember.Route.extend({ +}); diff --git a/tests/dummy/app/routes/application/template.hbs b/tests/dummy/app/routes/application/template.hbs new file mode 100644 index 000000000..1da2d383a --- /dev/null +++ b/tests/dummy/app/routes/application/template.hbs @@ -0,0 +1 @@ +{{history-outlet}} From e98011680bcafd160cbbb638344c496912e97152 Mon Sep 17 00:00:00 2001 From: Arjun Kathuria Date: Sat, 4 Jun 2016 21:25:08 +0530 Subject: [PATCH 20/61] all code lintered properly along with the dot config files --- .jscsrc | 4 ++-- .jshintrc | 3 ++- src/hammer.js | 4 ++-- src/input/mouse.js | 3 ++- src/input/pointerevent.js | 7 ++++--- src/input/singletouch.js | 13 +++++++------ src/input/touch.js | 6 +++--- src/input/touchmouse.js | 6 +++--- src/main.js | 11 +++++++---- src/manager.js | 5 ++--- src/recognizerjs/directionStr.js | 8 +++----- src/recognizerjs/getRecognizerByNameIfManager.js | 7 +------ src/recognizerjs/recognizerConstructor.js | 12 +++++------- src/recognizerjs/recognizerConsts.js | 7 +------ src/recognizerjs/stateStr.js | 8 +++----- src/recognizers/attribute.js | 4 ++-- src/recognizers/pan.js | 14 +++++++------- src/recognizers/pinch.js | 5 +++-- src/recognizers/press.js | 4 ++-- src/recognizers/rotate.js | 5 +++-- src/recognizers/tap.js | 5 +++-- src/touchactionjs/cleanTouchActions.js | 7 ++----- src/touchactionjs/getTouchActionProps.js | 7 ++----- src/touchactionjs/touchActionConstructor.js | 7 ++----- src/touchactionjs/touchactionConsts.js | 9 +++------ 25 files changed, 76 insertions(+), 95 deletions(-) diff --git a/.jscsrc b/.jscsrc index 168677b82..b2c223815 100644 --- a/.jscsrc +++ b/.jscsrc @@ -86,10 +86,10 @@ "disallowSpacesInsideObjectBrackets": "all", "disallowSpacesInsideArrayBrackets": "all", "disallowSpacesInsideParentheses": true, - "validateJSDoc": { + "jsDoc": { "checkParamNames": true, "requireParamTypes": true }, "disallowMultipleLineBreaks": true, "disallowNewlineBeforeBlockStatements": true -} \ No newline at end of file +} diff --git a/.jshintrc b/.jshintrc index 925e528b5..7cd12e8a0 100644 --- a/.jshintrc +++ b/.jshintrc @@ -5,10 +5,11 @@ "expr": true, "maxerr": 100, "freeze": true, + "esversion":6, "newcap": true, "node": true, "quotmark": "single", - "strict": true, + "strict": false, "sub": true, "trailing": true, "undef": true, diff --git a/src/hammer.js b/src/hammer.js index f97581722..9c1fac9ad 100644 --- a/src/hammer.js +++ b/src/hammer.js @@ -1,6 +1,6 @@ import {ifUndefined} from './utilsjs/ifUndefined'; import {TOUCH_ACTION_COMPUTE} from './touchactionjs/touchactionConsts'; -import {DIRECTION_HORIZONTAL} from './inputjs/inputConsts' +import {DIRECTION_HORIZONTAL} from './inputjs/inputConsts'; import {RotateRecognizer} from './recognizers/rotate'; import {PinchRecognizer} from './recognizers/pinch'; import {SwipeRecognizer} from './recognizers/swipe'; @@ -138,4 +138,4 @@ Hammer.defaults = { } }; -export {Hammer}; \ No newline at end of file +export {Hammer}; diff --git a/src/input/mouse.js b/src/input/mouse.js index f9b36d9ff..ed94bc820 100644 --- a/src/input/mouse.js +++ b/src/input/mouse.js @@ -1,6 +1,7 @@ -import {INPUT_START,INPUT_MOVE,INPUT_END,INPUT_TYPE_MOUSE} from '../inputjs/inputConsts' +import {INPUT_START,INPUT_MOVE,INPUT_END,INPUT_TYPE_MOUSE} from '../inputjs/inputConsts'; import {Input} from '../inputjs/inputConstructor'; import {inherit} from '../utilsjs/inherit'; + var MOUSE_INPUT_MAP = { mousedown: INPUT_START, mousemove: INPUT_MOVE, diff --git a/src/input/pointerevent.js b/src/input/pointerevent.js index 8ec1b2262..478befeeb 100644 --- a/src/input/pointerevent.js +++ b/src/input/pointerevent.js @@ -1,7 +1,8 @@ -import {INPUT_START,INPUT_END,INPUT_CANCEL,INPUT_MOVE,INPUT_TYPE_TOUCH,INPUT_TYPE_MOUSE,INPUT_TYPE_PEN,INPUT_TYPE_KINECT} from '../inputjs/inputConsts' +import {INPUT_START,INPUT_END,INPUT_CANCEL,INPUT_MOVE,INPUT_TYPE_TOUCH, +INPUT_TYPE_MOUSE,INPUT_TYPE_PEN,INPUT_TYPE_KINECT} from '../inputjs/inputConsts'; import {Input} from '../inputjs/inputConstructor'; import {inherit} from '../utilsjs/inherit'; -import {inArray} from '../utilsjs/inArray' +import {inArray} from '../utilsjs/inArray'; var POINTER_INPUT_MAP = { pointerdown: INPUT_START, @@ -92,4 +93,4 @@ inherit(PointerEventInput, Input, { } }); -export {PointerEventInput} \ No newline at end of file +export {PointerEventInput}; diff --git a/src/input/singletouch.js b/src/input/singletouch.js index ce8d68b94..f295867b1 100644 --- a/src/input/singletouch.js +++ b/src/input/singletouch.js @@ -1,8 +1,9 @@ -import {INPUT_START,INPUT_MOVE,INPUT_END,INPUT_CANCEL,INPUT_TYPE_TOUCH} from '../inputjs/inputConsts' -import {Input} from '../inputjs/inputConstructor' -import {inherit} from '../utilsjs/inherit' -import {toArray} from '../utilsjs/toArray' -import {uniqueArray} from '../utilsjs/uniqueArray' +import {INPUT_START,INPUT_MOVE,INPUT_END,INPUT_CANCEL,INPUT_TYPE_TOUCH} from '../inputjs/inputConsts'; +import {Input} from '../inputjs/inputConstructor'; +import {inherit} from '../utilsjs/inherit'; +import {toArray} from '../utilsjs/toArray'; +import {uniqueArray} from '../utilsjs/uniqueArray'; + var SINGLE_TOUCH_INPUT_MAP = { touchstart: INPUT_START, touchmove: INPUT_MOVE, @@ -72,4 +73,4 @@ function normalizeSingleTouches(ev, type) { return [all, changed]; } -export {SingleTouchInput} +export {SingleTouchInput}; diff --git a/src/input/touch.js b/src/input/touch.js index 3bbaacd18..f933d52e1 100644 --- a/src/input/touch.js +++ b/src/input/touch.js @@ -1,5 +1,5 @@ -import {INPUT_START,INPUT_MOVE,INPUT_END,INPUT_CANCEL,INPUT_TYPE_TOUCH} from '../inputjs/inputConsts' -import {Input} from '../inputjs/inputConstructor' +import {INPUT_START,INPUT_MOVE,INPUT_END,INPUT_CANCEL,INPUT_TYPE_TOUCH} from '../inputjs/inputConsts'; +import {Input} from '../inputjs/inputConstructor'; import {inherit} from '../utilsjs/inherit'; import {toArray} from '../utilsjs/toArray'; import {hasParent} from '../utilsjs/hasParent'; @@ -104,4 +104,4 @@ function getTouches(ev, type) { ]; } -export {TouchInput}; \ No newline at end of file +export {TouchInput}; diff --git a/src/input/touchmouse.js b/src/input/touchmouse.js index 78f35ceff..1dcd3b207 100644 --- a/src/input/touchmouse.js +++ b/src/input/touchmouse.js @@ -1,9 +1,9 @@ -import {Input} from '../inputjs/inputConstructor' +import {Input} from '../inputjs/inputConstructor'; import {inherit} from '../utilsjs/inherit'; import {bindFn} from '../utilsjs/bindFn'; import {TouchInput} from './touch'; import {MouseInput} from './mouse'; -import {INPUT_START,INPUT_END,INPUT_CANCEL,INPUT_TYPE_TOUCH,INPUT_TYPE_MOUSE} from '../inputjs/inputConsts' +import {INPUT_START,INPUT_END,INPUT_CANCEL,INPUT_TYPE_TOUCH,INPUT_TYPE_MOUSE} from '../inputjs/inputConsts'; /** * Combined touch and mouse input @@ -101,4 +101,4 @@ function isSyntheticEvent(eventData) { return false; } -export {TouchMouseInput} \ No newline at end of file +export {TouchMouseInput}; diff --git a/src/main.js b/src/main.js index cca2807bc..9ce8b5e63 100644 --- a/src/main.js +++ b/src/main.js @@ -1,8 +1,11 @@ import {Hammer} from './hammer'; import {assign} from './utilsjs/assign'; import {INPUT_START,INPUT_MOVE,INPUT_END,INPUT_CANCEL} from './inputjs/inputConsts'; -import {STATE_POSSIBLE,STATE_BEGAN,STATE_CHANGED,STATE_ENDED,STATE_RECOGNIZED,STATE_CANCELLED,STATE_FAILED} from './recognizerjs/recognizerConsts'; -import {DIRECTION_NONE,DIRECTION_LEFT,DIRECTION_RIGHT,DIRECTION_UP,DIRECTION_DOWN,DIRECTION_HORIZONTAL,DIRECTION_VERTICAL,DIRECTION_ALL} from './inputjs/inputConsts'; +import {STATE_POSSIBLE,STATE_BEGAN,STATE_CHANGED,STATE_ENDED,STATE_RECOGNIZED, + STATE_CANCELLED,STATE_FAILED} from './recognizerjs/recognizerConsts'; +import {DIRECTION_NONE,DIRECTION_LEFT,DIRECTION_RIGHT,DIRECTION_UP,DIRECTION_DOWN, + DIRECTION_HORIZONTAL,DIRECTION_VERTICAL,DIRECTION_ALL} from './inputjs/inputConsts'; + import {Manager} from './manager'; import {Input} from './inputjs/inputConstructor'; import {TouchAction} from './touchactionjs/touchActionConstructor'; @@ -30,7 +33,6 @@ import {inherit} from './utilsjs/inherit'; import {bindFn} from './utilsjs/bindFn'; import {prefixed} from './utilsjs/prefixed'; - // this prevents errors when Hammer is loaded in the presence of an AMD // style loader but by script tag, not by the loader. @@ -86,6 +88,7 @@ assign(Hammer, { bindFn: bindFn, prefixed: prefixed }); + var freeGlobal = (typeof window !== 'undefined' ? window : (typeof self !== 'undefined' ? self : {})); // jshint ignore:line freeGlobal.Hammer = Hammer; @@ -97,4 +100,4 @@ if (typeof define === 'function' && define.amd) { module.exports = Hammer; } else { window[exportName] = Hammer; -} \ No newline at end of file +} diff --git a/src/manager.js b/src/manager.js index ccce800c5..eed9dc021 100644 --- a/src/manager.js +++ b/src/manager.js @@ -10,7 +10,6 @@ import {prefixed} from './utilsjs/prefixed'; import {Recognizer} from './recognizerjs/recognizerConstructor'; import {STATE_BEGAN,STATE_ENDED,STATE_CHANGED,STATE_RECOGNIZED} from './recognizerjs/recognizerConsts'; - var STOP = 1; var FORCED_STOP = 2; @@ -114,7 +113,7 @@ Manager.prototype = { // that is being recognized. // 3. allow if the recognizer is allowed to run simultaneous with the current recognized recognizer. // this can be setup with the `recognizeWith()` method on the recognizer. - if (session.stopped !== FORCED_STOP && ( // 1 + if (session.stopped !== FORCED_STOP && (// 1 !curRecognizer || recognizer == curRecognizer || // 2 recognizer.canRecognizeWith(curRecognizer))) { // 3 recognizer.recognize(inputData); @@ -324,4 +323,4 @@ function triggerDomEvent(event, data) { data.target.dispatchEvent(gestureEvent); } -export {Manager} \ No newline at end of file +export {Manager}; diff --git a/src/recognizerjs/directionStr.js b/src/recognizerjs/directionStr.js index 88f61b61b..3513e5948 100644 --- a/src/recognizerjs/directionStr.js +++ b/src/recognizerjs/directionStr.js @@ -1,7 +1,5 @@ -/** - * Created by arjun on 25/05/16. - */ -import {DIRECTION_LEFT,DIRECTION_RIGHT,DIRECTION_UP,DIRECTION_DOWN} from '../inputjs/inputConsts' +import {DIRECTION_LEFT,DIRECTION_RIGHT,DIRECTION_UP,DIRECTION_DOWN} from '../inputjs/inputConsts'; + /** * direction cons to string * @param {constant} direction @@ -20,4 +18,4 @@ function directionStr(direction) { return ''; } -export {directionStr} \ No newline at end of file +export {directionStr}; diff --git a/src/recognizerjs/getRecognizerByNameIfManager.js b/src/recognizerjs/getRecognizerByNameIfManager.js index 04ae3fe3b..7df93f809 100644 --- a/src/recognizerjs/getRecognizerByNameIfManager.js +++ b/src/recognizerjs/getRecognizerByNameIfManager.js @@ -1,8 +1,3 @@ -/** - * Created by arjun on 25/05/16. - */ - - /** * get a recognizer by name if it is bound to a manager * @param {Recognizer|String} otherRecognizer @@ -17,4 +12,4 @@ function getRecognizerByNameIfManager(otherRecognizer, recognizer) { return otherRecognizer; } -export {getRecognizerByNameIfManager}; \ No newline at end of file +export {getRecognizerByNameIfManager}; diff --git a/src/recognizerjs/recognizerConstructor.js b/src/recognizerjs/recognizerConstructor.js index f7696ffc5..6a0d9c475 100644 --- a/src/recognizerjs/recognizerConstructor.js +++ b/src/recognizerjs/recognizerConstructor.js @@ -1,15 +1,13 @@ -/** - * Created by arjun on 25/05/16. - */ -import {STATE_POSSIBLE,STATE_ENDED,STATE_FAILED,STATE_RECOGNIZED,STATE_CANCELLED,STATE_BEGAN,STATE_CHANGED} from './recognizerConsts' +import {STATE_POSSIBLE,STATE_ENDED,STATE_FAILED,STATE_RECOGNIZED,STATE_CANCELLED, + STATE_BEGAN,STATE_CHANGED} from './recognizerConsts'; import {assign} from '../utilsjs/assign'; import {uniqueId} from '../utilsjs/uniqueId'; import {ifUndefined} from '../utilsjs/ifUndefined'; import {invokeArrayArg} from '../utilsjs/invokeArrayArg'; import {inArray} from '../utilsjs/inArray'; import {boolOrFn} from '../utilsjs/boolOrFn'; -import {getRecognizerByNameIfManager} from './getRecognizerByNameIfManager' -import {stateStr} from './stateStr' +import {getRecognizerByNameIfManager} from './getRecognizerByNameIfManager'; +import {stateStr} from './stateStr'; /** * Recognizer flow explained; * * All recognizers have the initial state of POSSIBLE when a input session starts. @@ -281,4 +279,4 @@ Recognizer.prototype = { reset: function() { } }; -export {Recognizer} ; \ No newline at end of file +export {Recognizer}; diff --git a/src/recognizerjs/recognizerConsts.js b/src/recognizerjs/recognizerConsts.js index 4b3da4cd6..c3023ba24 100644 --- a/src/recognizerjs/recognizerConsts.js +++ b/src/recognizerjs/recognizerConsts.js @@ -1,8 +1,3 @@ -/** - * Created by arjun on 25/05/16. - */ - - var STATE_POSSIBLE = 1; var STATE_BEGAN = 2; var STATE_CHANGED = 4; @@ -11,4 +6,4 @@ var STATE_RECOGNIZED = STATE_ENDED; var STATE_CANCELLED = 16; var STATE_FAILED = 32; -export {STATE_POSSIBLE,STATE_BEGAN,STATE_CHANGED,STATE_ENDED,STATE_RECOGNIZED,STATE_CANCELLED,STATE_FAILED}; \ No newline at end of file +export {STATE_POSSIBLE,STATE_BEGAN,STATE_CHANGED,STATE_ENDED,STATE_RECOGNIZED,STATE_CANCELLED,STATE_FAILED}; diff --git a/src/recognizerjs/stateStr.js b/src/recognizerjs/stateStr.js index ffd439399..651f9f3b1 100644 --- a/src/recognizerjs/stateStr.js +++ b/src/recognizerjs/stateStr.js @@ -1,7 +1,5 @@ -/** - * Created by arjun on 25/05/16. - */ -import {STATE_CANCELLED,STATE_ENDED,STATE_CHANGED,STATE_BEGAN} from './recognizerConsts' +import {STATE_CANCELLED,STATE_ENDED,STATE_CHANGED,STATE_BEGAN} from './recognizerConsts'; + /** * get a usable string, used as event postfix * @param {constant} state @@ -20,4 +18,4 @@ function stateStr(state) { return ''; } -export {stateStr} \ No newline at end of file +export {stateStr}; diff --git a/src/recognizers/attribute.js b/src/recognizers/attribute.js index 533f0946c..c98052d08 100644 --- a/src/recognizers/attribute.js +++ b/src/recognizers/attribute.js @@ -1,5 +1,5 @@ import {inherit} from '../utilsjs/inherit'; -import {Recognizer} from '../recognizerjs/recognizerConstructor' +import {Recognizer} from '../recognizerjs/recognizerConstructor'; import {STATE_BEGAN,STATE_CHANGED,STATE_CANCELLED,STATE_ENDED,STATE_FAILED} from '../recognizerjs/recognizerConsts'; import {INPUT_CANCEL,INPUT_END} from '../inputjs/inputConsts'; @@ -64,4 +64,4 @@ inherit(AttrRecognizer, Recognizer, { } }); -export {AttrRecognizer} +export {AttrRecognizer}; diff --git a/src/recognizers/pan.js b/src/recognizers/pan.js index 28f0ea0e7..8fed083b6 100644 --- a/src/recognizers/pan.js +++ b/src/recognizers/pan.js @@ -1,10 +1,10 @@ -import {AttrRecognizer} from './attribute' -import {inherit} from '../utilsjs/inherit' +import {AttrRecognizer} from './attribute'; +import {inherit} from '../utilsjs/inherit'; import {DIRECTION_ALL,DIRECTION_HORIZONTAL,DIRECTION_VERTICAL,DIRECTION_NONE,DIRECTION_UP,DIRECTION_DOWN, -DIRECTION_LEFT,DIRECTION_RIGHT} from '../inputjs/inputConsts' -import {STATE_BEGAN} from '../recognizerjs/recognizerConsts' -import {TOUCH_ACTION_PAN_X,TOUCH_ACTION_PAN_Y} from '../touchactionjs/touchactionConsts' -import {directionStr} from '../recognizerjs/directionStr' +DIRECTION_LEFT,DIRECTION_RIGHT} from '../inputjs/inputConsts'; +import {STATE_BEGAN} from '../recognizerjs/recognizerConsts'; +import {TOUCH_ACTION_PAN_X,TOUCH_ACTION_PAN_Y} from '../touchactionjs/touchactionConsts'; +import {directionStr} from '../recognizerjs/directionStr'; /** * Pan @@ -86,4 +86,4 @@ inherit(PanRecognizer, AttrRecognizer, { } }); -export {PanRecognizer}; \ No newline at end of file +export {PanRecognizer}; diff --git a/src/recognizers/pinch.js b/src/recognizers/pinch.js index f978cae43..0e5b960ff 100644 --- a/src/recognizers/pinch.js +++ b/src/recognizers/pinch.js @@ -1,7 +1,8 @@ import {AttrRecognizer} from './attribute'; import {inherit} from '../utilsjs/inherit'; import {TOUCH_ACTION_NONE} from '../touchactionjs/touchactionConsts'; -import {STATE_BEGAN} from '../recognizerjs/recognizerConsts' +import {STATE_BEGAN} from '../recognizerjs/recognizerConsts'; + /** * Pinch * Recognized when two or more pointers are moving toward (zoom-in) or away from each other (zoom-out). @@ -41,4 +42,4 @@ inherit(PinchRecognizer, AttrRecognizer, { } }); -export {PinchRecognizer}; \ No newline at end of file +export {PinchRecognizer}; diff --git a/src/recognizers/press.js b/src/recognizers/press.js index bba59bfb2..ae2795fb7 100644 --- a/src/recognizers/press.js +++ b/src/recognizers/press.js @@ -4,7 +4,7 @@ import {inherit} from '../utilsjs/inherit'; import {now} from '../utilsjs/utilsConsts'; import {setTimeoutContext} from '../utilsjs/setTimeoutContext'; import {TOUCH_ACTION_AUTO} from '../touchactionjs/touchactionConsts'; -import {INPUT_START,INPUT_END,INPUT_CANCEL} from '../inputjs/inputConsts' +import {INPUT_START,INPUT_END,INPUT_CANCEL} from '../inputjs/inputConsts'; /** * Press @@ -77,4 +77,4 @@ inherit(PressRecognizer, Recognizer, { } }); -export {PressRecognizer}; \ No newline at end of file +export {PressRecognizer}; diff --git a/src/recognizers/rotate.js b/src/recognizers/rotate.js index 8895a5420..af50e1c90 100644 --- a/src/recognizers/rotate.js +++ b/src/recognizers/rotate.js @@ -1,7 +1,8 @@ import {AttrRecognizer} from './attribute'; import {inherit} from '../utilsjs/inherit'; import {TOUCH_ACTION_NONE} from '../touchactionjs/touchactionConsts'; -import {STATE_BEGAN} from '../recognizerjs/recognizerConsts' +import {STATE_BEGAN} from '../recognizerjs/recognizerConsts'; + /** * Rotate * Recognized when two or more pointer are moving in a circular motion. @@ -33,4 +34,4 @@ inherit(RotateRecognizer, AttrRecognizer, { } }); -export {RotateRecognizer}; \ No newline at end of file +export {RotateRecognizer}; diff --git a/src/recognizers/tap.js b/src/recognizers/tap.js index 9d9b995e5..5cee178ac 100644 --- a/src/recognizers/tap.js +++ b/src/recognizers/tap.js @@ -3,8 +3,9 @@ import {setTimeoutContext} from '../utilsjs/setTimeoutContext'; import {Recognizer} from '../recognizerjs/recognizerConstructor'; import {TOUCH_ACTION_MANIPULATION} from '../touchactionjs/touchactionConsts'; import {INPUT_START,INPUT_END} from '../inputjs/inputConsts'; -import {STATE_RECOGNIZED,STATE_BEGAN,STATE_FAILED} from '../recognizerjs/recognizerConsts' +import {STATE_RECOGNIZED,STATE_BEGAN,STATE_FAILED} from '../recognizerjs/recognizerConsts'; import {getDistance} from '../inputjs/getDistance'; + /** * A tap is ecognized when the pointer is doing a small tap/click. Multiple taps are recognized if they occur * between the given interval and position. The delay option can be used to recognize multi-taps without firing @@ -120,4 +121,4 @@ inherit(TapRecognizer, Recognizer, { } }); -export {TapRecognizer}; \ No newline at end of file +export {TapRecognizer}; diff --git a/src/touchactionjs/cleanTouchActions.js b/src/touchactionjs/cleanTouchActions.js index ed9af1616..5e0e976df 100644 --- a/src/touchactionjs/cleanTouchActions.js +++ b/src/touchactionjs/cleanTouchActions.js @@ -1,9 +1,6 @@ -/* - * Created by arjun on 28/05/16. - */ import {inStr} from '../utilsjs/inStr'; import {TOUCH_ACTION_NONE,TOUCH_ACTION_PAN_X,TOUCH_ACTION_PAN_Y,TOUCH_ACTION_MANIPULATION, -TOUCH_ACTION_AUTO} from './touchactionConsts' +TOUCH_ACTION_AUTO} from './touchactionConsts'; /** * when the touchActions are collected they are not a valid value, so we need to clean things up. * @@ -40,4 +37,4 @@ function cleanTouchActions(actions) { return TOUCH_ACTION_AUTO; } -export {cleanTouchActions} \ No newline at end of file +export {cleanTouchActions}; diff --git a/src/touchactionjs/getTouchActionProps.js b/src/touchactionjs/getTouchActionProps.js index 1c49843a5..2c531258e 100644 --- a/src/touchactionjs/getTouchActionProps.js +++ b/src/touchactionjs/getTouchActionProps.js @@ -1,7 +1,4 @@ -/* - * Created by arjun on 28/05/16. - */ -import {NATIVE_TOUCH_ACTION} from './touchactionConsts' +import {NATIVE_TOUCH_ACTION} from './touchactionConsts'; function getTouchActionProps() { if (!NATIVE_TOUCH_ACTION) { return false; @@ -17,4 +14,4 @@ function getTouchActionProps() { return touchMap; } -export {getTouchActionProps} +export {getTouchActionProps}; diff --git a/src/touchactionjs/touchActionConstructor.js b/src/touchactionjs/touchActionConstructor.js index 0f3375a8e..ff0f8841d 100644 --- a/src/touchactionjs/touchActionConstructor.js +++ b/src/touchactionjs/touchActionConstructor.js @@ -1,7 +1,3 @@ -/** - * Created by arjun on 28/05/16. - */ - import {TOUCH_ACTION_COMPUTE,TOUCH_ACTION_MAP,NATIVE_TOUCH_ACTION,PREFIXED_TOUCH_ACTION,TOUCH_ACTION_NONE, TOUCH_ACTION_PAN_X,TOUCH_ACTION_PAN_Y} from './touchactionConsts'; import {DIRECTION_VERTICAL,DIRECTION_HORIZONTAL} from '../inputjs/inputConsts'; @@ -9,6 +5,7 @@ import {each} from '../utilsjs/each'; import {boolOrFn} from '../utilsjs/boolOrFn'; import {inStr} from '../utilsjs/inStr'; import {cleanTouchActions} from './cleanTouchActions'; + /** * Touch Action * sets the touchAction property or uses the js alternative @@ -112,4 +109,4 @@ TouchAction.prototype = { } }; -export {TouchAction}; \ No newline at end of file +export {TouchAction}; diff --git a/src/touchactionjs/touchactionConsts.js b/src/touchactionjs/touchactionConsts.js index de4bd4964..34c5e36a7 100644 --- a/src/touchactionjs/touchactionConsts.js +++ b/src/touchactionjs/touchactionConsts.js @@ -1,7 +1,3 @@ -/** - * - * Created by arjun on 28/05/16. - */ import {prefixed} from '../utilsjs/prefixed'; import {TEST_ELEMENT} from '../utilsjs/utilsConsts'; import {getTouchActionProps} from './getTouchActionProps'; @@ -18,5 +14,6 @@ var TOUCH_ACTION_PAN_X = 'pan-x'; var TOUCH_ACTION_PAN_Y = 'pan-y'; var TOUCH_ACTION_MAP = getTouchActionProps(); -export {PREFIXED_TOUCH_ACTION,NATIVE_TOUCH_ACTION,TOUCH_ACTION_AUTO,TOUCH_ACTION_COMPUTE,TOUCH_ACTION_MANIPULATION,TOUCH_ACTION_NONE, -TOUCH_ACTION_PAN_X,TOUCH_ACTION_PAN_Y,TOUCH_ACTION_MAP} +export {PREFIXED_TOUCH_ACTION,NATIVE_TOUCH_ACTION,TOUCH_ACTION_AUTO,TOUCH_ACTION_COMPUTE, + TOUCH_ACTION_MANIPULATION,TOUCH_ACTION_NONE,TOUCH_ACTION_PAN_X,TOUCH_ACTION_PAN_Y, + TOUCH_ACTION_MAP}; From 1af421be01a251206d28947602f96a22ddbad1be Mon Sep 17 00:00:00 2001 From: Arjun Kathuria Date: Sun, 5 Jun 2016 01:44:23 +0530 Subject: [PATCH 21/61] implemented default exports and renamed utilsjs folder to utils --- bundle.js | 2691 ----------------- src/hammer.js | 2 +- src/input/mouse.js | 2 +- src/input/pointerevent.js | 4 +- src/input/singletouch.js | 6 +- src/input/touch.js | 8 +- src/input/touchmouse.js | 4 +- src/inputjs/computeDeltaXY.js | 4 +- src/inputjs/computeInputData.js | 30 +- src/inputjs/computeIntervalInputData.js | 11 +- src/inputjs/createInputInstance.js | 6 +- src/inputjs/getAngle.js | 4 +- src/inputjs/getCenter.js | 6 +- src/inputjs/getDirection.js | 6 +- src/inputjs/getDistance.js | 4 +- src/inputjs/getRotation.js | 6 +- src/inputjs/getScale.js | 6 +- src/inputjs/getVelocity.js | 4 +- src/inputjs/inputConstructor.js | 8 +- src/inputjs/inputConsts.js | 2 +- src/inputjs/inputHandler.js | 6 +- src/inputjs/simpleCloneInputData.js | 8 +- src/main.js | 18 +- src/manager.js | 14 +- src/recognizerjs/directionStr.js | 4 +- .../getRecognizerByNameIfManager.js | 4 +- src/recognizerjs/recognizerConstructor.js | 19 +- src/recognizerjs/stateStr.js | 4 +- src/recognizers/attribute.js | 2 +- src/recognizers/pan.js | 4 +- src/recognizers/pinch.js | 2 +- src/recognizers/press.js | 6 +- src/recognizers/rotate.js | 2 +- src/recognizers/swipe.js | 6 +- src/recognizers/tap.js | 8 +- src/touchactionjs/cleanTouchActions.js | 6 +- src/touchactionjs/getTouchActionProps.js | 5 +- src/touchactionjs/touchActionConstructor.js | 8 +- src/touchactionjs/touchactionConsts.js | 6 +- src/{utilsjs => utils}/addEventListeners.js | 8 +- src/{utilsjs => utils}/assign.js | 0 src/{utilsjs => utils}/bindFn.js | 4 +- src/{utilsjs => utils}/boolOrFn.js | 4 +- src/{utilsjs => utils}/deprecate.js | 4 +- src/{utilsjs => utils}/each.js | 4 +- src/{utilsjs => utils}/extend.js | 2 +- src/{utilsjs => utils}/getWindowForElement.js | 3 +- src/{utilsjs => utils}/hasParent.js | 4 +- src/{utilsjs => utils}/ifUndefined.js | 4 +- src/{utilsjs => utils}/inArray.js | 4 +- src/{utilsjs => utils}/inStr.js | 4 +- src/{utilsjs => utils}/inherit.js | 4 +- src/{utilsjs => utils}/invokeArrayArg.js | 6 +- src/{utilsjs => utils}/merge.js | 2 +- src/{utilsjs => utils}/prefixed.js | 4 +- .../removeEventListeners.js | 8 +- src/{utilsjs => utils}/setTimeoutContext.js | 7 +- src/{utilsjs => utils}/splitStr.js | 5 +- src/{utilsjs => utils}/toArray.js | 4 +- src/{utilsjs => utils}/uniqueArray.js | 7 +- src/{utilsjs => utils}/uniqueId.js | 4 +- src/{utilsjs => utils}/utilsConsts.js | 0 62 files changed, 142 insertions(+), 2900 deletions(-) delete mode 100644 bundle.js rename src/{utilsjs => utils}/addEventListeners.js (62%) rename src/{utilsjs => utils}/assign.js (100%) rename src/{utilsjs => utils}/bindFn.js (79%) rename src/{utilsjs => utils}/boolOrFn.js (88%) rename src/{utilsjs => utils}/deprecate.js (92%) rename src/{utilsjs => utils}/each.js (90%) rename src/{utilsjs => utils}/extend.js (93%) rename src/{utilsjs => utils}/getWindowForElement.js (76%) rename src/{utilsjs => utils}/hasParent.js (84%) rename src/{utilsjs => utils}/ifUndefined.js (72%) rename src/{utilsjs => utils}/inArray.js (90%) rename src/{utilsjs => utils}/inStr.js (76%) rename src/{utilsjs => utils}/inherit.js (85%) rename src/{utilsjs => utils}/invokeArrayArg.js (81%) rename src/{utilsjs => utils}/merge.js (90%) rename src/{utilsjs => utils}/prefixed.js (90%) rename src/{utilsjs => utils}/removeEventListeners.js (62%) rename src/{utilsjs => utils}/setTimeoutContext.js (63%) rename src/{utilsjs => utils}/splitStr.js (74%) rename src/{utilsjs => utils}/toArray.js (77%) rename src/{utilsjs => utils}/uniqueArray.js (88%) rename src/{utilsjs => utils}/uniqueId.js (70%) rename src/{utilsjs => utils}/utilsConsts.js (100%) diff --git a/bundle.js b/bundle.js deleted file mode 100644 index 301757037..000000000 --- a/bundle.js +++ /dev/null @@ -1,2691 +0,0 @@ -(function(window, document, exportName, undefined) { -'use strict' - -var babelHelpers = {}; -babelHelpers.typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { - return typeof obj; -} : function (obj) { - return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj; -}; -babelHelpers; - -/** - * Created by arjun on 25/05/16. - */ - -/** - * use the val2 when val1 is undefined - * @param {*} val1 - * @param {*} val2 - * @returns {*} - */ -function ifUndefined(val1, val2) { - return val1 === undefined ? val2 : val1; -} - -/** - * Created by arjun on 19/05/16. - */ - -var VENDOR_PREFIXES = ['', 'webkit', 'Moz', 'MS', 'ms', 'o']; -var TEST_ELEMENT = document.createElement('div'); - -var TYPE_FUNCTION = 'function'; - -var round = Math.round; -var abs = Math.abs; -var now = Date.now; - -/** - * get the prefixed property - * @param {Object} obj - * @param {String} property - * @returns {String|Undefined} prefixed - */ -function prefixed(obj, property) { - var prefix, prop; - var camelProp = property[0].toUpperCase() + property.slice(1); - - var i = 0; - while (i < VENDOR_PREFIXES.length) { - prefix = VENDOR_PREFIXES[i]; - prop = prefix ? prefix + camelProp : property; - - if (prop in obj) { - return prop; - } - i++; - } - return undefined; -} - -function getTouchActionProps() { - if (!NATIVE_TOUCH_ACTION) { - return false; - } - var touchMap = {}; - var cssSupports = window.CSS && window.CSS.supports; - ['auto', 'manipulation', 'pan-y', 'pan-x', 'pan-x pan-y', 'none'].forEach(function (val) { - - // If css.supports is not supported but there is native touch-action assume it supports - // all values. This is the case for IE 10 and 11. - touchMap[val] = cssSupports ? window.CSS.supports('touch-action', val) : true; - }); - return touchMap; -} - -var PREFIXED_TOUCH_ACTION = prefixed(TEST_ELEMENT.style, 'touchAction'); -var NATIVE_TOUCH_ACTION = PREFIXED_TOUCH_ACTION !== undefined; - -// magical touchAction value -var TOUCH_ACTION_COMPUTE = 'compute'; -var TOUCH_ACTION_AUTO = 'auto'; -var TOUCH_ACTION_MANIPULATION = 'manipulation'; // not implemented -var TOUCH_ACTION_NONE = 'none'; -var TOUCH_ACTION_PAN_X = 'pan-x'; -var TOUCH_ACTION_PAN_Y = 'pan-y'; -var TOUCH_ACTION_MAP = getTouchActionProps(); - -var MOBILE_REGEX = /mobile|tablet|ip(ad|hone|od)|android/i; - -var SUPPORT_TOUCH = 'ontouchstart' in window; -var SUPPORT_POINTER_EVENTS = prefixed(window, 'PointerEvent') !== undefined; -var SUPPORT_ONLY_TOUCH = SUPPORT_TOUCH && MOBILE_REGEX.test(navigator.userAgent); - -var INPUT_TYPE_TOUCH = 'touch'; -var INPUT_TYPE_PEN = 'pen'; -var INPUT_TYPE_MOUSE = 'mouse'; -var INPUT_TYPE_KINECT = 'kinect'; - -var COMPUTE_INTERVAL = 25; - -var INPUT_START = 1; -var INPUT_MOVE = 2; -var INPUT_END = 4; -var INPUT_CANCEL = 8; - -var DIRECTION_NONE = 1; -var DIRECTION_LEFT = 2; -var DIRECTION_RIGHT = 4; -var DIRECTION_UP = 8; -var DIRECTION_DOWN = 16; - -var DIRECTION_HORIZONTAL = DIRECTION_LEFT | DIRECTION_RIGHT; -var DIRECTION_VERTICAL = DIRECTION_UP | DIRECTION_DOWN; -var DIRECTION_ALL = DIRECTION_HORIZONTAL | DIRECTION_VERTICAL; - -var PROPS_XY = ['x', 'y']; -var PROPS_CLIENT_XY = ['clientX', 'clientY']; - -/** - * Created by arjun on 19/05/16. - */ - -/** - * extend object. - * means that properties in dest will be overwritten by the ones in src. - * @param {Object} target - * @param {...Object} objects_to_assign - * @returns {Object} target - */ -var assign; -if (typeof Object.assign !== 'function') { - assign = function assign(target) { - if (target === undefined || target === null) { - throw new TypeError('Cannot convert undefined or null to object'); - } - - var output = Object(target); - for (var index = 1; index < arguments.length; index++) { - var source = arguments[index]; - if (source !== undefined && source !== null) { - for (var nextKey in source) { - if (source.hasOwnProperty(nextKey)) { - output[nextKey] = source[nextKey]; - } - } - } - } - return output; - }; -} else { - assign = Object.assign; -} - -/** - * simple class inheritance - * @param {Function} child - * @param {Function} base - * @param {Object} [properties] - */ -function inherit(child, base, properties) { - var baseP = base.prototype, - childP; - - childP = child.prototype = Object.create(baseP); - childP.constructor = child; - childP._super = baseP; - - if (properties) { - assign(childP, properties); - } -} - -/** - * Created by arjun on 25/05/16. - */ - -var STATE_POSSIBLE = 1; -var STATE_BEGAN = 2; -var STATE_CHANGED = 4; -var STATE_ENDED = 8; -var STATE_RECOGNIZED = STATE_ENDED; -var STATE_CANCELLED = 16; -var STATE_FAILED = 32; - -/** - * Created by arjun on 20/05/16. - */ - -/** - * get a unique id - * @returns {number} uniqueId - */ -var _uniqueId = 1; -function uniqueId() { - return _uniqueId++; -} - -/** - * Created by arjun on 19/05/16. - */ - -/** - * walk objects and arrays - * @param {Object} obj - * @param {Function} iterator - * @param {Object} context - */ -function each(obj, iterator, context) { - var i; - - if (!obj) { - return; - } - - if (obj.forEach) { - obj.forEach(iterator, context); - } else if (obj.length !== undefined) { - i = 0; - while (i < obj.length) { - iterator.call(context, obj[i], i, obj); - i++; - } - } else { - for (i in obj) { - obj.hasOwnProperty(i) && iterator.call(context, obj[i], i, obj); - } - } -} - -/** - * if the argument is an array, we want to execute the fn on each entry - * if it aint an array we don't want to do a thing. - * this is used by all the methods that accept a single and array argument. - * @param {*|Array} arg - * @param {String} fn - * @param {Object} [context] - * @returns {Boolean} - */ -function invokeArrayArg(arg, fn, context) { - if (Array.isArray(arg)) { - each(arg, context[fn], context); - return true; - } - return false; -} - -/** - * Created by arjun on 20/05/16. - */ - -/** - * find if a array contains the object using indexOf or a simple polyFill - * @param {Array} src - * @param {String} find - * @param {String} [findByKey] - * @return {Boolean|Number} false when not found, or the index - */ -function inArray(src, find, findByKey) { - if (src.indexOf && !findByKey) { - return src.indexOf(find); - } else { - var i = 0; - while (i < src.length) { - if (findByKey && src[i][findByKey] == find || !findByKey && src[i] === find) { - return i; - } - i++; - } - return -1; - } -} - -/** - * let a boolean value also be a function that must return a boolean - * this first item in args will be used as the context - * @param {Boolean|Function} val - * @param {Array} [args] - * @returns {Boolean} - */ -function boolOrFn(val, args) { - if ((typeof val === 'undefined' ? 'undefined' : babelHelpers.typeof(val)) == TYPE_FUNCTION) { - return val.apply(args ? args[0] || undefined : undefined, args); - } - return val; -} - -/** - * Created by arjun on 25/05/16. - */ - -/** - * get a recognizer by name if it is bound to a manager - * @param {Recognizer|String} otherRecognizer - * @param {Recognizer} recognizer - * @returns {Recognizer} - */ -function getRecognizerByNameIfManager(otherRecognizer, recognizer) { - var manager = recognizer.manager; - if (manager) { - return manager.get(otherRecognizer); - } - return otherRecognizer; -} - -/** - * get a usable string, used as event postfix - * @param {constant} state - * @returns {String} state - */ -function stateStr(state) { - if (state & STATE_CANCELLED) { - return 'cancel'; - } else if (state & STATE_ENDED) { - return 'end'; - } else if (state & STATE_CHANGED) { - return 'move'; - } else if (state & STATE_BEGAN) { - return 'start'; - } - return ''; -} - -/** - * Recognizer flow explained; * - * All recognizers have the initial state of POSSIBLE when a input session starts. - * The definition of a input session is from the first input until the last input, with all it's movement in it. * - * Example session for mouse-input: mousedown -> mousemove -> mouseup - * - * On each recognizing cycle (see Manager.recognize) the .recognize() method is executed - * which determines with state it should be. - * - * If the recognizer has the state FAILED, CANCELLED or RECOGNIZED (equals ENDED), it is reset to - * POSSIBLE to give it another change on the next cycle. - * - * Possible - * | - * +-----+---------------+ - * | | - * +-----+-----+ | - * | | | - * Failed Cancelled | - * +-------+------+ - * | | - * Recognized Began - * | - * Changed - * | - * Ended/Recognized - */ - -/** - * Recognizer - * Every recognizer needs to extend from this class. - * @constructor - * @param {Object} options - */ -function Recognizer(options) { - this.options = assign({}, this.defaults, options || {}); - - this.id = uniqueId(); - - this.manager = null; - - // default is enable true - this.options.enable = ifUndefined(this.options.enable, true); - - this.state = STATE_POSSIBLE; - - this.simultaneous = {}; - this.requireFail = []; -} - -Recognizer.prototype = { - /** - * @virtual - * @type {Object} - */ - defaults: {}, - - /** - * set options - * @param {Object} options - * @return {Recognizer} - */ - set: function set(options) { - assign(this.options, options); - - // also update the touchAction, in case something changed about the directions/enabled state - this.manager && this.manager.touchAction.update(); - return this; - }, - - /** - * recognize simultaneous with an other recognizer. - * @param {Recognizer} otherRecognizer - * @returns {Recognizer} this - */ - recognizeWith: function recognizeWith(otherRecognizer) { - if (invokeArrayArg(otherRecognizer, 'recognizeWith', this)) { - return this; - } - - var simultaneous = this.simultaneous; - otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this); - if (!simultaneous[otherRecognizer.id]) { - simultaneous[otherRecognizer.id] = otherRecognizer; - otherRecognizer.recognizeWith(this); - } - return this; - }, - - /** - * drop the simultaneous link. it doesnt remove the link on the other recognizer. - * @param {Recognizer} otherRecognizer - * @returns {Recognizer} this - */ - dropRecognizeWith: function dropRecognizeWith(otherRecognizer) { - if (invokeArrayArg(otherRecognizer, 'dropRecognizeWith', this)) { - return this; - } - - otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this); - delete this.simultaneous[otherRecognizer.id]; - return this; - }, - - /** - * recognizer can only run when an other is failing - * @param {Recognizer} otherRecognizer - * @returns {Recognizer} this - */ - requireFailure: function requireFailure(otherRecognizer) { - if (invokeArrayArg(otherRecognizer, 'requireFailure', this)) { - return this; - } - - var requireFail = this.requireFail; - otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this); - if (inArray(requireFail, otherRecognizer) === -1) { - requireFail.push(otherRecognizer); - otherRecognizer.requireFailure(this); - } - return this; - }, - - /** - * drop the requireFailure link. it does not remove the link on the other recognizer. - * @param {Recognizer} otherRecognizer - * @returns {Recognizer} this - */ - dropRequireFailure: function dropRequireFailure(otherRecognizer) { - if (invokeArrayArg(otherRecognizer, 'dropRequireFailure', this)) { - return this; - } - - otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this); - var index = inArray(this.requireFail, otherRecognizer); - if (index > -1) { - this.requireFail.splice(index, 1); - } - return this; - }, - - /** - * has require failures boolean - * @returns {boolean} - */ - hasRequireFailures: function hasRequireFailures() { - return this.requireFail.length > 0; - }, - - /** - * if the recognizer can recognize simultaneous with an other recognizer - * @param {Recognizer} otherRecognizer - * @returns {Boolean} - */ - canRecognizeWith: function canRecognizeWith(otherRecognizer) { - return !!this.simultaneous[otherRecognizer.id]; - }, - - /** - * You should use `tryEmit` instead of `emit` directly to check - * that all the needed recognizers has failed before emitting. - * @param {Object} input - */ - emit: function emit(input) { - var self = this; - var state = this.state; - - function emit(event) { - self.manager.emit(event, input); - } - - // 'panstart' and 'panmove' - if (state < STATE_ENDED) { - emit(self.options.event + stateStr(state)); - } - - emit(self.options.event); // simple 'eventName' events - - if (input.additionalEvent) { - // additional event(panleft, panright, pinchin, pinchout...) - emit(input.additionalEvent); - } - - // panend and pancancel - if (state >= STATE_ENDED) { - emit(self.options.event + stateStr(state)); - } - }, - - /** - * Check that all the require failure recognizers has failed, - * if true, it emits a gesture event, - * otherwise, setup the state to FAILED. - * @param {Object} input - */ - tryEmit: function tryEmit(input) { - if (this.canEmit()) { - return this.emit(input); - } - // it's failing anyway - this.state = STATE_FAILED; - }, - - /** - * can we emit? - * @returns {boolean} - */ - canEmit: function canEmit() { - var i = 0; - while (i < this.requireFail.length) { - if (!(this.requireFail[i].state & (STATE_FAILED | STATE_POSSIBLE))) { - return false; - } - i++; - } - return true; - }, - - /** - * update the recognizer - * @param {Object} inputData - */ - recognize: function recognize(inputData) { - // make a new copy of the inputData - // so we can change the inputData without messing up the other recognizers - var inputDataClone = assign({}, inputData); - - // is is enabled and allow recognizing? - if (!boolOrFn(this.options.enable, [this, inputDataClone])) { - this.reset(); - this.state = STATE_FAILED; - return; - } - - // reset when we've reached the end - if (this.state & (STATE_RECOGNIZED | STATE_CANCELLED | STATE_FAILED)) { - this.state = STATE_POSSIBLE; - } - - this.state = this.process(inputDataClone); - - // the recognizer has recognized a gesture - // so trigger an event - if (this.state & (STATE_BEGAN | STATE_CHANGED | STATE_ENDED | STATE_CANCELLED)) { - this.tryEmit(inputDataClone); - } - }, - - /** - * return the state of the recognizer - * the actual recognizing happens in this method - * @virtual - * @param {Object} inputData - * @returns {constant} STATE - */ - process: function process(inputData) {}, // jshint ignore:line - - /** - * return the preferred touch-action - * @virtual - * @returns {Array} - */ - getTouchAction: function getTouchAction() {}, - - /** - * called when the gesture isn't allowed to recognize - * like when another is being recognized or it is disabled - * @virtual - */ - reset: function reset() {} -}; - -/** - * This recognizer is just used as a base for the simple attribute recognizers. - * @constructor - * @extends Recognizer - */ -function AttrRecognizer() { - Recognizer.apply(this, arguments); -} - -inherit(AttrRecognizer, Recognizer, { - /** - * @namespace - * @memberof AttrRecognizer - */ - defaults: { - /** - * @type {Number} - * @default 1 - */ - pointers: 1 - }, - - /** - * Used to check if it the recognizer receives valid input, like input.distance > 10. - * @memberof AttrRecognizer - * @param {Object} input - * @returns {Boolean} recognized - */ - attrTest: function attrTest(input) { - var optionPointers = this.options.pointers; - return optionPointers === 0 || input.pointers.length === optionPointers; - }, - - /** - * Process the input and return the state for the recognizer - * @memberof AttrRecognizer - * @param {Object} input - * @returns {*} State - */ - process: function process(input) { - var state = this.state; - var eventType = input.eventType; - - var isRecognized = state & (STATE_BEGAN | STATE_CHANGED); - var isValid = this.attrTest(input); - - // on cancel input and we've recognized before, return STATE_CANCELLED - if (isRecognized && (eventType & INPUT_CANCEL || !isValid)) { - return state | STATE_CANCELLED; - } else if (isRecognized || isValid) { - if (eventType & INPUT_END) { - return state | STATE_ENDED; - } else if (!(state & STATE_BEGAN)) { - return STATE_BEGAN; - } - return state | STATE_CHANGED; - } - return STATE_FAILED; - } -}); - -/** - * Rotate - * Recognized when two or more pointer are moving in a circular motion. - * @constructor - * @extends AttrRecognizer - */ -function RotateRecognizer() { - AttrRecognizer.apply(this, arguments); -} - -inherit(RotateRecognizer, AttrRecognizer, { - /** - * @namespace - * @memberof RotateRecognizer - */ - defaults: { - event: 'rotate', - threshold: 0, - pointers: 2 - }, - - getTouchAction: function getTouchAction() { - return [TOUCH_ACTION_NONE]; - }, - - attrTest: function attrTest(input) { - return this._super.attrTest.call(this, input) && (Math.abs(input.rotation) > this.options.threshold || this.state & STATE_BEGAN); - } -}); - -/** - * Pinch - * Recognized when two or more pointers are moving toward (zoom-in) or away from each other (zoom-out). - * @constructor - * @extends AttrRecognizer - */ -function PinchRecognizer() { - AttrRecognizer.apply(this, arguments); -} - -inherit(PinchRecognizer, AttrRecognizer, { - /** - * @namespace - * @memberof PinchRecognizer - */ - defaults: { - event: 'pinch', - threshold: 0, - pointers: 2 - }, - - getTouchAction: function getTouchAction() { - return [TOUCH_ACTION_NONE]; - }, - - attrTest: function attrTest(input) { - return this._super.attrTest.call(this, input) && (Math.abs(input.scale - 1) > this.options.threshold || this.state & STATE_BEGAN); - }, - - emit: function emit(input) { - if (input.scale !== 1) { - var inOut = input.scale < 1 ? 'in' : 'out'; - input.additionalEvent = this.options.event + inOut; - } - this._super.emit.call(this, input); - } -}); - -/** - * direction cons to string - * @param {constant} direction - * @returns {String} - */ -function directionStr(direction) { - if (direction == DIRECTION_DOWN) { - return 'down'; - } else if (direction == DIRECTION_UP) { - return 'up'; - } else if (direction == DIRECTION_LEFT) { - return 'left'; - } else if (direction == DIRECTION_RIGHT) { - return 'right'; - } - return ''; -} - -/** - * Pan - * Recognized when the pointer is down and moved in the allowed direction. - * @constructor - * @extends AttrRecognizer - */ -function PanRecognizer() { - AttrRecognizer.apply(this, arguments); - - this.pX = null; - this.pY = null; -} - -inherit(PanRecognizer, AttrRecognizer, { - /** - * @namespace - * @memberof PanRecognizer - */ - defaults: { - event: 'pan', - threshold: 10, - pointers: 1, - direction: DIRECTION_ALL - }, - - getTouchAction: function getTouchAction() { - var direction = this.options.direction; - var actions = []; - if (direction & DIRECTION_HORIZONTAL) { - actions.push(TOUCH_ACTION_PAN_Y); - } - if (direction & DIRECTION_VERTICAL) { - actions.push(TOUCH_ACTION_PAN_X); - } - return actions; - }, - - directionTest: function directionTest(input) { - var options = this.options; - var hasMoved = true; - var distance = input.distance; - var direction = input.direction; - var x = input.deltaX; - var y = input.deltaY; - - // lock to axis? - if (!(direction & options.direction)) { - if (options.direction & DIRECTION_HORIZONTAL) { - direction = x === 0 ? DIRECTION_NONE : x < 0 ? DIRECTION_LEFT : DIRECTION_RIGHT; - hasMoved = x != this.pX; - distance = Math.abs(input.deltaX); - } else { - direction = y === 0 ? DIRECTION_NONE : y < 0 ? DIRECTION_UP : DIRECTION_DOWN; - hasMoved = y != this.pY; - distance = Math.abs(input.deltaY); - } - } - input.direction = direction; - return hasMoved && distance > options.threshold && direction & options.direction; - }, - - attrTest: function attrTest(input) { - return AttrRecognizer.prototype.attrTest.call(this, input) && (this.state & STATE_BEGAN || !(this.state & STATE_BEGAN) && this.directionTest(input)); - }, - - emit: function emit(input) { - - this.pX = input.deltaX; - this.pY = input.deltaY; - - var direction = directionStr(input.direction); - - if (direction) { - input.additionalEvent = this.options.event + direction; - } - this._super.emit.call(this, input); - } -}); - -/** - * Swipe - * Recognized when the pointer is moving fast (velocity), with enough distance in the allowed direction. - * @constructor - * @extends AttrRecognizer - */ -function SwipeRecognizer() { - AttrRecognizer.apply(this, arguments); -} - -inherit(SwipeRecognizer, AttrRecognizer, { - /** - * @namespace - * @memberof SwipeRecognizer - */ - defaults: { - event: 'swipe', - threshold: 10, - velocity: 0.3, - direction: DIRECTION_HORIZONTAL | DIRECTION_VERTICAL, - pointers: 1 - }, - - getTouchAction: function getTouchAction() { - return PanRecognizer.prototype.getTouchAction.call(this); - }, - - attrTest: function attrTest(input) { - var direction = this.options.direction; - var velocity; - - if (direction & (DIRECTION_HORIZONTAL | DIRECTION_VERTICAL)) { - velocity = input.overallVelocity; - } else if (direction & DIRECTION_HORIZONTAL) { - velocity = input.overallVelocityX; - } else if (direction & DIRECTION_VERTICAL) { - velocity = input.overallVelocityY; - } - - return this._super.attrTest.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; - }, - - emit: function emit(input) { - var direction = directionStr(input.offsetDirection); - if (direction) { - this.manager.emit(this.options.event + direction, input); - } - - this.manager.emit(this.options.event, input); - } -}); - -/** - * - * Created by arjun on 20/05/16. - */ - -/** - * simple function bind - * @param {Function} fn - * @param {Object} context - * @returns {Function} - */ -function bindFn(fn, context) { - return function boundFn() { - return fn.apply(context, arguments); - }; -} - -/** - * set a timeout with a given scope - * @param {Function} fn - * @param {Number} timeout - * @param {Object} context - * @returns {number} - */ -function setTimeoutContext(fn, timeout, context) { - return setTimeout(bindFn(fn, context), timeout); -} - -/** - * calculate the absolute distance between two points - * @param {Object} p1 {x, y} - * @param {Object} p2 {x, y} - * @param {Array} [props] containing x and y keys - * @return {Number} distance - */ -function getDistance(p1, p2, props) { - if (!props) { - props = PROPS_XY; - } - var x = p2[props[0]] - p1[props[0]], - y = p2[props[1]] - p1[props[1]]; - - return Math.sqrt(x * x + y * y); -} - -/** - * A tap is ecognized when the pointer is doing a small tap/click. Multiple taps are recognized if they occur - * between the given interval and position. The delay option can be used to recognize multi-taps without firing - * a single tap. - * - * The eventData from the emitted event contains the property `tapCount`, which contains the amount of - * multi-taps being recognized. - * @constructor - * @extends Recognizer - */ -function TapRecognizer() { - Recognizer.apply(this, arguments); - - // previous time and center, - // used for tap counting - this.pTime = false; - this.pCenter = false; - - this._timer = null; - this._input = null; - this.count = 0; -} - -inherit(TapRecognizer, Recognizer, { - /** - * @namespace - * @memberof PinchRecognizer - */ - defaults: { - event: 'tap', - pointers: 1, - taps: 1, - interval: 300, // max time between the multi-tap taps - time: 250, // max time of the pointer to be down (like finger on the screen) - threshold: 9, // a minimal movement is ok, but keep it low - posThreshold: 10 // a multi-tap can be a bit off the initial position - }, - - getTouchAction: function getTouchAction() { - return [TOUCH_ACTION_MANIPULATION]; - }, - - process: function process(input) { - var options = this.options; - - var validPointers = input.pointers.length === options.pointers; - var validMovement = input.distance < options.threshold; - var validTouchTime = input.deltaTime < options.time; - - this.reset(); - - if (input.eventType & INPUT_START && this.count === 0) { - return this.failTimeout(); - } - - // we only allow little movement - // and we've reached an end event, so a tap is possible - if (validMovement && validTouchTime && validPointers) { - if (input.eventType != INPUT_END) { - return this.failTimeout(); - } - - var validInterval = this.pTime ? input.timeStamp - this.pTime < options.interval : true; - var validMultiTap = !this.pCenter || getDistance(this.pCenter, input.center) < options.posThreshold; - - this.pTime = input.timeStamp; - this.pCenter = input.center; - - if (!validMultiTap || !validInterval) { - this.count = 1; - } else { - this.count += 1; - } - - this._input = input; - - // if tap count matches we have recognized it, - // else it has began recognizing... - var tapCount = this.count % options.taps; - if (tapCount === 0) { - // no failing requirements, immediately trigger the tap event - // or wait as long as the multitap interval to trigger - if (!this.hasRequireFailures()) { - return STATE_RECOGNIZED; - } else { - this._timer = setTimeoutContext(function () { - this.state = STATE_RECOGNIZED; - this.tryEmit(); - }, options.interval, this); - return STATE_BEGAN; - } - } - } - return STATE_FAILED; - }, - - failTimeout: function failTimeout() { - this._timer = setTimeoutContext(function () { - this.state = STATE_FAILED; - }, this.options.interval, this); - return STATE_FAILED; - }, - - reset: function reset() { - clearTimeout(this._timer); - }, - - emit: function emit() { - if (this.state == STATE_RECOGNIZED) { - this._input.tapCount = this.count; - this.manager.emit(this.options.event, this._input); - } - } -}); - -/** - * Press - * Recognized when the pointer is down for x ms without any movement. - * @constructor - * @extends Recognizer - */ -function PressRecognizer() { - Recognizer.apply(this, arguments); - - this._timer = null; - this._input = null; -} - -inherit(PressRecognizer, Recognizer, { - /** - * @namespace - * @memberof PressRecognizer - */ - defaults: { - event: 'press', - pointers: 1, - time: 251, // minimal time of the pointer to be pressed - threshold: 9 // a minimal movement is ok, but keep it low - }, - - getTouchAction: function getTouchAction() { - return [TOUCH_ACTION_AUTO]; - }, - - process: function process(input) { - var options = this.options; - var validPointers = input.pointers.length === options.pointers; - var validMovement = input.distance < options.threshold; - var validTime = input.deltaTime > options.time; - - this._input = input; - - // we only allow little movement - // and we've reached an end event, so a tap is possible - if (!validMovement || !validPointers || input.eventType & (INPUT_END | INPUT_CANCEL) && !validTime) { - this.reset(); - } else if (input.eventType & INPUT_START) { - this.reset(); - this._timer = setTimeoutContext(function () { - this.state = STATE_RECOGNIZED; - this.tryEmit(); - }, options.time, this); - } else if (input.eventType & INPUT_END) { - return STATE_RECOGNIZED; - } - return STATE_FAILED; - }, - - reset: function reset() { - clearTimeout(this._timer); - }, - - emit: function emit(input) { - if (this.state !== STATE_RECOGNIZED) { - return; - } - - if (input && input.eventType & INPUT_END) { - this.manager.emit(this.options.event + 'up', input); - } else { - this._input.timeStamp = now(); - this.manager.emit(this.options.event, this._input); - } - } -}); - -/** - * Created by arjun on 20/05/16. - */ - -/** - * small indexOf wrapper - * @param {String} str - * @param {String} find - * @returns {Boolean} found - */ -function inStr(str, find) { - return str.indexOf(find) > -1; -} - -/** - * when the touchActions are collected they are not a valid value, so we need to clean things up. * - * @param {String} actions - * @returns {*} - */ -function cleanTouchActions(actions) { - // none - if (inStr(actions, TOUCH_ACTION_NONE)) { - return TOUCH_ACTION_NONE; - } - - var hasPanX = inStr(actions, TOUCH_ACTION_PAN_X); - var hasPanY = inStr(actions, TOUCH_ACTION_PAN_Y); - - // if both pan-x and pan-y are set (different recognizers - // for different directions, e.g. horizontal pan but vertical swipe?) - // we need none (as otherwise with pan-x pan-y combined none of these - // recognizers will work, since the browser would handle all panning - if (hasPanX && hasPanY) { - return TOUCH_ACTION_NONE; - } - - // pan-x OR pan-y - if (hasPanX || hasPanY) { - return hasPanX ? TOUCH_ACTION_PAN_X : TOUCH_ACTION_PAN_Y; - } - - // manipulation - if (inStr(actions, TOUCH_ACTION_MANIPULATION)) { - return TOUCH_ACTION_MANIPULATION; - } - - return TOUCH_ACTION_AUTO; -} - -/** - * Touch Action - * sets the touchAction property or uses the js alternative - * @param {Manager} manager - * @param {String} value - * @constructor - */ -function TouchAction(manager, value) { - this.manager = manager; - this.set(value); -} - -TouchAction.prototype = { - /** - * set the touchAction value on the element or enable the polyfill - * @param {String} value - */ - set: function set(value) { - // find out the touch-action by the event handlers - if (value == TOUCH_ACTION_COMPUTE) { - value = this.compute(); - } - - if (NATIVE_TOUCH_ACTION && this.manager.element.style && TOUCH_ACTION_MAP[value]) { - this.manager.element.style[PREFIXED_TOUCH_ACTION] = value; - } - this.actions = value.toLowerCase().trim(); - }, - - /** - * just re-set the touchAction value - */ - update: function update() { - this.set(this.manager.options.touchAction); - }, - - /** - * compute the value for the touchAction property based on the recognizer's settings - * @returns {String} value - */ - compute: function compute() { - var actions = []; - each(this.manager.recognizers, function (recognizer) { - if (boolOrFn(recognizer.options.enable, [recognizer])) { - actions = actions.concat(recognizer.getTouchAction()); - } - }); - return cleanTouchActions(actions.join(' ')); - }, - - /** - * this method is called on each input cycle and provides the preventing of the browser behavior - * @param {Object} input - */ - preventDefaults: function preventDefaults(input) { - var srcEvent = input.srcEvent; - var direction = input.offsetDirection; - - // if the touch action did prevented once this session - if (this.manager.session.prevented) { - srcEvent.preventDefault(); - return; - } - - var actions = this.actions; - var hasNone = inStr(actions, TOUCH_ACTION_NONE) && !TOUCH_ACTION_MAP[TOUCH_ACTION_NONE]; - var hasPanY = inStr(actions, TOUCH_ACTION_PAN_Y) && !TOUCH_ACTION_MAP[TOUCH_ACTION_PAN_Y]; - var hasPanX = inStr(actions, TOUCH_ACTION_PAN_X) && !TOUCH_ACTION_MAP[TOUCH_ACTION_PAN_X]; - - if (hasNone) { - //do not prevent defaults if this is a tap gesture - - var isTapPointer = input.pointers.length === 1; - var isTapMovement = input.distance < 2; - var isTapTouchTime = input.deltaTime < 250; - - if (isTapPointer && isTapMovement && isTapTouchTime) { - return; - } - } - - if (hasPanX && hasPanY) { - // `pan-x pan-y` means browser handles all scrolling/panning, do not prevent - return; - } - - if (hasNone || hasPanY && direction & DIRECTION_HORIZONTAL || hasPanX && direction & DIRECTION_VERTICAL) { - return this.preventSrc(srcEvent); - } - }, - - /** - * call preventDefault to prevent the browser's default behavior (scrolling in most cases) - * @param {Object} srcEvent - */ - preventSrc: function preventSrc(srcEvent) { - this.manager.session.prevented = true; - srcEvent.preventDefault(); - } -}; - -/** - * Created by arjun on 20/05/16. - */ - -/** - * find if a node is in the given parent - * @method hasParent - * @param {HTMLElement} node - * @param {HTMLElement} parent - * @return {Boolean} found - */ -function hasParent(node, parent) { - while (node) { - if (node == parent) { - return true; - } - node = node.parentNode; - } - return false; -} - -/** - * get the center of all the pointers - * @param {Array} pointers - * @return {Object} center contains `x` and `y` properties - */ -function getCenter(pointers) { - var pointersLength = pointers.length; - - // no need to loop when only one touch - if (pointersLength === 1) { - return { - x: round(pointers[0].clientX), - y: round(pointers[0].clientY) - }; - } - - var x = 0, - y = 0, - i = 0; - while (i < pointersLength) { - x += pointers[i].clientX; - y += pointers[i].clientY; - i++; - } - - return { - x: round(x / pointersLength), - y: round(y / pointersLength) - }; -} - -/** - * create a simple clone from the input used for storage of firstInput and firstMultiple - * @param {Object} input - * @returns {Object} clonedInputData - */ -function simpleCloneInputData(input) { - // make a simple copy of the pointers because we will get a reference if we don't - // we only need clientXY for the calculations - var pointers = []; - var i = 0; - while (i < input.pointers.length) { - pointers[i] = { - clientX: round(input.pointers[i].clientX), - clientY: round(input.pointers[i].clientY) - }; - i++; - } - - return { - timeStamp: now(), - pointers: pointers, - center: getCenter(pointers), - deltaX: input.deltaX, - deltaY: input.deltaY - }; -} - -/** - * calculate the angle between two coordinates - * @param {Object} p1 - * @param {Object} p2 - * @param {Array} [props] containing x and y keys - * @return {Number} angle - */ -function getAngle(p1, p2, props) { - if (!props) { - props = PROPS_XY; - } - var x = p2[props[0]] - p1[props[0]], - y = p2[props[1]] - p1[props[1]]; - return Math.atan2(y, x) * 180 / Math.PI; -} - -/** - * get the direction between two points - * @param {Number} x - * @param {Number} y - * @return {Number} direction - */ -function getDirection(x, y) { - if (x === y) { - return DIRECTION_NONE; - } - - if (abs(x) >= abs(y)) { - return x < 0 ? DIRECTION_LEFT : DIRECTION_RIGHT; - } - return y < 0 ? DIRECTION_UP : DIRECTION_DOWN; -} - -function computeDeltaXY(session, input) { - var center = input.center; - var offset = session.offsetDelta || {}; - var prevDelta = session.prevDelta || {}; - var prevInput = session.prevInput || {}; - - if (input.eventType === INPUT_START || prevInput.eventType === INPUT_END) { - prevDelta = session.prevDelta = { - x: prevInput.deltaX || 0, - y: prevInput.deltaY || 0 - }; - - offset = session.offsetDelta = { - x: center.x, - y: center.y - }; - } - - input.deltaX = prevDelta.x + (center.x - offset.x); - input.deltaY = prevDelta.y + (center.y - offset.y); -} - -/** - * Created by arjun on 20/05/16. - */ - -/** - * calculate the velocity between two points. unit is in px per ms. - * @param {Number} deltaTime - * @param {Number} x - * @param {Number} y - * @return {Object} velocity `x` and `y` - */ -function getVelocity(deltaTime, x, y) { - return { - x: x / deltaTime || 0, - y: y / deltaTime || 0 - }; -} - -/** - * calculate the scale factor between two pointersets - * no scale is 1, and goes down to 0 when pinched together, and bigger when pinched out - * @param {Array} start array of pointers - * @param {Array} end array of pointers - * @return {Number} scale - */ -function getScale(start, end) { - return getDistance(end[0], end[1], PROPS_CLIENT_XY) / getDistance(start[0], start[1], PROPS_CLIENT_XY); -} - -/** - * calculate the rotation degrees between two pointersets - * @param {Array} start array of pointers - * @param {Array} end array of pointers - * @return {Number} rotation - */ -function getRotation(start, end) { - return getAngle(end[1], end[0], PROPS_CLIENT_XY) + getAngle(start[1], start[0], PROPS_CLIENT_XY); -} - -/** - * velocity is calculated every x ms - * @param {Object} session - * @param {Object} input - */ -function computeIntervalInputData(session, input) { - var last = session.lastInterval || input, - deltaTime = input.timeStamp - last.timeStamp, - velocity, - velocityX, - velocityY, - direction; - - if (input.eventType != INPUT_CANCEL && (deltaTime > COMPUTE_INTERVAL || last.velocity === undefined)) { - var deltaX = input.deltaX - last.deltaX; - var deltaY = input.deltaY - last.deltaY; - - var v = getVelocity(deltaTime, deltaX, deltaY); - velocityX = v.x; - velocityY = v.y; - velocity = abs(v.x) > abs(v.y) ? v.x : v.y; - direction = getDirection(deltaX, deltaY); - - session.lastInterval = input; - } else { - // use latest velocity info if it doesn't overtake a minimum period - velocity = last.velocity; - velocityX = last.velocityX; - velocityY = last.velocityY; - direction = last.direction; - } - - input.velocity = velocity; - input.velocityX = velocityX; - input.velocityY = velocityY; - input.direction = direction; -} - -/** - * extend the data with some usable properties like scale, rotate, velocity etc - * @param {Object} manager - * @param {Object} input - */ -function computeInputData(manager, input) { - var session = manager.session; - var pointers = input.pointers; - var pointersLength = pointers.length; - - // store the first input to calculate the distance and direction - if (!session.firstInput) { - session.firstInput = simpleCloneInputData(input); - } - - // to compute scale and rotation we need to store the multiple touches - if (pointersLength > 1 && !session.firstMultiple) { - session.firstMultiple = simpleCloneInputData(input); - } else if (pointersLength === 1) { - session.firstMultiple = false; - } - - var firstInput = session.firstInput; - var firstMultiple = session.firstMultiple; - var offsetCenter = firstMultiple ? firstMultiple.center : firstInput.center; - - var center = input.center = getCenter(pointers); - input.timeStamp = now(); - input.deltaTime = input.timeStamp - firstInput.timeStamp; - - input.angle = getAngle(offsetCenter, center); - input.distance = getDistance(offsetCenter, center); - - computeDeltaXY(session, input); - input.offsetDirection = getDirection(input.deltaX, input.deltaY); - - var overallVelocity = getVelocity(input.deltaTime, input.deltaX, input.deltaY); - input.overallVelocityX = overallVelocity.x; - input.overallVelocityY = overallVelocity.y; - input.overallVelocity = abs(overallVelocity.x) > abs(overallVelocity.y) ? overallVelocity.x : overallVelocity.y; - - input.scale = firstMultiple ? getScale(firstMultiple.pointers, pointers) : 1; - input.rotation = firstMultiple ? getRotation(firstMultiple.pointers, pointers) : 0; - - input.maxPointers = !session.prevInput ? input.pointers.length : input.pointers.length > session.prevInput.maxPointers ? input.pointers.length : session.prevInput.maxPointers; - - computeIntervalInputData(session, input); - - // find the correct target - var target = manager.element; - if (hasParent(input.srcEvent.target, target)) { - target = input.srcEvent.target; - } - input.target = target; -} - -/** - * handle input events - * @param {Manager} manager - * @param {String} eventType - * @param {Object} input - */ -function inputHandler(manager, eventType, input) { - var pointersLen = input.pointers.length; - var changedPointersLen = input.changedPointers.length; - var isFirst = eventType & INPUT_START && pointersLen - changedPointersLen === 0; - var isFinal = eventType & (INPUT_END | INPUT_CANCEL) && pointersLen - changedPointersLen === 0; - - input.isFirst = !!isFirst; - input.isFinal = !!isFinal; - - if (isFirst) { - manager.session = {}; - } - - // source event is the normalized value of the domEvents - // like 'touchstart, mouseup, pointerdown' - input.eventType = eventType; - - // compute scale, rotation etc - computeInputData(manager, input); - - // emit secret event - manager.emit('hammer.input', input); - - manager.recognize(input); - manager.session.prevInput = input; -} - -/** - * Created by arjun on 20/05/16. - */ - -/** - * split string on whitespace - * @param {String} str - * @returns {Array} words - */ -function splitStr(str) { - return str.trim().split(/\s+/g); -} - -/** - * addEventListener with multiple events at once - * @param {EventTarget} target - * @param {String} types - * @param {Function} handler - */ -function addEventListeners(target, types, handler) { - each(splitStr(types), function (type) { - target.addEventListener(type, handler, false); - }); -} - -/** - * removeEventListener with multiple events at once - * @param {EventTarget} target - * @param {String} types - * @param {Function} handler - */ -function removeEventListeners(target, types, handler) { - each(splitStr(types), function (type) { - target.removeEventListener(type, handler, false); - }); -} - -/** - * get the window object of an element - * @param {HTMLElement} element - * @returns {DocumentView|Window} - */ -function getWindowForElement(element) { - var doc = element.ownerDocument || element; - return doc.defaultView || doc.parentWindow || window; -} - -/** - * create new input type manager - * @param {Manager} manager - * @param {Function} callback - * @returns {Input} - * @constructor - */ -function Input(manager, callback) { - var self = this; - this.manager = manager; - this.callback = callback; - this.element = manager.element; - this.target = manager.options.inputTarget; - - // smaller wrapper around the handler, for the scope and the enabled state of the manager, - // so when disabled the input events are completely bypassed. - this.domHandler = function (ev) { - if (boolOrFn(manager.options.enable, [manager])) { - self.handler(ev); - } - }; - - this.init(); -} - -Input.prototype = { - /** - * should handle the inputEvent data and trigger the callback - * @virtual - */ - handler: function handler() {}, - - /** - * bind the events - */ - init: function init() { - this.evEl && addEventListeners(this.element, this.evEl, this.domHandler); - this.evTarget && addEventListeners(this.target, this.evTarget, this.domHandler); - this.evWin && addEventListeners(getWindowForElement(this.element), this.evWin, this.domHandler); - }, - - /** - * unbind the events - */ - destroy: function destroy() { - this.evEl && removeEventListeners(this.element, this.evEl, this.domHandler); - this.evTarget && removeEventListeners(this.target, this.evTarget, this.domHandler); - this.evWin && removeEventListeners(getWindowForElement(this.element), this.evWin, this.domHandler); - } -}; - -var POINTER_INPUT_MAP = { - pointerdown: INPUT_START, - pointermove: INPUT_MOVE, - pointerup: INPUT_END, - pointercancel: INPUT_CANCEL, - pointerout: INPUT_CANCEL -}; - -// in IE10 the pointer types is defined as an enum -var IE10_POINTER_TYPE_ENUM = { - 2: INPUT_TYPE_TOUCH, - 3: INPUT_TYPE_PEN, - 4: INPUT_TYPE_MOUSE, - 5: INPUT_TYPE_KINECT // see https://twitter.com/jacobrossi/status/480596438489890816 -}; - -var POINTER_ELEMENT_EVENTS = 'pointerdown'; -var POINTER_WINDOW_EVENTS = 'pointermove pointerup pointercancel'; - -// IE10 has prefixed support, and case-sensitive -if (window.MSPointerEvent && !window.PointerEvent) { - POINTER_ELEMENT_EVENTS = 'MSPointerDown'; - POINTER_WINDOW_EVENTS = 'MSPointerMove MSPointerUp MSPointerCancel'; -} - -/** - * Pointer events input - * @constructor - * @extends Input - */ -function PointerEventInput() { - this.evEl = POINTER_ELEMENT_EVENTS; - this.evWin = POINTER_WINDOW_EVENTS; - - Input.apply(this, arguments); - - this.store = this.manager.session.pointerEvents = []; -} - -inherit(PointerEventInput, Input, { - /** - * handle mouse events - * @param {Object} ev - */ - handler: function PEhandler(ev) { - var store = this.store; - var removePointer = false; - - var eventTypeNormalized = ev.type.toLowerCase().replace('ms', ''); - var eventType = POINTER_INPUT_MAP[eventTypeNormalized]; - var pointerType = IE10_POINTER_TYPE_ENUM[ev.pointerType] || ev.pointerType; - - var isTouch = pointerType == INPUT_TYPE_TOUCH; - - // get index of the event in the store - var storeIndex = inArray(store, ev.pointerId, 'pointerId'); - - // start and mouse must be down - if (eventType & INPUT_START && (ev.button === 0 || isTouch)) { - if (storeIndex < 0) { - store.push(ev); - storeIndex = store.length - 1; - } - } else if (eventType & (INPUT_END | INPUT_CANCEL)) { - removePointer = true; - } - - // it not found, so the pointer hasn't been down (so it's probably a hover) - if (storeIndex < 0) { - return; - } - - // update the event in the store - store[storeIndex] = ev; - - this.callback(this.manager, eventType, { - pointers: store, - changedPointers: [ev], - pointerType: pointerType, - srcEvent: ev - }); - - if (removePointer) { - // remove from the store - store.splice(storeIndex, 1); - } - } -}); - -/** - * Created by arjun on 20/05/16. - */ - -/** - * convert array-like objects to real arrays - * @param {Object} obj - * @returns {Array} - */ -function toArray(obj) { - return Array.prototype.slice.call(obj, 0); -} - -/** - * unique array with objects based on a key (like 'id') or just by the array's value - * @param {Array} src [{id:1},{id:2},{id:1}] - * @param {String} [key] - * @param {Boolean} [sort=False] - * @returns {Array} [{id:1},{id:2}] - */ -function uniqueArray(src, key, sort) { - var results = []; - var values = []; - var i = 0; - - while (i < src.length) { - var val = key ? src[i][key] : src[i]; - if (inArray(values, val) < 0) { - results.push(src[i]); - } - values[i] = val; - i++; - } - - if (sort) { - if (!key) { - results = results.sort(); - } else { - results = results.sort(function sortUniqueArray(a, b) { - return a[key] > b[key]; - }); - } - } - - return results; -} - -var TOUCH_INPUT_MAP = { - touchstart: INPUT_START, - touchmove: INPUT_MOVE, - touchend: INPUT_END, - touchcancel: INPUT_CANCEL -}; - -var TOUCH_TARGET_EVENTS = 'touchstart touchmove touchend touchcancel'; - -/** - * Multi-user touch events input - * @constructor - * @extends Input - */ -function TouchInput() { - this.evTarget = TOUCH_TARGET_EVENTS; - this.targetIds = {}; - - Input.apply(this, arguments); -} - -inherit(TouchInput, Input, { - handler: function MTEhandler(ev) { - var type = TOUCH_INPUT_MAP[ev.type]; - var touches = getTouches.call(this, ev, type); - if (!touches) { - return; - } - - this.callback(this.manager, type, { - pointers: touches[0], - changedPointers: touches[1], - pointerType: INPUT_TYPE_TOUCH, - srcEvent: ev - }); - } -}); - -/** - * @this {TouchInput} - * @param {Object} ev - * @param {Number} type flag - * @returns {undefined|Array} [all, changed] - */ -function getTouches(ev, type) { - var allTouches = toArray(ev.touches); - var targetIds = this.targetIds; - - // when there is only one touch, the process can be simplified - if (type & (INPUT_START | INPUT_MOVE) && allTouches.length === 1) { - targetIds[allTouches[0].identifier] = true; - return [allTouches, allTouches]; - } - - var i, - targetTouches, - changedTouches = toArray(ev.changedTouches), - changedTargetTouches = [], - target = this.target; - - // get target touches from touches - targetTouches = allTouches.filter(function (touch) { - return hasParent(touch.target, target); - }); - - // collect touches - if (type === INPUT_START) { - i = 0; - while (i < targetTouches.length) { - targetIds[targetTouches[i].identifier] = true; - i++; - } - } - - // filter changed touches to only contain touches that exist in the collected target ids - i = 0; - while (i < changedTouches.length) { - if (targetIds[changedTouches[i].identifier]) { - changedTargetTouches.push(changedTouches[i]); - } - - // cleanup removed touches - if (type & (INPUT_END | INPUT_CANCEL)) { - delete targetIds[changedTouches[i].identifier]; - } - i++; - } - - if (!changedTargetTouches.length) { - return; - } - - return [ - // merge targetTouches with changedTargetTouches so it contains ALL touches, including 'end' and 'cancel' - uniqueArray(targetTouches.concat(changedTargetTouches), 'identifier', true), changedTargetTouches]; -} - -var MOUSE_INPUT_MAP = { - mousedown: INPUT_START, - mousemove: INPUT_MOVE, - mouseup: INPUT_END -}; - -var MOUSE_ELEMENT_EVENTS = 'mousedown'; -var MOUSE_WINDOW_EVENTS = 'mousemove mouseup'; - -/** - * Mouse events input - * @constructor - * @extends Input - */ -function MouseInput() { - this.evEl = MOUSE_ELEMENT_EVENTS; - this.evWin = MOUSE_WINDOW_EVENTS; - - this.pressed = false; // mousedown state - - Input.apply(this, arguments); -} - -inherit(MouseInput, Input, { - /** - * handle mouse events - * @param {Object} ev - */ - handler: function MEhandler(ev) { - var eventType = MOUSE_INPUT_MAP[ev.type]; - - // on start we want to have the left mouse button down - if (eventType & INPUT_START && ev.button === 0) { - this.pressed = true; - } - - if (eventType & INPUT_MOVE && ev.which !== 1) { - eventType = INPUT_END; - } - - // mouse must be down - if (!this.pressed) { - return; - } - - if (eventType & INPUT_END) { - this.pressed = false; - } - - this.callback(this.manager, eventType, { - pointers: [ev], - changedPointers: [ev], - pointerType: INPUT_TYPE_MOUSE, - srcEvent: ev - }); - } -}); - -/** - * Combined touch and mouse input - * - * Touch has a higher priority then mouse, and while touching no mouse events are allowed. - * This because touch devices also emit mouse events while doing a touch. - * - * @constructor - * @extends Input - */ - -var DEDUP_TIMEOUT = 2500; -var DEDUP_DISTANCE = 25; - -function TouchMouseInput() { - Input.apply(this, arguments); - - var handler = bindFn(this.handler, this); - this.touch = new TouchInput(this.manager, handler); - this.mouse = new MouseInput(this.manager, handler); - - this.primaryTouch = null; - this.lastTouches = []; -} - -inherit(TouchMouseInput, Input, { - /** - * handle mouse and touch events - * @param {Hammer} manager - * @param {String} inputEvent - * @param {Object} inputData - */ - handler: function TMEhandler(manager, inputEvent, inputData) { - var isTouch = inputData.pointerType == INPUT_TYPE_TOUCH, - isMouse = inputData.pointerType == INPUT_TYPE_MOUSE; - - if (isMouse && inputData.sourceCapabilities && inputData.sourceCapabilities.firesTouchEvents) { - return; - } - - // when we're in a touch event, record touches to de-dupe synthetic mouse event - if (isTouch) { - recordTouches.call(this, inputEvent, inputData); - } else if (isMouse && isSyntheticEvent.call(this, inputData)) { - return; - } - - this.callback(manager, inputEvent, inputData); - }, - - /** - * remove the event listeners - */ - destroy: function destroy() { - this.touch.destroy(); - this.mouse.destroy(); - } -}); - -function recordTouches(eventType, eventData) { - if (eventType & INPUT_START) { - this.primaryTouch = eventData.changedPointers[0].identifier; - setLastTouch.call(this, eventData); - } else if (eventType & (INPUT_END | INPUT_CANCEL)) { - setLastTouch.call(this, eventData); - } -} - -function setLastTouch(eventData) { - var touch = eventData.changedPointers[0]; - - if (touch.identifier === this.primaryTouch) { - var lastTouch = { x: touch.clientX, y: touch.clientY }; - this.lastTouches.push(lastTouch); - var lts = this.lastTouches; - var removeLastTouch = function removeLastTouch() { - var i = lts.indexOf(lastTouch); - if (i > -1) { - lts.splice(i, 1); - } - }; - setTimeout(removeLastTouch, DEDUP_TIMEOUT); - } -} - -function isSyntheticEvent(eventData) { - var x = eventData.srcEvent.clientX, - y = eventData.srcEvent.clientY; - for (var i = 0; i < this.lastTouches.length; i++) { - var t = this.lastTouches[i]; - var dx = Math.abs(x - t.x), - dy = Math.abs(y - t.y); - if (dx <= DEDUP_DISTANCE && dy <= DEDUP_DISTANCE) { - return true; - } - } - return false; -} - -/** - * create new input type manager - * called by the Manager constructor - * @param {Hammer} manager - * @returns {Input} - */ -function createInputInstance(manager) { - var Type; - var inputClass = manager.options.inputClass; - - if (inputClass) { - Type = inputClass; - } else if (SUPPORT_POINTER_EVENTS) { - Type = PointerEventInput; - } else if (SUPPORT_ONLY_TOUCH) { - Type = TouchInput; - } else if (!SUPPORT_TOUCH) { - Type = MouseInput; - } else { - Type = TouchMouseInput; - } - return new Type(manager, inputHandler); -} - -var STOP = 1; -var FORCED_STOP = 2; - -/** - * Manager - * @param {HTMLElement} element - * @param {Object} [options] - * @constructor - */ -function Manager(element, options) { - this.options = assign({}, Hammer.defaults, options || {}); - - this.options.inputTarget = this.options.inputTarget || element; - - this.handlers = {}; - this.session = {}; - this.recognizers = []; - this.oldCssProps = {}; - - this.element = element; - this.input = createInputInstance(this); - this.touchAction = new TouchAction(this, this.options.touchAction); - - toggleCssProps(this, true); - - each(this.options.recognizers, function (item) { - var recognizer = this.add(new item[0](item[1])); - item[2] && recognizer.recognizeWith(item[2]); - item[3] && recognizer.requireFailure(item[3]); - }, this); -} - -Manager.prototype = { - /** - * set options - * @param {Object} options - * @returns {Manager} - */ - set: function set(options) { - assign(this.options, options); - - // Options that need a little more setup - if (options.touchAction) { - this.touchAction.update(); - } - if (options.inputTarget) { - // Clean up existing event listeners and reinitialize - this.input.destroy(); - this.input.target = options.inputTarget; - this.input.init(); - } - return this; - }, - - /** - * stop recognizing for this session. - * This session will be discarded, when a new [input]start event is fired. - * When forced, the recognizer cycle is stopped immediately. - * @param {Boolean} [force] - */ - stop: function stop(force) { - this.session.stopped = force ? FORCED_STOP : STOP; - }, - - /** - * run the recognizers! - * called by the inputHandler function on every movement of the pointers (touches) - * it walks through all the recognizers and tries to detect the gesture that is being made - * @param {Object} inputData - */ - recognize: function recognize(inputData) { - var session = this.session; - if (session.stopped) { - return; - } - - // run the touch-action polyfill - this.touchAction.preventDefaults(inputData); - - var recognizer; - var recognizers = this.recognizers; - - // this holds the recognizer that is being recognized. - // so the recognizer's state needs to be BEGAN, CHANGED, ENDED or RECOGNIZED - // if no recognizer is detecting a thing, it is set to `null` - var curRecognizer = session.curRecognizer; - - // reset when the last recognizer is recognized - // or when we're in a new session - if (!curRecognizer || curRecognizer && curRecognizer.state & STATE_RECOGNIZED) { - curRecognizer = session.curRecognizer = null; - } - - var i = 0; - while (i < recognizers.length) { - recognizer = recognizers[i]; - - // find out if we are allowed try to recognize the input for this one. - // 1. allow if the session is NOT forced stopped (see the .stop() method) - // 2. allow if we still haven't recognized a gesture in this session, or the this recognizer is the one - // that is being recognized. - // 3. allow if the recognizer is allowed to run simultaneous with the current recognized recognizer. - // this can be setup with the `recognizeWith()` method on the recognizer. - if (session.stopped !== FORCED_STOP && ( // 1 - !curRecognizer || recognizer == curRecognizer || // 2 - recognizer.canRecognizeWith(curRecognizer))) { - // 3 - recognizer.recognize(inputData); - } else { - recognizer.reset(); - } - - // if the recognizer has been recognizing the input as a valid gesture, we want to store this one as the - // current active recognizer. but only if we don't already have an active recognizer - if (!curRecognizer && recognizer.state & (STATE_BEGAN | STATE_CHANGED | STATE_ENDED)) { - curRecognizer = session.curRecognizer = recognizer; - } - i++; - } - }, - - /** - * get a recognizer by its event name. - * @param {Recognizer|String} recognizer - * @returns {Recognizer|Null} - */ - get: function get(recognizer) { - if (recognizer instanceof Recognizer) { - return recognizer; - } - - var recognizers = this.recognizers; - for (var i = 0; i < recognizers.length; i++) { - if (recognizers[i].options.event == recognizer) { - return recognizers[i]; - } - } - return null; - }, - - /** - * add a recognizer to the manager - * existing recognizers with the same event name will be removed - * @param {Recognizer} recognizer - * @returns {Recognizer|Manager} - */ - add: function add(recognizer) { - if (invokeArrayArg(recognizer, 'add', this)) { - return this; - } - - // remove existing - var existing = this.get(recognizer.options.event); - if (existing) { - this.remove(existing); - } - - this.recognizers.push(recognizer); - recognizer.manager = this; - - this.touchAction.update(); - return recognizer; - }, - - /** - * remove a recognizer by name or instance - * @param {Recognizer|String} recognizer - * @returns {Manager} - */ - remove: function remove(recognizer) { - if (invokeArrayArg(recognizer, 'remove', this)) { - return this; - } - - recognizer = this.get(recognizer); - - // let's make sure this recognizer exists - if (recognizer) { - var recognizers = this.recognizers; - var index = inArray(recognizers, recognizer); - - if (index !== -1) { - recognizers.splice(index, 1); - this.touchAction.update(); - } - } - - return this; - }, - - /** - * bind event - * @param {String} events - * @param {Function} handler - * @returns {EventEmitter} this - */ - on: function on(events, handler) { - if (events === undefined) { - return; - } - if (handler === undefined) { - return; - } - - var handlers = this.handlers; - each(splitStr(events), function (event) { - handlers[event] = handlers[event] || []; - handlers[event].push(handler); - }); - return this; - }, - - /** - * unbind event, leave emit blank to remove all handlers - * @param {String} events - * @param {Function} [handler] - * @returns {EventEmitter} this - */ - off: function off(events, handler) { - if (events === undefined) { - return; - } - - var handlers = this.handlers; - each(splitStr(events), function (event) { - if (!handler) { - delete handlers[event]; - } else { - handlers[event] && handlers[event].splice(inArray(handlers[event], handler), 1); - } - }); - return this; - }, - - /** - * emit event to the listeners - * @param {String} event - * @param {Object} data - */ - emit: function emit(event, data) { - // we also want to trigger dom events - if (this.options.domEvents) { - triggerDomEvent(event, data); - } - - // no handlers, so skip it all - var handlers = this.handlers[event] && this.handlers[event].slice(); - if (!handlers || !handlers.length) { - return; - } - - data.type = event; - data.preventDefault = function () { - data.srcEvent.preventDefault(); - }; - - var i = 0; - while (i < handlers.length) { - handlers[i](data); - i++; - } - }, - - /** - * destroy the manager and unbinds all events - * it doesn't unbind dom events, that is the user own responsibility - */ - destroy: function destroy() { - this.element && toggleCssProps(this, false); - - this.handlers = {}; - this.session = {}; - this.input.destroy(); - this.element = null; - } -}; - -/** - * add/remove the css properties as defined in manager.options.cssProps - * @param {Manager} manager - * @param {Boolean} add - */ -function toggleCssProps(manager, add) { - var element = manager.element; - if (!element.style) { - return; - } - var prop; - each(manager.options.cssProps, function (value, name) { - prop = prefixed(element.style, name); - if (add) { - manager.oldCssProps[prop] = element.style[prop]; - element.style[prop] = value; - } else { - element.style[prop] = manager.oldCssProps[prop] || ''; - } - }); - if (!add) { - manager.oldCssProps = {}; - } -} - -/** - * trigger dom event - * @param {String} event - * @param {Object} data - */ -function triggerDomEvent(event, data) { - var gestureEvent = document.createEvent('Event'); - gestureEvent.initEvent(event, true, true); - gestureEvent.gesture = data; - data.target.dispatchEvent(gestureEvent); -} - -/** - * Simple way to create a manager with a default set of recognizers. - * @param {HTMLElement} element - * @param {Object} [options] - * @constructor - */ -function Hammer(element, options) { - options = options || {}; - options.recognizers = ifUndefined(options.recognizers, Hammer.defaults.preset); - return new Manager(element, options); -} - -/** - * @const {string} - */ -Hammer.VERSION = '{{PKG_VERSION}}'; - -/** - * default settings - * @namespace - */ -Hammer.defaults = { - /** - * set if DOM events are being triggered. - * But this is slower and unused by simple implementations, so disabled by default. - * @type {Boolean} - * @default false - */ - domEvents: false, - - /** - * The value for the touchAction property/fallback. - * When set to `compute` it will magically set the correct value based on the added recognizers. - * @type {String} - * @default compute - */ - touchAction: TOUCH_ACTION_COMPUTE, - - /** - * @type {Boolean} - * @default true - */ - enable: true, - - /** - * EXPERIMENTAL FEATURE -- can be removed/changed - * Change the parent input target element. - * If Null, then it is being set the to main element. - * @type {Null|EventTarget} - * @default null - */ - inputTarget: null, - - /** - * force an input class - * @type {Null|Function} - * @default null - */ - inputClass: null, - - /** - * Default recognizer setup when calling `Hammer()` - * When creating a new Manager these will be skipped. - * @type {Array} - */ - preset: [ - // RecognizerClass, options, [recognizeWith, ...], [requireFailure, ...] - [RotateRecognizer, { enable: false }], [PinchRecognizer, { enable: false }, ['rotate']], [SwipeRecognizer, { direction: DIRECTION_HORIZONTAL }], [PanRecognizer, { direction: DIRECTION_HORIZONTAL }, ['swipe']], [TapRecognizer], [TapRecognizer, { event: 'doubletap', taps: 2 }, ['tap']], [PressRecognizer]], - - /** - * Some CSS properties can be used to improve the working of Hammer. - * Add them to this method and they will be set when creating a new Manager. - * @namespace - */ - cssProps: { - /** - * Disables text selection to improve the dragging gesture. Mainly for desktop browsers. - * @type {String} - * @default 'none' - */ - userSelect: 'none', - - /** - * Disable the Windows Phone grippers when pressing an element. - * @type {String} - * @default 'none' - */ - touchSelect: 'none', - - /** - * Disables the default callout shown when you touch and hold a touch target. - * On iOS, when you touch and hold a touch target such as a link, Safari displays - * a callout containing information about the link. This property allows you to disable that callout. - * @type {String} - * @default 'none' - */ - touchCallout: 'none', - - /** - * Specifies whether zooming is enabled. Used by IE10> - * @type {String} - * @default 'none' - */ - contentZooming: 'none', - - /** - * Specifies that an entire element should be draggable instead of its contents. Mainly for desktop browsers. - * @type {String} - * @default 'none' - */ - userDrag: 'none', - - /** - * Overrides the highlight color shown when the user taps a link or a JavaScript - * clickable element in iOS. This property obeys the alpha value, if specified. - * @type {String} - * @default 'rgba(0,0,0,0)' - */ - tapHighlightColor: 'rgba(0,0,0,0)' - } -}; - -var SINGLE_TOUCH_INPUT_MAP = { - touchstart: INPUT_START, - touchmove: INPUT_MOVE, - touchend: INPUT_END, - touchcancel: INPUT_CANCEL -}; - -var SINGLE_TOUCH_TARGET_EVENTS = 'touchstart'; -var SINGLE_TOUCH_WINDOW_EVENTS = 'touchstart touchmove touchend touchcancel'; - -/** - * Touch events input - * @constructor - * @extends Input - */ -function SingleTouchInput() { - this.evTarget = SINGLE_TOUCH_TARGET_EVENTS; - this.evWin = SINGLE_TOUCH_WINDOW_EVENTS; - this.started = false; - - Input.apply(this, arguments); -} - -inherit(SingleTouchInput, Input, { - handler: function TEhandler(ev) { - var type = SINGLE_TOUCH_INPUT_MAP[ev.type]; - - // should we handle the touch events? - if (type === INPUT_START) { - this.started = true; - } - - if (!this.started) { - return; - } - - var touches = normalizeSingleTouches.call(this, ev, type); - - // when done, reset the started state - if (type & (INPUT_END | INPUT_CANCEL) && touches[0].length - touches[1].length === 0) { - this.started = false; - } - - this.callback(this.manager, type, { - pointers: touches[0], - changedPointers: touches[1], - pointerType: INPUT_TYPE_TOUCH, - srcEvent: ev - }); - } -}); - -/** - * @this {TouchInput} - * @param {Object} ev - * @param {Number} type flag - * @returns {undefined|Array} [all, changed] - */ -function normalizeSingleTouches(ev, type) { - var all = toArray(ev.touches); - var changed = toArray(ev.changedTouches); - - if (type & (INPUT_END | INPUT_CANCEL)) { - all = uniqueArray(all.concat(changed), 'identifier', true); - } - - return [all, changed]; -} - -/** - * Created by arjun on 19/05/16. - */ - -/** - * wrap a method with a deprecation warning and stack trace - * @param {Function} method - * @param {String} name - * @param {String} message - * @returns {Function} A new function wrapping the supplied method. - */ -function deprecate(method, name, message) { - var deprecationMessage = 'DEPRECATED METHOD: ' + name + '\n' + message + ' AT \n'; - return function () { - var e = new Error('get-stack-trace'); - var stack = e && e.stack ? e.stack.replace(/^[^\(]+?[\n$]/gm, '').replace(/^\s+at\s+/gm, '').replace(/^Object.\s*\(/gm, '{anonymous}()@') : 'Unknown Stack Trace'; - - var log = window.console && (window.console.warn || window.console.log); - if (log) { - log.call(window.console, deprecationMessage, stack); - } - return method.apply(this, arguments); - }; -} - -/** - * extend object. - * means that properties in dest will be overwritten by the ones in src. - * @param {Object} dest - * @param {Object} src - * @param {Boolean} [merge=false] - * @returns {Object} dest - */ -var extend = deprecate(function extend(dest, src, merge) { - var keys = Object.keys(src); - var i = 0; - while (i < keys.length) { - if (!merge || merge && dest[keys[i]] === undefined) { - dest[keys[i]] = src[keys[i]]; - } - i++; - } - return dest; -}, 'extend', 'Use `assign`.'); - -/** - * merge the values from src in the dest. - * means that properties that exist in dest will not be overwritten by src - * @param {Object} dest - * @param {Object} src - * @returns {Object} dest - */ -var merge = deprecate(function merge(dest, src) { - return extend(dest, src, true); -}, 'merge', 'Use `assign`.'); - -// this prevents errors when Hammer is loaded in the presence of an AMD -// style loader but by script tag, not by the loader. - -assign(Hammer, { - INPUT_START: INPUT_START, - INPUT_MOVE: INPUT_MOVE, - INPUT_END: INPUT_END, - INPUT_CANCEL: INPUT_CANCEL, - - STATE_POSSIBLE: STATE_POSSIBLE, - STATE_BEGAN: STATE_BEGAN, - STATE_CHANGED: STATE_CHANGED, - STATE_ENDED: STATE_ENDED, - STATE_RECOGNIZED: STATE_RECOGNIZED, - STATE_CANCELLED: STATE_CANCELLED, - STATE_FAILED: STATE_FAILED, - - DIRECTION_NONE: DIRECTION_NONE, - DIRECTION_LEFT: DIRECTION_LEFT, - DIRECTION_RIGHT: DIRECTION_RIGHT, - DIRECTION_UP: DIRECTION_UP, - DIRECTION_DOWN: DIRECTION_DOWN, - DIRECTION_HORIZONTAL: DIRECTION_HORIZONTAL, - DIRECTION_VERTICAL: DIRECTION_VERTICAL, - DIRECTION_ALL: DIRECTION_ALL, - - Manager: Manager, - Input: Input, - TouchAction: TouchAction, - - TouchInput: TouchInput, - MouseInput: MouseInput, - PointerEventInput: PointerEventInput, - TouchMouseInput: TouchMouseInput, - SingleTouchInput: SingleTouchInput, - - Recognizer: Recognizer, - AttrRecognizer: AttrRecognizer, - Tap: TapRecognizer, - Pan: PanRecognizer, - Swipe: SwipeRecognizer, - Pinch: PinchRecognizer, - Rotate: RotateRecognizer, - Press: PressRecognizer, - - on: addEventListeners, - off: removeEventListeners, - each: each, - merge: merge, - extend: extend, - assign: assign, - inherit: inherit, - bindFn: bindFn, - prefixed: prefixed -}); -if (typeof define === 'function' && define.amd) { - define(function () { - return Hammer; - }); -} else if (typeof module != 'undefined' && module.exports) { - module.exports = Hammer; -} else { - window[exportName] = Hammer; -} -})(window, document, 'Hammer'); \ No newline at end of file diff --git a/src/hammer.js b/src/hammer.js index 9c1fac9ad..41eeb70d4 100644 --- a/src/hammer.js +++ b/src/hammer.js @@ -1,4 +1,4 @@ -import {ifUndefined} from './utilsjs/ifUndefined'; +import ifUndefined from './utils/ifUndefined'; import {TOUCH_ACTION_COMPUTE} from './touchactionjs/touchactionConsts'; import {DIRECTION_HORIZONTAL} from './inputjs/inputConsts'; import {RotateRecognizer} from './recognizers/rotate'; diff --git a/src/input/mouse.js b/src/input/mouse.js index ed94bc820..053adfd98 100644 --- a/src/input/mouse.js +++ b/src/input/mouse.js @@ -1,6 +1,6 @@ import {INPUT_START,INPUT_MOVE,INPUT_END,INPUT_TYPE_MOUSE} from '../inputjs/inputConsts'; import {Input} from '../inputjs/inputConstructor'; -import {inherit} from '../utilsjs/inherit'; +import inherit from '../utils/inherit'; var MOUSE_INPUT_MAP = { mousedown: INPUT_START, diff --git a/src/input/pointerevent.js b/src/input/pointerevent.js index 478befeeb..ec0c64f0a 100644 --- a/src/input/pointerevent.js +++ b/src/input/pointerevent.js @@ -1,8 +1,8 @@ import {INPUT_START,INPUT_END,INPUT_CANCEL,INPUT_MOVE,INPUT_TYPE_TOUCH, INPUT_TYPE_MOUSE,INPUT_TYPE_PEN,INPUT_TYPE_KINECT} from '../inputjs/inputConsts'; import {Input} from '../inputjs/inputConstructor'; -import {inherit} from '../utilsjs/inherit'; -import {inArray} from '../utilsjs/inArray'; +import inherit from '../utils/inherit'; +import inArray from '../utils/inArray'; var POINTER_INPUT_MAP = { pointerdown: INPUT_START, diff --git a/src/input/singletouch.js b/src/input/singletouch.js index f295867b1..a9f1a0363 100644 --- a/src/input/singletouch.js +++ b/src/input/singletouch.js @@ -1,8 +1,8 @@ import {INPUT_START,INPUT_MOVE,INPUT_END,INPUT_CANCEL,INPUT_TYPE_TOUCH} from '../inputjs/inputConsts'; import {Input} from '../inputjs/inputConstructor'; -import {inherit} from '../utilsjs/inherit'; -import {toArray} from '../utilsjs/toArray'; -import {uniqueArray} from '../utilsjs/uniqueArray'; +import inherit from '../utils/inherit'; +import toArray from '../utils/toArray'; +import uniqueArray from '../utils/uniqueArray'; var SINGLE_TOUCH_INPUT_MAP = { touchstart: INPUT_START, diff --git a/src/input/touch.js b/src/input/touch.js index f933d52e1..e99335d25 100644 --- a/src/input/touch.js +++ b/src/input/touch.js @@ -1,9 +1,9 @@ import {INPUT_START,INPUT_MOVE,INPUT_END,INPUT_CANCEL,INPUT_TYPE_TOUCH} from '../inputjs/inputConsts'; import {Input} from '../inputjs/inputConstructor'; -import {inherit} from '../utilsjs/inherit'; -import {toArray} from '../utilsjs/toArray'; -import {hasParent} from '../utilsjs/hasParent'; -import {uniqueArray} from '../utilsjs/uniqueArray'; +import inherit from '../utils/inherit'; +import toArray from '../utils/toArray'; +import hasParent from '../utils/hasParent'; +import uniqueArray from '../utils/uniqueArray'; var TOUCH_INPUT_MAP = { touchstart: INPUT_START, diff --git a/src/input/touchmouse.js b/src/input/touchmouse.js index 1dcd3b207..d8dca7e54 100644 --- a/src/input/touchmouse.js +++ b/src/input/touchmouse.js @@ -1,6 +1,6 @@ import {Input} from '../inputjs/inputConstructor'; -import {inherit} from '../utilsjs/inherit'; -import {bindFn} from '../utilsjs/bindFn'; +import inherit from '../utils/inherit'; +import bindFn from '../utils/bindFn'; import {TouchInput} from './touch'; import {MouseInput} from './mouse'; import {INPUT_START,INPUT_END,INPUT_CANCEL,INPUT_TYPE_TOUCH,INPUT_TYPE_MOUSE} from '../inputjs/inputConsts'; diff --git a/src/inputjs/computeDeltaXY.js b/src/inputjs/computeDeltaXY.js index a1d4b8fc2..af3de4f0e 100644 --- a/src/inputjs/computeDeltaXY.js +++ b/src/inputjs/computeDeltaXY.js @@ -1,6 +1,6 @@ import {INPUT_START,INPUT_END} from './inputConsts'; -function computeDeltaXY(session, input) { +export default function computeDeltaXY(session, input) { var center = input.center; var offset = session.offsetDelta || {}; var prevDelta = session.prevDelta || {}; @@ -21,5 +21,3 @@ function computeDeltaXY(session, input) { input.deltaX = prevDelta.x + (center.x - offset.x); input.deltaY = prevDelta.y + (center.y - offset.y); } - -export {computeDeltaXY}; diff --git a/src/inputjs/computeInputData.js b/src/inputjs/computeInputData.js index 54b4fa99a..2daad704b 100644 --- a/src/inputjs/computeInputData.js +++ b/src/inputjs/computeInputData.js @@ -1,23 +1,23 @@ -import {now} from '../utilsjs/utilsConsts'; -import {abs} from '../utilsjs/utilsConsts'; -import {hasParent} from '../utilsjs/hasParent'; -import {simpleCloneInputData} from './simpleCloneInputData'; -import {getCenter} from './getCenter'; -import {getDistance} from './getDistance'; -import {getAngle} from './getAngle'; -import {getDirection} from './getDirection'; -import {computeDeltaXY} from './computeDeltaXY'; -import {getVelocity} from './getVelocity'; -import {getScale} from './getScale'; -import {getRotation} from './getRotation'; -import {computeIntervalInputData} from './computeIntervalInputData'; +import {now} from '../utils/utilsConsts'; +import {abs} from '../utils/utilsConsts'; +import hasParent from '../utils/hasParent'; +import simpleCloneInputData from './simpleCloneInputData'; +import getCenter from './getCenter'; +import getDistance from './getDistance'; +import getAngle from './getAngle'; +import getDirection from './getDirection'; +import computeDeltaXY from './computeDeltaXY'; +import getVelocity from './getVelocity'; +import getScale from './getScale'; +import getRotation from './getRotation'; +import computeIntervalInputData from './computeIntervalInputData'; /** * extend the data with some usable properties like scale, rotate, velocity etc * @param {Object} manager * @param {Object} input */ -function computeInputData(manager, input) { +export default function computeInputData(manager, input) { var session = manager.session; var pointers = input.pointers; var pointersLength = pointers.length; @@ -68,5 +68,3 @@ function computeInputData(manager, input) { } input.target = target; } - -export {computeInputData}; diff --git a/src/inputjs/computeIntervalInputData.js b/src/inputjs/computeIntervalInputData.js index f102f7258..30e9e1857 100644 --- a/src/inputjs/computeIntervalInputData.js +++ b/src/inputjs/computeIntervalInputData.js @@ -1,13 +1,14 @@ import {INPUT_CANCEL,COMPUTE_INTERVAL} from './inputConsts'; -import {abs} from '../utilsjs/utilsConsts'; -import {getVelocity} from './getVelocity'; -import {getDirection} from './getDirection'; +import {abs} from '../utils/utilsConsts'; +import getVelocity from './getVelocity'; +import getDirection from './getDirection'; + /** * velocity is calculated every x ms * @param {Object} session * @param {Object} input */ -function computeIntervalInputData(session, input) { +export default function computeIntervalInputData(session, input) { var last = session.lastInterval || input, deltaTime = input.timeStamp - last.timeStamp, velocity, velocityX, velocityY, direction; @@ -36,5 +37,3 @@ function computeIntervalInputData(session, input) { input.velocityY = velocityY; input.direction = direction; } - -export {computeIntervalInputData}; diff --git a/src/inputjs/createInputInstance.js b/src/inputjs/createInputInstance.js index d9872962e..e9d952770 100644 --- a/src/inputjs/createInputInstance.js +++ b/src/inputjs/createInputInstance.js @@ -1,5 +1,5 @@ import {SUPPORT_POINTER_EVENTS,SUPPORT_ONLY_TOUCH,SUPPORT_TOUCH} from './inputConsts'; -import {inputHandler} from './inputHandler'; +import inputHandler from './inputHandler'; import {PointerEventInput} from '../input/pointerevent'; import {TouchInput} from '../input/touch'; import {MouseInput} from '../input/mouse'; @@ -11,7 +11,7 @@ import {TouchMouseInput} from '../input/touchmouse'; * @param {Hammer} manager * @returns {Input} */ -function createInputInstance(manager) { +export default function createInputInstance(manager) { var Type; var inputClass = manager.options.inputClass; @@ -28,5 +28,3 @@ function createInputInstance(manager) { } return new (Type)(manager, inputHandler); } - -export {createInputInstance}; diff --git a/src/inputjs/getAngle.js b/src/inputjs/getAngle.js index 14ed31e71..3f2118bfb 100644 --- a/src/inputjs/getAngle.js +++ b/src/inputjs/getAngle.js @@ -7,7 +7,7 @@ import {PROPS_XY} from './inputConsts'; * @param {Array} [props] containing x and y keys * @return {Number} angle */ -function getAngle(p1, p2, props) { +export default function getAngle(p1, p2, props) { if (!props) { props = PROPS_XY; } @@ -15,5 +15,3 @@ function getAngle(p1, p2, props) { y = p2[props[1]] - p1[props[1]]; return Math.atan2(y, x) * 180 / Math.PI; } - -export {getAngle}; diff --git a/src/inputjs/getCenter.js b/src/inputjs/getCenter.js index 9fae4ef09..99b0662e7 100644 --- a/src/inputjs/getCenter.js +++ b/src/inputjs/getCenter.js @@ -1,11 +1,11 @@ -import {round} from '../utilsjs/utilsConsts'; +import {round} from '../utils/utilsConsts'; /** * get the center of all the pointers * @param {Array} pointers * @return {Object} center contains `x` and `y` properties */ -function getCenter(pointers) { +export default function getCenter(pointers) { var pointersLength = pointers.length; // no need to loop when only one touch @@ -28,5 +28,3 @@ function getCenter(pointers) { y: round(y / pointersLength) }; } - -export {getCenter}; diff --git a/src/inputjs/getDirection.js b/src/inputjs/getDirection.js index 8879445a4..55a0d513a 100644 --- a/src/inputjs/getDirection.js +++ b/src/inputjs/getDirection.js @@ -1,4 +1,4 @@ -import {abs} from '../utilsjs/utilsConsts'; +import {abs} from '../utils/utilsConsts'; import {DIRECTION_NONE,DIRECTION_LEFT,DIRECTION_RIGHT,DIRECTION_UP,DIRECTION_DOWN} from './inputConsts'; /** @@ -7,7 +7,7 @@ import {DIRECTION_NONE,DIRECTION_LEFT,DIRECTION_RIGHT,DIRECTION_UP,DIRECTION_DOW * @param {Number} y * @return {Number} direction */ -function getDirection(x, y) { +export default function getDirection(x, y) { if (x === y) { return DIRECTION_NONE; } @@ -17,5 +17,3 @@ function getDirection(x, y) { } return y < 0 ? DIRECTION_UP : DIRECTION_DOWN; } - -export {getDirection}; diff --git a/src/inputjs/getDistance.js b/src/inputjs/getDistance.js index 3b1557026..261e9ab2b 100644 --- a/src/inputjs/getDistance.js +++ b/src/inputjs/getDistance.js @@ -7,7 +7,7 @@ import {PROPS_XY} from './inputConsts'; * @param {Array} [props] containing x and y keys * @return {Number} distance */ -function getDistance(p1, p2, props) { +export default function getDistance(p1, p2, props) { if (!props) { props = PROPS_XY; } @@ -16,5 +16,3 @@ function getDistance(p1, p2, props) { return Math.sqrt((x * x) + (y * y)); } - -export {getDistance}; diff --git a/src/inputjs/getRotation.js b/src/inputjs/getRotation.js index 4a1bd303a..7fa5398b1 100644 --- a/src/inputjs/getRotation.js +++ b/src/inputjs/getRotation.js @@ -1,4 +1,4 @@ -import {getAngle} from './getAngle'; +import getAngle from './getAngle'; import {PROPS_CLIENT_XY} from './inputConsts'; /** @@ -7,8 +7,6 @@ import {PROPS_CLIENT_XY} from './inputConsts'; * @param {Array} end array of pointers * @return {Number} rotation */ -function getRotation(start, end) { +export default function getRotation(start, end) { return getAngle(end[1], end[0], PROPS_CLIENT_XY) + getAngle(start[1], start[0], PROPS_CLIENT_XY); } - -export {getRotation}; diff --git a/src/inputjs/getScale.js b/src/inputjs/getScale.js index 1c1bc86bb..b64b2881f 100644 --- a/src/inputjs/getScale.js +++ b/src/inputjs/getScale.js @@ -1,5 +1,5 @@ import {PROPS_CLIENT_XY} from './inputConsts'; -import {getDistance} from './getDistance'; +import getDistance from './getDistance'; /** * calculate the scale factor between two pointersets * no scale is 1, and goes down to 0 when pinched together, and bigger when pinched out @@ -7,8 +7,6 @@ import {getDistance} from './getDistance'; * @param {Array} end array of pointers * @return {Number} scale */ -function getScale(start, end) { +export default function getScale(start, end) { return getDistance(end[0], end[1], PROPS_CLIENT_XY) / getDistance(start[0], start[1], PROPS_CLIENT_XY); } - -export {getScale}; diff --git a/src/inputjs/getVelocity.js b/src/inputjs/getVelocity.js index 72c4ad6dd..a07bdd9aa 100644 --- a/src/inputjs/getVelocity.js +++ b/src/inputjs/getVelocity.js @@ -5,11 +5,9 @@ * @param {Number} y * @return {Object} velocity `x` and `y` */ -function getVelocity(deltaTime, x, y) { +export default function getVelocity(deltaTime, x, y) { return { x: x / deltaTime || 0, y: y / deltaTime || 0 }; } - -export {getVelocity}; diff --git a/src/inputjs/inputConstructor.js b/src/inputjs/inputConstructor.js index c41242795..1f4a61a46 100644 --- a/src/inputjs/inputConstructor.js +++ b/src/inputjs/inputConstructor.js @@ -1,7 +1,7 @@ -import {boolOrFn} from './../utilsjs/boolOrFn'; -import {addEventListeners} from './../utilsjs/addEventListeners'; -import {removeEventListeners} from './../utilsjs/removeEventListeners'; -import {getWindowForElement} from './../utilsjs/getWindowForElement'; +import boolOrFn from '../utils/boolOrFn'; +import addEventListeners from '../utils/addEventListeners'; +import removeEventListeners from '../utils/removeEventListeners'; +import getWindowForElement from '../utils/getWindowForElement'; /** * create new input type manager diff --git a/src/inputjs/inputConsts.js b/src/inputjs/inputConsts.js index 279149ef0..77381e5ad 100644 --- a/src/inputjs/inputConsts.js +++ b/src/inputjs/inputConsts.js @@ -1,4 +1,4 @@ -import {prefixed} from '../utilsjs/prefixed'; +import prefixed from '../utils/prefixed'; var MOBILE_REGEX = /mobile|tablet|ip(ad|hone|od)|android/i; diff --git a/src/inputjs/inputHandler.js b/src/inputjs/inputHandler.js index 8022f40c2..6fb880681 100644 --- a/src/inputjs/inputHandler.js +++ b/src/inputjs/inputHandler.js @@ -1,5 +1,5 @@ import {INPUT_START,INPUT_END,INPUT_CANCEL} from './inputConsts'; -import {computeInputData} from './computeInputData'; +import computeInputData from './computeInputData'; /** * handle input events @@ -7,7 +7,7 @@ import {computeInputData} from './computeInputData'; * @param {String} eventType * @param {Object} input */ -function inputHandler(manager, eventType, input) { +export default function inputHandler(manager, eventType, input) { var pointersLen = input.pointers.length; var changedPointersLen = input.changedPointers.length; var isFirst = (eventType & INPUT_START && (pointersLen - changedPointersLen === 0)); @@ -33,5 +33,3 @@ function inputHandler(manager, eventType, input) { manager.recognize(input); manager.session.prevInput = input; } - -export {inputHandler}; diff --git a/src/inputjs/simpleCloneInputData.js b/src/inputjs/simpleCloneInputData.js index fbcea8f0f..796a8da92 100644 --- a/src/inputjs/simpleCloneInputData.js +++ b/src/inputjs/simpleCloneInputData.js @@ -1,12 +1,12 @@ -import {now,round} from '../utilsjs/utilsConsts'; -import {getCenter} from './getCenter'; +import {now,round} from '../utils/utilsConsts'; +import getCenter from './getCenter'; /** * create a simple clone from the input used for storage of firstInput and firstMultiple * @param {Object} input * @returns {Object} clonedInputData */ -function simpleCloneInputData(input) { +export default function simpleCloneInputData(input) { // make a simple copy of the pointers because we will get a reference if we don't // we only need clientXY for the calculations var pointers = []; @@ -27,5 +27,3 @@ function simpleCloneInputData(input) { deltaY: input.deltaY }; } - -export {simpleCloneInputData}; diff --git a/src/main.js b/src/main.js index 9ce8b5e63..51945c800 100644 --- a/src/main.js +++ b/src/main.js @@ -1,5 +1,5 @@ import {Hammer} from './hammer'; -import {assign} from './utilsjs/assign'; +import {assign} from './utils/assign'; import {INPUT_START,INPUT_MOVE,INPUT_END,INPUT_CANCEL} from './inputjs/inputConsts'; import {STATE_POSSIBLE,STATE_BEGAN,STATE_CHANGED,STATE_ENDED,STATE_RECOGNIZED, STATE_CANCELLED,STATE_FAILED} from './recognizerjs/recognizerConsts'; @@ -24,14 +24,14 @@ import {PinchRecognizer} from './recognizers/pinch'; import {RotateRecognizer} from './recognizers/rotate'; import {PressRecognizer} from './recognizers/press'; -import {addEventListeners} from './utilsjs/addEventListeners'; -import {removeEventListeners} from './utilsjs/removeEventListeners'; -import {each} from './utilsjs/each'; -import {merge} from './utilsjs/merge'; -import {extend} from './utilsjs/extend'; -import {inherit} from './utilsjs/inherit'; -import {bindFn} from './utilsjs/bindFn'; -import {prefixed} from './utilsjs/prefixed'; +import addEventListeners from './utils/addEventListeners'; +import removeEventListeners from './utils/removeEventListeners'; +import each from './utils/each'; +import {merge} from './utils/merge'; +import {extend} from './utils/extend'; +import inherit from './utils/inherit'; +import bindFn from './utils/bindFn'; +import prefixed from './utils/prefixed'; // this prevents errors when Hammer is loaded in the presence of an AMD // style loader but by script tag, not by the loader. diff --git a/src/manager.js b/src/manager.js index eed9dc021..0ddfcb2be 100644 --- a/src/manager.js +++ b/src/manager.js @@ -1,12 +1,12 @@ -import {assign} from './utilsjs/assign'; +import {assign} from './utils/assign'; import {Hammer} from './hammer'; import {TouchAction} from './touchactionjs/touchActionConstructor'; -import {createInputInstance} from './inputjs/createInputInstance'; -import {each} from './utilsjs/each'; -import {inArray} from './utilsjs/inArray'; -import {invokeArrayArg} from './utilsjs/invokeArrayArg'; -import {splitStr} from './utilsjs/splitStr'; -import {prefixed} from './utilsjs/prefixed'; +import createInputInstance from './inputjs/createInputInstance'; +import each from './utils/each'; +import inArray from './utils/inArray'; +import invokeArrayArg from './utils/invokeArrayArg'; +import splitStr from './utils/splitStr'; +import prefixed from './utils/prefixed'; import {Recognizer} from './recognizerjs/recognizerConstructor'; import {STATE_BEGAN,STATE_ENDED,STATE_CHANGED,STATE_RECOGNIZED} from './recognizerjs/recognizerConsts'; diff --git a/src/recognizerjs/directionStr.js b/src/recognizerjs/directionStr.js index 3513e5948..d6d6da84d 100644 --- a/src/recognizerjs/directionStr.js +++ b/src/recognizerjs/directionStr.js @@ -5,7 +5,7 @@ import {DIRECTION_LEFT,DIRECTION_RIGHT,DIRECTION_UP,DIRECTION_DOWN} from '../inp * @param {constant} direction * @returns {String} */ -function directionStr(direction) { +export default function directionStr(direction) { if (direction == DIRECTION_DOWN) { return 'down'; } else if (direction == DIRECTION_UP) { @@ -17,5 +17,3 @@ function directionStr(direction) { } return ''; } - -export {directionStr}; diff --git a/src/recognizerjs/getRecognizerByNameIfManager.js b/src/recognizerjs/getRecognizerByNameIfManager.js index 7df93f809..52bd53012 100644 --- a/src/recognizerjs/getRecognizerByNameIfManager.js +++ b/src/recognizerjs/getRecognizerByNameIfManager.js @@ -4,12 +4,10 @@ * @param {Recognizer} recognizer * @returns {Recognizer} */ -function getRecognizerByNameIfManager(otherRecognizer, recognizer) { +export default function getRecognizerByNameIfManager(otherRecognizer, recognizer) { var manager = recognizer.manager; if (manager) { return manager.get(otherRecognizer); } return otherRecognizer; } - -export {getRecognizerByNameIfManager}; diff --git a/src/recognizerjs/recognizerConstructor.js b/src/recognizerjs/recognizerConstructor.js index 6a0d9c475..7ae60afe1 100644 --- a/src/recognizerjs/recognizerConstructor.js +++ b/src/recognizerjs/recognizerConstructor.js @@ -1,13 +1,14 @@ import {STATE_POSSIBLE,STATE_ENDED,STATE_FAILED,STATE_RECOGNIZED,STATE_CANCELLED, - STATE_BEGAN,STATE_CHANGED} from './recognizerConsts'; -import {assign} from '../utilsjs/assign'; -import {uniqueId} from '../utilsjs/uniqueId'; -import {ifUndefined} from '../utilsjs/ifUndefined'; -import {invokeArrayArg} from '../utilsjs/invokeArrayArg'; -import {inArray} from '../utilsjs/inArray'; -import {boolOrFn} from '../utilsjs/boolOrFn'; -import {getRecognizerByNameIfManager} from './getRecognizerByNameIfManager'; -import {stateStr} from './stateStr'; + STATE_BEGAN,STATE_CHANGED} from './recognizerConsts'; +import {assign} from '../utils/assign'; +import uniqueId from '../utils/uniqueId'; +import ifUndefined from '../utils/ifUndefined'; +import invokeArrayArg from '../utils/invokeArrayArg'; +import inArray from '../utils/inArray'; +import boolOrFn from '../utils/boolOrFn'; +import getRecognizerByNameIfManager from './getRecognizerByNameIfManager'; +import stateStr from './stateStr'; + /** * Recognizer flow explained; * * All recognizers have the initial state of POSSIBLE when a input session starts. diff --git a/src/recognizerjs/stateStr.js b/src/recognizerjs/stateStr.js index 651f9f3b1..e9f740d89 100644 --- a/src/recognizerjs/stateStr.js +++ b/src/recognizerjs/stateStr.js @@ -5,7 +5,7 @@ import {STATE_CANCELLED,STATE_ENDED,STATE_CHANGED,STATE_BEGAN} from './recognize * @param {constant} state * @returns {String} state */ -function stateStr(state) { +export default function stateStr(state) { if (state & STATE_CANCELLED) { return 'cancel'; } else if (state & STATE_ENDED) { @@ -17,5 +17,3 @@ function stateStr(state) { } return ''; } - -export {stateStr}; diff --git a/src/recognizers/attribute.js b/src/recognizers/attribute.js index c98052d08..257488e34 100644 --- a/src/recognizers/attribute.js +++ b/src/recognizers/attribute.js @@ -1,4 +1,4 @@ -import {inherit} from '../utilsjs/inherit'; +import inherit from '../utils/inherit'; import {Recognizer} from '../recognizerjs/recognizerConstructor'; import {STATE_BEGAN,STATE_CHANGED,STATE_CANCELLED,STATE_ENDED,STATE_FAILED} from '../recognizerjs/recognizerConsts'; import {INPUT_CANCEL,INPUT_END} from '../inputjs/inputConsts'; diff --git a/src/recognizers/pan.js b/src/recognizers/pan.js index 8fed083b6..e6a932914 100644 --- a/src/recognizers/pan.js +++ b/src/recognizers/pan.js @@ -1,10 +1,10 @@ import {AttrRecognizer} from './attribute'; -import {inherit} from '../utilsjs/inherit'; +import inherit from '../utils/inherit'; import {DIRECTION_ALL,DIRECTION_HORIZONTAL,DIRECTION_VERTICAL,DIRECTION_NONE,DIRECTION_UP,DIRECTION_DOWN, DIRECTION_LEFT,DIRECTION_RIGHT} from '../inputjs/inputConsts'; import {STATE_BEGAN} from '../recognizerjs/recognizerConsts'; import {TOUCH_ACTION_PAN_X,TOUCH_ACTION_PAN_Y} from '../touchactionjs/touchactionConsts'; -import {directionStr} from '../recognizerjs/directionStr'; +import directionStr from '../recognizerjs/directionStr'; /** * Pan diff --git a/src/recognizers/pinch.js b/src/recognizers/pinch.js index 0e5b960ff..b35bd433f 100644 --- a/src/recognizers/pinch.js +++ b/src/recognizers/pinch.js @@ -1,5 +1,5 @@ import {AttrRecognizer} from './attribute'; -import {inherit} from '../utilsjs/inherit'; +import inherit from '../utils/inherit'; import {TOUCH_ACTION_NONE} from '../touchactionjs/touchactionConsts'; import {STATE_BEGAN} from '../recognizerjs/recognizerConsts'; diff --git a/src/recognizers/press.js b/src/recognizers/press.js index ae2795fb7..185d3a4b2 100644 --- a/src/recognizers/press.js +++ b/src/recognizers/press.js @@ -1,8 +1,8 @@ import {Recognizer} from '../recognizerjs/recognizerConstructor'; import {STATE_RECOGNIZED,STATE_FAILED} from '../recognizerjs/recognizerConsts'; -import {inherit} from '../utilsjs/inherit'; -import {now} from '../utilsjs/utilsConsts'; -import {setTimeoutContext} from '../utilsjs/setTimeoutContext'; +import inherit from '../utils/inherit'; +import {now} from '../utils/utilsConsts'; +import setTimeoutContext from '../utils/setTimeoutContext'; import {TOUCH_ACTION_AUTO} from '../touchactionjs/touchactionConsts'; import {INPUT_START,INPUT_END,INPUT_CANCEL} from '../inputjs/inputConsts'; diff --git a/src/recognizers/rotate.js b/src/recognizers/rotate.js index af50e1c90..cf8270245 100644 --- a/src/recognizers/rotate.js +++ b/src/recognizers/rotate.js @@ -1,5 +1,5 @@ import {AttrRecognizer} from './attribute'; -import {inherit} from '../utilsjs/inherit'; +import inherit from '../utils/inherit'; import {TOUCH_ACTION_NONE} from '../touchactionjs/touchactionConsts'; import {STATE_BEGAN} from '../recognizerjs/recognizerConsts'; diff --git a/src/recognizers/swipe.js b/src/recognizers/swipe.js index be429dbee..bee3699b8 100644 --- a/src/recognizers/swipe.js +++ b/src/recognizers/swipe.js @@ -1,10 +1,10 @@ import {AttrRecognizer} from '../recognizers/attribute'; -import {inherit} from '../utilsjs/inherit'; -import {abs} from '../utilsjs/utilsConsts'; +import inherit from '../utils/inherit'; +import {abs} from '../utils/utilsConsts'; import {DIRECTION_HORIZONTAL,DIRECTION_VERTICAL} from '../inputjs/inputConsts'; import {PanRecognizer} from './pan'; import {INPUT_END} from '../inputjs/inputConsts'; -import {directionStr} from '../recognizerjs/directionStr'; +import directionStr from '../recognizerjs/directionStr'; /** * Swipe diff --git a/src/recognizers/tap.js b/src/recognizers/tap.js index 5cee178ac..075e7dc88 100644 --- a/src/recognizers/tap.js +++ b/src/recognizers/tap.js @@ -1,13 +1,13 @@ -import {inherit} from '../utilsjs/inherit'; -import {setTimeoutContext} from '../utilsjs/setTimeoutContext'; +import inherit from '../utils/inherit'; +import setTimeoutContext from '../utils/setTimeoutContext'; import {Recognizer} from '../recognizerjs/recognizerConstructor'; import {TOUCH_ACTION_MANIPULATION} from '../touchactionjs/touchactionConsts'; import {INPUT_START,INPUT_END} from '../inputjs/inputConsts'; import {STATE_RECOGNIZED,STATE_BEGAN,STATE_FAILED} from '../recognizerjs/recognizerConsts'; -import {getDistance} from '../inputjs/getDistance'; +import getDistance from '../inputjs/getDistance'; /** - * A tap is ecognized when the pointer is doing a small tap/click. Multiple taps are recognized if they occur + * A tap is recognized when the pointer is doing a small tap/click. Multiple taps are recognized if they occur * between the given interval and position. The delay option can be used to recognize multi-taps without firing * a single tap. * diff --git a/src/touchactionjs/cleanTouchActions.js b/src/touchactionjs/cleanTouchActions.js index 5e0e976df..f651834a5 100644 --- a/src/touchactionjs/cleanTouchActions.js +++ b/src/touchactionjs/cleanTouchActions.js @@ -1,4 +1,4 @@ -import {inStr} from '../utilsjs/inStr'; +import inStr from '../utils/inStr'; import {TOUCH_ACTION_NONE,TOUCH_ACTION_PAN_X,TOUCH_ACTION_PAN_Y,TOUCH_ACTION_MANIPULATION, TOUCH_ACTION_AUTO} from './touchactionConsts'; @@ -7,7 +7,7 @@ TOUCH_ACTION_AUTO} from './touchactionConsts'; * @param {String} actions * @returns {*} */ -function cleanTouchActions(actions) { +export default function cleanTouchActions(actions) { // none if (inStr(actions, TOUCH_ACTION_NONE)) { return TOUCH_ACTION_NONE; @@ -36,5 +36,3 @@ function cleanTouchActions(actions) { return TOUCH_ACTION_AUTO; } - -export {cleanTouchActions}; diff --git a/src/touchactionjs/getTouchActionProps.js b/src/touchactionjs/getTouchActionProps.js index 2c531258e..5eee7e992 100644 --- a/src/touchactionjs/getTouchActionProps.js +++ b/src/touchactionjs/getTouchActionProps.js @@ -1,5 +1,6 @@ import {NATIVE_TOUCH_ACTION} from './touchactionConsts'; -function getTouchActionProps() { + +export default function getTouchActionProps() { if (!NATIVE_TOUCH_ACTION) { return false; } @@ -13,5 +14,3 @@ function getTouchActionProps() { }); return touchMap; } - -export {getTouchActionProps}; diff --git a/src/touchactionjs/touchActionConstructor.js b/src/touchactionjs/touchActionConstructor.js index ff0f8841d..bbccdd84f 100644 --- a/src/touchactionjs/touchActionConstructor.js +++ b/src/touchactionjs/touchActionConstructor.js @@ -1,10 +1,10 @@ import {TOUCH_ACTION_COMPUTE,TOUCH_ACTION_MAP,NATIVE_TOUCH_ACTION,PREFIXED_TOUCH_ACTION,TOUCH_ACTION_NONE, TOUCH_ACTION_PAN_X,TOUCH_ACTION_PAN_Y} from './touchactionConsts'; import {DIRECTION_VERTICAL,DIRECTION_HORIZONTAL} from '../inputjs/inputConsts'; -import {each} from '../utilsjs/each'; -import {boolOrFn} from '../utilsjs/boolOrFn'; -import {inStr} from '../utilsjs/inStr'; -import {cleanTouchActions} from './cleanTouchActions'; +import each from '../utils/each'; +import boolOrFn from '../utils/boolOrFn'; +import inStr from '../utils/inStr'; +import cleanTouchActions from './cleanTouchActions'; /** * Touch Action diff --git a/src/touchactionjs/touchactionConsts.js b/src/touchactionjs/touchactionConsts.js index 34c5e36a7..344aebddc 100644 --- a/src/touchactionjs/touchactionConsts.js +++ b/src/touchactionjs/touchactionConsts.js @@ -1,6 +1,6 @@ -import {prefixed} from '../utilsjs/prefixed'; -import {TEST_ELEMENT} from '../utilsjs/utilsConsts'; -import {getTouchActionProps} from './getTouchActionProps'; +import prefixed from '../utils/prefixed'; +import {TEST_ELEMENT} from '../utils/utilsConsts'; +import getTouchActionProps from './getTouchActionProps'; var PREFIXED_TOUCH_ACTION = prefixed(TEST_ELEMENT.style, 'touchAction'); var NATIVE_TOUCH_ACTION = PREFIXED_TOUCH_ACTION !== undefined; diff --git a/src/utilsjs/addEventListeners.js b/src/utils/addEventListeners.js similarity index 62% rename from src/utilsjs/addEventListeners.js rename to src/utils/addEventListeners.js index b4475beea..ee70ec74a 100644 --- a/src/utilsjs/addEventListeners.js +++ b/src/utils/addEventListeners.js @@ -1,15 +1,13 @@ -import {each} from './each'; -import {splitStr} from './splitStr'; +import each from './each'; +import splitStr from './splitStr'; /** * addEventListener with multiple events at once * @param {EventTarget} target * @param {String} types * @param {Function} handler */ -function addEventListeners(target, types, handler) { +export default function addEventListeners(target, types, handler) { each(splitStr(types), function(type) { target.addEventListener(type, handler, false); }); } - -export {addEventListeners}; diff --git a/src/utilsjs/assign.js b/src/utils/assign.js similarity index 100% rename from src/utilsjs/assign.js rename to src/utils/assign.js diff --git a/src/utilsjs/bindFn.js b/src/utils/bindFn.js similarity index 79% rename from src/utilsjs/bindFn.js rename to src/utils/bindFn.js index 859a8ff3e..58c453fd7 100644 --- a/src/utilsjs/bindFn.js +++ b/src/utils/bindFn.js @@ -4,10 +4,8 @@ * @param {Object} context * @returns {Function} */ -function bindFn(fn, context) { +export default function bindFn(fn, context) { return function boundFn() { return fn.apply(context, arguments); }; } - -export {bindFn}; diff --git a/src/utilsjs/boolOrFn.js b/src/utils/boolOrFn.js similarity index 88% rename from src/utilsjs/boolOrFn.js rename to src/utils/boolOrFn.js index aff64a1e3..4971b0c20 100644 --- a/src/utilsjs/boolOrFn.js +++ b/src/utils/boolOrFn.js @@ -6,11 +6,9 @@ import {TYPE_FUNCTION} from './utilsConsts'; * @param {Array} [args] * @returns {Boolean} */ -function boolOrFn(val, args) { +export default function boolOrFn(val, args) { if (typeof val == TYPE_FUNCTION) { return val.apply(args ? args[0] || undefined : undefined, args); } return val; } - -export {boolOrFn}; diff --git a/src/utilsjs/deprecate.js b/src/utils/deprecate.js similarity index 92% rename from src/utilsjs/deprecate.js rename to src/utils/deprecate.js index b13340fe4..89ebae1e0 100644 --- a/src/utilsjs/deprecate.js +++ b/src/utils/deprecate.js @@ -5,7 +5,7 @@ * @param {String} message * @returns {Function} A new function wrapping the supplied method. */ -function deprecate(method, name, message) { +export default function deprecate(method, name, message) { var deprecationMessage = 'DEPRECATED METHOD: ' + name + '\n' + message + ' AT \n'; return function() { var e = new Error('get-stack-trace'); @@ -20,5 +20,3 @@ function deprecate(method, name, message) { return method.apply(this, arguments); }; } - -export {deprecate}; diff --git a/src/utilsjs/each.js b/src/utils/each.js similarity index 90% rename from src/utilsjs/each.js rename to src/utils/each.js index 8e8b65b99..60ea73a98 100644 --- a/src/utilsjs/each.js +++ b/src/utils/each.js @@ -4,7 +4,7 @@ * @param {Function} iterator * @param {Object} context */ -function each(obj, iterator, context) { +export default function each(obj, iterator, context) { var i; if (!obj) { @@ -25,5 +25,3 @@ function each(obj, iterator, context) { } } } - -export {each}; diff --git a/src/utilsjs/extend.js b/src/utils/extend.js similarity index 93% rename from src/utilsjs/extend.js rename to src/utils/extend.js index 17de8c135..facab691b 100644 --- a/src/utilsjs/extend.js +++ b/src/utils/extend.js @@ -1,4 +1,4 @@ -import {deprecate} from './deprecate'; +import deprecate from './deprecate'; /** * extend object. * means that properties in dest will be overwritten by the ones in src. diff --git a/src/utilsjs/getWindowForElement.js b/src/utils/getWindowForElement.js similarity index 76% rename from src/utilsjs/getWindowForElement.js rename to src/utils/getWindowForElement.js index 37757b232..a4a58919e 100644 --- a/src/utilsjs/getWindowForElement.js +++ b/src/utils/getWindowForElement.js @@ -3,8 +3,7 @@ * @param {HTMLElement} element * @returns {DocumentView|Window} */ -function getWindowForElement(element) { +export default function getWindowForElement(element) { var doc = element.ownerDocument || element; return (doc.defaultView || doc.parentWindow || window); } -export {getWindowForElement}; diff --git a/src/utilsjs/hasParent.js b/src/utils/hasParent.js similarity index 84% rename from src/utilsjs/hasParent.js rename to src/utils/hasParent.js index e4ee0c899..09215994f 100644 --- a/src/utilsjs/hasParent.js +++ b/src/utils/hasParent.js @@ -5,7 +5,7 @@ * @param {HTMLElement} parent * @return {Boolean} found */ -function hasParent(node, parent) { +export default function hasParent(node, parent) { while (node) { if (node == parent) { return true; @@ -14,5 +14,3 @@ function hasParent(node, parent) { } return false; } - -export {hasParent}; diff --git a/src/utilsjs/ifUndefined.js b/src/utils/ifUndefined.js similarity index 72% rename from src/utilsjs/ifUndefined.js rename to src/utils/ifUndefined.js index 7a96b23f0..896f6257b 100644 --- a/src/utilsjs/ifUndefined.js +++ b/src/utils/ifUndefined.js @@ -4,8 +4,6 @@ * @param {*} val2 * @returns {*} */ -function ifUndefined(val1, val2) { +export default function ifUndefined(val1, val2) { return (val1 === undefined) ? val2 : val1; } - -export {ifUndefined}; diff --git a/src/utilsjs/inArray.js b/src/utils/inArray.js similarity index 90% rename from src/utilsjs/inArray.js rename to src/utils/inArray.js index 58bd456a3..4186c9f65 100644 --- a/src/utilsjs/inArray.js +++ b/src/utils/inArray.js @@ -5,7 +5,7 @@ * @param {String} [findByKey] * @return {Boolean|Number} false when not found, or the index */ -function inArray(src, find, findByKey) { +export default function inArray(src, find, findByKey) { if (src.indexOf && !findByKey) { return src.indexOf(find); } else { @@ -19,5 +19,3 @@ function inArray(src, find, findByKey) { return -1; } } - -export {inArray}; diff --git a/src/utilsjs/inStr.js b/src/utils/inStr.js similarity index 76% rename from src/utilsjs/inStr.js rename to src/utils/inStr.js index c4c93370f..d81951089 100644 --- a/src/utilsjs/inStr.js +++ b/src/utils/inStr.js @@ -4,8 +4,6 @@ * @param {String} find * @returns {Boolean} found */ -function inStr(str, find) { +export default function inStr(str, find) { return str.indexOf(find) > -1; } - -export {inStr}; diff --git a/src/utilsjs/inherit.js b/src/utils/inherit.js similarity index 85% rename from src/utilsjs/inherit.js rename to src/utils/inherit.js index 3483ab066..898487680 100644 --- a/src/utilsjs/inherit.js +++ b/src/utils/inherit.js @@ -5,7 +5,7 @@ import {assign} from './assign'; * @param {Function} base * @param {Object} [properties] */ -function inherit(child, base, properties) { +export default function inherit(child, base, properties) { var baseP = base.prototype, childP; @@ -17,5 +17,3 @@ function inherit(child, base, properties) { assign(childP, properties); } } - -export {inherit}; diff --git a/src/utilsjs/invokeArrayArg.js b/src/utils/invokeArrayArg.js similarity index 81% rename from src/utilsjs/invokeArrayArg.js rename to src/utils/invokeArrayArg.js index 21d400854..c77fa396e 100644 --- a/src/utilsjs/invokeArrayArg.js +++ b/src/utils/invokeArrayArg.js @@ -1,4 +1,4 @@ -import {each} from './each'; +import each from './each'; /** * if the argument is an array, we want to execute the fn on each entry * if it aint an array we don't want to do a thing. @@ -8,12 +8,10 @@ import {each} from './each'; * @param {Object} [context] * @returns {Boolean} */ -function invokeArrayArg(arg, fn, context) { +export default function invokeArrayArg(arg, fn, context) { if (Array.isArray(arg)) { each(arg, context[fn], context); return true; } return false; } - -export {invokeArrayArg}; diff --git a/src/utilsjs/merge.js b/src/utils/merge.js similarity index 90% rename from src/utilsjs/merge.js rename to src/utils/merge.js index 6ca144c8b..ad1257d3a 100644 --- a/src/utilsjs/merge.js +++ b/src/utils/merge.js @@ -1,4 +1,4 @@ -import {deprecate} from './deprecate'; +import deprecate from './deprecate'; import {extend} from './extend'; /** * merge the values from src in the dest. diff --git a/src/utilsjs/prefixed.js b/src/utils/prefixed.js similarity index 90% rename from src/utilsjs/prefixed.js rename to src/utils/prefixed.js index bd6ea07f9..8d9b803b1 100644 --- a/src/utilsjs/prefixed.js +++ b/src/utils/prefixed.js @@ -5,7 +5,7 @@ import {VENDOR_PREFIXES} from './utilsConsts'; * @param {String} property * @returns {String|Undefined} prefixed */ -function prefixed(obj, property) { +export default function prefixed(obj, property) { var prefix, prop; var camelProp = property[0].toUpperCase() + property.slice(1); @@ -21,5 +21,3 @@ function prefixed(obj, property) { } return undefined; } - -export {prefixed}; diff --git a/src/utilsjs/removeEventListeners.js b/src/utils/removeEventListeners.js similarity index 62% rename from src/utilsjs/removeEventListeners.js rename to src/utils/removeEventListeners.js index 5a396b6a6..2b51bf1d0 100644 --- a/src/utilsjs/removeEventListeners.js +++ b/src/utils/removeEventListeners.js @@ -1,15 +1,13 @@ -import {each} from './each'; -import {splitStr} from './splitStr'; +import each from './each'; +import splitStr from './splitStr'; /** * removeEventListener with multiple events at once * @param {EventTarget} target * @param {String} types * @param {Function} handler */ -function removeEventListeners(target, types, handler) { +export default function removeEventListeners(target, types, handler) { each(splitStr(types), function(type) { target.removeEventListener(type, handler, false); }); } - -export {removeEventListeners}; diff --git a/src/utilsjs/setTimeoutContext.js b/src/utils/setTimeoutContext.js similarity index 63% rename from src/utilsjs/setTimeoutContext.js rename to src/utils/setTimeoutContext.js index 3437d4202..60077a626 100644 --- a/src/utilsjs/setTimeoutContext.js +++ b/src/utils/setTimeoutContext.js @@ -1,4 +1,5 @@ -import {bindFn} from './bindFn'; +import bindFn from './bindFn'; + /** * set a timeout with a given scope * @param {Function} fn @@ -6,8 +7,6 @@ import {bindFn} from './bindFn'; * @param {Object} context * @returns {number} */ -function setTimeoutContext(fn, timeout, context) { +export default function setTimeoutContext(fn, timeout, context) { return setTimeout(bindFn(fn, context), timeout); } - -export {setTimeoutContext}; diff --git a/src/utilsjs/splitStr.js b/src/utils/splitStr.js similarity index 74% rename from src/utilsjs/splitStr.js rename to src/utils/splitStr.js index 1897926a9..5175a9b44 100644 --- a/src/utilsjs/splitStr.js +++ b/src/utils/splitStr.js @@ -3,8 +3,7 @@ * @param {String} str * @returns {Array} words */ -function splitStr(str) { + +export default function splitStr(str) { return str.trim().split(/\s+/g); } - -export {splitStr}; diff --git a/src/utilsjs/toArray.js b/src/utils/toArray.js similarity index 77% rename from src/utilsjs/toArray.js rename to src/utils/toArray.js index 2de0d7f18..b4ef3915f 100644 --- a/src/utilsjs/toArray.js +++ b/src/utils/toArray.js @@ -3,8 +3,6 @@ * @param {Object} obj * @returns {Array} */ -function toArray(obj) { +export default function toArray(obj) { return Array.prototype.slice.call(obj, 0); } - -export {toArray}; diff --git a/src/utilsjs/uniqueArray.js b/src/utils/uniqueArray.js similarity index 88% rename from src/utilsjs/uniqueArray.js rename to src/utils/uniqueArray.js index 7c12da9e7..fd7d776c0 100644 --- a/src/utilsjs/uniqueArray.js +++ b/src/utils/uniqueArray.js @@ -1,4 +1,5 @@ -import {inArray} from './inArray'; +import inArray from './inArray'; + /** * unique array with objects based on a key (like 'id') or just by the array's value * @param {Array} src [{id:1},{id:2},{id:1}] @@ -6,7 +7,7 @@ import {inArray} from './inArray'; * @param {Boolean} [sort=False] * @returns {Array} [{id:1},{id:2}] */ -function uniqueArray(src, key, sort) { +export default function uniqueArray(src, key, sort) { var results = []; var values = []; var i = 0; @@ -32,5 +33,3 @@ function uniqueArray(src, key, sort) { return results; } - -export {uniqueArray}; diff --git a/src/utilsjs/uniqueId.js b/src/utils/uniqueId.js similarity index 70% rename from src/utilsjs/uniqueId.js rename to src/utils/uniqueId.js index b7f7c4029..397f8338d 100644 --- a/src/utilsjs/uniqueId.js +++ b/src/utils/uniqueId.js @@ -3,8 +3,6 @@ * @returns {number} uniqueId */ var _uniqueId = 1; -function uniqueId() { +export default function uniqueId() { return _uniqueId++; } - -export {uniqueId}; diff --git a/src/utilsjs/utilsConsts.js b/src/utils/utilsConsts.js similarity index 100% rename from src/utilsjs/utilsConsts.js rename to src/utils/utilsConsts.js From 00b84ce9a7d62ef6d5c73d0a1fabacfd28701e98 Mon Sep 17 00:00:00 2001 From: Arjun Kathuria Date: Mon, 6 Jun 2016 11:03:23 +0530 Subject: [PATCH 22/61] builds hammer with rollup via grunt task, removes concat completely. modified package.json to update to newer versions, excluded test task for the moment. build passes jshint and jscs tests --- .jshintrc | 1 - Gruntfile.coffee | 46 +++++++++++++++++++--------------------------- package.json | 8 ++++---- rollup.config.js | 2 +- src/.babelrc | 2 +- 5 files changed, 25 insertions(+), 34 deletions(-) diff --git a/.jshintrc b/.jshintrc index 7cd12e8a0..0182f27e7 100644 --- a/.jshintrc +++ b/.jshintrc @@ -8,7 +8,6 @@ "esversion":6, "newcap": true, "node": true, - "quotmark": "single", "strict": false, "sub": true, "trailing": true, diff --git a/Gruntfile.coffee b/Gruntfile.coffee index 739af0c56..8083ada1f 100644 --- a/Gruntfile.coffee +++ b/Gruntfile.coffee @@ -1,3 +1,4 @@ +babel = require('rollup-plugin-babel'); module.exports = (grunt) -> grunt.initConfig pkg: grunt.file.readJSON 'package.json' @@ -16,22 +17,16 @@ module.exports = (grunt) -> files: src: ['./hammer.js','./hammer.min.js'] - concat: - build: - src: [ - 'src/hammer.prefix.js' - 'src/utils.js' - 'src/input.js' - 'src/input/*.js' - 'src/touchaction.js' - 'src/recognizer.js' - 'src/recognizers/*.js' - 'src/hammer.js' - 'src/manager.js' - 'src/expose.js' - 'src/hammer.suffix.js'] + rollup: + options: + format: 'es6' + plugins: [ babel({exclude: 'node_modules/**'}) ] + intro: " (function(window, document, exportName, undefined) { \n'use strict';" + outro: "})(window, document, 'Hammer');" + files: dest: 'hammer.js' - + src: 'src/main.js' + uglify: min: options: @@ -52,15 +47,14 @@ module.exports = (grunt) -> exportName: 'Hammer' files: 'tests/build.js': [ - 'src/utils.js' - 'src/input.js' + 'src/utils/*.js' + 'src/inputjs/*.js' 'src/input/*.js' - 'src/touchaction.js' - 'src/recognizer.js' + 'src/touchactionjs/*.js' + 'src/recognizerjs/*.js' 'src/recognizers/*.js' 'src/hammer.js' - 'src/manager.js' - 'src/expose.js'] + 'src/manager.js'] 'string-replace': version: @@ -80,9 +74,7 @@ module.exports = (grunt) -> jscs: src: [ - 'src/**/*.js', - '!src/hammer.prefix.js', - '!src/hammer.suffix.js' + 'src/**/*.js' ] options: config: "./.jscsrc" @@ -106,7 +98,7 @@ module.exports = (grunt) -> # Load tasks - grunt.loadNpmTasks 'grunt-contrib-concat' + grunt.loadNpmTasks 'grunt-rollup'; grunt.loadNpmTasks 'grunt-contrib-uglify' grunt.loadNpmTasks 'grunt-contrib-qunit' grunt.loadNpmTasks 'grunt-contrib-watch' @@ -119,6 +111,6 @@ module.exports = (grunt) -> # Default task(s) grunt.registerTask 'default', ['connect', 'watch'] grunt.registerTask 'default-test', ['connect', 'uglify:test', 'watch'] - grunt.registerTask 'build', ['concat', 'string-replace', 'uglify:min', 'usebanner', 'test'] - grunt.registerTask 'test', ['jshint', 'jscs', 'uglify:test', 'qunit'] + grunt.registerTask 'build', ['rollup','string-replace', 'uglify:min', 'usebanner'] #'test'] + grunt.registerTask 'test', ['jshint', 'jscs','qunit'] grunt.registerTask 'test-travis', ['build'] diff --git a/package.json b/package.json index 9f2d976b0..d8f461f21 100644 --- a/package.json +++ b/package.json @@ -37,13 +37,13 @@ "git-tags": "^0.2.4", "grunt": "0.4.x", "grunt-banner": "^0.2.3", - "grunt-contrib-concat": "0.4.x", "grunt-contrib-connect": "0.7.x", - "grunt-contrib-jshint": "0.10.x", + "grunt-contrib-jshint": "^1.0.0", "grunt-contrib-qunit": "^0.5.1", - "grunt-contrib-uglify": "0.7.x", + "grunt-contrib-uglify": "^1.0.0", "grunt-contrib-watch": "0.6.x", - "grunt-jscs": "^0.8.0", + "grunt-jscs": "3.0.0", + "grunt-rollup": "^0.7.1", "grunt-string-replace": "^0.2.7", "hammer-simulator": "git://github.com/hammerjs/simulator#master", "jquery-hammerjs": "2.0.x", diff --git a/rollup.config.js b/rollup.config.js index 026d4c394..c91de8eae 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -9,7 +9,7 @@ export default { format: 'es6', // moduleName: 'HAMMER', plugins: [ babel({exclude: 'node_modules/**'}) ], - dest: 'bundle.js', + dest: 'hammer.js', intro: " (function(window, document, exportName, undefined) { \n'use strict' ", outro: "})(window, document, 'Hammer');" diff --git a/src/.babelrc b/src/.babelrc index 13b76880d..1d9cdd528 100644 --- a/src/.babelrc +++ b/src/.babelrc @@ -1,3 +1,3 @@ { "presets": ["es2015-rollup"] -} \ No newline at end of file +} From 8b24cd0dfdc725bda0f33112308608e60f13c507 Mon Sep 17 00:00:00 2001 From: Arjun Kathuria Date: Mon, 6 Jun 2016 12:32:09 +0530 Subject: [PATCH 23/61] fix! missed to replace concat with rollup in watch task, now done --- Gruntfile.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gruntfile.coffee b/Gruntfile.coffee index 8083ada1f..4b425d0a5 100644 --- a/Gruntfile.coffee +++ b/Gruntfile.coffee @@ -83,7 +83,7 @@ module.exports = (grunt) -> watch: scripts: files: ['src/**/*.js'] - tasks: ['concat','string-replace','uglify','jshint','jscs'] + tasks: ['rollup','string-replace','uglify','jshint','jscs'] options: interrupt: true From 70094e70769b7f13f53650327c2f3655a3b0734a Mon Sep 17 00:00:00 2001 From: Arjun Kathuria Date: Tue, 7 Jun 2016 21:58:16 +0530 Subject: [PATCH 24/61] tests hack, testing build now produced by rollup manually via rollup -c command instead of uglify:test to accomodate es6 --- Gruntfile.coffee | 45 +- rollup.config.js | 4 +- src/testMain.js | 117 ++ tests/testBuild.js | 2640 ++++++++++++++++++++++++++++++++++++++ tests/unit/index.html | 2 +- tests/unit/test_utils.js | 52 +- 6 files changed, 2809 insertions(+), 51 deletions(-) create mode 100644 src/testMain.js create mode 100644 tests/testBuild.js diff --git a/Gruntfile.coffee b/Gruntfile.coffee index 4b425d0a5..1d3b0321b 100644 --- a/Gruntfile.coffee +++ b/Gruntfile.coffee @@ -34,27 +34,28 @@ module.exports = (grunt) -> sourceMap: 'hammer.min.map' files: 'hammer.min.js': ['hammer.js'] - # special test build that exposes everything so it's testable - test: - options: - wrap: "$H" - comments: 'all' - exportAll: true - mangle: false - beautify: true - compress: - global_defs: - exportName: 'Hammer' - files: - 'tests/build.js': [ - 'src/utils/*.js' - 'src/inputjs/*.js' - 'src/input/*.js' - 'src/touchactionjs/*.js' - 'src/recognizerjs/*.js' - 'src/recognizers/*.js' - 'src/hammer.js' - 'src/manager.js'] + # special test build that exposes everything so it's testable, now the test build is produced via rollup -c in terminal + # the output is /tests/testBuild.js +# test: +# options: +# wrap: "$H" +# comments: 'all' +# exportAll: true +# mangle: false +# beautify: true +# compress: +# global_defs: +# exportName: 'Hammer' +# files: +# 'tests/build.js': [ +# 'src/utils/*.js' +# 'src/inputjs/*.js' +# 'src/input/*.js' +# 'src/touchactionjs/*.js' +# 'src/recognizerjs/*.js' +# 'src/recognizers/*.js' +# 'src/hammer.js' +# 'src/manager.js'] 'string-replace': version: @@ -111,6 +112,6 @@ module.exports = (grunt) -> # Default task(s) grunt.registerTask 'default', ['connect', 'watch'] grunt.registerTask 'default-test', ['connect', 'uglify:test', 'watch'] - grunt.registerTask 'build', ['rollup','string-replace', 'uglify:min', 'usebanner'] #'test'] + grunt.registerTask 'build', ['rollup','string-replace', 'uglify:min', 'usebanner', 'test'] grunt.registerTask 'test', ['jshint', 'jscs','qunit'] grunt.registerTask 'test-travis', ['build'] diff --git a/rollup.config.js b/rollup.config.js index c91de8eae..a09455930 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -5,11 +5,11 @@ import babel from 'rollup-plugin-babel'; export default { - entry: 'src/main.js', + entry: 'src/testMain.js', format: 'es6', // moduleName: 'HAMMER', plugins: [ babel({exclude: 'node_modules/**'}) ], - dest: 'hammer.js', + dest: 'tests/testBuild.js', intro: " (function(window, document, exportName, undefined) { \n'use strict' ", outro: "})(window, document, 'Hammer');" diff --git a/src/testMain.js b/src/testMain.js new file mode 100644 index 000000000..47e222992 --- /dev/null +++ b/src/testMain.js @@ -0,0 +1,117 @@ +import {Hammer} from './hammer'; +import {assign} from './utils/assign'; +import {INPUT_START,INPUT_MOVE,INPUT_END,INPUT_CANCEL} from './inputjs/inputConsts'; +import {STATE_POSSIBLE,STATE_BEGAN,STATE_CHANGED,STATE_ENDED,STATE_RECOGNIZED, + STATE_CANCELLED,STATE_FAILED} from './recognizerjs/recognizerConsts'; +import {DIRECTION_NONE,DIRECTION_LEFT,DIRECTION_RIGHT,DIRECTION_UP,DIRECTION_DOWN, + DIRECTION_HORIZONTAL,DIRECTION_VERTICAL,DIRECTION_ALL} from './inputjs/inputConsts'; + +import {Manager} from './manager'; +import {Input} from './inputjs/inputConstructor'; +import {TouchAction} from './touchactionjs/touchActionConstructor'; +import {TouchInput} from './input/touch'; +import {MouseInput} from './input/mouse'; +import {PointerEventInput} from './input/pointerevent'; +import {SingleTouchInput} from './input/singletouch'; +import {TouchMouseInput} from './input/touchmouse'; + +import {Recognizer} from './recognizerjs/recognizerConstructor'; +import {AttrRecognizer} from './recognizers/attribute'; +import {TapRecognizer} from './recognizers/tap'; +import {PanRecognizer} from './recognizers/pan'; +import {SwipeRecognizer} from './recognizers/swipe'; +import {PinchRecognizer} from './recognizers/pinch'; +import {RotateRecognizer} from './recognizers/rotate'; +import {PressRecognizer} from './recognizers/press'; + +import addEventListeners from './utils/addEventListeners'; +import removeEventListeners from './utils/removeEventListeners'; +import each from './utils/each'; +import {merge} from './utils/merge'; +import {extend} from './utils/extend'; +import inherit from './utils/inherit'; +import bindFn from './utils/bindFn'; +import prefixed from './utils/prefixed'; +import toArray from'./utils/toArray'; +import uniqueArray from'./utils/uniqueArray'; +import splitStr from'./utils/splitStr'; +import inArray from'./utils/inArray'; +import boolOrFn from'./utils/boolOrFn'; +import hasParent from'./utils/hasParent'; + +// this prevents errors when Hammer is loaded in the presence of an AMD +// style loader but by script tag, not by the loader. + +assign(Hammer, { + INPUT_START: INPUT_START, + INPUT_MOVE: INPUT_MOVE, + INPUT_END: INPUT_END, + INPUT_CANCEL: INPUT_CANCEL, + + STATE_POSSIBLE: STATE_POSSIBLE, + STATE_BEGAN: STATE_BEGAN, + STATE_CHANGED: STATE_CHANGED, + STATE_ENDED: STATE_ENDED, + STATE_RECOGNIZED: STATE_RECOGNIZED, + STATE_CANCELLED: STATE_CANCELLED, + STATE_FAILED: STATE_FAILED, + + DIRECTION_NONE: DIRECTION_NONE, + DIRECTION_LEFT: DIRECTION_LEFT, + DIRECTION_RIGHT: DIRECTION_RIGHT, + DIRECTION_UP: DIRECTION_UP, + DIRECTION_DOWN: DIRECTION_DOWN, + DIRECTION_HORIZONTAL: DIRECTION_HORIZONTAL, + DIRECTION_VERTICAL: DIRECTION_VERTICAL, + DIRECTION_ALL: DIRECTION_ALL, + + Manager: Manager, + Input: Input, + TouchAction: TouchAction, + + TouchInput: TouchInput, + MouseInput: MouseInput, + PointerEventInput: PointerEventInput, + TouchMouseInput: TouchMouseInput, + SingleTouchInput: SingleTouchInput, + + Recognizer: Recognizer, + AttrRecognizer: AttrRecognizer, + Tap: TapRecognizer, + Pan: PanRecognizer, + Swipe: SwipeRecognizer, + Pinch: PinchRecognizer, + Rotate: RotateRecognizer, + Press: PressRecognizer, + + on: addEventListeners, + off: removeEventListeners, + each: each, + merge: merge, + extend: extend, + assign: assign, + inherit: inherit, + bindFn: bindFn, + prefixed: prefixed, + toArray: toArray, + inArray: inArray, + uniqueArray: uniqueArray, + splitStr: splitStr, + boolOrFn:boolOrFn, + hasParent:hasParent, + addEventListeners: addEventListeners, + removeEventListeners: removeEventListeners +}); + +var freeGlobal = (typeof window !== 'undefined' ? window : (typeof self !== 'undefined' ? self : {})); // jshint ignore:line +freeGlobal.Hammer = Hammer; + +if (typeof define === 'function' && define.amd) { + define(function() { + return Hammer; + }); +} else if (typeof module != 'undefined' && module.exports) { + module.exports = Hammer; +} else { + window[exportName] = Hammer; +} diff --git a/tests/testBuild.js b/tests/testBuild.js new file mode 100644 index 000000000..b9fe98465 --- /dev/null +++ b/tests/testBuild.js @@ -0,0 +1,2640 @@ +(function(window, document, exportName, undefined) { +'use strict' + +var babelHelpers = {}; +babelHelpers.typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { + return typeof obj; +} : function (obj) { + return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj; +}; +babelHelpers; + +/** + * use the val2 when val1 is undefined + * @param {*} val1 + * @param {*} val2 + * @returns {*} + */ +function ifUndefined(val1, val2) { + return val1 === undefined ? val2 : val1; +} + +var VENDOR_PREFIXES = ['', 'webkit', 'Moz', 'MS', 'ms', 'o']; +var TEST_ELEMENT = document.createElement('div'); + +var TYPE_FUNCTION = 'function'; + +var round = Math.round; +var abs = Math.abs; +var now = Date.now; + +/** + * get the prefixed property + * @param {Object} obj + * @param {String} property + * @returns {String|Undefined} prefixed + */ +function prefixed(obj, property) { + var prefix, prop; + var camelProp = property[0].toUpperCase() + property.slice(1); + + var i = 0; + while (i < VENDOR_PREFIXES.length) { + prefix = VENDOR_PREFIXES[i]; + prop = prefix ? prefix + camelProp : property; + + if (prop in obj) { + return prop; + } + i++; + } + return undefined; +} + +function getTouchActionProps() { + if (!NATIVE_TOUCH_ACTION) { + return false; + } + var touchMap = {}; + var cssSupports = window.CSS && window.CSS.supports; + ['auto', 'manipulation', 'pan-y', 'pan-x', 'pan-x pan-y', 'none'].forEach(function (val) { + + // If css.supports is not supported but there is native touch-action assume it supports + // all values. This is the case for IE 10 and 11. + touchMap[val] = cssSupports ? window.CSS.supports('touch-action', val) : true; + }); + return touchMap; +} + +var PREFIXED_TOUCH_ACTION = prefixed(TEST_ELEMENT.style, 'touchAction'); +var NATIVE_TOUCH_ACTION = PREFIXED_TOUCH_ACTION !== undefined; + +// magical touchAction value +var TOUCH_ACTION_COMPUTE = 'compute'; +var TOUCH_ACTION_AUTO = 'auto'; +var TOUCH_ACTION_MANIPULATION = 'manipulation'; // not implemented +var TOUCH_ACTION_NONE = 'none'; +var TOUCH_ACTION_PAN_X = 'pan-x'; +var TOUCH_ACTION_PAN_Y = 'pan-y'; +var TOUCH_ACTION_MAP = getTouchActionProps(); + +var MOBILE_REGEX = /mobile|tablet|ip(ad|hone|od)|android/i; + +var SUPPORT_TOUCH = 'ontouchstart' in window; +var SUPPORT_POINTER_EVENTS = prefixed(window, 'PointerEvent') !== undefined; +var SUPPORT_ONLY_TOUCH = SUPPORT_TOUCH && MOBILE_REGEX.test(navigator.userAgent); + +var INPUT_TYPE_TOUCH = 'touch'; +var INPUT_TYPE_PEN = 'pen'; +var INPUT_TYPE_MOUSE = 'mouse'; +var INPUT_TYPE_KINECT = 'kinect'; + +var COMPUTE_INTERVAL = 25; + +var INPUT_START = 1; +var INPUT_MOVE = 2; +var INPUT_END = 4; +var INPUT_CANCEL = 8; + +var DIRECTION_NONE = 1; +var DIRECTION_LEFT = 2; +var DIRECTION_RIGHT = 4; +var DIRECTION_UP = 8; +var DIRECTION_DOWN = 16; + +var DIRECTION_HORIZONTAL = DIRECTION_LEFT | DIRECTION_RIGHT; +var DIRECTION_VERTICAL = DIRECTION_UP | DIRECTION_DOWN; +var DIRECTION_ALL = DIRECTION_HORIZONTAL | DIRECTION_VERTICAL; + +var PROPS_XY = ['x', 'y']; +var PROPS_CLIENT_XY = ['clientX', 'clientY']; + +/** + * extend object. + * means that properties in dest will be overwritten by the ones in src. + * @param {Object} target + * @param {...Object} objects_to_assign + * @returns {Object} target + */ +var assign; +if (typeof Object.assign !== 'function') { + assign = function assign(target) { + if (target === undefined || target === null) { + throw new TypeError('Cannot convert undefined or null to object'); + } + + var output = Object(target); + for (var index = 1; index < arguments.length; index++) { + var source = arguments[index]; + if (source !== undefined && source !== null) { + for (var nextKey in source) { + if (source.hasOwnProperty(nextKey)) { + output[nextKey] = source[nextKey]; + } + } + } + } + return output; + }; +} else { + assign = Object.assign; +} + +/** + * simple class inheritance + * @param {Function} child + * @param {Function} base + * @param {Object} [properties] + */ +function inherit(child, base, properties) { + var baseP = base.prototype, + childP; + + childP = child.prototype = Object.create(baseP); + childP.constructor = child; + childP._super = baseP; + + if (properties) { + assign(childP, properties); + } +} + +var STATE_POSSIBLE = 1; +var STATE_BEGAN = 2; +var STATE_CHANGED = 4; +var STATE_ENDED = 8; +var STATE_RECOGNIZED = STATE_ENDED; +var STATE_CANCELLED = 16; +var STATE_FAILED = 32; + +/** + * get a unique id + * @returns {number} uniqueId + */ +var _uniqueId = 1; +function uniqueId() { + return _uniqueId++; +} + +/** + * walk objects and arrays + * @param {Object} obj + * @param {Function} iterator + * @param {Object} context + */ +function each(obj, iterator, context) { + var i; + + if (!obj) { + return; + } + + if (obj.forEach) { + obj.forEach(iterator, context); + } else if (obj.length !== undefined) { + i = 0; + while (i < obj.length) { + iterator.call(context, obj[i], i, obj); + i++; + } + } else { + for (i in obj) { + obj.hasOwnProperty(i) && iterator.call(context, obj[i], i, obj); + } + } +} + +/** + * if the argument is an array, we want to execute the fn on each entry + * if it aint an array we don't want to do a thing. + * this is used by all the methods that accept a single and array argument. + * @param {*|Array} arg + * @param {String} fn + * @param {Object} [context] + * @returns {Boolean} + */ +function invokeArrayArg(arg, fn, context) { + if (Array.isArray(arg)) { + each(arg, context[fn], context); + return true; + } + return false; +} + +/** + * find if a array contains the object using indexOf or a simple polyFill + * @param {Array} src + * @param {String} find + * @param {String} [findByKey] + * @return {Boolean|Number} false when not found, or the index + */ +function inArray(src, find, findByKey) { + if (src.indexOf && !findByKey) { + return src.indexOf(find); + } else { + var i = 0; + while (i < src.length) { + if (findByKey && src[i][findByKey] == find || !findByKey && src[i] === find) { + return i; + } + i++; + } + return -1; + } +} + +/** + * let a boolean value also be a function that must return a boolean + * this first item in args will be used as the context + * @param {Boolean|Function} val + * @param {Array} [args] + * @returns {Boolean} + */ +function boolOrFn(val, args) { + if ((typeof val === 'undefined' ? 'undefined' : babelHelpers.typeof(val)) == TYPE_FUNCTION) { + return val.apply(args ? args[0] || undefined : undefined, args); + } + return val; +} + +/** + * get a recognizer by name if it is bound to a manager + * @param {Recognizer|String} otherRecognizer + * @param {Recognizer} recognizer + * @returns {Recognizer} + */ +function getRecognizerByNameIfManager(otherRecognizer, recognizer) { + var manager = recognizer.manager; + if (manager) { + return manager.get(otherRecognizer); + } + return otherRecognizer; +} + +/** + * get a usable string, used as event postfix + * @param {constant} state + * @returns {String} state + */ +function stateStr(state) { + if (state & STATE_CANCELLED) { + return 'cancel'; + } else if (state & STATE_ENDED) { + return 'end'; + } else if (state & STATE_CHANGED) { + return 'move'; + } else if (state & STATE_BEGAN) { + return 'start'; + } + return ''; +} + +/** + * Recognizer flow explained; * + * All recognizers have the initial state of POSSIBLE when a input session starts. + * The definition of a input session is from the first input until the last input, with all it's movement in it. * + * Example session for mouse-input: mousedown -> mousemove -> mouseup + * + * On each recognizing cycle (see Manager.recognize) the .recognize() method is executed + * which determines with state it should be. + * + * If the recognizer has the state FAILED, CANCELLED or RECOGNIZED (equals ENDED), it is reset to + * POSSIBLE to give it another change on the next cycle. + * + * Possible + * | + * +-----+---------------+ + * | | + * +-----+-----+ | + * | | | + * Failed Cancelled | + * +-------+------+ + * | | + * Recognized Began + * | + * Changed + * | + * Ended/Recognized + */ + +/** + * Recognizer + * Every recognizer needs to extend from this class. + * @constructor + * @param {Object} options + */ +function Recognizer(options) { + this.options = assign({}, this.defaults, options || {}); + + this.id = uniqueId(); + + this.manager = null; + + // default is enable true + this.options.enable = ifUndefined(this.options.enable, true); + + this.state = STATE_POSSIBLE; + + this.simultaneous = {}; + this.requireFail = []; +} + +Recognizer.prototype = { + /** + * @virtual + * @type {Object} + */ + defaults: {}, + + /** + * set options + * @param {Object} options + * @return {Recognizer} + */ + set: function set(options) { + assign(this.options, options); + + // also update the touchAction, in case something changed about the directions/enabled state + this.manager && this.manager.touchAction.update(); + return this; + }, + + /** + * recognize simultaneous with an other recognizer. + * @param {Recognizer} otherRecognizer + * @returns {Recognizer} this + */ + recognizeWith: function recognizeWith(otherRecognizer) { + if (invokeArrayArg(otherRecognizer, 'recognizeWith', this)) { + return this; + } + + var simultaneous = this.simultaneous; + otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this); + if (!simultaneous[otherRecognizer.id]) { + simultaneous[otherRecognizer.id] = otherRecognizer; + otherRecognizer.recognizeWith(this); + } + return this; + }, + + /** + * drop the simultaneous link. it doesnt remove the link on the other recognizer. + * @param {Recognizer} otherRecognizer + * @returns {Recognizer} this + */ + dropRecognizeWith: function dropRecognizeWith(otherRecognizer) { + if (invokeArrayArg(otherRecognizer, 'dropRecognizeWith', this)) { + return this; + } + + otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this); + delete this.simultaneous[otherRecognizer.id]; + return this; + }, + + /** + * recognizer can only run when an other is failing + * @param {Recognizer} otherRecognizer + * @returns {Recognizer} this + */ + requireFailure: function requireFailure(otherRecognizer) { + if (invokeArrayArg(otherRecognizer, 'requireFailure', this)) { + return this; + } + + var requireFail = this.requireFail; + otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this); + if (inArray(requireFail, otherRecognizer) === -1) { + requireFail.push(otherRecognizer); + otherRecognizer.requireFailure(this); + } + return this; + }, + + /** + * drop the requireFailure link. it does not remove the link on the other recognizer. + * @param {Recognizer} otherRecognizer + * @returns {Recognizer} this + */ + dropRequireFailure: function dropRequireFailure(otherRecognizer) { + if (invokeArrayArg(otherRecognizer, 'dropRequireFailure', this)) { + return this; + } + + otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this); + var index = inArray(this.requireFail, otherRecognizer); + if (index > -1) { + this.requireFail.splice(index, 1); + } + return this; + }, + + /** + * has require failures boolean + * @returns {boolean} + */ + hasRequireFailures: function hasRequireFailures() { + return this.requireFail.length > 0; + }, + + /** + * if the recognizer can recognize simultaneous with an other recognizer + * @param {Recognizer} otherRecognizer + * @returns {Boolean} + */ + canRecognizeWith: function canRecognizeWith(otherRecognizer) { + return !!this.simultaneous[otherRecognizer.id]; + }, + + /** + * You should use `tryEmit` instead of `emit` directly to check + * that all the needed recognizers has failed before emitting. + * @param {Object} input + */ + emit: function emit(input) { + var self = this; + var state = this.state; + + function emit(event) { + self.manager.emit(event, input); + } + + // 'panstart' and 'panmove' + if (state < STATE_ENDED) { + emit(self.options.event + stateStr(state)); + } + + emit(self.options.event); // simple 'eventName' events + + if (input.additionalEvent) { + // additional event(panleft, panright, pinchin, pinchout...) + emit(input.additionalEvent); + } + + // panend and pancancel + if (state >= STATE_ENDED) { + emit(self.options.event + stateStr(state)); + } + }, + + /** + * Check that all the require failure recognizers has failed, + * if true, it emits a gesture event, + * otherwise, setup the state to FAILED. + * @param {Object} input + */ + tryEmit: function tryEmit(input) { + if (this.canEmit()) { + return this.emit(input); + } + // it's failing anyway + this.state = STATE_FAILED; + }, + + /** + * can we emit? + * @returns {boolean} + */ + canEmit: function canEmit() { + var i = 0; + while (i < this.requireFail.length) { + if (!(this.requireFail[i].state & (STATE_FAILED | STATE_POSSIBLE))) { + return false; + } + i++; + } + return true; + }, + + /** + * update the recognizer + * @param {Object} inputData + */ + recognize: function recognize(inputData) { + // make a new copy of the inputData + // so we can change the inputData without messing up the other recognizers + var inputDataClone = assign({}, inputData); + + // is is enabled and allow recognizing? + if (!boolOrFn(this.options.enable, [this, inputDataClone])) { + this.reset(); + this.state = STATE_FAILED; + return; + } + + // reset when we've reached the end + if (this.state & (STATE_RECOGNIZED | STATE_CANCELLED | STATE_FAILED)) { + this.state = STATE_POSSIBLE; + } + + this.state = this.process(inputDataClone); + + // the recognizer has recognized a gesture + // so trigger an event + if (this.state & (STATE_BEGAN | STATE_CHANGED | STATE_ENDED | STATE_CANCELLED)) { + this.tryEmit(inputDataClone); + } + }, + + /** + * return the state of the recognizer + * the actual recognizing happens in this method + * @virtual + * @param {Object} inputData + * @returns {constant} STATE + */ + process: function process(inputData) {}, // jshint ignore:line + + /** + * return the preferred touch-action + * @virtual + * @returns {Array} + */ + getTouchAction: function getTouchAction() {}, + + /** + * called when the gesture isn't allowed to recognize + * like when another is being recognized or it is disabled + * @virtual + */ + reset: function reset() {} +}; + +/** + * This recognizer is just used as a base for the simple attribute recognizers. + * @constructor + * @extends Recognizer + */ +function AttrRecognizer() { + Recognizer.apply(this, arguments); +} + +inherit(AttrRecognizer, Recognizer, { + /** + * @namespace + * @memberof AttrRecognizer + */ + defaults: { + /** + * @type {Number} + * @default 1 + */ + pointers: 1 + }, + + /** + * Used to check if it the recognizer receives valid input, like input.distance > 10. + * @memberof AttrRecognizer + * @param {Object} input + * @returns {Boolean} recognized + */ + attrTest: function attrTest(input) { + var optionPointers = this.options.pointers; + return optionPointers === 0 || input.pointers.length === optionPointers; + }, + + /** + * Process the input and return the state for the recognizer + * @memberof AttrRecognizer + * @param {Object} input + * @returns {*} State + */ + process: function process(input) { + var state = this.state; + var eventType = input.eventType; + + var isRecognized = state & (STATE_BEGAN | STATE_CHANGED); + var isValid = this.attrTest(input); + + // on cancel input and we've recognized before, return STATE_CANCELLED + if (isRecognized && (eventType & INPUT_CANCEL || !isValid)) { + return state | STATE_CANCELLED; + } else if (isRecognized || isValid) { + if (eventType & INPUT_END) { + return state | STATE_ENDED; + } else if (!(state & STATE_BEGAN)) { + return STATE_BEGAN; + } + return state | STATE_CHANGED; + } + return STATE_FAILED; + } +}); + +/** + * Rotate + * Recognized when two or more pointer are moving in a circular motion. + * @constructor + * @extends AttrRecognizer + */ +function RotateRecognizer() { + AttrRecognizer.apply(this, arguments); +} + +inherit(RotateRecognizer, AttrRecognizer, { + /** + * @namespace + * @memberof RotateRecognizer + */ + defaults: { + event: 'rotate', + threshold: 0, + pointers: 2 + }, + + getTouchAction: function getTouchAction() { + return [TOUCH_ACTION_NONE]; + }, + + attrTest: function attrTest(input) { + return this._super.attrTest.call(this, input) && (Math.abs(input.rotation) > this.options.threshold || this.state & STATE_BEGAN); + } +}); + +/** + * Pinch + * Recognized when two or more pointers are moving toward (zoom-in) or away from each other (zoom-out). + * @constructor + * @extends AttrRecognizer + */ +function PinchRecognizer() { + AttrRecognizer.apply(this, arguments); +} + +inherit(PinchRecognizer, AttrRecognizer, { + /** + * @namespace + * @memberof PinchRecognizer + */ + defaults: { + event: 'pinch', + threshold: 0, + pointers: 2 + }, + + getTouchAction: function getTouchAction() { + return [TOUCH_ACTION_NONE]; + }, + + attrTest: function attrTest(input) { + return this._super.attrTest.call(this, input) && (Math.abs(input.scale - 1) > this.options.threshold || this.state & STATE_BEGAN); + }, + + emit: function emit(input) { + if (input.scale !== 1) { + var inOut = input.scale < 1 ? 'in' : 'out'; + input.additionalEvent = this.options.event + inOut; + } + this._super.emit.call(this, input); + } +}); + +/** + * direction cons to string + * @param {constant} direction + * @returns {String} + */ +function directionStr(direction) { + if (direction == DIRECTION_DOWN) { + return 'down'; + } else if (direction == DIRECTION_UP) { + return 'up'; + } else if (direction == DIRECTION_LEFT) { + return 'left'; + } else if (direction == DIRECTION_RIGHT) { + return 'right'; + } + return ''; +} + +/** + * Pan + * Recognized when the pointer is down and moved in the allowed direction. + * @constructor + * @extends AttrRecognizer + */ +function PanRecognizer() { + AttrRecognizer.apply(this, arguments); + + this.pX = null; + this.pY = null; +} + +inherit(PanRecognizer, AttrRecognizer, { + /** + * @namespace + * @memberof PanRecognizer + */ + defaults: { + event: 'pan', + threshold: 10, + pointers: 1, + direction: DIRECTION_ALL + }, + + getTouchAction: function getTouchAction() { + var direction = this.options.direction; + var actions = []; + if (direction & DIRECTION_HORIZONTAL) { + actions.push(TOUCH_ACTION_PAN_Y); + } + if (direction & DIRECTION_VERTICAL) { + actions.push(TOUCH_ACTION_PAN_X); + } + return actions; + }, + + directionTest: function directionTest(input) { + var options = this.options; + var hasMoved = true; + var distance = input.distance; + var direction = input.direction; + var x = input.deltaX; + var y = input.deltaY; + + // lock to axis? + if (!(direction & options.direction)) { + if (options.direction & DIRECTION_HORIZONTAL) { + direction = x === 0 ? DIRECTION_NONE : x < 0 ? DIRECTION_LEFT : DIRECTION_RIGHT; + hasMoved = x != this.pX; + distance = Math.abs(input.deltaX); + } else { + direction = y === 0 ? DIRECTION_NONE : y < 0 ? DIRECTION_UP : DIRECTION_DOWN; + hasMoved = y != this.pY; + distance = Math.abs(input.deltaY); + } + } + input.direction = direction; + return hasMoved && distance > options.threshold && direction & options.direction; + }, + + attrTest: function attrTest(input) { + return AttrRecognizer.prototype.attrTest.call(this, input) && (this.state & STATE_BEGAN || !(this.state & STATE_BEGAN) && this.directionTest(input)); + }, + + emit: function emit(input) { + + this.pX = input.deltaX; + this.pY = input.deltaY; + + var direction = directionStr(input.direction); + + if (direction) { + input.additionalEvent = this.options.event + direction; + } + this._super.emit.call(this, input); + } +}); + +/** + * Swipe + * Recognized when the pointer is moving fast (velocity), with enough distance in the allowed direction. + * @constructor + * @extends AttrRecognizer + */ +function SwipeRecognizer() { + AttrRecognizer.apply(this, arguments); +} + +inherit(SwipeRecognizer, AttrRecognizer, { + /** + * @namespace + * @memberof SwipeRecognizer + */ + defaults: { + event: 'swipe', + threshold: 10, + velocity: 0.3, + direction: DIRECTION_HORIZONTAL | DIRECTION_VERTICAL, + pointers: 1 + }, + + getTouchAction: function getTouchAction() { + return PanRecognizer.prototype.getTouchAction.call(this); + }, + + attrTest: function attrTest(input) { + var direction = this.options.direction; + var velocity; + + if (direction & (DIRECTION_HORIZONTAL | DIRECTION_VERTICAL)) { + velocity = input.overallVelocity; + } else if (direction & DIRECTION_HORIZONTAL) { + velocity = input.overallVelocityX; + } else if (direction & DIRECTION_VERTICAL) { + velocity = input.overallVelocityY; + } + + return this._super.attrTest.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; + }, + + emit: function emit(input) { + var direction = directionStr(input.offsetDirection); + if (direction) { + this.manager.emit(this.options.event + direction, input); + } + + this.manager.emit(this.options.event, input); + } +}); + +/** + * simple function bind + * @param {Function} fn + * @param {Object} context + * @returns {Function} + */ +function bindFn(fn, context) { + return function boundFn() { + return fn.apply(context, arguments); + }; +} + +/** + * set a timeout with a given scope + * @param {Function} fn + * @param {Number} timeout + * @param {Object} context + * @returns {number} + */ +function setTimeoutContext(fn, timeout, context) { + return setTimeout(bindFn(fn, context), timeout); +} + +/** + * calculate the absolute distance between two points + * @param {Object} p1 {x, y} + * @param {Object} p2 {x, y} + * @param {Array} [props] containing x and y keys + * @return {Number} distance + */ +function getDistance(p1, p2, props) { + if (!props) { + props = PROPS_XY; + } + var x = p2[props[0]] - p1[props[0]], + y = p2[props[1]] - p1[props[1]]; + + return Math.sqrt(x * x + y * y); +} + +/** + * A tap is recognized when the pointer is doing a small tap/click. Multiple taps are recognized if they occur + * between the given interval and position. The delay option can be used to recognize multi-taps without firing + * a single tap. + * + * The eventData from the emitted event contains the property `tapCount`, which contains the amount of + * multi-taps being recognized. + * @constructor + * @extends Recognizer + */ +function TapRecognizer() { + Recognizer.apply(this, arguments); + + // previous time and center, + // used for tap counting + this.pTime = false; + this.pCenter = false; + + this._timer = null; + this._input = null; + this.count = 0; +} + +inherit(TapRecognizer, Recognizer, { + /** + * @namespace + * @memberof PinchRecognizer + */ + defaults: { + event: 'tap', + pointers: 1, + taps: 1, + interval: 300, // max time between the multi-tap taps + time: 250, // max time of the pointer to be down (like finger on the screen) + threshold: 9, // a minimal movement is ok, but keep it low + posThreshold: 10 // a multi-tap can be a bit off the initial position + }, + + getTouchAction: function getTouchAction() { + return [TOUCH_ACTION_MANIPULATION]; + }, + + process: function process(input) { + var options = this.options; + + var validPointers = input.pointers.length === options.pointers; + var validMovement = input.distance < options.threshold; + var validTouchTime = input.deltaTime < options.time; + + this.reset(); + + if (input.eventType & INPUT_START && this.count === 0) { + return this.failTimeout(); + } + + // we only allow little movement + // and we've reached an end event, so a tap is possible + if (validMovement && validTouchTime && validPointers) { + if (input.eventType != INPUT_END) { + return this.failTimeout(); + } + + var validInterval = this.pTime ? input.timeStamp - this.pTime < options.interval : true; + var validMultiTap = !this.pCenter || getDistance(this.pCenter, input.center) < options.posThreshold; + + this.pTime = input.timeStamp; + this.pCenter = input.center; + + if (!validMultiTap || !validInterval) { + this.count = 1; + } else { + this.count += 1; + } + + this._input = input; + + // if tap count matches we have recognized it, + // else it has began recognizing... + var tapCount = this.count % options.taps; + if (tapCount === 0) { + // no failing requirements, immediately trigger the tap event + // or wait as long as the multitap interval to trigger + if (!this.hasRequireFailures()) { + return STATE_RECOGNIZED; + } else { + this._timer = setTimeoutContext(function () { + this.state = STATE_RECOGNIZED; + this.tryEmit(); + }, options.interval, this); + return STATE_BEGAN; + } + } + } + return STATE_FAILED; + }, + + failTimeout: function failTimeout() { + this._timer = setTimeoutContext(function () { + this.state = STATE_FAILED; + }, this.options.interval, this); + return STATE_FAILED; + }, + + reset: function reset() { + clearTimeout(this._timer); + }, + + emit: function emit() { + if (this.state == STATE_RECOGNIZED) { + this._input.tapCount = this.count; + this.manager.emit(this.options.event, this._input); + } + } +}); + +/** + * Press + * Recognized when the pointer is down for x ms without any movement. + * @constructor + * @extends Recognizer + */ +function PressRecognizer() { + Recognizer.apply(this, arguments); + + this._timer = null; + this._input = null; +} + +inherit(PressRecognizer, Recognizer, { + /** + * @namespace + * @memberof PressRecognizer + */ + defaults: { + event: 'press', + pointers: 1, + time: 251, // minimal time of the pointer to be pressed + threshold: 9 // a minimal movement is ok, but keep it low + }, + + getTouchAction: function getTouchAction() { + return [TOUCH_ACTION_AUTO]; + }, + + process: function process(input) { + var options = this.options; + var validPointers = input.pointers.length === options.pointers; + var validMovement = input.distance < options.threshold; + var validTime = input.deltaTime > options.time; + + this._input = input; + + // we only allow little movement + // and we've reached an end event, so a tap is possible + if (!validMovement || !validPointers || input.eventType & (INPUT_END | INPUT_CANCEL) && !validTime) { + this.reset(); + } else if (input.eventType & INPUT_START) { + this.reset(); + this._timer = setTimeoutContext(function () { + this.state = STATE_RECOGNIZED; + this.tryEmit(); + }, options.time, this); + } else if (input.eventType & INPUT_END) { + return STATE_RECOGNIZED; + } + return STATE_FAILED; + }, + + reset: function reset() { + clearTimeout(this._timer); + }, + + emit: function emit(input) { + if (this.state !== STATE_RECOGNIZED) { + return; + } + + if (input && input.eventType & INPUT_END) { + this.manager.emit(this.options.event + 'up', input); + } else { + this._input.timeStamp = now(); + this.manager.emit(this.options.event, this._input); + } + } +}); + +/** + * small indexOf wrapper + * @param {String} str + * @param {String} find + * @returns {Boolean} found + */ +function inStr(str, find) { + return str.indexOf(find) > -1; +} + +/** + * when the touchActions are collected they are not a valid value, so we need to clean things up. * + * @param {String} actions + * @returns {*} + */ +function cleanTouchActions(actions) { + // none + if (inStr(actions, TOUCH_ACTION_NONE)) { + return TOUCH_ACTION_NONE; + } + + var hasPanX = inStr(actions, TOUCH_ACTION_PAN_X); + var hasPanY = inStr(actions, TOUCH_ACTION_PAN_Y); + + // if both pan-x and pan-y are set (different recognizers + // for different directions, e.g. horizontal pan but vertical swipe?) + // we need none (as otherwise with pan-x pan-y combined none of these + // recognizers will work, since the browser would handle all panning + if (hasPanX && hasPanY) { + return TOUCH_ACTION_NONE; + } + + // pan-x OR pan-y + if (hasPanX || hasPanY) { + return hasPanX ? TOUCH_ACTION_PAN_X : TOUCH_ACTION_PAN_Y; + } + + // manipulation + if (inStr(actions, TOUCH_ACTION_MANIPULATION)) { + return TOUCH_ACTION_MANIPULATION; + } + + return TOUCH_ACTION_AUTO; +} + +/** + * Touch Action + * sets the touchAction property or uses the js alternative + * @param {Manager} manager + * @param {String} value + * @constructor + */ +function TouchAction(manager, value) { + this.manager = manager; + this.set(value); +} + +TouchAction.prototype = { + /** + * set the touchAction value on the element or enable the polyfill + * @param {String} value + */ + set: function set(value) { + // find out the touch-action by the event handlers + if (value == TOUCH_ACTION_COMPUTE) { + value = this.compute(); + } + + if (NATIVE_TOUCH_ACTION && this.manager.element.style && TOUCH_ACTION_MAP[value]) { + this.manager.element.style[PREFIXED_TOUCH_ACTION] = value; + } + this.actions = value.toLowerCase().trim(); + }, + + /** + * just re-set the touchAction value + */ + update: function update() { + this.set(this.manager.options.touchAction); + }, + + /** + * compute the value for the touchAction property based on the recognizer's settings + * @returns {String} value + */ + compute: function compute() { + var actions = []; + each(this.manager.recognizers, function (recognizer) { + if (boolOrFn(recognizer.options.enable, [recognizer])) { + actions = actions.concat(recognizer.getTouchAction()); + } + }); + return cleanTouchActions(actions.join(' ')); + }, + + /** + * this method is called on each input cycle and provides the preventing of the browser behavior + * @param {Object} input + */ + preventDefaults: function preventDefaults(input) { + var srcEvent = input.srcEvent; + var direction = input.offsetDirection; + + // if the touch action did prevented once this session + if (this.manager.session.prevented) { + srcEvent.preventDefault(); + return; + } + + var actions = this.actions; + var hasNone = inStr(actions, TOUCH_ACTION_NONE) && !TOUCH_ACTION_MAP[TOUCH_ACTION_NONE]; + var hasPanY = inStr(actions, TOUCH_ACTION_PAN_Y) && !TOUCH_ACTION_MAP[TOUCH_ACTION_PAN_Y]; + var hasPanX = inStr(actions, TOUCH_ACTION_PAN_X) && !TOUCH_ACTION_MAP[TOUCH_ACTION_PAN_X]; + + if (hasNone) { + //do not prevent defaults if this is a tap gesture + + var isTapPointer = input.pointers.length === 1; + var isTapMovement = input.distance < 2; + var isTapTouchTime = input.deltaTime < 250; + + if (isTapPointer && isTapMovement && isTapTouchTime) { + return; + } + } + + if (hasPanX && hasPanY) { + // `pan-x pan-y` means browser handles all scrolling/panning, do not prevent + return; + } + + if (hasNone || hasPanY && direction & DIRECTION_HORIZONTAL || hasPanX && direction & DIRECTION_VERTICAL) { + return this.preventSrc(srcEvent); + } + }, + + /** + * call preventDefault to prevent the browser's default behavior (scrolling in most cases) + * @param {Object} srcEvent + */ + preventSrc: function preventSrc(srcEvent) { + this.manager.session.prevented = true; + srcEvent.preventDefault(); + } +}; + +/** + * find if a node is in the given parent + * @method hasParent + * @param {HTMLElement} node + * @param {HTMLElement} parent + * @return {Boolean} found + */ +function hasParent(node, parent) { + while (node) { + if (node == parent) { + return true; + } + node = node.parentNode; + } + return false; +} + +/** + * get the center of all the pointers + * @param {Array} pointers + * @return {Object} center contains `x` and `y` properties + */ +function getCenter(pointers) { + var pointersLength = pointers.length; + + // no need to loop when only one touch + if (pointersLength === 1) { + return { + x: round(pointers[0].clientX), + y: round(pointers[0].clientY) + }; + } + + var x = 0, + y = 0, + i = 0; + while (i < pointersLength) { + x += pointers[i].clientX; + y += pointers[i].clientY; + i++; + } + + return { + x: round(x / pointersLength), + y: round(y / pointersLength) + }; +} + +/** + * create a simple clone from the input used for storage of firstInput and firstMultiple + * @param {Object} input + * @returns {Object} clonedInputData + */ +function simpleCloneInputData(input) { + // make a simple copy of the pointers because we will get a reference if we don't + // we only need clientXY for the calculations + var pointers = []; + var i = 0; + while (i < input.pointers.length) { + pointers[i] = { + clientX: round(input.pointers[i].clientX), + clientY: round(input.pointers[i].clientY) + }; + i++; + } + + return { + timeStamp: now(), + pointers: pointers, + center: getCenter(pointers), + deltaX: input.deltaX, + deltaY: input.deltaY + }; +} + +/** + * calculate the angle between two coordinates + * @param {Object} p1 + * @param {Object} p2 + * @param {Array} [props] containing x and y keys + * @return {Number} angle + */ +function getAngle(p1, p2, props) { + if (!props) { + props = PROPS_XY; + } + var x = p2[props[0]] - p1[props[0]], + y = p2[props[1]] - p1[props[1]]; + return Math.atan2(y, x) * 180 / Math.PI; +} + +/** + * get the direction between two points + * @param {Number} x + * @param {Number} y + * @return {Number} direction + */ +function getDirection(x, y) { + if (x === y) { + return DIRECTION_NONE; + } + + if (abs(x) >= abs(y)) { + return x < 0 ? DIRECTION_LEFT : DIRECTION_RIGHT; + } + return y < 0 ? DIRECTION_UP : DIRECTION_DOWN; +} + +function computeDeltaXY(session, input) { + var center = input.center; + var offset = session.offsetDelta || {}; + var prevDelta = session.prevDelta || {}; + var prevInput = session.prevInput || {}; + + if (input.eventType === INPUT_START || prevInput.eventType === INPUT_END) { + prevDelta = session.prevDelta = { + x: prevInput.deltaX || 0, + y: prevInput.deltaY || 0 + }; + + offset = session.offsetDelta = { + x: center.x, + y: center.y + }; + } + + input.deltaX = prevDelta.x + (center.x - offset.x); + input.deltaY = prevDelta.y + (center.y - offset.y); +} + +/** + * calculate the velocity between two points. unit is in px per ms. + * @param {Number} deltaTime + * @param {Number} x + * @param {Number} y + * @return {Object} velocity `x` and `y` + */ +function getVelocity(deltaTime, x, y) { + return { + x: x / deltaTime || 0, + y: y / deltaTime || 0 + }; +} + +/** + * calculate the scale factor between two pointersets + * no scale is 1, and goes down to 0 when pinched together, and bigger when pinched out + * @param {Array} start array of pointers + * @param {Array} end array of pointers + * @return {Number} scale + */ +function getScale(start, end) { + return getDistance(end[0], end[1], PROPS_CLIENT_XY) / getDistance(start[0], start[1], PROPS_CLIENT_XY); +} + +/** + * calculate the rotation degrees between two pointersets + * @param {Array} start array of pointers + * @param {Array} end array of pointers + * @return {Number} rotation + */ +function getRotation(start, end) { + return getAngle(end[1], end[0], PROPS_CLIENT_XY) + getAngle(start[1], start[0], PROPS_CLIENT_XY); +} + +/** + * velocity is calculated every x ms + * @param {Object} session + * @param {Object} input + */ +function computeIntervalInputData(session, input) { + var last = session.lastInterval || input, + deltaTime = input.timeStamp - last.timeStamp, + velocity, + velocityX, + velocityY, + direction; + + if (input.eventType != INPUT_CANCEL && (deltaTime > COMPUTE_INTERVAL || last.velocity === undefined)) { + var deltaX = input.deltaX - last.deltaX; + var deltaY = input.deltaY - last.deltaY; + + var v = getVelocity(deltaTime, deltaX, deltaY); + velocityX = v.x; + velocityY = v.y; + velocity = abs(v.x) > abs(v.y) ? v.x : v.y; + direction = getDirection(deltaX, deltaY); + + session.lastInterval = input; + } else { + // use latest velocity info if it doesn't overtake a minimum period + velocity = last.velocity; + velocityX = last.velocityX; + velocityY = last.velocityY; + direction = last.direction; + } + + input.velocity = velocity; + input.velocityX = velocityX; + input.velocityY = velocityY; + input.direction = direction; +} + +/** + * extend the data with some usable properties like scale, rotate, velocity etc + * @param {Object} manager + * @param {Object} input + */ +function computeInputData(manager, input) { + var session = manager.session; + var pointers = input.pointers; + var pointersLength = pointers.length; + + // store the first input to calculate the distance and direction + if (!session.firstInput) { + session.firstInput = simpleCloneInputData(input); + } + + // to compute scale and rotation we need to store the multiple touches + if (pointersLength > 1 && !session.firstMultiple) { + session.firstMultiple = simpleCloneInputData(input); + } else if (pointersLength === 1) { + session.firstMultiple = false; + } + + var firstInput = session.firstInput; + var firstMultiple = session.firstMultiple; + var offsetCenter = firstMultiple ? firstMultiple.center : firstInput.center; + + var center = input.center = getCenter(pointers); + input.timeStamp = now(); + input.deltaTime = input.timeStamp - firstInput.timeStamp; + + input.angle = getAngle(offsetCenter, center); + input.distance = getDistance(offsetCenter, center); + + computeDeltaXY(session, input); + input.offsetDirection = getDirection(input.deltaX, input.deltaY); + + var overallVelocity = getVelocity(input.deltaTime, input.deltaX, input.deltaY); + input.overallVelocityX = overallVelocity.x; + input.overallVelocityY = overallVelocity.y; + input.overallVelocity = abs(overallVelocity.x) > abs(overallVelocity.y) ? overallVelocity.x : overallVelocity.y; + + input.scale = firstMultiple ? getScale(firstMultiple.pointers, pointers) : 1; + input.rotation = firstMultiple ? getRotation(firstMultiple.pointers, pointers) : 0; + + input.maxPointers = !session.prevInput ? input.pointers.length : input.pointers.length > session.prevInput.maxPointers ? input.pointers.length : session.prevInput.maxPointers; + + computeIntervalInputData(session, input); + + // find the correct target + var target = manager.element; + if (hasParent(input.srcEvent.target, target)) { + target = input.srcEvent.target; + } + input.target = target; +} + +/** + * handle input events + * @param {Manager} manager + * @param {String} eventType + * @param {Object} input + */ +function inputHandler(manager, eventType, input) { + var pointersLen = input.pointers.length; + var changedPointersLen = input.changedPointers.length; + var isFirst = eventType & INPUT_START && pointersLen - changedPointersLen === 0; + var isFinal = eventType & (INPUT_END | INPUT_CANCEL) && pointersLen - changedPointersLen === 0; + + input.isFirst = !!isFirst; + input.isFinal = !!isFinal; + + if (isFirst) { + manager.session = {}; + } + + // source event is the normalized value of the domEvents + // like 'touchstart, mouseup, pointerdown' + input.eventType = eventType; + + // compute scale, rotation etc + computeInputData(manager, input); + + // emit secret event + manager.emit('hammer.input', input); + + manager.recognize(input); + manager.session.prevInput = input; +} + +/** + * split string on whitespace + * @param {String} str + * @returns {Array} words + */ + +function splitStr(str) { + return str.trim().split(/\s+/g); +} + +/** + * addEventListener with multiple events at once + * @param {EventTarget} target + * @param {String} types + * @param {Function} handler + */ +function addEventListeners(target, types, handler) { + each(splitStr(types), function (type) { + target.addEventListener(type, handler, false); + }); +} + +/** + * removeEventListener with multiple events at once + * @param {EventTarget} target + * @param {String} types + * @param {Function} handler + */ +function removeEventListeners(target, types, handler) { + each(splitStr(types), function (type) { + target.removeEventListener(type, handler, false); + }); +} + +/** + * get the window object of an element + * @param {HTMLElement} element + * @returns {DocumentView|Window} + */ +function getWindowForElement(element) { + var doc = element.ownerDocument || element; + return doc.defaultView || doc.parentWindow || window; +} + +/** + * create new input type manager + * @param {Manager} manager + * @param {Function} callback + * @returns {Input} + * @constructor + */ +function Input(manager, callback) { + var self = this; + this.manager = manager; + this.callback = callback; + this.element = manager.element; + this.target = manager.options.inputTarget; + + // smaller wrapper around the handler, for the scope and the enabled state of the manager, + // so when disabled the input events are completely bypassed. + this.domHandler = function (ev) { + if (boolOrFn(manager.options.enable, [manager])) { + self.handler(ev); + } + }; + + this.init(); +} + +Input.prototype = { + /** + * should handle the inputEvent data and trigger the callback + * @virtual + */ + handler: function handler() {}, + + /** + * bind the events + */ + init: function init() { + this.evEl && addEventListeners(this.element, this.evEl, this.domHandler); + this.evTarget && addEventListeners(this.target, this.evTarget, this.domHandler); + this.evWin && addEventListeners(getWindowForElement(this.element), this.evWin, this.domHandler); + }, + + /** + * unbind the events + */ + destroy: function destroy() { + this.evEl && removeEventListeners(this.element, this.evEl, this.domHandler); + this.evTarget && removeEventListeners(this.target, this.evTarget, this.domHandler); + this.evWin && removeEventListeners(getWindowForElement(this.element), this.evWin, this.domHandler); + } +}; + +var POINTER_INPUT_MAP = { + pointerdown: INPUT_START, + pointermove: INPUT_MOVE, + pointerup: INPUT_END, + pointercancel: INPUT_CANCEL, + pointerout: INPUT_CANCEL +}; + +// in IE10 the pointer types is defined as an enum +var IE10_POINTER_TYPE_ENUM = { + 2: INPUT_TYPE_TOUCH, + 3: INPUT_TYPE_PEN, + 4: INPUT_TYPE_MOUSE, + 5: INPUT_TYPE_KINECT // see https://twitter.com/jacobrossi/status/480596438489890816 +}; + +var POINTER_ELEMENT_EVENTS = 'pointerdown'; +var POINTER_WINDOW_EVENTS = 'pointermove pointerup pointercancel'; + +// IE10 has prefixed support, and case-sensitive +if (window.MSPointerEvent && !window.PointerEvent) { + POINTER_ELEMENT_EVENTS = 'MSPointerDown'; + POINTER_WINDOW_EVENTS = 'MSPointerMove MSPointerUp MSPointerCancel'; +} + +/** + * Pointer events input + * @constructor + * @extends Input + */ +function PointerEventInput() { + this.evEl = POINTER_ELEMENT_EVENTS; + this.evWin = POINTER_WINDOW_EVENTS; + + Input.apply(this, arguments); + + this.store = this.manager.session.pointerEvents = []; +} + +inherit(PointerEventInput, Input, { + /** + * handle mouse events + * @param {Object} ev + */ + handler: function PEhandler(ev) { + var store = this.store; + var removePointer = false; + + var eventTypeNormalized = ev.type.toLowerCase().replace('ms', ''); + var eventType = POINTER_INPUT_MAP[eventTypeNormalized]; + var pointerType = IE10_POINTER_TYPE_ENUM[ev.pointerType] || ev.pointerType; + + var isTouch = pointerType == INPUT_TYPE_TOUCH; + + // get index of the event in the store + var storeIndex = inArray(store, ev.pointerId, 'pointerId'); + + // start and mouse must be down + if (eventType & INPUT_START && (ev.button === 0 || isTouch)) { + if (storeIndex < 0) { + store.push(ev); + storeIndex = store.length - 1; + } + } else if (eventType & (INPUT_END | INPUT_CANCEL)) { + removePointer = true; + } + + // it not found, so the pointer hasn't been down (so it's probably a hover) + if (storeIndex < 0) { + return; + } + + // update the event in the store + store[storeIndex] = ev; + + this.callback(this.manager, eventType, { + pointers: store, + changedPointers: [ev], + pointerType: pointerType, + srcEvent: ev + }); + + if (removePointer) { + // remove from the store + store.splice(storeIndex, 1); + } + } +}); + +/** + * convert array-like objects to real arrays + * @param {Object} obj + * @returns {Array} + */ +function toArray(obj) { + return Array.prototype.slice.call(obj, 0); +} + +/** + * unique array with objects based on a key (like 'id') or just by the array's value + * @param {Array} src [{id:1},{id:2},{id:1}] + * @param {String} [key] + * @param {Boolean} [sort=False] + * @returns {Array} [{id:1},{id:2}] + */ +function uniqueArray(src, key, sort) { + var results = []; + var values = []; + var i = 0; + + while (i < src.length) { + var val = key ? src[i][key] : src[i]; + if (inArray(values, val) < 0) { + results.push(src[i]); + } + values[i] = val; + i++; + } + + if (sort) { + if (!key) { + results = results.sort(); + } else { + results = results.sort(function sortUniqueArray(a, b) { + return a[key] > b[key]; + }); + } + } + + return results; +} + +var TOUCH_INPUT_MAP = { + touchstart: INPUT_START, + touchmove: INPUT_MOVE, + touchend: INPUT_END, + touchcancel: INPUT_CANCEL +}; + +var TOUCH_TARGET_EVENTS = 'touchstart touchmove touchend touchcancel'; + +/** + * Multi-user touch events input + * @constructor + * @extends Input + */ +function TouchInput() { + this.evTarget = TOUCH_TARGET_EVENTS; + this.targetIds = {}; + + Input.apply(this, arguments); +} + +inherit(TouchInput, Input, { + handler: function MTEhandler(ev) { + var type = TOUCH_INPUT_MAP[ev.type]; + var touches = getTouches.call(this, ev, type); + if (!touches) { + return; + } + + this.callback(this.manager, type, { + pointers: touches[0], + changedPointers: touches[1], + pointerType: INPUT_TYPE_TOUCH, + srcEvent: ev + }); + } +}); + +/** + * @this {TouchInput} + * @param {Object} ev + * @param {Number} type flag + * @returns {undefined|Array} [all, changed] + */ +function getTouches(ev, type) { + var allTouches = toArray(ev.touches); + var targetIds = this.targetIds; + + // when there is only one touch, the process can be simplified + if (type & (INPUT_START | INPUT_MOVE) && allTouches.length === 1) { + targetIds[allTouches[0].identifier] = true; + return [allTouches, allTouches]; + } + + var i, + targetTouches, + changedTouches = toArray(ev.changedTouches), + changedTargetTouches = [], + target = this.target; + + // get target touches from touches + targetTouches = allTouches.filter(function (touch) { + return hasParent(touch.target, target); + }); + + // collect touches + if (type === INPUT_START) { + i = 0; + while (i < targetTouches.length) { + targetIds[targetTouches[i].identifier] = true; + i++; + } + } + + // filter changed touches to only contain touches that exist in the collected target ids + i = 0; + while (i < changedTouches.length) { + if (targetIds[changedTouches[i].identifier]) { + changedTargetTouches.push(changedTouches[i]); + } + + // cleanup removed touches + if (type & (INPUT_END | INPUT_CANCEL)) { + delete targetIds[changedTouches[i].identifier]; + } + i++; + } + + if (!changedTargetTouches.length) { + return; + } + + return [ + // merge targetTouches with changedTargetTouches so it contains ALL touches, including 'end' and 'cancel' + uniqueArray(targetTouches.concat(changedTargetTouches), 'identifier', true), changedTargetTouches]; +} + +var MOUSE_INPUT_MAP = { + mousedown: INPUT_START, + mousemove: INPUT_MOVE, + mouseup: INPUT_END +}; + +var MOUSE_ELEMENT_EVENTS = 'mousedown'; +var MOUSE_WINDOW_EVENTS = 'mousemove mouseup'; + +/** + * Mouse events input + * @constructor + * @extends Input + */ +function MouseInput() { + this.evEl = MOUSE_ELEMENT_EVENTS; + this.evWin = MOUSE_WINDOW_EVENTS; + + this.pressed = false; // mousedown state + + Input.apply(this, arguments); +} + +inherit(MouseInput, Input, { + /** + * handle mouse events + * @param {Object} ev + */ + handler: function MEhandler(ev) { + var eventType = MOUSE_INPUT_MAP[ev.type]; + + // on start we want to have the left mouse button down + if (eventType & INPUT_START && ev.button === 0) { + this.pressed = true; + } + + if (eventType & INPUT_MOVE && ev.which !== 1) { + eventType = INPUT_END; + } + + // mouse must be down + if (!this.pressed) { + return; + } + + if (eventType & INPUT_END) { + this.pressed = false; + } + + this.callback(this.manager, eventType, { + pointers: [ev], + changedPointers: [ev], + pointerType: INPUT_TYPE_MOUSE, + srcEvent: ev + }); + } +}); + +/** + * Combined touch and mouse input + * + * Touch has a higher priority then mouse, and while touching no mouse events are allowed. + * This because touch devices also emit mouse events while doing a touch. + * + * @constructor + * @extends Input + */ + +var DEDUP_TIMEOUT = 2500; +var DEDUP_DISTANCE = 25; + +function TouchMouseInput() { + Input.apply(this, arguments); + + var handler = bindFn(this.handler, this); + this.touch = new TouchInput(this.manager, handler); + this.mouse = new MouseInput(this.manager, handler); + + this.primaryTouch = null; + this.lastTouches = []; +} + +inherit(TouchMouseInput, Input, { + /** + * handle mouse and touch events + * @param {Hammer} manager + * @param {String} inputEvent + * @param {Object} inputData + */ + handler: function TMEhandler(manager, inputEvent, inputData) { + var isTouch = inputData.pointerType == INPUT_TYPE_TOUCH, + isMouse = inputData.pointerType == INPUT_TYPE_MOUSE; + + if (isMouse && inputData.sourceCapabilities && inputData.sourceCapabilities.firesTouchEvents) { + return; + } + + // when we're in a touch event, record touches to de-dupe synthetic mouse event + if (isTouch) { + recordTouches.call(this, inputEvent, inputData); + } else if (isMouse && isSyntheticEvent.call(this, inputData)) { + return; + } + + this.callback(manager, inputEvent, inputData); + }, + + /** + * remove the event listeners + */ + destroy: function destroy() { + this.touch.destroy(); + this.mouse.destroy(); + } +}); + +function recordTouches(eventType, eventData) { + if (eventType & INPUT_START) { + this.primaryTouch = eventData.changedPointers[0].identifier; + setLastTouch.call(this, eventData); + } else if (eventType & (INPUT_END | INPUT_CANCEL)) { + setLastTouch.call(this, eventData); + } +} + +function setLastTouch(eventData) { + var touch = eventData.changedPointers[0]; + + if (touch.identifier === this.primaryTouch) { + var lastTouch = { x: touch.clientX, y: touch.clientY }; + this.lastTouches.push(lastTouch); + var lts = this.lastTouches; + var removeLastTouch = function removeLastTouch() { + var i = lts.indexOf(lastTouch); + if (i > -1) { + lts.splice(i, 1); + } + }; + setTimeout(removeLastTouch, DEDUP_TIMEOUT); + } +} + +function isSyntheticEvent(eventData) { + var x = eventData.srcEvent.clientX, + y = eventData.srcEvent.clientY; + for (var i = 0; i < this.lastTouches.length; i++) { + var t = this.lastTouches[i]; + var dx = Math.abs(x - t.x), + dy = Math.abs(y - t.y); + if (dx <= DEDUP_DISTANCE && dy <= DEDUP_DISTANCE) { + return true; + } + } + return false; +} + +/** + * create new input type manager + * called by the Manager constructor + * @param {Hammer} manager + * @returns {Input} + */ +function createInputInstance(manager) { + var Type; + var inputClass = manager.options.inputClass; + + if (inputClass) { + Type = inputClass; + } else if (SUPPORT_POINTER_EVENTS) { + Type = PointerEventInput; + } else if (SUPPORT_ONLY_TOUCH) { + Type = TouchInput; + } else if (!SUPPORT_TOUCH) { + Type = MouseInput; + } else { + Type = TouchMouseInput; + } + return new Type(manager, inputHandler); +} + +var STOP = 1; +var FORCED_STOP = 2; + +/** + * Manager + * @param {HTMLElement} element + * @param {Object} [options] + * @constructor + */ +function Manager(element, options) { + this.options = assign({}, Hammer.defaults, options || {}); + + this.options.inputTarget = this.options.inputTarget || element; + + this.handlers = {}; + this.session = {}; + this.recognizers = []; + this.oldCssProps = {}; + + this.element = element; + this.input = createInputInstance(this); + this.touchAction = new TouchAction(this, this.options.touchAction); + + toggleCssProps(this, true); + + each(this.options.recognizers, function (item) { + var recognizer = this.add(new item[0](item[1])); + item[2] && recognizer.recognizeWith(item[2]); + item[3] && recognizer.requireFailure(item[3]); + }, this); +} + +Manager.prototype = { + /** + * set options + * @param {Object} options + * @returns {Manager} + */ + set: function set(options) { + assign(this.options, options); + + // Options that need a little more setup + if (options.touchAction) { + this.touchAction.update(); + } + if (options.inputTarget) { + // Clean up existing event listeners and reinitialize + this.input.destroy(); + this.input.target = options.inputTarget; + this.input.init(); + } + return this; + }, + + /** + * stop recognizing for this session. + * This session will be discarded, when a new [input]start event is fired. + * When forced, the recognizer cycle is stopped immediately. + * @param {Boolean} [force] + */ + stop: function stop(force) { + this.session.stopped = force ? FORCED_STOP : STOP; + }, + + /** + * run the recognizers! + * called by the inputHandler function on every movement of the pointers (touches) + * it walks through all the recognizers and tries to detect the gesture that is being made + * @param {Object} inputData + */ + recognize: function recognize(inputData) { + var session = this.session; + if (session.stopped) { + return; + } + + // run the touch-action polyfill + this.touchAction.preventDefaults(inputData); + + var recognizer; + var recognizers = this.recognizers; + + // this holds the recognizer that is being recognized. + // so the recognizer's state needs to be BEGAN, CHANGED, ENDED or RECOGNIZED + // if no recognizer is detecting a thing, it is set to `null` + var curRecognizer = session.curRecognizer; + + // reset when the last recognizer is recognized + // or when we're in a new session + if (!curRecognizer || curRecognizer && curRecognizer.state & STATE_RECOGNIZED) { + curRecognizer = session.curRecognizer = null; + } + + var i = 0; + while (i < recognizers.length) { + recognizer = recognizers[i]; + + // find out if we are allowed try to recognize the input for this one. + // 1. allow if the session is NOT forced stopped (see the .stop() method) + // 2. allow if we still haven't recognized a gesture in this session, or the this recognizer is the one + // that is being recognized. + // 3. allow if the recognizer is allowed to run simultaneous with the current recognized recognizer. + // this can be setup with the `recognizeWith()` method on the recognizer. + if (session.stopped !== FORCED_STOP && ( // 1 + !curRecognizer || recognizer == curRecognizer || // 2 + recognizer.canRecognizeWith(curRecognizer))) { + // 3 + recognizer.recognize(inputData); + } else { + recognizer.reset(); + } + + // if the recognizer has been recognizing the input as a valid gesture, we want to store this one as the + // current active recognizer. but only if we don't already have an active recognizer + if (!curRecognizer && recognizer.state & (STATE_BEGAN | STATE_CHANGED | STATE_ENDED)) { + curRecognizer = session.curRecognizer = recognizer; + } + i++; + } + }, + + /** + * get a recognizer by its event name. + * @param {Recognizer|String} recognizer + * @returns {Recognizer|Null} + */ + get: function get(recognizer) { + if (recognizer instanceof Recognizer) { + return recognizer; + } + + var recognizers = this.recognizers; + for (var i = 0; i < recognizers.length; i++) { + if (recognizers[i].options.event == recognizer) { + return recognizers[i]; + } + } + return null; + }, + + /** + * add a recognizer to the manager + * existing recognizers with the same event name will be removed + * @param {Recognizer} recognizer + * @returns {Recognizer|Manager} + */ + add: function add(recognizer) { + if (invokeArrayArg(recognizer, 'add', this)) { + return this; + } + + // remove existing + var existing = this.get(recognizer.options.event); + if (existing) { + this.remove(existing); + } + + this.recognizers.push(recognizer); + recognizer.manager = this; + + this.touchAction.update(); + return recognizer; + }, + + /** + * remove a recognizer by name or instance + * @param {Recognizer|String} recognizer + * @returns {Manager} + */ + remove: function remove(recognizer) { + if (invokeArrayArg(recognizer, 'remove', this)) { + return this; + } + + recognizer = this.get(recognizer); + + // let's make sure this recognizer exists + if (recognizer) { + var recognizers = this.recognizers; + var index = inArray(recognizers, recognizer); + + if (index !== -1) { + recognizers.splice(index, 1); + this.touchAction.update(); + } + } + + return this; + }, + + /** + * bind event + * @param {String} events + * @param {Function} handler + * @returns {EventEmitter} this + */ + on: function on(events, handler) { + if (events === undefined) { + return; + } + if (handler === undefined) { + return; + } + + var handlers = this.handlers; + each(splitStr(events), function (event) { + handlers[event] = handlers[event] || []; + handlers[event].push(handler); + }); + return this; + }, + + /** + * unbind event, leave emit blank to remove all handlers + * @param {String} events + * @param {Function} [handler] + * @returns {EventEmitter} this + */ + off: function off(events, handler) { + if (events === undefined) { + return; + } + + var handlers = this.handlers; + each(splitStr(events), function (event) { + if (!handler) { + delete handlers[event]; + } else { + handlers[event] && handlers[event].splice(inArray(handlers[event], handler), 1); + } + }); + return this; + }, + + /** + * emit event to the listeners + * @param {String} event + * @param {Object} data + */ + emit: function emit(event, data) { + // we also want to trigger dom events + if (this.options.domEvents) { + triggerDomEvent(event, data); + } + + // no handlers, so skip it all + var handlers = this.handlers[event] && this.handlers[event].slice(); + if (!handlers || !handlers.length) { + return; + } + + data.type = event; + data.preventDefault = function () { + data.srcEvent.preventDefault(); + }; + + var i = 0; + while (i < handlers.length) { + handlers[i](data); + i++; + } + }, + + /** + * destroy the manager and unbinds all events + * it doesn't unbind dom events, that is the user own responsibility + */ + destroy: function destroy() { + this.element && toggleCssProps(this, false); + + this.handlers = {}; + this.session = {}; + this.input.destroy(); + this.element = null; + } +}; + +/** + * add/remove the css properties as defined in manager.options.cssProps + * @param {Manager} manager + * @param {Boolean} add + */ +function toggleCssProps(manager, add) { + var element = manager.element; + if (!element.style) { + return; + } + var prop; + each(manager.options.cssProps, function (value, name) { + prop = prefixed(element.style, name); + if (add) { + manager.oldCssProps[prop] = element.style[prop]; + element.style[prop] = value; + } else { + element.style[prop] = manager.oldCssProps[prop] || ''; + } + }); + if (!add) { + manager.oldCssProps = {}; + } +} + +/** + * trigger dom event + * @param {String} event + * @param {Object} data + */ +function triggerDomEvent(event, data) { + var gestureEvent = document.createEvent('Event'); + gestureEvent.initEvent(event, true, true); + gestureEvent.gesture = data; + data.target.dispatchEvent(gestureEvent); +} + +/** + * Simple way to create a manager with a default set of recognizers. + * @param {HTMLElement} element + * @param {Object} [options] + * @constructor + */ +function Hammer(element, options) { + options = options || {}; + options.recognizers = ifUndefined(options.recognizers, Hammer.defaults.preset); + return new Manager(element, options); +} + +/** + * @const {string} + */ +Hammer.VERSION = '{{PKG_VERSION}}'; + +/** + * default settings + * @namespace + */ +Hammer.defaults = { + /** + * set if DOM events are being triggered. + * But this is slower and unused by simple implementations, so disabled by default. + * @type {Boolean} + * @default false + */ + domEvents: false, + + /** + * The value for the touchAction property/fallback. + * When set to `compute` it will magically set the correct value based on the added recognizers. + * @type {String} + * @default compute + */ + touchAction: TOUCH_ACTION_COMPUTE, + + /** + * @type {Boolean} + * @default true + */ + enable: true, + + /** + * EXPERIMENTAL FEATURE -- can be removed/changed + * Change the parent input target element. + * If Null, then it is being set the to main element. + * @type {Null|EventTarget} + * @default null + */ + inputTarget: null, + + /** + * force an input class + * @type {Null|Function} + * @default null + */ + inputClass: null, + + /** + * Default recognizer setup when calling `Hammer()` + * When creating a new Manager these will be skipped. + * @type {Array} + */ + preset: [ + // RecognizerClass, options, [recognizeWith, ...], [requireFailure, ...] + [RotateRecognizer, { enable: false }], [PinchRecognizer, { enable: false }, ['rotate']], [SwipeRecognizer, { direction: DIRECTION_HORIZONTAL }], [PanRecognizer, { direction: DIRECTION_HORIZONTAL }, ['swipe']], [TapRecognizer], [TapRecognizer, { event: 'doubletap', taps: 2 }, ['tap']], [PressRecognizer]], + + /** + * Some CSS properties can be used to improve the working of Hammer. + * Add them to this method and they will be set when creating a new Manager. + * @namespace + */ + cssProps: { + /** + * Disables text selection to improve the dragging gesture. Mainly for desktop browsers. + * @type {String} + * @default 'none' + */ + userSelect: 'none', + + /** + * Disable the Windows Phone grippers when pressing an element. + * @type {String} + * @default 'none' + */ + touchSelect: 'none', + + /** + * Disables the default callout shown when you touch and hold a touch target. + * On iOS, when you touch and hold a touch target such as a link, Safari displays + * a callout containing information about the link. This property allows you to disable that callout. + * @type {String} + * @default 'none' + */ + touchCallout: 'none', + + /** + * Specifies whether zooming is enabled. Used by IE10> + * @type {String} + * @default 'none' + */ + contentZooming: 'none', + + /** + * Specifies that an entire element should be draggable instead of its contents. Mainly for desktop browsers. + * @type {String} + * @default 'none' + */ + userDrag: 'none', + + /** + * Overrides the highlight color shown when the user taps a link or a JavaScript + * clickable element in iOS. This property obeys the alpha value, if specified. + * @type {String} + * @default 'rgba(0,0,0,0)' + */ + tapHighlightColor: 'rgba(0,0,0,0)' + } +}; + +var SINGLE_TOUCH_INPUT_MAP = { + touchstart: INPUT_START, + touchmove: INPUT_MOVE, + touchend: INPUT_END, + touchcancel: INPUT_CANCEL +}; + +var SINGLE_TOUCH_TARGET_EVENTS = 'touchstart'; +var SINGLE_TOUCH_WINDOW_EVENTS = 'touchstart touchmove touchend touchcancel'; + +/** + * Touch events input + * @constructor + * @extends Input + */ +function SingleTouchInput() { + this.evTarget = SINGLE_TOUCH_TARGET_EVENTS; + this.evWin = SINGLE_TOUCH_WINDOW_EVENTS; + this.started = false; + + Input.apply(this, arguments); +} + +inherit(SingleTouchInput, Input, { + handler: function TEhandler(ev) { + var type = SINGLE_TOUCH_INPUT_MAP[ev.type]; + + // should we handle the touch events? + if (type === INPUT_START) { + this.started = true; + } + + if (!this.started) { + return; + } + + var touches = normalizeSingleTouches.call(this, ev, type); + + // when done, reset the started state + if (type & (INPUT_END | INPUT_CANCEL) && touches[0].length - touches[1].length === 0) { + this.started = false; + } + + this.callback(this.manager, type, { + pointers: touches[0], + changedPointers: touches[1], + pointerType: INPUT_TYPE_TOUCH, + srcEvent: ev + }); + } +}); + +/** + * @this {TouchInput} + * @param {Object} ev + * @param {Number} type flag + * @returns {undefined|Array} [all, changed] + */ +function normalizeSingleTouches(ev, type) { + var all = toArray(ev.touches); + var changed = toArray(ev.changedTouches); + + if (type & (INPUT_END | INPUT_CANCEL)) { + all = uniqueArray(all.concat(changed), 'identifier', true); + } + + return [all, changed]; +} + +/** + * wrap a method with a deprecation warning and stack trace + * @param {Function} method + * @param {String} name + * @param {String} message + * @returns {Function} A new function wrapping the supplied method. + */ +function deprecate(method, name, message) { + var deprecationMessage = 'DEPRECATED METHOD: ' + name + '\n' + message + ' AT \n'; + return function () { + var e = new Error('get-stack-trace'); + var stack = e && e.stack ? e.stack.replace(/^[^\(]+?[\n$]/gm, '').replace(/^\s+at\s+/gm, '').replace(/^Object.\s*\(/gm, '{anonymous}()@') : 'Unknown Stack Trace'; + + var log = window.console && (window.console.warn || window.console.log); + if (log) { + log.call(window.console, deprecationMessage, stack); + } + return method.apply(this, arguments); + }; +} + +/** + * extend object. + * means that properties in dest will be overwritten by the ones in src. + * @param {Object} dest + * @param {Object} src + * @param {Boolean} [merge=false] + * @returns {Object} dest + */ +var extend = deprecate(function extend(dest, src, merge) { + var keys = Object.keys(src); + var i = 0; + while (i < keys.length) { + if (!merge || merge && dest[keys[i]] === undefined) { + dest[keys[i]] = src[keys[i]]; + } + i++; + } + return dest; +}, 'extend', 'Use `assign`.'); + +/** + * merge the values from src in the dest. + * means that properties that exist in dest will not be overwritten by src + * @param {Object} dest + * @param {Object} src + * @returns {Object} dest + */ +var merge = deprecate(function merge(dest, src) { + return extend(dest, src, true); +}, 'merge', 'Use `assign`.'); + +// this prevents errors when Hammer is loaded in the presence of an AMD +// style loader but by script tag, not by the loader. + +assign(Hammer, { + INPUT_START: INPUT_START, + INPUT_MOVE: INPUT_MOVE, + INPUT_END: INPUT_END, + INPUT_CANCEL: INPUT_CANCEL, + + STATE_POSSIBLE: STATE_POSSIBLE, + STATE_BEGAN: STATE_BEGAN, + STATE_CHANGED: STATE_CHANGED, + STATE_ENDED: STATE_ENDED, + STATE_RECOGNIZED: STATE_RECOGNIZED, + STATE_CANCELLED: STATE_CANCELLED, + STATE_FAILED: STATE_FAILED, + + DIRECTION_NONE: DIRECTION_NONE, + DIRECTION_LEFT: DIRECTION_LEFT, + DIRECTION_RIGHT: DIRECTION_RIGHT, + DIRECTION_UP: DIRECTION_UP, + DIRECTION_DOWN: DIRECTION_DOWN, + DIRECTION_HORIZONTAL: DIRECTION_HORIZONTAL, + DIRECTION_VERTICAL: DIRECTION_VERTICAL, + DIRECTION_ALL: DIRECTION_ALL, + + Manager: Manager, + Input: Input, + TouchAction: TouchAction, + + TouchInput: TouchInput, + MouseInput: MouseInput, + PointerEventInput: PointerEventInput, + TouchMouseInput: TouchMouseInput, + SingleTouchInput: SingleTouchInput, + + Recognizer: Recognizer, + AttrRecognizer: AttrRecognizer, + Tap: TapRecognizer, + Pan: PanRecognizer, + Swipe: SwipeRecognizer, + Pinch: PinchRecognizer, + Rotate: RotateRecognizer, + Press: PressRecognizer, + + on: addEventListeners, + off: removeEventListeners, + each: each, + merge: merge, + extend: extend, + assign: assign, + inherit: inherit, + bindFn: bindFn, + prefixed: prefixed, + toArray: toArray, + inArray: inArray, + uniqueArray: uniqueArray, + splitStr: splitStr, + boolOrFn: boolOrFn, + hasParent: hasParent, + addEventListeners: addEventListeners, + removeEventListeners: removeEventListeners +}); + +if (typeof define === 'function' && define.amd) { + define(function () { + return Hammer; + }); +} else if (typeof module != 'undefined' && module.exports) { + module.exports = Hammer; +} else { + window[exportName] = Hammer; +} +})(window, document, 'Hammer'); \ No newline at end of file diff --git a/tests/unit/index.html b/tests/unit/index.html index 2ad74a6cf..6eb22cbe8 100644 --- a/tests/unit/index.html +++ b/tests/unit/index.html @@ -17,7 +17,7 @@ Simulator.events.touch.fakeSupport(); - +
diff --git a/tests/unit/test_utils.js b/tests/unit/test_utils.js index f9d5f80b3..321b1afac 100644 --- a/tests/unit/test_utils.js +++ b/tests/unit/test_utils.js @@ -1,12 +1,12 @@ module('utils'); -// for the tests, all hammer properties and methods of Hammer are exposed to window.$H +// for the tests, all hammer properties and methods of Hammer are exposed to window.Hammer test('get/set prefixed util', function() { - ok(_.isUndefined($H.prefixed(window, 'FakeProperty')), 'non existent property returns undefined'); + ok(_.isUndefined(Hammer.prefixed(window, 'FakeProperty')), 'non existent property returns undefined'); window.webkitFakeProperty = 1337; - ok($H.prefixed(window, 'FakeProperty') == 'webkitFakeProperty', 'existent prefixed property returns the prefixed name'); + ok(Hammer.prefixed(window, 'FakeProperty') == 'webkitFakeProperty', 'existent prefixed property returns the prefixed name'); delete window.webkitFakeProperty; }); @@ -14,7 +14,7 @@ test('get/set prefixed util', function() { test('fnBind', function() { var context = { a: true }; - $H.bindFn(function(b) { + Hammer.bindFn(function(b) { ok(this.a === true, 'bindFn scope'); ok(b === 123, 'bindFn argument'); }, context)(123); @@ -29,7 +29,7 @@ test('Inherit objects', function() { Base.call(this); } - $H.inherit(Child, Base, { + Hammer.inherit(Child, Base, { newMethod: function() { } }); @@ -45,29 +45,29 @@ test('Inherit objects', function() { }); test('toArray', function() { - ok(_.isArray($H.toArray({ 0: true, 1: 'second', length: 2 })), 'converted an array-like object to an array'); - ok(_.isArray($H.toArray([true, true])), 'array stays an array'); + ok(_.isArray(Hammer.toArray({ 0: true, 1: 'second', length: 2 })), 'converted an array-like object to an array'); + ok(_.isArray(Hammer.toArray([true, true])), 'array stays an array'); }); test('inArray', function() { - ok($H.inArray([1, 2, 3, 4, 'hammer'], 'hammer') === 4, 'found item and returned the index'); - ok($H.inArray([1, 2, 3, 4, 'hammer'], 'notfound') === -1, 'not found an item and returned -1'); - ok($H.inArray([ + ok(Hammer.inArray([1, 2, 3, 4, 'hammer'], 'hammer') === 4, 'found item and returned the index'); + ok(Hammer.inArray([1, 2, 3, 4, 'hammer'], 'notfound') === -1, 'not found an item and returned -1'); + ok(Hammer.inArray([ {id: 2}, {id: 24} ], '24', 'id') === 1, 'find by key and return the index'); - ok($H.inArray([ + ok(Hammer.inArray([ {id: 2}, {id: 24} ], '22', 'id') === -1, 'not found by key and return -1'); }); test('splitStr', function() { - deepEqual($H.splitStr(' a b c d '), ['a', 'b', 'c', 'd'], 'str split valid'); + deepEqual(Hammer.splitStr(' a b c d '), ['a', 'b', 'c', 'd'], 'str split valid'); }); test('uniqueArray', function() { - deepEqual($H.uniqueArray([ + deepEqual(Hammer.uniqueArray([ {id: 1}, {id: 2}, {id: 2} @@ -78,12 +78,12 @@ test('uniqueArray', function() { }); test('boolOrFn', function() { - equal($H.boolOrFn(true), true, 'Passing an boolean'); - equal($H.boolOrFn(false), false, 'Passing an boolean'); - equal($H.boolOrFn(function() { + equal(Hammer.boolOrFn(true), true, 'Passing an boolean'); + equal(Hammer.boolOrFn(false), false, 'Passing an boolean'); + equal(Hammer.boolOrFn(function() { return true; }), true, 'Passing an boolean'); - equal($H.boolOrFn(1), true, 'Passing an integer'); + equal(Hammer.boolOrFn(1), true, 'Passing an integer'); }); test('hasParent', function() { @@ -93,8 +93,8 @@ test('hasParent', function() { document.body.appendChild(parent); parent.appendChild(child); - equal($H.hasParent(child, parent), true, 'Found parent'); - equal($H.hasParent(parent, child), false, 'Not in parent'); + equal(Hammer.hasParent(child, parent), true, 'Found parent'); + equal(Hammer.hasParent(parent, child), false, 'Not in parent'); document.body.removeChild(parent); }); @@ -105,7 +105,7 @@ test('each', function() { var loop; loop = false; - $H.each(object, function(value, key) { + Hammer.each(object, function(value, key) { if (key == 'hi' && value === true) { loop = true; } @@ -113,7 +113,7 @@ test('each', function() { ok(loop, 'object loop'); loop = 0; - $H.each(array, function(value, key) { + Hammer.each(array, function(value, key) { if (value) { loop++; } @@ -122,7 +122,7 @@ test('each', function() { loop = 0; array.forEach = null; - $H.each(array, function(value, key) { + Hammer.each(array, function(value, key) { if (value) { loop++; } @@ -133,7 +133,7 @@ test('each', function() { test('assign', function() { expect(2); deepEqual( - $H.assign( + Hammer.assign( {a: 1, b: 3}, {b: 2, c: 3} ), @@ -142,7 +142,7 @@ test('assign', function() { ); var src = { foo: true }; - var dest = $H.assign({}, src); + var dest = Hammer.assign({}, src); src.foo = false; deepEqual(dest, {foo: true}, 'Clone reference'); }); @@ -154,11 +154,11 @@ test('test add/removeEventListener', function() { expect(2); - $H.addEventListeners(window, 'testEvent1 testEvent2 ', handleEvent); + Hammer.addEventListeners(window, 'testEvent1 testEvent2 ', handleEvent); utils.triggerDomEvent(window, 'testEvent1'); utils.triggerDomEvent(window, 'testEvent2'); - $H.removeEventListeners(window, ' testEvent1 testEvent2 ', handleEvent); + Hammer.removeEventListeners(window, ' testEvent1 testEvent2 ', handleEvent); utils.triggerDomEvent(window, 'testEvent1'); utils.triggerDomEvent(window, 'testEvent2'); }); From c6b55cd2bdcf8677709116713da579700667b29e Mon Sep 17 00:00:00 2001 From: Arjun Kathuria Date: Wed, 8 Jun 2016 13:28:49 +0530 Subject: [PATCH 25/61] Tests fix, tests the rollup build, now A-Okay --- src/main.js | 16 +++++++++++++++- tests/unit/index.html | 2 +- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/main.js b/src/main.js index 51945c800..f140602c8 100644 --- a/src/main.js +++ b/src/main.js @@ -32,6 +32,12 @@ import {extend} from './utils/extend'; import inherit from './utils/inherit'; import bindFn from './utils/bindFn'; import prefixed from './utils/prefixed'; +import toArray from'./utils/toArray'; +import uniqueArray from'./utils/uniqueArray'; +import splitStr from'./utils/splitStr'; +import inArray from'./utils/inArray'; +import boolOrFn from'./utils/boolOrFn'; +import hasParent from'./utils/hasParent'; // this prevents errors when Hammer is loaded in the presence of an AMD // style loader but by script tag, not by the loader. @@ -86,7 +92,15 @@ assign(Hammer, { assign: assign, inherit: inherit, bindFn: bindFn, - prefixed: prefixed + prefixed: prefixed, + toArray: toArray, + inArray: inArray, + uniqueArray: uniqueArray, + splitStr: splitStr, + boolOrFn:boolOrFn, + hasParent:hasParent, + addEventListeners: addEventListeners, + removeEventListeners: removeEventListeners }); var freeGlobal = (typeof window !== 'undefined' ? window : (typeof self !== 'undefined' ? self : {})); // jshint ignore:line diff --git a/tests/unit/index.html b/tests/unit/index.html index 6eb22cbe8..ccfdf5a59 100644 --- a/tests/unit/index.html +++ b/tests/unit/index.html @@ -17,7 +17,7 @@ Simulator.events.touch.fakeSupport(); - +
From 3d2df61d27461caf7e699e2eacee2931644527eb Mon Sep 17 00:00:00 2001 From: Arjun Kathuria Date: Wed, 8 Jun 2016 14:54:24 +0530 Subject: [PATCH 26/61] chore: removing redundant files --- rollup.config.js | 4 +- src/testMain.js | 117 -- tests/testBuild.js | 2640 -------------------------------------------- 3 files changed, 2 insertions(+), 2759 deletions(-) delete mode 100644 src/testMain.js delete mode 100644 tests/testBuild.js diff --git a/rollup.config.js b/rollup.config.js index a09455930..c91de8eae 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -5,11 +5,11 @@ import babel from 'rollup-plugin-babel'; export default { - entry: 'src/testMain.js', + entry: 'src/main.js', format: 'es6', // moduleName: 'HAMMER', plugins: [ babel({exclude: 'node_modules/**'}) ], - dest: 'tests/testBuild.js', + dest: 'hammer.js', intro: " (function(window, document, exportName, undefined) { \n'use strict' ", outro: "})(window, document, 'Hammer');" diff --git a/src/testMain.js b/src/testMain.js deleted file mode 100644 index 47e222992..000000000 --- a/src/testMain.js +++ /dev/null @@ -1,117 +0,0 @@ -import {Hammer} from './hammer'; -import {assign} from './utils/assign'; -import {INPUT_START,INPUT_MOVE,INPUT_END,INPUT_CANCEL} from './inputjs/inputConsts'; -import {STATE_POSSIBLE,STATE_BEGAN,STATE_CHANGED,STATE_ENDED,STATE_RECOGNIZED, - STATE_CANCELLED,STATE_FAILED} from './recognizerjs/recognizerConsts'; -import {DIRECTION_NONE,DIRECTION_LEFT,DIRECTION_RIGHT,DIRECTION_UP,DIRECTION_DOWN, - DIRECTION_HORIZONTAL,DIRECTION_VERTICAL,DIRECTION_ALL} from './inputjs/inputConsts'; - -import {Manager} from './manager'; -import {Input} from './inputjs/inputConstructor'; -import {TouchAction} from './touchactionjs/touchActionConstructor'; -import {TouchInput} from './input/touch'; -import {MouseInput} from './input/mouse'; -import {PointerEventInput} from './input/pointerevent'; -import {SingleTouchInput} from './input/singletouch'; -import {TouchMouseInput} from './input/touchmouse'; - -import {Recognizer} from './recognizerjs/recognizerConstructor'; -import {AttrRecognizer} from './recognizers/attribute'; -import {TapRecognizer} from './recognizers/tap'; -import {PanRecognizer} from './recognizers/pan'; -import {SwipeRecognizer} from './recognizers/swipe'; -import {PinchRecognizer} from './recognizers/pinch'; -import {RotateRecognizer} from './recognizers/rotate'; -import {PressRecognizer} from './recognizers/press'; - -import addEventListeners from './utils/addEventListeners'; -import removeEventListeners from './utils/removeEventListeners'; -import each from './utils/each'; -import {merge} from './utils/merge'; -import {extend} from './utils/extend'; -import inherit from './utils/inherit'; -import bindFn from './utils/bindFn'; -import prefixed from './utils/prefixed'; -import toArray from'./utils/toArray'; -import uniqueArray from'./utils/uniqueArray'; -import splitStr from'./utils/splitStr'; -import inArray from'./utils/inArray'; -import boolOrFn from'./utils/boolOrFn'; -import hasParent from'./utils/hasParent'; - -// this prevents errors when Hammer is loaded in the presence of an AMD -// style loader but by script tag, not by the loader. - -assign(Hammer, { - INPUT_START: INPUT_START, - INPUT_MOVE: INPUT_MOVE, - INPUT_END: INPUT_END, - INPUT_CANCEL: INPUT_CANCEL, - - STATE_POSSIBLE: STATE_POSSIBLE, - STATE_BEGAN: STATE_BEGAN, - STATE_CHANGED: STATE_CHANGED, - STATE_ENDED: STATE_ENDED, - STATE_RECOGNIZED: STATE_RECOGNIZED, - STATE_CANCELLED: STATE_CANCELLED, - STATE_FAILED: STATE_FAILED, - - DIRECTION_NONE: DIRECTION_NONE, - DIRECTION_LEFT: DIRECTION_LEFT, - DIRECTION_RIGHT: DIRECTION_RIGHT, - DIRECTION_UP: DIRECTION_UP, - DIRECTION_DOWN: DIRECTION_DOWN, - DIRECTION_HORIZONTAL: DIRECTION_HORIZONTAL, - DIRECTION_VERTICAL: DIRECTION_VERTICAL, - DIRECTION_ALL: DIRECTION_ALL, - - Manager: Manager, - Input: Input, - TouchAction: TouchAction, - - TouchInput: TouchInput, - MouseInput: MouseInput, - PointerEventInput: PointerEventInput, - TouchMouseInput: TouchMouseInput, - SingleTouchInput: SingleTouchInput, - - Recognizer: Recognizer, - AttrRecognizer: AttrRecognizer, - Tap: TapRecognizer, - Pan: PanRecognizer, - Swipe: SwipeRecognizer, - Pinch: PinchRecognizer, - Rotate: RotateRecognizer, - Press: PressRecognizer, - - on: addEventListeners, - off: removeEventListeners, - each: each, - merge: merge, - extend: extend, - assign: assign, - inherit: inherit, - bindFn: bindFn, - prefixed: prefixed, - toArray: toArray, - inArray: inArray, - uniqueArray: uniqueArray, - splitStr: splitStr, - boolOrFn:boolOrFn, - hasParent:hasParent, - addEventListeners: addEventListeners, - removeEventListeners: removeEventListeners -}); - -var freeGlobal = (typeof window !== 'undefined' ? window : (typeof self !== 'undefined' ? self : {})); // jshint ignore:line -freeGlobal.Hammer = Hammer; - -if (typeof define === 'function' && define.amd) { - define(function() { - return Hammer; - }); -} else if (typeof module != 'undefined' && module.exports) { - module.exports = Hammer; -} else { - window[exportName] = Hammer; -} diff --git a/tests/testBuild.js b/tests/testBuild.js deleted file mode 100644 index b9fe98465..000000000 --- a/tests/testBuild.js +++ /dev/null @@ -1,2640 +0,0 @@ -(function(window, document, exportName, undefined) { -'use strict' - -var babelHelpers = {}; -babelHelpers.typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { - return typeof obj; -} : function (obj) { - return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj; -}; -babelHelpers; - -/** - * use the val2 when val1 is undefined - * @param {*} val1 - * @param {*} val2 - * @returns {*} - */ -function ifUndefined(val1, val2) { - return val1 === undefined ? val2 : val1; -} - -var VENDOR_PREFIXES = ['', 'webkit', 'Moz', 'MS', 'ms', 'o']; -var TEST_ELEMENT = document.createElement('div'); - -var TYPE_FUNCTION = 'function'; - -var round = Math.round; -var abs = Math.abs; -var now = Date.now; - -/** - * get the prefixed property - * @param {Object} obj - * @param {String} property - * @returns {String|Undefined} prefixed - */ -function prefixed(obj, property) { - var prefix, prop; - var camelProp = property[0].toUpperCase() + property.slice(1); - - var i = 0; - while (i < VENDOR_PREFIXES.length) { - prefix = VENDOR_PREFIXES[i]; - prop = prefix ? prefix + camelProp : property; - - if (prop in obj) { - return prop; - } - i++; - } - return undefined; -} - -function getTouchActionProps() { - if (!NATIVE_TOUCH_ACTION) { - return false; - } - var touchMap = {}; - var cssSupports = window.CSS && window.CSS.supports; - ['auto', 'manipulation', 'pan-y', 'pan-x', 'pan-x pan-y', 'none'].forEach(function (val) { - - // If css.supports is not supported but there is native touch-action assume it supports - // all values. This is the case for IE 10 and 11. - touchMap[val] = cssSupports ? window.CSS.supports('touch-action', val) : true; - }); - return touchMap; -} - -var PREFIXED_TOUCH_ACTION = prefixed(TEST_ELEMENT.style, 'touchAction'); -var NATIVE_TOUCH_ACTION = PREFIXED_TOUCH_ACTION !== undefined; - -// magical touchAction value -var TOUCH_ACTION_COMPUTE = 'compute'; -var TOUCH_ACTION_AUTO = 'auto'; -var TOUCH_ACTION_MANIPULATION = 'manipulation'; // not implemented -var TOUCH_ACTION_NONE = 'none'; -var TOUCH_ACTION_PAN_X = 'pan-x'; -var TOUCH_ACTION_PAN_Y = 'pan-y'; -var TOUCH_ACTION_MAP = getTouchActionProps(); - -var MOBILE_REGEX = /mobile|tablet|ip(ad|hone|od)|android/i; - -var SUPPORT_TOUCH = 'ontouchstart' in window; -var SUPPORT_POINTER_EVENTS = prefixed(window, 'PointerEvent') !== undefined; -var SUPPORT_ONLY_TOUCH = SUPPORT_TOUCH && MOBILE_REGEX.test(navigator.userAgent); - -var INPUT_TYPE_TOUCH = 'touch'; -var INPUT_TYPE_PEN = 'pen'; -var INPUT_TYPE_MOUSE = 'mouse'; -var INPUT_TYPE_KINECT = 'kinect'; - -var COMPUTE_INTERVAL = 25; - -var INPUT_START = 1; -var INPUT_MOVE = 2; -var INPUT_END = 4; -var INPUT_CANCEL = 8; - -var DIRECTION_NONE = 1; -var DIRECTION_LEFT = 2; -var DIRECTION_RIGHT = 4; -var DIRECTION_UP = 8; -var DIRECTION_DOWN = 16; - -var DIRECTION_HORIZONTAL = DIRECTION_LEFT | DIRECTION_RIGHT; -var DIRECTION_VERTICAL = DIRECTION_UP | DIRECTION_DOWN; -var DIRECTION_ALL = DIRECTION_HORIZONTAL | DIRECTION_VERTICAL; - -var PROPS_XY = ['x', 'y']; -var PROPS_CLIENT_XY = ['clientX', 'clientY']; - -/** - * extend object. - * means that properties in dest will be overwritten by the ones in src. - * @param {Object} target - * @param {...Object} objects_to_assign - * @returns {Object} target - */ -var assign; -if (typeof Object.assign !== 'function') { - assign = function assign(target) { - if (target === undefined || target === null) { - throw new TypeError('Cannot convert undefined or null to object'); - } - - var output = Object(target); - for (var index = 1; index < arguments.length; index++) { - var source = arguments[index]; - if (source !== undefined && source !== null) { - for (var nextKey in source) { - if (source.hasOwnProperty(nextKey)) { - output[nextKey] = source[nextKey]; - } - } - } - } - return output; - }; -} else { - assign = Object.assign; -} - -/** - * simple class inheritance - * @param {Function} child - * @param {Function} base - * @param {Object} [properties] - */ -function inherit(child, base, properties) { - var baseP = base.prototype, - childP; - - childP = child.prototype = Object.create(baseP); - childP.constructor = child; - childP._super = baseP; - - if (properties) { - assign(childP, properties); - } -} - -var STATE_POSSIBLE = 1; -var STATE_BEGAN = 2; -var STATE_CHANGED = 4; -var STATE_ENDED = 8; -var STATE_RECOGNIZED = STATE_ENDED; -var STATE_CANCELLED = 16; -var STATE_FAILED = 32; - -/** - * get a unique id - * @returns {number} uniqueId - */ -var _uniqueId = 1; -function uniqueId() { - return _uniqueId++; -} - -/** - * walk objects and arrays - * @param {Object} obj - * @param {Function} iterator - * @param {Object} context - */ -function each(obj, iterator, context) { - var i; - - if (!obj) { - return; - } - - if (obj.forEach) { - obj.forEach(iterator, context); - } else if (obj.length !== undefined) { - i = 0; - while (i < obj.length) { - iterator.call(context, obj[i], i, obj); - i++; - } - } else { - for (i in obj) { - obj.hasOwnProperty(i) && iterator.call(context, obj[i], i, obj); - } - } -} - -/** - * if the argument is an array, we want to execute the fn on each entry - * if it aint an array we don't want to do a thing. - * this is used by all the methods that accept a single and array argument. - * @param {*|Array} arg - * @param {String} fn - * @param {Object} [context] - * @returns {Boolean} - */ -function invokeArrayArg(arg, fn, context) { - if (Array.isArray(arg)) { - each(arg, context[fn], context); - return true; - } - return false; -} - -/** - * find if a array contains the object using indexOf or a simple polyFill - * @param {Array} src - * @param {String} find - * @param {String} [findByKey] - * @return {Boolean|Number} false when not found, or the index - */ -function inArray(src, find, findByKey) { - if (src.indexOf && !findByKey) { - return src.indexOf(find); - } else { - var i = 0; - while (i < src.length) { - if (findByKey && src[i][findByKey] == find || !findByKey && src[i] === find) { - return i; - } - i++; - } - return -1; - } -} - -/** - * let a boolean value also be a function that must return a boolean - * this first item in args will be used as the context - * @param {Boolean|Function} val - * @param {Array} [args] - * @returns {Boolean} - */ -function boolOrFn(val, args) { - if ((typeof val === 'undefined' ? 'undefined' : babelHelpers.typeof(val)) == TYPE_FUNCTION) { - return val.apply(args ? args[0] || undefined : undefined, args); - } - return val; -} - -/** - * get a recognizer by name if it is bound to a manager - * @param {Recognizer|String} otherRecognizer - * @param {Recognizer} recognizer - * @returns {Recognizer} - */ -function getRecognizerByNameIfManager(otherRecognizer, recognizer) { - var manager = recognizer.manager; - if (manager) { - return manager.get(otherRecognizer); - } - return otherRecognizer; -} - -/** - * get a usable string, used as event postfix - * @param {constant} state - * @returns {String} state - */ -function stateStr(state) { - if (state & STATE_CANCELLED) { - return 'cancel'; - } else if (state & STATE_ENDED) { - return 'end'; - } else if (state & STATE_CHANGED) { - return 'move'; - } else if (state & STATE_BEGAN) { - return 'start'; - } - return ''; -} - -/** - * Recognizer flow explained; * - * All recognizers have the initial state of POSSIBLE when a input session starts. - * The definition of a input session is from the first input until the last input, with all it's movement in it. * - * Example session for mouse-input: mousedown -> mousemove -> mouseup - * - * On each recognizing cycle (see Manager.recognize) the .recognize() method is executed - * which determines with state it should be. - * - * If the recognizer has the state FAILED, CANCELLED or RECOGNIZED (equals ENDED), it is reset to - * POSSIBLE to give it another change on the next cycle. - * - * Possible - * | - * +-----+---------------+ - * | | - * +-----+-----+ | - * | | | - * Failed Cancelled | - * +-------+------+ - * | | - * Recognized Began - * | - * Changed - * | - * Ended/Recognized - */ - -/** - * Recognizer - * Every recognizer needs to extend from this class. - * @constructor - * @param {Object} options - */ -function Recognizer(options) { - this.options = assign({}, this.defaults, options || {}); - - this.id = uniqueId(); - - this.manager = null; - - // default is enable true - this.options.enable = ifUndefined(this.options.enable, true); - - this.state = STATE_POSSIBLE; - - this.simultaneous = {}; - this.requireFail = []; -} - -Recognizer.prototype = { - /** - * @virtual - * @type {Object} - */ - defaults: {}, - - /** - * set options - * @param {Object} options - * @return {Recognizer} - */ - set: function set(options) { - assign(this.options, options); - - // also update the touchAction, in case something changed about the directions/enabled state - this.manager && this.manager.touchAction.update(); - return this; - }, - - /** - * recognize simultaneous with an other recognizer. - * @param {Recognizer} otherRecognizer - * @returns {Recognizer} this - */ - recognizeWith: function recognizeWith(otherRecognizer) { - if (invokeArrayArg(otherRecognizer, 'recognizeWith', this)) { - return this; - } - - var simultaneous = this.simultaneous; - otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this); - if (!simultaneous[otherRecognizer.id]) { - simultaneous[otherRecognizer.id] = otherRecognizer; - otherRecognizer.recognizeWith(this); - } - return this; - }, - - /** - * drop the simultaneous link. it doesnt remove the link on the other recognizer. - * @param {Recognizer} otherRecognizer - * @returns {Recognizer} this - */ - dropRecognizeWith: function dropRecognizeWith(otherRecognizer) { - if (invokeArrayArg(otherRecognizer, 'dropRecognizeWith', this)) { - return this; - } - - otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this); - delete this.simultaneous[otherRecognizer.id]; - return this; - }, - - /** - * recognizer can only run when an other is failing - * @param {Recognizer} otherRecognizer - * @returns {Recognizer} this - */ - requireFailure: function requireFailure(otherRecognizer) { - if (invokeArrayArg(otherRecognizer, 'requireFailure', this)) { - return this; - } - - var requireFail = this.requireFail; - otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this); - if (inArray(requireFail, otherRecognizer) === -1) { - requireFail.push(otherRecognizer); - otherRecognizer.requireFailure(this); - } - return this; - }, - - /** - * drop the requireFailure link. it does not remove the link on the other recognizer. - * @param {Recognizer} otherRecognizer - * @returns {Recognizer} this - */ - dropRequireFailure: function dropRequireFailure(otherRecognizer) { - if (invokeArrayArg(otherRecognizer, 'dropRequireFailure', this)) { - return this; - } - - otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this); - var index = inArray(this.requireFail, otherRecognizer); - if (index > -1) { - this.requireFail.splice(index, 1); - } - return this; - }, - - /** - * has require failures boolean - * @returns {boolean} - */ - hasRequireFailures: function hasRequireFailures() { - return this.requireFail.length > 0; - }, - - /** - * if the recognizer can recognize simultaneous with an other recognizer - * @param {Recognizer} otherRecognizer - * @returns {Boolean} - */ - canRecognizeWith: function canRecognizeWith(otherRecognizer) { - return !!this.simultaneous[otherRecognizer.id]; - }, - - /** - * You should use `tryEmit` instead of `emit` directly to check - * that all the needed recognizers has failed before emitting. - * @param {Object} input - */ - emit: function emit(input) { - var self = this; - var state = this.state; - - function emit(event) { - self.manager.emit(event, input); - } - - // 'panstart' and 'panmove' - if (state < STATE_ENDED) { - emit(self.options.event + stateStr(state)); - } - - emit(self.options.event); // simple 'eventName' events - - if (input.additionalEvent) { - // additional event(panleft, panright, pinchin, pinchout...) - emit(input.additionalEvent); - } - - // panend and pancancel - if (state >= STATE_ENDED) { - emit(self.options.event + stateStr(state)); - } - }, - - /** - * Check that all the require failure recognizers has failed, - * if true, it emits a gesture event, - * otherwise, setup the state to FAILED. - * @param {Object} input - */ - tryEmit: function tryEmit(input) { - if (this.canEmit()) { - return this.emit(input); - } - // it's failing anyway - this.state = STATE_FAILED; - }, - - /** - * can we emit? - * @returns {boolean} - */ - canEmit: function canEmit() { - var i = 0; - while (i < this.requireFail.length) { - if (!(this.requireFail[i].state & (STATE_FAILED | STATE_POSSIBLE))) { - return false; - } - i++; - } - return true; - }, - - /** - * update the recognizer - * @param {Object} inputData - */ - recognize: function recognize(inputData) { - // make a new copy of the inputData - // so we can change the inputData without messing up the other recognizers - var inputDataClone = assign({}, inputData); - - // is is enabled and allow recognizing? - if (!boolOrFn(this.options.enable, [this, inputDataClone])) { - this.reset(); - this.state = STATE_FAILED; - return; - } - - // reset when we've reached the end - if (this.state & (STATE_RECOGNIZED | STATE_CANCELLED | STATE_FAILED)) { - this.state = STATE_POSSIBLE; - } - - this.state = this.process(inputDataClone); - - // the recognizer has recognized a gesture - // so trigger an event - if (this.state & (STATE_BEGAN | STATE_CHANGED | STATE_ENDED | STATE_CANCELLED)) { - this.tryEmit(inputDataClone); - } - }, - - /** - * return the state of the recognizer - * the actual recognizing happens in this method - * @virtual - * @param {Object} inputData - * @returns {constant} STATE - */ - process: function process(inputData) {}, // jshint ignore:line - - /** - * return the preferred touch-action - * @virtual - * @returns {Array} - */ - getTouchAction: function getTouchAction() {}, - - /** - * called when the gesture isn't allowed to recognize - * like when another is being recognized or it is disabled - * @virtual - */ - reset: function reset() {} -}; - -/** - * This recognizer is just used as a base for the simple attribute recognizers. - * @constructor - * @extends Recognizer - */ -function AttrRecognizer() { - Recognizer.apply(this, arguments); -} - -inherit(AttrRecognizer, Recognizer, { - /** - * @namespace - * @memberof AttrRecognizer - */ - defaults: { - /** - * @type {Number} - * @default 1 - */ - pointers: 1 - }, - - /** - * Used to check if it the recognizer receives valid input, like input.distance > 10. - * @memberof AttrRecognizer - * @param {Object} input - * @returns {Boolean} recognized - */ - attrTest: function attrTest(input) { - var optionPointers = this.options.pointers; - return optionPointers === 0 || input.pointers.length === optionPointers; - }, - - /** - * Process the input and return the state for the recognizer - * @memberof AttrRecognizer - * @param {Object} input - * @returns {*} State - */ - process: function process(input) { - var state = this.state; - var eventType = input.eventType; - - var isRecognized = state & (STATE_BEGAN | STATE_CHANGED); - var isValid = this.attrTest(input); - - // on cancel input and we've recognized before, return STATE_CANCELLED - if (isRecognized && (eventType & INPUT_CANCEL || !isValid)) { - return state | STATE_CANCELLED; - } else if (isRecognized || isValid) { - if (eventType & INPUT_END) { - return state | STATE_ENDED; - } else if (!(state & STATE_BEGAN)) { - return STATE_BEGAN; - } - return state | STATE_CHANGED; - } - return STATE_FAILED; - } -}); - -/** - * Rotate - * Recognized when two or more pointer are moving in a circular motion. - * @constructor - * @extends AttrRecognizer - */ -function RotateRecognizer() { - AttrRecognizer.apply(this, arguments); -} - -inherit(RotateRecognizer, AttrRecognizer, { - /** - * @namespace - * @memberof RotateRecognizer - */ - defaults: { - event: 'rotate', - threshold: 0, - pointers: 2 - }, - - getTouchAction: function getTouchAction() { - return [TOUCH_ACTION_NONE]; - }, - - attrTest: function attrTest(input) { - return this._super.attrTest.call(this, input) && (Math.abs(input.rotation) > this.options.threshold || this.state & STATE_BEGAN); - } -}); - -/** - * Pinch - * Recognized when two or more pointers are moving toward (zoom-in) or away from each other (zoom-out). - * @constructor - * @extends AttrRecognizer - */ -function PinchRecognizer() { - AttrRecognizer.apply(this, arguments); -} - -inherit(PinchRecognizer, AttrRecognizer, { - /** - * @namespace - * @memberof PinchRecognizer - */ - defaults: { - event: 'pinch', - threshold: 0, - pointers: 2 - }, - - getTouchAction: function getTouchAction() { - return [TOUCH_ACTION_NONE]; - }, - - attrTest: function attrTest(input) { - return this._super.attrTest.call(this, input) && (Math.abs(input.scale - 1) > this.options.threshold || this.state & STATE_BEGAN); - }, - - emit: function emit(input) { - if (input.scale !== 1) { - var inOut = input.scale < 1 ? 'in' : 'out'; - input.additionalEvent = this.options.event + inOut; - } - this._super.emit.call(this, input); - } -}); - -/** - * direction cons to string - * @param {constant} direction - * @returns {String} - */ -function directionStr(direction) { - if (direction == DIRECTION_DOWN) { - return 'down'; - } else if (direction == DIRECTION_UP) { - return 'up'; - } else if (direction == DIRECTION_LEFT) { - return 'left'; - } else if (direction == DIRECTION_RIGHT) { - return 'right'; - } - return ''; -} - -/** - * Pan - * Recognized when the pointer is down and moved in the allowed direction. - * @constructor - * @extends AttrRecognizer - */ -function PanRecognizer() { - AttrRecognizer.apply(this, arguments); - - this.pX = null; - this.pY = null; -} - -inherit(PanRecognizer, AttrRecognizer, { - /** - * @namespace - * @memberof PanRecognizer - */ - defaults: { - event: 'pan', - threshold: 10, - pointers: 1, - direction: DIRECTION_ALL - }, - - getTouchAction: function getTouchAction() { - var direction = this.options.direction; - var actions = []; - if (direction & DIRECTION_HORIZONTAL) { - actions.push(TOUCH_ACTION_PAN_Y); - } - if (direction & DIRECTION_VERTICAL) { - actions.push(TOUCH_ACTION_PAN_X); - } - return actions; - }, - - directionTest: function directionTest(input) { - var options = this.options; - var hasMoved = true; - var distance = input.distance; - var direction = input.direction; - var x = input.deltaX; - var y = input.deltaY; - - // lock to axis? - if (!(direction & options.direction)) { - if (options.direction & DIRECTION_HORIZONTAL) { - direction = x === 0 ? DIRECTION_NONE : x < 0 ? DIRECTION_LEFT : DIRECTION_RIGHT; - hasMoved = x != this.pX; - distance = Math.abs(input.deltaX); - } else { - direction = y === 0 ? DIRECTION_NONE : y < 0 ? DIRECTION_UP : DIRECTION_DOWN; - hasMoved = y != this.pY; - distance = Math.abs(input.deltaY); - } - } - input.direction = direction; - return hasMoved && distance > options.threshold && direction & options.direction; - }, - - attrTest: function attrTest(input) { - return AttrRecognizer.prototype.attrTest.call(this, input) && (this.state & STATE_BEGAN || !(this.state & STATE_BEGAN) && this.directionTest(input)); - }, - - emit: function emit(input) { - - this.pX = input.deltaX; - this.pY = input.deltaY; - - var direction = directionStr(input.direction); - - if (direction) { - input.additionalEvent = this.options.event + direction; - } - this._super.emit.call(this, input); - } -}); - -/** - * Swipe - * Recognized when the pointer is moving fast (velocity), with enough distance in the allowed direction. - * @constructor - * @extends AttrRecognizer - */ -function SwipeRecognizer() { - AttrRecognizer.apply(this, arguments); -} - -inherit(SwipeRecognizer, AttrRecognizer, { - /** - * @namespace - * @memberof SwipeRecognizer - */ - defaults: { - event: 'swipe', - threshold: 10, - velocity: 0.3, - direction: DIRECTION_HORIZONTAL | DIRECTION_VERTICAL, - pointers: 1 - }, - - getTouchAction: function getTouchAction() { - return PanRecognizer.prototype.getTouchAction.call(this); - }, - - attrTest: function attrTest(input) { - var direction = this.options.direction; - var velocity; - - if (direction & (DIRECTION_HORIZONTAL | DIRECTION_VERTICAL)) { - velocity = input.overallVelocity; - } else if (direction & DIRECTION_HORIZONTAL) { - velocity = input.overallVelocityX; - } else if (direction & DIRECTION_VERTICAL) { - velocity = input.overallVelocityY; - } - - return this._super.attrTest.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; - }, - - emit: function emit(input) { - var direction = directionStr(input.offsetDirection); - if (direction) { - this.manager.emit(this.options.event + direction, input); - } - - this.manager.emit(this.options.event, input); - } -}); - -/** - * simple function bind - * @param {Function} fn - * @param {Object} context - * @returns {Function} - */ -function bindFn(fn, context) { - return function boundFn() { - return fn.apply(context, arguments); - }; -} - -/** - * set a timeout with a given scope - * @param {Function} fn - * @param {Number} timeout - * @param {Object} context - * @returns {number} - */ -function setTimeoutContext(fn, timeout, context) { - return setTimeout(bindFn(fn, context), timeout); -} - -/** - * calculate the absolute distance between two points - * @param {Object} p1 {x, y} - * @param {Object} p2 {x, y} - * @param {Array} [props] containing x and y keys - * @return {Number} distance - */ -function getDistance(p1, p2, props) { - if (!props) { - props = PROPS_XY; - } - var x = p2[props[0]] - p1[props[0]], - y = p2[props[1]] - p1[props[1]]; - - return Math.sqrt(x * x + y * y); -} - -/** - * A tap is recognized when the pointer is doing a small tap/click. Multiple taps are recognized if they occur - * between the given interval and position. The delay option can be used to recognize multi-taps without firing - * a single tap. - * - * The eventData from the emitted event contains the property `tapCount`, which contains the amount of - * multi-taps being recognized. - * @constructor - * @extends Recognizer - */ -function TapRecognizer() { - Recognizer.apply(this, arguments); - - // previous time and center, - // used for tap counting - this.pTime = false; - this.pCenter = false; - - this._timer = null; - this._input = null; - this.count = 0; -} - -inherit(TapRecognizer, Recognizer, { - /** - * @namespace - * @memberof PinchRecognizer - */ - defaults: { - event: 'tap', - pointers: 1, - taps: 1, - interval: 300, // max time between the multi-tap taps - time: 250, // max time of the pointer to be down (like finger on the screen) - threshold: 9, // a minimal movement is ok, but keep it low - posThreshold: 10 // a multi-tap can be a bit off the initial position - }, - - getTouchAction: function getTouchAction() { - return [TOUCH_ACTION_MANIPULATION]; - }, - - process: function process(input) { - var options = this.options; - - var validPointers = input.pointers.length === options.pointers; - var validMovement = input.distance < options.threshold; - var validTouchTime = input.deltaTime < options.time; - - this.reset(); - - if (input.eventType & INPUT_START && this.count === 0) { - return this.failTimeout(); - } - - // we only allow little movement - // and we've reached an end event, so a tap is possible - if (validMovement && validTouchTime && validPointers) { - if (input.eventType != INPUT_END) { - return this.failTimeout(); - } - - var validInterval = this.pTime ? input.timeStamp - this.pTime < options.interval : true; - var validMultiTap = !this.pCenter || getDistance(this.pCenter, input.center) < options.posThreshold; - - this.pTime = input.timeStamp; - this.pCenter = input.center; - - if (!validMultiTap || !validInterval) { - this.count = 1; - } else { - this.count += 1; - } - - this._input = input; - - // if tap count matches we have recognized it, - // else it has began recognizing... - var tapCount = this.count % options.taps; - if (tapCount === 0) { - // no failing requirements, immediately trigger the tap event - // or wait as long as the multitap interval to trigger - if (!this.hasRequireFailures()) { - return STATE_RECOGNIZED; - } else { - this._timer = setTimeoutContext(function () { - this.state = STATE_RECOGNIZED; - this.tryEmit(); - }, options.interval, this); - return STATE_BEGAN; - } - } - } - return STATE_FAILED; - }, - - failTimeout: function failTimeout() { - this._timer = setTimeoutContext(function () { - this.state = STATE_FAILED; - }, this.options.interval, this); - return STATE_FAILED; - }, - - reset: function reset() { - clearTimeout(this._timer); - }, - - emit: function emit() { - if (this.state == STATE_RECOGNIZED) { - this._input.tapCount = this.count; - this.manager.emit(this.options.event, this._input); - } - } -}); - -/** - * Press - * Recognized when the pointer is down for x ms without any movement. - * @constructor - * @extends Recognizer - */ -function PressRecognizer() { - Recognizer.apply(this, arguments); - - this._timer = null; - this._input = null; -} - -inherit(PressRecognizer, Recognizer, { - /** - * @namespace - * @memberof PressRecognizer - */ - defaults: { - event: 'press', - pointers: 1, - time: 251, // minimal time of the pointer to be pressed - threshold: 9 // a minimal movement is ok, but keep it low - }, - - getTouchAction: function getTouchAction() { - return [TOUCH_ACTION_AUTO]; - }, - - process: function process(input) { - var options = this.options; - var validPointers = input.pointers.length === options.pointers; - var validMovement = input.distance < options.threshold; - var validTime = input.deltaTime > options.time; - - this._input = input; - - // we only allow little movement - // and we've reached an end event, so a tap is possible - if (!validMovement || !validPointers || input.eventType & (INPUT_END | INPUT_CANCEL) && !validTime) { - this.reset(); - } else if (input.eventType & INPUT_START) { - this.reset(); - this._timer = setTimeoutContext(function () { - this.state = STATE_RECOGNIZED; - this.tryEmit(); - }, options.time, this); - } else if (input.eventType & INPUT_END) { - return STATE_RECOGNIZED; - } - return STATE_FAILED; - }, - - reset: function reset() { - clearTimeout(this._timer); - }, - - emit: function emit(input) { - if (this.state !== STATE_RECOGNIZED) { - return; - } - - if (input && input.eventType & INPUT_END) { - this.manager.emit(this.options.event + 'up', input); - } else { - this._input.timeStamp = now(); - this.manager.emit(this.options.event, this._input); - } - } -}); - -/** - * small indexOf wrapper - * @param {String} str - * @param {String} find - * @returns {Boolean} found - */ -function inStr(str, find) { - return str.indexOf(find) > -1; -} - -/** - * when the touchActions are collected they are not a valid value, so we need to clean things up. * - * @param {String} actions - * @returns {*} - */ -function cleanTouchActions(actions) { - // none - if (inStr(actions, TOUCH_ACTION_NONE)) { - return TOUCH_ACTION_NONE; - } - - var hasPanX = inStr(actions, TOUCH_ACTION_PAN_X); - var hasPanY = inStr(actions, TOUCH_ACTION_PAN_Y); - - // if both pan-x and pan-y are set (different recognizers - // for different directions, e.g. horizontal pan but vertical swipe?) - // we need none (as otherwise with pan-x pan-y combined none of these - // recognizers will work, since the browser would handle all panning - if (hasPanX && hasPanY) { - return TOUCH_ACTION_NONE; - } - - // pan-x OR pan-y - if (hasPanX || hasPanY) { - return hasPanX ? TOUCH_ACTION_PAN_X : TOUCH_ACTION_PAN_Y; - } - - // manipulation - if (inStr(actions, TOUCH_ACTION_MANIPULATION)) { - return TOUCH_ACTION_MANIPULATION; - } - - return TOUCH_ACTION_AUTO; -} - -/** - * Touch Action - * sets the touchAction property or uses the js alternative - * @param {Manager} manager - * @param {String} value - * @constructor - */ -function TouchAction(manager, value) { - this.manager = manager; - this.set(value); -} - -TouchAction.prototype = { - /** - * set the touchAction value on the element or enable the polyfill - * @param {String} value - */ - set: function set(value) { - // find out the touch-action by the event handlers - if (value == TOUCH_ACTION_COMPUTE) { - value = this.compute(); - } - - if (NATIVE_TOUCH_ACTION && this.manager.element.style && TOUCH_ACTION_MAP[value]) { - this.manager.element.style[PREFIXED_TOUCH_ACTION] = value; - } - this.actions = value.toLowerCase().trim(); - }, - - /** - * just re-set the touchAction value - */ - update: function update() { - this.set(this.manager.options.touchAction); - }, - - /** - * compute the value for the touchAction property based on the recognizer's settings - * @returns {String} value - */ - compute: function compute() { - var actions = []; - each(this.manager.recognizers, function (recognizer) { - if (boolOrFn(recognizer.options.enable, [recognizer])) { - actions = actions.concat(recognizer.getTouchAction()); - } - }); - return cleanTouchActions(actions.join(' ')); - }, - - /** - * this method is called on each input cycle and provides the preventing of the browser behavior - * @param {Object} input - */ - preventDefaults: function preventDefaults(input) { - var srcEvent = input.srcEvent; - var direction = input.offsetDirection; - - // if the touch action did prevented once this session - if (this.manager.session.prevented) { - srcEvent.preventDefault(); - return; - } - - var actions = this.actions; - var hasNone = inStr(actions, TOUCH_ACTION_NONE) && !TOUCH_ACTION_MAP[TOUCH_ACTION_NONE]; - var hasPanY = inStr(actions, TOUCH_ACTION_PAN_Y) && !TOUCH_ACTION_MAP[TOUCH_ACTION_PAN_Y]; - var hasPanX = inStr(actions, TOUCH_ACTION_PAN_X) && !TOUCH_ACTION_MAP[TOUCH_ACTION_PAN_X]; - - if (hasNone) { - //do not prevent defaults if this is a tap gesture - - var isTapPointer = input.pointers.length === 1; - var isTapMovement = input.distance < 2; - var isTapTouchTime = input.deltaTime < 250; - - if (isTapPointer && isTapMovement && isTapTouchTime) { - return; - } - } - - if (hasPanX && hasPanY) { - // `pan-x pan-y` means browser handles all scrolling/panning, do not prevent - return; - } - - if (hasNone || hasPanY && direction & DIRECTION_HORIZONTAL || hasPanX && direction & DIRECTION_VERTICAL) { - return this.preventSrc(srcEvent); - } - }, - - /** - * call preventDefault to prevent the browser's default behavior (scrolling in most cases) - * @param {Object} srcEvent - */ - preventSrc: function preventSrc(srcEvent) { - this.manager.session.prevented = true; - srcEvent.preventDefault(); - } -}; - -/** - * find if a node is in the given parent - * @method hasParent - * @param {HTMLElement} node - * @param {HTMLElement} parent - * @return {Boolean} found - */ -function hasParent(node, parent) { - while (node) { - if (node == parent) { - return true; - } - node = node.parentNode; - } - return false; -} - -/** - * get the center of all the pointers - * @param {Array} pointers - * @return {Object} center contains `x` and `y` properties - */ -function getCenter(pointers) { - var pointersLength = pointers.length; - - // no need to loop when only one touch - if (pointersLength === 1) { - return { - x: round(pointers[0].clientX), - y: round(pointers[0].clientY) - }; - } - - var x = 0, - y = 0, - i = 0; - while (i < pointersLength) { - x += pointers[i].clientX; - y += pointers[i].clientY; - i++; - } - - return { - x: round(x / pointersLength), - y: round(y / pointersLength) - }; -} - -/** - * create a simple clone from the input used for storage of firstInput and firstMultiple - * @param {Object} input - * @returns {Object} clonedInputData - */ -function simpleCloneInputData(input) { - // make a simple copy of the pointers because we will get a reference if we don't - // we only need clientXY for the calculations - var pointers = []; - var i = 0; - while (i < input.pointers.length) { - pointers[i] = { - clientX: round(input.pointers[i].clientX), - clientY: round(input.pointers[i].clientY) - }; - i++; - } - - return { - timeStamp: now(), - pointers: pointers, - center: getCenter(pointers), - deltaX: input.deltaX, - deltaY: input.deltaY - }; -} - -/** - * calculate the angle between two coordinates - * @param {Object} p1 - * @param {Object} p2 - * @param {Array} [props] containing x and y keys - * @return {Number} angle - */ -function getAngle(p1, p2, props) { - if (!props) { - props = PROPS_XY; - } - var x = p2[props[0]] - p1[props[0]], - y = p2[props[1]] - p1[props[1]]; - return Math.atan2(y, x) * 180 / Math.PI; -} - -/** - * get the direction between two points - * @param {Number} x - * @param {Number} y - * @return {Number} direction - */ -function getDirection(x, y) { - if (x === y) { - return DIRECTION_NONE; - } - - if (abs(x) >= abs(y)) { - return x < 0 ? DIRECTION_LEFT : DIRECTION_RIGHT; - } - return y < 0 ? DIRECTION_UP : DIRECTION_DOWN; -} - -function computeDeltaXY(session, input) { - var center = input.center; - var offset = session.offsetDelta || {}; - var prevDelta = session.prevDelta || {}; - var prevInput = session.prevInput || {}; - - if (input.eventType === INPUT_START || prevInput.eventType === INPUT_END) { - prevDelta = session.prevDelta = { - x: prevInput.deltaX || 0, - y: prevInput.deltaY || 0 - }; - - offset = session.offsetDelta = { - x: center.x, - y: center.y - }; - } - - input.deltaX = prevDelta.x + (center.x - offset.x); - input.deltaY = prevDelta.y + (center.y - offset.y); -} - -/** - * calculate the velocity between two points. unit is in px per ms. - * @param {Number} deltaTime - * @param {Number} x - * @param {Number} y - * @return {Object} velocity `x` and `y` - */ -function getVelocity(deltaTime, x, y) { - return { - x: x / deltaTime || 0, - y: y / deltaTime || 0 - }; -} - -/** - * calculate the scale factor between two pointersets - * no scale is 1, and goes down to 0 when pinched together, and bigger when pinched out - * @param {Array} start array of pointers - * @param {Array} end array of pointers - * @return {Number} scale - */ -function getScale(start, end) { - return getDistance(end[0], end[1], PROPS_CLIENT_XY) / getDistance(start[0], start[1], PROPS_CLIENT_XY); -} - -/** - * calculate the rotation degrees between two pointersets - * @param {Array} start array of pointers - * @param {Array} end array of pointers - * @return {Number} rotation - */ -function getRotation(start, end) { - return getAngle(end[1], end[0], PROPS_CLIENT_XY) + getAngle(start[1], start[0], PROPS_CLIENT_XY); -} - -/** - * velocity is calculated every x ms - * @param {Object} session - * @param {Object} input - */ -function computeIntervalInputData(session, input) { - var last = session.lastInterval || input, - deltaTime = input.timeStamp - last.timeStamp, - velocity, - velocityX, - velocityY, - direction; - - if (input.eventType != INPUT_CANCEL && (deltaTime > COMPUTE_INTERVAL || last.velocity === undefined)) { - var deltaX = input.deltaX - last.deltaX; - var deltaY = input.deltaY - last.deltaY; - - var v = getVelocity(deltaTime, deltaX, deltaY); - velocityX = v.x; - velocityY = v.y; - velocity = abs(v.x) > abs(v.y) ? v.x : v.y; - direction = getDirection(deltaX, deltaY); - - session.lastInterval = input; - } else { - // use latest velocity info if it doesn't overtake a minimum period - velocity = last.velocity; - velocityX = last.velocityX; - velocityY = last.velocityY; - direction = last.direction; - } - - input.velocity = velocity; - input.velocityX = velocityX; - input.velocityY = velocityY; - input.direction = direction; -} - -/** - * extend the data with some usable properties like scale, rotate, velocity etc - * @param {Object} manager - * @param {Object} input - */ -function computeInputData(manager, input) { - var session = manager.session; - var pointers = input.pointers; - var pointersLength = pointers.length; - - // store the first input to calculate the distance and direction - if (!session.firstInput) { - session.firstInput = simpleCloneInputData(input); - } - - // to compute scale and rotation we need to store the multiple touches - if (pointersLength > 1 && !session.firstMultiple) { - session.firstMultiple = simpleCloneInputData(input); - } else if (pointersLength === 1) { - session.firstMultiple = false; - } - - var firstInput = session.firstInput; - var firstMultiple = session.firstMultiple; - var offsetCenter = firstMultiple ? firstMultiple.center : firstInput.center; - - var center = input.center = getCenter(pointers); - input.timeStamp = now(); - input.deltaTime = input.timeStamp - firstInput.timeStamp; - - input.angle = getAngle(offsetCenter, center); - input.distance = getDistance(offsetCenter, center); - - computeDeltaXY(session, input); - input.offsetDirection = getDirection(input.deltaX, input.deltaY); - - var overallVelocity = getVelocity(input.deltaTime, input.deltaX, input.deltaY); - input.overallVelocityX = overallVelocity.x; - input.overallVelocityY = overallVelocity.y; - input.overallVelocity = abs(overallVelocity.x) > abs(overallVelocity.y) ? overallVelocity.x : overallVelocity.y; - - input.scale = firstMultiple ? getScale(firstMultiple.pointers, pointers) : 1; - input.rotation = firstMultiple ? getRotation(firstMultiple.pointers, pointers) : 0; - - input.maxPointers = !session.prevInput ? input.pointers.length : input.pointers.length > session.prevInput.maxPointers ? input.pointers.length : session.prevInput.maxPointers; - - computeIntervalInputData(session, input); - - // find the correct target - var target = manager.element; - if (hasParent(input.srcEvent.target, target)) { - target = input.srcEvent.target; - } - input.target = target; -} - -/** - * handle input events - * @param {Manager} manager - * @param {String} eventType - * @param {Object} input - */ -function inputHandler(manager, eventType, input) { - var pointersLen = input.pointers.length; - var changedPointersLen = input.changedPointers.length; - var isFirst = eventType & INPUT_START && pointersLen - changedPointersLen === 0; - var isFinal = eventType & (INPUT_END | INPUT_CANCEL) && pointersLen - changedPointersLen === 0; - - input.isFirst = !!isFirst; - input.isFinal = !!isFinal; - - if (isFirst) { - manager.session = {}; - } - - // source event is the normalized value of the domEvents - // like 'touchstart, mouseup, pointerdown' - input.eventType = eventType; - - // compute scale, rotation etc - computeInputData(manager, input); - - // emit secret event - manager.emit('hammer.input', input); - - manager.recognize(input); - manager.session.prevInput = input; -} - -/** - * split string on whitespace - * @param {String} str - * @returns {Array} words - */ - -function splitStr(str) { - return str.trim().split(/\s+/g); -} - -/** - * addEventListener with multiple events at once - * @param {EventTarget} target - * @param {String} types - * @param {Function} handler - */ -function addEventListeners(target, types, handler) { - each(splitStr(types), function (type) { - target.addEventListener(type, handler, false); - }); -} - -/** - * removeEventListener with multiple events at once - * @param {EventTarget} target - * @param {String} types - * @param {Function} handler - */ -function removeEventListeners(target, types, handler) { - each(splitStr(types), function (type) { - target.removeEventListener(type, handler, false); - }); -} - -/** - * get the window object of an element - * @param {HTMLElement} element - * @returns {DocumentView|Window} - */ -function getWindowForElement(element) { - var doc = element.ownerDocument || element; - return doc.defaultView || doc.parentWindow || window; -} - -/** - * create new input type manager - * @param {Manager} manager - * @param {Function} callback - * @returns {Input} - * @constructor - */ -function Input(manager, callback) { - var self = this; - this.manager = manager; - this.callback = callback; - this.element = manager.element; - this.target = manager.options.inputTarget; - - // smaller wrapper around the handler, for the scope and the enabled state of the manager, - // so when disabled the input events are completely bypassed. - this.domHandler = function (ev) { - if (boolOrFn(manager.options.enable, [manager])) { - self.handler(ev); - } - }; - - this.init(); -} - -Input.prototype = { - /** - * should handle the inputEvent data and trigger the callback - * @virtual - */ - handler: function handler() {}, - - /** - * bind the events - */ - init: function init() { - this.evEl && addEventListeners(this.element, this.evEl, this.domHandler); - this.evTarget && addEventListeners(this.target, this.evTarget, this.domHandler); - this.evWin && addEventListeners(getWindowForElement(this.element), this.evWin, this.domHandler); - }, - - /** - * unbind the events - */ - destroy: function destroy() { - this.evEl && removeEventListeners(this.element, this.evEl, this.domHandler); - this.evTarget && removeEventListeners(this.target, this.evTarget, this.domHandler); - this.evWin && removeEventListeners(getWindowForElement(this.element), this.evWin, this.domHandler); - } -}; - -var POINTER_INPUT_MAP = { - pointerdown: INPUT_START, - pointermove: INPUT_MOVE, - pointerup: INPUT_END, - pointercancel: INPUT_CANCEL, - pointerout: INPUT_CANCEL -}; - -// in IE10 the pointer types is defined as an enum -var IE10_POINTER_TYPE_ENUM = { - 2: INPUT_TYPE_TOUCH, - 3: INPUT_TYPE_PEN, - 4: INPUT_TYPE_MOUSE, - 5: INPUT_TYPE_KINECT // see https://twitter.com/jacobrossi/status/480596438489890816 -}; - -var POINTER_ELEMENT_EVENTS = 'pointerdown'; -var POINTER_WINDOW_EVENTS = 'pointermove pointerup pointercancel'; - -// IE10 has prefixed support, and case-sensitive -if (window.MSPointerEvent && !window.PointerEvent) { - POINTER_ELEMENT_EVENTS = 'MSPointerDown'; - POINTER_WINDOW_EVENTS = 'MSPointerMove MSPointerUp MSPointerCancel'; -} - -/** - * Pointer events input - * @constructor - * @extends Input - */ -function PointerEventInput() { - this.evEl = POINTER_ELEMENT_EVENTS; - this.evWin = POINTER_WINDOW_EVENTS; - - Input.apply(this, arguments); - - this.store = this.manager.session.pointerEvents = []; -} - -inherit(PointerEventInput, Input, { - /** - * handle mouse events - * @param {Object} ev - */ - handler: function PEhandler(ev) { - var store = this.store; - var removePointer = false; - - var eventTypeNormalized = ev.type.toLowerCase().replace('ms', ''); - var eventType = POINTER_INPUT_MAP[eventTypeNormalized]; - var pointerType = IE10_POINTER_TYPE_ENUM[ev.pointerType] || ev.pointerType; - - var isTouch = pointerType == INPUT_TYPE_TOUCH; - - // get index of the event in the store - var storeIndex = inArray(store, ev.pointerId, 'pointerId'); - - // start and mouse must be down - if (eventType & INPUT_START && (ev.button === 0 || isTouch)) { - if (storeIndex < 0) { - store.push(ev); - storeIndex = store.length - 1; - } - } else if (eventType & (INPUT_END | INPUT_CANCEL)) { - removePointer = true; - } - - // it not found, so the pointer hasn't been down (so it's probably a hover) - if (storeIndex < 0) { - return; - } - - // update the event in the store - store[storeIndex] = ev; - - this.callback(this.manager, eventType, { - pointers: store, - changedPointers: [ev], - pointerType: pointerType, - srcEvent: ev - }); - - if (removePointer) { - // remove from the store - store.splice(storeIndex, 1); - } - } -}); - -/** - * convert array-like objects to real arrays - * @param {Object} obj - * @returns {Array} - */ -function toArray(obj) { - return Array.prototype.slice.call(obj, 0); -} - -/** - * unique array with objects based on a key (like 'id') or just by the array's value - * @param {Array} src [{id:1},{id:2},{id:1}] - * @param {String} [key] - * @param {Boolean} [sort=False] - * @returns {Array} [{id:1},{id:2}] - */ -function uniqueArray(src, key, sort) { - var results = []; - var values = []; - var i = 0; - - while (i < src.length) { - var val = key ? src[i][key] : src[i]; - if (inArray(values, val) < 0) { - results.push(src[i]); - } - values[i] = val; - i++; - } - - if (sort) { - if (!key) { - results = results.sort(); - } else { - results = results.sort(function sortUniqueArray(a, b) { - return a[key] > b[key]; - }); - } - } - - return results; -} - -var TOUCH_INPUT_MAP = { - touchstart: INPUT_START, - touchmove: INPUT_MOVE, - touchend: INPUT_END, - touchcancel: INPUT_CANCEL -}; - -var TOUCH_TARGET_EVENTS = 'touchstart touchmove touchend touchcancel'; - -/** - * Multi-user touch events input - * @constructor - * @extends Input - */ -function TouchInput() { - this.evTarget = TOUCH_TARGET_EVENTS; - this.targetIds = {}; - - Input.apply(this, arguments); -} - -inherit(TouchInput, Input, { - handler: function MTEhandler(ev) { - var type = TOUCH_INPUT_MAP[ev.type]; - var touches = getTouches.call(this, ev, type); - if (!touches) { - return; - } - - this.callback(this.manager, type, { - pointers: touches[0], - changedPointers: touches[1], - pointerType: INPUT_TYPE_TOUCH, - srcEvent: ev - }); - } -}); - -/** - * @this {TouchInput} - * @param {Object} ev - * @param {Number} type flag - * @returns {undefined|Array} [all, changed] - */ -function getTouches(ev, type) { - var allTouches = toArray(ev.touches); - var targetIds = this.targetIds; - - // when there is only one touch, the process can be simplified - if (type & (INPUT_START | INPUT_MOVE) && allTouches.length === 1) { - targetIds[allTouches[0].identifier] = true; - return [allTouches, allTouches]; - } - - var i, - targetTouches, - changedTouches = toArray(ev.changedTouches), - changedTargetTouches = [], - target = this.target; - - // get target touches from touches - targetTouches = allTouches.filter(function (touch) { - return hasParent(touch.target, target); - }); - - // collect touches - if (type === INPUT_START) { - i = 0; - while (i < targetTouches.length) { - targetIds[targetTouches[i].identifier] = true; - i++; - } - } - - // filter changed touches to only contain touches that exist in the collected target ids - i = 0; - while (i < changedTouches.length) { - if (targetIds[changedTouches[i].identifier]) { - changedTargetTouches.push(changedTouches[i]); - } - - // cleanup removed touches - if (type & (INPUT_END | INPUT_CANCEL)) { - delete targetIds[changedTouches[i].identifier]; - } - i++; - } - - if (!changedTargetTouches.length) { - return; - } - - return [ - // merge targetTouches with changedTargetTouches so it contains ALL touches, including 'end' and 'cancel' - uniqueArray(targetTouches.concat(changedTargetTouches), 'identifier', true), changedTargetTouches]; -} - -var MOUSE_INPUT_MAP = { - mousedown: INPUT_START, - mousemove: INPUT_MOVE, - mouseup: INPUT_END -}; - -var MOUSE_ELEMENT_EVENTS = 'mousedown'; -var MOUSE_WINDOW_EVENTS = 'mousemove mouseup'; - -/** - * Mouse events input - * @constructor - * @extends Input - */ -function MouseInput() { - this.evEl = MOUSE_ELEMENT_EVENTS; - this.evWin = MOUSE_WINDOW_EVENTS; - - this.pressed = false; // mousedown state - - Input.apply(this, arguments); -} - -inherit(MouseInput, Input, { - /** - * handle mouse events - * @param {Object} ev - */ - handler: function MEhandler(ev) { - var eventType = MOUSE_INPUT_MAP[ev.type]; - - // on start we want to have the left mouse button down - if (eventType & INPUT_START && ev.button === 0) { - this.pressed = true; - } - - if (eventType & INPUT_MOVE && ev.which !== 1) { - eventType = INPUT_END; - } - - // mouse must be down - if (!this.pressed) { - return; - } - - if (eventType & INPUT_END) { - this.pressed = false; - } - - this.callback(this.manager, eventType, { - pointers: [ev], - changedPointers: [ev], - pointerType: INPUT_TYPE_MOUSE, - srcEvent: ev - }); - } -}); - -/** - * Combined touch and mouse input - * - * Touch has a higher priority then mouse, and while touching no mouse events are allowed. - * This because touch devices also emit mouse events while doing a touch. - * - * @constructor - * @extends Input - */ - -var DEDUP_TIMEOUT = 2500; -var DEDUP_DISTANCE = 25; - -function TouchMouseInput() { - Input.apply(this, arguments); - - var handler = bindFn(this.handler, this); - this.touch = new TouchInput(this.manager, handler); - this.mouse = new MouseInput(this.manager, handler); - - this.primaryTouch = null; - this.lastTouches = []; -} - -inherit(TouchMouseInput, Input, { - /** - * handle mouse and touch events - * @param {Hammer} manager - * @param {String} inputEvent - * @param {Object} inputData - */ - handler: function TMEhandler(manager, inputEvent, inputData) { - var isTouch = inputData.pointerType == INPUT_TYPE_TOUCH, - isMouse = inputData.pointerType == INPUT_TYPE_MOUSE; - - if (isMouse && inputData.sourceCapabilities && inputData.sourceCapabilities.firesTouchEvents) { - return; - } - - // when we're in a touch event, record touches to de-dupe synthetic mouse event - if (isTouch) { - recordTouches.call(this, inputEvent, inputData); - } else if (isMouse && isSyntheticEvent.call(this, inputData)) { - return; - } - - this.callback(manager, inputEvent, inputData); - }, - - /** - * remove the event listeners - */ - destroy: function destroy() { - this.touch.destroy(); - this.mouse.destroy(); - } -}); - -function recordTouches(eventType, eventData) { - if (eventType & INPUT_START) { - this.primaryTouch = eventData.changedPointers[0].identifier; - setLastTouch.call(this, eventData); - } else if (eventType & (INPUT_END | INPUT_CANCEL)) { - setLastTouch.call(this, eventData); - } -} - -function setLastTouch(eventData) { - var touch = eventData.changedPointers[0]; - - if (touch.identifier === this.primaryTouch) { - var lastTouch = { x: touch.clientX, y: touch.clientY }; - this.lastTouches.push(lastTouch); - var lts = this.lastTouches; - var removeLastTouch = function removeLastTouch() { - var i = lts.indexOf(lastTouch); - if (i > -1) { - lts.splice(i, 1); - } - }; - setTimeout(removeLastTouch, DEDUP_TIMEOUT); - } -} - -function isSyntheticEvent(eventData) { - var x = eventData.srcEvent.clientX, - y = eventData.srcEvent.clientY; - for (var i = 0; i < this.lastTouches.length; i++) { - var t = this.lastTouches[i]; - var dx = Math.abs(x - t.x), - dy = Math.abs(y - t.y); - if (dx <= DEDUP_DISTANCE && dy <= DEDUP_DISTANCE) { - return true; - } - } - return false; -} - -/** - * create new input type manager - * called by the Manager constructor - * @param {Hammer} manager - * @returns {Input} - */ -function createInputInstance(manager) { - var Type; - var inputClass = manager.options.inputClass; - - if (inputClass) { - Type = inputClass; - } else if (SUPPORT_POINTER_EVENTS) { - Type = PointerEventInput; - } else if (SUPPORT_ONLY_TOUCH) { - Type = TouchInput; - } else if (!SUPPORT_TOUCH) { - Type = MouseInput; - } else { - Type = TouchMouseInput; - } - return new Type(manager, inputHandler); -} - -var STOP = 1; -var FORCED_STOP = 2; - -/** - * Manager - * @param {HTMLElement} element - * @param {Object} [options] - * @constructor - */ -function Manager(element, options) { - this.options = assign({}, Hammer.defaults, options || {}); - - this.options.inputTarget = this.options.inputTarget || element; - - this.handlers = {}; - this.session = {}; - this.recognizers = []; - this.oldCssProps = {}; - - this.element = element; - this.input = createInputInstance(this); - this.touchAction = new TouchAction(this, this.options.touchAction); - - toggleCssProps(this, true); - - each(this.options.recognizers, function (item) { - var recognizer = this.add(new item[0](item[1])); - item[2] && recognizer.recognizeWith(item[2]); - item[3] && recognizer.requireFailure(item[3]); - }, this); -} - -Manager.prototype = { - /** - * set options - * @param {Object} options - * @returns {Manager} - */ - set: function set(options) { - assign(this.options, options); - - // Options that need a little more setup - if (options.touchAction) { - this.touchAction.update(); - } - if (options.inputTarget) { - // Clean up existing event listeners and reinitialize - this.input.destroy(); - this.input.target = options.inputTarget; - this.input.init(); - } - return this; - }, - - /** - * stop recognizing for this session. - * This session will be discarded, when a new [input]start event is fired. - * When forced, the recognizer cycle is stopped immediately. - * @param {Boolean} [force] - */ - stop: function stop(force) { - this.session.stopped = force ? FORCED_STOP : STOP; - }, - - /** - * run the recognizers! - * called by the inputHandler function on every movement of the pointers (touches) - * it walks through all the recognizers and tries to detect the gesture that is being made - * @param {Object} inputData - */ - recognize: function recognize(inputData) { - var session = this.session; - if (session.stopped) { - return; - } - - // run the touch-action polyfill - this.touchAction.preventDefaults(inputData); - - var recognizer; - var recognizers = this.recognizers; - - // this holds the recognizer that is being recognized. - // so the recognizer's state needs to be BEGAN, CHANGED, ENDED or RECOGNIZED - // if no recognizer is detecting a thing, it is set to `null` - var curRecognizer = session.curRecognizer; - - // reset when the last recognizer is recognized - // or when we're in a new session - if (!curRecognizer || curRecognizer && curRecognizer.state & STATE_RECOGNIZED) { - curRecognizer = session.curRecognizer = null; - } - - var i = 0; - while (i < recognizers.length) { - recognizer = recognizers[i]; - - // find out if we are allowed try to recognize the input for this one. - // 1. allow if the session is NOT forced stopped (see the .stop() method) - // 2. allow if we still haven't recognized a gesture in this session, or the this recognizer is the one - // that is being recognized. - // 3. allow if the recognizer is allowed to run simultaneous with the current recognized recognizer. - // this can be setup with the `recognizeWith()` method on the recognizer. - if (session.stopped !== FORCED_STOP && ( // 1 - !curRecognizer || recognizer == curRecognizer || // 2 - recognizer.canRecognizeWith(curRecognizer))) { - // 3 - recognizer.recognize(inputData); - } else { - recognizer.reset(); - } - - // if the recognizer has been recognizing the input as a valid gesture, we want to store this one as the - // current active recognizer. but only if we don't already have an active recognizer - if (!curRecognizer && recognizer.state & (STATE_BEGAN | STATE_CHANGED | STATE_ENDED)) { - curRecognizer = session.curRecognizer = recognizer; - } - i++; - } - }, - - /** - * get a recognizer by its event name. - * @param {Recognizer|String} recognizer - * @returns {Recognizer|Null} - */ - get: function get(recognizer) { - if (recognizer instanceof Recognizer) { - return recognizer; - } - - var recognizers = this.recognizers; - for (var i = 0; i < recognizers.length; i++) { - if (recognizers[i].options.event == recognizer) { - return recognizers[i]; - } - } - return null; - }, - - /** - * add a recognizer to the manager - * existing recognizers with the same event name will be removed - * @param {Recognizer} recognizer - * @returns {Recognizer|Manager} - */ - add: function add(recognizer) { - if (invokeArrayArg(recognizer, 'add', this)) { - return this; - } - - // remove existing - var existing = this.get(recognizer.options.event); - if (existing) { - this.remove(existing); - } - - this.recognizers.push(recognizer); - recognizer.manager = this; - - this.touchAction.update(); - return recognizer; - }, - - /** - * remove a recognizer by name or instance - * @param {Recognizer|String} recognizer - * @returns {Manager} - */ - remove: function remove(recognizer) { - if (invokeArrayArg(recognizer, 'remove', this)) { - return this; - } - - recognizer = this.get(recognizer); - - // let's make sure this recognizer exists - if (recognizer) { - var recognizers = this.recognizers; - var index = inArray(recognizers, recognizer); - - if (index !== -1) { - recognizers.splice(index, 1); - this.touchAction.update(); - } - } - - return this; - }, - - /** - * bind event - * @param {String} events - * @param {Function} handler - * @returns {EventEmitter} this - */ - on: function on(events, handler) { - if (events === undefined) { - return; - } - if (handler === undefined) { - return; - } - - var handlers = this.handlers; - each(splitStr(events), function (event) { - handlers[event] = handlers[event] || []; - handlers[event].push(handler); - }); - return this; - }, - - /** - * unbind event, leave emit blank to remove all handlers - * @param {String} events - * @param {Function} [handler] - * @returns {EventEmitter} this - */ - off: function off(events, handler) { - if (events === undefined) { - return; - } - - var handlers = this.handlers; - each(splitStr(events), function (event) { - if (!handler) { - delete handlers[event]; - } else { - handlers[event] && handlers[event].splice(inArray(handlers[event], handler), 1); - } - }); - return this; - }, - - /** - * emit event to the listeners - * @param {String} event - * @param {Object} data - */ - emit: function emit(event, data) { - // we also want to trigger dom events - if (this.options.domEvents) { - triggerDomEvent(event, data); - } - - // no handlers, so skip it all - var handlers = this.handlers[event] && this.handlers[event].slice(); - if (!handlers || !handlers.length) { - return; - } - - data.type = event; - data.preventDefault = function () { - data.srcEvent.preventDefault(); - }; - - var i = 0; - while (i < handlers.length) { - handlers[i](data); - i++; - } - }, - - /** - * destroy the manager and unbinds all events - * it doesn't unbind dom events, that is the user own responsibility - */ - destroy: function destroy() { - this.element && toggleCssProps(this, false); - - this.handlers = {}; - this.session = {}; - this.input.destroy(); - this.element = null; - } -}; - -/** - * add/remove the css properties as defined in manager.options.cssProps - * @param {Manager} manager - * @param {Boolean} add - */ -function toggleCssProps(manager, add) { - var element = manager.element; - if (!element.style) { - return; - } - var prop; - each(manager.options.cssProps, function (value, name) { - prop = prefixed(element.style, name); - if (add) { - manager.oldCssProps[prop] = element.style[prop]; - element.style[prop] = value; - } else { - element.style[prop] = manager.oldCssProps[prop] || ''; - } - }); - if (!add) { - manager.oldCssProps = {}; - } -} - -/** - * trigger dom event - * @param {String} event - * @param {Object} data - */ -function triggerDomEvent(event, data) { - var gestureEvent = document.createEvent('Event'); - gestureEvent.initEvent(event, true, true); - gestureEvent.gesture = data; - data.target.dispatchEvent(gestureEvent); -} - -/** - * Simple way to create a manager with a default set of recognizers. - * @param {HTMLElement} element - * @param {Object} [options] - * @constructor - */ -function Hammer(element, options) { - options = options || {}; - options.recognizers = ifUndefined(options.recognizers, Hammer.defaults.preset); - return new Manager(element, options); -} - -/** - * @const {string} - */ -Hammer.VERSION = '{{PKG_VERSION}}'; - -/** - * default settings - * @namespace - */ -Hammer.defaults = { - /** - * set if DOM events are being triggered. - * But this is slower and unused by simple implementations, so disabled by default. - * @type {Boolean} - * @default false - */ - domEvents: false, - - /** - * The value for the touchAction property/fallback. - * When set to `compute` it will magically set the correct value based on the added recognizers. - * @type {String} - * @default compute - */ - touchAction: TOUCH_ACTION_COMPUTE, - - /** - * @type {Boolean} - * @default true - */ - enable: true, - - /** - * EXPERIMENTAL FEATURE -- can be removed/changed - * Change the parent input target element. - * If Null, then it is being set the to main element. - * @type {Null|EventTarget} - * @default null - */ - inputTarget: null, - - /** - * force an input class - * @type {Null|Function} - * @default null - */ - inputClass: null, - - /** - * Default recognizer setup when calling `Hammer()` - * When creating a new Manager these will be skipped. - * @type {Array} - */ - preset: [ - // RecognizerClass, options, [recognizeWith, ...], [requireFailure, ...] - [RotateRecognizer, { enable: false }], [PinchRecognizer, { enable: false }, ['rotate']], [SwipeRecognizer, { direction: DIRECTION_HORIZONTAL }], [PanRecognizer, { direction: DIRECTION_HORIZONTAL }, ['swipe']], [TapRecognizer], [TapRecognizer, { event: 'doubletap', taps: 2 }, ['tap']], [PressRecognizer]], - - /** - * Some CSS properties can be used to improve the working of Hammer. - * Add them to this method and they will be set when creating a new Manager. - * @namespace - */ - cssProps: { - /** - * Disables text selection to improve the dragging gesture. Mainly for desktop browsers. - * @type {String} - * @default 'none' - */ - userSelect: 'none', - - /** - * Disable the Windows Phone grippers when pressing an element. - * @type {String} - * @default 'none' - */ - touchSelect: 'none', - - /** - * Disables the default callout shown when you touch and hold a touch target. - * On iOS, when you touch and hold a touch target such as a link, Safari displays - * a callout containing information about the link. This property allows you to disable that callout. - * @type {String} - * @default 'none' - */ - touchCallout: 'none', - - /** - * Specifies whether zooming is enabled. Used by IE10> - * @type {String} - * @default 'none' - */ - contentZooming: 'none', - - /** - * Specifies that an entire element should be draggable instead of its contents. Mainly for desktop browsers. - * @type {String} - * @default 'none' - */ - userDrag: 'none', - - /** - * Overrides the highlight color shown when the user taps a link or a JavaScript - * clickable element in iOS. This property obeys the alpha value, if specified. - * @type {String} - * @default 'rgba(0,0,0,0)' - */ - tapHighlightColor: 'rgba(0,0,0,0)' - } -}; - -var SINGLE_TOUCH_INPUT_MAP = { - touchstart: INPUT_START, - touchmove: INPUT_MOVE, - touchend: INPUT_END, - touchcancel: INPUT_CANCEL -}; - -var SINGLE_TOUCH_TARGET_EVENTS = 'touchstart'; -var SINGLE_TOUCH_WINDOW_EVENTS = 'touchstart touchmove touchend touchcancel'; - -/** - * Touch events input - * @constructor - * @extends Input - */ -function SingleTouchInput() { - this.evTarget = SINGLE_TOUCH_TARGET_EVENTS; - this.evWin = SINGLE_TOUCH_WINDOW_EVENTS; - this.started = false; - - Input.apply(this, arguments); -} - -inherit(SingleTouchInput, Input, { - handler: function TEhandler(ev) { - var type = SINGLE_TOUCH_INPUT_MAP[ev.type]; - - // should we handle the touch events? - if (type === INPUT_START) { - this.started = true; - } - - if (!this.started) { - return; - } - - var touches = normalizeSingleTouches.call(this, ev, type); - - // when done, reset the started state - if (type & (INPUT_END | INPUT_CANCEL) && touches[0].length - touches[1].length === 0) { - this.started = false; - } - - this.callback(this.manager, type, { - pointers: touches[0], - changedPointers: touches[1], - pointerType: INPUT_TYPE_TOUCH, - srcEvent: ev - }); - } -}); - -/** - * @this {TouchInput} - * @param {Object} ev - * @param {Number} type flag - * @returns {undefined|Array} [all, changed] - */ -function normalizeSingleTouches(ev, type) { - var all = toArray(ev.touches); - var changed = toArray(ev.changedTouches); - - if (type & (INPUT_END | INPUT_CANCEL)) { - all = uniqueArray(all.concat(changed), 'identifier', true); - } - - return [all, changed]; -} - -/** - * wrap a method with a deprecation warning and stack trace - * @param {Function} method - * @param {String} name - * @param {String} message - * @returns {Function} A new function wrapping the supplied method. - */ -function deprecate(method, name, message) { - var deprecationMessage = 'DEPRECATED METHOD: ' + name + '\n' + message + ' AT \n'; - return function () { - var e = new Error('get-stack-trace'); - var stack = e && e.stack ? e.stack.replace(/^[^\(]+?[\n$]/gm, '').replace(/^\s+at\s+/gm, '').replace(/^Object.\s*\(/gm, '{anonymous}()@') : 'Unknown Stack Trace'; - - var log = window.console && (window.console.warn || window.console.log); - if (log) { - log.call(window.console, deprecationMessage, stack); - } - return method.apply(this, arguments); - }; -} - -/** - * extend object. - * means that properties in dest will be overwritten by the ones in src. - * @param {Object} dest - * @param {Object} src - * @param {Boolean} [merge=false] - * @returns {Object} dest - */ -var extend = deprecate(function extend(dest, src, merge) { - var keys = Object.keys(src); - var i = 0; - while (i < keys.length) { - if (!merge || merge && dest[keys[i]] === undefined) { - dest[keys[i]] = src[keys[i]]; - } - i++; - } - return dest; -}, 'extend', 'Use `assign`.'); - -/** - * merge the values from src in the dest. - * means that properties that exist in dest will not be overwritten by src - * @param {Object} dest - * @param {Object} src - * @returns {Object} dest - */ -var merge = deprecate(function merge(dest, src) { - return extend(dest, src, true); -}, 'merge', 'Use `assign`.'); - -// this prevents errors when Hammer is loaded in the presence of an AMD -// style loader but by script tag, not by the loader. - -assign(Hammer, { - INPUT_START: INPUT_START, - INPUT_MOVE: INPUT_MOVE, - INPUT_END: INPUT_END, - INPUT_CANCEL: INPUT_CANCEL, - - STATE_POSSIBLE: STATE_POSSIBLE, - STATE_BEGAN: STATE_BEGAN, - STATE_CHANGED: STATE_CHANGED, - STATE_ENDED: STATE_ENDED, - STATE_RECOGNIZED: STATE_RECOGNIZED, - STATE_CANCELLED: STATE_CANCELLED, - STATE_FAILED: STATE_FAILED, - - DIRECTION_NONE: DIRECTION_NONE, - DIRECTION_LEFT: DIRECTION_LEFT, - DIRECTION_RIGHT: DIRECTION_RIGHT, - DIRECTION_UP: DIRECTION_UP, - DIRECTION_DOWN: DIRECTION_DOWN, - DIRECTION_HORIZONTAL: DIRECTION_HORIZONTAL, - DIRECTION_VERTICAL: DIRECTION_VERTICAL, - DIRECTION_ALL: DIRECTION_ALL, - - Manager: Manager, - Input: Input, - TouchAction: TouchAction, - - TouchInput: TouchInput, - MouseInput: MouseInput, - PointerEventInput: PointerEventInput, - TouchMouseInput: TouchMouseInput, - SingleTouchInput: SingleTouchInput, - - Recognizer: Recognizer, - AttrRecognizer: AttrRecognizer, - Tap: TapRecognizer, - Pan: PanRecognizer, - Swipe: SwipeRecognizer, - Pinch: PinchRecognizer, - Rotate: RotateRecognizer, - Press: PressRecognizer, - - on: addEventListeners, - off: removeEventListeners, - each: each, - merge: merge, - extend: extend, - assign: assign, - inherit: inherit, - bindFn: bindFn, - prefixed: prefixed, - toArray: toArray, - inArray: inArray, - uniqueArray: uniqueArray, - splitStr: splitStr, - boolOrFn: boolOrFn, - hasParent: hasParent, - addEventListeners: addEventListeners, - removeEventListeners: removeEventListeners -}); - -if (typeof define === 'function' && define.amd) { - define(function () { - return Hammer; - }); -} else if (typeof module != 'undefined' && module.exports) { - module.exports = Hammer; -} else { - window[exportName] = Hammer; -} -})(window, document, 'Hammer'); \ No newline at end of file From 197f5df09fa2f8236d07ea33e4a79dcefb591ac9 Mon Sep 17 00:00:00 2001 From: Arjun Kathuria Date: Thu, 9 Jun 2016 20:49:54 +0530 Subject: [PATCH 27/61] use kebab dasherized case for file names, not camelCase. --- src/hammer.js | 6 ++-- src/input/mouse.js | 4 +-- src/input/pointerevent.js | 6 ++-- src/input/singletouch.js | 8 ++--- src/input/touch.js | 10 +++---- src/input/touchmouse.js | 6 ++-- ...{computeDeltaXY.js => compute-delta-xy.js} | 2 +- ...puteInputData.js => compute-input-data.js} | 26 ++++++++-------- ...Data.js => compute-interval-input-data.js} | 8 ++--- ...utInstance.js => create-input-instance.js} | 4 +-- src/inputjs/{getAngle.js => get-angle.js} | 2 +- src/inputjs/{getCenter.js => get-center.js} | 2 +- .../{getDirection.js => get-direction.js} | 4 +-- .../{getDistance.js => get-distance.js} | 2 +- .../{getRotation.js => get-rotation.js} | 4 +-- src/inputjs/{getScale.js => get-scale.js} | 4 +-- .../{getVelocity.js => get-velocity.js} | 0 ...putConstructor.js => input-constructor.js} | 8 ++--- .../{inputConsts.js => input-consts.js} | 0 .../{inputHandler.js => input-handler.js} | 4 +-- ...nputData.js => simple-clone-input-data.js} | 4 +-- src/main.js | 30 +++++++++---------- src/manager.js | 14 ++++----- .../{directionStr.js => direction-str.js} | 2 +- ...s => get-recognizer-by-name-if-manager.js} | 0 ...nstructor.js => recognizer-constructor.js} | 16 +++++----- ...cognizerConsts.js => recognizer-consts.js} | 0 .../{stateStr.js => state-str.js} | 2 +- src/recognizers/attribute.js | 6 ++-- src/recognizers/pan.js | 8 ++--- src/recognizers/pinch.js | 4 +-- src/recognizers/press.js | 12 ++++---- src/recognizers/rotate.js | 4 +-- src/recognizers/swipe.js | 8 ++--- src/recognizers/tap.js | 12 ++++---- ...TouchActions.js => clean-touch-actions.js} | 4 +-- ...ctionProps.js => get-touchaction-props.js} | 2 +- ...hactionConsts.js => touchaction-Consts.js} | 4 +-- ...structor.js => touchaction-constructor.js} | 10 +++---- ...entListeners.js => add-event-listeners.js} | 2 +- src/utils/{bindFn.js => bind-fn.js} | 0 src/utils/{boolOrFn.js => bool-or-fn.js} | 2 +- ...orElement.js => get-window-for-element.js} | 0 src/utils/{hasParent.js => has-parent.js} | 0 src/utils/{ifUndefined.js => if-undefined.js} | 0 src/utils/{inArray.js => in-array.js} | 0 src/utils/{inStr.js => in-str.js} | 0 ...{invokeArrayArg.js => invoke-array-arg.js} | 0 src/utils/prefixed.js | 2 +- ...Listeners.js => remove-event-listeners.js} | 2 +- ...meoutContext.js => set-timeout-context.js} | 2 +- src/utils/{splitStr.js => split-str.js} | 0 src/utils/{toArray.js => to-array.js} | 0 src/utils/{uniqueArray.js => unique-array.js} | 2 +- src/utils/{uniqueId.js => unique-id.js} | 0 src/utils/{utilsConsts.js => utils-consts.js} | 0 56 files changed, 132 insertions(+), 132 deletions(-) rename src/inputjs/{computeDeltaXY.js => compute-delta-xy.js} (92%) rename src/inputjs/{computeInputData.js => compute-input-data.js} (78%) rename src/inputjs/{computeIntervalInputData.js => compute-interval-input-data.js} (85%) rename src/inputjs/{createInputInstance.js => create-input-instance.js} (92%) rename src/inputjs/{getAngle.js => get-angle.js} (90%) rename src/inputjs/{getCenter.js => get-center.js} (93%) rename src/inputjs/{getDirection.js => get-direction.js} (83%) rename src/inputjs/{getDistance.js => get-distance.js} (91%) rename src/inputjs/{getRotation.js => get-rotation.js} (79%) rename src/inputjs/{getScale.js => get-scale.js} (82%) rename src/inputjs/{getVelocity.js => get-velocity.js} (100%) rename src/inputjs/{inputConstructor.js => input-constructor.js} (86%) rename src/inputjs/{inputConsts.js => input-consts.js} (100%) rename src/inputjs/{inputHandler.js => input-handler.js} (88%) rename src/inputjs/{simpleCloneInputData.js => simple-clone-input-data.js} (89%) rename src/recognizerjs/{directionStr.js => direction-str.js} (93%) rename src/recognizerjs/{getRecognizerByNameIfManager.js => get-recognizer-by-name-if-manager.js} (100%) rename src/recognizerjs/{recognizerConstructor.js => recognizer-constructor.js} (95%) rename src/recognizerjs/{recognizerConsts.js => recognizer-consts.js} (100%) rename src/recognizerjs/{stateStr.js => state-str.js} (94%) rename src/touchactionjs/{cleanTouchActions.js => clean-touch-actions.js} (93%) rename src/touchactionjs/{getTouchActionProps.js => get-touchaction-props.js} (90%) rename src/touchactionjs/{touchactionConsts.js => touchaction-Consts.js} (86%) rename src/touchactionjs/{touchActionConstructor.js => touchaction-constructor.js} (93%) rename src/utils/{addEventListeners.js => add-event-listeners.js} (90%) rename src/utils/{bindFn.js => bind-fn.js} (100%) rename src/utils/{boolOrFn.js => bool-or-fn.js} (89%) rename src/utils/{getWindowForElement.js => get-window-for-element.js} (100%) rename src/utils/{hasParent.js => has-parent.js} (100%) rename src/utils/{ifUndefined.js => if-undefined.js} (100%) rename src/utils/{inArray.js => in-array.js} (100%) rename src/utils/{inStr.js => in-str.js} (100%) rename src/utils/{invokeArrayArg.js => invoke-array-arg.js} (100%) rename src/utils/{removeEventListeners.js => remove-event-listeners.js} (90%) rename src/utils/{setTimeoutContext.js => set-timeout-context.js} (89%) rename src/utils/{splitStr.js => split-str.js} (100%) rename src/utils/{toArray.js => to-array.js} (100%) rename src/utils/{uniqueArray.js => unique-array.js} (95%) rename src/utils/{uniqueId.js => unique-id.js} (100%) rename src/utils/{utilsConsts.js => utils-consts.js} (100%) diff --git a/src/hammer.js b/src/hammer.js index 41eeb70d4..e133a9962 100644 --- a/src/hammer.js +++ b/src/hammer.js @@ -1,6 +1,6 @@ -import ifUndefined from './utils/ifUndefined'; -import {TOUCH_ACTION_COMPUTE} from './touchactionjs/touchactionConsts'; -import {DIRECTION_HORIZONTAL} from './inputjs/inputConsts'; +import ifUndefined from './utils/if-undefined'; +import {TOUCH_ACTION_COMPUTE} from './touchactionjs/touchaction-Consts'; +import {DIRECTION_HORIZONTAL} from './inputjs/input-consts'; import {RotateRecognizer} from './recognizers/rotate'; import {PinchRecognizer} from './recognizers/pinch'; import {SwipeRecognizer} from './recognizers/swipe'; diff --git a/src/input/mouse.js b/src/input/mouse.js index 053adfd98..0a089fff1 100644 --- a/src/input/mouse.js +++ b/src/input/mouse.js @@ -1,5 +1,5 @@ -import {INPUT_START,INPUT_MOVE,INPUT_END,INPUT_TYPE_MOUSE} from '../inputjs/inputConsts'; -import {Input} from '../inputjs/inputConstructor'; +import {INPUT_START,INPUT_MOVE,INPUT_END,INPUT_TYPE_MOUSE} from '../inputjs/input-consts'; +import {Input} from '../inputjs/input-constructor'; import inherit from '../utils/inherit'; var MOUSE_INPUT_MAP = { diff --git a/src/input/pointerevent.js b/src/input/pointerevent.js index ec0c64f0a..2585623f4 100644 --- a/src/input/pointerevent.js +++ b/src/input/pointerevent.js @@ -1,8 +1,8 @@ import {INPUT_START,INPUT_END,INPUT_CANCEL,INPUT_MOVE,INPUT_TYPE_TOUCH, -INPUT_TYPE_MOUSE,INPUT_TYPE_PEN,INPUT_TYPE_KINECT} from '../inputjs/inputConsts'; -import {Input} from '../inputjs/inputConstructor'; +INPUT_TYPE_MOUSE,INPUT_TYPE_PEN,INPUT_TYPE_KINECT} from '../inputjs/input-consts'; +import {Input} from '../inputjs/input-constructor'; import inherit from '../utils/inherit'; -import inArray from '../utils/inArray'; +import inArray from '../utils/in-array'; var POINTER_INPUT_MAP = { pointerdown: INPUT_START, diff --git a/src/input/singletouch.js b/src/input/singletouch.js index a9f1a0363..3f8a81fda 100644 --- a/src/input/singletouch.js +++ b/src/input/singletouch.js @@ -1,8 +1,8 @@ -import {INPUT_START,INPUT_MOVE,INPUT_END,INPUT_CANCEL,INPUT_TYPE_TOUCH} from '../inputjs/inputConsts'; -import {Input} from '../inputjs/inputConstructor'; +import {INPUT_START,INPUT_MOVE,INPUT_END,INPUT_CANCEL,INPUT_TYPE_TOUCH} from '../inputjs/input-consts'; +import {Input} from '../inputjs/input-constructor'; import inherit from '../utils/inherit'; -import toArray from '../utils/toArray'; -import uniqueArray from '../utils/uniqueArray'; +import toArray from '../utils/to-array'; +import uniqueArray from '../utils/unique-array'; var SINGLE_TOUCH_INPUT_MAP = { touchstart: INPUT_START, diff --git a/src/input/touch.js b/src/input/touch.js index e99335d25..34dc160fc 100644 --- a/src/input/touch.js +++ b/src/input/touch.js @@ -1,9 +1,9 @@ -import {INPUT_START,INPUT_MOVE,INPUT_END,INPUT_CANCEL,INPUT_TYPE_TOUCH} from '../inputjs/inputConsts'; -import {Input} from '../inputjs/inputConstructor'; +import {INPUT_START,INPUT_MOVE,INPUT_END,INPUT_CANCEL,INPUT_TYPE_TOUCH} from '../inputjs/input-consts'; +import {Input} from '../inputjs/input-constructor'; import inherit from '../utils/inherit'; -import toArray from '../utils/toArray'; -import hasParent from '../utils/hasParent'; -import uniqueArray from '../utils/uniqueArray'; +import toArray from '../utils/to-array'; +import hasParent from '../utils/has-parent'; +import uniqueArray from '../utils/unique-array'; var TOUCH_INPUT_MAP = { touchstart: INPUT_START, diff --git a/src/input/touchmouse.js b/src/input/touchmouse.js index d8dca7e54..d1db3b8bd 100644 --- a/src/input/touchmouse.js +++ b/src/input/touchmouse.js @@ -1,9 +1,9 @@ -import {Input} from '../inputjs/inputConstructor'; +import {Input} from '../inputjs/input-constructor'; import inherit from '../utils/inherit'; -import bindFn from '../utils/bindFn'; +import bindFn from '../utils/bind-fn'; import {TouchInput} from './touch'; import {MouseInput} from './mouse'; -import {INPUT_START,INPUT_END,INPUT_CANCEL,INPUT_TYPE_TOUCH,INPUT_TYPE_MOUSE} from '../inputjs/inputConsts'; +import {INPUT_START,INPUT_END,INPUT_CANCEL,INPUT_TYPE_TOUCH,INPUT_TYPE_MOUSE} from '../inputjs/input-consts'; /** * Combined touch and mouse input diff --git a/src/inputjs/computeDeltaXY.js b/src/inputjs/compute-delta-xy.js similarity index 92% rename from src/inputjs/computeDeltaXY.js rename to src/inputjs/compute-delta-xy.js index af3de4f0e..82cffef47 100644 --- a/src/inputjs/computeDeltaXY.js +++ b/src/inputjs/compute-delta-xy.js @@ -1,4 +1,4 @@ -import {INPUT_START,INPUT_END} from './inputConsts'; +import {INPUT_START,INPUT_END} from './input-consts'; export default function computeDeltaXY(session, input) { var center = input.center; diff --git a/src/inputjs/computeInputData.js b/src/inputjs/compute-input-data.js similarity index 78% rename from src/inputjs/computeInputData.js rename to src/inputjs/compute-input-data.js index 2daad704b..24906e60a 100644 --- a/src/inputjs/computeInputData.js +++ b/src/inputjs/compute-input-data.js @@ -1,16 +1,16 @@ -import {now} from '../utils/utilsConsts'; -import {abs} from '../utils/utilsConsts'; -import hasParent from '../utils/hasParent'; -import simpleCloneInputData from './simpleCloneInputData'; -import getCenter from './getCenter'; -import getDistance from './getDistance'; -import getAngle from './getAngle'; -import getDirection from './getDirection'; -import computeDeltaXY from './computeDeltaXY'; -import getVelocity from './getVelocity'; -import getScale from './getScale'; -import getRotation from './getRotation'; -import computeIntervalInputData from './computeIntervalInputData'; +import {now} from '../utils/utils-consts'; +import {abs} from '../utils/utils-consts'; +import hasParent from '../utils/has-parent'; +import simpleCloneInputData from './simple-clone-input-data'; +import getCenter from './get-center'; +import getDistance from './get-distance'; +import getAngle from './get-angle'; +import getDirection from './get-direction'; +import computeDeltaXY from './compute-delta-xy'; +import getVelocity from './get-velocity'; +import getScale from './get-scale'; +import getRotation from './get-rotation'; +import computeIntervalInputData from './compute-interval-input-data'; /** * extend the data with some usable properties like scale, rotate, velocity etc diff --git a/src/inputjs/computeIntervalInputData.js b/src/inputjs/compute-interval-input-data.js similarity index 85% rename from src/inputjs/computeIntervalInputData.js rename to src/inputjs/compute-interval-input-data.js index 30e9e1857..69976132f 100644 --- a/src/inputjs/computeIntervalInputData.js +++ b/src/inputjs/compute-interval-input-data.js @@ -1,7 +1,7 @@ -import {INPUT_CANCEL,COMPUTE_INTERVAL} from './inputConsts'; -import {abs} from '../utils/utilsConsts'; -import getVelocity from './getVelocity'; -import getDirection from './getDirection'; +import {INPUT_CANCEL,COMPUTE_INTERVAL} from './input-consts'; +import {abs} from '../utils/utils-consts'; +import getVelocity from './get-velocity'; +import getDirection from './get-direction'; /** * velocity is calculated every x ms diff --git a/src/inputjs/createInputInstance.js b/src/inputjs/create-input-instance.js similarity index 92% rename from src/inputjs/createInputInstance.js rename to src/inputjs/create-input-instance.js index e9d952770..abb661cc1 100644 --- a/src/inputjs/createInputInstance.js +++ b/src/inputjs/create-input-instance.js @@ -1,5 +1,5 @@ -import {SUPPORT_POINTER_EVENTS,SUPPORT_ONLY_TOUCH,SUPPORT_TOUCH} from './inputConsts'; -import inputHandler from './inputHandler'; +import {SUPPORT_POINTER_EVENTS,SUPPORT_ONLY_TOUCH,SUPPORT_TOUCH} from './input-consts'; +import inputHandler from './input-handler'; import {PointerEventInput} from '../input/pointerevent'; import {TouchInput} from '../input/touch'; import {MouseInput} from '../input/mouse'; diff --git a/src/inputjs/getAngle.js b/src/inputjs/get-angle.js similarity index 90% rename from src/inputjs/getAngle.js rename to src/inputjs/get-angle.js index 3f2118bfb..fb55e47f7 100644 --- a/src/inputjs/getAngle.js +++ b/src/inputjs/get-angle.js @@ -1,4 +1,4 @@ -import {PROPS_XY} from './inputConsts'; +import {PROPS_XY} from './input-consts'; /** * calculate the angle between two coordinates diff --git a/src/inputjs/getCenter.js b/src/inputjs/get-center.js similarity index 93% rename from src/inputjs/getCenter.js rename to src/inputjs/get-center.js index 99b0662e7..70e92c12f 100644 --- a/src/inputjs/getCenter.js +++ b/src/inputjs/get-center.js @@ -1,4 +1,4 @@ -import {round} from '../utils/utilsConsts'; +import {round} from '../utils/utils-consts'; /** * get the center of all the pointers diff --git a/src/inputjs/getDirection.js b/src/inputjs/get-direction.js similarity index 83% rename from src/inputjs/getDirection.js rename to src/inputjs/get-direction.js index 55a0d513a..e21147ee6 100644 --- a/src/inputjs/getDirection.js +++ b/src/inputjs/get-direction.js @@ -1,5 +1,5 @@ -import {abs} from '../utils/utilsConsts'; -import {DIRECTION_NONE,DIRECTION_LEFT,DIRECTION_RIGHT,DIRECTION_UP,DIRECTION_DOWN} from './inputConsts'; +import {abs} from '../utils/utils-consts'; +import {DIRECTION_NONE,DIRECTION_LEFT,DIRECTION_RIGHT,DIRECTION_UP,DIRECTION_DOWN} from './input-consts'; /** * get the direction between two points diff --git a/src/inputjs/getDistance.js b/src/inputjs/get-distance.js similarity index 91% rename from src/inputjs/getDistance.js rename to src/inputjs/get-distance.js index 261e9ab2b..16d1f34a6 100644 --- a/src/inputjs/getDistance.js +++ b/src/inputjs/get-distance.js @@ -1,4 +1,4 @@ -import {PROPS_XY} from './inputConsts'; +import {PROPS_XY} from './input-consts'; /** * calculate the absolute distance between two points diff --git a/src/inputjs/getRotation.js b/src/inputjs/get-rotation.js similarity index 79% rename from src/inputjs/getRotation.js rename to src/inputjs/get-rotation.js index 7fa5398b1..8515bce33 100644 --- a/src/inputjs/getRotation.js +++ b/src/inputjs/get-rotation.js @@ -1,5 +1,5 @@ -import getAngle from './getAngle'; -import {PROPS_CLIENT_XY} from './inputConsts'; +import getAngle from './get-angle'; +import {PROPS_CLIENT_XY} from './input-consts'; /** * calculate the rotation degrees between two pointersets diff --git a/src/inputjs/getScale.js b/src/inputjs/get-scale.js similarity index 82% rename from src/inputjs/getScale.js rename to src/inputjs/get-scale.js index b64b2881f..bf58547ba 100644 --- a/src/inputjs/getScale.js +++ b/src/inputjs/get-scale.js @@ -1,5 +1,5 @@ -import {PROPS_CLIENT_XY} from './inputConsts'; -import getDistance from './getDistance'; +import {PROPS_CLIENT_XY} from './input-consts'; +import getDistance from './get-distance'; /** * calculate the scale factor between two pointersets * no scale is 1, and goes down to 0 when pinched together, and bigger when pinched out diff --git a/src/inputjs/getVelocity.js b/src/inputjs/get-velocity.js similarity index 100% rename from src/inputjs/getVelocity.js rename to src/inputjs/get-velocity.js diff --git a/src/inputjs/inputConstructor.js b/src/inputjs/input-constructor.js similarity index 86% rename from src/inputjs/inputConstructor.js rename to src/inputjs/input-constructor.js index 1f4a61a46..d0aaf7f91 100644 --- a/src/inputjs/inputConstructor.js +++ b/src/inputjs/input-constructor.js @@ -1,7 +1,7 @@ -import boolOrFn from '../utils/boolOrFn'; -import addEventListeners from '../utils/addEventListeners'; -import removeEventListeners from '../utils/removeEventListeners'; -import getWindowForElement from '../utils/getWindowForElement'; +import boolOrFn from '../utils/bool-or-fn'; +import addEventListeners from '../utils/add-event-listeners'; +import removeEventListeners from '../utils/remove-event-listeners'; +import getWindowForElement from '../utils/get-window-for-element'; /** * create new input type manager diff --git a/src/inputjs/inputConsts.js b/src/inputjs/input-consts.js similarity index 100% rename from src/inputjs/inputConsts.js rename to src/inputjs/input-consts.js diff --git a/src/inputjs/inputHandler.js b/src/inputjs/input-handler.js similarity index 88% rename from src/inputjs/inputHandler.js rename to src/inputjs/input-handler.js index 6fb880681..45ca1e388 100644 --- a/src/inputjs/inputHandler.js +++ b/src/inputjs/input-handler.js @@ -1,5 +1,5 @@ -import {INPUT_START,INPUT_END,INPUT_CANCEL} from './inputConsts'; -import computeInputData from './computeInputData'; +import {INPUT_START,INPUT_END,INPUT_CANCEL} from './input-consts'; +import computeInputData from './compute-input-data'; /** * handle input events diff --git a/src/inputjs/simpleCloneInputData.js b/src/inputjs/simple-clone-input-data.js similarity index 89% rename from src/inputjs/simpleCloneInputData.js rename to src/inputjs/simple-clone-input-data.js index 796a8da92..b79fe216c 100644 --- a/src/inputjs/simpleCloneInputData.js +++ b/src/inputjs/simple-clone-input-data.js @@ -1,5 +1,5 @@ -import {now,round} from '../utils/utilsConsts'; -import getCenter from './getCenter'; +import {now,round} from '../utils/utils-consts'; +import getCenter from './get-center'; /** * create a simple clone from the input used for storage of firstInput and firstMultiple diff --git a/src/main.js b/src/main.js index f140602c8..fbf4bae44 100644 --- a/src/main.js +++ b/src/main.js @@ -1,21 +1,21 @@ import {Hammer} from './hammer'; import {assign} from './utils/assign'; -import {INPUT_START,INPUT_MOVE,INPUT_END,INPUT_CANCEL} from './inputjs/inputConsts'; +import {INPUT_START,INPUT_MOVE,INPUT_END,INPUT_CANCEL} from './inputjs/input-consts'; import {STATE_POSSIBLE,STATE_BEGAN,STATE_CHANGED,STATE_ENDED,STATE_RECOGNIZED, - STATE_CANCELLED,STATE_FAILED} from './recognizerjs/recognizerConsts'; + STATE_CANCELLED,STATE_FAILED} from './recognizerjs/recognizer-consts'; import {DIRECTION_NONE,DIRECTION_LEFT,DIRECTION_RIGHT,DIRECTION_UP,DIRECTION_DOWN, - DIRECTION_HORIZONTAL,DIRECTION_VERTICAL,DIRECTION_ALL} from './inputjs/inputConsts'; + DIRECTION_HORIZONTAL,DIRECTION_VERTICAL,DIRECTION_ALL} from './inputjs/input-consts'; import {Manager} from './manager'; -import {Input} from './inputjs/inputConstructor'; -import {TouchAction} from './touchactionjs/touchActionConstructor'; +import {Input} from './inputjs/input-constructor'; +import {TouchAction} from './touchactionjs/touchaction-constructor'; import {TouchInput} from './input/touch'; import {MouseInput} from './input/mouse'; import {PointerEventInput} from './input/pointerevent'; import {SingleTouchInput} from './input/singletouch'; import {TouchMouseInput} from './input/touchmouse'; -import {Recognizer} from './recognizerjs/recognizerConstructor'; +import {Recognizer} from './recognizerjs/recognizer-constructor'; import {AttrRecognizer} from './recognizers/attribute'; import {TapRecognizer} from './recognizers/tap'; import {PanRecognizer} from './recognizers/pan'; @@ -24,20 +24,20 @@ import {PinchRecognizer} from './recognizers/pinch'; import {RotateRecognizer} from './recognizers/rotate'; import {PressRecognizer} from './recognizers/press'; -import addEventListeners from './utils/addEventListeners'; -import removeEventListeners from './utils/removeEventListeners'; +import addEventListeners from './utils/add-event-listeners'; +import removeEventListeners from './utils/remove-event-listeners'; import each from './utils/each'; import {merge} from './utils/merge'; import {extend} from './utils/extend'; import inherit from './utils/inherit'; -import bindFn from './utils/bindFn'; +import bindFn from './utils/bind-fn'; import prefixed from './utils/prefixed'; -import toArray from'./utils/toArray'; -import uniqueArray from'./utils/uniqueArray'; -import splitStr from'./utils/splitStr'; -import inArray from'./utils/inArray'; -import boolOrFn from'./utils/boolOrFn'; -import hasParent from'./utils/hasParent'; +import toArray from'./utils/to-array'; +import uniqueArray from'./utils/unique-array'; +import splitStr from'./utils/split-str'; +import inArray from'./utils/in-array'; +import boolOrFn from'./utils/bool-or-fn'; +import hasParent from'./utils/has-parent'; // this prevents errors when Hammer is loaded in the presence of an AMD // style loader but by script tag, not by the loader. diff --git a/src/manager.js b/src/manager.js index 0ddfcb2be..2a51a6ed1 100644 --- a/src/manager.js +++ b/src/manager.js @@ -1,14 +1,14 @@ import {assign} from './utils/assign'; import {Hammer} from './hammer'; -import {TouchAction} from './touchactionjs/touchActionConstructor'; -import createInputInstance from './inputjs/createInputInstance'; +import {TouchAction} from './touchactionjs/touchaction-constructor'; +import createInputInstance from './inputjs/create-input-instance'; import each from './utils/each'; -import inArray from './utils/inArray'; -import invokeArrayArg from './utils/invokeArrayArg'; -import splitStr from './utils/splitStr'; +import inArray from './utils/in-array'; +import invokeArrayArg from './utils/invoke-array-arg'; +import splitStr from './utils/split-str'; import prefixed from './utils/prefixed'; -import {Recognizer} from './recognizerjs/recognizerConstructor'; -import {STATE_BEGAN,STATE_ENDED,STATE_CHANGED,STATE_RECOGNIZED} from './recognizerjs/recognizerConsts'; +import {Recognizer} from './recognizerjs/recognizer-constructor'; +import {STATE_BEGAN,STATE_ENDED,STATE_CHANGED,STATE_RECOGNIZED} from './recognizerjs/recognizer-consts'; var STOP = 1; var FORCED_STOP = 2; diff --git a/src/recognizerjs/directionStr.js b/src/recognizerjs/direction-str.js similarity index 93% rename from src/recognizerjs/directionStr.js rename to src/recognizerjs/direction-str.js index d6d6da84d..e20e2f7ab 100644 --- a/src/recognizerjs/directionStr.js +++ b/src/recognizerjs/direction-str.js @@ -1,4 +1,4 @@ -import {DIRECTION_LEFT,DIRECTION_RIGHT,DIRECTION_UP,DIRECTION_DOWN} from '../inputjs/inputConsts'; +import {DIRECTION_LEFT,DIRECTION_RIGHT,DIRECTION_UP,DIRECTION_DOWN} from '../inputjs/input-consts'; /** * direction cons to string diff --git a/src/recognizerjs/getRecognizerByNameIfManager.js b/src/recognizerjs/get-recognizer-by-name-if-manager.js similarity index 100% rename from src/recognizerjs/getRecognizerByNameIfManager.js rename to src/recognizerjs/get-recognizer-by-name-if-manager.js diff --git a/src/recognizerjs/recognizerConstructor.js b/src/recognizerjs/recognizer-constructor.js similarity index 95% rename from src/recognizerjs/recognizerConstructor.js rename to src/recognizerjs/recognizer-constructor.js index 7ae60afe1..a4153647a 100644 --- a/src/recognizerjs/recognizerConstructor.js +++ b/src/recognizerjs/recognizer-constructor.js @@ -1,13 +1,13 @@ import {STATE_POSSIBLE,STATE_ENDED,STATE_FAILED,STATE_RECOGNIZED,STATE_CANCELLED, - STATE_BEGAN,STATE_CHANGED} from './recognizerConsts'; + STATE_BEGAN,STATE_CHANGED} from './recognizer-consts'; import {assign} from '../utils/assign'; -import uniqueId from '../utils/uniqueId'; -import ifUndefined from '../utils/ifUndefined'; -import invokeArrayArg from '../utils/invokeArrayArg'; -import inArray from '../utils/inArray'; -import boolOrFn from '../utils/boolOrFn'; -import getRecognizerByNameIfManager from './getRecognizerByNameIfManager'; -import stateStr from './stateStr'; +import uniqueId from '../utils/unique-id'; +import ifUndefined from '../utils/if-undefined'; +import invokeArrayArg from '../utils/invoke-array-arg'; +import inArray from '../utils/in-array'; +import boolOrFn from '../utils/bool-or-fn'; +import getRecognizerByNameIfManager from './get-recognizer-by-name-if-manager'; +import stateStr from './state-str'; /** * Recognizer flow explained; * diff --git a/src/recognizerjs/recognizerConsts.js b/src/recognizerjs/recognizer-consts.js similarity index 100% rename from src/recognizerjs/recognizerConsts.js rename to src/recognizerjs/recognizer-consts.js diff --git a/src/recognizerjs/stateStr.js b/src/recognizerjs/state-str.js similarity index 94% rename from src/recognizerjs/stateStr.js rename to src/recognizerjs/state-str.js index e9f740d89..475e92560 100644 --- a/src/recognizerjs/stateStr.js +++ b/src/recognizerjs/state-str.js @@ -1,4 +1,4 @@ -import {STATE_CANCELLED,STATE_ENDED,STATE_CHANGED,STATE_BEGAN} from './recognizerConsts'; +import {STATE_CANCELLED,STATE_ENDED,STATE_CHANGED,STATE_BEGAN} from './recognizer-consts'; /** * get a usable string, used as event postfix diff --git a/src/recognizers/attribute.js b/src/recognizers/attribute.js index 257488e34..b4749e30f 100644 --- a/src/recognizers/attribute.js +++ b/src/recognizers/attribute.js @@ -1,7 +1,7 @@ import inherit from '../utils/inherit'; -import {Recognizer} from '../recognizerjs/recognizerConstructor'; -import {STATE_BEGAN,STATE_CHANGED,STATE_CANCELLED,STATE_ENDED,STATE_FAILED} from '../recognizerjs/recognizerConsts'; -import {INPUT_CANCEL,INPUT_END} from '../inputjs/inputConsts'; +import {Recognizer} from '../recognizerjs/recognizer-constructor'; +import {STATE_BEGAN,STATE_CHANGED,STATE_CANCELLED,STATE_ENDED,STATE_FAILED} from '../recognizerjs/recognizer-consts'; +import {INPUT_CANCEL,INPUT_END} from '../inputjs/input-consts'; /** * This recognizer is just used as a base for the simple attribute recognizers. diff --git a/src/recognizers/pan.js b/src/recognizers/pan.js index e6a932914..1ea661ac4 100644 --- a/src/recognizers/pan.js +++ b/src/recognizers/pan.js @@ -1,10 +1,10 @@ import {AttrRecognizer} from './attribute'; import inherit from '../utils/inherit'; import {DIRECTION_ALL,DIRECTION_HORIZONTAL,DIRECTION_VERTICAL,DIRECTION_NONE,DIRECTION_UP,DIRECTION_DOWN, -DIRECTION_LEFT,DIRECTION_RIGHT} from '../inputjs/inputConsts'; -import {STATE_BEGAN} from '../recognizerjs/recognizerConsts'; -import {TOUCH_ACTION_PAN_X,TOUCH_ACTION_PAN_Y} from '../touchactionjs/touchactionConsts'; -import directionStr from '../recognizerjs/directionStr'; +DIRECTION_LEFT,DIRECTION_RIGHT} from '../inputjs/input-consts'; +import {STATE_BEGAN} from '../recognizerjs/recognizer-consts'; +import {TOUCH_ACTION_PAN_X,TOUCH_ACTION_PAN_Y} from '../touchactionjs/touchaction-Consts'; +import directionStr from '../recognizerjs/direction-str'; /** * Pan diff --git a/src/recognizers/pinch.js b/src/recognizers/pinch.js index b35bd433f..6a8a399f6 100644 --- a/src/recognizers/pinch.js +++ b/src/recognizers/pinch.js @@ -1,7 +1,7 @@ import {AttrRecognizer} from './attribute'; import inherit from '../utils/inherit'; -import {TOUCH_ACTION_NONE} from '../touchactionjs/touchactionConsts'; -import {STATE_BEGAN} from '../recognizerjs/recognizerConsts'; +import {TOUCH_ACTION_NONE} from '../touchactionjs/touchaction-Consts'; +import {STATE_BEGAN} from '../recognizerjs/recognizer-consts'; /** * Pinch diff --git a/src/recognizers/press.js b/src/recognizers/press.js index 185d3a4b2..eda7ad53c 100644 --- a/src/recognizers/press.js +++ b/src/recognizers/press.js @@ -1,10 +1,10 @@ -import {Recognizer} from '../recognizerjs/recognizerConstructor'; -import {STATE_RECOGNIZED,STATE_FAILED} from '../recognizerjs/recognizerConsts'; +import {Recognizer} from '../recognizerjs/recognizer-constructor'; +import {STATE_RECOGNIZED,STATE_FAILED} from '../recognizerjs/recognizer-consts'; import inherit from '../utils/inherit'; -import {now} from '../utils/utilsConsts'; -import setTimeoutContext from '../utils/setTimeoutContext'; -import {TOUCH_ACTION_AUTO} from '../touchactionjs/touchactionConsts'; -import {INPUT_START,INPUT_END,INPUT_CANCEL} from '../inputjs/inputConsts'; +import {now} from '../utils/utils-consts'; +import setTimeoutContext from '../utils/set-timeout-context'; +import {TOUCH_ACTION_AUTO} from '../touchactionjs/touchaction-Consts'; +import {INPUT_START,INPUT_END,INPUT_CANCEL} from '../inputjs/input-consts'; /** * Press diff --git a/src/recognizers/rotate.js b/src/recognizers/rotate.js index cf8270245..696351c20 100644 --- a/src/recognizers/rotate.js +++ b/src/recognizers/rotate.js @@ -1,7 +1,7 @@ import {AttrRecognizer} from './attribute'; import inherit from '../utils/inherit'; -import {TOUCH_ACTION_NONE} from '../touchactionjs/touchactionConsts'; -import {STATE_BEGAN} from '../recognizerjs/recognizerConsts'; +import {TOUCH_ACTION_NONE} from '../touchactionjs/touchaction-Consts'; +import {STATE_BEGAN} from '../recognizerjs/recognizer-consts'; /** * Rotate diff --git a/src/recognizers/swipe.js b/src/recognizers/swipe.js index bee3699b8..423255f9e 100644 --- a/src/recognizers/swipe.js +++ b/src/recognizers/swipe.js @@ -1,10 +1,10 @@ import {AttrRecognizer} from '../recognizers/attribute'; import inherit from '../utils/inherit'; -import {abs} from '../utils/utilsConsts'; -import {DIRECTION_HORIZONTAL,DIRECTION_VERTICAL} from '../inputjs/inputConsts'; +import {abs} from '../utils/utils-consts'; +import {DIRECTION_HORIZONTAL,DIRECTION_VERTICAL} from '../inputjs/input-consts'; import {PanRecognizer} from './pan'; -import {INPUT_END} from '../inputjs/inputConsts'; -import directionStr from '../recognizerjs/directionStr'; +import {INPUT_END} from '../inputjs/input-consts'; +import directionStr from '../recognizerjs/direction-str'; /** * Swipe diff --git a/src/recognizers/tap.js b/src/recognizers/tap.js index 075e7dc88..cc5192af8 100644 --- a/src/recognizers/tap.js +++ b/src/recognizers/tap.js @@ -1,10 +1,10 @@ import inherit from '../utils/inherit'; -import setTimeoutContext from '../utils/setTimeoutContext'; -import {Recognizer} from '../recognizerjs/recognizerConstructor'; -import {TOUCH_ACTION_MANIPULATION} from '../touchactionjs/touchactionConsts'; -import {INPUT_START,INPUT_END} from '../inputjs/inputConsts'; -import {STATE_RECOGNIZED,STATE_BEGAN,STATE_FAILED} from '../recognizerjs/recognizerConsts'; -import getDistance from '../inputjs/getDistance'; +import setTimeoutContext from '../utils/set-timeout-context'; +import {Recognizer} from '../recognizerjs/recognizer-constructor'; +import {TOUCH_ACTION_MANIPULATION} from '../touchactionjs/touchaction-Consts'; +import {INPUT_START,INPUT_END} from '../inputjs/input-consts'; +import {STATE_RECOGNIZED,STATE_BEGAN,STATE_FAILED} from '../recognizerjs/recognizer-consts'; +import getDistance from '../inputjs/get-distance'; /** * A tap is recognized when the pointer is doing a small tap/click. Multiple taps are recognized if they occur diff --git a/src/touchactionjs/cleanTouchActions.js b/src/touchactionjs/clean-touch-actions.js similarity index 93% rename from src/touchactionjs/cleanTouchActions.js rename to src/touchactionjs/clean-touch-actions.js index f651834a5..c41e8b4aa 100644 --- a/src/touchactionjs/cleanTouchActions.js +++ b/src/touchactionjs/clean-touch-actions.js @@ -1,6 +1,6 @@ -import inStr from '../utils/inStr'; +import inStr from '../utils/in-str'; import {TOUCH_ACTION_NONE,TOUCH_ACTION_PAN_X,TOUCH_ACTION_PAN_Y,TOUCH_ACTION_MANIPULATION, -TOUCH_ACTION_AUTO} from './touchactionConsts'; +TOUCH_ACTION_AUTO} from './touchaction-Consts'; /** * when the touchActions are collected they are not a valid value, so we need to clean things up. * diff --git a/src/touchactionjs/getTouchActionProps.js b/src/touchactionjs/get-touchaction-props.js similarity index 90% rename from src/touchactionjs/getTouchActionProps.js rename to src/touchactionjs/get-touchaction-props.js index 5eee7e992..dad2d26d5 100644 --- a/src/touchactionjs/getTouchActionProps.js +++ b/src/touchactionjs/get-touchaction-props.js @@ -1,4 +1,4 @@ -import {NATIVE_TOUCH_ACTION} from './touchactionConsts'; +import {NATIVE_TOUCH_ACTION} from './touchaction-Consts'; export default function getTouchActionProps() { if (!NATIVE_TOUCH_ACTION) { diff --git a/src/touchactionjs/touchactionConsts.js b/src/touchactionjs/touchaction-Consts.js similarity index 86% rename from src/touchactionjs/touchactionConsts.js rename to src/touchactionjs/touchaction-Consts.js index 344aebddc..6f157e719 100644 --- a/src/touchactionjs/touchactionConsts.js +++ b/src/touchactionjs/touchaction-Consts.js @@ -1,6 +1,6 @@ import prefixed from '../utils/prefixed'; -import {TEST_ELEMENT} from '../utils/utilsConsts'; -import getTouchActionProps from './getTouchActionProps'; +import {TEST_ELEMENT} from '../utils/utils-consts'; +import getTouchActionProps from './get-touchaction-props'; var PREFIXED_TOUCH_ACTION = prefixed(TEST_ELEMENT.style, 'touchAction'); var NATIVE_TOUCH_ACTION = PREFIXED_TOUCH_ACTION !== undefined; diff --git a/src/touchactionjs/touchActionConstructor.js b/src/touchactionjs/touchaction-constructor.js similarity index 93% rename from src/touchactionjs/touchActionConstructor.js rename to src/touchactionjs/touchaction-constructor.js index bbccdd84f..a1fd8074a 100644 --- a/src/touchactionjs/touchActionConstructor.js +++ b/src/touchactionjs/touchaction-constructor.js @@ -1,10 +1,10 @@ import {TOUCH_ACTION_COMPUTE,TOUCH_ACTION_MAP,NATIVE_TOUCH_ACTION,PREFIXED_TOUCH_ACTION,TOUCH_ACTION_NONE, -TOUCH_ACTION_PAN_X,TOUCH_ACTION_PAN_Y} from './touchactionConsts'; -import {DIRECTION_VERTICAL,DIRECTION_HORIZONTAL} from '../inputjs/inputConsts'; +TOUCH_ACTION_PAN_X,TOUCH_ACTION_PAN_Y} from './touchaction-Consts'; +import {DIRECTION_VERTICAL,DIRECTION_HORIZONTAL} from '../inputjs/input-consts'; import each from '../utils/each'; -import boolOrFn from '../utils/boolOrFn'; -import inStr from '../utils/inStr'; -import cleanTouchActions from './cleanTouchActions'; +import boolOrFn from '../utils/bool-or-fn'; +import inStr from '../utils/in-str'; +import cleanTouchActions from './clean-touch-actions'; /** * Touch Action diff --git a/src/utils/addEventListeners.js b/src/utils/add-event-listeners.js similarity index 90% rename from src/utils/addEventListeners.js rename to src/utils/add-event-listeners.js index ee70ec74a..ec6e42462 100644 --- a/src/utils/addEventListeners.js +++ b/src/utils/add-event-listeners.js @@ -1,5 +1,5 @@ import each from './each'; -import splitStr from './splitStr'; +import splitStr from './split-str'; /** * addEventListener with multiple events at once * @param {EventTarget} target diff --git a/src/utils/bindFn.js b/src/utils/bind-fn.js similarity index 100% rename from src/utils/bindFn.js rename to src/utils/bind-fn.js diff --git a/src/utils/boolOrFn.js b/src/utils/bool-or-fn.js similarity index 89% rename from src/utils/boolOrFn.js rename to src/utils/bool-or-fn.js index 4971b0c20..a0bed137d 100644 --- a/src/utils/boolOrFn.js +++ b/src/utils/bool-or-fn.js @@ -1,4 +1,4 @@ -import {TYPE_FUNCTION} from './utilsConsts'; +import {TYPE_FUNCTION} from './utils-consts'; /** * let a boolean value also be a function that must return a boolean * this first item in args will be used as the context diff --git a/src/utils/getWindowForElement.js b/src/utils/get-window-for-element.js similarity index 100% rename from src/utils/getWindowForElement.js rename to src/utils/get-window-for-element.js diff --git a/src/utils/hasParent.js b/src/utils/has-parent.js similarity index 100% rename from src/utils/hasParent.js rename to src/utils/has-parent.js diff --git a/src/utils/ifUndefined.js b/src/utils/if-undefined.js similarity index 100% rename from src/utils/ifUndefined.js rename to src/utils/if-undefined.js diff --git a/src/utils/inArray.js b/src/utils/in-array.js similarity index 100% rename from src/utils/inArray.js rename to src/utils/in-array.js diff --git a/src/utils/inStr.js b/src/utils/in-str.js similarity index 100% rename from src/utils/inStr.js rename to src/utils/in-str.js diff --git a/src/utils/invokeArrayArg.js b/src/utils/invoke-array-arg.js similarity index 100% rename from src/utils/invokeArrayArg.js rename to src/utils/invoke-array-arg.js diff --git a/src/utils/prefixed.js b/src/utils/prefixed.js index 8d9b803b1..56ea42a98 100644 --- a/src/utils/prefixed.js +++ b/src/utils/prefixed.js @@ -1,4 +1,4 @@ -import {VENDOR_PREFIXES} from './utilsConsts'; +import {VENDOR_PREFIXES} from './utils-consts'; /** * get the prefixed property * @param {Object} obj diff --git a/src/utils/removeEventListeners.js b/src/utils/remove-event-listeners.js similarity index 90% rename from src/utils/removeEventListeners.js rename to src/utils/remove-event-listeners.js index 2b51bf1d0..4cbeee958 100644 --- a/src/utils/removeEventListeners.js +++ b/src/utils/remove-event-listeners.js @@ -1,5 +1,5 @@ import each from './each'; -import splitStr from './splitStr'; +import splitStr from './split-str'; /** * removeEventListener with multiple events at once * @param {EventTarget} target diff --git a/src/utils/setTimeoutContext.js b/src/utils/set-timeout-context.js similarity index 89% rename from src/utils/setTimeoutContext.js rename to src/utils/set-timeout-context.js index 60077a626..4b1e7f84b 100644 --- a/src/utils/setTimeoutContext.js +++ b/src/utils/set-timeout-context.js @@ -1,4 +1,4 @@ -import bindFn from './bindFn'; +import bindFn from './bind-fn'; /** * set a timeout with a given scope diff --git a/src/utils/splitStr.js b/src/utils/split-str.js similarity index 100% rename from src/utils/splitStr.js rename to src/utils/split-str.js diff --git a/src/utils/toArray.js b/src/utils/to-array.js similarity index 100% rename from src/utils/toArray.js rename to src/utils/to-array.js diff --git a/src/utils/uniqueArray.js b/src/utils/unique-array.js similarity index 95% rename from src/utils/uniqueArray.js rename to src/utils/unique-array.js index fd7d776c0..254823edc 100644 --- a/src/utils/uniqueArray.js +++ b/src/utils/unique-array.js @@ -1,4 +1,4 @@ -import inArray from './inArray'; +import inArray from './in-array'; /** * unique array with objects based on a key (like 'id') or just by the array's value diff --git a/src/utils/uniqueId.js b/src/utils/unique-id.js similarity index 100% rename from src/utils/uniqueId.js rename to src/utils/unique-id.js diff --git a/src/utils/utilsConsts.js b/src/utils/utils-consts.js similarity index 100% rename from src/utils/utilsConsts.js rename to src/utils/utils-consts.js From 3e494f4f53f4988bd39bf3c3dddf45b6b1af52cb Mon Sep 17 00:00:00 2001 From: Arjun Kathuria Date: Sun, 12 Jun 2016 22:38:55 +0530 Subject: [PATCH 28/61] chore(cleanup): remove redundant files --- Gruntfile.coffee | 22 ---------------- rollup.config.js | 16 ------------ src/expose.js | 67 ------------------------------------------------ 3 files changed, 105 deletions(-) delete mode 100644 rollup.config.js delete mode 100644 src/expose.js diff --git a/Gruntfile.coffee b/Gruntfile.coffee index 1d3b0321b..e23cf5275 100644 --- a/Gruntfile.coffee +++ b/Gruntfile.coffee @@ -34,28 +34,6 @@ module.exports = (grunt) -> sourceMap: 'hammer.min.map' files: 'hammer.min.js': ['hammer.js'] - # special test build that exposes everything so it's testable, now the test build is produced via rollup -c in terminal - # the output is /tests/testBuild.js -# test: -# options: -# wrap: "$H" -# comments: 'all' -# exportAll: true -# mangle: false -# beautify: true -# compress: -# global_defs: -# exportName: 'Hammer' -# files: -# 'tests/build.js': [ -# 'src/utils/*.js' -# 'src/inputjs/*.js' -# 'src/input/*.js' -# 'src/touchactionjs/*.js' -# 'src/recognizerjs/*.js' -# 'src/recognizers/*.js' -# 'src/hammer.js' -# 'src/manager.js'] 'string-replace': version: diff --git a/rollup.config.js b/rollup.config.js deleted file mode 100644 index c91de8eae..000000000 --- a/rollup.config.js +++ /dev/null @@ -1,16 +0,0 @@ -/** - * Created by arjun on 28/05/16. - */ - -import babel from 'rollup-plugin-babel'; - -export default { - entry: 'src/main.js', - format: 'es6', - // moduleName: 'HAMMER', - plugins: [ babel({exclude: 'node_modules/**'}) ], - dest: 'hammer.js', - intro: " (function(window, document, exportName, undefined) { \n'use strict' ", - outro: "})(window, document, 'Hammer');" - -}; \ No newline at end of file diff --git a/src/expose.js b/src/expose.js deleted file mode 100644 index 1fe14db25..000000000 --- a/src/expose.js +++ /dev/null @@ -1,67 +0,0 @@ -assign(Hammer, { - INPUT_START: INPUT_START, - INPUT_MOVE: INPUT_MOVE, - INPUT_END: INPUT_END, - INPUT_CANCEL: INPUT_CANCEL, - - STATE_POSSIBLE: STATE_POSSIBLE, - STATE_BEGAN: STATE_BEGAN, - STATE_CHANGED: STATE_CHANGED, - STATE_ENDED: STATE_ENDED, - STATE_RECOGNIZED: STATE_RECOGNIZED, - STATE_CANCELLED: STATE_CANCELLED, - STATE_FAILED: STATE_FAILED, - - DIRECTION_NONE: DIRECTION_NONE, - DIRECTION_LEFT: DIRECTION_LEFT, - DIRECTION_RIGHT: DIRECTION_RIGHT, - DIRECTION_UP: DIRECTION_UP, - DIRECTION_DOWN: DIRECTION_DOWN, - DIRECTION_HORIZONTAL: DIRECTION_HORIZONTAL, - DIRECTION_VERTICAL: DIRECTION_VERTICAL, - DIRECTION_ALL: DIRECTION_ALL, - - Manager: Manager, - Input: Input, - TouchAction: TouchAction, - - TouchInput: TouchInput, - MouseInput: MouseInput, - PointerEventInput: PointerEventInput, - TouchMouseInput: TouchMouseInput, - SingleTouchInput: SingleTouchInput, - - Recognizer: Recognizer, - AttrRecognizer: AttrRecognizer, - Tap: TapRecognizer, - Pan: PanRecognizer, - Swipe: SwipeRecognizer, - Pinch: PinchRecognizer, - Rotate: RotateRecognizer, - Press: PressRecognizer, - - on: addEventListeners, - off: removeEventListeners, - each: each, - merge: merge, - extend: extend, - assign: assign, - inherit: inherit, - bindFn: bindFn, - prefixed: prefixed -}); - -// this prevents errors when Hammer is loaded in the presence of an AMD -// style loader but by script tag, not by the loader. -var freeGlobal = (typeof window !== 'undefined' ? window : (typeof self !== 'undefined' ? self : {})); // jshint ignore:line -freeGlobal.Hammer = Hammer; - -if (typeof define === 'function' && define.amd) { - define(function() { - return Hammer; - }); -} else if (typeof module != 'undefined' && module.exports) { - module.exports = Hammer; -} else { - window[exportName] = Hammer; -} From d5722733a95704183f33791be3fb4957ba24091e Mon Sep 17 00:00:00 2001 From: Arjun Kathuria Date: Sun, 12 Jun 2016 23:28:07 +0530 Subject: [PATCH 29/61] style(formatting): formats imports & exports with nice spacing and indentations --- src/hammer.js | 20 +++--- src/input/mouse.js | 11 ++- src/input/pointerevent.js | 16 +++-- src/input/singletouch.js | 12 +++- src/input/touch.js | 12 +++- src/input/touchmouse.js | 16 +++-- src/inputjs/compute-delta-xy.js | 2 +- src/inputjs/compute-input-data.js | 4 +- src/inputjs/compute-interval-input-data.js | 4 +- src/inputjs/create-input-instance.js | 10 +-- src/inputjs/get-angle.js | 2 +- src/inputjs/get-center.js | 2 +- src/inputjs/get-direction.js | 4 +- src/inputjs/get-distance.js | 2 +- src/inputjs/get-rotation.js | 2 +- src/inputjs/get-scale.js | 2 +- src/inputjs/input-constructor.js | 2 +- src/inputjs/input-consts.js | 30 +++++++-- src/inputjs/input-handler.js | 2 +- src/inputjs/simple-clone-input-data.js | 2 +- src/main.js | 70 +++++++++++++------- src/manager.js | 17 +++-- src/recognizerjs/direction-str.js | 7 +- src/recognizerjs/recognizer-constructor.js | 15 +++-- src/recognizerjs/recognizer-consts.js | 10 ++- src/recognizerjs/state-str.js | 7 +- src/recognizers/attribute.js | 17 +++-- src/recognizers/pan.js | 20 ++++-- src/recognizers/pinch.js | 8 +-- src/recognizers/press.js | 19 ++++-- src/recognizers/rotate.js | 6 +- src/recognizers/swipe.js | 12 ++-- src/recognizers/tap.js | 14 ++-- src/touchactionjs/clean-touch-actions.js | 9 ++- src/touchactionjs/get-touchaction-props.js | 2 +- src/touchactionjs/touchaction-Consts.js | 16 +++-- src/touchactionjs/touchaction-constructor.js | 18 +++-- src/utils/assign.js | 2 +- src/utils/bool-or-fn.js | 2 +- src/utils/extend.js | 2 +- src/utils/inherit.js | 2 +- src/utils/merge.js | 4 +- src/utils/prefixed.js | 2 +- src/utils/utils-consts.js | 9 ++- 44 files changed, 303 insertions(+), 144 deletions(-) diff --git a/src/hammer.js b/src/hammer.js index e133a9962..7fc656f16 100644 --- a/src/hammer.js +++ b/src/hammer.js @@ -1,13 +1,13 @@ import ifUndefined from './utils/if-undefined'; -import {TOUCH_ACTION_COMPUTE} from './touchactionjs/touchaction-Consts'; -import {DIRECTION_HORIZONTAL} from './inputjs/input-consts'; -import {RotateRecognizer} from './recognizers/rotate'; -import {PinchRecognizer} from './recognizers/pinch'; -import {SwipeRecognizer} from './recognizers/swipe'; -import {PanRecognizer} from './recognizers/pan'; -import {TapRecognizer} from './recognizers/tap'; -import {PressRecognizer} from './recognizers/press'; -import {Manager} from './manager'; +import { TOUCH_ACTION_COMPUTE } from './touchactionjs/touchaction-Consts'; +import { DIRECTION_HORIZONTAL } from './inputjs/input-consts'; +import { RotateRecognizer } from './recognizers/rotate'; +import { PinchRecognizer } from './recognizers/pinch'; +import { SwipeRecognizer } from './recognizers/swipe'; +import { PanRecognizer } from './recognizers/pan'; +import { TapRecognizer } from './recognizers/tap'; +import { PressRecognizer } from './recognizers/press'; +import { Manager } from './manager'; /** * Simple way to create a manager with a default set of recognizers. @@ -138,4 +138,4 @@ Hammer.defaults = { } }; -export {Hammer}; +export { Hammer }; diff --git a/src/input/mouse.js b/src/input/mouse.js index 0a089fff1..2a5b6c2e9 100644 --- a/src/input/mouse.js +++ b/src/input/mouse.js @@ -1,5 +1,10 @@ -import {INPUT_START,INPUT_MOVE,INPUT_END,INPUT_TYPE_MOUSE} from '../inputjs/input-consts'; -import {Input} from '../inputjs/input-constructor'; +import { + INPUT_START, + INPUT_MOVE, + INPUT_END, + INPUT_TYPE_MOUSE +} from '../inputjs/input-consts'; +import { Input } from '../inputjs/input-constructor'; import inherit from '../utils/inherit'; var MOUSE_INPUT_MAP = { @@ -60,4 +65,4 @@ inherit(MouseInput, Input, { } }); -export {MouseInput}; +export { MouseInput }; diff --git a/src/input/pointerevent.js b/src/input/pointerevent.js index 2585623f4..56f2a8be3 100644 --- a/src/input/pointerevent.js +++ b/src/input/pointerevent.js @@ -1,6 +1,14 @@ -import {INPUT_START,INPUT_END,INPUT_CANCEL,INPUT_MOVE,INPUT_TYPE_TOUCH, -INPUT_TYPE_MOUSE,INPUT_TYPE_PEN,INPUT_TYPE_KINECT} from '../inputjs/input-consts'; -import {Input} from '../inputjs/input-constructor'; +import { + INPUT_START, + INPUT_END, + INPUT_CANCEL, + INPUT_MOVE, + INPUT_TYPE_TOUCH, + INPUT_TYPE_MOUSE, + INPUT_TYPE_PEN, + INPUT_TYPE_KINECT +} from '../inputjs/input-consts'; +import { Input } from '../inputjs/input-constructor'; import inherit from '../utils/inherit'; import inArray from '../utils/in-array'; @@ -93,4 +101,4 @@ inherit(PointerEventInput, Input, { } }); -export {PointerEventInput}; +export { PointerEventInput }; diff --git a/src/input/singletouch.js b/src/input/singletouch.js index 3f8a81fda..c937093e6 100644 --- a/src/input/singletouch.js +++ b/src/input/singletouch.js @@ -1,5 +1,11 @@ -import {INPUT_START,INPUT_MOVE,INPUT_END,INPUT_CANCEL,INPUT_TYPE_TOUCH} from '../inputjs/input-consts'; -import {Input} from '../inputjs/input-constructor'; +import { + INPUT_START, + INPUT_MOVE, + INPUT_END, + INPUT_CANCEL, + INPUT_TYPE_TOUCH +} from '../inputjs/input-consts'; +import { Input } from '../inputjs/input-constructor'; import inherit from '../utils/inherit'; import toArray from '../utils/to-array'; import uniqueArray from '../utils/unique-array'; @@ -73,4 +79,4 @@ function normalizeSingleTouches(ev, type) { return [all, changed]; } -export {SingleTouchInput}; +export { SingleTouchInput }; diff --git a/src/input/touch.js b/src/input/touch.js index 34dc160fc..7c822fc99 100644 --- a/src/input/touch.js +++ b/src/input/touch.js @@ -1,5 +1,11 @@ -import {INPUT_START,INPUT_MOVE,INPUT_END,INPUT_CANCEL,INPUT_TYPE_TOUCH} from '../inputjs/input-consts'; -import {Input} from '../inputjs/input-constructor'; +import { + INPUT_START, + INPUT_MOVE, + INPUT_END, + INPUT_CANCEL, + INPUT_TYPE_TOUCH +} from '../inputjs/input-consts'; +import { Input } from '../inputjs/input-constructor'; import inherit from '../utils/inherit'; import toArray from '../utils/to-array'; import hasParent from '../utils/has-parent'; @@ -104,4 +110,4 @@ function getTouches(ev, type) { ]; } -export {TouchInput}; +export { TouchInput }; diff --git a/src/input/touchmouse.js b/src/input/touchmouse.js index d1db3b8bd..17a8c1d72 100644 --- a/src/input/touchmouse.js +++ b/src/input/touchmouse.js @@ -1,9 +1,15 @@ -import {Input} from '../inputjs/input-constructor'; +import { Input } from '../inputjs/input-constructor'; import inherit from '../utils/inherit'; import bindFn from '../utils/bind-fn'; -import {TouchInput} from './touch'; -import {MouseInput} from './mouse'; -import {INPUT_START,INPUT_END,INPUT_CANCEL,INPUT_TYPE_TOUCH,INPUT_TYPE_MOUSE} from '../inputjs/input-consts'; +import { TouchInput } from './touch'; +import { MouseInput } from './mouse'; +import { + INPUT_START, + INPUT_END, + INPUT_CANCEL, + INPUT_TYPE_TOUCH, + INPUT_TYPE_MOUSE +} from '../inputjs/input-consts'; /** * Combined touch and mouse input @@ -101,4 +107,4 @@ function isSyntheticEvent(eventData) { return false; } -export {TouchMouseInput}; +export { TouchMouseInput }; diff --git a/src/inputjs/compute-delta-xy.js b/src/inputjs/compute-delta-xy.js index 82cffef47..ba74bc9b4 100644 --- a/src/inputjs/compute-delta-xy.js +++ b/src/inputjs/compute-delta-xy.js @@ -1,4 +1,4 @@ -import {INPUT_START,INPUT_END} from './input-consts'; +import { INPUT_START,INPUT_END } from './input-consts'; export default function computeDeltaXY(session, input) { var center = input.center; diff --git a/src/inputjs/compute-input-data.js b/src/inputjs/compute-input-data.js index 24906e60a..31d46310c 100644 --- a/src/inputjs/compute-input-data.js +++ b/src/inputjs/compute-input-data.js @@ -1,5 +1,5 @@ -import {now} from '../utils/utils-consts'; -import {abs} from '../utils/utils-consts'; +import { now } from '../utils/utils-consts'; +import { abs } from '../utils/utils-consts'; import hasParent from '../utils/has-parent'; import simpleCloneInputData from './simple-clone-input-data'; import getCenter from './get-center'; diff --git a/src/inputjs/compute-interval-input-data.js b/src/inputjs/compute-interval-input-data.js index 69976132f..48eb135cf 100644 --- a/src/inputjs/compute-interval-input-data.js +++ b/src/inputjs/compute-interval-input-data.js @@ -1,5 +1,5 @@ -import {INPUT_CANCEL,COMPUTE_INTERVAL} from './input-consts'; -import {abs} from '../utils/utils-consts'; +import { INPUT_CANCEL,COMPUTE_INTERVAL } from './input-consts'; +import { abs } from '../utils/utils-consts'; import getVelocity from './get-velocity'; import getDirection from './get-direction'; diff --git a/src/inputjs/create-input-instance.js b/src/inputjs/create-input-instance.js index abb661cc1..7a2e66efc 100644 --- a/src/inputjs/create-input-instance.js +++ b/src/inputjs/create-input-instance.js @@ -1,9 +1,9 @@ -import {SUPPORT_POINTER_EVENTS,SUPPORT_ONLY_TOUCH,SUPPORT_TOUCH} from './input-consts'; +import { SUPPORT_POINTER_EVENTS,SUPPORT_ONLY_TOUCH,SUPPORT_TOUCH } from './input-consts'; import inputHandler from './input-handler'; -import {PointerEventInput} from '../input/pointerevent'; -import {TouchInput} from '../input/touch'; -import {MouseInput} from '../input/mouse'; -import {TouchMouseInput} from '../input/touchmouse'; +import { PointerEventInput } from '../input/pointerevent'; +import { TouchInput } from '../input/touch'; +import { MouseInput } from '../input/mouse'; +import { TouchMouseInput } from '../input/touchmouse'; /** * create new input type manager diff --git a/src/inputjs/get-angle.js b/src/inputjs/get-angle.js index fb55e47f7..557f9c778 100644 --- a/src/inputjs/get-angle.js +++ b/src/inputjs/get-angle.js @@ -1,4 +1,4 @@ -import {PROPS_XY} from './input-consts'; +import { PROPS_XY } from './input-consts'; /** * calculate the angle between two coordinates diff --git a/src/inputjs/get-center.js b/src/inputjs/get-center.js index 70e92c12f..37f6de099 100644 --- a/src/inputjs/get-center.js +++ b/src/inputjs/get-center.js @@ -1,4 +1,4 @@ -import {round} from '../utils/utils-consts'; +import { round } from '../utils/utils-consts'; /** * get the center of all the pointers diff --git a/src/inputjs/get-direction.js b/src/inputjs/get-direction.js index e21147ee6..1e2d2674c 100644 --- a/src/inputjs/get-direction.js +++ b/src/inputjs/get-direction.js @@ -1,5 +1,5 @@ -import {abs} from '../utils/utils-consts'; -import {DIRECTION_NONE,DIRECTION_LEFT,DIRECTION_RIGHT,DIRECTION_UP,DIRECTION_DOWN} from './input-consts'; +import { abs } from '../utils/utils-consts'; +import { DIRECTION_NONE,DIRECTION_LEFT,DIRECTION_RIGHT,DIRECTION_UP,DIRECTION_DOWN } from './input-consts'; /** * get the direction between two points diff --git a/src/inputjs/get-distance.js b/src/inputjs/get-distance.js index 16d1f34a6..1ae3f4abc 100644 --- a/src/inputjs/get-distance.js +++ b/src/inputjs/get-distance.js @@ -1,4 +1,4 @@ -import {PROPS_XY} from './input-consts'; +import { PROPS_XY } from './input-consts'; /** * calculate the absolute distance between two points diff --git a/src/inputjs/get-rotation.js b/src/inputjs/get-rotation.js index 8515bce33..25c92de2d 100644 --- a/src/inputjs/get-rotation.js +++ b/src/inputjs/get-rotation.js @@ -1,5 +1,5 @@ import getAngle from './get-angle'; -import {PROPS_CLIENT_XY} from './input-consts'; +import { PROPS_CLIENT_XY } from './input-consts'; /** * calculate the rotation degrees between two pointersets diff --git a/src/inputjs/get-scale.js b/src/inputjs/get-scale.js index bf58547ba..6349d0b1f 100644 --- a/src/inputjs/get-scale.js +++ b/src/inputjs/get-scale.js @@ -1,4 +1,4 @@ -import {PROPS_CLIENT_XY} from './input-consts'; +import { PROPS_CLIENT_XY } from './input-consts'; import getDistance from './get-distance'; /** * calculate the scale factor between two pointersets diff --git a/src/inputjs/input-constructor.js b/src/inputjs/input-constructor.js index d0aaf7f91..393da64cd 100644 --- a/src/inputjs/input-constructor.js +++ b/src/inputjs/input-constructor.js @@ -55,4 +55,4 @@ Input.prototype = { } }; -export {Input}; +export { Input }; diff --git a/src/inputjs/input-consts.js b/src/inputjs/input-consts.js index 77381e5ad..1fce6dcf2 100644 --- a/src/inputjs/input-consts.js +++ b/src/inputjs/input-consts.js @@ -31,8 +31,28 @@ var DIRECTION_ALL = DIRECTION_HORIZONTAL | DIRECTION_VERTICAL; var PROPS_XY = ['x', 'y']; var PROPS_CLIENT_XY = ['clientX', 'clientY']; -export {MOBILE_REGEX,SUPPORT_ONLY_TOUCH,SUPPORT_POINTER_EVENTS,SUPPORT_TOUCH, - INPUT_TYPE_KINECT,INPUT_TYPE_MOUSE,INPUT_TYPE_PEN,INPUT_TYPE_TOUCH,COMPUTE_INTERVAL, - INPUT_START,INPUT_MOVE,INPUT_END,INPUT_CANCEL,DIRECTION_NONE,DIRECTION_LEFT, - DIRECTION_RIGHT,DIRECTION_UP,DIRECTION_DOWN,DIRECTION_HORIZONTAL, - DIRECTION_VERTICAL,DIRECTION_ALL,PROPS_XY,PROPS_CLIENT_XY}; +export { + MOBILE_REGEX, + SUPPORT_ONLY_TOUCH, + SUPPORT_POINTER_EVENTS, + SUPPORT_TOUCH, + INPUT_TYPE_KINECT, + INPUT_TYPE_MOUSE, + INPUT_TYPE_PEN, + INPUT_TYPE_TOUCH, + COMPUTE_INTERVAL, + INPUT_START, + INPUT_MOVE, + INPUT_END, + INPUT_CANCEL, + DIRECTION_NONE, + DIRECTION_LEFT, + DIRECTION_RIGHT, + DIRECTION_UP, + DIRECTION_DOWN, + DIRECTION_HORIZONTAL, + DIRECTION_VERTICAL, + DIRECTION_ALL, + PROPS_XY, + PROPS_CLIENT_XY +}; diff --git a/src/inputjs/input-handler.js b/src/inputjs/input-handler.js index 45ca1e388..ce39d0229 100644 --- a/src/inputjs/input-handler.js +++ b/src/inputjs/input-handler.js @@ -1,4 +1,4 @@ -import {INPUT_START,INPUT_END,INPUT_CANCEL} from './input-consts'; +import { INPUT_START,INPUT_END,INPUT_CANCEL } from './input-consts'; import computeInputData from './compute-input-data'; /** diff --git a/src/inputjs/simple-clone-input-data.js b/src/inputjs/simple-clone-input-data.js index b79fe216c..574f7d526 100644 --- a/src/inputjs/simple-clone-input-data.js +++ b/src/inputjs/simple-clone-input-data.js @@ -1,4 +1,4 @@ -import {now,round} from '../utils/utils-consts'; +import { now,round } from '../utils/utils-consts'; import getCenter from './get-center'; /** diff --git a/src/main.js b/src/main.js index fbf4bae44..625a522c7 100644 --- a/src/main.js +++ b/src/main.js @@ -1,34 +1,54 @@ -import {Hammer} from './hammer'; -import {assign} from './utils/assign'; -import {INPUT_START,INPUT_MOVE,INPUT_END,INPUT_CANCEL} from './inputjs/input-consts'; -import {STATE_POSSIBLE,STATE_BEGAN,STATE_CHANGED,STATE_ENDED,STATE_RECOGNIZED, - STATE_CANCELLED,STATE_FAILED} from './recognizerjs/recognizer-consts'; -import {DIRECTION_NONE,DIRECTION_LEFT,DIRECTION_RIGHT,DIRECTION_UP,DIRECTION_DOWN, - DIRECTION_HORIZONTAL,DIRECTION_VERTICAL,DIRECTION_ALL} from './inputjs/input-consts'; +import { Hammer } from './hammer'; +import assign from './utils/assign'; +import { + INPUT_START, + INPUT_MOVE, + INPUT_END, + INPUT_CANCEL +} from './inputjs/input-consts'; +import { + STATE_POSSIBLE, + STATE_BEGAN, + STATE_CHANGED, + STATE_ENDED, + STATE_RECOGNIZED, + STATE_CANCELLED, + STATE_FAILED +} from './recognizerjs/recognizer-consts'; +import { + DIRECTION_NONE, + DIRECTION_LEFT, + DIRECTION_RIGHT, + DIRECTION_UP, + DIRECTION_DOWN, + DIRECTION_HORIZONTAL, + DIRECTION_VERTICAL, + DIRECTION_ALL +} from './inputjs/input-consts'; -import {Manager} from './manager'; -import {Input} from './inputjs/input-constructor'; -import {TouchAction} from './touchactionjs/touchaction-constructor'; -import {TouchInput} from './input/touch'; -import {MouseInput} from './input/mouse'; -import {PointerEventInput} from './input/pointerevent'; -import {SingleTouchInput} from './input/singletouch'; -import {TouchMouseInput} from './input/touchmouse'; +import { Manager } from './manager'; +import { Input } from './inputjs/input-constructor'; +import { TouchAction } from './touchactionjs/touchaction-constructor'; +import { TouchInput } from './input/touch'; +import { MouseInput } from './input/mouse'; +import { PointerEventInput } from './input/pointerevent'; +import { SingleTouchInput } from './input/singletouch'; +import { TouchMouseInput } from './input/touchmouse'; -import {Recognizer} from './recognizerjs/recognizer-constructor'; -import {AttrRecognizer} from './recognizers/attribute'; -import {TapRecognizer} from './recognizers/tap'; -import {PanRecognizer} from './recognizers/pan'; -import {SwipeRecognizer} from './recognizers/swipe'; -import {PinchRecognizer} from './recognizers/pinch'; -import {RotateRecognizer} from './recognizers/rotate'; -import {PressRecognizer} from './recognizers/press'; +import { Recognizer } from './recognizerjs/recognizer-constructor'; +import { AttrRecognizer } from './recognizers/attribute'; +import { TapRecognizer } from './recognizers/tap'; +import { PanRecognizer } from './recognizers/pan'; +import { SwipeRecognizer } from './recognizers/swipe'; +import { PinchRecognizer } from './recognizers/pinch'; +import { RotateRecognizer } from './recognizers/rotate'; +import { PressRecognizer } from './recognizers/press'; import addEventListeners from './utils/add-event-listeners'; import removeEventListeners from './utils/remove-event-listeners'; import each from './utils/each'; -import {merge} from './utils/merge'; -import {extend} from './utils/extend'; +import merge from './utils/merge'; +import extend from './utils/extend'; import inherit from './utils/inherit'; import bindFn from './utils/bind-fn'; import prefixed from './utils/prefixed'; diff --git a/src/manager.js b/src/manager.js index 2a51a6ed1..ac22d560b 100644 --- a/src/manager.js +++ b/src/manager.js @@ -1,14 +1,19 @@ -import {assign} from './utils/assign'; -import {Hammer} from './hammer'; -import {TouchAction} from './touchactionjs/touchaction-constructor'; +import assign from './utils/assign'; +import { Hammer } from './hammer'; +import { TouchAction } from './touchactionjs/touchaction-constructor'; import createInputInstance from './inputjs/create-input-instance'; import each from './utils/each'; import inArray from './utils/in-array'; import invokeArrayArg from './utils/invoke-array-arg'; import splitStr from './utils/split-str'; import prefixed from './utils/prefixed'; -import {Recognizer} from './recognizerjs/recognizer-constructor'; -import {STATE_BEGAN,STATE_ENDED,STATE_CHANGED,STATE_RECOGNIZED} from './recognizerjs/recognizer-consts'; +import { Recognizer } from './recognizerjs/recognizer-constructor'; +import { + STATE_BEGAN, + STATE_ENDED, + STATE_CHANGED, + STATE_RECOGNIZED +} from './recognizerjs/recognizer-consts'; var STOP = 1; var FORCED_STOP = 2; @@ -323,4 +328,4 @@ function triggerDomEvent(event, data) { data.target.dispatchEvent(gestureEvent); } -export {Manager}; +export { Manager }; diff --git a/src/recognizerjs/direction-str.js b/src/recognizerjs/direction-str.js index e20e2f7ab..d1a1ea7ce 100644 --- a/src/recognizerjs/direction-str.js +++ b/src/recognizerjs/direction-str.js @@ -1,4 +1,9 @@ -import {DIRECTION_LEFT,DIRECTION_RIGHT,DIRECTION_UP,DIRECTION_DOWN} from '../inputjs/input-consts'; +import { + DIRECTION_LEFT, + DIRECTION_RIGHT, + DIRECTION_UP, + DIRECTION_DOWN +} from '../inputjs/input-consts'; /** * direction cons to string diff --git a/src/recognizerjs/recognizer-constructor.js b/src/recognizerjs/recognizer-constructor.js index a4153647a..e0065458c 100644 --- a/src/recognizerjs/recognizer-constructor.js +++ b/src/recognizerjs/recognizer-constructor.js @@ -1,6 +1,13 @@ -import {STATE_POSSIBLE,STATE_ENDED,STATE_FAILED,STATE_RECOGNIZED,STATE_CANCELLED, - STATE_BEGAN,STATE_CHANGED} from './recognizer-consts'; -import {assign} from '../utils/assign'; +import { + STATE_POSSIBLE, + STATE_ENDED, + STATE_FAILED, + STATE_RECOGNIZED, + STATE_CANCELLED, + STATE_BEGAN, + STATE_CHANGED +} from './recognizer-consts'; +import assign from '../utils/assign'; import uniqueId from '../utils/unique-id'; import ifUndefined from '../utils/if-undefined'; import invokeArrayArg from '../utils/invoke-array-arg'; @@ -280,4 +287,4 @@ Recognizer.prototype = { reset: function() { } }; -export {Recognizer}; +export { Recognizer }; diff --git a/src/recognizerjs/recognizer-consts.js b/src/recognizerjs/recognizer-consts.js index c3023ba24..195002e06 100644 --- a/src/recognizerjs/recognizer-consts.js +++ b/src/recognizerjs/recognizer-consts.js @@ -6,4 +6,12 @@ var STATE_RECOGNIZED = STATE_ENDED; var STATE_CANCELLED = 16; var STATE_FAILED = 32; -export {STATE_POSSIBLE,STATE_BEGAN,STATE_CHANGED,STATE_ENDED,STATE_RECOGNIZED,STATE_CANCELLED,STATE_FAILED}; +export { + STATE_POSSIBLE, + STATE_BEGAN, + STATE_CHANGED, + STATE_ENDED, + STATE_RECOGNIZED, + STATE_CANCELLED, + STATE_FAILED +}; diff --git a/src/recognizerjs/state-str.js b/src/recognizerjs/state-str.js index 475e92560..85cfd0447 100644 --- a/src/recognizerjs/state-str.js +++ b/src/recognizerjs/state-str.js @@ -1,4 +1,9 @@ -import {STATE_CANCELLED,STATE_ENDED,STATE_CHANGED,STATE_BEGAN} from './recognizer-consts'; +import { + STATE_CANCELLED, + STATE_ENDED, + STATE_CHANGED, + STATE_BEGAN +} from './recognizer-consts'; /** * get a usable string, used as event postfix diff --git a/src/recognizers/attribute.js b/src/recognizers/attribute.js index b4749e30f..e319e2fd4 100644 --- a/src/recognizers/attribute.js +++ b/src/recognizers/attribute.js @@ -1,7 +1,16 @@ import inherit from '../utils/inherit'; -import {Recognizer} from '../recognizerjs/recognizer-constructor'; -import {STATE_BEGAN,STATE_CHANGED,STATE_CANCELLED,STATE_ENDED,STATE_FAILED} from '../recognizerjs/recognizer-consts'; -import {INPUT_CANCEL,INPUT_END} from '../inputjs/input-consts'; +import { Recognizer } from '../recognizerjs/recognizer-constructor'; +import { + STATE_BEGAN, + STATE_CHANGED, + STATE_CANCELLED, + STATE_ENDED, + STATE_FAILED +} from '../recognizerjs/recognizer-consts'; +import { + INPUT_CANCEL, + INPUT_END +} from '../inputjs/input-consts'; /** * This recognizer is just used as a base for the simple attribute recognizers. @@ -64,4 +73,4 @@ inherit(AttrRecognizer, Recognizer, { } }); -export {AttrRecognizer}; +export { AttrRecognizer }; diff --git a/src/recognizers/pan.js b/src/recognizers/pan.js index 1ea661ac4..fc6d47653 100644 --- a/src/recognizers/pan.js +++ b/src/recognizers/pan.js @@ -1,9 +1,17 @@ -import {AttrRecognizer} from './attribute'; +import { AttrRecognizer } from './attribute'; import inherit from '../utils/inherit'; -import {DIRECTION_ALL,DIRECTION_HORIZONTAL,DIRECTION_VERTICAL,DIRECTION_NONE,DIRECTION_UP,DIRECTION_DOWN, -DIRECTION_LEFT,DIRECTION_RIGHT} from '../inputjs/input-consts'; -import {STATE_BEGAN} from '../recognizerjs/recognizer-consts'; -import {TOUCH_ACTION_PAN_X,TOUCH_ACTION_PAN_Y} from '../touchactionjs/touchaction-Consts'; +import { + DIRECTION_ALL, + DIRECTION_HORIZONTAL, + DIRECTION_VERTICAL, + DIRECTION_NONE, + DIRECTION_UP, + DIRECTION_DOWN, + DIRECTION_LEFT, + DIRECTION_RIGHT +} from '../inputjs/input-consts'; +import { STATE_BEGAN } from '../recognizerjs/recognizer-consts'; +import { TOUCH_ACTION_PAN_X,TOUCH_ACTION_PAN_Y } from '../touchactionjs/touchaction-Consts'; import directionStr from '../recognizerjs/direction-str'; /** @@ -86,4 +94,4 @@ inherit(PanRecognizer, AttrRecognizer, { } }); -export {PanRecognizer}; +export { PanRecognizer }; diff --git a/src/recognizers/pinch.js b/src/recognizers/pinch.js index 6a8a399f6..593fcc437 100644 --- a/src/recognizers/pinch.js +++ b/src/recognizers/pinch.js @@ -1,7 +1,7 @@ -import {AttrRecognizer} from './attribute'; +import { AttrRecognizer } from './attribute'; import inherit from '../utils/inherit'; -import {TOUCH_ACTION_NONE} from '../touchactionjs/touchaction-Consts'; -import {STATE_BEGAN} from '../recognizerjs/recognizer-consts'; +import { TOUCH_ACTION_NONE } from '../touchactionjs/touchaction-Consts'; +import { STATE_BEGAN } from '../recognizerjs/recognizer-consts'; /** * Pinch @@ -42,4 +42,4 @@ inherit(PinchRecognizer, AttrRecognizer, { } }); -export {PinchRecognizer}; +export { PinchRecognizer }; diff --git a/src/recognizers/press.js b/src/recognizers/press.js index eda7ad53c..0b8e37498 100644 --- a/src/recognizers/press.js +++ b/src/recognizers/press.js @@ -1,10 +1,17 @@ -import {Recognizer} from '../recognizerjs/recognizer-constructor'; -import {STATE_RECOGNIZED,STATE_FAILED} from '../recognizerjs/recognizer-consts'; +import { Recognizer } from '../recognizerjs/recognizer-constructor'; +import { + STATE_RECOGNIZED, + STATE_FAILED +} from '../recognizerjs/recognizer-consts'; import inherit from '../utils/inherit'; -import {now} from '../utils/utils-consts'; +import { now } from '../utils/utils-consts'; import setTimeoutContext from '../utils/set-timeout-context'; -import {TOUCH_ACTION_AUTO} from '../touchactionjs/touchaction-Consts'; -import {INPUT_START,INPUT_END,INPUT_CANCEL} from '../inputjs/input-consts'; +import { TOUCH_ACTION_AUTO } from '../touchactionjs/touchaction-Consts'; +import { + INPUT_START, + INPUT_END, + INPUT_CANCEL +} from '../inputjs/input-consts'; /** * Press @@ -77,4 +84,4 @@ inherit(PressRecognizer, Recognizer, { } }); -export {PressRecognizer}; +export { PressRecognizer }; diff --git a/src/recognizers/rotate.js b/src/recognizers/rotate.js index 696351c20..c4d3f7398 100644 --- a/src/recognizers/rotate.js +++ b/src/recognizers/rotate.js @@ -1,7 +1,7 @@ -import {AttrRecognizer} from './attribute'; +import { AttrRecognizer } from './attribute'; import inherit from '../utils/inherit'; -import {TOUCH_ACTION_NONE} from '../touchactionjs/touchaction-Consts'; -import {STATE_BEGAN} from '../recognizerjs/recognizer-consts'; +import { TOUCH_ACTION_NONE } from '../touchactionjs/touchaction-Consts'; +import { STATE_BEGAN } from '../recognizerjs/recognizer-consts'; /** * Rotate diff --git a/src/recognizers/swipe.js b/src/recognizers/swipe.js index 423255f9e..c7525b829 100644 --- a/src/recognizers/swipe.js +++ b/src/recognizers/swipe.js @@ -1,9 +1,9 @@ -import {AttrRecognizer} from '../recognizers/attribute'; +import { AttrRecognizer } from '../recognizers/attribute'; import inherit from '../utils/inherit'; -import {abs} from '../utils/utils-consts'; -import {DIRECTION_HORIZONTAL,DIRECTION_VERTICAL} from '../inputjs/input-consts'; -import {PanRecognizer} from './pan'; -import {INPUT_END} from '../inputjs/input-consts'; +import { abs } from '../utils/utils-consts'; +import { DIRECTION_HORIZONTAL,DIRECTION_VERTICAL } from '../inputjs/input-consts'; +import { PanRecognizer } from './pan'; +import { INPUT_END } from '../inputjs/input-consts'; import directionStr from '../recognizerjs/direction-str'; /** @@ -62,4 +62,4 @@ inherit(SwipeRecognizer, AttrRecognizer, { } }); -export {SwipeRecognizer}; +export { SwipeRecognizer }; diff --git a/src/recognizers/tap.js b/src/recognizers/tap.js index cc5192af8..25bbdfa60 100644 --- a/src/recognizers/tap.js +++ b/src/recognizers/tap.js @@ -1,9 +1,13 @@ import inherit from '../utils/inherit'; import setTimeoutContext from '../utils/set-timeout-context'; -import {Recognizer} from '../recognizerjs/recognizer-constructor'; -import {TOUCH_ACTION_MANIPULATION} from '../touchactionjs/touchaction-Consts'; -import {INPUT_START,INPUT_END} from '../inputjs/input-consts'; -import {STATE_RECOGNIZED,STATE_BEGAN,STATE_FAILED} from '../recognizerjs/recognizer-consts'; +import { Recognizer } from '../recognizerjs/recognizer-constructor'; +import { TOUCH_ACTION_MANIPULATION } from '../touchactionjs/touchaction-Consts'; +import {INPUT_START,INPUT_END } from '../inputjs/input-consts'; +import { + STATE_RECOGNIZED, + STATE_BEGAN, + STATE_FAILED +} from '../recognizerjs/recognizer-consts'; import getDistance from '../inputjs/get-distance'; /** @@ -121,4 +125,4 @@ inherit(TapRecognizer, Recognizer, { } }); -export {TapRecognizer}; +export { TapRecognizer }; diff --git a/src/touchactionjs/clean-touch-actions.js b/src/touchactionjs/clean-touch-actions.js index c41e8b4aa..eb09b53ee 100644 --- a/src/touchactionjs/clean-touch-actions.js +++ b/src/touchactionjs/clean-touch-actions.js @@ -1,6 +1,11 @@ import inStr from '../utils/in-str'; -import {TOUCH_ACTION_NONE,TOUCH_ACTION_PAN_X,TOUCH_ACTION_PAN_Y,TOUCH_ACTION_MANIPULATION, -TOUCH_ACTION_AUTO} from './touchaction-Consts'; +import { + TOUCH_ACTION_NONE, + TOUCH_ACTION_PAN_X, + TOUCH_ACTION_PAN_Y, + TOUCH_ACTION_MANIPULATION, + TOUCH_ACTION_AUTO +} from './touchaction-Consts'; /** * when the touchActions are collected they are not a valid value, so we need to clean things up. * diff --git a/src/touchactionjs/get-touchaction-props.js b/src/touchactionjs/get-touchaction-props.js index dad2d26d5..6432f81a1 100644 --- a/src/touchactionjs/get-touchaction-props.js +++ b/src/touchactionjs/get-touchaction-props.js @@ -1,4 +1,4 @@ -import {NATIVE_TOUCH_ACTION} from './touchaction-Consts'; +import { NATIVE_TOUCH_ACTION } from './touchaction-Consts'; export default function getTouchActionProps() { if (!NATIVE_TOUCH_ACTION) { diff --git a/src/touchactionjs/touchaction-Consts.js b/src/touchactionjs/touchaction-Consts.js index 6f157e719..b7ab89433 100644 --- a/src/touchactionjs/touchaction-Consts.js +++ b/src/touchactionjs/touchaction-Consts.js @@ -1,5 +1,5 @@ import prefixed from '../utils/prefixed'; -import {TEST_ELEMENT} from '../utils/utils-consts'; +import { TEST_ELEMENT } from '../utils/utils-consts'; import getTouchActionProps from './get-touchaction-props'; var PREFIXED_TOUCH_ACTION = prefixed(TEST_ELEMENT.style, 'touchAction'); @@ -14,6 +14,14 @@ var TOUCH_ACTION_PAN_X = 'pan-x'; var TOUCH_ACTION_PAN_Y = 'pan-y'; var TOUCH_ACTION_MAP = getTouchActionProps(); -export {PREFIXED_TOUCH_ACTION,NATIVE_TOUCH_ACTION,TOUCH_ACTION_AUTO,TOUCH_ACTION_COMPUTE, - TOUCH_ACTION_MANIPULATION,TOUCH_ACTION_NONE,TOUCH_ACTION_PAN_X,TOUCH_ACTION_PAN_Y, - TOUCH_ACTION_MAP}; +export { + PREFIXED_TOUCH_ACTION, + NATIVE_TOUCH_ACTION, + TOUCH_ACTION_AUTO, + TOUCH_ACTION_COMPUTE, + TOUCH_ACTION_MANIPULATION, + TOUCH_ACTION_NONE, + TOUCH_ACTION_PAN_X, + TOUCH_ACTION_PAN_Y, + TOUCH_ACTION_MAP +}; diff --git a/src/touchactionjs/touchaction-constructor.js b/src/touchactionjs/touchaction-constructor.js index a1fd8074a..fa238932e 100644 --- a/src/touchactionjs/touchaction-constructor.js +++ b/src/touchactionjs/touchaction-constructor.js @@ -1,6 +1,16 @@ -import {TOUCH_ACTION_COMPUTE,TOUCH_ACTION_MAP,NATIVE_TOUCH_ACTION,PREFIXED_TOUCH_ACTION,TOUCH_ACTION_NONE, -TOUCH_ACTION_PAN_X,TOUCH_ACTION_PAN_Y} from './touchaction-Consts'; -import {DIRECTION_VERTICAL,DIRECTION_HORIZONTAL} from '../inputjs/input-consts'; +import { + TOUCH_ACTION_COMPUTE, + TOUCH_ACTION_MAP, + NATIVE_TOUCH_ACTION, + PREFIXED_TOUCH_ACTION, + TOUCH_ACTION_NONE, + TOUCH_ACTION_PAN_X, + TOUCH_ACTION_PAN_Y +} from './touchaction-Consts'; +import { + DIRECTION_VERTICAL, + DIRECTION_HORIZONTAL +} from '../inputjs/input-consts'; import each from '../utils/each'; import boolOrFn from '../utils/bool-or-fn'; import inStr from '../utils/in-str'; @@ -109,4 +119,4 @@ TouchAction.prototype = { } }; -export {TouchAction}; +export { TouchAction }; diff --git a/src/utils/assign.js b/src/utils/assign.js index c002b3d3f..e4defa40e 100644 --- a/src/utils/assign.js +++ b/src/utils/assign.js @@ -29,4 +29,4 @@ if (typeof Object.assign !== 'function') { assign = Object.assign; } -export {assign}; +export default assign; diff --git a/src/utils/bool-or-fn.js b/src/utils/bool-or-fn.js index a0bed137d..e57c7ff84 100644 --- a/src/utils/bool-or-fn.js +++ b/src/utils/bool-or-fn.js @@ -1,4 +1,4 @@ -import {TYPE_FUNCTION} from './utils-consts'; +import { TYPE_FUNCTION } from './utils-consts'; /** * let a boolean value also be a function that must return a boolean * this first item in args will be used as the context diff --git a/src/utils/extend.js b/src/utils/extend.js index facab691b..8a6bc8db2 100644 --- a/src/utils/extend.js +++ b/src/utils/extend.js @@ -19,4 +19,4 @@ var extend = deprecate(function extend(dest, src, merge) { return dest; }, 'extend', 'Use `assign`.'); -export {extend}; +export default extend; diff --git a/src/utils/inherit.js b/src/utils/inherit.js index 898487680..c97ab5433 100644 --- a/src/utils/inherit.js +++ b/src/utils/inherit.js @@ -1,4 +1,4 @@ -import {assign} from './assign'; +import assign from './assign'; /** * simple class inheritance * @param {Function} child diff --git a/src/utils/merge.js b/src/utils/merge.js index ad1257d3a..48939647b 100644 --- a/src/utils/merge.js +++ b/src/utils/merge.js @@ -1,5 +1,5 @@ import deprecate from './deprecate'; -import {extend} from './extend'; +import extend from './extend'; /** * merge the values from src in the dest. * means that properties that exist in dest will not be overwritten by src @@ -11,4 +11,4 @@ var merge = deprecate(function merge(dest, src) { return extend(dest, src, true); }, 'merge', 'Use `assign`.'); -export {merge}; +export default merge; diff --git a/src/utils/prefixed.js b/src/utils/prefixed.js index 56ea42a98..dc098617a 100644 --- a/src/utils/prefixed.js +++ b/src/utils/prefixed.js @@ -1,4 +1,4 @@ -import {VENDOR_PREFIXES} from './utils-consts'; +import { VENDOR_PREFIXES } from './utils-consts'; /** * get the prefixed property * @param {Object} obj diff --git a/src/utils/utils-consts.js b/src/utils/utils-consts.js index 5e5b43a17..11903f525 100644 --- a/src/utils/utils-consts.js +++ b/src/utils/utils-consts.js @@ -7,4 +7,11 @@ var round = Math.round; var abs = Math.abs; var now = Date.now; -export {VENDOR_PREFIXES,TEST_ELEMENT,TYPE_FUNCTION,round,abs,now}; +export { + VENDOR_PREFIXES, + TEST_ELEMENT, + TYPE_FUNCTION, + round, + abs, + now +}; From e40a9bad60a6391f8c617253dcda3c4af2a546b0 Mon Sep 17 00:00:00 2001 From: Chris Thoburn Date: Mon, 13 Jun 2016 20:48:19 -0500 Subject: [PATCH 30/61] some work on the demo app --- .jscsrc | 3 + addon/-private/gestures/layer.js | 2 +- addon/-private/gestures/manager.js | 8 ++- addon/styles/addon.scss | 6 +- bower.json | 5 +- package.json | 6 +- tests/dummy/app/adapters/application.js | 1 + tests/dummy/app/index.html | 8 +-- tests/dummy/app/models/item.js | 5 +- tests/dummy/app/router.js | 3 + tests/dummy/app/routes/application/route.js | 15 +++- .../dummy/app/routes/application/template.hbs | 7 +- .../routes/components/swipe-box/component.js | 71 +++++++++++++++++++ .../routes/components/swipe-box/template.hbs | 1 + tests/dummy/app/routes/items/index/route.js | 13 ++++ .../dummy/app/routes/items/index/template.hbs | 11 +++ tests/dummy/app/routes/items/route.js | 13 ++++ tests/dummy/app/routes/items/single/route.js | 13 ++++ .../app/routes/items/single/template.hbs | 6 ++ tests/dummy/app/routes/items/template.hbs | 3 + tests/dummy/app/styles/{app.css => app.scss} | 0 tests/dummy/app/transitions.js | 23 ++++++ 22 files changed, 207 insertions(+), 16 deletions(-) create mode 100644 .jscsrc create mode 100644 tests/dummy/app/routes/components/swipe-box/component.js create mode 100644 tests/dummy/app/routes/components/swipe-box/template.hbs create mode 100644 tests/dummy/app/routes/items/index/route.js create mode 100644 tests/dummy/app/routes/items/index/template.hbs create mode 100644 tests/dummy/app/routes/items/route.js create mode 100644 tests/dummy/app/routes/items/single/route.js create mode 100644 tests/dummy/app/routes/items/single/template.hbs create mode 100644 tests/dummy/app/routes/items/template.hbs rename tests/dummy/app/styles/{app.css => app.scss} (100%) create mode 100644 tests/dummy/app/transitions.js diff --git a/.jscsrc b/.jscsrc new file mode 100644 index 000000000..e24512d0a --- /dev/null +++ b/.jscsrc @@ -0,0 +1,3 @@ +{ + "preset": "ember-suave" +} diff --git a/addon/-private/gestures/layer.js b/addon/-private/gestures/layer.js index 21218f4a4..fc311d6fe 100644 --- a/addon/-private/gestures/layer.js +++ b/addon/-private/gestures/layer.js @@ -25,6 +25,6 @@ export default class Layer { this.recognizers.push(recognizerInstance); } - emit() + emit() {} } diff --git a/addon/-private/gestures/manager.js b/addon/-private/gestures/manager.js index 7a27da19e..ee61ad4fd 100644 --- a/addon/-private/gestures/manager.js +++ b/addon/-private/gestures/manager.js @@ -16,8 +16,12 @@ export default class Manager { this.inputs = {}; this.options = assign({}, DEFAULT_OPTIONS, options || {}); - for (let { name, InputClass } of this.options.inputs) { - this.registerInput(name, InputClass); + if (this.options.inputs) { + for (let i = 0; i < this.options.inputs.length; i++) { + let { name, InputClass } = this.options.inputs[i]; + + this.registerInput(name, InputClass); + } } } diff --git a/addon/styles/addon.scss b/addon/styles/addon.scss index cc6dbe55b..273700db8 100644 --- a/addon/styles/addon.scss +++ b/addon/styles/addon.scss @@ -38,19 +38,19 @@ history-outlet { right { @include fillBlock(); z-index: 0; - willChange(80%); + @include willChange(80%); } main { @include fillBlock(); z-index: 1; - willChange(); + @include willChange(); } outlet { @include fillBlock(); z-index: 1; - willChange(); + @include willChange(); } fps { diff --git a/bower.json b/bower.json index 5724b2d04..2aa475a9e 100644 --- a/bower.json +++ b/bower.json @@ -4,6 +4,9 @@ "ember": "~2.6.0-beta.2", "ember-cli-shims": "0.1.1", "ember-cli-test-loader": "0.2.2", - "ember-qunit-notifications": "0.1.0" + "ember-qunit-notifications": "0.1.0", + "hammer.js": "2.0.6", + "hammer-time": "1.0.0", + "gsap": "1.18.2" } } diff --git a/package.json b/package.json index d4d0faa28..99c0d0c20 100644 --- a/package.json +++ b/package.json @@ -31,16 +31,20 @@ "ember-cli-release": "0.2.8", "ember-cli-sri": "^2.1.0", "ember-cli-uglify": "^1.2.0", + "ember-cli-version-checker": "^1.1.6", "ember-data": "^2.6.0-beta.1", "ember-disable-prototype-extensions": "^1.1.0", "ember-export-application-global": "^1.0.5", + "ember-gestures": "0.4.2", + "ember-hammertime": "^1.0.3", "ember-load-initializers": "^0.5.1", "ember-resolver": "^2.0.3", - "ember-welcome-page": "^1.0.1", + "ember-tweenlite": "1.0.1", "express": "^4.13.4", "faker": "^3.1.0", "flexi": "1.1.9", "glob": "^4.5.3", + "liquid-fire": "0.23.1", "loader.js": "^4.0.1", "morgan": "^1.7.0", "object-assign": "^4.1.0" diff --git a/tests/dummy/app/adapters/application.js b/tests/dummy/app/adapters/application.js index 03e214724..b37ab130e 100644 --- a/tests/dummy/app/adapters/application.js +++ b/tests/dummy/app/adapters/application.js @@ -1,4 +1,5 @@ import JSONAPIAdapter from 'ember-data/adapters/json-api'; export default JSONAPIAdapter.extend({ + namespace: 'api' }); diff --git a/tests/dummy/app/index.html b/tests/dummy/app/index.html index 5120bd73f..c9b432708 100644 --- a/tests/dummy/app/index.html +++ b/tests/dummy/app/index.html @@ -9,16 +9,16 @@ {{content-for "head"}} - - + + {{content-for "head-footer"}} {{content-for "body"}} - - + + {{content-for "body-footer"}} diff --git a/tests/dummy/app/models/item.js b/tests/dummy/app/models/item.js index 1246b0de1..fa2ed4bce 100644 --- a/tests/dummy/app/models/item.js +++ b/tests/dummy/app/models/item.js @@ -1,7 +1,8 @@ import Model from 'ember-data/model'; -// import attr from 'ember-data/attr'; +import attr from 'ember-data/attr'; // import { belongsTo, hasMany } from 'ember-data/relationships'; export default Model.extend({ - + title: attr(), + description: attr() }); diff --git a/tests/dummy/app/router.js b/tests/dummy/app/router.js index cdc257875..8bf2e61b4 100644 --- a/tests/dummy/app/router.js +++ b/tests/dummy/app/router.js @@ -7,6 +7,9 @@ const Router = Ember.Router.extend({ }); Router.map(function() { + this.route('items', { path: '/' }, function() { + this.route('single', { path: '/:id' }); + }); }); export default Router; diff --git a/tests/dummy/app/routes/application/route.js b/tests/dummy/app/routes/application/route.js index 26d9f3124..8251ca090 100644 --- a/tests/dummy/app/routes/application/route.js +++ b/tests/dummy/app/routes/application/route.js @@ -1,4 +1,17 @@ import Ember from 'ember'; -export default Ember.Route.extend({ +const { + get, + Route, + set + } = Ember; + +export default Route.extend({ + + setupController(controller, model) { + this._super(controller, model); + + set(controller, 'currentRouteName', get(this, 'routeName')); + } + }); diff --git a/tests/dummy/app/routes/application/template.hbs b/tests/dummy/app/routes/application/template.hbs index 1da2d383a..c68fcde9f 100644 --- a/tests/dummy/app/routes/application/template.hbs +++ b/tests/dummy/app/routes/application/template.hbs @@ -1 +1,6 @@ -{{history-outlet}} + + {{!-- + {{history-outlet currentRouteName=currentRouteName}} + --}} + {{outlet}} + \ No newline at end of file diff --git a/tests/dummy/app/routes/components/swipe-box/component.js b/tests/dummy/app/routes/components/swipe-box/component.js new file mode 100644 index 000000000..acb751b6f --- /dev/null +++ b/tests/dummy/app/routes/components/swipe-box/component.js @@ -0,0 +1,71 @@ +import Ember from 'ember'; +import layout from './template'; +import RecognizerMixin from 'ember-gestures/mixins/recognizers'; +import TweenLite from 'tweenlite'; + +export default Ember.Component.extend(RecognizerMixin, { + layout, + + recognizers: 'pan', + + isPanning: false, + _nextUpdate: undefined, + dX: 0, + _dX: 0, + + startAnimating() { + if (!this._nextUpdate) { + this.isPanning = true; + this._nextUpdate = requestAnimationFrame(() => { + this.updateAnimationState(); + }); + } + }, + + updateAnimationState() { + let { _dX, dX, element } = this; + + TweenLite.set(element, { css: { x: `${_dX + dX}px` }}); + + if (this.isPanning) { + this._nextUpdate = requestAnimationFrame(() => { + this.updateAnimationState(); + }); + } else { + // this._dX = _dX + dX; + this._nextUpdate = undefined; + + TweenLite.to(element, .35, { css: { x: `0px` }}); + + } + }, + + panStart() { + this.dX = 0; + this.startAnimating(); + }, + + panEnd(e) { + let { deltaX } = e.originalEvent.gesture; + + this.dX = deltaX; + this.isPanning = false; + }, + + panLeft(e) { + if (this.isPanning) { + let { deltaX } = e.originalEvent.gesture; + + this.dX = deltaX; + } + }, + + panRight(e) { + if (this.isPanning) { + let { deltaX } = e.originalEvent.gesture; + + this.dX = deltaX; + } + } + +}); diff --git a/tests/dummy/app/routes/components/swipe-box/template.hbs b/tests/dummy/app/routes/components/swipe-box/template.hbs new file mode 100644 index 000000000..889d9eead --- /dev/null +++ b/tests/dummy/app/routes/components/swipe-box/template.hbs @@ -0,0 +1 @@ +{{yield}} diff --git a/tests/dummy/app/routes/items/index/route.js b/tests/dummy/app/routes/items/index/route.js new file mode 100644 index 000000000..c738b98a6 --- /dev/null +++ b/tests/dummy/app/routes/items/index/route.js @@ -0,0 +1,13 @@ +import Ember from 'ember'; + +const { + Route + } = Ember; + +export default Route.extend({ + + model() { + return this.modelFor('items'); + } + +}); diff --git a/tests/dummy/app/routes/items/index/template.hbs b/tests/dummy/app/routes/items/index/template.hbs new file mode 100644 index 000000000..e188ed56f --- /dev/null +++ b/tests/dummy/app/routes/items/index/template.hbs @@ -0,0 +1,11 @@ +
    + {{#each model as |item|}} +
  • +

    + {{#link-to 'items.single' item}} + {{item.title}} + {{/link-to}} +

    +
  • + {{/each}} +
\ No newline at end of file diff --git a/tests/dummy/app/routes/items/route.js b/tests/dummy/app/routes/items/route.js new file mode 100644 index 000000000..a179b967f --- /dev/null +++ b/tests/dummy/app/routes/items/route.js @@ -0,0 +1,13 @@ +import Ember from 'ember'; + +const { + Route + } = Ember; + +export default Route.extend({ + + model() { + return this.get('store').findAll('item'); + } + +}); diff --git a/tests/dummy/app/routes/items/single/route.js b/tests/dummy/app/routes/items/single/route.js new file mode 100644 index 000000000..721cf6c1d --- /dev/null +++ b/tests/dummy/app/routes/items/single/route.js @@ -0,0 +1,13 @@ +import Ember from 'ember'; + +const { + Route + } = Ember; + +export default Route.extend({ + + model(params) { + return this.get('store').findRecord(params.id); + } + +}); diff --git a/tests/dummy/app/routes/items/single/template.hbs b/tests/dummy/app/routes/items/single/template.hbs new file mode 100644 index 000000000..106f4a3f6 --- /dev/null +++ b/tests/dummy/app/routes/items/single/template.hbs @@ -0,0 +1,6 @@ + +

{{model.title}}

+

+ {{model.description}} +

+
\ No newline at end of file diff --git a/tests/dummy/app/routes/items/template.hbs b/tests/dummy/app/routes/items/template.hbs new file mode 100644 index 000000000..5a6ed73c5 --- /dev/null +++ b/tests/dummy/app/routes/items/template.hbs @@ -0,0 +1,3 @@ +{{#swipe-box}} + {{liquid-outlet "main"}} +{{/swipe-box}} \ No newline at end of file diff --git a/tests/dummy/app/styles/app.css b/tests/dummy/app/styles/app.scss similarity index 100% rename from tests/dummy/app/styles/app.css rename to tests/dummy/app/styles/app.scss diff --git a/tests/dummy/app/transitions.js b/tests/dummy/app/transitions.js new file mode 100644 index 000000000..fff063440 --- /dev/null +++ b/tests/dummy/app/transitions.js @@ -0,0 +1,23 @@ +export default function() { + + // debug all + this.transition = this.transition.bind(this, this.debug()); + + /** + * Initial Render + * + * + */ + // Rule 1 + this.transition( + this.onInitialRender(), + this.use('fade', { duration: 500 }) + ); + + this.transition( + this.fromRoute('items.index'), + this.use('to-left', { duration: 350 }), + this.reverse('to-right', { duration: 350 }) + ); + +} From d842588a391011e6ca74e0b1975401056d6bf700 Mon Sep 17 00:00:00 2001 From: Chris Thoburn Date: Fri, 10 Jun 2016 13:02:37 -0500 Subject: [PATCH 31/61] feat(code-style): updates code style rules, this will cause some pain --- .editorconfig | 20 ++++++++++++ .jscsrc | 90 ++------------------------------------------------- .jshintrc | 53 ++++++++++++++++++------------ package.json | 1 + 4 files changed, 56 insertions(+), 108 deletions(-) create mode 100644 .editorconfig diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 000000000..eba5d9c20 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,20 @@ +# EditorConfig helps developers define and maintain consistent +# coding styles between different editors and IDEs +# editorconfig.org + +root = true + +[*] +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true +indent_style = space +indent_size = 2 + +[*.js] +indent_style = space +indent_size = 2 + +[*.{diff,md}] +trim_trailing_whitespace = false diff --git a/.jscsrc b/.jscsrc index b2c223815..f3c50dc51 100644 --- a/.jscsrc +++ b/.jscsrc @@ -1,95 +1,9 @@ { + "preset": "ember-suave", "excludeFiles": [ "*.js", "tests/**/assets", "node_modules/**" ], - "requireCurlyBraces": [ - "if", - "else", - "for", - "while", - "do", - "try", - "catch" - ], - "requireOperatorBeforeLineBreak": true, - "requireCamelCaseOrUpperCaseIdentifiers": true, - "maximumLineLength": { - "value": 120, - "allowComments": true, - "allowRegex": true - }, - "validateIndentation": 4, - "validateQuoteMarks": "'", - "disallowMultipleLineStrings": true, - "disallowMixedSpacesAndTabs": true, - "disallowTrailingWhitespace": true, - "disallowSpaceAfterPrefixUnaryOperators": true, - "requireSpaceAfterKeywords": [ - "if", - "else", - "for", - "while", - "do", - "switch", - "return", - "try", - "catch" - ], - "requireSpaceBeforeBinaryOperators": [ - "=", - "+=", - "-=", - "*=", - "/=", - "%=", - "<<=", - ">>=", - ">>>=", - "&=", - "|=", - "^=", - "+=", - "+", - "-", - "*", - "/", - "%", - "<<", - ">>", - ">>>", - "&", - "|", - "^", - "&&", - "||", - "===", - "==", - ">=", - "<=", - "<", - ">", - "!=", - "!==" - ], - "requireSpaceAfterBinaryOperators": true, - "requireSpacesInConditionalExpression": true, - "requireSpaceBeforeBlockStatements": true, - "requireLineFeedAtFileEnd": true, - "requireSpacesInFunctionExpression": { - "beforeOpeningCurlyBrace": true - }, - "disallowSpacesInAnonymousFunctionExpression": { - "beforeOpeningRoundBrace": true - }, - "disallowSpacesInsideObjectBrackets": "all", - "disallowSpacesInsideArrayBrackets": "all", - "disallowSpacesInsideParentheses": true, - "jsDoc": { - "checkParamNames": true, - "requireParamTypes": true - }, - "disallowMultipleLineBreaks": true, - "disallowNewlineBeforeBlockStatements": true + "disallowConstOutsideModuleScope": false } diff --git a/.jshintrc b/.jshintrc index 0182f27e7..55a1ac6f4 100644 --- a/.jshintrc +++ b/.jshintrc @@ -1,22 +1,35 @@ { - "browser": true, - "curly": true, - "eqnull": true, - "expr": true, - "maxerr": 100, - "freeze": true, - "esversion":6, - "newcap": true, - "node": true, - "strict": false, - "sub": true, - "trailing": true, - "undef": true, - "unused": true, - "camelcase": true, - "indent": 4, - "validthis": true, - "globals": { - "define": false - } + "maxerr": 100, + "freeze": true, + "node": false, + "indent": 2, + "predef": [ + "document", + "window" + ], + "browser": true, + "boss": true, + "curly": true, + "debug": false, + "devel": true, + "eqeqeq": true, + "evil": true, + "forin": false, + "immed": false, + "laxbreak": false, + "newcap": true, + "noarg": true, + "noempty": false, + "nonew": false, + "nomen": false, + "onevar": false, + "plusplus": false, + "regexp": false, + "undef": true, + "sub": true, + "strict": false, + "white": false, + "eqnull": true, + "esnext": true, + "unused": true } diff --git a/package.json b/package.json index d8f461f21..89fb3828d 100644 --- a/package.json +++ b/package.json @@ -34,6 +34,7 @@ "devDependencies": { "babel-preset-es2015-rollup": "^1.1.1", "changelogplease": "^1.2.0", + "ember-suave": "^2.0.1", "git-tags": "^0.2.4", "grunt": "0.4.x", "grunt-banner": "^0.2.3", From fa74be442f446285455d307ce33e155f7417c85d Mon Sep 17 00:00:00 2001 From: Arjun Kathuria Date: Mon, 13 Jun 2016 14:21:24 +0530 Subject: [PATCH 32/61] chore(cleanup): remove redundant files --- Gruntfile.coffee | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Gruntfile.coffee b/Gruntfile.coffee index e23cf5275..232100915 100644 --- a/Gruntfile.coffee +++ b/Gruntfile.coffee @@ -26,7 +26,7 @@ module.exports = (grunt) -> files: dest: 'hammer.js' src: 'src/main.js' - + uglify: min: options: @@ -53,7 +53,7 @@ module.exports = (grunt) -> jscs: src: [ - 'src/**/*.js' + 'src/**/*.js' ] options: config: "./.jscsrc" From 16c806271ee9da9b2f1966db387888d251bf2b77 Mon Sep 17 00:00:00 2001 From: Arjun Kathuria Date: Mon, 13 Jun 2016 14:27:29 +0530 Subject: [PATCH 33/61] style(jscs fix): files jscs src --fix fixes --- src/hammer.js | 178 +++--- src/input/mouse.js | 68 +-- src/input/pointerevent.js | 122 ++-- src/input/singletouch.js | 70 +-- src/input/touch.js | 134 ++--- src/input/touchmouse.js | 120 ++-- src/inputjs/compute-delta-xy.js | 32 +- src/inputjs/compute-input-data.js | 76 +-- src/inputjs/compute-interval-input-data.js | 46 +- src/inputjs/create-input-instance.js | 28 +- src/inputjs/get-angle.js | 12 +- src/inputjs/get-center.js | 36 +- src/inputjs/get-direction.js | 14 +- src/inputjs/get-distance.js | 12 +- src/inputjs/get-rotation.js | 2 +- src/inputjs/get-scale.js | 2 +- src/inputjs/get-velocity.js | 8 +- src/inputjs/input-constructor.js | 76 +-- src/inputjs/input-handler.js | 36 +- src/inputjs/simple-clone-input-data.js | 36 +- src/main.js | 114 ++-- src/manager.js | 546 +++++++++--------- src/recognizerjs/direction-str.js | 20 +- .../get-recognizer-by-name-if-manager.js | 10 +- src/recognizerjs/recognizer-constructor.js | 452 +++++++-------- src/recognizerjs/state-str.js | 20 +- src/recognizers/attribute.js | 86 +-- src/recognizers/pan.js | 116 ++-- src/recognizers/pinch.js | 46 +- src/recognizers/press.js | 100 ++-- src/recognizers/rotate.js | 34 +- src/recognizers/swipe.js | 76 +-- src/recognizers/tap.js | 188 +++--- src/touchactionjs/clean-touch-actions.js | 44 +- src/touchactionjs/get-touchaction-props.js | 22 +- src/touchactionjs/touchaction-constructor.js | 156 ++--- src/utils/add-event-listeners.js | 6 +- src/utils/assign.js | 34 +- src/utils/bind-fn.js | 6 +- src/utils/bool-or-fn.js | 8 +- src/utils/deprecate.js | 24 +- src/utils/each.js | 32 +- src/utils/extend.js | 16 +- src/utils/get-window-for-element.js | 4 +- src/utils/has-parent.js | 12 +- src/utils/if-undefined.js | 2 +- src/utils/in-array.js | 22 +- src/utils/in-str.js | 2 +- src/utils/inherit.js | 16 +- src/utils/invoke-array-arg.js | 10 +- src/utils/merge.js | 2 +- src/utils/prefixed.js | 22 +- src/utils/remove-event-listeners.js | 6 +- src/utils/set-timeout-context.js | 2 +- src/utils/split-str.js | 2 +- src/utils/to-array.js | 2 +- src/utils/unique-array.js | 38 +- src/utils/unique-id.js | 2 +- 58 files changed, 1704 insertions(+), 1704 deletions(-) diff --git a/src/hammer.js b/src/hammer.js index 7fc656f16..254d60b86 100644 --- a/src/hammer.js +++ b/src/hammer.js @@ -16,9 +16,9 @@ import { Manager } from './manager'; * @constructor */ function Hammer(element, options) { - options = options || {}; - options.recognizers = ifUndefined(options.recognizers, Hammer.defaults.preset); - return new Manager(element, options); + options = options || {}; + options.recognizers = ifUndefined(options.recognizers, Hammer.defaults.preset); + return new Manager(element, options); } /** @@ -31,111 +31,111 @@ Hammer.VERSION = '{{PKG_VERSION}}'; * @namespace */ Hammer.defaults = { - /** - * set if DOM events are being triggered. - * But this is slower and unused by simple implementations, so disabled by default. - * @type {Boolean} - * @default false - */ - domEvents: false, + /** + * set if DOM events are being triggered. + * But this is slower and unused by simple implementations, so disabled by default. + * @type {Boolean} + * @default false + */ + domEvents: false, + + /** + * The value for the touchAction property/fallback. + * When set to `compute` it will magically set the correct value based on the added recognizers. + * @type {String} + * @default compute + */ + touchAction: TOUCH_ACTION_COMPUTE, + + /** + * @type {Boolean} + * @default true + */ + enable: true, + + /** + * EXPERIMENTAL FEATURE -- can be removed/changed + * Change the parent input target element. + * If Null, then it is being set the to main element. + * @type {Null|EventTarget} + * @default null + */ + inputTarget: null, + /** + * force an input class + * @type {Null|Function} + * @default null + */ + inputClass: null, + + /** + * Default recognizer setup when calling `Hammer()` + * When creating a new Manager these will be skipped. + * @type {Array} + */ + preset: [ + // RecognizerClass, options, [recognizeWith, ...], [requireFailure, ...] + [RotateRecognizer, { enable: false }], + [PinchRecognizer, { enable: false }, ['rotate']], + [SwipeRecognizer, { direction: DIRECTION_HORIZONTAL }], + [PanRecognizer, { direction: DIRECTION_HORIZONTAL }, ['swipe']], + [TapRecognizer], + [TapRecognizer, { event: 'doubletap', taps: 2 }, ['tap']], + [PressRecognizer] + ], + + /** + * Some CSS properties can be used to improve the working of Hammer. + * Add them to this method and they will be set when creating a new Manager. + * @namespace + */ + cssProps: { /** - * The value for the touchAction property/fallback. - * When set to `compute` it will magically set the correct value based on the added recognizers. + * Disables text selection to improve the dragging gesture. Mainly for desktop browsers. * @type {String} - * @default compute + * @default 'none' */ - touchAction: TOUCH_ACTION_COMPUTE, + userSelect: 'none', /** - * @type {Boolean} - * @default true + * Disable the Windows Phone grippers when pressing an element. + * @type {String} + * @default 'none' */ - enable: true, + touchSelect: 'none', /** - * EXPERIMENTAL FEATURE -- can be removed/changed - * Change the parent input target element. - * If Null, then it is being set the to main element. - * @type {Null|EventTarget} - * @default null + * Disables the default callout shown when you touch and hold a touch target. + * On iOS, when you touch and hold a touch target such as a link, Safari displays + * a callout containing information about the link. This property allows you to disable that callout. + * @type {String} + * @default 'none' */ - inputTarget: null, + touchCallout: 'none', /** - * force an input class - * @type {Null|Function} - * @default null + * Specifies whether zooming is enabled. Used by IE10> + * @type {String} + * @default 'none' */ - inputClass: null, + contentZooming: 'none', /** - * Default recognizer setup when calling `Hammer()` - * When creating a new Manager these will be skipped. - * @type {Array} + * Specifies that an entire element should be draggable instead of its contents. Mainly for desktop browsers. + * @type {String} + * @default 'none' */ - preset: [ - // RecognizerClass, options, [recognizeWith, ...], [requireFailure, ...] - [RotateRecognizer, {enable: false}], - [PinchRecognizer, {enable: false}, ['rotate']], - [SwipeRecognizer, {direction: DIRECTION_HORIZONTAL}], - [PanRecognizer, {direction: DIRECTION_HORIZONTAL}, ['swipe']], - [TapRecognizer], - [TapRecognizer, {event: 'doubletap', taps: 2}, ['tap']], - [PressRecognizer] - ], + userDrag: 'none', /** - * Some CSS properties can be used to improve the working of Hammer. - * Add them to this method and they will be set when creating a new Manager. - * @namespace + * Overrides the highlight color shown when the user taps a link or a JavaScript + * clickable element in iOS. This property obeys the alpha value, if specified. + * @type {String} + * @default 'rgba(0,0,0,0)' */ - cssProps: { - /** - * Disables text selection to improve the dragging gesture. Mainly for desktop browsers. - * @type {String} - * @default 'none' - */ - userSelect: 'none', - - /** - * Disable the Windows Phone grippers when pressing an element. - * @type {String} - * @default 'none' - */ - touchSelect: 'none', - - /** - * Disables the default callout shown when you touch and hold a touch target. - * On iOS, when you touch and hold a touch target such as a link, Safari displays - * a callout containing information about the link. This property allows you to disable that callout. - * @type {String} - * @default 'none' - */ - touchCallout: 'none', - - /** - * Specifies whether zooming is enabled. Used by IE10> - * @type {String} - * @default 'none' - */ - contentZooming: 'none', - - /** - * Specifies that an entire element should be draggable instead of its contents. Mainly for desktop browsers. - * @type {String} - * @default 'none' - */ - userDrag: 'none', - - /** - * Overrides the highlight color shown when the user taps a link or a JavaScript - * clickable element in iOS. This property obeys the alpha value, if specified. - * @type {String} - * @default 'rgba(0,0,0,0)' - */ - tapHighlightColor: 'rgba(0,0,0,0)' - } + tapHighlightColor: 'rgba(0,0,0,0)' + } }; export { Hammer }; diff --git a/src/input/mouse.js b/src/input/mouse.js index 2a5b6c2e9..b2a6bd5f8 100644 --- a/src/input/mouse.js +++ b/src/input/mouse.js @@ -8,9 +8,9 @@ import { Input } from '../inputjs/input-constructor'; import inherit from '../utils/inherit'; var MOUSE_INPUT_MAP = { - mousedown: INPUT_START, - mousemove: INPUT_MOVE, - mouseup: INPUT_END + mousedown: INPUT_START, + mousemove: INPUT_MOVE, + mouseup: INPUT_END }; var MOUSE_ELEMENT_EVENTS = 'mousedown'; @@ -22,47 +22,47 @@ var MOUSE_WINDOW_EVENTS = 'mousemove mouseup'; * @extends Input */ function MouseInput() { - this.evEl = MOUSE_ELEMENT_EVENTS; - this.evWin = MOUSE_WINDOW_EVENTS; + this.evEl = MOUSE_ELEMENT_EVENTS; + this.evWin = MOUSE_WINDOW_EVENTS; - this.pressed = false; // mousedown state + this.pressed = false; // mousedown state - Input.apply(this, arguments); + Input.apply(this, arguments); } inherit(MouseInput, Input, { - /** - * handle mouse events - * @param {Object} ev - */ - handler: function MEhandler(ev) { - var eventType = MOUSE_INPUT_MAP[ev.type]; + /** + * handle mouse events + * @param {Object} ev + */ + handler: function MEhandler(ev) { + var eventType = MOUSE_INPUT_MAP[ev.type]; - // on start we want to have the left mouse button down - if (eventType & INPUT_START && ev.button === 0) { - this.pressed = true; - } - - if (eventType & INPUT_MOVE && ev.which !== 1) { - eventType = INPUT_END; - } + // on start we want to have the left mouse button down + if (eventType & INPUT_START && ev.button === 0) { + this.pressed = true; + } - // mouse must be down - if (!this.pressed) { - return; - } + if (eventType & INPUT_MOVE && ev.which !== 1) { + eventType = INPUT_END; + } - if (eventType & INPUT_END) { - this.pressed = false; - } + // mouse must be down + if (!this.pressed) { + return; + } - this.callback(this.manager, eventType, { - pointers: [ev], - changedPointers: [ev], - pointerType: INPUT_TYPE_MOUSE, - srcEvent: ev - }); + if (eventType & INPUT_END) { + this.pressed = false; } + + this.callback(this.manager, eventType, { + pointers: [ev], + changedPointers: [ev], + pointerType: INPUT_TYPE_MOUSE, + srcEvent: ev + }); + } }); export { MouseInput }; diff --git a/src/input/pointerevent.js b/src/input/pointerevent.js index 56f2a8be3..dcc51187f 100644 --- a/src/input/pointerevent.js +++ b/src/input/pointerevent.js @@ -13,19 +13,19 @@ import inherit from '../utils/inherit'; import inArray from '../utils/in-array'; var POINTER_INPUT_MAP = { - pointerdown: INPUT_START, - pointermove: INPUT_MOVE, - pointerup: INPUT_END, - pointercancel: INPUT_CANCEL, - pointerout: INPUT_CANCEL + pointerdown: INPUT_START, + pointermove: INPUT_MOVE, + pointerup: INPUT_END, + pointercancel: INPUT_CANCEL, + pointerout: INPUT_CANCEL }; // in IE10 the pointer types is defined as an enum var IE10_POINTER_TYPE_ENUM = { - 2: INPUT_TYPE_TOUCH, - 3: INPUT_TYPE_PEN, - 4: INPUT_TYPE_MOUSE, - 5: INPUT_TYPE_KINECT // see https://twitter.com/jacobrossi/status/480596438489890816 + 2: INPUT_TYPE_TOUCH, + 3: INPUT_TYPE_PEN, + 4: INPUT_TYPE_MOUSE, + 5: INPUT_TYPE_KINECT // see https://twitter.com/jacobrossi/status/480596438489890816 }; var POINTER_ELEMENT_EVENTS = 'pointerdown'; @@ -33,8 +33,8 @@ var POINTER_WINDOW_EVENTS = 'pointermove pointerup pointercancel'; // IE10 has prefixed support, and case-sensitive if (window.MSPointerEvent && !window.PointerEvent) { - POINTER_ELEMENT_EVENTS = 'MSPointerDown'; - POINTER_WINDOW_EVENTS = 'MSPointerMove MSPointerUp MSPointerCancel'; + POINTER_ELEMENT_EVENTS = 'MSPointerDown'; + POINTER_WINDOW_EVENTS = 'MSPointerMove MSPointerUp MSPointerCancel'; } /** @@ -43,62 +43,62 @@ if (window.MSPointerEvent && !window.PointerEvent) { * @extends Input */ function PointerEventInput() { - this.evEl = POINTER_ELEMENT_EVENTS; - this.evWin = POINTER_WINDOW_EVENTS; + this.evEl = POINTER_ELEMENT_EVENTS; + this.evWin = POINTER_WINDOW_EVENTS; - Input.apply(this, arguments); + Input.apply(this, arguments); - this.store = (this.manager.session.pointerEvents = []); + this.store = (this.manager.session.pointerEvents = []); } inherit(PointerEventInput, Input, { - /** - * handle mouse events - * @param {Object} ev - */ - handler: function PEhandler(ev) { - var store = this.store; - var removePointer = false; - - var eventTypeNormalized = ev.type.toLowerCase().replace('ms', ''); - var eventType = POINTER_INPUT_MAP[eventTypeNormalized]; - var pointerType = IE10_POINTER_TYPE_ENUM[ev.pointerType] || ev.pointerType; - - var isTouch = (pointerType == INPUT_TYPE_TOUCH); - - // get index of the event in the store - var storeIndex = inArray(store, ev.pointerId, 'pointerId'); - - // start and mouse must be down - if (eventType & INPUT_START && (ev.button === 0 || isTouch)) { - if (storeIndex < 0) { - store.push(ev); - storeIndex = store.length - 1; - } - } else if (eventType & (INPUT_END | INPUT_CANCEL)) { - removePointer = true; - } - - // it not found, so the pointer hasn't been down (so it's probably a hover) - if (storeIndex < 0) { - return; - } - - // update the event in the store - store[storeIndex] = ev; - - this.callback(this.manager, eventType, { - pointers: store, - changedPointers: [ev], - pointerType: pointerType, - srcEvent: ev - }); - - if (removePointer) { - // remove from the store - store.splice(storeIndex, 1); - } + /** + * handle mouse events + * @param {Object} ev + */ + handler: function PEhandler(ev) { + var store = this.store; + var removePointer = false; + + var eventTypeNormalized = ev.type.toLowerCase().replace('ms', ''); + var eventType = POINTER_INPUT_MAP[eventTypeNormalized]; + var pointerType = IE10_POINTER_TYPE_ENUM[ev.pointerType] || ev.pointerType; + + var isTouch = (pointerType == INPUT_TYPE_TOUCH); + + // get index of the event in the store + var storeIndex = inArray(store, ev.pointerId, 'pointerId'); + + // start and mouse must be down + if (eventType & INPUT_START && (ev.button === 0 || isTouch)) { + if (storeIndex < 0) { + store.push(ev); + storeIndex = store.length - 1; + } + } else if (eventType & (INPUT_END | INPUT_CANCEL)) { + removePointer = true; } + + // it not found, so the pointer hasn't been down (so it's probably a hover) + if (storeIndex < 0) { + return; + } + + // update the event in the store + store[storeIndex] = ev; + + this.callback(this.manager, eventType, { + pointers: store, + changedPointers: [ev], + pointerType: pointerType, + srcEvent: ev + }); + + if (removePointer) { + // remove from the store + store.splice(storeIndex, 1); + } + } }); export { PointerEventInput }; diff --git a/src/input/singletouch.js b/src/input/singletouch.js index c937093e6..c3896bd39 100644 --- a/src/input/singletouch.js +++ b/src/input/singletouch.js @@ -11,10 +11,10 @@ import toArray from '../utils/to-array'; import uniqueArray from '../utils/unique-array'; var SINGLE_TOUCH_INPUT_MAP = { - touchstart: INPUT_START, - touchmove: INPUT_MOVE, - touchend: INPUT_END, - touchcancel: INPUT_CANCEL + touchstart: INPUT_START, + touchmove: INPUT_MOVE, + touchend: INPUT_END, + touchcancel: INPUT_CANCEL }; var SINGLE_TOUCH_TARGET_EVENTS = 'touchstart'; @@ -26,40 +26,40 @@ var SINGLE_TOUCH_WINDOW_EVENTS = 'touchstart touchmove touchend touchcancel'; * @extends Input */ function SingleTouchInput() { - this.evTarget = SINGLE_TOUCH_TARGET_EVENTS; - this.evWin = SINGLE_TOUCH_WINDOW_EVENTS; - this.started = false; + this.evTarget = SINGLE_TOUCH_TARGET_EVENTS; + this.evWin = SINGLE_TOUCH_WINDOW_EVENTS; + this.started = false; - Input.apply(this, arguments); + Input.apply(this, arguments); } inherit(SingleTouchInput, Input, { - handler: function TEhandler(ev) { - var type = SINGLE_TOUCH_INPUT_MAP[ev.type]; + handler: function TEhandler(ev) { + var type = SINGLE_TOUCH_INPUT_MAP[ev.type]; - // should we handle the touch events? - if (type === INPUT_START) { - this.started = true; - } - - if (!this.started) { - return; - } + // should we handle the touch events? + if (type === INPUT_START) { + this.started = true; + } - var touches = normalizeSingleTouches.call(this, ev, type); + if (!this.started) { + return; + } - // when done, reset the started state - if (type & (INPUT_END | INPUT_CANCEL) && touches[0].length - touches[1].length === 0) { - this.started = false; - } + var touches = normalizeSingleTouches.call(this, ev, type); - this.callback(this.manager, type, { - pointers: touches[0], - changedPointers: touches[1], - pointerType: INPUT_TYPE_TOUCH, - srcEvent: ev - }); + // when done, reset the started state + if (type & (INPUT_END | INPUT_CANCEL) && touches[0].length - touches[1].length === 0) { + this.started = false; } + + this.callback(this.manager, type, { + pointers: touches[0], + changedPointers: touches[1], + pointerType: INPUT_TYPE_TOUCH, + srcEvent: ev + }); + } }); /** @@ -69,14 +69,14 @@ inherit(SingleTouchInput, Input, { * @returns {undefined|Array} [all, changed] */ function normalizeSingleTouches(ev, type) { - var all = toArray(ev.touches); - var changed = toArray(ev.changedTouches); + var all = toArray(ev.touches); + var changed = toArray(ev.changedTouches); - if (type & (INPUT_END | INPUT_CANCEL)) { - all = uniqueArray(all.concat(changed), 'identifier', true); - } + if (type & (INPUT_END | INPUT_CANCEL)) { + all = uniqueArray(all.concat(changed), 'identifier', true); + } - return [all, changed]; + return [all, changed]; } export { SingleTouchInput }; diff --git a/src/input/touch.js b/src/input/touch.js index 7c822fc99..c67f06777 100644 --- a/src/input/touch.js +++ b/src/input/touch.js @@ -12,10 +12,10 @@ import hasParent from '../utils/has-parent'; import uniqueArray from '../utils/unique-array'; var TOUCH_INPUT_MAP = { - touchstart: INPUT_START, - touchmove: INPUT_MOVE, - touchend: INPUT_END, - touchcancel: INPUT_CANCEL + touchstart: INPUT_START, + touchmove: INPUT_MOVE, + touchend: INPUT_END, + touchcancel: INPUT_CANCEL }; var TOUCH_TARGET_EVENTS = 'touchstart touchmove touchend touchcancel'; @@ -26,27 +26,27 @@ var TOUCH_TARGET_EVENTS = 'touchstart touchmove touchend touchcancel'; * @extends Input */ function TouchInput() { - this.evTarget = TOUCH_TARGET_EVENTS; - this.targetIds = {}; + this.evTarget = TOUCH_TARGET_EVENTS; + this.targetIds = {}; - Input.apply(this, arguments); + Input.apply(this, arguments); } inherit(TouchInput, Input, { - handler: function MTEhandler(ev) { - var type = TOUCH_INPUT_MAP[ev.type]; - var touches = getTouches.call(this, ev, type); - if (!touches) { - return; - } - - this.callback(this.manager, type, { - pointers: touches[0], - changedPointers: touches[1], - pointerType: INPUT_TYPE_TOUCH, - srcEvent: ev - }); + handler: function MTEhandler(ev) { + var type = TOUCH_INPUT_MAP[ev.type]; + var touches = getTouches.call(this, ev, type); + if (!touches) { + return; } + + this.callback(this.manager, type, { + pointers: touches[0], + changedPointers: touches[1], + pointerType: INPUT_TYPE_TOUCH, + srcEvent: ev + }); + } }); /** @@ -56,58 +56,58 @@ inherit(TouchInput, Input, { * @returns {undefined|Array} [all, changed] */ function getTouches(ev, type) { - var allTouches = toArray(ev.touches); - var targetIds = this.targetIds; - - // when there is only one touch, the process can be simplified - if (type & (INPUT_START | INPUT_MOVE) && allTouches.length === 1) { - targetIds[allTouches[0].identifier] = true; - return [allTouches, allTouches]; - } - - var i, - targetTouches, - changedTouches = toArray(ev.changedTouches), - changedTargetTouches = [], - target = this.target; - - // get target touches from touches - targetTouches = allTouches.filter(function(touch) { - return hasParent(touch.target, target); - }); - - // collect touches - if (type === INPUT_START) { - i = 0; - while (i < targetTouches.length) { - targetIds[targetTouches[i].identifier] = true; - i++; - } - } - - // filter changed touches to only contain touches that exist in the collected target ids + var allTouches = toArray(ev.touches); + var targetIds = this.targetIds; + + // when there is only one touch, the process can be simplified + if (type & (INPUT_START | INPUT_MOVE) && allTouches.length === 1) { + targetIds[allTouches[0].identifier] = true; + return [allTouches, allTouches]; + } + + var i, + targetTouches, + changedTouches = toArray(ev.changedTouches), + changedTargetTouches = [], + target = this.target; + + // get target touches from touches + targetTouches = allTouches.filter(function(touch) { + return hasParent(touch.target, target); + }); + + // collect touches + if (type === INPUT_START) { i = 0; - while (i < changedTouches.length) { - if (targetIds[changedTouches[i].identifier]) { - changedTargetTouches.push(changedTouches[i]); - } - - // cleanup removed touches - if (type & (INPUT_END | INPUT_CANCEL)) { - delete targetIds[changedTouches[i].identifier]; - } - i++; + while (i < targetTouches.length) { + targetIds[targetTouches[i].identifier] = true; + i++; } + } - if (!changedTargetTouches.length) { - return; + // filter changed touches to only contain touches that exist in the collected target ids + i = 0; + while (i < changedTouches.length) { + if (targetIds[changedTouches[i].identifier]) { + changedTargetTouches.push(changedTouches[i]); } - return [ - // merge targetTouches with changedTargetTouches so it contains ALL touches, including 'end' and 'cancel' - uniqueArray(targetTouches.concat(changedTargetTouches), 'identifier', true), - changedTargetTouches - ]; + // cleanup removed touches + if (type & (INPUT_END | INPUT_CANCEL)) { + delete targetIds[changedTouches[i].identifier]; + } + i++; + } + + if (!changedTargetTouches.length) { + return; + } + + return [ + // merge targetTouches with changedTargetTouches so it contains ALL touches, including 'end' and 'cancel' + uniqueArray(targetTouches.concat(changedTargetTouches), 'identifier', true), + changedTargetTouches + ]; } export { TouchInput }; diff --git a/src/input/touchmouse.js b/src/input/touchmouse.js index 17a8c1d72..39b988f8c 100644 --- a/src/input/touchmouse.js +++ b/src/input/touchmouse.js @@ -25,86 +25,86 @@ var DEDUP_TIMEOUT = 2500; var DEDUP_DISTANCE = 25; function TouchMouseInput() { - Input.apply(this, arguments); + Input.apply(this, arguments); - var handler = bindFn(this.handler, this); - this.touch = new TouchInput(this.manager, handler); - this.mouse = new MouseInput(this.manager, handler); + var handler = bindFn(this.handler, this); + this.touch = new TouchInput(this.manager, handler); + this.mouse = new MouseInput(this.manager, handler); - this.primaryTouch = null; - this.lastTouches = []; + this.primaryTouch = null; + this.lastTouches = []; } inherit(TouchMouseInput, Input, { - /** - * handle mouse and touch events - * @param {Hammer} manager - * @param {String} inputEvent - * @param {Object} inputData - */ - handler: function TMEhandler(manager, inputEvent, inputData) { - var isTouch = (inputData.pointerType == INPUT_TYPE_TOUCH), - isMouse = (inputData.pointerType == INPUT_TYPE_MOUSE); + /** + * handle mouse and touch events + * @param {Hammer} manager + * @param {String} inputEvent + * @param {Object} inputData + */ + handler: function TMEhandler(manager, inputEvent, inputData) { + var isTouch = (inputData.pointerType == INPUT_TYPE_TOUCH), + isMouse = (inputData.pointerType == INPUT_TYPE_MOUSE); - if (isMouse && inputData.sourceCapabilities && inputData.sourceCapabilities.firesTouchEvents) { - return; - } + if (isMouse && inputData.sourceCapabilities && inputData.sourceCapabilities.firesTouchEvents) { + return; + } - // when we're in a touch event, record touches to de-dupe synthetic mouse event - if (isTouch) { - recordTouches.call(this, inputEvent, inputData); - } else if (isMouse && isSyntheticEvent.call(this, inputData)) { - return; - } + // when we're in a touch event, record touches to de-dupe synthetic mouse event + if (isTouch) { + recordTouches.call(this, inputEvent, inputData); + } else if (isMouse && isSyntheticEvent.call(this, inputData)) { + return; + } - this.callback(manager, inputEvent, inputData); - }, + this.callback(manager, inputEvent, inputData); + }, - /** - * remove the event listeners - */ - destroy: function destroy() { - this.touch.destroy(); - this.mouse.destroy(); - } + /** + * remove the event listeners + */ + destroy: function destroy() { + this.touch.destroy(); + this.mouse.destroy(); + } }); function recordTouches(eventType, eventData) { - if (eventType & INPUT_START) { - this.primaryTouch = eventData.changedPointers[0].identifier; - setLastTouch.call(this, eventData); - } else if (eventType & (INPUT_END | INPUT_CANCEL)) { - setLastTouch.call(this, eventData); - } + if (eventType & INPUT_START) { + this.primaryTouch = eventData.changedPointers[0].identifier; + setLastTouch.call(this, eventData); + } else if (eventType & (INPUT_END | INPUT_CANCEL)) { + setLastTouch.call(this, eventData); + } } function setLastTouch(eventData) { - var touch = eventData.changedPointers[0]; + var touch = eventData.changedPointers[0]; - if (touch.identifier === this.primaryTouch) { - var lastTouch = {x: touch.clientX, y: touch.clientY}; - this.lastTouches.push(lastTouch); - var lts = this.lastTouches; - var removeLastTouch = function() { - var i = lts.indexOf(lastTouch); - if (i > -1) { - lts.splice(i, 1); - } - }; - setTimeout(removeLastTouch, DEDUP_TIMEOUT); - } + if (touch.identifier === this.primaryTouch) { + var lastTouch = { x: touch.clientX, y: touch.clientY }; + this.lastTouches.push(lastTouch); + var lts = this.lastTouches; + var removeLastTouch = function() { + var i = lts.indexOf(lastTouch); + if (i > -1) { + lts.splice(i, 1); + } + }; + setTimeout(removeLastTouch, DEDUP_TIMEOUT); + } } function isSyntheticEvent(eventData) { - var x = eventData.srcEvent.clientX, y = eventData.srcEvent.clientY; - for (var i = 0; i < this.lastTouches.length; i++) { - var t = this.lastTouches[i]; - var dx = Math.abs(x - t.x), dy = Math.abs(y - t.y); - if (dx <= DEDUP_DISTANCE && dy <= DEDUP_DISTANCE) { - return true; - } + var x = eventData.srcEvent.clientX, y = eventData.srcEvent.clientY; + for (var i = 0; i < this.lastTouches.length; i++) { + var t = this.lastTouches[i]; + var dx = Math.abs(x - t.x), dy = Math.abs(y - t.y); + if (dx <= DEDUP_DISTANCE && dy <= DEDUP_DISTANCE) { + return true; } - return false; + } + return false; } export { TouchMouseInput }; diff --git a/src/inputjs/compute-delta-xy.js b/src/inputjs/compute-delta-xy.js index ba74bc9b4..96745e78f 100644 --- a/src/inputjs/compute-delta-xy.js +++ b/src/inputjs/compute-delta-xy.js @@ -1,23 +1,23 @@ import { INPUT_START,INPUT_END } from './input-consts'; export default function computeDeltaXY(session, input) { - var center = input.center; - var offset = session.offsetDelta || {}; - var prevDelta = session.prevDelta || {}; - var prevInput = session.prevInput || {}; + var center = input.center; + var offset = session.offsetDelta || {}; + var prevDelta = session.prevDelta || {}; + var prevInput = session.prevInput || {}; - if (input.eventType === INPUT_START || prevInput.eventType === INPUT_END) { - prevDelta = session.prevDelta = { - x: prevInput.deltaX || 0, - y: prevInput.deltaY || 0 - }; + if (input.eventType === INPUT_START || prevInput.eventType === INPUT_END) { + prevDelta = session.prevDelta = { + x: prevInput.deltaX || 0, + y: prevInput.deltaY || 0 + }; - offset = session.offsetDelta = { - x: center.x, - y: center.y - }; - } + offset = session.offsetDelta = { + x: center.x, + y: center.y + }; + } - input.deltaX = prevDelta.x + (center.x - offset.x); - input.deltaY = prevDelta.y + (center.y - offset.y); + input.deltaX = prevDelta.x + (center.x - offset.x); + input.deltaY = prevDelta.y + (center.y - offset.y); } diff --git a/src/inputjs/compute-input-data.js b/src/inputjs/compute-input-data.js index 31d46310c..7bdc17c73 100644 --- a/src/inputjs/compute-input-data.js +++ b/src/inputjs/compute-input-data.js @@ -18,53 +18,53 @@ import computeIntervalInputData from './compute-interval-input-data'; * @param {Object} input */ export default function computeInputData(manager, input) { - var session = manager.session; - var pointers = input.pointers; - var pointersLength = pointers.length; + var session = manager.session; + var pointers = input.pointers; + var pointersLength = pointers.length; - // store the first input to calculate the distance and direction - if (!session.firstInput) { - session.firstInput = simpleCloneInputData(input); - } + // store the first input to calculate the distance and direction + if (!session.firstInput) { + session.firstInput = simpleCloneInputData(input); + } - // to compute scale and rotation we need to store the multiple touches - if (pointersLength > 1 && !session.firstMultiple) { - session.firstMultiple = simpleCloneInputData(input); - } else if (pointersLength === 1) { - session.firstMultiple = false; - } + // to compute scale and rotation we need to store the multiple touches + if (pointersLength > 1 && !session.firstMultiple) { + session.firstMultiple = simpleCloneInputData(input); + } else if (pointersLength === 1) { + session.firstMultiple = false; + } - var firstInput = session.firstInput; - var firstMultiple = session.firstMultiple; - var offsetCenter = firstMultiple ? firstMultiple.center : firstInput.center; + var firstInput = session.firstInput; + var firstMultiple = session.firstMultiple; + var offsetCenter = firstMultiple ? firstMultiple.center : firstInput.center; - var center = input.center = getCenter(pointers); - input.timeStamp = now(); - input.deltaTime = input.timeStamp - firstInput.timeStamp; + var center = input.center = getCenter(pointers); + input.timeStamp = now(); + input.deltaTime = input.timeStamp - firstInput.timeStamp; - input.angle = getAngle(offsetCenter, center); - input.distance = getDistance(offsetCenter, center); + input.angle = getAngle(offsetCenter, center); + input.distance = getDistance(offsetCenter, center); - computeDeltaXY(session, input); - input.offsetDirection = getDirection(input.deltaX, input.deltaY); + computeDeltaXY(session, input); + input.offsetDirection = getDirection(input.deltaX, input.deltaY); - var overallVelocity = getVelocity(input.deltaTime, input.deltaX, input.deltaY); - input.overallVelocityX = overallVelocity.x; - input.overallVelocityY = overallVelocity.y; - input.overallVelocity = (abs(overallVelocity.x) > abs(overallVelocity.y)) ? overallVelocity.x : overallVelocity.y; + var overallVelocity = getVelocity(input.deltaTime, input.deltaX, input.deltaY); + input.overallVelocityX = overallVelocity.x; + input.overallVelocityY = overallVelocity.y; + input.overallVelocity = (abs(overallVelocity.x) > abs(overallVelocity.y)) ? overallVelocity.x : overallVelocity.y; - input.scale = firstMultiple ? getScale(firstMultiple.pointers, pointers) : 1; - input.rotation = firstMultiple ? getRotation(firstMultiple.pointers, pointers) : 0; + input.scale = firstMultiple ? getScale(firstMultiple.pointers, pointers) : 1; + input.rotation = firstMultiple ? getRotation(firstMultiple.pointers, pointers) : 0; - input.maxPointers = !session.prevInput ? input.pointers.length : ((input.pointers.length > - session.prevInput.maxPointers) ? input.pointers.length : session.prevInput.maxPointers); + input.maxPointers = !session.prevInput ? input.pointers.length : ((input.pointers.length > + session.prevInput.maxPointers) ? input.pointers.length : session.prevInput.maxPointers); - computeIntervalInputData(session, input); + computeIntervalInputData(session, input); - // find the correct target - var target = manager.element; - if (hasParent(input.srcEvent.target, target)) { - target = input.srcEvent.target; - } - input.target = target; + // find the correct target + var target = manager.element; + if (hasParent(input.srcEvent.target, target)) { + target = input.srcEvent.target; + } + input.target = target; } diff --git a/src/inputjs/compute-interval-input-data.js b/src/inputjs/compute-interval-input-data.js index 48eb135cf..c060abb0e 100644 --- a/src/inputjs/compute-interval-input-data.js +++ b/src/inputjs/compute-interval-input-data.js @@ -9,31 +9,31 @@ import getDirection from './get-direction'; * @param {Object} input */ export default function computeIntervalInputData(session, input) { - var last = session.lastInterval || input, - deltaTime = input.timeStamp - last.timeStamp, - velocity, velocityX, velocityY, direction; + var last = session.lastInterval || input, + deltaTime = input.timeStamp - last.timeStamp, + velocity, velocityX, velocityY, direction; - if (input.eventType != INPUT_CANCEL && (deltaTime > COMPUTE_INTERVAL || last.velocity === undefined)) { - var deltaX = input.deltaX - last.deltaX; - var deltaY = input.deltaY - last.deltaY; + if (input.eventType != INPUT_CANCEL && (deltaTime > COMPUTE_INTERVAL || last.velocity === undefined)) { + var deltaX = input.deltaX - last.deltaX; + var deltaY = input.deltaY - last.deltaY; - var v = getVelocity(deltaTime, deltaX, deltaY); - velocityX = v.x; - velocityY = v.y; - velocity = (abs(v.x) > abs(v.y)) ? v.x : v.y; - direction = getDirection(deltaX, deltaY); + var v = getVelocity(deltaTime, deltaX, deltaY); + velocityX = v.x; + velocityY = v.y; + velocity = (abs(v.x) > abs(v.y)) ? v.x : v.y; + direction = getDirection(deltaX, deltaY); - session.lastInterval = input; - } else { - // use latest velocity info if it doesn't overtake a minimum period - velocity = last.velocity; - velocityX = last.velocityX; - velocityY = last.velocityY; - direction = last.direction; - } + session.lastInterval = input; + } else { + // use latest velocity info if it doesn't overtake a minimum period + velocity = last.velocity; + velocityX = last.velocityX; + velocityY = last.velocityY; + direction = last.direction; + } - input.velocity = velocity; - input.velocityX = velocityX; - input.velocityY = velocityY; - input.direction = direction; + input.velocity = velocity; + input.velocityX = velocityX; + input.velocityY = velocityY; + input.direction = direction; } diff --git a/src/inputjs/create-input-instance.js b/src/inputjs/create-input-instance.js index 7a2e66efc..c7f3677eb 100644 --- a/src/inputjs/create-input-instance.js +++ b/src/inputjs/create-input-instance.js @@ -12,19 +12,19 @@ import { TouchMouseInput } from '../input/touchmouse'; * @returns {Input} */ export default function createInputInstance(manager) { - var Type; - var inputClass = manager.options.inputClass; + var Type; + var inputClass = manager.options.inputClass; - if (inputClass) { - Type = inputClass; - } else if (SUPPORT_POINTER_EVENTS) { - Type = PointerEventInput; - } else if (SUPPORT_ONLY_TOUCH) { - Type = TouchInput; - } else if (!SUPPORT_TOUCH) { - Type = MouseInput; - } else { - Type = TouchMouseInput; - } - return new (Type)(manager, inputHandler); + if (inputClass) { + Type = inputClass; + } else if (SUPPORT_POINTER_EVENTS) { + Type = PointerEventInput; + } else if (SUPPORT_ONLY_TOUCH) { + Type = TouchInput; + } else if (!SUPPORT_TOUCH) { + Type = MouseInput; + } else { + Type = TouchMouseInput; + } + return new (Type)(manager, inputHandler); } diff --git a/src/inputjs/get-angle.js b/src/inputjs/get-angle.js index 557f9c778..27a8449ae 100644 --- a/src/inputjs/get-angle.js +++ b/src/inputjs/get-angle.js @@ -8,10 +8,10 @@ import { PROPS_XY } from './input-consts'; * @return {Number} angle */ export default function getAngle(p1, p2, props) { - if (!props) { - props = PROPS_XY; - } - var x = p2[props[0]] - p1[props[0]], - y = p2[props[1]] - p1[props[1]]; - return Math.atan2(y, x) * 180 / Math.PI; + if (!props) { + props = PROPS_XY; + } + var x = p2[props[0]] - p1[props[0]], + y = p2[props[1]] - p1[props[1]]; + return Math.atan2(y, x) * 180 / Math.PI; } diff --git a/src/inputjs/get-center.js b/src/inputjs/get-center.js index 37f6de099..806b45938 100644 --- a/src/inputjs/get-center.js +++ b/src/inputjs/get-center.js @@ -6,25 +6,25 @@ import { round } from '../utils/utils-consts'; * @return {Object} center contains `x` and `y` properties */ export default function getCenter(pointers) { - var pointersLength = pointers.length; - - // no need to loop when only one touch - if (pointersLength === 1) { - return { - x: round(pointers[0].clientX), - y: round(pointers[0].clientY) - }; - } - - var x = 0, y = 0, i = 0; - while (i < pointersLength) { - x += pointers[i].clientX; - y += pointers[i].clientY; - i++; - } + var pointersLength = pointers.length; + // no need to loop when only one touch + if (pointersLength === 1) { return { - x: round(x / pointersLength), - y: round(y / pointersLength) + x: round(pointers[0].clientX), + y: round(pointers[0].clientY) }; + } + + var x = 0, y = 0, i = 0; + while (i < pointersLength) { + x += pointers[i].clientX; + y += pointers[i].clientY; + i++; + } + + return { + x: round(x / pointersLength), + y: round(y / pointersLength) + }; } diff --git a/src/inputjs/get-direction.js b/src/inputjs/get-direction.js index 1e2d2674c..95721c82e 100644 --- a/src/inputjs/get-direction.js +++ b/src/inputjs/get-direction.js @@ -8,12 +8,12 @@ import { DIRECTION_NONE,DIRECTION_LEFT,DIRECTION_RIGHT,DIRECTION_UP,DIRECTION_DO * @return {Number} direction */ export default function getDirection(x, y) { - if (x === y) { - return DIRECTION_NONE; - } + if (x === y) { + return DIRECTION_NONE; + } - if (abs(x) >= abs(y)) { - return x < 0 ? DIRECTION_LEFT : DIRECTION_RIGHT; - } - return y < 0 ? DIRECTION_UP : DIRECTION_DOWN; + if (abs(x) >= abs(y)) { + return x < 0 ? DIRECTION_LEFT : DIRECTION_RIGHT; + } + return y < 0 ? DIRECTION_UP : DIRECTION_DOWN; } diff --git a/src/inputjs/get-distance.js b/src/inputjs/get-distance.js index 1ae3f4abc..acb69c595 100644 --- a/src/inputjs/get-distance.js +++ b/src/inputjs/get-distance.js @@ -8,11 +8,11 @@ import { PROPS_XY } from './input-consts'; * @return {Number} distance */ export default function getDistance(p1, p2, props) { - if (!props) { - props = PROPS_XY; - } - var x = p2[props[0]] - p1[props[0]], - y = p2[props[1]] - p1[props[1]]; + if (!props) { + props = PROPS_XY; + } + var x = p2[props[0]] - p1[props[0]], + y = p2[props[1]] - p1[props[1]]; - return Math.sqrt((x * x) + (y * y)); + return Math.sqrt((x * x) + (y * y)); } diff --git a/src/inputjs/get-rotation.js b/src/inputjs/get-rotation.js index 25c92de2d..7ffe1293c 100644 --- a/src/inputjs/get-rotation.js +++ b/src/inputjs/get-rotation.js @@ -8,5 +8,5 @@ import { PROPS_CLIENT_XY } from './input-consts'; * @return {Number} rotation */ export default function getRotation(start, end) { - return getAngle(end[1], end[0], PROPS_CLIENT_XY) + getAngle(start[1], start[0], PROPS_CLIENT_XY); + return getAngle(end[1], end[0], PROPS_CLIENT_XY) + getAngle(start[1], start[0], PROPS_CLIENT_XY); } diff --git a/src/inputjs/get-scale.js b/src/inputjs/get-scale.js index 6349d0b1f..69b607fce 100644 --- a/src/inputjs/get-scale.js +++ b/src/inputjs/get-scale.js @@ -8,5 +8,5 @@ import getDistance from './get-distance'; * @return {Number} scale */ export default function getScale(start, end) { - return getDistance(end[0], end[1], PROPS_CLIENT_XY) / getDistance(start[0], start[1], PROPS_CLIENT_XY); + return getDistance(end[0], end[1], PROPS_CLIENT_XY) / getDistance(start[0], start[1], PROPS_CLIENT_XY); } diff --git a/src/inputjs/get-velocity.js b/src/inputjs/get-velocity.js index a07bdd9aa..971eba7d6 100644 --- a/src/inputjs/get-velocity.js +++ b/src/inputjs/get-velocity.js @@ -6,8 +6,8 @@ * @return {Object} velocity `x` and `y` */ export default function getVelocity(deltaTime, x, y) { - return { - x: x / deltaTime || 0, - y: y / deltaTime || 0 - }; + return { + x: x / deltaTime || 0, + y: y / deltaTime || 0 + }; } diff --git a/src/inputjs/input-constructor.js b/src/inputjs/input-constructor.js index 393da64cd..b0dd1b335 100644 --- a/src/inputjs/input-constructor.js +++ b/src/inputjs/input-constructor.js @@ -11,48 +11,48 @@ import getWindowForElement from '../utils/get-window-for-element'; * @constructor */ function Input(manager, callback) { - var self = this; - this.manager = manager; - this.callback = callback; - this.element = manager.element; - this.target = manager.options.inputTarget; - - // smaller wrapper around the handler, for the scope and the enabled state of the manager, - // so when disabled the input events are completely bypassed. - this.domHandler = function(ev) { - if (boolOrFn(manager.options.enable, [manager])) { - self.handler(ev); - } - }; - - this.init(); + var self = this; + this.manager = manager; + this.callback = callback; + this.element = manager.element; + this.target = manager.options.inputTarget; + + // smaller wrapper around the handler, for the scope and the enabled state of the manager, + // so when disabled the input events are completely bypassed. + this.domHandler = function(ev) { + if (boolOrFn(manager.options.enable, [manager])) { + self.handler(ev); + } + }; + + this.init(); } Input.prototype = { - /** - * should handle the inputEvent data and trigger the callback - * @virtual - */ - handler: function() { }, - - /** - * bind the events - */ - init: function() { - this.evEl && addEventListeners(this.element, this.evEl, this.domHandler); - this.evTarget && addEventListeners(this.target, this.evTarget, this.domHandler); - this.evWin && addEventListeners(getWindowForElement(this.element), this.evWin, this.domHandler); - }, - - /** - * unbind the events - */ - destroy: function() { - this.evEl && removeEventListeners(this.element, this.evEl, this.domHandler); - this.evTarget && removeEventListeners(this.target, this.evTarget, this.domHandler); - this.evWin && removeEventListeners(getWindowForElement(this.element), this.evWin, this.domHandler); - } + /** + * should handle the inputEvent data and trigger the callback + * @virtual + */ + handler: function() { }, + + /** + * bind the events + */ + init: function() { + this.evEl && addEventListeners(this.element, this.evEl, this.domHandler); + this.evTarget && addEventListeners(this.target, this.evTarget, this.domHandler); + this.evWin && addEventListeners(getWindowForElement(this.element), this.evWin, this.domHandler); + }, + + /** + * unbind the events + */ + destroy: function() { + this.evEl && removeEventListeners(this.element, this.evEl, this.domHandler); + this.evTarget && removeEventListeners(this.target, this.evTarget, this.domHandler); + this.evWin && removeEventListeners(getWindowForElement(this.element), this.evWin, this.domHandler); + } }; export { Input }; diff --git a/src/inputjs/input-handler.js b/src/inputjs/input-handler.js index ce39d0229..ae3a162c6 100644 --- a/src/inputjs/input-handler.js +++ b/src/inputjs/input-handler.js @@ -8,28 +8,28 @@ import computeInputData from './compute-input-data'; * @param {Object} input */ export default function inputHandler(manager, eventType, input) { - var pointersLen = input.pointers.length; - var changedPointersLen = input.changedPointers.length; - var isFirst = (eventType & INPUT_START && (pointersLen - changedPointersLen === 0)); - var isFinal = (eventType & (INPUT_END | INPUT_CANCEL) && (pointersLen - changedPointersLen === 0)); + var pointersLen = input.pointers.length; + var changedPointersLen = input.changedPointers.length; + var isFirst = (eventType & INPUT_START && (pointersLen - changedPointersLen === 0)); + var isFinal = (eventType & (INPUT_END | INPUT_CANCEL) && (pointersLen - changedPointersLen === 0)); - input.isFirst = !!isFirst; - input.isFinal = !!isFinal; + input.isFirst = !!isFirst; + input.isFinal = !!isFinal; - if (isFirst) { - manager.session = {}; - } + if (isFirst) { + manager.session = {}; + } - // source event is the normalized value of the domEvents - // like 'touchstart, mouseup, pointerdown' - input.eventType = eventType; + // source event is the normalized value of the domEvents + // like 'touchstart, mouseup, pointerdown' + input.eventType = eventType; - // compute scale, rotation etc - computeInputData(manager, input); + // compute scale, rotation etc + computeInputData(manager, input); - // emit secret event - manager.emit('hammer.input', input); + // emit secret event + manager.emit('hammer.input', input); - manager.recognize(input); - manager.session.prevInput = input; + manager.recognize(input); + manager.session.prevInput = input; } diff --git a/src/inputjs/simple-clone-input-data.js b/src/inputjs/simple-clone-input-data.js index 574f7d526..c2aad2b30 100644 --- a/src/inputjs/simple-clone-input-data.js +++ b/src/inputjs/simple-clone-input-data.js @@ -7,23 +7,23 @@ import getCenter from './get-center'; * @returns {Object} clonedInputData */ export default function simpleCloneInputData(input) { - // make a simple copy of the pointers because we will get a reference if we don't - // we only need clientXY for the calculations - var pointers = []; - var i = 0; - while (i < input.pointers.length) { - pointers[i] = { - clientX: round(input.pointers[i].clientX), - clientY: round(input.pointers[i].clientY) - }; - i++; - } - - return { - timeStamp: now(), - pointers: pointers, - center: getCenter(pointers), - deltaX: input.deltaX, - deltaY: input.deltaY + // make a simple copy of the pointers because we will get a reference if we don't + // we only need clientXY for the calculations + var pointers = []; + var i = 0; + while (i < input.pointers.length) { + pointers[i] = { + clientX: round(input.pointers[i].clientX), + clientY: round(input.pointers[i].clientY) }; + i++; + } + + return { + timeStamp: now(), + pointers: pointers, + center: getCenter(pointers), + deltaX: input.deltaX, + deltaY: input.deltaY + }; } diff --git a/src/main.js b/src/main.js index 625a522c7..7d2dea843 100644 --- a/src/main.js +++ b/src/main.js @@ -63,75 +63,75 @@ import hasParent from'./utils/has-parent'; // style loader but by script tag, not by the loader. assign(Hammer, { - INPUT_START: INPUT_START, - INPUT_MOVE: INPUT_MOVE, - INPUT_END: INPUT_END, - INPUT_CANCEL: INPUT_CANCEL, + INPUT_START: INPUT_START, + INPUT_MOVE: INPUT_MOVE, + INPUT_END: INPUT_END, + INPUT_CANCEL: INPUT_CANCEL, - STATE_POSSIBLE: STATE_POSSIBLE, - STATE_BEGAN: STATE_BEGAN, - STATE_CHANGED: STATE_CHANGED, - STATE_ENDED: STATE_ENDED, - STATE_RECOGNIZED: STATE_RECOGNIZED, - STATE_CANCELLED: STATE_CANCELLED, - STATE_FAILED: STATE_FAILED, + STATE_POSSIBLE: STATE_POSSIBLE, + STATE_BEGAN: STATE_BEGAN, + STATE_CHANGED: STATE_CHANGED, + STATE_ENDED: STATE_ENDED, + STATE_RECOGNIZED: STATE_RECOGNIZED, + STATE_CANCELLED: STATE_CANCELLED, + STATE_FAILED: STATE_FAILED, - DIRECTION_NONE: DIRECTION_NONE, - DIRECTION_LEFT: DIRECTION_LEFT, - DIRECTION_RIGHT: DIRECTION_RIGHT, - DIRECTION_UP: DIRECTION_UP, - DIRECTION_DOWN: DIRECTION_DOWN, - DIRECTION_HORIZONTAL: DIRECTION_HORIZONTAL, - DIRECTION_VERTICAL: DIRECTION_VERTICAL, - DIRECTION_ALL: DIRECTION_ALL, + DIRECTION_NONE: DIRECTION_NONE, + DIRECTION_LEFT: DIRECTION_LEFT, + DIRECTION_RIGHT: DIRECTION_RIGHT, + DIRECTION_UP: DIRECTION_UP, + DIRECTION_DOWN: DIRECTION_DOWN, + DIRECTION_HORIZONTAL: DIRECTION_HORIZONTAL, + DIRECTION_VERTICAL: DIRECTION_VERTICAL, + DIRECTION_ALL: DIRECTION_ALL, - Manager: Manager, - Input: Input, - TouchAction: TouchAction, + Manager: Manager, + Input: Input, + TouchAction: TouchAction, - TouchInput: TouchInput, - MouseInput: MouseInput, - PointerEventInput: PointerEventInput, - TouchMouseInput: TouchMouseInput, - SingleTouchInput: SingleTouchInput, + TouchInput: TouchInput, + MouseInput: MouseInput, + PointerEventInput: PointerEventInput, + TouchMouseInput: TouchMouseInput, + SingleTouchInput: SingleTouchInput, - Recognizer: Recognizer, - AttrRecognizer: AttrRecognizer, - Tap: TapRecognizer, - Pan: PanRecognizer, - Swipe: SwipeRecognizer, - Pinch: PinchRecognizer, - Rotate: RotateRecognizer, - Press: PressRecognizer, + Recognizer: Recognizer, + AttrRecognizer: AttrRecognizer, + Tap: TapRecognizer, + Pan: PanRecognizer, + Swipe: SwipeRecognizer, + Pinch: PinchRecognizer, + Rotate: RotateRecognizer, + Press: PressRecognizer, - on: addEventListeners, - off: removeEventListeners, - each: each, - merge: merge, - extend: extend, - assign: assign, - inherit: inherit, - bindFn: bindFn, - prefixed: prefixed, - toArray: toArray, - inArray: inArray, - uniqueArray: uniqueArray, - splitStr: splitStr, - boolOrFn:boolOrFn, - hasParent:hasParent, - addEventListeners: addEventListeners, - removeEventListeners: removeEventListeners + on: addEventListeners, + off: removeEventListeners, + each: each, + merge: merge, + extend: extend, + assign: assign, + inherit: inherit, + bindFn: bindFn, + prefixed: prefixed, + toArray: toArray, + inArray: inArray, + uniqueArray: uniqueArray, + splitStr: splitStr, + boolOrFn: boolOrFn, + hasParent: hasParent, + addEventListeners: addEventListeners, + removeEventListeners: removeEventListeners }); var freeGlobal = (typeof window !== 'undefined' ? window : (typeof self !== 'undefined' ? self : {})); // jshint ignore:line freeGlobal.Hammer = Hammer; if (typeof define === 'function' && define.amd) { - define(function() { - return Hammer; - }); + define(function() { + return Hammer; + }); } else if (typeof module != 'undefined' && module.exports) { - module.exports = Hammer; + module.exports = Hammer; } else { - window[exportName] = Hammer; + window[exportName] = Hammer; } diff --git a/src/manager.js b/src/manager.js index ac22d560b..7b98bada3 100644 --- a/src/manager.js +++ b/src/manager.js @@ -25,270 +25,270 @@ var FORCED_STOP = 2; * @constructor */ function Manager(element, options) { - this.options = assign({}, Hammer.defaults, options || {}); + this.options = assign({}, Hammer.defaults, options || {}); - this.options.inputTarget = this.options.inputTarget || element; + this.options.inputTarget = this.options.inputTarget || element; - this.handlers = {}; - this.session = {}; - this.recognizers = []; - this.oldCssProps = {}; + this.handlers = {}; + this.session = {}; + this.recognizers = []; + this.oldCssProps = {}; - this.element = element; - this.input = createInputInstance(this); - this.touchAction = new TouchAction(this, this.options.touchAction); + this.element = element; + this.input = createInputInstance(this); + this.touchAction = new TouchAction(this, this.options.touchAction); - toggleCssProps(this, true); + toggleCssProps(this, true); - each(this.options.recognizers, function(item) { - var recognizer = this.add(new (item[0])(item[1])); - item[2] && recognizer.recognizeWith(item[2]); - item[3] && recognizer.requireFailure(item[3]); - }, this); + each(this.options.recognizers, function(item) { + var recognizer = this.add(new (item[0])(item[1])); + item[2] && recognizer.recognizeWith(item[2]); + item[3] && recognizer.requireFailure(item[3]); + }, this); } Manager.prototype = { - /** - * set options - * @param {Object} options - * @returns {Manager} - */ - set: function(options) { - assign(this.options, options); - - // Options that need a little more setup - if (options.touchAction) { - this.touchAction.update(); - } - if (options.inputTarget) { - // Clean up existing event listeners and reinitialize - this.input.destroy(); - this.input.target = options.inputTarget; - this.input.init(); - } - return this; - }, - - /** - * stop recognizing for this session. - * This session will be discarded, when a new [input]start event is fired. - * When forced, the recognizer cycle is stopped immediately. - * @param {Boolean} [force] - */ - stop: function(force) { - this.session.stopped = force ? FORCED_STOP : STOP; - }, - - /** - * run the recognizers! - * called by the inputHandler function on every movement of the pointers (touches) - * it walks through all the recognizers and tries to detect the gesture that is being made - * @param {Object} inputData - */ - recognize: function(inputData) { - var session = this.session; - if (session.stopped) { - return; - } - - // run the touch-action polyfill - this.touchAction.preventDefaults(inputData); - - var recognizer; - var recognizers = this.recognizers; - - // this holds the recognizer that is being recognized. - // so the recognizer's state needs to be BEGAN, CHANGED, ENDED or RECOGNIZED - // if no recognizer is detecting a thing, it is set to `null` - var curRecognizer = session.curRecognizer; - - // reset when the last recognizer is recognized - // or when we're in a new session - if (!curRecognizer || (curRecognizer && curRecognizer.state & STATE_RECOGNIZED)) { - curRecognizer = session.curRecognizer = null; - } - - var i = 0; - while (i < recognizers.length) { - recognizer = recognizers[i]; - - // find out if we are allowed try to recognize the input for this one. - // 1. allow if the session is NOT forced stopped (see the .stop() method) - // 2. allow if we still haven't recognized a gesture in this session, or the this recognizer is the one - // that is being recognized. - // 3. allow if the recognizer is allowed to run simultaneous with the current recognized recognizer. - // this can be setup with the `recognizeWith()` method on the recognizer. - if (session.stopped !== FORCED_STOP && (// 1 - !curRecognizer || recognizer == curRecognizer || // 2 - recognizer.canRecognizeWith(curRecognizer))) { // 3 - recognizer.recognize(inputData); - } else { - recognizer.reset(); - } - - // if the recognizer has been recognizing the input as a valid gesture, we want to store this one as the - // current active recognizer. but only if we don't already have an active recognizer - if (!curRecognizer && recognizer.state & (STATE_BEGAN | STATE_CHANGED | STATE_ENDED)) { - curRecognizer = session.curRecognizer = recognizer; - } - i++; - } - }, - - /** - * get a recognizer by its event name. - * @param {Recognizer|String} recognizer - * @returns {Recognizer|Null} - */ - get: function(recognizer) { - if (recognizer instanceof Recognizer) { - return recognizer; - } - - var recognizers = this.recognizers; - for (var i = 0; i < recognizers.length; i++) { - if (recognizers[i].options.event == recognizer) { - return recognizers[i]; - } - } - return null; - }, - - /** - * add a recognizer to the manager - * existing recognizers with the same event name will be removed - * @param {Recognizer} recognizer - * @returns {Recognizer|Manager} - */ - add: function(recognizer) { - if (invokeArrayArg(recognizer, 'add', this)) { - return this; - } - - // remove existing - var existing = this.get(recognizer.options.event); - if (existing) { - this.remove(existing); - } - - this.recognizers.push(recognizer); - recognizer.manager = this; + /** + * set options + * @param {Object} options + * @returns {Manager} + */ + set: function(options) { + assign(this.options, options); + + // Options that need a little more setup + if (options.touchAction) { + this.touchAction.update(); + } + if (options.inputTarget) { + // Clean up existing event listeners and reinitialize + this.input.destroy(); + this.input.target = options.inputTarget; + this.input.init(); + } + return this; + }, + + /** + * stop recognizing for this session. + * This session will be discarded, when a new [input]start event is fired. + * When forced, the recognizer cycle is stopped immediately. + * @param {Boolean} [force] + */ + stop: function(force) { + this.session.stopped = force ? FORCED_STOP : STOP; + }, + + /** + * run the recognizers! + * called by the inputHandler function on every movement of the pointers (touches) + * it walks through all the recognizers and tries to detect the gesture that is being made + * @param {Object} inputData + */ + recognize: function(inputData) { + var session = this.session; + if (session.stopped) { + return; + } + + // run the touch-action polyfill + this.touchAction.preventDefaults(inputData); + + var recognizer; + var recognizers = this.recognizers; + + // this holds the recognizer that is being recognized. + // so the recognizer's state needs to be BEGAN, CHANGED, ENDED or RECOGNIZED + // if no recognizer is detecting a thing, it is set to `null` + var curRecognizer = session.curRecognizer; + + // reset when the last recognizer is recognized + // or when we're in a new session + if (!curRecognizer || (curRecognizer && curRecognizer.state & STATE_RECOGNIZED)) { + curRecognizer = session.curRecognizer = null; + } + + var i = 0; + while (i < recognizers.length) { + recognizer = recognizers[i]; + + // find out if we are allowed try to recognize the input for this one. + // 1. allow if the session is NOT forced stopped (see the .stop() method) + // 2. allow if we still haven't recognized a gesture in this session, or the this recognizer is the one + // that is being recognized. + // 3. allow if the recognizer is allowed to run simultaneous with the current recognized recognizer. + // this can be setup with the `recognizeWith()` method on the recognizer. + if (session.stopped !== FORCED_STOP && (// 1 + !curRecognizer || recognizer == curRecognizer || // 2 + recognizer.canRecognizeWith(curRecognizer))) { // 3 + recognizer.recognize(inputData); + } else { + recognizer.reset(); + } + + // if the recognizer has been recognizing the input as a valid gesture, we want to store this one as the + // current active recognizer. but only if we don't already have an active recognizer + if (!curRecognizer && recognizer.state & (STATE_BEGAN | STATE_CHANGED | STATE_ENDED)) { + curRecognizer = session.curRecognizer = recognizer; + } + i++; + } + }, + + /** + * get a recognizer by its event name. + * @param {Recognizer|String} recognizer + * @returns {Recognizer|Null} + */ + get: function(recognizer) { + if (recognizer instanceof Recognizer) { + return recognizer; + } + + var recognizers = this.recognizers; + for (var i = 0; i < recognizers.length; i++) { + if (recognizers[i].options.event == recognizer) { + return recognizers[i]; + } + } + return null; + }, + + /** + * add a recognizer to the manager + * existing recognizers with the same event name will be removed + * @param {Recognizer} recognizer + * @returns {Recognizer|Manager} + */ + add: function(recognizer) { + if (invokeArrayArg(recognizer, 'add', this)) { + return this; + } + + // remove existing + var existing = this.get(recognizer.options.event); + if (existing) { + this.remove(existing); + } + + this.recognizers.push(recognizer); + recognizer.manager = this; + + this.touchAction.update(); + return recognizer; + }, + + /** + * remove a recognizer by name or instance + * @param {Recognizer|String} recognizer + * @returns {Manager} + */ + remove: function(recognizer) { + if (invokeArrayArg(recognizer, 'remove', this)) { + return this; + } + + recognizer = this.get(recognizer); + // let's make sure this recognizer exists + if (recognizer) { + var recognizers = this.recognizers; + var index = inArray(recognizers, recognizer); + + if (index !== -1) { + recognizers.splice(index, 1); this.touchAction.update(); - return recognizer; - }, - - /** - * remove a recognizer by name or instance - * @param {Recognizer|String} recognizer - * @returns {Manager} - */ - remove: function(recognizer) { - if (invokeArrayArg(recognizer, 'remove', this)) { - return this; - } - - recognizer = this.get(recognizer); - - // let's make sure this recognizer exists - if (recognizer) { - var recognizers = this.recognizers; - var index = inArray(recognizers, recognizer); - - if (index !== -1) { - recognizers.splice(index, 1); - this.touchAction.update(); - } - } - - return this; - }, - - /** - * bind event - * @param {String} events - * @param {Function} handler - * @returns {EventEmitter} this - */ - on: function(events, handler) { - if (events === undefined) { - return; - } - if (handler === undefined) { - return; - } - - var handlers = this.handlers; - each(splitStr(events), function(event) { - handlers[event] = handlers[event] || []; - handlers[event].push(handler); - }); - return this; - }, - - /** - * unbind event, leave emit blank to remove all handlers - * @param {String} events - * @param {Function} [handler] - * @returns {EventEmitter} this - */ - off: function(events, handler) { - if (events === undefined) { - return; - } - - var handlers = this.handlers; - each(splitStr(events), function(event) { - if (!handler) { - delete handlers[event]; - } else { - handlers[event] && handlers[event].splice(inArray(handlers[event], handler), 1); - } - }); - return this; - }, - - /** - * emit event to the listeners - * @param {String} event - * @param {Object} data - */ - emit: function(event, data) { - // we also want to trigger dom events - if (this.options.domEvents) { - triggerDomEvent(event, data); - } - - // no handlers, so skip it all - var handlers = this.handlers[event] && this.handlers[event].slice(); - if (!handlers || !handlers.length) { - return; - } - - data.type = event; - data.preventDefault = function() { - data.srcEvent.preventDefault(); - }; - - var i = 0; - while (i < handlers.length) { - handlers[i](data); - i++; - } - }, - - /** - * destroy the manager and unbinds all events - * it doesn't unbind dom events, that is the user own responsibility - */ - destroy: function() { - this.element && toggleCssProps(this, false); - - this.handlers = {}; - this.session = {}; - this.input.destroy(); - this.element = null; + } + } + + return this; + }, + + /** + * bind event + * @param {String} events + * @param {Function} handler + * @returns {EventEmitter} this + */ + on: function(events, handler) { + if (events === undefined) { + return; } + if (handler === undefined) { + return; + } + + var handlers = this.handlers; + each(splitStr(events), function(event) { + handlers[event] = handlers[event] || []; + handlers[event].push(handler); + }); + return this; + }, + + /** + * unbind event, leave emit blank to remove all handlers + * @param {String} events + * @param {Function} [handler] + * @returns {EventEmitter} this + */ + off: function(events, handler) { + if (events === undefined) { + return; + } + + var handlers = this.handlers; + each(splitStr(events), function(event) { + if (!handler) { + delete handlers[event]; + } else { + handlers[event] && handlers[event].splice(inArray(handlers[event], handler), 1); + } + }); + return this; + }, + + /** + * emit event to the listeners + * @param {String} event + * @param {Object} data + */ + emit: function(event, data) { + // we also want to trigger dom events + if (this.options.domEvents) { + triggerDomEvent(event, data); + } + + // no handlers, so skip it all + var handlers = this.handlers[event] && this.handlers[event].slice(); + if (!handlers || !handlers.length) { + return; + } + + data.type = event; + data.preventDefault = function() { + data.srcEvent.preventDefault(); + }; + + var i = 0; + while (i < handlers.length) { + handlers[i](data); + i++; + } + }, + + /** + * destroy the manager and unbinds all events + * it doesn't unbind dom events, that is the user own responsibility + */ + destroy: function() { + this.element && toggleCssProps(this, false); + + this.handlers = {}; + this.session = {}; + this.input.destroy(); + this.element = null; + } }; /** @@ -297,23 +297,23 @@ Manager.prototype = { * @param {Boolean} add */ function toggleCssProps(manager, add) { - var element = manager.element; - if (!element.style) { - return; - } - var prop; - each(manager.options.cssProps, function(value, name) { - prop = prefixed(element.style, name); - if (add) { - manager.oldCssProps[prop] = element.style[prop]; - element.style[prop] = value; - } else { - element.style[prop] = manager.oldCssProps[prop] || ''; - } - }); - if (!add) { - manager.oldCssProps = {}; + var element = manager.element; + if (!element.style) { + return; + } + var prop; + each(manager.options.cssProps, function(value, name) { + prop = prefixed(element.style, name); + if (add) { + manager.oldCssProps[prop] = element.style[prop]; + element.style[prop] = value; + } else { + element.style[prop] = manager.oldCssProps[prop] || ''; } + }); + if (!add) { + manager.oldCssProps = {}; + } } /** @@ -322,10 +322,10 @@ function toggleCssProps(manager, add) { * @param {Object} data */ function triggerDomEvent(event, data) { - var gestureEvent = document.createEvent('Event'); - gestureEvent.initEvent(event, true, true); - gestureEvent.gesture = data; - data.target.dispatchEvent(gestureEvent); + var gestureEvent = document.createEvent('Event'); + gestureEvent.initEvent(event, true, true); + gestureEvent.gesture = data; + data.target.dispatchEvent(gestureEvent); } export { Manager }; diff --git a/src/recognizerjs/direction-str.js b/src/recognizerjs/direction-str.js index d1a1ea7ce..ffaf2ecb5 100644 --- a/src/recognizerjs/direction-str.js +++ b/src/recognizerjs/direction-str.js @@ -11,14 +11,14 @@ import { * @returns {String} */ export default function directionStr(direction) { - if (direction == DIRECTION_DOWN) { - return 'down'; - } else if (direction == DIRECTION_UP) { - return 'up'; - } else if (direction == DIRECTION_LEFT) { - return 'left'; - } else if (direction == DIRECTION_RIGHT) { - return 'right'; - } - return ''; + if (direction == DIRECTION_DOWN) { + return 'down'; + } else if (direction == DIRECTION_UP) { + return 'up'; + } else if (direction == DIRECTION_LEFT) { + return 'left'; + } else if (direction == DIRECTION_RIGHT) { + return 'right'; + } + return ''; } diff --git a/src/recognizerjs/get-recognizer-by-name-if-manager.js b/src/recognizerjs/get-recognizer-by-name-if-manager.js index 52bd53012..02de27bd3 100644 --- a/src/recognizerjs/get-recognizer-by-name-if-manager.js +++ b/src/recognizerjs/get-recognizer-by-name-if-manager.js @@ -5,9 +5,9 @@ * @returns {Recognizer} */ export default function getRecognizerByNameIfManager(otherRecognizer, recognizer) { - var manager = recognizer.manager; - if (manager) { - return manager.get(otherRecognizer); - } - return otherRecognizer; + var manager = recognizer.manager; + if (manager) { + return manager.get(otherRecognizer); + } + return otherRecognizer; } diff --git a/src/recognizerjs/recognizer-constructor.js b/src/recognizerjs/recognizer-constructor.js index e0065458c..18eefbf80 100644 --- a/src/recognizerjs/recognizer-constructor.js +++ b/src/recognizerjs/recognizer-constructor.js @@ -51,240 +51,240 @@ import stateStr from './state-str'; * @param {Object} options */ function Recognizer(options) { - this.options = assign({}, this.defaults, options || {}); + this.options = assign({}, this.defaults, options || {}); - this.id = uniqueId(); + this.id = uniqueId(); - this.manager = null; + this.manager = null; - // default is enable true - this.options.enable = ifUndefined(this.options.enable, true); + // default is enable true + this.options.enable = ifUndefined(this.options.enable, true); - this.state = STATE_POSSIBLE; + this.state = STATE_POSSIBLE; - this.simultaneous = {}; - this.requireFail = []; + this.simultaneous = {}; + this.requireFail = []; } Recognizer.prototype = { - /** - * @virtual - * @type {Object} - */ - defaults: {}, - - /** - * set options - * @param {Object} options - * @return {Recognizer} - */ - set: function(options) { - assign(this.options, options); - - // also update the touchAction, in case something changed about the directions/enabled state - this.manager && this.manager.touchAction.update(); - return this; - }, - - /** - * recognize simultaneous with an other recognizer. - * @param {Recognizer} otherRecognizer - * @returns {Recognizer} this - */ - recognizeWith: function(otherRecognizer) { - if (invokeArrayArg(otherRecognizer, 'recognizeWith', this)) { - return this; - } - - var simultaneous = this.simultaneous; - otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this); - if (!simultaneous[otherRecognizer.id]) { - simultaneous[otherRecognizer.id] = otherRecognizer; - otherRecognizer.recognizeWith(this); - } - return this; - }, - - /** - * drop the simultaneous link. it doesnt remove the link on the other recognizer. - * @param {Recognizer} otherRecognizer - * @returns {Recognizer} this - */ - dropRecognizeWith: function(otherRecognizer) { - if (invokeArrayArg(otherRecognizer, 'dropRecognizeWith', this)) { - return this; - } - - otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this); - delete this.simultaneous[otherRecognizer.id]; - return this; - }, - - /** - * recognizer can only run when an other is failing - * @param {Recognizer} otherRecognizer - * @returns {Recognizer} this - */ - requireFailure: function(otherRecognizer) { - if (invokeArrayArg(otherRecognizer, 'requireFailure', this)) { - return this; - } - - var requireFail = this.requireFail; - otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this); - if (inArray(requireFail, otherRecognizer) === -1) { - requireFail.push(otherRecognizer); - otherRecognizer.requireFailure(this); - } - return this; - }, - - /** - * drop the requireFailure link. it does not remove the link on the other recognizer. - * @param {Recognizer} otherRecognizer - * @returns {Recognizer} this - */ - dropRequireFailure: function(otherRecognizer) { - if (invokeArrayArg(otherRecognizer, 'dropRequireFailure', this)) { - return this; - } - - otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this); - var index = inArray(this.requireFail, otherRecognizer); - if (index > -1) { - this.requireFail.splice(index, 1); - } - return this; - }, - - /** - * has require failures boolean - * @returns {boolean} - */ - hasRequireFailures: function() { - return this.requireFail.length > 0; - }, - - /** - * if the recognizer can recognize simultaneous with an other recognizer - * @param {Recognizer} otherRecognizer - * @returns {Boolean} - */ - canRecognizeWith: function(otherRecognizer) { - return !!this.simultaneous[otherRecognizer.id]; - }, - - /** - * You should use `tryEmit` instead of `emit` directly to check - * that all the needed recognizers has failed before emitting. - * @param {Object} input - */ - emit: function(input) { - var self = this; - var state = this.state; - - function emit(event) { - self.manager.emit(event, input); - } - - // 'panstart' and 'panmove' - if (state < STATE_ENDED) { - emit(self.options.event + stateStr(state)); - } - - emit(self.options.event); // simple 'eventName' events - - if (input.additionalEvent) { // additional event(panleft, panright, pinchin, pinchout...) - emit(input.additionalEvent); - } - - // panend and pancancel - if (state >= STATE_ENDED) { - emit(self.options.event + stateStr(state)); - } - }, - - /** - * Check that all the require failure recognizers has failed, - * if true, it emits a gesture event, - * otherwise, setup the state to FAILED. - * @param {Object} input - */ - tryEmit: function(input) { - if (this.canEmit()) { - return this.emit(input); - } - // it's failing anyway - this.state = STATE_FAILED; - }, - - /** - * can we emit? - * @returns {boolean} - */ - canEmit: function() { - var i = 0; - while (i < this.requireFail.length) { - if (!(this.requireFail[i].state & (STATE_FAILED | STATE_POSSIBLE))) { - return false; - } - i++; - } - return true; - }, - - /** - * update the recognizer - * @param {Object} inputData - */ - recognize: function(inputData) { - // make a new copy of the inputData - // so we can change the inputData without messing up the other recognizers - var inputDataClone = assign({}, inputData); - - // is is enabled and allow recognizing? - if (!boolOrFn(this.options.enable, [this, inputDataClone])) { - this.reset(); - this.state = STATE_FAILED; - return; - } - - // reset when we've reached the end - if (this.state & (STATE_RECOGNIZED | STATE_CANCELLED | STATE_FAILED)) { - this.state = STATE_POSSIBLE; - } - - this.state = this.process(inputDataClone); - - // the recognizer has recognized a gesture - // so trigger an event - if (this.state & (STATE_BEGAN | STATE_CHANGED | STATE_ENDED | STATE_CANCELLED)) { - this.tryEmit(inputDataClone); - } - }, - - /** - * return the state of the recognizer - * the actual recognizing happens in this method - * @virtual - * @param {Object} inputData - * @returns {constant} STATE - */ - process: function(inputData) { }, // jshint ignore:line - - /** - * return the preferred touch-action - * @virtual - * @returns {Array} - */ - getTouchAction: function() { }, - - /** - * called when the gesture isn't allowed to recognize - * like when another is being recognized or it is disabled - * @virtual - */ - reset: function() { } + /** + * @virtual + * @type {Object} + */ + defaults: {}, + + /** + * set options + * @param {Object} options + * @return {Recognizer} + */ + set: function(options) { + assign(this.options, options); + + // also update the touchAction, in case something changed about the directions/enabled state + this.manager && this.manager.touchAction.update(); + return this; + }, + + /** + * recognize simultaneous with an other recognizer. + * @param {Recognizer} otherRecognizer + * @returns {Recognizer} this + */ + recognizeWith: function(otherRecognizer) { + if (invokeArrayArg(otherRecognizer, 'recognizeWith', this)) { + return this; + } + + var simultaneous = this.simultaneous; + otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this); + if (!simultaneous[otherRecognizer.id]) { + simultaneous[otherRecognizer.id] = otherRecognizer; + otherRecognizer.recognizeWith(this); + } + return this; + }, + + /** + * drop the simultaneous link. it doesnt remove the link on the other recognizer. + * @param {Recognizer} otherRecognizer + * @returns {Recognizer} this + */ + dropRecognizeWith: function(otherRecognizer) { + if (invokeArrayArg(otherRecognizer, 'dropRecognizeWith', this)) { + return this; + } + + otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this); + delete this.simultaneous[otherRecognizer.id]; + return this; + }, + + /** + * recognizer can only run when an other is failing + * @param {Recognizer} otherRecognizer + * @returns {Recognizer} this + */ + requireFailure: function(otherRecognizer) { + if (invokeArrayArg(otherRecognizer, 'requireFailure', this)) { + return this; + } + + var requireFail = this.requireFail; + otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this); + if (inArray(requireFail, otherRecognizer) === -1) { + requireFail.push(otherRecognizer); + otherRecognizer.requireFailure(this); + } + return this; + }, + + /** + * drop the requireFailure link. it does not remove the link on the other recognizer. + * @param {Recognizer} otherRecognizer + * @returns {Recognizer} this + */ + dropRequireFailure: function(otherRecognizer) { + if (invokeArrayArg(otherRecognizer, 'dropRequireFailure', this)) { + return this; + } + + otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this); + var index = inArray(this.requireFail, otherRecognizer); + if (index > -1) { + this.requireFail.splice(index, 1); + } + return this; + }, + + /** + * has require failures boolean + * @returns {boolean} + */ + hasRequireFailures: function() { + return this.requireFail.length > 0; + }, + + /** + * if the recognizer can recognize simultaneous with an other recognizer + * @param {Recognizer} otherRecognizer + * @returns {Boolean} + */ + canRecognizeWith: function(otherRecognizer) { + return !!this.simultaneous[otherRecognizer.id]; + }, + + /** + * You should use `tryEmit` instead of `emit` directly to check + * that all the needed recognizers has failed before emitting. + * @param {Object} input + */ + emit: function(input) { + var self = this; + var state = this.state; + + function emit(event) { + self.manager.emit(event, input); + } + + // 'panstart' and 'panmove' + if (state < STATE_ENDED) { + emit(self.options.event + stateStr(state)); + } + + emit(self.options.event); // simple 'eventName' events + + if (input.additionalEvent) { // additional event(panleft, panright, pinchin, pinchout...) + emit(input.additionalEvent); + } + + // panend and pancancel + if (state >= STATE_ENDED) { + emit(self.options.event + stateStr(state)); + } + }, + + /** + * Check that all the require failure recognizers has failed, + * if true, it emits a gesture event, + * otherwise, setup the state to FAILED. + * @param {Object} input + */ + tryEmit: function(input) { + if (this.canEmit()) { + return this.emit(input); + } + // it's failing anyway + this.state = STATE_FAILED; + }, + + /** + * can we emit? + * @returns {boolean} + */ + canEmit: function() { + var i = 0; + while (i < this.requireFail.length) { + if (!(this.requireFail[i].state & (STATE_FAILED | STATE_POSSIBLE))) { + return false; + } + i++; + } + return true; + }, + + /** + * update the recognizer + * @param {Object} inputData + */ + recognize: function(inputData) { + // make a new copy of the inputData + // so we can change the inputData without messing up the other recognizers + var inputDataClone = assign({}, inputData); + + // is is enabled and allow recognizing? + if (!boolOrFn(this.options.enable, [this, inputDataClone])) { + this.reset(); + this.state = STATE_FAILED; + return; + } + + // reset when we've reached the end + if (this.state & (STATE_RECOGNIZED | STATE_CANCELLED | STATE_FAILED)) { + this.state = STATE_POSSIBLE; + } + + this.state = this.process(inputDataClone); + + // the recognizer has recognized a gesture + // so trigger an event + if (this.state & (STATE_BEGAN | STATE_CHANGED | STATE_ENDED | STATE_CANCELLED)) { + this.tryEmit(inputDataClone); + } + }, + + /** + * return the state of the recognizer + * the actual recognizing happens in this method + * @virtual + * @param {Object} inputData + * @returns {constant} STATE + */ + process: function(inputData) { }, // jshint ignore:line + + /** + * return the preferred touch-action + * @virtual + * @returns {Array} + */ + getTouchAction: function() { }, + + /** + * called when the gesture isn't allowed to recognize + * like when another is being recognized or it is disabled + * @virtual + */ + reset: function() { } }; export { Recognizer }; diff --git a/src/recognizerjs/state-str.js b/src/recognizerjs/state-str.js index 85cfd0447..acf92f197 100644 --- a/src/recognizerjs/state-str.js +++ b/src/recognizerjs/state-str.js @@ -11,14 +11,14 @@ import { * @returns {String} state */ export default function stateStr(state) { - if (state & STATE_CANCELLED) { - return 'cancel'; - } else if (state & STATE_ENDED) { - return 'end'; - } else if (state & STATE_CHANGED) { - return 'move'; - } else if (state & STATE_BEGAN) { - return 'start'; - } - return ''; + if (state & STATE_CANCELLED) { + return 'cancel'; + } else if (state & STATE_ENDED) { + return 'end'; + } else if (state & STATE_CHANGED) { + return 'move'; + } else if (state & STATE_BEGAN) { + return 'start'; + } + return ''; } diff --git a/src/recognizers/attribute.js b/src/recognizers/attribute.js index e319e2fd4..a1878b870 100644 --- a/src/recognizers/attribute.js +++ b/src/recognizers/attribute.js @@ -18,59 +18,59 @@ import { * @extends Recognizer */ function AttrRecognizer() { - Recognizer.apply(this, arguments); + Recognizer.apply(this, arguments); } inherit(AttrRecognizer, Recognizer, { + /** + * @namespace + * @memberof AttrRecognizer + */ + defaults: { /** - * @namespace - * @memberof AttrRecognizer + * @type {Number} + * @default 1 */ - defaults: { - /** - * @type {Number} - * @default 1 - */ - pointers: 1 - }, + pointers: 1 + }, - /** - * Used to check if it the recognizer receives valid input, like input.distance > 10. - * @memberof AttrRecognizer - * @param {Object} input - * @returns {Boolean} recognized - */ - attrTest: function(input) { - var optionPointers = this.options.pointers; - return optionPointers === 0 || input.pointers.length === optionPointers; - }, + /** + * Used to check if it the recognizer receives valid input, like input.distance > 10. + * @memberof AttrRecognizer + * @param {Object} input + * @returns {Boolean} recognized + */ + attrTest: function(input) { + var optionPointers = this.options.pointers; + return optionPointers === 0 || input.pointers.length === optionPointers; + }, - /** - * Process the input and return the state for the recognizer - * @memberof AttrRecognizer - * @param {Object} input - * @returns {*} State - */ - process: function(input) { - var state = this.state; - var eventType = input.eventType; + /** + * Process the input and return the state for the recognizer + * @memberof AttrRecognizer + * @param {Object} input + * @returns {*} State + */ + process: function(input) { + var state = this.state; + var eventType = input.eventType; - var isRecognized = state & (STATE_BEGAN | STATE_CHANGED); - var isValid = this.attrTest(input); + var isRecognized = state & (STATE_BEGAN | STATE_CHANGED); + var isValid = this.attrTest(input); - // on cancel input and we've recognized before, return STATE_CANCELLED - if (isRecognized && (eventType & INPUT_CANCEL || !isValid)) { - return state | STATE_CANCELLED; - } else if (isRecognized || isValid) { - if (eventType & INPUT_END) { - return state | STATE_ENDED; - } else if (!(state & STATE_BEGAN)) { - return STATE_BEGAN; - } - return state | STATE_CHANGED; - } - return STATE_FAILED; + // on cancel input and we've recognized before, return STATE_CANCELLED + if (isRecognized && (eventType & INPUT_CANCEL || !isValid)) { + return state | STATE_CANCELLED; + } else if (isRecognized || isValid) { + if (eventType & INPUT_END) { + return state | STATE_ENDED; + } else if (!(state & STATE_BEGAN)) { + return STATE_BEGAN; + } + return state | STATE_CHANGED; } + return STATE_FAILED; + } }); export { AttrRecognizer }; diff --git a/src/recognizers/pan.js b/src/recognizers/pan.js index fc6d47653..12134583a 100644 --- a/src/recognizers/pan.js +++ b/src/recognizers/pan.js @@ -21,77 +21,77 @@ import directionStr from '../recognizerjs/direction-str'; * @extends AttrRecognizer */ function PanRecognizer() { - AttrRecognizer.apply(this, arguments); + AttrRecognizer.apply(this, arguments); - this.pX = null; - this.pY = null; + this.pX = null; + this.pY = null; } inherit(PanRecognizer, AttrRecognizer, { - /** - * @namespace - * @memberof PanRecognizer - */ - defaults: { - event: 'pan', - threshold: 10, - pointers: 1, - direction: DIRECTION_ALL - }, + /** + * @namespace + * @memberof PanRecognizer + */ + defaults: { + event: 'pan', + threshold: 10, + pointers: 1, + direction: DIRECTION_ALL + }, - getTouchAction: function() { - var direction = this.options.direction; - var actions = []; - if (direction & DIRECTION_HORIZONTAL) { - actions.push(TOUCH_ACTION_PAN_Y); - } - if (direction & DIRECTION_VERTICAL) { - actions.push(TOUCH_ACTION_PAN_X); - } - return actions; - }, + getTouchAction: function() { + var direction = this.options.direction; + var actions = []; + if (direction & DIRECTION_HORIZONTAL) { + actions.push(TOUCH_ACTION_PAN_Y); + } + if (direction & DIRECTION_VERTICAL) { + actions.push(TOUCH_ACTION_PAN_X); + } + return actions; + }, - directionTest: function(input) { - var options = this.options; - var hasMoved = true; - var distance = input.distance; - var direction = input.direction; - var x = input.deltaX; - var y = input.deltaY; + directionTest: function(input) { + var options = this.options; + var hasMoved = true; + var distance = input.distance; + var direction = input.direction; + var x = input.deltaX; + var y = input.deltaY; - // lock to axis? - if (!(direction & options.direction)) { - if (options.direction & DIRECTION_HORIZONTAL) { - direction = (x === 0) ? DIRECTION_NONE : (x < 0) ? DIRECTION_LEFT : DIRECTION_RIGHT; - hasMoved = x != this.pX; - distance = Math.abs(input.deltaX); - } else { - direction = (y === 0) ? DIRECTION_NONE : (y < 0) ? DIRECTION_UP : DIRECTION_DOWN; - hasMoved = y != this.pY; - distance = Math.abs(input.deltaY); - } - } - input.direction = direction; - return hasMoved && distance > options.threshold && direction & options.direction; - }, + // lock to axis? + if (!(direction & options.direction)) { + if (options.direction & DIRECTION_HORIZONTAL) { + direction = (x === 0) ? DIRECTION_NONE : (x < 0) ? DIRECTION_LEFT : DIRECTION_RIGHT; + hasMoved = x != this.pX; + distance = Math.abs(input.deltaX); + } else { + direction = (y === 0) ? DIRECTION_NONE : (y < 0) ? DIRECTION_UP : DIRECTION_DOWN; + hasMoved = y != this.pY; + distance = Math.abs(input.deltaY); + } + } + input.direction = direction; + return hasMoved && distance > options.threshold && direction & options.direction; + }, - attrTest: function(input) { - return AttrRecognizer.prototype.attrTest.call(this, input) && - (this.state & STATE_BEGAN || (!(this.state & STATE_BEGAN) && this.directionTest(input))); - }, + attrTest: function(input) { + return AttrRecognizer.prototype.attrTest.call(this, input) && + (this.state & STATE_BEGAN || (!(this.state & STATE_BEGAN) && this.directionTest(input))); + }, - emit: function(input) { + emit: function(input) { - this.pX = input.deltaX; - this.pY = input.deltaY; + this.pX = input.deltaX; + this.pY = input.deltaY; - var direction = directionStr(input.direction); + var direction = directionStr(input.direction); - if (direction) { - input.additionalEvent = this.options.event + direction; - } - this._super.emit.call(this, input); + if (direction) { + input.additionalEvent = this.options.event + direction; } + this._super.emit.call(this, input); + } }); export { PanRecognizer }; diff --git a/src/recognizers/pinch.js b/src/recognizers/pinch.js index 593fcc437..931f593fd 100644 --- a/src/recognizers/pinch.js +++ b/src/recognizers/pinch.js @@ -10,36 +10,36 @@ import { STATE_BEGAN } from '../recognizerjs/recognizer-consts'; * @extends AttrRecognizer */ function PinchRecognizer() { - AttrRecognizer.apply(this, arguments); + AttrRecognizer.apply(this, arguments); } inherit(PinchRecognizer, AttrRecognizer, { - /** - * @namespace - * @memberof PinchRecognizer - */ - defaults: { - event: 'pinch', - threshold: 0, - pointers: 2 - }, + /** + * @namespace + * @memberof PinchRecognizer + */ + defaults: { + event: 'pinch', + threshold: 0, + pointers: 2 + }, - getTouchAction: function() { - return [TOUCH_ACTION_NONE]; - }, + getTouchAction: function() { + return [TOUCH_ACTION_NONE]; + }, - attrTest: function(input) { - return this._super.attrTest.call(this, input) && - (Math.abs(input.scale - 1) > this.options.threshold || this.state & STATE_BEGAN); - }, + attrTest: function(input) { + return this._super.attrTest.call(this, input) && + (Math.abs(input.scale - 1) > this.options.threshold || this.state & STATE_BEGAN); + }, - emit: function(input) { - if (input.scale !== 1) { - var inOut = input.scale < 1 ? 'in' : 'out'; - input.additionalEvent = this.options.event + inOut; - } - this._super.emit.call(this, input); + emit: function(input) { + if (input.scale !== 1) { + var inOut = input.scale < 1 ? 'in' : 'out'; + input.additionalEvent = this.options.event + inOut; } + this._super.emit.call(this, input); + } }); export { PinchRecognizer }; diff --git a/src/recognizers/press.js b/src/recognizers/press.js index 0b8e37498..3fa32dfec 100644 --- a/src/recognizers/press.js +++ b/src/recognizers/press.js @@ -20,68 +20,68 @@ import { * @extends Recognizer */ function PressRecognizer() { - Recognizer.apply(this, arguments); + Recognizer.apply(this, arguments); - this._timer = null; - this._input = null; + this._timer = null; + this._input = null; } inherit(PressRecognizer, Recognizer, { - /** - * @namespace - * @memberof PressRecognizer - */ - defaults: { - event: 'press', - pointers: 1, - time: 251, // minimal time of the pointer to be pressed - threshold: 9 // a minimal movement is ok, but keep it low - }, + /** + * @namespace + * @memberof PressRecognizer + */ + defaults: { + event: 'press', + pointers: 1, + time: 251, // minimal time of the pointer to be pressed + threshold: 9 // a minimal movement is ok, but keep it low + }, - getTouchAction: function() { - return [TOUCH_ACTION_AUTO]; - }, + getTouchAction: function() { + return [TOUCH_ACTION_AUTO]; + }, - process: function(input) { - var options = this.options; - var validPointers = input.pointers.length === options.pointers; - var validMovement = input.distance < options.threshold; - var validTime = input.deltaTime > options.time; + process: function(input) { + var options = this.options; + var validPointers = input.pointers.length === options.pointers; + var validMovement = input.distance < options.threshold; + var validTime = input.deltaTime > options.time; - this._input = input; + this._input = input; - // we only allow little movement - // and we've reached an end event, so a tap is possible - if (!validMovement || !validPointers || (input.eventType & (INPUT_END | INPUT_CANCEL) && !validTime)) { - this.reset(); - } else if (input.eventType & INPUT_START) { - this.reset(); - this._timer = setTimeoutContext(function() { - this.state = STATE_RECOGNIZED; - this.tryEmit(); - }, options.time, this); - } else if (input.eventType & INPUT_END) { - return STATE_RECOGNIZED; - } - return STATE_FAILED; - }, + // we only allow little movement + // and we've reached an end event, so a tap is possible + if (!validMovement || !validPointers || (input.eventType & (INPUT_END | INPUT_CANCEL) && !validTime)) { + this.reset(); + } else if (input.eventType & INPUT_START) { + this.reset(); + this._timer = setTimeoutContext(function() { + this.state = STATE_RECOGNIZED; + this.tryEmit(); + }, options.time, this); + } else if (input.eventType & INPUT_END) { + return STATE_RECOGNIZED; + } + return STATE_FAILED; + }, - reset: function() { - clearTimeout(this._timer); - }, + reset: function() { + clearTimeout(this._timer); + }, - emit: function(input) { - if (this.state !== STATE_RECOGNIZED) { - return; - } + emit: function(input) { + if (this.state !== STATE_RECOGNIZED) { + return; + } - if (input && (input.eventType & INPUT_END)) { - this.manager.emit(this.options.event + 'up', input); - } else { - this._input.timeStamp = now(); - this.manager.emit(this.options.event, this._input); - } + if (input && (input.eventType & INPUT_END)) { + this.manager.emit(this.options.event + 'up', input); + } else { + this._input.timeStamp = now(); + this.manager.emit(this.options.event, this._input); } + } }); export { PressRecognizer }; diff --git a/src/recognizers/rotate.js b/src/recognizers/rotate.js index c4d3f7398..fa7a33c59 100644 --- a/src/recognizers/rotate.js +++ b/src/recognizers/rotate.js @@ -10,28 +10,28 @@ import { STATE_BEGAN } from '../recognizerjs/recognizer-consts'; * @extends AttrRecognizer */ function RotateRecognizer() { - AttrRecognizer.apply(this, arguments); + AttrRecognizer.apply(this, arguments); } inherit(RotateRecognizer, AttrRecognizer, { - /** - * @namespace - * @memberof RotateRecognizer - */ - defaults: { - event: 'rotate', - threshold: 0, - pointers: 2 - }, + /** + * @namespace + * @memberof RotateRecognizer + */ + defaults: { + event: 'rotate', + threshold: 0, + pointers: 2 + }, - getTouchAction: function() { - return [TOUCH_ACTION_NONE]; - }, + getTouchAction: function() { + return [TOUCH_ACTION_NONE]; + }, - attrTest: function(input) { - return this._super.attrTest.call(this, input) && - (Math.abs(input.rotation) > this.options.threshold || this.state & STATE_BEGAN); - } + attrTest: function(input) { + return this._super.attrTest.call(this, input) && + (Math.abs(input.rotation) > this.options.threshold || this.state & STATE_BEGAN); + } }); export {RotateRecognizer}; diff --git a/src/recognizers/swipe.js b/src/recognizers/swipe.js index c7525b829..caea8f218 100644 --- a/src/recognizers/swipe.js +++ b/src/recognizers/swipe.js @@ -13,53 +13,53 @@ import directionStr from '../recognizerjs/direction-str'; * @extends AttrRecognizer */ function SwipeRecognizer() { - AttrRecognizer.apply(this, arguments); + AttrRecognizer.apply(this, arguments); } inherit(SwipeRecognizer, AttrRecognizer, { - /** - * @namespace - * @memberof SwipeRecognizer - */ - defaults: { - event: 'swipe', - threshold: 10, - velocity: 0.3, - direction: DIRECTION_HORIZONTAL | DIRECTION_VERTICAL, - pointers: 1 - }, + /** + * @namespace + * @memberof SwipeRecognizer + */ + defaults: { + event: 'swipe', + threshold: 10, + velocity: 0.3, + direction: DIRECTION_HORIZONTAL | DIRECTION_VERTICAL, + pointers: 1 + }, - getTouchAction: function() { - return PanRecognizer.prototype.getTouchAction.call(this); - }, + getTouchAction: function() { + return PanRecognizer.prototype.getTouchAction.call(this); + }, - attrTest: function(input) { - var direction = this.options.direction; - var velocity; + attrTest: function(input) { + var direction = this.options.direction; + var velocity; - if (direction & (DIRECTION_HORIZONTAL | DIRECTION_VERTICAL)) { - velocity = input.overallVelocity; - } else if (direction & DIRECTION_HORIZONTAL) { - velocity = input.overallVelocityX; - } else if (direction & DIRECTION_VERTICAL) { - velocity = input.overallVelocityY; - } - - return this._super.attrTest.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; - }, + if (direction & (DIRECTION_HORIZONTAL | DIRECTION_VERTICAL)) { + velocity = input.overallVelocity; + } else if (direction & DIRECTION_HORIZONTAL) { + velocity = input.overallVelocityX; + } else if (direction & DIRECTION_VERTICAL) { + velocity = input.overallVelocityY; + } - emit: function(input) { - var direction = directionStr(input.offsetDirection); - if (direction) { - this.manager.emit(this.options.event + direction, input); - } + return this._super.attrTest.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; + }, - this.manager.emit(this.options.event, input); + emit: function(input) { + var direction = directionStr(input.offsetDirection); + if (direction) { + this.manager.emit(this.options.event + direction, input); } + + this.manager.emit(this.options.event, input); + } }); export { SwipeRecognizer }; diff --git a/src/recognizers/tap.js b/src/recognizers/tap.js index 25bbdfa60..cdef1bd57 100644 --- a/src/recognizers/tap.js +++ b/src/recognizers/tap.js @@ -21,108 +21,108 @@ import getDistance from '../inputjs/get-distance'; * @extends Recognizer */ function TapRecognizer() { - Recognizer.apply(this, arguments); + Recognizer.apply(this, arguments); - // previous time and center, - // used for tap counting - this.pTime = false; - this.pCenter = false; + // previous time and center, + // used for tap counting + this.pTime = false; + this.pCenter = false; - this._timer = null; - this._input = null; - this.count = 0; + this._timer = null; + this._input = null; + this.count = 0; } inherit(TapRecognizer, Recognizer, { - /** - * @namespace - * @memberof PinchRecognizer - */ - defaults: { - event: 'tap', - pointers: 1, - taps: 1, - interval: 300, // max time between the multi-tap taps - time: 250, // max time of the pointer to be down (like finger on the screen) - threshold: 9, // a minimal movement is ok, but keep it low - posThreshold: 10 // a multi-tap can be a bit off the initial position - }, - - getTouchAction: function() { - return [TOUCH_ACTION_MANIPULATION]; - }, - - process: function(input) { - var options = this.options; - - var validPointers = input.pointers.length === options.pointers; - var validMovement = input.distance < options.threshold; - var validTouchTime = input.deltaTime < options.time; - - this.reset(); - - if ((input.eventType & INPUT_START) && (this.count === 0)) { - return this.failTimeout(); - } + /** + * @namespace + * @memberof PinchRecognizer + */ + defaults: { + event: 'tap', + pointers: 1, + taps: 1, + interval: 300, // max time between the multi-tap taps + time: 250, // max time of the pointer to be down (like finger on the screen) + threshold: 9, // a minimal movement is ok, but keep it low + posThreshold: 10 // a multi-tap can be a bit off the initial position + }, + + getTouchAction: function() { + return [TOUCH_ACTION_MANIPULATION]; + }, + + process: function(input) { + var options = this.options; + + var validPointers = input.pointers.length === options.pointers; + var validMovement = input.distance < options.threshold; + var validTouchTime = input.deltaTime < options.time; + + this.reset(); + + if ((input.eventType & INPUT_START) && (this.count === 0)) { + return this.failTimeout(); + } - // we only allow little movement - // and we've reached an end event, so a tap is possible - if (validMovement && validTouchTime && validPointers) { - if (input.eventType != INPUT_END) { - return this.failTimeout(); - } - - var validInterval = this.pTime ? (input.timeStamp - this.pTime < options.interval) : true; - var validMultiTap = !this.pCenter || getDistance(this.pCenter, input.center) < options.posThreshold; - - this.pTime = input.timeStamp; - this.pCenter = input.center; - - if (!validMultiTap || !validInterval) { - this.count = 1; - } else { - this.count += 1; - } - - this._input = input; - - // if tap count matches we have recognized it, - // else it has began recognizing... - var tapCount = this.count % options.taps; - if (tapCount === 0) { - // no failing requirements, immediately trigger the tap event - // or wait as long as the multitap interval to trigger - if (!this.hasRequireFailures()) { - return STATE_RECOGNIZED; - } else { - this._timer = setTimeoutContext(function() { - this.state = STATE_RECOGNIZED; - this.tryEmit(); - }, options.interval, this); - return STATE_BEGAN; - } - } - } - return STATE_FAILED; - }, - - failTimeout: function() { - this._timer = setTimeoutContext(function() { - this.state = STATE_FAILED; - }, this.options.interval, this); - return STATE_FAILED; - }, - - reset: function() { - clearTimeout(this._timer); - }, - - emit: function() { - if (this.state == STATE_RECOGNIZED) { - this._input.tapCount = this.count; - this.manager.emit(this.options.event, this._input); + // we only allow little movement + // and we've reached an end event, so a tap is possible + if (validMovement && validTouchTime && validPointers) { + if (input.eventType != INPUT_END) { + return this.failTimeout(); + } + + var validInterval = this.pTime ? (input.timeStamp - this.pTime < options.interval) : true; + var validMultiTap = !this.pCenter || getDistance(this.pCenter, input.center) < options.posThreshold; + + this.pTime = input.timeStamp; + this.pCenter = input.center; + + if (!validMultiTap || !validInterval) { + this.count = 1; + } else { + this.count += 1; + } + + this._input = input; + + // if tap count matches we have recognized it, + // else it has began recognizing... + var tapCount = this.count % options.taps; + if (tapCount === 0) { + // no failing requirements, immediately trigger the tap event + // or wait as long as the multitap interval to trigger + if (!this.hasRequireFailures()) { + return STATE_RECOGNIZED; + } else { + this._timer = setTimeoutContext(function() { + this.state = STATE_RECOGNIZED; + this.tryEmit(); + }, options.interval, this); + return STATE_BEGAN; } + } + } + return STATE_FAILED; + }, + + failTimeout: function() { + this._timer = setTimeoutContext(function() { + this.state = STATE_FAILED; + }, this.options.interval, this); + return STATE_FAILED; + }, + + reset: function() { + clearTimeout(this._timer); + }, + + emit: function() { + if (this.state == STATE_RECOGNIZED) { + this._input.tapCount = this.count; + this.manager.emit(this.options.event, this._input); } + } }); export { TapRecognizer }; diff --git a/src/touchactionjs/clean-touch-actions.js b/src/touchactionjs/clean-touch-actions.js index eb09b53ee..80fea930d 100644 --- a/src/touchactionjs/clean-touch-actions.js +++ b/src/touchactionjs/clean-touch-actions.js @@ -13,31 +13,31 @@ import { * @returns {*} */ export default function cleanTouchActions(actions) { - // none - if (inStr(actions, TOUCH_ACTION_NONE)) { - return TOUCH_ACTION_NONE; - } + // none + if (inStr(actions, TOUCH_ACTION_NONE)) { + return TOUCH_ACTION_NONE; + } - var hasPanX = inStr(actions, TOUCH_ACTION_PAN_X); - var hasPanY = inStr(actions, TOUCH_ACTION_PAN_Y); + var hasPanX = inStr(actions, TOUCH_ACTION_PAN_X); + var hasPanY = inStr(actions, TOUCH_ACTION_PAN_Y); - // if both pan-x and pan-y are set (different recognizers - // for different directions, e.g. horizontal pan but vertical swipe?) - // we need none (as otherwise with pan-x pan-y combined none of these - // recognizers will work, since the browser would handle all panning - if (hasPanX && hasPanY) { - return TOUCH_ACTION_NONE; - } + // if both pan-x and pan-y are set (different recognizers + // for different directions, e.g. horizontal pan but vertical swipe?) + // we need none (as otherwise with pan-x pan-y combined none of these + // recognizers will work, since the browser would handle all panning + if (hasPanX && hasPanY) { + return TOUCH_ACTION_NONE; + } - // pan-x OR pan-y - if (hasPanX || hasPanY) { - return hasPanX ? TOUCH_ACTION_PAN_X : TOUCH_ACTION_PAN_Y; - } + // pan-x OR pan-y + if (hasPanX || hasPanY) { + return hasPanX ? TOUCH_ACTION_PAN_X : TOUCH_ACTION_PAN_Y; + } - // manipulation - if (inStr(actions, TOUCH_ACTION_MANIPULATION)) { - return TOUCH_ACTION_MANIPULATION; - } + // manipulation + if (inStr(actions, TOUCH_ACTION_MANIPULATION)) { + return TOUCH_ACTION_MANIPULATION; + } - return TOUCH_ACTION_AUTO; + return TOUCH_ACTION_AUTO; } diff --git a/src/touchactionjs/get-touchaction-props.js b/src/touchactionjs/get-touchaction-props.js index 6432f81a1..e9cb16462 100644 --- a/src/touchactionjs/get-touchaction-props.js +++ b/src/touchactionjs/get-touchaction-props.js @@ -1,16 +1,16 @@ import { NATIVE_TOUCH_ACTION } from './touchaction-Consts'; export default function getTouchActionProps() { - if (!NATIVE_TOUCH_ACTION) { - return false; - } - var touchMap = {}; - var cssSupports = window.CSS && window.CSS.supports; - ['auto', 'manipulation', 'pan-y', 'pan-x', 'pan-x pan-y', 'none'].forEach(function(val) { + if (!NATIVE_TOUCH_ACTION) { + return false; + } + var touchMap = {}; + var cssSupports = window.CSS && window.CSS.supports; + ['auto', 'manipulation', 'pan-y', 'pan-x', 'pan-x pan-y', 'none'].forEach(function(val) { - // If css.supports is not supported but there is native touch-action assume it supports - // all values. This is the case for IE 10 and 11. - touchMap[val] = cssSupports ? window.CSS.supports('touch-action', val) : true; - }); - return touchMap; + // If css.supports is not supported but there is native touch-action assume it supports + // all values. This is the case for IE 10 and 11. + touchMap[val] = cssSupports ? window.CSS.supports('touch-action', val) : true; + }); + return touchMap; } diff --git a/src/touchactionjs/touchaction-constructor.js b/src/touchactionjs/touchaction-constructor.js index fa238932e..af7202331 100644 --- a/src/touchactionjs/touchaction-constructor.js +++ b/src/touchactionjs/touchaction-constructor.js @@ -24,99 +24,99 @@ import cleanTouchActions from './clean-touch-actions'; * @constructor */ function TouchAction(manager, value) { - this.manager = manager; - this.set(value); + this.manager = manager; + this.set(value); } TouchAction.prototype = { - /** - * set the touchAction value on the element or enable the polyfill - * @param {String} value - */ - set: function(value) { - // find out the touch-action by the event handlers - if (value == TOUCH_ACTION_COMPUTE) { - value = this.compute(); - } - - if (NATIVE_TOUCH_ACTION && this.manager.element.style && TOUCH_ACTION_MAP[value]) { - this.manager.element.style[PREFIXED_TOUCH_ACTION] = value; - } - this.actions = value.toLowerCase().trim(); - }, + /** + * set the touchAction value on the element or enable the polyfill + * @param {String} value + */ + set: function(value) { + // find out the touch-action by the event handlers + if (value == TOUCH_ACTION_COMPUTE) { + value = this.compute(); + } - /** - * just re-set the touchAction value - */ - update: function() { - this.set(this.manager.options.touchAction); - }, + if (NATIVE_TOUCH_ACTION && this.manager.element.style && TOUCH_ACTION_MAP[value]) { + this.manager.element.style[PREFIXED_TOUCH_ACTION] = value; + } + this.actions = value.toLowerCase().trim(); + }, - /** - * compute the value for the touchAction property based on the recognizer's settings - * @returns {String} value - */ - compute: function() { - var actions = []; - each(this.manager.recognizers, function(recognizer) { - if (boolOrFn(recognizer.options.enable, [recognizer])) { - actions = actions.concat(recognizer.getTouchAction()); - } - }); - return cleanTouchActions(actions.join(' ')); - }, + /** + * just re-set the touchAction value + */ + update: function() { + this.set(this.manager.options.touchAction); + }, - /** - * this method is called on each input cycle and provides the preventing of the browser behavior - * @param {Object} input - */ - preventDefaults: function(input) { - var srcEvent = input.srcEvent; - var direction = input.offsetDirection; + /** + * compute the value for the touchAction property based on the recognizer's settings + * @returns {String} value + */ + compute: function() { + var actions = []; + each(this.manager.recognizers, function(recognizer) { + if (boolOrFn(recognizer.options.enable, [recognizer])) { + actions = actions.concat(recognizer.getTouchAction()); + } + }); + return cleanTouchActions(actions.join(' ')); + }, - // if the touch action did prevented once this session - if (this.manager.session.prevented) { - srcEvent.preventDefault(); - return; - } + /** + * this method is called on each input cycle and provides the preventing of the browser behavior + * @param {Object} input + */ + preventDefaults: function(input) { + var srcEvent = input.srcEvent; + var direction = input.offsetDirection; - var actions = this.actions; - var hasNone = inStr(actions, TOUCH_ACTION_NONE) && !TOUCH_ACTION_MAP[TOUCH_ACTION_NONE]; - var hasPanY = inStr(actions, TOUCH_ACTION_PAN_Y) && !TOUCH_ACTION_MAP[TOUCH_ACTION_PAN_Y]; - var hasPanX = inStr(actions, TOUCH_ACTION_PAN_X) && !TOUCH_ACTION_MAP[TOUCH_ACTION_PAN_X]; + // if the touch action did prevented once this session + if (this.manager.session.prevented) { + srcEvent.preventDefault(); + return; + } - if (hasNone) { - //do not prevent defaults if this is a tap gesture + var actions = this.actions; + var hasNone = inStr(actions, TOUCH_ACTION_NONE) && !TOUCH_ACTION_MAP[TOUCH_ACTION_NONE]; + var hasPanY = inStr(actions, TOUCH_ACTION_PAN_Y) && !TOUCH_ACTION_MAP[TOUCH_ACTION_PAN_Y]; + var hasPanX = inStr(actions, TOUCH_ACTION_PAN_X) && !TOUCH_ACTION_MAP[TOUCH_ACTION_PAN_X]; - var isTapPointer = input.pointers.length === 1; - var isTapMovement = input.distance < 2; - var isTapTouchTime = input.deltaTime < 250; + if (hasNone) { + //do not prevent defaults if this is a tap gesture - if (isTapPointer && isTapMovement && isTapTouchTime) { - return; - } - } + var isTapPointer = input.pointers.length === 1; + var isTapMovement = input.distance < 2; + var isTapTouchTime = input.deltaTime < 250; - if (hasPanX && hasPanY) { - // `pan-x pan-y` means browser handles all scrolling/panning, do not prevent - return; - } + if (isTapPointer && isTapMovement && isTapTouchTime) { + return; + } + } - if (hasNone || - (hasPanY && direction & DIRECTION_HORIZONTAL) || - (hasPanX && direction & DIRECTION_VERTICAL)) { - return this.preventSrc(srcEvent); - } - }, + if (hasPanX && hasPanY) { + // `pan-x pan-y` means browser handles all scrolling/panning, do not prevent + return; + } - /** - * call preventDefault to prevent the browser's default behavior (scrolling in most cases) - * @param {Object} srcEvent - */ - preventSrc: function(srcEvent) { - this.manager.session.prevented = true; - srcEvent.preventDefault(); + if (hasNone || + (hasPanY && direction & DIRECTION_HORIZONTAL) || + (hasPanX && direction & DIRECTION_VERTICAL)) { + return this.preventSrc(srcEvent); } + }, + + /** + * call preventDefault to prevent the browser's default behavior (scrolling in most cases) + * @param {Object} srcEvent + */ + preventSrc: function(srcEvent) { + this.manager.session.prevented = true; + srcEvent.preventDefault(); + } }; export { TouchAction }; diff --git a/src/utils/add-event-listeners.js b/src/utils/add-event-listeners.js index ec6e42462..187503c5e 100644 --- a/src/utils/add-event-listeners.js +++ b/src/utils/add-event-listeners.js @@ -7,7 +7,7 @@ import splitStr from './split-str'; * @param {Function} handler */ export default function addEventListeners(target, types, handler) { - each(splitStr(types), function(type) { - target.addEventListener(type, handler, false); - }); + each(splitStr(types), function(type) { + target.addEventListener(type, handler, false); + }); } diff --git a/src/utils/assign.js b/src/utils/assign.js index e4defa40e..99d7f29af 100644 --- a/src/utils/assign.js +++ b/src/utils/assign.js @@ -7,26 +7,26 @@ */ var assign; if (typeof Object.assign !== 'function') { - assign = function assign(target) { - if (target === undefined || target === null) { - throw new TypeError('Cannot convert undefined or null to object'); - } + assign = function assign(target) { + if (target === undefined || target === null) { + throw new TypeError('Cannot convert undefined or null to object'); + } - var output = Object(target); - for (var index = 1; index < arguments.length; index++) { - var source = arguments[index]; - if (source !== undefined && source !== null) { - for (var nextKey in source) { - if (source.hasOwnProperty(nextKey)) { - output[nextKey] = source[nextKey]; - } - } - } + var output = Object(target); + for (var index = 1; index < arguments.length; index++) { + var source = arguments[index]; + if (source !== undefined && source !== null) { + for (var nextKey in source) { + if (source.hasOwnProperty(nextKey)) { + output[nextKey] = source[nextKey]; + } } - return output; - }; + } + } + return output; + }; } else { - assign = Object.assign; + assign = Object.assign; } export default assign; diff --git a/src/utils/bind-fn.js b/src/utils/bind-fn.js index 58c453fd7..204da767a 100644 --- a/src/utils/bind-fn.js +++ b/src/utils/bind-fn.js @@ -5,7 +5,7 @@ * @returns {Function} */ export default function bindFn(fn, context) { - return function boundFn() { - return fn.apply(context, arguments); - }; + return function boundFn() { + return fn.apply(context, arguments); + }; } diff --git a/src/utils/bool-or-fn.js b/src/utils/bool-or-fn.js index e57c7ff84..e94bce957 100644 --- a/src/utils/bool-or-fn.js +++ b/src/utils/bool-or-fn.js @@ -7,8 +7,8 @@ import { TYPE_FUNCTION } from './utils-consts'; * @returns {Boolean} */ export default function boolOrFn(val, args) { - if (typeof val == TYPE_FUNCTION) { - return val.apply(args ? args[0] || undefined : undefined, args); - } - return val; + if (typeof val == TYPE_FUNCTION) { + return val.apply(args ? args[0] || undefined : undefined, args); + } + return val; } diff --git a/src/utils/deprecate.js b/src/utils/deprecate.js index 89ebae1e0..2be0c38dd 100644 --- a/src/utils/deprecate.js +++ b/src/utils/deprecate.js @@ -6,17 +6,17 @@ * @returns {Function} A new function wrapping the supplied method. */ export default function deprecate(method, name, message) { - var deprecationMessage = 'DEPRECATED METHOD: ' + name + '\n' + message + ' AT \n'; - return function() { - var e = new Error('get-stack-trace'); - var stack = e && e.stack ? e.stack.replace(/^[^\(]+?[\n$]/gm, '') - .replace(/^\s+at\s+/gm, '') - .replace(/^Object.\s*\(/gm, '{anonymous}()@') : 'Unknown Stack Trace'; + var deprecationMessage = 'DEPRECATED METHOD: ' + name + '\n' + message + ' AT \n'; + return function() { + var e = new Error('get-stack-trace'); + var stack = e && e.stack ? e.stack.replace(/^[^\(]+?[\n$]/gm, '') + .replace(/^\s+at\s+/gm, '') + .replace(/^Object.\s*\(/gm, '{anonymous}()@') : 'Unknown Stack Trace'; - var log = window.console && (window.console.warn || window.console.log); - if (log) { - log.call(window.console, deprecationMessage, stack); - } - return method.apply(this, arguments); - }; + var log = window.console && (window.console.warn || window.console.log); + if (log) { + log.call(window.console, deprecationMessage, stack); + } + return method.apply(this, arguments); + }; } diff --git a/src/utils/each.js b/src/utils/each.js index 60ea73a98..875d608eb 100644 --- a/src/utils/each.js +++ b/src/utils/each.js @@ -5,23 +5,23 @@ * @param {Object} context */ export default function each(obj, iterator, context) { - var i; + var i; - if (!obj) { - return; - } + if (!obj) { + return; + } - if (obj.forEach) { - obj.forEach(iterator, context); - } else if (obj.length !== undefined) { - i = 0; - while (i < obj.length) { - iterator.call(context, obj[i], i, obj); - i++; - } - } else { - for (i in obj) { - obj.hasOwnProperty(i) && iterator.call(context, obj[i], i, obj); - } + if (obj.forEach) { + obj.forEach(iterator, context); + } else if (obj.length !== undefined) { + i = 0; + while (i < obj.length) { + iterator.call(context, obj[i], i, obj); + i++; + } + } else { + for (i in obj) { + obj.hasOwnProperty(i) && iterator.call(context, obj[i], i, obj); } + } } diff --git a/src/utils/extend.js b/src/utils/extend.js index 8a6bc8db2..d4559b19c 100644 --- a/src/utils/extend.js +++ b/src/utils/extend.js @@ -8,15 +8,15 @@ import deprecate from './deprecate'; * @returns {Object} dest */ var extend = deprecate(function extend(dest, src, merge) { - var keys = Object.keys(src); - var i = 0; - while (i < keys.length) { - if (!merge || (merge && dest[keys[i]] === undefined)) { - dest[keys[i]] = src[keys[i]]; - } - i++; + var keys = Object.keys(src); + var i = 0; + while (i < keys.length) { + if (!merge || (merge && dest[keys[i]] === undefined)) { + dest[keys[i]] = src[keys[i]]; } - return dest; + i++; + } + return dest; }, 'extend', 'Use `assign`.'); export default extend; diff --git a/src/utils/get-window-for-element.js b/src/utils/get-window-for-element.js index a4a58919e..7b6a562ef 100644 --- a/src/utils/get-window-for-element.js +++ b/src/utils/get-window-for-element.js @@ -4,6 +4,6 @@ * @returns {DocumentView|Window} */ export default function getWindowForElement(element) { - var doc = element.ownerDocument || element; - return (doc.defaultView || doc.parentWindow || window); + var doc = element.ownerDocument || element; + return (doc.defaultView || doc.parentWindow || window); } diff --git a/src/utils/has-parent.js b/src/utils/has-parent.js index 09215994f..e2c2a163f 100644 --- a/src/utils/has-parent.js +++ b/src/utils/has-parent.js @@ -6,11 +6,11 @@ * @return {Boolean} found */ export default function hasParent(node, parent) { - while (node) { - if (node == parent) { - return true; - } - node = node.parentNode; + while (node) { + if (node == parent) { + return true; } - return false; + node = node.parentNode; + } + return false; } diff --git a/src/utils/if-undefined.js b/src/utils/if-undefined.js index 896f6257b..95837eb0f 100644 --- a/src/utils/if-undefined.js +++ b/src/utils/if-undefined.js @@ -5,5 +5,5 @@ * @returns {*} */ export default function ifUndefined(val1, val2) { - return (val1 === undefined) ? val2 : val1; + return (val1 === undefined) ? val2 : val1; } diff --git a/src/utils/in-array.js b/src/utils/in-array.js index 4186c9f65..1e19f2b4a 100644 --- a/src/utils/in-array.js +++ b/src/utils/in-array.js @@ -6,16 +6,16 @@ * @return {Boolean|Number} false when not found, or the index */ export default function inArray(src, find, findByKey) { - if (src.indexOf && !findByKey) { - return src.indexOf(find); - } else { - var i = 0; - while (i < src.length) { - if ((findByKey && src[i][findByKey] == find) || (!findByKey && src[i] === find)) { - return i; - } - i++; - } - return -1; + if (src.indexOf && !findByKey) { + return src.indexOf(find); + } else { + var i = 0; + while (i < src.length) { + if ((findByKey && src[i][findByKey] == find) || (!findByKey && src[i] === find)) { + return i; + } + i++; } + return -1; + } } diff --git a/src/utils/in-str.js b/src/utils/in-str.js index d81951089..eeea7134e 100644 --- a/src/utils/in-str.js +++ b/src/utils/in-str.js @@ -5,5 +5,5 @@ * @returns {Boolean} found */ export default function inStr(str, find) { - return str.indexOf(find) > -1; + return str.indexOf(find) > -1; } diff --git a/src/utils/inherit.js b/src/utils/inherit.js index c97ab5433..86a48db90 100644 --- a/src/utils/inherit.js +++ b/src/utils/inherit.js @@ -6,14 +6,14 @@ import assign from './assign'; * @param {Object} [properties] */ export default function inherit(child, base, properties) { - var baseP = base.prototype, - childP; + var baseP = base.prototype, + childP; - childP = child.prototype = Object.create(baseP); - childP.constructor = child; - childP._super = baseP; + childP = child.prototype = Object.create(baseP); + childP.constructor = child; + childP._super = baseP; - if (properties) { - assign(childP, properties); - } + if (properties) { + assign(childP, properties); + } } diff --git a/src/utils/invoke-array-arg.js b/src/utils/invoke-array-arg.js index c77fa396e..3ab56284e 100644 --- a/src/utils/invoke-array-arg.js +++ b/src/utils/invoke-array-arg.js @@ -9,9 +9,9 @@ import each from './each'; * @returns {Boolean} */ export default function invokeArrayArg(arg, fn, context) { - if (Array.isArray(arg)) { - each(arg, context[fn], context); - return true; - } - return false; + if (Array.isArray(arg)) { + each(arg, context[fn], context); + return true; + } + return false; } diff --git a/src/utils/merge.js b/src/utils/merge.js index 48939647b..dd19bd3d4 100644 --- a/src/utils/merge.js +++ b/src/utils/merge.js @@ -8,7 +8,7 @@ import extend from './extend'; * @returns {Object} dest */ var merge = deprecate(function merge(dest, src) { - return extend(dest, src, true); + return extend(dest, src, true); }, 'merge', 'Use `assign`.'); export default merge; diff --git a/src/utils/prefixed.js b/src/utils/prefixed.js index dc098617a..38ebbbb27 100644 --- a/src/utils/prefixed.js +++ b/src/utils/prefixed.js @@ -6,18 +6,18 @@ import { VENDOR_PREFIXES } from './utils-consts'; * @returns {String|Undefined} prefixed */ export default function prefixed(obj, property) { - var prefix, prop; - var camelProp = property[0].toUpperCase() + property.slice(1); + var prefix, prop; + var camelProp = property[0].toUpperCase() + property.slice(1); - var i = 0; - while (i < VENDOR_PREFIXES.length) { - prefix = VENDOR_PREFIXES[i]; - prop = (prefix) ? prefix + camelProp : property; + var i = 0; + while (i < VENDOR_PREFIXES.length) { + prefix = VENDOR_PREFIXES[i]; + prop = (prefix) ? prefix + camelProp : property; - if (prop in obj) { - return prop; - } - i++; + if (prop in obj) { + return prop; } - return undefined; + i++; + } + return undefined; } diff --git a/src/utils/remove-event-listeners.js b/src/utils/remove-event-listeners.js index 4cbeee958..15c7de56e 100644 --- a/src/utils/remove-event-listeners.js +++ b/src/utils/remove-event-listeners.js @@ -7,7 +7,7 @@ import splitStr from './split-str'; * @param {Function} handler */ export default function removeEventListeners(target, types, handler) { - each(splitStr(types), function(type) { - target.removeEventListener(type, handler, false); - }); + each(splitStr(types), function(type) { + target.removeEventListener(type, handler, false); + }); } diff --git a/src/utils/set-timeout-context.js b/src/utils/set-timeout-context.js index 4b1e7f84b..90279aa54 100644 --- a/src/utils/set-timeout-context.js +++ b/src/utils/set-timeout-context.js @@ -8,5 +8,5 @@ import bindFn from './bind-fn'; * @returns {number} */ export default function setTimeoutContext(fn, timeout, context) { - return setTimeout(bindFn(fn, context), timeout); + return setTimeout(bindFn(fn, context), timeout); } diff --git a/src/utils/split-str.js b/src/utils/split-str.js index 5175a9b44..7f73f6459 100644 --- a/src/utils/split-str.js +++ b/src/utils/split-str.js @@ -5,5 +5,5 @@ */ export default function splitStr(str) { - return str.trim().split(/\s+/g); + return str.trim().split(/\s+/g); } diff --git a/src/utils/to-array.js b/src/utils/to-array.js index b4ef3915f..8dad49f2a 100644 --- a/src/utils/to-array.js +++ b/src/utils/to-array.js @@ -4,5 +4,5 @@ * @returns {Array} */ export default function toArray(obj) { - return Array.prototype.slice.call(obj, 0); + return Array.prototype.slice.call(obj, 0); } diff --git a/src/utils/unique-array.js b/src/utils/unique-array.js index 254823edc..66f02fb6c 100644 --- a/src/utils/unique-array.js +++ b/src/utils/unique-array.js @@ -8,28 +8,28 @@ import inArray from './in-array'; * @returns {Array} [{id:1},{id:2}] */ export default function uniqueArray(src, key, sort) { - var results = []; - var values = []; - var i = 0; + var results = []; + var values = []; + var i = 0; - while (i < src.length) { - var val = key ? src[i][key] : src[i]; - if (inArray(values, val) < 0) { - results.push(src[i]); - } - values[i] = val; - i++; + while (i < src.length) { + var val = key ? src[i][key] : src[i]; + if (inArray(values, val) < 0) { + results.push(src[i]); } + values[i] = val; + i++; + } - if (sort) { - if (!key) { - results = results.sort(); - } else { - results = results.sort(function sortUniqueArray(a, b) { - return a[key] > b[key]; - }); - } + if (sort) { + if (!key) { + results = results.sort(); + } else { + results = results.sort(function sortUniqueArray(a, b) { + return a[key] > b[key]; + }); } + } - return results; + return results; } diff --git a/src/utils/unique-id.js b/src/utils/unique-id.js index 397f8338d..9bb1e61ff 100644 --- a/src/utils/unique-id.js +++ b/src/utils/unique-id.js @@ -4,5 +4,5 @@ */ var _uniqueId = 1; export default function uniqueId() { - return _uniqueId++; + return _uniqueId++; } From 709d55978c511e9d88332932da1adcc5c3a47696 Mon Sep 17 00:00:00 2001 From: Arjun Kathuria Date: Mon, 13 Jun 2016 16:32:57 +0530 Subject: [PATCH 34/61] style(disAllow Var): replaces all var with let or const --- package.json | 2 +- src/input/mouse.js | 8 +- src/input/pointerevent.js | 24 ++--- src/input/singletouch.js | 14 +-- src/input/touch.js | 22 ++--- src/input/touchmouse.js | 30 ++++--- src/inputjs/compute-delta-xy.js | 8 +- src/inputjs/compute-input-data.js | 18 ++-- src/inputjs/compute-interval-input-data.js | 15 ++-- src/inputjs/create-input-instance.js | 4 +- src/inputjs/get-angle.js | 4 +- src/inputjs/get-center.js | 6 +- src/inputjs/get-distance.js | 4 +- src/inputjs/input-constructor.js | 2 +- src/inputjs/input-consts.js | 46 +++++----- src/inputjs/input-handler.js | 8 +- src/inputjs/simple-clone-input-data.js | 6 +- src/main.js | 90 +++++++++---------- src/manager.js | 40 ++++----- .../get-recognizer-by-name-if-manager.js | 2 +- src/recognizerjs/recognizer-constructor.js | 14 +-- src/recognizerjs/recognizer-consts.js | 14 +-- src/recognizers/attribute.js | 10 +-- src/recognizers/pan.js | 18 ++-- src/recognizers/pinch.js | 2 +- src/recognizers/press.js | 8 +- src/recognizers/swipe.js | 6 +- src/recognizers/tap.js | 14 +-- src/touchactionjs/clean-touch-actions.js | 4 +- src/touchactionjs/get-touchaction-props.js | 4 +- src/touchactionjs/touchaction-Consts.js | 18 ++-- src/touchactionjs/touchaction-constructor.js | 20 ++--- src/utils/assign.js | 10 +-- src/utils/deprecate.js | 8 +- src/utils/each.js | 2 +- src/utils/extend.js | 6 +- src/utils/get-window-for-element.js | 2 +- src/utils/in-array.js | 2 +- src/utils/inherit.js | 4 +- src/utils/merge.js | 2 +- src/utils/prefixed.js | 7 +- src/utils/unique-array.js | 8 +- src/utils/unique-id.js | 2 +- src/utils/utils-consts.js | 12 +-- 44 files changed, 279 insertions(+), 271 deletions(-) diff --git a/package.json b/package.json index 89fb3828d..b11578c9a 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,7 @@ "devDependencies": { "babel-preset-es2015-rollup": "^1.1.1", "changelogplease": "^1.2.0", - "ember-suave": "^2.0.1", + "ember-suave": "3.0.0", "git-tags": "^0.2.4", "grunt": "0.4.x", "grunt-banner": "^0.2.3", diff --git a/src/input/mouse.js b/src/input/mouse.js index b2a6bd5f8..ac5355e9a 100644 --- a/src/input/mouse.js +++ b/src/input/mouse.js @@ -7,14 +7,14 @@ import { import { Input } from '../inputjs/input-constructor'; import inherit from '../utils/inherit'; -var MOUSE_INPUT_MAP = { +const MOUSE_INPUT_MAP = { mousedown: INPUT_START, mousemove: INPUT_MOVE, mouseup: INPUT_END }; -var MOUSE_ELEMENT_EVENTS = 'mousedown'; -var MOUSE_WINDOW_EVENTS = 'mousemove mouseup'; +const MOUSE_ELEMENT_EVENTS = 'mousedown'; +const MOUSE_WINDOW_EVENTS = 'mousemove mouseup'; /** * Mouse events input @@ -36,7 +36,7 @@ inherit(MouseInput, Input, { * @param {Object} ev */ handler: function MEhandler(ev) { - var eventType = MOUSE_INPUT_MAP[ev.type]; + let eventType = MOUSE_INPUT_MAP[ev.type]; // on start we want to have the left mouse button down if (eventType & INPUT_START && ev.button === 0) { diff --git a/src/input/pointerevent.js b/src/input/pointerevent.js index dcc51187f..1dccec61e 100644 --- a/src/input/pointerevent.js +++ b/src/input/pointerevent.js @@ -12,7 +12,7 @@ import { Input } from '../inputjs/input-constructor'; import inherit from '../utils/inherit'; import inArray from '../utils/in-array'; -var POINTER_INPUT_MAP = { +const POINTER_INPUT_MAP = { pointerdown: INPUT_START, pointermove: INPUT_MOVE, pointerup: INPUT_END, @@ -21,15 +21,15 @@ var POINTER_INPUT_MAP = { }; // in IE10 the pointer types is defined as an enum -var IE10_POINTER_TYPE_ENUM = { +const IE10_POINTER_TYPE_ENUM = { 2: INPUT_TYPE_TOUCH, 3: INPUT_TYPE_PEN, 4: INPUT_TYPE_MOUSE, 5: INPUT_TYPE_KINECT // see https://twitter.com/jacobrossi/status/480596438489890816 }; -var POINTER_ELEMENT_EVENTS = 'pointerdown'; -var POINTER_WINDOW_EVENTS = 'pointermove pointerup pointercancel'; +let POINTER_ELEMENT_EVENTS = 'pointerdown'; +let POINTER_WINDOW_EVENTS = 'pointermove pointerup pointercancel'; // IE10 has prefixed support, and case-sensitive if (window.MSPointerEvent && !window.PointerEvent) { @@ -57,17 +57,17 @@ inherit(PointerEventInput, Input, { * @param {Object} ev */ handler: function PEhandler(ev) { - var store = this.store; - var removePointer = false; + let store = this.store; + let removePointer = false; - var eventTypeNormalized = ev.type.toLowerCase().replace('ms', ''); - var eventType = POINTER_INPUT_MAP[eventTypeNormalized]; - var pointerType = IE10_POINTER_TYPE_ENUM[ev.pointerType] || ev.pointerType; + let eventTypeNormalized = ev.type.toLowerCase().replace('ms', ''); + let eventType = POINTER_INPUT_MAP[eventTypeNormalized]; + let pointerType = IE10_POINTER_TYPE_ENUM[ev.pointerType] || ev.pointerType; - var isTouch = (pointerType == INPUT_TYPE_TOUCH); + let isTouch = (pointerType == INPUT_TYPE_TOUCH); // get index of the event in the store - var storeIndex = inArray(store, ev.pointerId, 'pointerId'); + let storeIndex = inArray(store, ev.pointerId, 'pointerId'); // start and mouse must be down if (eventType & INPUT_START && (ev.button === 0 || isTouch)) { @@ -90,7 +90,7 @@ inherit(PointerEventInput, Input, { this.callback(this.manager, eventType, { pointers: store, changedPointers: [ev], - pointerType: pointerType, + pointerType, srcEvent: ev }); diff --git a/src/input/singletouch.js b/src/input/singletouch.js index c3896bd39..83cc164ae 100644 --- a/src/input/singletouch.js +++ b/src/input/singletouch.js @@ -10,15 +10,15 @@ import inherit from '../utils/inherit'; import toArray from '../utils/to-array'; import uniqueArray from '../utils/unique-array'; -var SINGLE_TOUCH_INPUT_MAP = { +const SINGLE_TOUCH_INPUT_MAP = { touchstart: INPUT_START, touchmove: INPUT_MOVE, touchend: INPUT_END, touchcancel: INPUT_CANCEL }; -var SINGLE_TOUCH_TARGET_EVENTS = 'touchstart'; -var SINGLE_TOUCH_WINDOW_EVENTS = 'touchstart touchmove touchend touchcancel'; +const SINGLE_TOUCH_TARGET_EVENTS = 'touchstart'; +const SINGLE_TOUCH_WINDOW_EVENTS = 'touchstart touchmove touchend touchcancel'; /** * Touch events input @@ -35,7 +35,7 @@ function SingleTouchInput() { inherit(SingleTouchInput, Input, { handler: function TEhandler(ev) { - var type = SINGLE_TOUCH_INPUT_MAP[ev.type]; + let type = SINGLE_TOUCH_INPUT_MAP[ev.type]; // should we handle the touch events? if (type === INPUT_START) { @@ -46,7 +46,7 @@ inherit(SingleTouchInput, Input, { return; } - var touches = normalizeSingleTouches.call(this, ev, type); + let touches = normalizeSingleTouches.call(this, ev, type); // when done, reset the started state if (type & (INPUT_END | INPUT_CANCEL) && touches[0].length - touches[1].length === 0) { @@ -69,8 +69,8 @@ inherit(SingleTouchInput, Input, { * @returns {undefined|Array} [all, changed] */ function normalizeSingleTouches(ev, type) { - var all = toArray(ev.touches); - var changed = toArray(ev.changedTouches); + let all = toArray(ev.touches); + let changed = toArray(ev.changedTouches); if (type & (INPUT_END | INPUT_CANCEL)) { all = uniqueArray(all.concat(changed), 'identifier', true); diff --git a/src/input/touch.js b/src/input/touch.js index c67f06777..88bddd620 100644 --- a/src/input/touch.js +++ b/src/input/touch.js @@ -11,14 +11,14 @@ import toArray from '../utils/to-array'; import hasParent from '../utils/has-parent'; import uniqueArray from '../utils/unique-array'; -var TOUCH_INPUT_MAP = { +const TOUCH_INPUT_MAP = { touchstart: INPUT_START, touchmove: INPUT_MOVE, touchend: INPUT_END, touchcancel: INPUT_CANCEL }; -var TOUCH_TARGET_EVENTS = 'touchstart touchmove touchend touchcancel'; +const TOUCH_TARGET_EVENTS = 'touchstart touchmove touchend touchcancel'; /** * Multi-user touch events input @@ -34,8 +34,8 @@ function TouchInput() { inherit(TouchInput, Input, { handler: function MTEhandler(ev) { - var type = TOUCH_INPUT_MAP[ev.type]; - var touches = getTouches.call(this, ev, type); + let type = TOUCH_INPUT_MAP[ev.type]; + let touches = getTouches.call(this, ev, type); if (!touches) { return; } @@ -56,8 +56,8 @@ inherit(TouchInput, Input, { * @returns {undefined|Array} [all, changed] */ function getTouches(ev, type) { - var allTouches = toArray(ev.touches); - var targetIds = this.targetIds; + let allTouches = toArray(ev.touches); + let targetIds = this.targetIds; // when there is only one touch, the process can be simplified if (type & (INPUT_START | INPUT_MOVE) && allTouches.length === 1) { @@ -65,11 +65,11 @@ function getTouches(ev, type) { return [allTouches, allTouches]; } - var i, - targetTouches, - changedTouches = toArray(ev.changedTouches), - changedTargetTouches = [], - target = this.target; + let i; + let targetTouches; + let changedTouches = toArray(ev.changedTouches); + let changedTargetTouches = []; + let target = this.target; // get target touches from touches targetTouches = allTouches.filter(function(touch) { diff --git a/src/input/touchmouse.js b/src/input/touchmouse.js index 39b988f8c..f0d0cec1c 100644 --- a/src/input/touchmouse.js +++ b/src/input/touchmouse.js @@ -21,13 +21,13 @@ import { * @extends Input */ -var DEDUP_TIMEOUT = 2500; -var DEDUP_DISTANCE = 25; +const DEDUP_TIMEOUT = 2500; +const DEDUP_DISTANCE = 25; function TouchMouseInput() { Input.apply(this, arguments); - var handler = bindFn(this.handler, this); + let handler = bindFn(this.handler, this); this.touch = new TouchInput(this.manager, handler); this.mouse = new MouseInput(this.manager, handler); @@ -43,8 +43,8 @@ inherit(TouchMouseInput, Input, { * @param {Object} inputData */ handler: function TMEhandler(manager, inputEvent, inputData) { - var isTouch = (inputData.pointerType == INPUT_TYPE_TOUCH), - isMouse = (inputData.pointerType == INPUT_TYPE_MOUSE); + let isTouch = (inputData.pointerType == INPUT_TYPE_TOUCH); + let isMouse = (inputData.pointerType == INPUT_TYPE_MOUSE); if (isMouse && inputData.sourceCapabilities && inputData.sourceCapabilities.firesTouchEvents) { return; @@ -79,14 +79,14 @@ function recordTouches(eventType, eventData) { } function setLastTouch(eventData) { - var touch = eventData.changedPointers[0]; + let touch = eventData.changedPointers[0]; if (touch.identifier === this.primaryTouch) { - var lastTouch = { x: touch.clientX, y: touch.clientY }; + let lastTouch = { x: touch.clientX, y: touch.clientY }; this.lastTouches.push(lastTouch); - var lts = this.lastTouches; - var removeLastTouch = function() { - var i = lts.indexOf(lastTouch); + let lts = this.lastTouches; + let removeLastTouch = function() { + let i = lts.indexOf(lastTouch); if (i > -1) { lts.splice(i, 1); } @@ -96,10 +96,12 @@ function setLastTouch(eventData) { } function isSyntheticEvent(eventData) { - var x = eventData.srcEvent.clientX, y = eventData.srcEvent.clientY; - for (var i = 0; i < this.lastTouches.length; i++) { - var t = this.lastTouches[i]; - var dx = Math.abs(x - t.x), dy = Math.abs(y - t.y); + let x = eventData.srcEvent.clientX; + let y = eventData.srcEvent.clientY; + for (let i = 0; i < this.lastTouches.length; i++) { + let t = this.lastTouches[i]; + let dx = Math.abs(x - t.x); + let dy = Math.abs(y - t.y); if (dx <= DEDUP_DISTANCE && dy <= DEDUP_DISTANCE) { return true; } diff --git a/src/inputjs/compute-delta-xy.js b/src/inputjs/compute-delta-xy.js index 96745e78f..f72d918e5 100644 --- a/src/inputjs/compute-delta-xy.js +++ b/src/inputjs/compute-delta-xy.js @@ -1,10 +1,10 @@ import { INPUT_START,INPUT_END } from './input-consts'; export default function computeDeltaXY(session, input) { - var center = input.center; - var offset = session.offsetDelta || {}; - var prevDelta = session.prevDelta || {}; - var prevInput = session.prevInput || {}; + let center = input.center; + let offset = session.offsetDelta || {}; + let prevDelta = session.prevDelta || {}; + let prevInput = session.prevInput || {}; if (input.eventType === INPUT_START || prevInput.eventType === INPUT_END) { prevDelta = session.prevDelta = { diff --git a/src/inputjs/compute-input-data.js b/src/inputjs/compute-input-data.js index 7bdc17c73..7f742cf23 100644 --- a/src/inputjs/compute-input-data.js +++ b/src/inputjs/compute-input-data.js @@ -18,9 +18,9 @@ import computeIntervalInputData from './compute-interval-input-data'; * @param {Object} input */ export default function computeInputData(manager, input) { - var session = manager.session; - var pointers = input.pointers; - var pointersLength = pointers.length; + let session = manager.session; + let pointers = input.pointers; + let pointersLength = pointers.length; // store the first input to calculate the distance and direction if (!session.firstInput) { @@ -34,11 +34,11 @@ export default function computeInputData(manager, input) { session.firstMultiple = false; } - var firstInput = session.firstInput; - var firstMultiple = session.firstMultiple; - var offsetCenter = firstMultiple ? firstMultiple.center : firstInput.center; + let firstInput = session.firstInput; + let firstMultiple = session.firstMultiple; + let offsetCenter = firstMultiple ? firstMultiple.center : firstInput.center; - var center = input.center = getCenter(pointers); + let center = input.center = getCenter(pointers); input.timeStamp = now(); input.deltaTime = input.timeStamp - firstInput.timeStamp; @@ -48,7 +48,7 @@ export default function computeInputData(manager, input) { computeDeltaXY(session, input); input.offsetDirection = getDirection(input.deltaX, input.deltaY); - var overallVelocity = getVelocity(input.deltaTime, input.deltaX, input.deltaY); + let overallVelocity = getVelocity(input.deltaTime, input.deltaX, input.deltaY); input.overallVelocityX = overallVelocity.x; input.overallVelocityY = overallVelocity.y; input.overallVelocity = (abs(overallVelocity.x) > abs(overallVelocity.y)) ? overallVelocity.x : overallVelocity.y; @@ -62,7 +62,7 @@ export default function computeInputData(manager, input) { computeIntervalInputData(session, input); // find the correct target - var target = manager.element; + let target = manager.element; if (hasParent(input.srcEvent.target, target)) { target = input.srcEvent.target; } diff --git a/src/inputjs/compute-interval-input-data.js b/src/inputjs/compute-interval-input-data.js index c060abb0e..fba4310df 100644 --- a/src/inputjs/compute-interval-input-data.js +++ b/src/inputjs/compute-interval-input-data.js @@ -9,15 +9,18 @@ import getDirection from './get-direction'; * @param {Object} input */ export default function computeIntervalInputData(session, input) { - var last = session.lastInterval || input, - deltaTime = input.timeStamp - last.timeStamp, - velocity, velocityX, velocityY, direction; + let last = session.lastInterval || input; + let deltaTime = input.timeStamp - last.timeStamp; + let velocity; + let velocityX; + let velocityY; + let direction; if (input.eventType != INPUT_CANCEL && (deltaTime > COMPUTE_INTERVAL || last.velocity === undefined)) { - var deltaX = input.deltaX - last.deltaX; - var deltaY = input.deltaY - last.deltaY; + let deltaX = input.deltaX - last.deltaX; + let deltaY = input.deltaY - last.deltaY; - var v = getVelocity(deltaTime, deltaX, deltaY); + let v = getVelocity(deltaTime, deltaX, deltaY); velocityX = v.x; velocityY = v.y; velocity = (abs(v.x) > abs(v.y)) ? v.x : v.y; diff --git a/src/inputjs/create-input-instance.js b/src/inputjs/create-input-instance.js index c7f3677eb..721b67f09 100644 --- a/src/inputjs/create-input-instance.js +++ b/src/inputjs/create-input-instance.js @@ -12,8 +12,8 @@ import { TouchMouseInput } from '../input/touchmouse'; * @returns {Input} */ export default function createInputInstance(manager) { - var Type; - var inputClass = manager.options.inputClass; + let Type; + let inputClass = manager.options.inputClass; if (inputClass) { Type = inputClass; diff --git a/src/inputjs/get-angle.js b/src/inputjs/get-angle.js index 27a8449ae..041e86efa 100644 --- a/src/inputjs/get-angle.js +++ b/src/inputjs/get-angle.js @@ -11,7 +11,7 @@ export default function getAngle(p1, p2, props) { if (!props) { props = PROPS_XY; } - var x = p2[props[0]] - p1[props[0]], - y = p2[props[1]] - p1[props[1]]; + let x = p2[props[0]] - p1[props[0]]; + let y = p2[props[1]] - p1[props[1]]; return Math.atan2(y, x) * 180 / Math.PI; } diff --git a/src/inputjs/get-center.js b/src/inputjs/get-center.js index 806b45938..4fee78fc3 100644 --- a/src/inputjs/get-center.js +++ b/src/inputjs/get-center.js @@ -6,7 +6,7 @@ import { round } from '../utils/utils-consts'; * @return {Object} center contains `x` and `y` properties */ export default function getCenter(pointers) { - var pointersLength = pointers.length; + let pointersLength = pointers.length; // no need to loop when only one touch if (pointersLength === 1) { @@ -16,7 +16,9 @@ export default function getCenter(pointers) { }; } - var x = 0, y = 0, i = 0; + let x = 0; + let y = 0; + let i = 0; while (i < pointersLength) { x += pointers[i].clientX; y += pointers[i].clientY; diff --git a/src/inputjs/get-distance.js b/src/inputjs/get-distance.js index acb69c595..adaea53e8 100644 --- a/src/inputjs/get-distance.js +++ b/src/inputjs/get-distance.js @@ -11,8 +11,8 @@ export default function getDistance(p1, p2, props) { if (!props) { props = PROPS_XY; } - var x = p2[props[0]] - p1[props[0]], - y = p2[props[1]] - p1[props[1]]; + let x = p2[props[0]] - p1[props[0]]; + let y = p2[props[1]] - p1[props[1]]; return Math.sqrt((x * x) + (y * y)); } diff --git a/src/inputjs/input-constructor.js b/src/inputjs/input-constructor.js index b0dd1b335..9c518f9b5 100644 --- a/src/inputjs/input-constructor.js +++ b/src/inputjs/input-constructor.js @@ -11,7 +11,7 @@ import getWindowForElement from '../utils/get-window-for-element'; * @constructor */ function Input(manager, callback) { - var self = this; + let self = this; this.manager = manager; this.callback = callback; this.element = manager.element; diff --git a/src/inputjs/input-consts.js b/src/inputjs/input-consts.js index 1fce6dcf2..69c3bfbee 100644 --- a/src/inputjs/input-consts.js +++ b/src/inputjs/input-consts.js @@ -1,35 +1,35 @@ import prefixed from '../utils/prefixed'; -var MOBILE_REGEX = /mobile|tablet|ip(ad|hone|od)|android/i; +const MOBILE_REGEX = /mobile|tablet|ip(ad|hone|od)|android/i; -var SUPPORT_TOUCH = ('ontouchstart' in window); -var SUPPORT_POINTER_EVENTS = prefixed(window, 'PointerEvent') !== undefined; -var SUPPORT_ONLY_TOUCH = SUPPORT_TOUCH && MOBILE_REGEX.test(navigator.userAgent); +const SUPPORT_TOUCH = ('ontouchstart' in window); +const SUPPORT_POINTER_EVENTS = prefixed(window, 'PointerEvent') !== undefined; +const SUPPORT_ONLY_TOUCH = SUPPORT_TOUCH && MOBILE_REGEX.test(navigator.userAgent); -var INPUT_TYPE_TOUCH = 'touch'; -var INPUT_TYPE_PEN = 'pen'; -var INPUT_TYPE_MOUSE = 'mouse'; -var INPUT_TYPE_KINECT = 'kinect'; +const INPUT_TYPE_TOUCH = 'touch'; +const INPUT_TYPE_PEN = 'pen'; +const INPUT_TYPE_MOUSE = 'mouse'; +const INPUT_TYPE_KINECT = 'kinect'; -var COMPUTE_INTERVAL = 25; +const COMPUTE_INTERVAL = 25; -var INPUT_START = 1; -var INPUT_MOVE = 2; -var INPUT_END = 4; -var INPUT_CANCEL = 8; +const INPUT_START = 1; +const INPUT_MOVE = 2; +const INPUT_END = 4; +const INPUT_CANCEL = 8; -var DIRECTION_NONE = 1; -var DIRECTION_LEFT = 2; -var DIRECTION_RIGHT = 4; -var DIRECTION_UP = 8; -var DIRECTION_DOWN = 16; +const DIRECTION_NONE = 1; +const DIRECTION_LEFT = 2; +const DIRECTION_RIGHT = 4; +const DIRECTION_UP = 8; +const DIRECTION_DOWN = 16; -var DIRECTION_HORIZONTAL = DIRECTION_LEFT | DIRECTION_RIGHT; -var DIRECTION_VERTICAL = DIRECTION_UP | DIRECTION_DOWN; -var DIRECTION_ALL = DIRECTION_HORIZONTAL | DIRECTION_VERTICAL; +const DIRECTION_HORIZONTAL = DIRECTION_LEFT | DIRECTION_RIGHT; +const DIRECTION_VERTICAL = DIRECTION_UP | DIRECTION_DOWN; +const DIRECTION_ALL = DIRECTION_HORIZONTAL | DIRECTION_VERTICAL; -var PROPS_XY = ['x', 'y']; -var PROPS_CLIENT_XY = ['clientX', 'clientY']; +const PROPS_XY = ['x', 'y']; +const PROPS_CLIENT_XY = ['clientX', 'clientY']; export { MOBILE_REGEX, diff --git a/src/inputjs/input-handler.js b/src/inputjs/input-handler.js index ae3a162c6..0ce8a131b 100644 --- a/src/inputjs/input-handler.js +++ b/src/inputjs/input-handler.js @@ -8,10 +8,10 @@ import computeInputData from './compute-input-data'; * @param {Object} input */ export default function inputHandler(manager, eventType, input) { - var pointersLen = input.pointers.length; - var changedPointersLen = input.changedPointers.length; - var isFirst = (eventType & INPUT_START && (pointersLen - changedPointersLen === 0)); - var isFinal = (eventType & (INPUT_END | INPUT_CANCEL) && (pointersLen - changedPointersLen === 0)); + let pointersLen = input.pointers.length; + let changedPointersLen = input.changedPointers.length; + let isFirst = (eventType & INPUT_START && (pointersLen - changedPointersLen === 0)); + let isFinal = (eventType & (INPUT_END | INPUT_CANCEL) && (pointersLen - changedPointersLen === 0)); input.isFirst = !!isFirst; input.isFinal = !!isFinal; diff --git a/src/inputjs/simple-clone-input-data.js b/src/inputjs/simple-clone-input-data.js index c2aad2b30..324d914bb 100644 --- a/src/inputjs/simple-clone-input-data.js +++ b/src/inputjs/simple-clone-input-data.js @@ -9,8 +9,8 @@ import getCenter from './get-center'; export default function simpleCloneInputData(input) { // make a simple copy of the pointers because we will get a reference if we don't // we only need clientXY for the calculations - var pointers = []; - var i = 0; + let pointers = []; + let i = 0; while (i < input.pointers.length) { pointers[i] = { clientX: round(input.pointers[i].clientX), @@ -21,7 +21,7 @@ export default function simpleCloneInputData(input) { return { timeStamp: now(), - pointers: pointers, + pointers, center: getCenter(pointers), deltaX: input.deltaX, deltaY: input.deltaY diff --git a/src/main.js b/src/main.js index 7d2dea843..1ac036d7c 100644 --- a/src/main.js +++ b/src/main.js @@ -63,40 +63,40 @@ import hasParent from'./utils/has-parent'; // style loader but by script tag, not by the loader. assign(Hammer, { - INPUT_START: INPUT_START, - INPUT_MOVE: INPUT_MOVE, - INPUT_END: INPUT_END, - INPUT_CANCEL: INPUT_CANCEL, + INPUT_START, + INPUT_MOVE, + INPUT_END, + INPUT_CANCEL, - STATE_POSSIBLE: STATE_POSSIBLE, - STATE_BEGAN: STATE_BEGAN, - STATE_CHANGED: STATE_CHANGED, - STATE_ENDED: STATE_ENDED, - STATE_RECOGNIZED: STATE_RECOGNIZED, - STATE_CANCELLED: STATE_CANCELLED, - STATE_FAILED: STATE_FAILED, + STATE_POSSIBLE, + STATE_BEGAN, + STATE_CHANGED, + STATE_ENDED, + STATE_RECOGNIZED, + STATE_CANCELLED, + STATE_FAILED, - DIRECTION_NONE: DIRECTION_NONE, - DIRECTION_LEFT: DIRECTION_LEFT, - DIRECTION_RIGHT: DIRECTION_RIGHT, - DIRECTION_UP: DIRECTION_UP, - DIRECTION_DOWN: DIRECTION_DOWN, - DIRECTION_HORIZONTAL: DIRECTION_HORIZONTAL, - DIRECTION_VERTICAL: DIRECTION_VERTICAL, - DIRECTION_ALL: DIRECTION_ALL, + DIRECTION_NONE, + DIRECTION_LEFT, + DIRECTION_RIGHT, + DIRECTION_UP, + DIRECTION_DOWN, + DIRECTION_HORIZONTAL, + DIRECTION_VERTICAL, + DIRECTION_ALL, - Manager: Manager, - Input: Input, - TouchAction: TouchAction, + Manager, + Input, + TouchAction, - TouchInput: TouchInput, - MouseInput: MouseInput, - PointerEventInput: PointerEventInput, - TouchMouseInput: TouchMouseInput, - SingleTouchInput: SingleTouchInput, + TouchInput, + MouseInput, + PointerEventInput, + TouchMouseInput, + SingleTouchInput, - Recognizer: Recognizer, - AttrRecognizer: AttrRecognizer, + Recognizer, + AttrRecognizer, Tap: TapRecognizer, Pan: PanRecognizer, Swipe: SwipeRecognizer, @@ -106,24 +106,24 @@ assign(Hammer, { on: addEventListeners, off: removeEventListeners, - each: each, - merge: merge, - extend: extend, - assign: assign, - inherit: inherit, - bindFn: bindFn, - prefixed: prefixed, - toArray: toArray, - inArray: inArray, - uniqueArray: uniqueArray, - splitStr: splitStr, - boolOrFn: boolOrFn, - hasParent: hasParent, - addEventListeners: addEventListeners, - removeEventListeners: removeEventListeners + each, + merge, + extend, + assign, + inherit, + bindFn, + prefixed, + toArray, + inArray, + uniqueArray, + splitStr, + boolOrFn, + hasParent, + addEventListeners, + removeEventListeners }); -var freeGlobal = (typeof window !== 'undefined' ? window : (typeof self !== 'undefined' ? self : {})); // jshint ignore:line +let freeGlobal = (typeof window !== 'undefined' ? window : (typeof self !== 'undefined' ? self : {})); // jshint ignore:line freeGlobal.Hammer = Hammer; if (typeof define === 'function' && define.amd) { diff --git a/src/manager.js b/src/manager.js index 7b98bada3..e16ca7508 100644 --- a/src/manager.js +++ b/src/manager.js @@ -15,8 +15,8 @@ import { STATE_RECOGNIZED } from './recognizerjs/recognizer-consts'; -var STOP = 1; -var FORCED_STOP = 2; +const STOP = 1; +const FORCED_STOP = 2; /** * Manager @@ -41,7 +41,7 @@ function Manager(element, options) { toggleCssProps(this, true); each(this.options.recognizers, function(item) { - var recognizer = this.add(new (item[0])(item[1])); + let recognizer = this.add(new (item[0])(item[1])); item[2] && recognizer.recognizeWith(item[2]); item[3] && recognizer.requireFailure(item[3]); }, this); @@ -86,7 +86,7 @@ Manager.prototype = { * @param {Object} inputData */ recognize: function(inputData) { - var session = this.session; + let session = this.session; if (session.stopped) { return; } @@ -94,13 +94,13 @@ Manager.prototype = { // run the touch-action polyfill this.touchAction.preventDefaults(inputData); - var recognizer; - var recognizers = this.recognizers; + let recognizer; + let recognizers = this.recognizers; // this holds the recognizer that is being recognized. // so the recognizer's state needs to be BEGAN, CHANGED, ENDED or RECOGNIZED // if no recognizer is detecting a thing, it is set to `null` - var curRecognizer = session.curRecognizer; + let curRecognizer = session.curRecognizer; // reset when the last recognizer is recognized // or when we're in a new session @@ -108,7 +108,7 @@ Manager.prototype = { curRecognizer = session.curRecognizer = null; } - var i = 0; + let i = 0; while (i < recognizers.length) { recognizer = recognizers[i]; @@ -145,8 +145,8 @@ Manager.prototype = { return recognizer; } - var recognizers = this.recognizers; - for (var i = 0; i < recognizers.length; i++) { + let recognizers = this.recognizers; + for (let i = 0; i < recognizers.length; i++) { if (recognizers[i].options.event == recognizer) { return recognizers[i]; } @@ -166,7 +166,7 @@ Manager.prototype = { } // remove existing - var existing = this.get(recognizer.options.event); + let existing = this.get(recognizer.options.event); if (existing) { this.remove(existing); } @@ -192,8 +192,8 @@ Manager.prototype = { // let's make sure this recognizer exists if (recognizer) { - var recognizers = this.recognizers; - var index = inArray(recognizers, recognizer); + let recognizers = this.recognizers; + let index = inArray(recognizers, recognizer); if (index !== -1) { recognizers.splice(index, 1); @@ -218,7 +218,7 @@ Manager.prototype = { return; } - var handlers = this.handlers; + let handlers = this.handlers; each(splitStr(events), function(event) { handlers[event] = handlers[event] || []; handlers[event].push(handler); @@ -237,7 +237,7 @@ Manager.prototype = { return; } - var handlers = this.handlers; + let handlers = this.handlers; each(splitStr(events), function(event) { if (!handler) { delete handlers[event]; @@ -260,7 +260,7 @@ Manager.prototype = { } // no handlers, so skip it all - var handlers = this.handlers[event] && this.handlers[event].slice(); + let handlers = this.handlers[event] && this.handlers[event].slice(); if (!handlers || !handlers.length) { return; } @@ -270,7 +270,7 @@ Manager.prototype = { data.srcEvent.preventDefault(); }; - var i = 0; + let i = 0; while (i < handlers.length) { handlers[i](data); i++; @@ -297,11 +297,11 @@ Manager.prototype = { * @param {Boolean} add */ function toggleCssProps(manager, add) { - var element = manager.element; + let element = manager.element; if (!element.style) { return; } - var prop; + let prop; each(manager.options.cssProps, function(value, name) { prop = prefixed(element.style, name); if (add) { @@ -322,7 +322,7 @@ function toggleCssProps(manager, add) { * @param {Object} data */ function triggerDomEvent(event, data) { - var gestureEvent = document.createEvent('Event'); + let gestureEvent = document.createEvent('Event'); gestureEvent.initEvent(event, true, true); gestureEvent.gesture = data; data.target.dispatchEvent(gestureEvent); diff --git a/src/recognizerjs/get-recognizer-by-name-if-manager.js b/src/recognizerjs/get-recognizer-by-name-if-manager.js index 02de27bd3..0f43a4648 100644 --- a/src/recognizerjs/get-recognizer-by-name-if-manager.js +++ b/src/recognizerjs/get-recognizer-by-name-if-manager.js @@ -5,7 +5,7 @@ * @returns {Recognizer} */ export default function getRecognizerByNameIfManager(otherRecognizer, recognizer) { - var manager = recognizer.manager; + let manager = recognizer.manager; if (manager) { return manager.get(otherRecognizer); } diff --git a/src/recognizerjs/recognizer-constructor.js b/src/recognizerjs/recognizer-constructor.js index 18eefbf80..9a4575789 100644 --- a/src/recognizerjs/recognizer-constructor.js +++ b/src/recognizerjs/recognizer-constructor.js @@ -96,7 +96,7 @@ Recognizer.prototype = { return this; } - var simultaneous = this.simultaneous; + let simultaneous = this.simultaneous; otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this); if (!simultaneous[otherRecognizer.id]) { simultaneous[otherRecognizer.id] = otherRecognizer; @@ -130,7 +130,7 @@ Recognizer.prototype = { return this; } - var requireFail = this.requireFail; + let requireFail = this.requireFail; otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this); if (inArray(requireFail, otherRecognizer) === -1) { requireFail.push(otherRecognizer); @@ -150,7 +150,7 @@ Recognizer.prototype = { } otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this); - var index = inArray(this.requireFail, otherRecognizer); + let index = inArray(this.requireFail, otherRecognizer); if (index > -1) { this.requireFail.splice(index, 1); } @@ -180,8 +180,8 @@ Recognizer.prototype = { * @param {Object} input */ emit: function(input) { - var self = this; - var state = this.state; + let self = this; + let state = this.state; function emit(event) { self.manager.emit(event, input); @@ -223,7 +223,7 @@ Recognizer.prototype = { * @returns {boolean} */ canEmit: function() { - var i = 0; + let i = 0; while (i < this.requireFail.length) { if (!(this.requireFail[i].state & (STATE_FAILED | STATE_POSSIBLE))) { return false; @@ -240,7 +240,7 @@ Recognizer.prototype = { recognize: function(inputData) { // make a new copy of the inputData // so we can change the inputData without messing up the other recognizers - var inputDataClone = assign({}, inputData); + let inputDataClone = assign({}, inputData); // is is enabled and allow recognizing? if (!boolOrFn(this.options.enable, [this, inputDataClone])) { diff --git a/src/recognizerjs/recognizer-consts.js b/src/recognizerjs/recognizer-consts.js index 195002e06..7b1aa340c 100644 --- a/src/recognizerjs/recognizer-consts.js +++ b/src/recognizerjs/recognizer-consts.js @@ -1,10 +1,10 @@ -var STATE_POSSIBLE = 1; -var STATE_BEGAN = 2; -var STATE_CHANGED = 4; -var STATE_ENDED = 8; -var STATE_RECOGNIZED = STATE_ENDED; -var STATE_CANCELLED = 16; -var STATE_FAILED = 32; +const STATE_POSSIBLE = 1; +const STATE_BEGAN = 2; +const STATE_CHANGED = 4; +const STATE_ENDED = 8; +const STATE_RECOGNIZED = STATE_ENDED; +const STATE_CANCELLED = 16; +const STATE_FAILED = 32; export { STATE_POSSIBLE, diff --git a/src/recognizers/attribute.js b/src/recognizers/attribute.js index a1878b870..253a18d6e 100644 --- a/src/recognizers/attribute.js +++ b/src/recognizers/attribute.js @@ -41,7 +41,7 @@ inherit(AttrRecognizer, Recognizer, { * @returns {Boolean} recognized */ attrTest: function(input) { - var optionPointers = this.options.pointers; + let optionPointers = this.options.pointers; return optionPointers === 0 || input.pointers.length === optionPointers; }, @@ -52,11 +52,11 @@ inherit(AttrRecognizer, Recognizer, { * @returns {*} State */ process: function(input) { - var state = this.state; - var eventType = input.eventType; + let state = this.state; + let eventType = input.eventType; - var isRecognized = state & (STATE_BEGAN | STATE_CHANGED); - var isValid = this.attrTest(input); + let isRecognized = state & (STATE_BEGAN | STATE_CHANGED); + let isValid = this.attrTest(input); // on cancel input and we've recognized before, return STATE_CANCELLED if (isRecognized && (eventType & INPUT_CANCEL || !isValid)) { diff --git a/src/recognizers/pan.js b/src/recognizers/pan.js index 12134583a..69cdb9305 100644 --- a/src/recognizers/pan.js +++ b/src/recognizers/pan.js @@ -40,8 +40,8 @@ inherit(PanRecognizer, AttrRecognizer, { }, getTouchAction: function() { - var direction = this.options.direction; - var actions = []; + let direction = this.options.direction; + let actions = []; if (direction & DIRECTION_HORIZONTAL) { actions.push(TOUCH_ACTION_PAN_Y); } @@ -52,12 +52,12 @@ inherit(PanRecognizer, AttrRecognizer, { }, directionTest: function(input) { - var options = this.options; - var hasMoved = true; - var distance = input.distance; - var direction = input.direction; - var x = input.deltaX; - var y = input.deltaY; + let options = this.options; + let hasMoved = true; + let distance = input.distance; + let direction = input.direction; + let x = input.deltaX; + let y = input.deltaY; // lock to axis? if (!(direction & options.direction)) { @@ -85,7 +85,7 @@ inherit(PanRecognizer, AttrRecognizer, { this.pX = input.deltaX; this.pY = input.deltaY; - var direction = directionStr(input.direction); + let direction = directionStr(input.direction); if (direction) { input.additionalEvent = this.options.event + direction; diff --git a/src/recognizers/pinch.js b/src/recognizers/pinch.js index 931f593fd..8b4b05675 100644 --- a/src/recognizers/pinch.js +++ b/src/recognizers/pinch.js @@ -35,7 +35,7 @@ inherit(PinchRecognizer, AttrRecognizer, { emit: function(input) { if (input.scale !== 1) { - var inOut = input.scale < 1 ? 'in' : 'out'; + let inOut = input.scale < 1 ? 'in' : 'out'; input.additionalEvent = this.options.event + inOut; } this._super.emit.call(this, input); diff --git a/src/recognizers/press.js b/src/recognizers/press.js index 3fa32dfec..6a9e01207 100644 --- a/src/recognizers/press.js +++ b/src/recognizers/press.js @@ -43,10 +43,10 @@ inherit(PressRecognizer, Recognizer, { }, process: function(input) { - var options = this.options; - var validPointers = input.pointers.length === options.pointers; - var validMovement = input.distance < options.threshold; - var validTime = input.deltaTime > options.time; + let options = this.options; + let validPointers = input.pointers.length === options.pointers; + let validMovement = input.distance < options.threshold; + let validTime = input.deltaTime > options.time; this._input = input; diff --git a/src/recognizers/swipe.js b/src/recognizers/swipe.js index caea8f218..1df2c8267 100644 --- a/src/recognizers/swipe.js +++ b/src/recognizers/swipe.js @@ -34,8 +34,8 @@ inherit(SwipeRecognizer, AttrRecognizer, { }, attrTest: function(input) { - var direction = this.options.direction; - var velocity; + let direction = this.options.direction; + let velocity; if (direction & (DIRECTION_HORIZONTAL | DIRECTION_VERTICAL)) { velocity = input.overallVelocity; @@ -53,7 +53,7 @@ inherit(SwipeRecognizer, AttrRecognizer, { }, emit: function(input) { - var direction = directionStr(input.offsetDirection); + let direction = directionStr(input.offsetDirection); if (direction) { this.manager.emit(this.options.event + direction, input); } diff --git a/src/recognizers/tap.js b/src/recognizers/tap.js index cdef1bd57..c50a1bf95 100644 --- a/src/recognizers/tap.js +++ b/src/recognizers/tap.js @@ -53,11 +53,11 @@ inherit(TapRecognizer, Recognizer, { }, process: function(input) { - var options = this.options; + let options = this.options; - var validPointers = input.pointers.length === options.pointers; - var validMovement = input.distance < options.threshold; - var validTouchTime = input.deltaTime < options.time; + let validPointers = input.pointers.length === options.pointers; + let validMovement = input.distance < options.threshold; + let validTouchTime = input.deltaTime < options.time; this.reset(); @@ -72,8 +72,8 @@ inherit(TapRecognizer, Recognizer, { return this.failTimeout(); } - var validInterval = this.pTime ? (input.timeStamp - this.pTime < options.interval) : true; - var validMultiTap = !this.pCenter || getDistance(this.pCenter, input.center) < options.posThreshold; + let validInterval = this.pTime ? (input.timeStamp - this.pTime < options.interval) : true; + let validMultiTap = !this.pCenter || getDistance(this.pCenter, input.center) < options.posThreshold; this.pTime = input.timeStamp; this.pCenter = input.center; @@ -88,7 +88,7 @@ inherit(TapRecognizer, Recognizer, { // if tap count matches we have recognized it, // else it has began recognizing... - var tapCount = this.count % options.taps; + let tapCount = this.count % options.taps; if (tapCount === 0) { // no failing requirements, immediately trigger the tap event // or wait as long as the multitap interval to trigger diff --git a/src/touchactionjs/clean-touch-actions.js b/src/touchactionjs/clean-touch-actions.js index 80fea930d..a10e0563f 100644 --- a/src/touchactionjs/clean-touch-actions.js +++ b/src/touchactionjs/clean-touch-actions.js @@ -18,8 +18,8 @@ export default function cleanTouchActions(actions) { return TOUCH_ACTION_NONE; } - var hasPanX = inStr(actions, TOUCH_ACTION_PAN_X); - var hasPanY = inStr(actions, TOUCH_ACTION_PAN_Y); + let hasPanX = inStr(actions, TOUCH_ACTION_PAN_X); + let hasPanY = inStr(actions, TOUCH_ACTION_PAN_Y); // if both pan-x and pan-y are set (different recognizers // for different directions, e.g. horizontal pan but vertical swipe?) diff --git a/src/touchactionjs/get-touchaction-props.js b/src/touchactionjs/get-touchaction-props.js index e9cb16462..3b695fd69 100644 --- a/src/touchactionjs/get-touchaction-props.js +++ b/src/touchactionjs/get-touchaction-props.js @@ -4,8 +4,8 @@ export default function getTouchActionProps() { if (!NATIVE_TOUCH_ACTION) { return false; } - var touchMap = {}; - var cssSupports = window.CSS && window.CSS.supports; + let touchMap = {}; + let cssSupports = window.CSS && window.CSS.supports; ['auto', 'manipulation', 'pan-y', 'pan-x', 'pan-x pan-y', 'none'].forEach(function(val) { // If css.supports is not supported but there is native touch-action assume it supports diff --git a/src/touchactionjs/touchaction-Consts.js b/src/touchactionjs/touchaction-Consts.js index b7ab89433..2259e321a 100644 --- a/src/touchactionjs/touchaction-Consts.js +++ b/src/touchactionjs/touchaction-Consts.js @@ -2,17 +2,17 @@ import prefixed from '../utils/prefixed'; import { TEST_ELEMENT } from '../utils/utils-consts'; import getTouchActionProps from './get-touchaction-props'; -var PREFIXED_TOUCH_ACTION = prefixed(TEST_ELEMENT.style, 'touchAction'); -var NATIVE_TOUCH_ACTION = PREFIXED_TOUCH_ACTION !== undefined; +const PREFIXED_TOUCH_ACTION = prefixed(TEST_ELEMENT.style, 'touchAction'); +const NATIVE_TOUCH_ACTION = PREFIXED_TOUCH_ACTION !== undefined; // magical touchAction value -var TOUCH_ACTION_COMPUTE = 'compute'; -var TOUCH_ACTION_AUTO = 'auto'; -var TOUCH_ACTION_MANIPULATION = 'manipulation'; // not implemented -var TOUCH_ACTION_NONE = 'none'; -var TOUCH_ACTION_PAN_X = 'pan-x'; -var TOUCH_ACTION_PAN_Y = 'pan-y'; -var TOUCH_ACTION_MAP = getTouchActionProps(); +const TOUCH_ACTION_COMPUTE = 'compute'; +const TOUCH_ACTION_AUTO = 'auto'; +const TOUCH_ACTION_MANIPULATION = 'manipulation'; // not implemented +const TOUCH_ACTION_NONE = 'none'; +const TOUCH_ACTION_PAN_X = 'pan-x'; +const TOUCH_ACTION_PAN_Y = 'pan-y'; +const TOUCH_ACTION_MAP = getTouchActionProps(); export { PREFIXED_TOUCH_ACTION, diff --git a/src/touchactionjs/touchaction-constructor.js b/src/touchactionjs/touchaction-constructor.js index af7202331..7d1560a4f 100644 --- a/src/touchactionjs/touchaction-constructor.js +++ b/src/touchactionjs/touchaction-constructor.js @@ -57,7 +57,7 @@ TouchAction.prototype = { * @returns {String} value */ compute: function() { - var actions = []; + let actions = []; each(this.manager.recognizers, function(recognizer) { if (boolOrFn(recognizer.options.enable, [recognizer])) { actions = actions.concat(recognizer.getTouchAction()); @@ -71,8 +71,8 @@ TouchAction.prototype = { * @param {Object} input */ preventDefaults: function(input) { - var srcEvent = input.srcEvent; - var direction = input.offsetDirection; + let srcEvent = input.srcEvent; + let direction = input.offsetDirection; // if the touch action did prevented once this session if (this.manager.session.prevented) { @@ -80,17 +80,17 @@ TouchAction.prototype = { return; } - var actions = this.actions; - var hasNone = inStr(actions, TOUCH_ACTION_NONE) && !TOUCH_ACTION_MAP[TOUCH_ACTION_NONE]; - var hasPanY = inStr(actions, TOUCH_ACTION_PAN_Y) && !TOUCH_ACTION_MAP[TOUCH_ACTION_PAN_Y]; - var hasPanX = inStr(actions, TOUCH_ACTION_PAN_X) && !TOUCH_ACTION_MAP[TOUCH_ACTION_PAN_X]; + let actions = this.actions; + let hasNone = inStr(actions, TOUCH_ACTION_NONE) && !TOUCH_ACTION_MAP[TOUCH_ACTION_NONE]; + let hasPanY = inStr(actions, TOUCH_ACTION_PAN_Y) && !TOUCH_ACTION_MAP[TOUCH_ACTION_PAN_Y]; + let hasPanX = inStr(actions, TOUCH_ACTION_PAN_X) && !TOUCH_ACTION_MAP[TOUCH_ACTION_PAN_X]; if (hasNone) { //do not prevent defaults if this is a tap gesture - var isTapPointer = input.pointers.length === 1; - var isTapMovement = input.distance < 2; - var isTapTouchTime = input.deltaTime < 250; + let isTapPointer = input.pointers.length === 1; + let isTapMovement = input.distance < 2; + let isTapTouchTime = input.deltaTime < 250; if (isTapPointer && isTapMovement && isTapTouchTime) { return; diff --git a/src/utils/assign.js b/src/utils/assign.js index 99d7f29af..aea814595 100644 --- a/src/utils/assign.js +++ b/src/utils/assign.js @@ -5,18 +5,18 @@ * @param {...Object} objects_to_assign * @returns {Object} target */ -var assign; +let assign; if (typeof Object.assign !== 'function') { assign = function assign(target) { if (target === undefined || target === null) { throw new TypeError('Cannot convert undefined or null to object'); } - var output = Object(target); - for (var index = 1; index < arguments.length; index++) { - var source = arguments[index]; + let output = Object(target); + for (let index = 1; index < arguments.length; index++) { + const source = arguments[index]; if (source !== undefined && source !== null) { - for (var nextKey in source) { + for (const nextKey in source) { if (source.hasOwnProperty(nextKey)) { output[nextKey] = source[nextKey]; } diff --git a/src/utils/deprecate.js b/src/utils/deprecate.js index 2be0c38dd..067c3edd6 100644 --- a/src/utils/deprecate.js +++ b/src/utils/deprecate.js @@ -6,14 +6,14 @@ * @returns {Function} A new function wrapping the supplied method. */ export default function deprecate(method, name, message) { - var deprecationMessage = 'DEPRECATED METHOD: ' + name + '\n' + message + ' AT \n'; + let deprecationMessage = 'DEPRECATED METHOD: ' + name + '\n' + message + ' AT \n'; return function() { - var e = new Error('get-stack-trace'); - var stack = e && e.stack ? e.stack.replace(/^[^\(]+?[\n$]/gm, '') + let e = new Error('get-stack-trace'); + let stack = e && e.stack ? e.stack.replace(/^[^\(]+?[\n$]/gm, '') .replace(/^\s+at\s+/gm, '') .replace(/^Object.\s*\(/gm, '{anonymous}()@') : 'Unknown Stack Trace'; - var log = window.console && (window.console.warn || window.console.log); + let log = window.console && (window.console.warn || window.console.log); if (log) { log.call(window.console, deprecationMessage, stack); } diff --git a/src/utils/each.js b/src/utils/each.js index 875d608eb..e09b40116 100644 --- a/src/utils/each.js +++ b/src/utils/each.js @@ -5,7 +5,7 @@ * @param {Object} context */ export default function each(obj, iterator, context) { - var i; + let i; if (!obj) { return; diff --git a/src/utils/extend.js b/src/utils/extend.js index d4559b19c..e8fc3cee0 100644 --- a/src/utils/extend.js +++ b/src/utils/extend.js @@ -7,9 +7,9 @@ import deprecate from './deprecate'; * @param {Boolean} [merge=false] * @returns {Object} dest */ -var extend = deprecate(function extend(dest, src, merge) { - var keys = Object.keys(src); - var i = 0; +const extend = deprecate(function extend(dest, src, merge) { + let keys = Object.keys(src); + let i = 0; while (i < keys.length) { if (!merge || (merge && dest[keys[i]] === undefined)) { dest[keys[i]] = src[keys[i]]; diff --git a/src/utils/get-window-for-element.js b/src/utils/get-window-for-element.js index 7b6a562ef..bf29c0476 100644 --- a/src/utils/get-window-for-element.js +++ b/src/utils/get-window-for-element.js @@ -4,6 +4,6 @@ * @returns {DocumentView|Window} */ export default function getWindowForElement(element) { - var doc = element.ownerDocument || element; + let doc = element.ownerDocument || element; return (doc.defaultView || doc.parentWindow || window); } diff --git a/src/utils/in-array.js b/src/utils/in-array.js index 1e19f2b4a..a61044137 100644 --- a/src/utils/in-array.js +++ b/src/utils/in-array.js @@ -9,7 +9,7 @@ export default function inArray(src, find, findByKey) { if (src.indexOf && !findByKey) { return src.indexOf(find); } else { - var i = 0; + let i = 0; while (i < src.length) { if ((findByKey && src[i][findByKey] == find) || (!findByKey && src[i] === find)) { return i; diff --git a/src/utils/inherit.js b/src/utils/inherit.js index 86a48db90..929a63c79 100644 --- a/src/utils/inherit.js +++ b/src/utils/inherit.js @@ -6,8 +6,8 @@ import assign from './assign'; * @param {Object} [properties] */ export default function inherit(child, base, properties) { - var baseP = base.prototype, - childP; + let baseP = base.prototype; + let childP; childP = child.prototype = Object.create(baseP); childP.constructor = child; diff --git a/src/utils/merge.js b/src/utils/merge.js index dd19bd3d4..8e5f4fd15 100644 --- a/src/utils/merge.js +++ b/src/utils/merge.js @@ -7,7 +7,7 @@ import extend from './extend'; * @param {Object} src * @returns {Object} dest */ -var merge = deprecate(function merge(dest, src) { +const merge = deprecate(function merge(dest, src) { return extend(dest, src, true); }, 'merge', 'Use `assign`.'); diff --git a/src/utils/prefixed.js b/src/utils/prefixed.js index 38ebbbb27..80ef6e834 100644 --- a/src/utils/prefixed.js +++ b/src/utils/prefixed.js @@ -6,10 +6,11 @@ import { VENDOR_PREFIXES } from './utils-consts'; * @returns {String|Undefined} prefixed */ export default function prefixed(obj, property) { - var prefix, prop; - var camelProp = property[0].toUpperCase() + property.slice(1); + let prefix; + let prop; + let camelProp = property[0].toUpperCase() + property.slice(1); - var i = 0; + let i = 0; while (i < VENDOR_PREFIXES.length) { prefix = VENDOR_PREFIXES[i]; prop = (prefix) ? prefix + camelProp : property; diff --git a/src/utils/unique-array.js b/src/utils/unique-array.js index 66f02fb6c..9f445b360 100644 --- a/src/utils/unique-array.js +++ b/src/utils/unique-array.js @@ -8,12 +8,12 @@ import inArray from './in-array'; * @returns {Array} [{id:1},{id:2}] */ export default function uniqueArray(src, key, sort) { - var results = []; - var values = []; - var i = 0; + let results = []; + let values = []; + let i = 0; while (i < src.length) { - var val = key ? src[i][key] : src[i]; + let val = key ? src[i][key] : src[i]; if (inArray(values, val) < 0) { results.push(src[i]); } diff --git a/src/utils/unique-id.js b/src/utils/unique-id.js index 9bb1e61ff..0625b4adc 100644 --- a/src/utils/unique-id.js +++ b/src/utils/unique-id.js @@ -2,7 +2,7 @@ * get a unique id * @returns {number} uniqueId */ -var _uniqueId = 1; +let _uniqueId = 1; export default function uniqueId() { return _uniqueId++; } diff --git a/src/utils/utils-consts.js b/src/utils/utils-consts.js index 11903f525..7843ac80f 100644 --- a/src/utils/utils-consts.js +++ b/src/utils/utils-consts.js @@ -1,11 +1,11 @@ -var VENDOR_PREFIXES = ['', 'webkit', 'Moz', 'MS', 'ms', 'o']; -var TEST_ELEMENT = document.createElement('div'); +const VENDOR_PREFIXES = ['', 'webkit', 'Moz', 'MS', 'ms', 'o']; +const TEST_ELEMENT = document.createElement('div'); -var TYPE_FUNCTION = 'function'; +const TYPE_FUNCTION = 'function'; -var round = Math.round; -var abs = Math.abs; -var now = Date.now; +const round = Math.round; +const abs = Math.abs; +const now = Date.now; export { VENDOR_PREFIXES, From 18cdcadafae1893e0e15c14b0b9ea78b77734055 Mon Sep 17 00:00:00 2001 From: Arjun Kathuria Date: Mon, 13 Jun 2016 16:49:51 +0530 Subject: [PATCH 35/61] style(template strings for concatenation): uses the new template string notation for concating string --- src/recognizers/press.js | 2 +- src/utils/deprecate.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/recognizers/press.js b/src/recognizers/press.js index 6a9e01207..706d56f8c 100644 --- a/src/recognizers/press.js +++ b/src/recognizers/press.js @@ -76,7 +76,7 @@ inherit(PressRecognizer, Recognizer, { } if (input && (input.eventType & INPUT_END)) { - this.manager.emit(this.options.event + 'up', input); + this.manager.emit(`${this.options.event}up`, input); } else { this._input.timeStamp = now(); this.manager.emit(this.options.event, this._input); diff --git a/src/utils/deprecate.js b/src/utils/deprecate.js index 067c3edd6..dab8fa78e 100644 --- a/src/utils/deprecate.js +++ b/src/utils/deprecate.js @@ -6,7 +6,7 @@ * @returns {Function} A new function wrapping the supplied method. */ export default function deprecate(method, name, message) { - let deprecationMessage = 'DEPRECATED METHOD: ' + name + '\n' + message + ' AT \n'; + let deprecationMessage = `DEPRECATED METHOD: ${name}\n${message} AT \n`; return function() { let e = new Error('get-stack-trace'); let stack = e && e.stack ? e.stack.replace(/^[^\(]+?[\n$]/gm, '') From 1d30b20cae01596bd1b676f42016de7f3f481339 Mon Sep 17 00:00:00 2001 From: Arjun Kathuria Date: Mon, 13 Jun 2016 17:42:34 +0530 Subject: [PATCH 36/61] style(Object Destructuring): property assignments now use ES6 object destructuring --- src/input/pointerevent.js | 2 +- src/input/touch.js | 4 ++-- src/input/touchmouse.js | 3 +-- src/inputjs/compute-delta-xy.js | 4 ++-- src/inputjs/compute-input-data.js | 10 +++++----- src/inputjs/create-input-instance.js | 4 ++-- src/manager.js | 16 ++++++++-------- .../get-recognizer-by-name-if-manager.js | 2 +- src/recognizerjs/recognizer-constructor.js | 6 +++--- src/recognizers/attribute.js | 4 ++-- src/recognizers/pan.js | 8 ++++---- src/recognizers/press.js | 2 +- src/recognizers/swipe.js | 2 +- src/recognizers/tap.js | 2 +- src/touchactionjs/touchaction-constructor.js | 7 +++---- src/utils/utils-consts.js | 6 +++--- 16 files changed, 40 insertions(+), 42 deletions(-) diff --git a/src/input/pointerevent.js b/src/input/pointerevent.js index 1dccec61e..8ab698570 100644 --- a/src/input/pointerevent.js +++ b/src/input/pointerevent.js @@ -57,7 +57,7 @@ inherit(PointerEventInput, Input, { * @param {Object} ev */ handler: function PEhandler(ev) { - let store = this.store; + let { store } = this; let removePointer = false; let eventTypeNormalized = ev.type.toLowerCase().replace('ms', ''); diff --git a/src/input/touch.js b/src/input/touch.js index 88bddd620..e975208c7 100644 --- a/src/input/touch.js +++ b/src/input/touch.js @@ -57,7 +57,7 @@ inherit(TouchInput, Input, { */ function getTouches(ev, type) { let allTouches = toArray(ev.touches); - let targetIds = this.targetIds; + let { targetIds } = this; // when there is only one touch, the process can be simplified if (type & (INPUT_START | INPUT_MOVE) && allTouches.length === 1) { @@ -69,7 +69,7 @@ function getTouches(ev, type) { let targetTouches; let changedTouches = toArray(ev.changedTouches); let changedTargetTouches = []; - let target = this.target; + let { target } = this; // get target touches from touches targetTouches = allTouches.filter(function(touch) { diff --git a/src/input/touchmouse.js b/src/input/touchmouse.js index f0d0cec1c..ac63ecbf7 100644 --- a/src/input/touchmouse.js +++ b/src/input/touchmouse.js @@ -79,8 +79,7 @@ function recordTouches(eventType, eventData) { } function setLastTouch(eventData) { - let touch = eventData.changedPointers[0]; - + let { changedPointers:[touch] } = eventData; if (touch.identifier === this.primaryTouch) { let lastTouch = { x: touch.clientX, y: touch.clientY }; this.lastTouches.push(lastTouch); diff --git a/src/inputjs/compute-delta-xy.js b/src/inputjs/compute-delta-xy.js index f72d918e5..b4ecda9b8 100644 --- a/src/inputjs/compute-delta-xy.js +++ b/src/inputjs/compute-delta-xy.js @@ -1,8 +1,8 @@ import { INPUT_START,INPUT_END } from './input-consts'; export default function computeDeltaXY(session, input) { - let center = input.center; - let offset = session.offsetDelta || {}; + let { center } = input; + let offset = session.offsetDelta || {}; // could be further deconstructed later on let prevDelta = session.prevDelta || {}; let prevInput = session.prevInput || {}; diff --git a/src/inputjs/compute-input-data.js b/src/inputjs/compute-input-data.js index 7f742cf23..ce3a86c31 100644 --- a/src/inputjs/compute-input-data.js +++ b/src/inputjs/compute-input-data.js @@ -18,9 +18,9 @@ import computeIntervalInputData from './compute-interval-input-data'; * @param {Object} input */ export default function computeInputData(manager, input) { - let session = manager.session; - let pointers = input.pointers; - let pointersLength = pointers.length; + let { session } = manager; + let { pointers } = input; + let { length:pointersLength } = pointers; // store the first input to calculate the distance and direction if (!session.firstInput) { @@ -34,8 +34,8 @@ export default function computeInputData(manager, input) { session.firstMultiple = false; } - let firstInput = session.firstInput; - let firstMultiple = session.firstMultiple; + let { firstInput } = session; + let { firstMultiple } = session; let offsetCenter = firstMultiple ? firstMultiple.center : firstInput.center; let center = input.center = getCenter(pointers); diff --git a/src/inputjs/create-input-instance.js b/src/inputjs/create-input-instance.js index 721b67f09..d6289df48 100644 --- a/src/inputjs/create-input-instance.js +++ b/src/inputjs/create-input-instance.js @@ -13,8 +13,8 @@ import { TouchMouseInput } from '../input/touchmouse'; */ export default function createInputInstance(manager) { let Type; - let inputClass = manager.options.inputClass; - + // let inputClass = manager.options.inputClass; + let { options:{ inputClass } } = manager; if (inputClass) { Type = inputClass; } else if (SUPPORT_POINTER_EVENTS) { diff --git a/src/manager.js b/src/manager.js index e16ca7508..7c315bbd9 100644 --- a/src/manager.js +++ b/src/manager.js @@ -86,7 +86,7 @@ Manager.prototype = { * @param {Object} inputData */ recognize: function(inputData) { - let session = this.session; + let { session } = this; if (session.stopped) { return; } @@ -95,12 +95,12 @@ Manager.prototype = { this.touchAction.preventDefaults(inputData); let recognizer; - let recognizers = this.recognizers; + let { recognizers } = this; // this holds the recognizer that is being recognized. // so the recognizer's state needs to be BEGAN, CHANGED, ENDED or RECOGNIZED // if no recognizer is detecting a thing, it is set to `null` - let curRecognizer = session.curRecognizer; + let { curRecognizer } = session; // reset when the last recognizer is recognized // or when we're in a new session @@ -145,7 +145,7 @@ Manager.prototype = { return recognizer; } - let recognizers = this.recognizers; + let { recognizers } = this; for (let i = 0; i < recognizers.length; i++) { if (recognizers[i].options.event == recognizer) { return recognizers[i]; @@ -192,7 +192,7 @@ Manager.prototype = { // let's make sure this recognizer exists if (recognizer) { - let recognizers = this.recognizers; + let { recognizers } = this; let index = inArray(recognizers, recognizer); if (index !== -1) { @@ -218,7 +218,7 @@ Manager.prototype = { return; } - let handlers = this.handlers; + let { handlers } = this; each(splitStr(events), function(event) { handlers[event] = handlers[event] || []; handlers[event].push(handler); @@ -237,7 +237,7 @@ Manager.prototype = { return; } - let handlers = this.handlers; + let { handlers } = this; each(splitStr(events), function(event) { if (!handler) { delete handlers[event]; @@ -297,7 +297,7 @@ Manager.prototype = { * @param {Boolean} add */ function toggleCssProps(manager, add) { - let element = manager.element; + let { element } = manager; if (!element.style) { return; } diff --git a/src/recognizerjs/get-recognizer-by-name-if-manager.js b/src/recognizerjs/get-recognizer-by-name-if-manager.js index 0f43a4648..2583cd9ee 100644 --- a/src/recognizerjs/get-recognizer-by-name-if-manager.js +++ b/src/recognizerjs/get-recognizer-by-name-if-manager.js @@ -5,7 +5,7 @@ * @returns {Recognizer} */ export default function getRecognizerByNameIfManager(otherRecognizer, recognizer) { - let manager = recognizer.manager; + let { manager } = recognizer; if (manager) { return manager.get(otherRecognizer); } diff --git a/src/recognizerjs/recognizer-constructor.js b/src/recognizerjs/recognizer-constructor.js index 9a4575789..ff2d54a1d 100644 --- a/src/recognizerjs/recognizer-constructor.js +++ b/src/recognizerjs/recognizer-constructor.js @@ -96,7 +96,7 @@ Recognizer.prototype = { return this; } - let simultaneous = this.simultaneous; + let { simultaneous } = this; otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this); if (!simultaneous[otherRecognizer.id]) { simultaneous[otherRecognizer.id] = otherRecognizer; @@ -130,7 +130,7 @@ Recognizer.prototype = { return this; } - let requireFail = this.requireFail; + let { requireFail }= this; otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this); if (inArray(requireFail, otherRecognizer) === -1) { requireFail.push(otherRecognizer); @@ -181,7 +181,7 @@ Recognizer.prototype = { */ emit: function(input) { let self = this; - let state = this.state; + let { state } = this; function emit(event) { self.manager.emit(event, input); diff --git a/src/recognizers/attribute.js b/src/recognizers/attribute.js index 253a18d6e..33179d7e3 100644 --- a/src/recognizers/attribute.js +++ b/src/recognizers/attribute.js @@ -52,8 +52,8 @@ inherit(AttrRecognizer, Recognizer, { * @returns {*} State */ process: function(input) { - let state = this.state; - let eventType = input.eventType; + let { state } = this; + let { eventType } = input; let isRecognized = state & (STATE_BEGAN | STATE_CHANGED); let isValid = this.attrTest(input); diff --git a/src/recognizers/pan.js b/src/recognizers/pan.js index 69cdb9305..840040134 100644 --- a/src/recognizers/pan.js +++ b/src/recognizers/pan.js @@ -40,7 +40,7 @@ inherit(PanRecognizer, AttrRecognizer, { }, getTouchAction: function() { - let direction = this.options.direction; + let { options:{ direction } } = this; let actions = []; if (direction & DIRECTION_HORIZONTAL) { actions.push(TOUCH_ACTION_PAN_Y); @@ -52,10 +52,10 @@ inherit(PanRecognizer, AttrRecognizer, { }, directionTest: function(input) { - let options = this.options; + let { options } = this; let hasMoved = true; - let distance = input.distance; - let direction = input.direction; + let { distance } = input; + let { direction } = input; let x = input.deltaX; let y = input.deltaY; diff --git a/src/recognizers/press.js b/src/recognizers/press.js index 706d56f8c..77ab7c012 100644 --- a/src/recognizers/press.js +++ b/src/recognizers/press.js @@ -43,7 +43,7 @@ inherit(PressRecognizer, Recognizer, { }, process: function(input) { - let options = this.options; + let { options } = this; let validPointers = input.pointers.length === options.pointers; let validMovement = input.distance < options.threshold; let validTime = input.deltaTime > options.time; diff --git a/src/recognizers/swipe.js b/src/recognizers/swipe.js index 1df2c8267..67ab82312 100644 --- a/src/recognizers/swipe.js +++ b/src/recognizers/swipe.js @@ -34,7 +34,7 @@ inherit(SwipeRecognizer, AttrRecognizer, { }, attrTest: function(input) { - let direction = this.options.direction; + let { options:{ direction } } = this; let velocity; if (direction & (DIRECTION_HORIZONTAL | DIRECTION_VERTICAL)) { diff --git a/src/recognizers/tap.js b/src/recognizers/tap.js index c50a1bf95..293b1d6d2 100644 --- a/src/recognizers/tap.js +++ b/src/recognizers/tap.js @@ -53,7 +53,7 @@ inherit(TapRecognizer, Recognizer, { }, process: function(input) { - let options = this.options; + let { options } = this; let validPointers = input.pointers.length === options.pointers; let validMovement = input.distance < options.threshold; diff --git a/src/touchactionjs/touchaction-constructor.js b/src/touchactionjs/touchaction-constructor.js index 7d1560a4f..9c7f6ce2c 100644 --- a/src/touchactionjs/touchaction-constructor.js +++ b/src/touchactionjs/touchaction-constructor.js @@ -71,7 +71,7 @@ TouchAction.prototype = { * @param {Object} input */ preventDefaults: function(input) { - let srcEvent = input.srcEvent; + let { srcEvent } = input; let direction = input.offsetDirection; // if the touch action did prevented once this session @@ -80,14 +80,13 @@ TouchAction.prototype = { return; } - let actions = this.actions; + let { actions } = this; let hasNone = inStr(actions, TOUCH_ACTION_NONE) && !TOUCH_ACTION_MAP[TOUCH_ACTION_NONE]; let hasPanY = inStr(actions, TOUCH_ACTION_PAN_Y) && !TOUCH_ACTION_MAP[TOUCH_ACTION_PAN_Y]; let hasPanX = inStr(actions, TOUCH_ACTION_PAN_X) && !TOUCH_ACTION_MAP[TOUCH_ACTION_PAN_X]; if (hasNone) { - //do not prevent defaults if this is a tap gesture - + // do not prevent defaults if this is a tap gesture let isTapPointer = input.pointers.length === 1; let isTapMovement = input.distance < 2; let isTapTouchTime = input.deltaTime < 250; diff --git a/src/utils/utils-consts.js b/src/utils/utils-consts.js index 7843ac80f..7054369d4 100644 --- a/src/utils/utils-consts.js +++ b/src/utils/utils-consts.js @@ -3,9 +3,9 @@ const TEST_ELEMENT = document.createElement('div'); const TYPE_FUNCTION = 'function'; -const round = Math.round; -const abs = Math.abs; -const now = Date.now; +const { round } = Math; +const { abs } = Math; +const { now } = Date; export { VENDOR_PREFIXES, From 29f3441fd07f67527da12b9aa772d14307acb225 Mon Sep 17 00:00:00 2001 From: Arjun Kathuria Date: Mon, 13 Jun 2016 18:14:21 +0530 Subject: [PATCH 37/61] style(===): replaces equality == with strict equality === --- .jshintrc | 7 +++++-- src/input/pointerevent.js | 2 +- src/input/touchmouse.js | 4 ++-- src/inputjs/compute-interval-input-data.js | 2 +- src/main.js | 2 +- src/manager.js | 4 ++-- src/recognizerjs/direction-str.js | 8 ++++---- src/recognizers/pan.js | 4 ++-- src/recognizers/swipe.js | 2 +- src/recognizers/tap.js | 4 ++-- src/touchactionjs/touchaction-constructor.js | 2 +- src/utils/bool-or-fn.js | 2 +- src/utils/has-parent.js | 2 +- 13 files changed, 24 insertions(+), 21 deletions(-) diff --git a/.jshintrc b/.jshintrc index 55a1ac6f4..7e3773177 100644 --- a/.jshintrc +++ b/.jshintrc @@ -5,14 +5,17 @@ "indent": 2, "predef": [ "document", - "window" + "window", + "define", + "module" ], "browser": true, "boss": true, "curly": true, "debug": false, "devel": true, - "eqeqeq": true, + "expr": true, + "validthis": true, "evil": true, "forin": false, "immed": false, diff --git a/src/input/pointerevent.js b/src/input/pointerevent.js index 8ab698570..1aa87d1d1 100644 --- a/src/input/pointerevent.js +++ b/src/input/pointerevent.js @@ -64,7 +64,7 @@ inherit(PointerEventInput, Input, { let eventType = POINTER_INPUT_MAP[eventTypeNormalized]; let pointerType = IE10_POINTER_TYPE_ENUM[ev.pointerType] || ev.pointerType; - let isTouch = (pointerType == INPUT_TYPE_TOUCH); + let isTouch = (pointerType === INPUT_TYPE_TOUCH); // get index of the event in the store let storeIndex = inArray(store, ev.pointerId, 'pointerId'); diff --git a/src/input/touchmouse.js b/src/input/touchmouse.js index ac63ecbf7..9bb71c96b 100644 --- a/src/input/touchmouse.js +++ b/src/input/touchmouse.js @@ -43,8 +43,8 @@ inherit(TouchMouseInput, Input, { * @param {Object} inputData */ handler: function TMEhandler(manager, inputEvent, inputData) { - let isTouch = (inputData.pointerType == INPUT_TYPE_TOUCH); - let isMouse = (inputData.pointerType == INPUT_TYPE_MOUSE); + let isTouch = (inputData.pointerType === INPUT_TYPE_TOUCH); + let isMouse = (inputData.pointerType === INPUT_TYPE_MOUSE); if (isMouse && inputData.sourceCapabilities && inputData.sourceCapabilities.firesTouchEvents) { return; diff --git a/src/inputjs/compute-interval-input-data.js b/src/inputjs/compute-interval-input-data.js index fba4310df..e6849aca9 100644 --- a/src/inputjs/compute-interval-input-data.js +++ b/src/inputjs/compute-interval-input-data.js @@ -16,7 +16,7 @@ export default function computeIntervalInputData(session, input) { let velocityY; let direction; - if (input.eventType != INPUT_CANCEL && (deltaTime > COMPUTE_INTERVAL || last.velocity === undefined)) { + if (input.eventType !== INPUT_CANCEL && (deltaTime > COMPUTE_INTERVAL || last.velocity === undefined)) { let deltaX = input.deltaX - last.deltaX; let deltaY = input.deltaY - last.deltaY; diff --git a/src/main.js b/src/main.js index 1ac036d7c..15e21c50c 100644 --- a/src/main.js +++ b/src/main.js @@ -130,7 +130,7 @@ if (typeof define === 'function' && define.amd) { define(function() { return Hammer; }); -} else if (typeof module != 'undefined' && module.exports) { +} else if (typeof module !== 'undefined' && module.exports) { module.exports = Hammer; } else { window[exportName] = Hammer; diff --git a/src/manager.js b/src/manager.js index 7c315bbd9..502eb9160 100644 --- a/src/manager.js +++ b/src/manager.js @@ -119,7 +119,7 @@ Manager.prototype = { // 3. allow if the recognizer is allowed to run simultaneous with the current recognized recognizer. // this can be setup with the `recognizeWith()` method on the recognizer. if (session.stopped !== FORCED_STOP && (// 1 - !curRecognizer || recognizer == curRecognizer || // 2 + !curRecognizer || recognizer === curRecognizer || // 2 recognizer.canRecognizeWith(curRecognizer))) { // 3 recognizer.recognize(inputData); } else { @@ -147,7 +147,7 @@ Manager.prototype = { let { recognizers } = this; for (let i = 0; i < recognizers.length; i++) { - if (recognizers[i].options.event == recognizer) { + if (recognizers[i].options.event === recognizer) { return recognizers[i]; } } diff --git a/src/recognizerjs/direction-str.js b/src/recognizerjs/direction-str.js index ffaf2ecb5..aa18d96c8 100644 --- a/src/recognizerjs/direction-str.js +++ b/src/recognizerjs/direction-str.js @@ -11,13 +11,13 @@ import { * @returns {String} */ export default function directionStr(direction) { - if (direction == DIRECTION_DOWN) { + if (direction === DIRECTION_DOWN) { return 'down'; - } else if (direction == DIRECTION_UP) { + } else if (direction === DIRECTION_UP) { return 'up'; - } else if (direction == DIRECTION_LEFT) { + } else if (direction === DIRECTION_LEFT) { return 'left'; - } else if (direction == DIRECTION_RIGHT) { + } else if (direction === DIRECTION_RIGHT) { return 'right'; } return ''; diff --git a/src/recognizers/pan.js b/src/recognizers/pan.js index 840040134..4ba8476e0 100644 --- a/src/recognizers/pan.js +++ b/src/recognizers/pan.js @@ -63,11 +63,11 @@ inherit(PanRecognizer, AttrRecognizer, { if (!(direction & options.direction)) { if (options.direction & DIRECTION_HORIZONTAL) { direction = (x === 0) ? DIRECTION_NONE : (x < 0) ? DIRECTION_LEFT : DIRECTION_RIGHT; - hasMoved = x != this.pX; + hasMoved = x !== this.pX; distance = Math.abs(input.deltaX); } else { direction = (y === 0) ? DIRECTION_NONE : (y < 0) ? DIRECTION_UP : DIRECTION_DOWN; - hasMoved = y != this.pY; + hasMoved = y !== this.pY; distance = Math.abs(input.deltaY); } } diff --git a/src/recognizers/swipe.js b/src/recognizers/swipe.js index 67ab82312..8f7206cb5 100644 --- a/src/recognizers/swipe.js +++ b/src/recognizers/swipe.js @@ -48,7 +48,7 @@ inherit(SwipeRecognizer, AttrRecognizer, { return this._super.attrTest.call(this, input) && direction & input.offsetDirection && input.distance > this.options.threshold && - input.maxPointers == this.options.pointers && + input.maxPointers === this.options.pointers && abs(velocity) > this.options.velocity && input.eventType & INPUT_END; }, diff --git a/src/recognizers/tap.js b/src/recognizers/tap.js index 293b1d6d2..f14d49dba 100644 --- a/src/recognizers/tap.js +++ b/src/recognizers/tap.js @@ -68,7 +68,7 @@ inherit(TapRecognizer, Recognizer, { // we only allow little movement // and we've reached an end event, so a tap is possible if (validMovement && validTouchTime && validPointers) { - if (input.eventType != INPUT_END) { + if (input.eventType !== INPUT_END) { return this.failTimeout(); } @@ -118,7 +118,7 @@ inherit(TapRecognizer, Recognizer, { }, emit: function() { - if (this.state == STATE_RECOGNIZED) { + if (this.state === STATE_RECOGNIZED) { this._input.tapCount = this.count; this.manager.emit(this.options.event, this._input); } diff --git a/src/touchactionjs/touchaction-constructor.js b/src/touchactionjs/touchaction-constructor.js index 9c7f6ce2c..9c1167d87 100644 --- a/src/touchactionjs/touchaction-constructor.js +++ b/src/touchactionjs/touchaction-constructor.js @@ -35,7 +35,7 @@ TouchAction.prototype = { */ set: function(value) { // find out the touch-action by the event handlers - if (value == TOUCH_ACTION_COMPUTE) { + if (value === TOUCH_ACTION_COMPUTE) { value = this.compute(); } diff --git a/src/utils/bool-or-fn.js b/src/utils/bool-or-fn.js index e94bce957..fb0acf5ed 100644 --- a/src/utils/bool-or-fn.js +++ b/src/utils/bool-or-fn.js @@ -7,7 +7,7 @@ import { TYPE_FUNCTION } from './utils-consts'; * @returns {Boolean} */ export default function boolOrFn(val, args) { - if (typeof val == TYPE_FUNCTION) { + if (typeof val === TYPE_FUNCTION) { return val.apply(args ? args[0] || undefined : undefined, args); } return val; diff --git a/src/utils/has-parent.js b/src/utils/has-parent.js index e2c2a163f..6264c7579 100644 --- a/src/utils/has-parent.js +++ b/src/utils/has-parent.js @@ -7,7 +7,7 @@ */ export default function hasParent(node, parent) { while (node) { - if (node == parent) { + if (node === parent) { return true; } node = node.parentNode; From ed8d35493f98d816706e371a5375274113438bee Mon Sep 17 00:00:00 2001 From: Arjun Kathuria Date: Tue, 14 Jun 2016 14:24:37 +0530 Subject: [PATCH 38/61] style(jscs requireCommentsToIncludeAccess): you must supply @public, @private, @protected for block comments --- .jshintrc | 7 +++++-- src/hammer.js | 16 ++++++++++++++++ src/input/mouse.js | 2 ++ src/input/pointerevent.js | 2 ++ src/input/singletouch.js | 2 ++ src/input/touch.js | 2 ++ src/input/touchmouse.js | 3 +++ src/inputjs/compute-input-data.js | 1 + src/inputjs/compute-interval-input-data.js | 1 + src/inputjs/create-input-instance.js | 1 + src/inputjs/get-angle.js | 1 + src/inputjs/get-center.js | 1 + src/inputjs/get-direction.js | 1 + src/inputjs/get-distance.js | 1 + src/inputjs/get-rotation.js | 1 + src/inputjs/get-scale.js | 1 + src/inputjs/get-velocity.js | 1 + src/inputjs/input-constructor.js | 4 ++++ src/inputjs/input-handler.js | 1 + src/inputjs/simple-clone-input-data.js | 1 + src/manager.js | 16 +++++++++++++--- src/recognizerjs/direction-str.js | 1 + .../get-recognizer-by-name-if-manager.js | 1 + src/recognizerjs/recognizer-constructor.js | 19 ++++++++++++++++++- src/recognizerjs/state-str.js | 1 + src/recognizers/attribute.js | 5 +++++ src/recognizers/pan.js | 2 ++ src/recognizers/pinch.js | 2 ++ src/recognizers/press.js | 2 ++ src/recognizers/rotate.js | 2 ++ src/recognizers/swipe.js | 2 ++ src/recognizers/tap.js | 2 ++ src/touchactionjs/clean-touch-actions.js | 1 + src/touchactionjs/touchaction-constructor.js | 6 ++++++ src/utils/add-event-listeners.js | 1 + src/utils/assign.js | 1 + src/utils/bind-fn.js | 1 + src/utils/bool-or-fn.js | 1 + src/utils/deprecate.js | 1 + src/utils/each.js | 1 + src/utils/extend.js | 1 + src/utils/get-window-for-element.js | 1 + src/utils/has-parent.js | 1 + src/utils/if-undefined.js | 1 + src/utils/in-array.js | 3 ++- src/utils/in-str.js | 1 + src/utils/inherit.js | 1 + src/utils/invoke-array-arg.js | 1 + src/utils/merge.js | 1 + src/utils/prefixed.js | 1 + src/utils/remove-event-listeners.js | 1 + src/utils/set-timeout-context.js | 1 + src/utils/split-str.js | 1 + src/utils/to-array.js | 1 + src/utils/unique-array.js | 1 + src/utils/unique-id.js | 1 + 56 files changed, 129 insertions(+), 7 deletions(-) diff --git a/.jshintrc b/.jshintrc index 7e3773177..f565275e5 100644 --- a/.jshintrc +++ b/.jshintrc @@ -33,6 +33,9 @@ "strict": false, "white": false, "eqnull": true, - "esnext": true, - "unused": true + "esversion": 6, + "unused": true, + "-W116": true, + "-W080": true, + "-W038": true } diff --git a/src/hammer.js b/src/hammer.js index 254d60b86..5eee80235 100644 --- a/src/hammer.js +++ b/src/hammer.js @@ -10,6 +10,7 @@ import { PressRecognizer } from './recognizers/press'; import { Manager } from './manager'; /** + * @private * Simple way to create a manager with a default set of recognizers. * @param {HTMLElement} element * @param {Object} [options] @@ -22,16 +23,19 @@ function Hammer(element, options) { } /** + * @private * @const {string} */ Hammer.VERSION = '{{PKG_VERSION}}'; /** + * @private * default settings * @namespace */ Hammer.defaults = { /** + * @private * set if DOM events are being triggered. * But this is slower and unused by simple implementations, so disabled by default. * @type {Boolean} @@ -40,6 +44,7 @@ Hammer.defaults = { domEvents: false, /** + * @private * The value for the touchAction property/fallback. * When set to `compute` it will magically set the correct value based on the added recognizers. * @type {String} @@ -48,12 +53,14 @@ Hammer.defaults = { touchAction: TOUCH_ACTION_COMPUTE, /** + * @private * @type {Boolean} * @default true */ enable: true, /** + * @private * EXPERIMENTAL FEATURE -- can be removed/changed * Change the parent input target element. * If Null, then it is being set the to main element. @@ -63,6 +70,7 @@ Hammer.defaults = { inputTarget: null, /** + * @private * force an input class * @type {Null|Function} * @default null @@ -70,6 +78,7 @@ Hammer.defaults = { inputClass: null, /** + * @private * Default recognizer setup when calling `Hammer()` * When creating a new Manager these will be skipped. * @type {Array} @@ -86,12 +95,14 @@ Hammer.defaults = { ], /** + * @private * Some CSS properties can be used to improve the working of Hammer. * Add them to this method and they will be set when creating a new Manager. * @namespace */ cssProps: { /** + * @private * Disables text selection to improve the dragging gesture. Mainly for desktop browsers. * @type {String} * @default 'none' @@ -99,6 +110,7 @@ Hammer.defaults = { userSelect: 'none', /** + * @private * Disable the Windows Phone grippers when pressing an element. * @type {String} * @default 'none' @@ -106,6 +118,7 @@ Hammer.defaults = { touchSelect: 'none', /** + * @private * Disables the default callout shown when you touch and hold a touch target. * On iOS, when you touch and hold a touch target such as a link, Safari displays * a callout containing information about the link. This property allows you to disable that callout. @@ -115,6 +128,7 @@ Hammer.defaults = { touchCallout: 'none', /** + * @private * Specifies whether zooming is enabled. Used by IE10> * @type {String} * @default 'none' @@ -122,6 +136,7 @@ Hammer.defaults = { contentZooming: 'none', /** + * @private * Specifies that an entire element should be draggable instead of its contents. Mainly for desktop browsers. * @type {String} * @default 'none' @@ -129,6 +144,7 @@ Hammer.defaults = { userDrag: 'none', /** + * @private * Overrides the highlight color shown when the user taps a link or a JavaScript * clickable element in iOS. This property obeys the alpha value, if specified. * @type {String} diff --git a/src/input/mouse.js b/src/input/mouse.js index ac5355e9a..88e6cb92d 100644 --- a/src/input/mouse.js +++ b/src/input/mouse.js @@ -17,6 +17,7 @@ const MOUSE_ELEMENT_EVENTS = 'mousedown'; const MOUSE_WINDOW_EVENTS = 'mousemove mouseup'; /** + * @private * Mouse events input * @constructor * @extends Input @@ -32,6 +33,7 @@ function MouseInput() { inherit(MouseInput, Input, { /** + * @private * handle mouse events * @param {Object} ev */ diff --git a/src/input/pointerevent.js b/src/input/pointerevent.js index 1aa87d1d1..2852d2a5b 100644 --- a/src/input/pointerevent.js +++ b/src/input/pointerevent.js @@ -38,6 +38,7 @@ if (window.MSPointerEvent && !window.PointerEvent) { } /** + * @private * Pointer events input * @constructor * @extends Input @@ -53,6 +54,7 @@ function PointerEventInput() { inherit(PointerEventInput, Input, { /** + * @private * handle mouse events * @param {Object} ev */ diff --git a/src/input/singletouch.js b/src/input/singletouch.js index 83cc164ae..c8b4bdb05 100644 --- a/src/input/singletouch.js +++ b/src/input/singletouch.js @@ -21,6 +21,7 @@ const SINGLE_TOUCH_TARGET_EVENTS = 'touchstart'; const SINGLE_TOUCH_WINDOW_EVENTS = 'touchstart touchmove touchend touchcancel'; /** + * @private * Touch events input * @constructor * @extends Input @@ -63,6 +64,7 @@ inherit(SingleTouchInput, Input, { }); /** + * @private * @this {TouchInput} * @param {Object} ev * @param {Number} type flag diff --git a/src/input/touch.js b/src/input/touch.js index e975208c7..1a660687d 100644 --- a/src/input/touch.js +++ b/src/input/touch.js @@ -21,6 +21,7 @@ const TOUCH_INPUT_MAP = { const TOUCH_TARGET_EVENTS = 'touchstart touchmove touchend touchcancel'; /** + * @private * Multi-user touch events input * @constructor * @extends Input @@ -50,6 +51,7 @@ inherit(TouchInput, Input, { }); /** + * @private * @this {TouchInput} * @param {Object} ev * @param {Number} type flag diff --git a/src/input/touchmouse.js b/src/input/touchmouse.js index 9bb71c96b..7621caad8 100644 --- a/src/input/touchmouse.js +++ b/src/input/touchmouse.js @@ -12,6 +12,7 @@ import { } from '../inputjs/input-consts'; /** + * @private * Combined touch and mouse input * * Touch has a higher priority then mouse, and while touching no mouse events are allowed. @@ -37,6 +38,7 @@ function TouchMouseInput() { inherit(TouchMouseInput, Input, { /** + * @private * handle mouse and touch events * @param {Hammer} manager * @param {String} inputEvent @@ -61,6 +63,7 @@ inherit(TouchMouseInput, Input, { }, /** + * @private * remove the event listeners */ destroy: function destroy() { diff --git a/src/inputjs/compute-input-data.js b/src/inputjs/compute-input-data.js index ce3a86c31..20217e86f 100644 --- a/src/inputjs/compute-input-data.js +++ b/src/inputjs/compute-input-data.js @@ -13,6 +13,7 @@ import getRotation from './get-rotation'; import computeIntervalInputData from './compute-interval-input-data'; /** +* @private * extend the data with some usable properties like scale, rotate, velocity etc * @param {Object} manager * @param {Object} input diff --git a/src/inputjs/compute-interval-input-data.js b/src/inputjs/compute-interval-input-data.js index e6849aca9..eb5746a31 100644 --- a/src/inputjs/compute-interval-input-data.js +++ b/src/inputjs/compute-interval-input-data.js @@ -4,6 +4,7 @@ import getVelocity from './get-velocity'; import getDirection from './get-direction'; /** + * @private * velocity is calculated every x ms * @param {Object} session * @param {Object} input diff --git a/src/inputjs/create-input-instance.js b/src/inputjs/create-input-instance.js index d6289df48..9abdf1091 100644 --- a/src/inputjs/create-input-instance.js +++ b/src/inputjs/create-input-instance.js @@ -6,6 +6,7 @@ import { MouseInput } from '../input/mouse'; import { TouchMouseInput } from '../input/touchmouse'; /** + * @private * create new input type manager * called by the Manager constructor * @param {Hammer} manager diff --git a/src/inputjs/get-angle.js b/src/inputjs/get-angle.js index 041e86efa..0015c23aa 100644 --- a/src/inputjs/get-angle.js +++ b/src/inputjs/get-angle.js @@ -1,6 +1,7 @@ import { PROPS_XY } from './input-consts'; /** + * @private * calculate the angle between two coordinates * @param {Object} p1 * @param {Object} p2 diff --git a/src/inputjs/get-center.js b/src/inputjs/get-center.js index 4fee78fc3..225b1ec07 100644 --- a/src/inputjs/get-center.js +++ b/src/inputjs/get-center.js @@ -1,6 +1,7 @@ import { round } from '../utils/utils-consts'; /** + * @private * get the center of all the pointers * @param {Array} pointers * @return {Object} center contains `x` and `y` properties diff --git a/src/inputjs/get-direction.js b/src/inputjs/get-direction.js index 95721c82e..cf577a888 100644 --- a/src/inputjs/get-direction.js +++ b/src/inputjs/get-direction.js @@ -2,6 +2,7 @@ import { abs } from '../utils/utils-consts'; import { DIRECTION_NONE,DIRECTION_LEFT,DIRECTION_RIGHT,DIRECTION_UP,DIRECTION_DOWN } from './input-consts'; /** + * @private * get the direction between two points * @param {Number} x * @param {Number} y diff --git a/src/inputjs/get-distance.js b/src/inputjs/get-distance.js index adaea53e8..066ea89c6 100644 --- a/src/inputjs/get-distance.js +++ b/src/inputjs/get-distance.js @@ -1,6 +1,7 @@ import { PROPS_XY } from './input-consts'; /** + * @private * calculate the absolute distance between two points * @param {Object} p1 {x, y} * @param {Object} p2 {x, y} diff --git a/src/inputjs/get-rotation.js b/src/inputjs/get-rotation.js index 7ffe1293c..d507ae9da 100644 --- a/src/inputjs/get-rotation.js +++ b/src/inputjs/get-rotation.js @@ -2,6 +2,7 @@ import getAngle from './get-angle'; import { PROPS_CLIENT_XY } from './input-consts'; /** + * @private * calculate the rotation degrees between two pointersets * @param {Array} start array of pointers * @param {Array} end array of pointers diff --git a/src/inputjs/get-scale.js b/src/inputjs/get-scale.js index 69b607fce..840e68388 100644 --- a/src/inputjs/get-scale.js +++ b/src/inputjs/get-scale.js @@ -1,6 +1,7 @@ import { PROPS_CLIENT_XY } from './input-consts'; import getDistance from './get-distance'; /** + * @private * calculate the scale factor between two pointersets * no scale is 1, and goes down to 0 when pinched together, and bigger when pinched out * @param {Array} start array of pointers diff --git a/src/inputjs/get-velocity.js b/src/inputjs/get-velocity.js index 971eba7d6..589a2d222 100644 --- a/src/inputjs/get-velocity.js +++ b/src/inputjs/get-velocity.js @@ -1,4 +1,5 @@ /** + * @private * calculate the velocity between two points. unit is in px per ms. * @param {Number} deltaTime * @param {Number} x diff --git a/src/inputjs/input-constructor.js b/src/inputjs/input-constructor.js index 9c518f9b5..180d0cabf 100644 --- a/src/inputjs/input-constructor.js +++ b/src/inputjs/input-constructor.js @@ -4,6 +4,7 @@ import removeEventListeners from '../utils/remove-event-listeners'; import getWindowForElement from '../utils/get-window-for-element'; /** + * @private * create new input type manager * @param {Manager} manager * @param {Function} callback @@ -31,12 +32,14 @@ function Input(manager, callback) { Input.prototype = { /** + * @private * should handle the inputEvent data and trigger the callback * @virtual */ handler: function() { }, /** + * @private * bind the events */ init: function() { @@ -46,6 +49,7 @@ Input.prototype = { }, /** + * @private * unbind the events */ destroy: function() { diff --git a/src/inputjs/input-handler.js b/src/inputjs/input-handler.js index 0ce8a131b..8c75d92c9 100644 --- a/src/inputjs/input-handler.js +++ b/src/inputjs/input-handler.js @@ -2,6 +2,7 @@ import { INPUT_START,INPUT_END,INPUT_CANCEL } from './input-consts'; import computeInputData from './compute-input-data'; /** + * @private * handle input events * @param {Manager} manager * @param {String} eventType diff --git a/src/inputjs/simple-clone-input-data.js b/src/inputjs/simple-clone-input-data.js index 324d914bb..270c531f3 100644 --- a/src/inputjs/simple-clone-input-data.js +++ b/src/inputjs/simple-clone-input-data.js @@ -2,6 +2,7 @@ import { now,round } from '../utils/utils-consts'; import getCenter from './get-center'; /** + * @private * create a simple clone from the input used for storage of firstInput and firstMultiple * @param {Object} input * @returns {Object} clonedInputData diff --git a/src/manager.js b/src/manager.js index 502eb9160..aa091bb1c 100644 --- a/src/manager.js +++ b/src/manager.js @@ -19,6 +19,7 @@ const STOP = 1; const FORCED_STOP = 2; /** +* @private * Manager * @param {HTMLElement} element * @param {Object} [options] @@ -49,6 +50,7 @@ function Manager(element, options) { Manager.prototype = { /** + * @private * set options * @param {Object} options * @returns {Manager} @@ -70,6 +72,7 @@ Manager.prototype = { }, /** + * @private * stop recognizing for this session. * This session will be discarded, when a new [input]start event is fired. * When forced, the recognizer cycle is stopped immediately. @@ -80,6 +83,7 @@ Manager.prototype = { }, /** + * @private * run the recognizers! * called by the inputHandler function on every movement of the pointers (touches) * it walks through all the recognizers and tries to detect the gesture that is being made @@ -136,6 +140,7 @@ Manager.prototype = { }, /** + * @private * get a recognizer by its event name. * @param {Recognizer|String} recognizer * @returns {Recognizer|Null} @@ -155,7 +160,7 @@ Manager.prototype = { }, /** - * add a recognizer to the manager + * @private add a recognizer to the manager * existing recognizers with the same event name will be removed * @param {Recognizer} recognizer * @returns {Recognizer|Manager} @@ -179,6 +184,7 @@ Manager.prototype = { }, /** + * @private * remove a recognizer by name or instance * @param {Recognizer|String} recognizer * @returns {Manager} @@ -205,6 +211,7 @@ Manager.prototype = { }, /** + * @private * bind event * @param {String} events * @param {Function} handler @@ -227,7 +234,7 @@ Manager.prototype = { }, /** - * unbind event, leave emit blank to remove all handlers + * @private unbind event, leave emit blank to remove all handlers * @param {String} events * @param {Function} [handler] * @returns {EventEmitter} this @@ -249,7 +256,7 @@ Manager.prototype = { }, /** - * emit event to the listeners + * @private emit event to the listeners * @param {String} event * @param {Object} data */ @@ -278,6 +285,7 @@ Manager.prototype = { }, /** + * @private * destroy the manager and unbinds all events * it doesn't unbind dom events, that is the user own responsibility */ @@ -292,6 +300,7 @@ Manager.prototype = { }; /** + * @private * add/remove the css properties as defined in manager.options.cssProps * @param {Manager} manager * @param {Boolean} add @@ -317,6 +326,7 @@ function toggleCssProps(manager, add) { } /** + * @private * trigger dom event * @param {String} event * @param {Object} data diff --git a/src/recognizerjs/direction-str.js b/src/recognizerjs/direction-str.js index aa18d96c8..1dfd21806 100644 --- a/src/recognizerjs/direction-str.js +++ b/src/recognizerjs/direction-str.js @@ -6,6 +6,7 @@ import { } from '../inputjs/input-consts'; /** + * @private * direction cons to string * @param {constant} direction * @returns {String} diff --git a/src/recognizerjs/get-recognizer-by-name-if-manager.js b/src/recognizerjs/get-recognizer-by-name-if-manager.js index 2583cd9ee..395236c39 100644 --- a/src/recognizerjs/get-recognizer-by-name-if-manager.js +++ b/src/recognizerjs/get-recognizer-by-name-if-manager.js @@ -1,4 +1,5 @@ /** + * @private * get a recognizer by name if it is bound to a manager * @param {Recognizer|String} otherRecognizer * @param {Recognizer} recognizer diff --git a/src/recognizerjs/recognizer-constructor.js b/src/recognizerjs/recognizer-constructor.js index ff2d54a1d..c96ed24f9 100644 --- a/src/recognizerjs/recognizer-constructor.js +++ b/src/recognizerjs/recognizer-constructor.js @@ -17,6 +17,7 @@ import getRecognizerByNameIfManager from './get-recognizer-by-name-if-manager'; import stateStr from './state-str'; /** + * @private * Recognizer flow explained; * * All recognizers have the initial state of POSSIBLE when a input session starts. * The definition of a input session is from the first input until the last input, with all it's movement in it. * @@ -45,6 +46,7 @@ import stateStr from './state-str'; */ /** + * @private * Recognizer * Every recognizer needs to extend from this class. * @constructor @@ -68,12 +70,14 @@ function Recognizer(options) { Recognizer.prototype = { /** + * @private * @virtual * @type {Object} */ defaults: {}, /** + * @private * set options * @param {Object} options * @return {Recognizer} @@ -87,6 +91,7 @@ Recognizer.prototype = { }, /** + * @private * recognize simultaneous with an other recognizer. * @param {Recognizer} otherRecognizer * @returns {Recognizer} this @@ -106,6 +111,7 @@ Recognizer.prototype = { }, /** + * @private * drop the simultaneous link. it doesnt remove the link on the other recognizer. * @param {Recognizer} otherRecognizer * @returns {Recognizer} this @@ -121,6 +127,7 @@ Recognizer.prototype = { }, /** + * @private * recognizer can only run when an other is failing * @param {Recognizer} otherRecognizer * @returns {Recognizer} this @@ -130,7 +137,7 @@ Recognizer.prototype = { return this; } - let { requireFail }= this; + let { requireFail } = this; otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this); if (inArray(requireFail, otherRecognizer) === -1) { requireFail.push(otherRecognizer); @@ -140,6 +147,7 @@ Recognizer.prototype = { }, /** + * @private * drop the requireFailure link. it does not remove the link on the other recognizer. * @param {Recognizer} otherRecognizer * @returns {Recognizer} this @@ -158,6 +166,7 @@ Recognizer.prototype = { }, /** + * @private * has require failures boolean * @returns {boolean} */ @@ -166,6 +175,7 @@ Recognizer.prototype = { }, /** + * @private * if the recognizer can recognize simultaneous with an other recognizer * @param {Recognizer} otherRecognizer * @returns {Boolean} @@ -175,6 +185,7 @@ Recognizer.prototype = { }, /** + * @private * You should use `tryEmit` instead of `emit` directly to check * that all the needed recognizers has failed before emitting. * @param {Object} input @@ -205,6 +216,7 @@ Recognizer.prototype = { }, /** + * @private * Check that all the require failure recognizers has failed, * if true, it emits a gesture event, * otherwise, setup the state to FAILED. @@ -219,6 +231,7 @@ Recognizer.prototype = { }, /** + * @private * can we emit? * @returns {boolean} */ @@ -234,6 +247,7 @@ Recognizer.prototype = { }, /** + * @private * update the recognizer * @param {Object} inputData */ @@ -264,6 +278,7 @@ Recognizer.prototype = { }, /** + * @private * return the state of the recognizer * the actual recognizing happens in this method * @virtual @@ -273,6 +288,7 @@ Recognizer.prototype = { process: function(inputData) { }, // jshint ignore:line /** + * @private * return the preferred touch-action * @virtual * @returns {Array} @@ -280,6 +296,7 @@ Recognizer.prototype = { getTouchAction: function() { }, /** + * @private * called when the gesture isn't allowed to recognize * like when another is being recognized or it is disabled * @virtual diff --git a/src/recognizerjs/state-str.js b/src/recognizerjs/state-str.js index acf92f197..e37c58497 100644 --- a/src/recognizerjs/state-str.js +++ b/src/recognizerjs/state-str.js @@ -6,6 +6,7 @@ import { } from './recognizer-consts'; /** + * @private * get a usable string, used as event postfix * @param {constant} state * @returns {String} state diff --git a/src/recognizers/attribute.js b/src/recognizers/attribute.js index 33179d7e3..b2f0d8aba 100644 --- a/src/recognizers/attribute.js +++ b/src/recognizers/attribute.js @@ -13,6 +13,7 @@ import { } from '../inputjs/input-consts'; /** + * @private * This recognizer is just used as a base for the simple attribute recognizers. * @constructor * @extends Recognizer @@ -23,11 +24,13 @@ function AttrRecognizer() { inherit(AttrRecognizer, Recognizer, { /** + * @private * @namespace * @memberof AttrRecognizer */ defaults: { /** + * @private * @type {Number} * @default 1 */ @@ -35,6 +38,7 @@ inherit(AttrRecognizer, Recognizer, { }, /** + * @private * Used to check if it the recognizer receives valid input, like input.distance > 10. * @memberof AttrRecognizer * @param {Object} input @@ -46,6 +50,7 @@ inherit(AttrRecognizer, Recognizer, { }, /** + * @private * Process the input and return the state for the recognizer * @memberof AttrRecognizer * @param {Object} input diff --git a/src/recognizers/pan.js b/src/recognizers/pan.js index 4ba8476e0..cd6c78082 100644 --- a/src/recognizers/pan.js +++ b/src/recognizers/pan.js @@ -15,6 +15,7 @@ import { TOUCH_ACTION_PAN_X,TOUCH_ACTION_PAN_Y } from '../touchactionjs/touchact import directionStr from '../recognizerjs/direction-str'; /** + * @private * Pan * Recognized when the pointer is down and moved in the allowed direction. * @constructor @@ -29,6 +30,7 @@ function PanRecognizer() { inherit(PanRecognizer, AttrRecognizer, { /** + * @private * @namespace * @memberof PanRecognizer */ diff --git a/src/recognizers/pinch.js b/src/recognizers/pinch.js index 8b4b05675..affdb729a 100644 --- a/src/recognizers/pinch.js +++ b/src/recognizers/pinch.js @@ -4,6 +4,7 @@ import { TOUCH_ACTION_NONE } from '../touchactionjs/touchaction-Consts'; import { STATE_BEGAN } from '../recognizerjs/recognizer-consts'; /** + * @private * Pinch * Recognized when two or more pointers are moving toward (zoom-in) or away from each other (zoom-out). * @constructor @@ -15,6 +16,7 @@ function PinchRecognizer() { inherit(PinchRecognizer, AttrRecognizer, { /** + * @private * @namespace * @memberof PinchRecognizer */ diff --git a/src/recognizers/press.js b/src/recognizers/press.js index 77ab7c012..5a244a96c 100644 --- a/src/recognizers/press.js +++ b/src/recognizers/press.js @@ -14,6 +14,7 @@ import { } from '../inputjs/input-consts'; /** + * @private * Press * Recognized when the pointer is down for x ms without any movement. * @constructor @@ -28,6 +29,7 @@ function PressRecognizer() { inherit(PressRecognizer, Recognizer, { /** + * @private * @namespace * @memberof PressRecognizer */ diff --git a/src/recognizers/rotate.js b/src/recognizers/rotate.js index fa7a33c59..4733588a9 100644 --- a/src/recognizers/rotate.js +++ b/src/recognizers/rotate.js @@ -4,6 +4,7 @@ import { TOUCH_ACTION_NONE } from '../touchactionjs/touchaction-Consts'; import { STATE_BEGAN } from '../recognizerjs/recognizer-consts'; /** + * @private * Rotate * Recognized when two or more pointer are moving in a circular motion. * @constructor @@ -15,6 +16,7 @@ function RotateRecognizer() { inherit(RotateRecognizer, AttrRecognizer, { /** + * @private * @namespace * @memberof RotateRecognizer */ diff --git a/src/recognizers/swipe.js b/src/recognizers/swipe.js index 8f7206cb5..22795e7f2 100644 --- a/src/recognizers/swipe.js +++ b/src/recognizers/swipe.js @@ -7,6 +7,7 @@ import { INPUT_END } from '../inputjs/input-consts'; import directionStr from '../recognizerjs/direction-str'; /** + * @private * Swipe * Recognized when the pointer is moving fast (velocity), with enough distance in the allowed direction. * @constructor @@ -18,6 +19,7 @@ function SwipeRecognizer() { inherit(SwipeRecognizer, AttrRecognizer, { /** + * @private * @namespace * @memberof SwipeRecognizer */ diff --git a/src/recognizers/tap.js b/src/recognizers/tap.js index f14d49dba..ab2a248f0 100644 --- a/src/recognizers/tap.js +++ b/src/recognizers/tap.js @@ -11,6 +11,7 @@ import { import getDistance from '../inputjs/get-distance'; /** + * @private * A tap is recognized when the pointer is doing a small tap/click. Multiple taps are recognized if they occur * between the given interval and position. The delay option can be used to recognize multi-taps without firing * a single tap. @@ -35,6 +36,7 @@ function TapRecognizer() { inherit(TapRecognizer, Recognizer, { /** + * @private * @namespace * @memberof PinchRecognizer */ diff --git a/src/touchactionjs/clean-touch-actions.js b/src/touchactionjs/clean-touch-actions.js index a10e0563f..2244fd816 100644 --- a/src/touchactionjs/clean-touch-actions.js +++ b/src/touchactionjs/clean-touch-actions.js @@ -8,6 +8,7 @@ import { } from './touchaction-Consts'; /** + * @private * when the touchActions are collected they are not a valid value, so we need to clean things up. * * @param {String} actions * @returns {*} diff --git a/src/touchactionjs/touchaction-constructor.js b/src/touchactionjs/touchaction-constructor.js index 9c1167d87..51bc64ea7 100644 --- a/src/touchactionjs/touchaction-constructor.js +++ b/src/touchactionjs/touchaction-constructor.js @@ -17,6 +17,7 @@ import inStr from '../utils/in-str'; import cleanTouchActions from './clean-touch-actions'; /** + * @private * Touch Action * sets the touchAction property or uses the js alternative * @param {Manager} manager @@ -30,6 +31,7 @@ function TouchAction(manager, value) { TouchAction.prototype = { /** + * @private * set the touchAction value on the element or enable the polyfill * @param {String} value */ @@ -46,6 +48,7 @@ TouchAction.prototype = { }, /** + * @private * just re-set the touchAction value */ update: function() { @@ -53,6 +56,7 @@ TouchAction.prototype = { }, /** + * @private * compute the value for the touchAction property based on the recognizer's settings * @returns {String} value */ @@ -67,6 +71,7 @@ TouchAction.prototype = { }, /** + * @private * this method is called on each input cycle and provides the preventing of the browser behavior * @param {Object} input */ @@ -109,6 +114,7 @@ TouchAction.prototype = { }, /** + * @private * call preventDefault to prevent the browser's default behavior (scrolling in most cases) * @param {Object} srcEvent */ diff --git a/src/utils/add-event-listeners.js b/src/utils/add-event-listeners.js index 187503c5e..bbfad9ede 100644 --- a/src/utils/add-event-listeners.js +++ b/src/utils/add-event-listeners.js @@ -1,6 +1,7 @@ import each from './each'; import splitStr from './split-str'; /** + * @private * addEventListener with multiple events at once * @param {EventTarget} target * @param {String} types diff --git a/src/utils/assign.js b/src/utils/assign.js index aea814595..8cc50220a 100644 --- a/src/utils/assign.js +++ b/src/utils/assign.js @@ -1,4 +1,5 @@ /** + * @private * extend object. * means that properties in dest will be overwritten by the ones in src. * @param {Object} target diff --git a/src/utils/bind-fn.js b/src/utils/bind-fn.js index 204da767a..b915d84a6 100644 --- a/src/utils/bind-fn.js +++ b/src/utils/bind-fn.js @@ -1,4 +1,5 @@ /** + * @private * simple function bind * @param {Function} fn * @param {Object} context diff --git a/src/utils/bool-or-fn.js b/src/utils/bool-or-fn.js index fb0acf5ed..b57ebb517 100644 --- a/src/utils/bool-or-fn.js +++ b/src/utils/bool-or-fn.js @@ -1,5 +1,6 @@ import { TYPE_FUNCTION } from './utils-consts'; /** + * @private * let a boolean value also be a function that must return a boolean * this first item in args will be used as the context * @param {Boolean|Function} val diff --git a/src/utils/deprecate.js b/src/utils/deprecate.js index dab8fa78e..8f896375f 100644 --- a/src/utils/deprecate.js +++ b/src/utils/deprecate.js @@ -1,4 +1,5 @@ /** + * @private * wrap a method with a deprecation warning and stack trace * @param {Function} method * @param {String} name diff --git a/src/utils/each.js b/src/utils/each.js index e09b40116..dd124bb3a 100644 --- a/src/utils/each.js +++ b/src/utils/each.js @@ -1,4 +1,5 @@ /** + * @private * walk objects and arrays * @param {Object} obj * @param {Function} iterator diff --git a/src/utils/extend.js b/src/utils/extend.js index e8fc3cee0..0b41be4c5 100644 --- a/src/utils/extend.js +++ b/src/utils/extend.js @@ -1,5 +1,6 @@ import deprecate from './deprecate'; /** + * @private * extend object. * means that properties in dest will be overwritten by the ones in src. * @param {Object} dest diff --git a/src/utils/get-window-for-element.js b/src/utils/get-window-for-element.js index bf29c0476..f63cc409b 100644 --- a/src/utils/get-window-for-element.js +++ b/src/utils/get-window-for-element.js @@ -1,4 +1,5 @@ /** + * @private * get the window object of an element * @param {HTMLElement} element * @returns {DocumentView|Window} diff --git a/src/utils/has-parent.js b/src/utils/has-parent.js index 6264c7579..0e52d5329 100644 --- a/src/utils/has-parent.js +++ b/src/utils/has-parent.js @@ -1,4 +1,5 @@ /** + * @private * find if a node is in the given parent * @method hasParent * @param {HTMLElement} node diff --git a/src/utils/if-undefined.js b/src/utils/if-undefined.js index 95837eb0f..72ea9218d 100644 --- a/src/utils/if-undefined.js +++ b/src/utils/if-undefined.js @@ -1,4 +1,5 @@ /** + * @private * use the val2 when val1 is undefined * @param {*} val1 * @param {*} val2 diff --git a/src/utils/in-array.js b/src/utils/in-array.js index a61044137..11f7769e5 100644 --- a/src/utils/in-array.js +++ b/src/utils/in-array.js @@ -1,4 +1,5 @@ /** + * @private * find if a array contains the object using indexOf or a simple polyFill * @param {Array} src * @param {String} find @@ -11,7 +12,7 @@ export default function inArray(src, find, findByKey) { } else { let i = 0; while (i < src.length) { - if ((findByKey && src[i][findByKey] == find) || (!findByKey && src[i] === find)) { + if ((findByKey && src[i][findByKey] == find) || (!findByKey && src[i] === find)) {// do not use === here, test fails return i; } i++; diff --git a/src/utils/in-str.js b/src/utils/in-str.js index eeea7134e..c45fb4f32 100644 --- a/src/utils/in-str.js +++ b/src/utils/in-str.js @@ -1,4 +1,5 @@ /** + * @private * small indexOf wrapper * @param {String} str * @param {String} find diff --git a/src/utils/inherit.js b/src/utils/inherit.js index 929a63c79..1780b175d 100644 --- a/src/utils/inherit.js +++ b/src/utils/inherit.js @@ -1,5 +1,6 @@ import assign from './assign'; /** + * @private * simple class inheritance * @param {Function} child * @param {Function} base diff --git a/src/utils/invoke-array-arg.js b/src/utils/invoke-array-arg.js index 3ab56284e..7f909ab6c 100644 --- a/src/utils/invoke-array-arg.js +++ b/src/utils/invoke-array-arg.js @@ -1,5 +1,6 @@ import each from './each'; /** + * @private * if the argument is an array, we want to execute the fn on each entry * if it aint an array we don't want to do a thing. * this is used by all the methods that accept a single and array argument. diff --git a/src/utils/merge.js b/src/utils/merge.js index 8e5f4fd15..333df4f86 100644 --- a/src/utils/merge.js +++ b/src/utils/merge.js @@ -1,6 +1,7 @@ import deprecate from './deprecate'; import extend from './extend'; /** + * @private * merge the values from src in the dest. * means that properties that exist in dest will not be overwritten by src * @param {Object} dest diff --git a/src/utils/prefixed.js b/src/utils/prefixed.js index 80ef6e834..9f4fd2602 100644 --- a/src/utils/prefixed.js +++ b/src/utils/prefixed.js @@ -1,5 +1,6 @@ import { VENDOR_PREFIXES } from './utils-consts'; /** + * @private * get the prefixed property * @param {Object} obj * @param {String} property diff --git a/src/utils/remove-event-listeners.js b/src/utils/remove-event-listeners.js index 15c7de56e..56fa66484 100644 --- a/src/utils/remove-event-listeners.js +++ b/src/utils/remove-event-listeners.js @@ -1,6 +1,7 @@ import each from './each'; import splitStr from './split-str'; /** + * @private * removeEventListener with multiple events at once * @param {EventTarget} target * @param {String} types diff --git a/src/utils/set-timeout-context.js b/src/utils/set-timeout-context.js index 90279aa54..9f461bb46 100644 --- a/src/utils/set-timeout-context.js +++ b/src/utils/set-timeout-context.js @@ -1,6 +1,7 @@ import bindFn from './bind-fn'; /** + * @private * set a timeout with a given scope * @param {Function} fn * @param {Number} timeout diff --git a/src/utils/split-str.js b/src/utils/split-str.js index 7f73f6459..352e73fb6 100644 --- a/src/utils/split-str.js +++ b/src/utils/split-str.js @@ -1,4 +1,5 @@ /** + * @private * split string on whitespace * @param {String} str * @returns {Array} words diff --git a/src/utils/to-array.js b/src/utils/to-array.js index 8dad49f2a..8187e8326 100644 --- a/src/utils/to-array.js +++ b/src/utils/to-array.js @@ -1,4 +1,5 @@ /** + * @private * convert array-like objects to real arrays * @param {Object} obj * @returns {Array} diff --git a/src/utils/unique-array.js b/src/utils/unique-array.js index 9f445b360..de5144ce1 100644 --- a/src/utils/unique-array.js +++ b/src/utils/unique-array.js @@ -1,6 +1,7 @@ import inArray from './in-array'; /** + * @private * unique array with objects based on a key (like 'id') or just by the array's value * @param {Array} src [{id:1},{id:2},{id:1}] * @param {String} [key] diff --git a/src/utils/unique-id.js b/src/utils/unique-id.js index 0625b4adc..10916ab10 100644 --- a/src/utils/unique-id.js +++ b/src/utils/unique-id.js @@ -1,4 +1,5 @@ /** + * @private * get a unique id * @returns {number} uniqueId */ From 6da743d7ef21cefafa92fb75ddb3ccd32f87118d Mon Sep 17 00:00:00 2001 From: Arjun Kathuria Date: Tue, 14 Jun 2016 15:12:24 +0530 Subject: [PATCH 39/61] style(jscs requireEnhancedObjectLiterals): Resolves Property assignment should use enhanced object literal function. --- src/input/mouse.js | 2 +- src/input/pointerevent.js | 2 +- src/input/singletouch.js | 2 +- src/input/touch.js | 2 +- src/input/touchmouse.js | 4 +-- src/inputjs/input-constructor.js | 6 ++-- src/manager.js | 20 ++++++------- src/recognizerjs/recognizer-constructor.js | 31 +++++++++++--------- src/recognizers/attribute.js | 4 +-- src/recognizers/pan.js | 8 ++--- src/recognizers/pinch.js | 6 ++-- src/recognizers/press.js | 8 ++--- src/recognizers/rotate.js | 4 +-- src/recognizers/swipe.js | 6 ++-- src/recognizers/tap.js | 10 +++---- src/touchactionjs/touchaction-constructor.js | 10 +++---- 16 files changed, 64 insertions(+), 61 deletions(-) diff --git a/src/input/mouse.js b/src/input/mouse.js index 88e6cb92d..e537e74b8 100644 --- a/src/input/mouse.js +++ b/src/input/mouse.js @@ -37,7 +37,7 @@ inherit(MouseInput, Input, { * handle mouse events * @param {Object} ev */ - handler: function MEhandler(ev) { + handler(ev) { let eventType = MOUSE_INPUT_MAP[ev.type]; // on start we want to have the left mouse button down diff --git a/src/input/pointerevent.js b/src/input/pointerevent.js index 2852d2a5b..1298582de 100644 --- a/src/input/pointerevent.js +++ b/src/input/pointerevent.js @@ -58,7 +58,7 @@ inherit(PointerEventInput, Input, { * handle mouse events * @param {Object} ev */ - handler: function PEhandler(ev) { + handler(ev) { let { store } = this; let removePointer = false; diff --git a/src/input/singletouch.js b/src/input/singletouch.js index c8b4bdb05..2e12e5af0 100644 --- a/src/input/singletouch.js +++ b/src/input/singletouch.js @@ -35,7 +35,7 @@ function SingleTouchInput() { } inherit(SingleTouchInput, Input, { - handler: function TEhandler(ev) { + handler(ev) { let type = SINGLE_TOUCH_INPUT_MAP[ev.type]; // should we handle the touch events? diff --git a/src/input/touch.js b/src/input/touch.js index 1a660687d..5e3708b82 100644 --- a/src/input/touch.js +++ b/src/input/touch.js @@ -34,7 +34,7 @@ function TouchInput() { } inherit(TouchInput, Input, { - handler: function MTEhandler(ev) { + handler(ev) { let type = TOUCH_INPUT_MAP[ev.type]; let touches = getTouches.call(this, ev, type); if (!touches) { diff --git a/src/input/touchmouse.js b/src/input/touchmouse.js index 7621caad8..446325555 100644 --- a/src/input/touchmouse.js +++ b/src/input/touchmouse.js @@ -44,7 +44,7 @@ inherit(TouchMouseInput, Input, { * @param {String} inputEvent * @param {Object} inputData */ - handler: function TMEhandler(manager, inputEvent, inputData) { + handler(manager, inputEvent, inputData) { let isTouch = (inputData.pointerType === INPUT_TYPE_TOUCH); let isMouse = (inputData.pointerType === INPUT_TYPE_MOUSE); @@ -66,7 +66,7 @@ inherit(TouchMouseInput, Input, { * @private * remove the event listeners */ - destroy: function destroy() { + destroy() { this.touch.destroy(); this.mouse.destroy(); } diff --git a/src/inputjs/input-constructor.js b/src/inputjs/input-constructor.js index 180d0cabf..41c99ac89 100644 --- a/src/inputjs/input-constructor.js +++ b/src/inputjs/input-constructor.js @@ -36,13 +36,13 @@ Input.prototype = { * should handle the inputEvent data and trigger the callback * @virtual */ - handler: function() { }, + handler() { }, /** * @private * bind the events */ - init: function() { + init() { this.evEl && addEventListeners(this.element, this.evEl, this.domHandler); this.evTarget && addEventListeners(this.target, this.evTarget, this.domHandler); this.evWin && addEventListeners(getWindowForElement(this.element), this.evWin, this.domHandler); @@ -52,7 +52,7 @@ Input.prototype = { * @private * unbind the events */ - destroy: function() { + destroy() { this.evEl && removeEventListeners(this.element, this.evEl, this.domHandler); this.evTarget && removeEventListeners(this.target, this.evTarget, this.domHandler); this.evWin && removeEventListeners(getWindowForElement(this.element), this.evWin, this.domHandler); diff --git a/src/manager.js b/src/manager.js index aa091bb1c..cb2b602b1 100644 --- a/src/manager.js +++ b/src/manager.js @@ -55,7 +55,7 @@ Manager.prototype = { * @param {Object} options * @returns {Manager} */ - set: function(options) { + set(options) { assign(this.options, options); // Options that need a little more setup @@ -78,7 +78,7 @@ Manager.prototype = { * When forced, the recognizer cycle is stopped immediately. * @param {Boolean} [force] */ - stop: function(force) { + stop(force) { this.session.stopped = force ? FORCED_STOP : STOP; }, @@ -89,7 +89,7 @@ Manager.prototype = { * it walks through all the recognizers and tries to detect the gesture that is being made * @param {Object} inputData */ - recognize: function(inputData) { + recognize(inputData) { let { session } = this; if (session.stopped) { return; @@ -145,7 +145,7 @@ Manager.prototype = { * @param {Recognizer|String} recognizer * @returns {Recognizer|Null} */ - get: function(recognizer) { + get(recognizer) { if (recognizer instanceof Recognizer) { return recognizer; } @@ -165,7 +165,7 @@ Manager.prototype = { * @param {Recognizer} recognizer * @returns {Recognizer|Manager} */ - add: function(recognizer) { + add(recognizer) { if (invokeArrayArg(recognizer, 'add', this)) { return this; } @@ -189,7 +189,7 @@ Manager.prototype = { * @param {Recognizer|String} recognizer * @returns {Manager} */ - remove: function(recognizer) { + remove(recognizer) { if (invokeArrayArg(recognizer, 'remove', this)) { return this; } @@ -217,7 +217,7 @@ Manager.prototype = { * @param {Function} handler * @returns {EventEmitter} this */ - on: function(events, handler) { + on(events, handler) { if (events === undefined) { return; } @@ -239,7 +239,7 @@ Manager.prototype = { * @param {Function} [handler] * @returns {EventEmitter} this */ - off: function(events, handler) { + off(events, handler) { if (events === undefined) { return; } @@ -260,7 +260,7 @@ Manager.prototype = { * @param {String} event * @param {Object} data */ - emit: function(event, data) { + emit(event, data) { // we also want to trigger dom events if (this.options.domEvents) { triggerDomEvent(event, data); @@ -289,7 +289,7 @@ Manager.prototype = { * destroy the manager and unbinds all events * it doesn't unbind dom events, that is the user own responsibility */ - destroy: function() { + destroy() { this.element && toggleCssProps(this, false); this.handlers = {}; diff --git a/src/recognizerjs/recognizer-constructor.js b/src/recognizerjs/recognizer-constructor.js index c96ed24f9..3612c3cca 100644 --- a/src/recognizerjs/recognizer-constructor.js +++ b/src/recognizerjs/recognizer-constructor.js @@ -82,7 +82,7 @@ Recognizer.prototype = { * @param {Object} options * @return {Recognizer} */ - set: function(options) { + set(options) { assign(this.options, options); // also update the touchAction, in case something changed about the directions/enabled state @@ -96,7 +96,7 @@ Recognizer.prototype = { * @param {Recognizer} otherRecognizer * @returns {Recognizer} this */ - recognizeWith: function(otherRecognizer) { + recognizeWith(otherRecognizer) { if (invokeArrayArg(otherRecognizer, 'recognizeWith', this)) { return this; } @@ -116,7 +116,7 @@ Recognizer.prototype = { * @param {Recognizer} otherRecognizer * @returns {Recognizer} this */ - dropRecognizeWith: function(otherRecognizer) { + dropRecognizeWith(otherRecognizer) { if (invokeArrayArg(otherRecognizer, 'dropRecognizeWith', this)) { return this; } @@ -132,7 +132,7 @@ Recognizer.prototype = { * @param {Recognizer} otherRecognizer * @returns {Recognizer} this */ - requireFailure: function(otherRecognizer) { + requireFailure(otherRecognizer) { if (invokeArrayArg(otherRecognizer, 'requireFailure', this)) { return this; } @@ -152,7 +152,7 @@ Recognizer.prototype = { * @param {Recognizer} otherRecognizer * @returns {Recognizer} this */ - dropRequireFailure: function(otherRecognizer) { + dropRequireFailure(otherRecognizer) { if (invokeArrayArg(otherRecognizer, 'dropRequireFailure', this)) { return this; } @@ -170,7 +170,7 @@ Recognizer.prototype = { * has require failures boolean * @returns {boolean} */ - hasRequireFailures: function() { + hasRequireFailures() { return this.requireFail.length > 0; }, @@ -180,7 +180,7 @@ Recognizer.prototype = { * @param {Recognizer} otherRecognizer * @returns {Boolean} */ - canRecognizeWith: function(otherRecognizer) { + canRecognizeWith(otherRecognizer) { return !!this.simultaneous[otherRecognizer.id]; }, @@ -190,7 +190,7 @@ Recognizer.prototype = { * that all the needed recognizers has failed before emitting. * @param {Object} input */ - emit: function(input) { + emit(input) { let self = this; let { state } = this; @@ -222,7 +222,7 @@ Recognizer.prototype = { * otherwise, setup the state to FAILED. * @param {Object} input */ - tryEmit: function(input) { + tryEmit(input) { if (this.canEmit()) { return this.emit(input); } @@ -235,7 +235,7 @@ Recognizer.prototype = { * can we emit? * @returns {boolean} */ - canEmit: function() { + canEmit() { let i = 0; while (i < this.requireFail.length) { if (!(this.requireFail[i].state & (STATE_FAILED | STATE_POSSIBLE))) { @@ -251,7 +251,7 @@ Recognizer.prototype = { * update the recognizer * @param {Object} inputData */ - recognize: function(inputData) { + recognize(inputData) { // make a new copy of the inputData // so we can change the inputData without messing up the other recognizers let inputDataClone = assign({}, inputData); @@ -285,7 +285,10 @@ Recognizer.prototype = { * @param {Object} inputData * @returns {constant} STATE */ - process: function(inputData) { }, // jshint ignore:line + + /* jshint ignore:start */ + process(inputData) { }, + /* jshint ignore:end */ /** * @private @@ -293,7 +296,7 @@ Recognizer.prototype = { * @virtual * @returns {Array} */ - getTouchAction: function() { }, + getTouchAction() { }, /** * @private @@ -301,7 +304,7 @@ Recognizer.prototype = { * like when another is being recognized or it is disabled * @virtual */ - reset: function() { } + reset() { } }; export { Recognizer }; diff --git a/src/recognizers/attribute.js b/src/recognizers/attribute.js index b2f0d8aba..f1a7bca2f 100644 --- a/src/recognizers/attribute.js +++ b/src/recognizers/attribute.js @@ -44,7 +44,7 @@ inherit(AttrRecognizer, Recognizer, { * @param {Object} input * @returns {Boolean} recognized */ - attrTest: function(input) { + attrTest(input) { let optionPointers = this.options.pointers; return optionPointers === 0 || input.pointers.length === optionPointers; }, @@ -56,7 +56,7 @@ inherit(AttrRecognizer, Recognizer, { * @param {Object} input * @returns {*} State */ - process: function(input) { + process(input) { let { state } = this; let { eventType } = input; diff --git a/src/recognizers/pan.js b/src/recognizers/pan.js index cd6c78082..4edc00865 100644 --- a/src/recognizers/pan.js +++ b/src/recognizers/pan.js @@ -41,7 +41,7 @@ inherit(PanRecognizer, AttrRecognizer, { direction: DIRECTION_ALL }, - getTouchAction: function() { + getTouchAction() { let { options:{ direction } } = this; let actions = []; if (direction & DIRECTION_HORIZONTAL) { @@ -53,7 +53,7 @@ inherit(PanRecognizer, AttrRecognizer, { return actions; }, - directionTest: function(input) { + directionTest(input) { let { options } = this; let hasMoved = true; let { distance } = input; @@ -77,12 +77,12 @@ inherit(PanRecognizer, AttrRecognizer, { return hasMoved && distance > options.threshold && direction & options.direction; }, - attrTest: function(input) { + attrTest(input) { return AttrRecognizer.prototype.attrTest.call(this, input) && (this.state & STATE_BEGAN || (!(this.state & STATE_BEGAN) && this.directionTest(input))); }, - emit: function(input) { + emit(input) { this.pX = input.deltaX; this.pY = input.deltaY; diff --git a/src/recognizers/pinch.js b/src/recognizers/pinch.js index affdb729a..02e6c1901 100644 --- a/src/recognizers/pinch.js +++ b/src/recognizers/pinch.js @@ -26,16 +26,16 @@ inherit(PinchRecognizer, AttrRecognizer, { pointers: 2 }, - getTouchAction: function() { + getTouchAction() { return [TOUCH_ACTION_NONE]; }, - attrTest: function(input) { + attrTest(input) { return this._super.attrTest.call(this, input) && (Math.abs(input.scale - 1) > this.options.threshold || this.state & STATE_BEGAN); }, - emit: function(input) { + emit(input) { if (input.scale !== 1) { let inOut = input.scale < 1 ? 'in' : 'out'; input.additionalEvent = this.options.event + inOut; diff --git a/src/recognizers/press.js b/src/recognizers/press.js index 5a244a96c..f8ee3271e 100644 --- a/src/recognizers/press.js +++ b/src/recognizers/press.js @@ -40,11 +40,11 @@ inherit(PressRecognizer, Recognizer, { threshold: 9 // a minimal movement is ok, but keep it low }, - getTouchAction: function() { + getTouchAction() { return [TOUCH_ACTION_AUTO]; }, - process: function(input) { + process(input) { let { options } = this; let validPointers = input.pointers.length === options.pointers; let validMovement = input.distance < options.threshold; @@ -68,11 +68,11 @@ inherit(PressRecognizer, Recognizer, { return STATE_FAILED; }, - reset: function() { + reset() { clearTimeout(this._timer); }, - emit: function(input) { + emit(input) { if (this.state !== STATE_RECOGNIZED) { return; } diff --git a/src/recognizers/rotate.js b/src/recognizers/rotate.js index 4733588a9..e6d9ec4e4 100644 --- a/src/recognizers/rotate.js +++ b/src/recognizers/rotate.js @@ -26,11 +26,11 @@ inherit(RotateRecognizer, AttrRecognizer, { pointers: 2 }, - getTouchAction: function() { + getTouchAction() { return [TOUCH_ACTION_NONE]; }, - attrTest: function(input) { + attrTest(input) { return this._super.attrTest.call(this, input) && (Math.abs(input.rotation) > this.options.threshold || this.state & STATE_BEGAN); } diff --git a/src/recognizers/swipe.js b/src/recognizers/swipe.js index 22795e7f2..b78c1a726 100644 --- a/src/recognizers/swipe.js +++ b/src/recognizers/swipe.js @@ -31,11 +31,11 @@ inherit(SwipeRecognizer, AttrRecognizer, { pointers: 1 }, - getTouchAction: function() { + getTouchAction() { return PanRecognizer.prototype.getTouchAction.call(this); }, - attrTest: function(input) { + attrTest(input) { let { options:{ direction } } = this; let velocity; @@ -54,7 +54,7 @@ inherit(SwipeRecognizer, AttrRecognizer, { abs(velocity) > this.options.velocity && input.eventType & INPUT_END; }, - emit: function(input) { + emit(input) { let direction = directionStr(input.offsetDirection); if (direction) { this.manager.emit(this.options.event + direction, input); diff --git a/src/recognizers/tap.js b/src/recognizers/tap.js index ab2a248f0..e11a981e4 100644 --- a/src/recognizers/tap.js +++ b/src/recognizers/tap.js @@ -50,11 +50,11 @@ inherit(TapRecognizer, Recognizer, { posThreshold: 10 // a multi-tap can be a bit off the initial position }, - getTouchAction: function() { + getTouchAction() { return [TOUCH_ACTION_MANIPULATION]; }, - process: function(input) { + process(input) { let { options } = this; let validPointers = input.pointers.length === options.pointers; @@ -108,18 +108,18 @@ inherit(TapRecognizer, Recognizer, { return STATE_FAILED; }, - failTimeout: function() { + failTimeout() { this._timer = setTimeoutContext(function() { this.state = STATE_FAILED; }, this.options.interval, this); return STATE_FAILED; }, - reset: function() { + reset() { clearTimeout(this._timer); }, - emit: function() { + emit() { if (this.state === STATE_RECOGNIZED) { this._input.tapCount = this.count; this.manager.emit(this.options.event, this._input); diff --git a/src/touchactionjs/touchaction-constructor.js b/src/touchactionjs/touchaction-constructor.js index 51bc64ea7..79f417bd9 100644 --- a/src/touchactionjs/touchaction-constructor.js +++ b/src/touchactionjs/touchaction-constructor.js @@ -35,7 +35,7 @@ TouchAction.prototype = { * set the touchAction value on the element or enable the polyfill * @param {String} value */ - set: function(value) { + set(value) { // find out the touch-action by the event handlers if (value === TOUCH_ACTION_COMPUTE) { value = this.compute(); @@ -51,7 +51,7 @@ TouchAction.prototype = { * @private * just re-set the touchAction value */ - update: function() { + update() { this.set(this.manager.options.touchAction); }, @@ -60,7 +60,7 @@ TouchAction.prototype = { * compute the value for the touchAction property based on the recognizer's settings * @returns {String} value */ - compute: function() { + compute() { let actions = []; each(this.manager.recognizers, function(recognizer) { if (boolOrFn(recognizer.options.enable, [recognizer])) { @@ -75,7 +75,7 @@ TouchAction.prototype = { * this method is called on each input cycle and provides the preventing of the browser behavior * @param {Object} input */ - preventDefaults: function(input) { + preventDefaults(input) { let { srcEvent } = input; let direction = input.offsetDirection; @@ -118,7 +118,7 @@ TouchAction.prototype = { * call preventDefault to prevent the browser's default behavior (scrolling in most cases) * @param {Object} srcEvent */ - preventSrc: function(srcEvent) { + preventSrc(srcEvent) { this.manager.session.prevented = true; srcEvent.preventDefault(); } From 4d17e67c9b20152278f24c11fa5c44e61309e537 Mon Sep 17 00:00:00 2001 From: Chris Thoburn Date: Tue, 14 Jun 2016 21:35:27 -0500 Subject: [PATCH 40/61] working prototype --- .jscsrc | 3 +- addon/-private/gestures/inputs/input.js | 113 ++++-- addon/-private/gestures/inputs/mouse.js | 21 +- addon/-private/gestures/layer.js | 28 +- addon/-private/gestures/manager.js | 45 +- .../gestures/recognizers/vertical-pan.js | 49 ++- .../-private/gestures/streams/stream-event.js | 87 +++- addon/-private/gestures/streams/stream.js | 23 +- .../gestures/{ => utils}/detection.js | 8 +- addon/-private/gestures/utils/macro-task.js | 7 + .../gestures/utils/supports-passive.js | 13 + addon/components/history-outlet/component.js | 384 +++++++++++++++++- addon/components/history-outlet/template.hbs | 5 +- addon/services/history.js | 198 +++++++++ addon/styles/addon.scss | 53 ++- addon/utils/dom/append-cached-range.js | 14 + addon/utils/dom/append-range.js | 17 + addon/utils/dom/clone-range.js | 12 + addon/utils/dom/remove-range.js | 15 + app/components/history-outlet.js | 2 +- app/services/history.js | 1 + index.js | 53 ++- package.json | 1 + .../routes/components/swipe-box/component.js | 5 +- tests/dummy/app/routes/items/route.js | 8 + tests/dummy/app/routes/items/single/route.js | 2 +- tests/dummy/app/routes/items/template.hbs | 4 +- tests/dummy/app/styles/app.scss | 47 +++ tests/dummy/app/transitions.js | 5 +- tests/dummy/config/environment.js | 1 + tests/helpers/module-for-acceptance.js | 5 +- .../gesture-recognition-test.js | 15 +- tests/unit/services/history-test.js | 12 + 33 files changed, 1126 insertions(+), 130 deletions(-) rename addon/-private/gestures/{ => utils}/detection.js (81%) create mode 100644 addon/-private/gestures/utils/macro-task.js create mode 100644 addon/-private/gestures/utils/supports-passive.js create mode 100644 addon/services/history.js create mode 100644 addon/utils/dom/append-cached-range.js create mode 100644 addon/utils/dom/append-range.js create mode 100644 addon/utils/dom/clone-range.js create mode 100644 addon/utils/dom/remove-range.js create mode 100644 app/services/history.js create mode 100644 tests/unit/services/history-test.js diff --git a/.jscsrc b/.jscsrc index e24512d0a..da64c7db4 100644 --- a/.jscsrc +++ b/.jscsrc @@ -1,3 +1,4 @@ { - "preset": "ember-suave" + "preset": "ember-suave", + "disallowConstOutsideModuleScope": false } diff --git a/addon/-private/gestures/inputs/input.js b/addon/-private/gestures/inputs/input.js index bb2bcb7b9..ae7b395aa 100644 --- a/addon/-private/gestures/inputs/input.js +++ b/addon/-private/gestures/inputs/input.js @@ -10,10 +10,13 @@ export default class Input { this.handler = null; this.handlerStack = []; this.streaming = false; - this.hasPointer = false; + this.hasMoved = false; + this._nextEvent = undefined; this._handlers = { start: null, update: null, end: null, interrupt: null }; this.manager = manager; + + this.attach(); } _bind(name) { @@ -27,14 +30,15 @@ export default class Input { const { streams } = this; // splice existing streams - for (let s of streams) { - s.split(); + for (let i = 0; i < streams.length; i++) { + // console.log('splitting existing stream'); + streams[i].split(); } this.streaming = true; - this.hasPointer = true; streams.push(stream); + // console.log('opening new stream'); let streamEvent = stream.open({ x: event.clientX, y: event.clientY, @@ -47,58 +51,105 @@ export default class Input { } this.manager.recognize(this, streams, streamEvent); + + this._poll(); } - update(event) { - if (!this.streaming) { - return; + trigger(streamEvent) { + if (this.handler) { + this.handler.recognize(this, this.streams, streamEvent); + } else { + this.manager.recognize(this, this.streams, streamEvent); } + } + _update(event) { + // console.log('updating'); let { streams } = this; let [stream] = streams; + let streamEvent; - let streamEvent = stream.push({ - x: event.clientX, - y: event.clientY, - event - }); + if (!this.streaming) { + if (!this.handler) { + + } + // console.log('closing stream'); + streamEvent = stream.close({ + x: event.clientX, + y: event.clientY, + event + }); + + this.hasMoved = false; + this.trigger(streamEvent); + + let wasRecognizing = this.handler; + + this.handler = null; + + // vacate this stream + // console.log('removing stream'); + streams.pop(); + + if (wasRecognizing && !streams.length) { + this.manager.endInputRecognition(); + } - if (this.handler) { - this.handler.recognize(this, this.streams, streamEvent); } else { - this.manager.recognize(this, this.streams, streamEvent); + streamEvent = stream.push({ + x: event.clientX, + y: event.clientY, + event + }); + + this.trigger(streamEvent); } + } - _close(event) { - let { streams } = this; - let stream = streams.pop(); + _poll() { + return void requestAnimationFrame(() => { + let event = this._nextEvent; - this.streaming = false; + if (event) { + this._update(event); + this._nextEvent = undefined; + } - let streamEvent = stream.close({ - x: event.clientX, - y: event.clientY, - event + if (this.streaming) { + this._poll(); + } }); + } - if (this.handler) { - this.handler.recognize(this, this.streams, streamEvent); - this.handler = null; - } else { - this.manager.recognize(this, this.streams, streamEvent); + update(event) { + if (!this.streaming) { + return; + } + + this._nextEvent = event; + if (!this.hasMoved) { + this.hasMoved = true; + this._update(event); + } + } + + _close(event) { + if (this.streaming) { + // console.log('received close event'); + this.streaming = false; + this._nextEvent = event; } } end(event) { - if (this.hasPointer) { + if (this.streaming) { this._close(event); - this.hasPointer = false; } } interrupt(event) { - if (this.hasPointer) { + if (this.streaming) { this._close(event); } } diff --git a/addon/-private/gestures/inputs/mouse.js b/addon/-private/gestures/inputs/mouse.js index db736d76f..6b60842e9 100644 --- a/addon/-private/gestures/inputs/mouse.js +++ b/addon/-private/gestures/inputs/mouse.js @@ -1,4 +1,5 @@ import Input from './input'; +import SUPPORTS_PASSIVE from '../utils/supports-passive'; export default class MouseInput extends Input { @@ -8,10 +9,12 @@ export default class MouseInput extends Input { } const { element } = this; - element.addEventListener('mousedown', this._bind('start') , true); - element.addEventListener('mouseup', this._bind('end') , true); - element.addEventListener('mouseexit', this._bind('interrupt') , true); - element.addEventListener('mousemove', this._bind('update') , true); + let opts = SUPPORTS_PASSIVE ? { capture: true, passive: true } : true; + + element.addEventListener('mousedown', this._bind('start'), opts); + element.addEventListener('mouseup', this._bind('end'), opts); + element.addEventListener('mouseexit', this._bind('interrupt'), opts); + element.addEventListener('mousemove', this._bind('update'), opts); this.attached = true; } @@ -22,10 +25,12 @@ export default class MouseInput extends Input { } const { element, _handlers } = this; - element.removeEventListener('mousedown', _handlers.start , true); - element.removeEventListener('mouseup', _handlers.end , true); - element.removeEventListener('mouseexit', _handlers.interrupt , true); - element.removeEventListener('mousemove', _handlers.update , true); + let opts = SUPPORTS_PASSIVE ? { capture: true, passive: true } : true; + + element.removeEventListener('mousedown', _handlers.start, opts); + element.removeEventListener('mouseup', _handlers.end, opts); + element.removeEventListener('mouseexit', _handlers.interrupt, opts); + element.removeEventListener('mousemove', _handlers.update, opts); } } diff --git a/addon/-private/gestures/layer.js b/addon/-private/gestures/layer.js index fc311d6fe..6bc13fa0c 100644 --- a/addon/-private/gestures/layer.js +++ b/addon/-private/gestures/layer.js @@ -4,27 +4,43 @@ export default class Layer { constructor(element) { this.element = element; this.recognizers = []; - this.isRecognizing = false; + this._handlers = {}; } recognize(input, streams, streamEvent) { let { recognizers } = this; - for (let recognizer of recognizers) { + for (let i = 0; i < recognizers.length; i++) { + let recognizer = recognizers[i]; + if (recognizer.recognize(input, streams, streamEvent)) { - this.isRecognizing = true; input.handler = recognizer; - break; + return true; } } - return this.isRecognizing; + return false; } addRecognizer(recognizerInstance) { + recognizerInstance.layer = this; this.recognizers.push(recognizerInstance); } - emit() {} + emit(e) { + let { name, event } = e; + let handlers = (this._handlers['*'] || []).concat(this._handlers[name] || []); + + for (let i = 0; i < handlers.length; i++) { + handlers[i].call(null, e); + } + } + + on(event, handler) { + this._handlers[event] = this._handlers[event] || []; + this._handlers[event].push(handler); + } + + off() {} } diff --git a/addon/-private/gestures/manager.js b/addon/-private/gestures/manager.js index ee61ad4fd..cc95f30ff 100644 --- a/addon/-private/gestures/manager.js +++ b/addon/-private/gestures/manager.js @@ -1,24 +1,28 @@ -import { availableInputs } from './detection'; +import { availableInputs } from './utils/detection'; +import Ember from 'ember'; -const assign = Object.assign; +const assign = Ember.assign || Object.assign || Ember.merge; const DEFAULT_OPTIONS = { inputs: availableInputs() }; -const HANDLER_SYMBOL = Symbol('element-gesture-handler'); - export default class Manager { constructor(rootElement, options) { this.rootElement = rootElement || window; this.layers = new WeakMap(); + this._recognizedInputs = 0; + this.isRecognizing = false; this.inputs = {}; this.options = assign({}, DEFAULT_OPTIONS, options || {}); if (this.options.inputs) { - for (let i = 0; i < this.options.inputs.length; i++) { - let { name, InputClass } = this.options.inputs[i]; + let inputs = Object.keys(this.options.inputs); + + for (let i = 0; i < inputs.length; i++) { + let name = inputs[i]; + let InputClass = this.options.inputs[name]; this.registerInput(name, InputClass); } @@ -35,10 +39,31 @@ export default class Manager { while (layer) { if (layer.recognize(input, streams, streamEvent)) { + this.startInputRecognition(); break; } layer = layer.parent; } + + if (this.isRecognizing && streamEvent.name === 'end') { + this.endInputRecognition(); + } + } + + startInputRecognition() { + this._recognizedInputs++; + if (this._recognizedInputs === 1) { + this.isRecognizing = true; + document.body.setAttribute('gesture-no-touch', 'true'); + } + } + + endInputRecognition() { + this._recognizedInputs--; + if (this._recognizedInputs === 0) { + this.isRecognizing = false; + document.body.removeAttribute('gesture-no-touch'); + } } unregisterInput(name) { @@ -51,8 +76,10 @@ export default class Manager { } registerLayer(layer) { + layer.element.setAttribute('gesture-layer', true); this.layers.set(layer.element, layer); - layer.parent = this._findParentLayer(layer.element); + + layer.parent = this._findParentLayer(layer.element.parentNode); // insert into linked layer list if (layer.parent) { @@ -81,14 +108,14 @@ export default class Manager { _findParentLayer(element) { do { - if (element.hasAttribute('gesture-layer')) { + if (element && element.hasAttribute('gesture-layer')) { let layer = this.layers.get(element); if (layer) { return layer; } } - } while (element = element.parentNode); + } while (element && element !== document.body && (element = element.parentNode)); return null; } diff --git a/addon/-private/gestures/recognizers/vertical-pan.js b/addon/-private/gestures/recognizers/vertical-pan.js index f8958e4a2..d118f7471 100644 --- a/addon/-private/gestures/recognizers/vertical-pan.js +++ b/addon/-private/gestures/recognizers/vertical-pan.js @@ -5,21 +5,52 @@ export default class VerticalPan { constructor(options) { this.name = 'vertical-pan'; this.options = options; - this.layer = null; - this.inflow = []; + this.layer = undefined; + this.stream = undefined; this.isRecognizing = false; } + beginRecognizing(input, streams, streamEvent) { + this.isRecognizing = true; + + this.stream = streams[streams.length - 1]; + let { series } = this.stream; + + for (let i = 0; i < series.length; i++) { + this.relay(series[i]); + } + } + + relay(event) { + if (event.name === 'start') { + this.layer.emit({ name: 'panStart', event }); + + } else if (event.name === 'end') { + this.isRecognizing = false; + this.layer.emit({ name: 'panEnd', event }); + this.stream = undefined; + + } else if (event.totalX < 0 || event.prev.totalX < 0) { + this.layer.emit({ name: 'panLeft', event }); + + } else { + this.layer.emit({ name: 'panRight', event }); + } + } + + emit(name, event) { + this.layer.emit({ name, event }); + } + recognize(input, streams, streamEvent) { - if (this.isRecognizing || streamEvent.totalY === 0 && streamEvent.totalX !== 0) { - this.isRecognizing = true; - this.layer.emit({ - name: 'pan', - event: streamEvent - }); - console.log('vertical pan!', streamEvent); + if (this.isRecognizing) { + this.relay(streamEvent); + } else if (streamEvent.totalY === 0 && streamEvent.totalX !== 0) { + this.beginRecognizing(input, streams, streamEvent); } + + return this.isRecognizing; } } diff --git a/addon/-private/gestures/streams/stream-event.js b/addon/-private/gestures/streams/stream-event.js index 1c0a47086..ac6b49309 100644 --- a/addon/-private/gestures/streams/stream-event.js +++ b/addon/-private/gestures/streams/stream-event.js @@ -18,8 +18,10 @@ export default class StreamEvent { this.y = info.y; // deltas off of origin event - this.totalX = info.x - info.originX; - this.totalY = info.y - info.originY; + this.originX = prev ? (prev.originX || prev.x) : info.x; + this.originY = prev ? (prev.originY || prev.y) : info.y; + this.totalX = info.x - this.originX; + this.totalY = info.y - this.originY; // deltas off of last event this.dX = prev ? info.x - prev.x : 0; @@ -38,36 +40,81 @@ export default class StreamEvent { this.nextY = 0; } - getAcceleration() { + getAccelerationX() { const { dT, prev } = this; - const { vX, vY } = this.getVelocity(); - const { vX: _vX, vY: _vY } = prev; + const vX = this.getVelocityX(); + const { vX: _vX } = prev; + + return this.aX = (vX - _vX) / dT; + } + + getAccelerationY() { + const { dT, prev } = this; + const vY = this.getVelocityY(); + const { vY: _vY } = prev; + + return this.aY = (vY - _vY) / dT; + } - // acceleration - let aX = this.aX = (vX - _vX) / dT; - let aY = this.aY = (vY - _vY) / dT; + getAcceleration() { + const aX = this.getAccelerationX(); + const aY = this.getAccelerationY(); let acceleration = this.acceleration = Math.sqrt(aX * aX + aY * aY); return { aX, aY, acceleration }; } - getVelocity() { - const { dX, dY, dT } = this; + getVelocityX() { + const { dX, dT } = this; + + debugger; + + return this.vX = dX / dT; + } + + getVelocityY() { + const { dY, dT } = this; + + return this.vY = dY / dT; + } - let vX = this.vX = dX / dT; - let vY = this.vY = dY / dT; + getVelocity() { + const vX = this.getVelocityX(); + const vY = this.getVelocityY(); let velocity = this.velocity = Math.sqrt(vX * vX + vY * vY); return { vX, vY, velocity }; } - predict() { - const { aX, aY } = this.getAcceleration(); - const { x, y, vX, vY, dT } = this; + predictX() { + const aX = this.getAccelerationX(); + const { x, dX, vX, dT, totalX } = this; + + // distance = initial distance + velocity * time + 1/2 acceleration * time^2 + let nextDeltaX = Math.round((vX * dT) + (0.5 * aX * dT * dT)); + let nextdX = dX + nextDeltaX; + let nextX = x + nextDeltaX; + let nextTotalX = totalX + nextDeltaX; + + return this.nextX = { x: nextX, dX: nextdX, totalX: nextTotalX }; + } + + predictY() { + const aY = this.getAccelerationY(); + const { y, dY, vY, dT, totalY } = this; // distance = initial distance + velocity * time + 1/2 acceleration * time^2 - let nextX = this.nextX = x + (vX * dT) + (.5 * aX * dT * dT); - let nextY = this.nextY = y + (vY * dT) + (.5 * aY * dT * dT); + let nextDeltaY = Math.round((vY * dT) + (0.5 * aY * dT * dT)); + let nextdY = dY + nextDeltaY; + let nextY = y + nextDeltaY; + let nextTotalY = totalY + nextDeltaY; + + return this.nextY = { y: nextY, dY: nextdY, totalY: nextTotalY }; + } + + predict() { + const nextX = this.predictX(); + const nextY = this.predictY(); return { x: nextX, y: nextY }; } @@ -79,4 +126,10 @@ export default class StreamEvent { this.silenced = true; } + destroy() { + this.source = undefined; + this.prev = undefined; + this.element = undefined; + } + } diff --git a/addon/-private/gestures/streams/stream.js b/addon/-private/gestures/streams/stream.js index 80c7bbb92..87f74921b 100644 --- a/addon/-private/gestures/streams/stream.js +++ b/addon/-private/gestures/streams/stream.js @@ -1,10 +1,13 @@ import StreamEvent from './stream-event'; +import MacroTask from '../utils/macro-task'; export default class Stream { constructor() { this.segments = null; this.series = null; + this._isDestroyed = false; + this._isDestroying = false; this.active = false; } @@ -22,6 +25,7 @@ export default class Stream { } push(info) { + // Improve Chrome Performance if (this.segments.length > 1 || this.series.length > 2) { info.cancelable = false; } @@ -39,11 +43,15 @@ export default class Stream { let streamEvent = new StreamEvent('end', info, lastEvent); this.series.push(streamEvent); + + this._isDestroying = true; + new MacroTask(() => { this.destroy(); }); + return streamEvent; } silence() { - let [down, initial] = this.segments[0]; + let [[down, initial]] = this.segments; down.silence(); initial.silence(); @@ -54,4 +62,17 @@ export default class Stream { this.segments.push(this.series); } + destroy() { + if (!this._isDestroyed) { + this._isDestroyed = true; + this.series = undefined; + for (let i = 0; i < this.segments.length; i++) { + for (let j = 0; j < this.segments[i].length; j++) { + this.segments[i][j].destroy(); + } + } + this.segments = undefined; + } + } + } diff --git a/addon/-private/gestures/detection.js b/addon/-private/gestures/utils/detection.js similarity index 81% rename from addon/-private/gestures/detection.js rename to addon/-private/gestures/utils/detection.js index ce72ac7f9..eb1b28baf 100644 --- a/addon/-private/gestures/detection.js +++ b/addon/-private/gestures/utils/detection.js @@ -1,13 +1,13 @@ /* global navigator, window */ -import TouchInput from './inputs/touch'; -import MouseInput from './inputs/mouse'; +import TouchInput from './../inputs/touch'; +import MouseInput from './../inputs/mouse'; // import PointerInput from './inputs/pointer'; const MAY_SUPPORT_TOUCH = (('ontouchstart' in window) || // html5 browsers (navigator.maxTouchPoints > 0) || // future IE (navigator.msMaxTouchPoints > 0)); // current IE10 -const MAY_SUPPORT_MOUSE = !!('onmousemove' in window); +const MAY_SUPPORT_MOUSE = true; // const SUPPORT_POINTER_EVENTS = prefixed(window, 'PointerEvent') !== undefined; @@ -27,6 +27,6 @@ function availableInputs() { export { availableInputs -} +}; export default availableInputs; diff --git a/addon/-private/gestures/utils/macro-task.js b/addon/-private/gestures/utils/macro-task.js new file mode 100644 index 000000000..b4bbec27c --- /dev/null +++ b/addon/-private/gestures/utils/macro-task.js @@ -0,0 +1,7 @@ +export default class MacroTask { + + constructor(job) { + setTimeout(job, 0); + } + +} diff --git a/addon/-private/gestures/utils/supports-passive.js b/addon/-private/gestures/utils/supports-passive.js new file mode 100644 index 000000000..3a9e6df05 --- /dev/null +++ b/addon/-private/gestures/utils/supports-passive.js @@ -0,0 +1,13 @@ +let supportsPassive = false; + +try { + let opts = Object.defineProperty({}, 'passive', { + get() { + supportsPassive = true; + } + }); + + window.addEventListener('test', null, opts); +} catch (e) {} + +export default supportsPassive; diff --git a/addon/components/history-outlet/component.js b/addon/components/history-outlet/component.js index c5cd1ab08..8b19ce372 100644 --- a/addon/components/history-outlet/component.js +++ b/addon/components/history-outlet/component.js @@ -1,41 +1,306 @@ +/* global Linear */ import Ember from 'ember'; -import layout from 'history-outlet'; +import layout from './template'; import Layer from 'history/-private/gestures/layer'; import VerticalPan from 'history/-private/gestures/recognizers/vertical-pan'; +import TweenLite from 'tweenlite'; +import removeRange from 'history/utils/dom/remove-range'; +import appendRange from 'history/utils/dom/append-range'; const { inject, - Component + computed, + Component, + RSVP } = Ember; +const assign = Ember.assign || Object.assign || Ember.merge; + +function tween(element, time, options) { + return new Promise(function(resolve) { + options.onComplete = resolve; + TweenLite.to(element, time / 1000, options); + }); +} + +function carryMomentum(element, duration, options) { + let opts = assign({ ease: Linear.easeOut }, options); + + return tween(element, duration, opts); +} + +function getDuration(streamEvent, width) { + return (width - Math.abs(streamEvent.totalX)) * 5; +} + +function updateStyle(element, css) { + let options = { immediateRender: true, css }; + + TweenLite.set(element, options); +} + export default Component.extend({ layout, tagName: 'history-outlet', - _left: null, - _main: null, - _right: null, - _outlet: null, + + _left: undefined, + _main: undefined, + _right: undefined, + _outlet: undefined, gestures: inject.service('gesture-recognition'), + history: inject.service('history'), + + transitionAt: 0.5, + parallax: 0.2, + _leftDefault: undefined, + _rightDefault: undefined, + duration: 350, + width: 0, + + _isTransitioning: false, + + currentRouteName: '', + activeRouteName: computed.alias('history.currentRouteName'), + + canGoBack: computed('history.stack.lastObject', function() { + let last = this.get('history.stack.lastObject'); + let routeName = this.get('currentRouteName'); + + return !!last && last.routeName.indexOf(routeName) === 0; + }), + + canGoForward: computed('history.seen.lastObject', function() { + let next = this.get('history.seen.lastObject'); + let routeName = this.get('currentRouteName'); + + return !!next && next.routeName.indexOf(routeName) === 0; + }), + + // fps meter + debugMode: true, + _lastTime: undefined, + _frames: undefined, + fps: 0, + avg: 0, + _emulateSlowdown: false, + low: 0, + + _fpsMeter() { + requestAnimationFrame((time) => { + let diff = (time - this._lastTime) / 1000; + let fps = Math.round(1 / diff); + + let frames = this._frames = this._frames || []; + + frames.push({ + delta: diff, + fps: fps + }); + + if (frames.length > 60) { + frames.shift(); + } + + this._lastTime = time; + + let low = { fps: 60 }; + let avg = Math.round( + frames.reduce((v, f) => { + if (f.fps < low.fps) { + low = f; + } + + return v + f.fps; + }, 0) / frames.length + ); + + if (low.fps < 60) { + console.log(low.fps, Math.round(low.delta * 1000), frames); + this._frames = []; + } + + this.setProperties({ + fps, + avg, + low: low.fps + }); + + this._fpsMeter() + }) + }, + + + panStart(e) { + this.width = this._main.clientWidth; + this.updateAnimationState(e.totalX); + }, + + panEnd(e) { + this.resolveAnimationState(e); + }, + + panLeft(e) { + this.updateAnimationState(e.totalX); + }, + + panRight(e) { + this.updateAnimationState(e.totalX); + }, + + transition(isLeft) { + const history = this.get('history'); + + return isLeft ? history.back() : history.forward(); + }, + + updateAnimationState(dX) { + let availableNav = this.getProperties('canGoBack', 'canGoForward'); + let { parallax } = this; + let scaledDeltaX = dX * parallax; + let isLeft = dX > 0; - pan() { - console.log('pan!'); + if (isLeft && availableNav.canGoBack) { + + updateStyle(this._left, { x: scaledDeltaX, visibility: 'visible' }); + updateStyle(this._right, { x: this._rightDefault, visibility: 'hidden' }); + + } else if (!isLeft && availableNav.canGoForward) { + let inverseDeltaX = dX * (1 - parallax); + + updateStyle(this._right, { x: inverseDeltaX, visibility: 'visible' }); + updateStyle(this._left, { x: this._leftDefault, visibility: 'hidden' }); + } else { + return; + } + + updateStyle(this._main, { x: dX }); + updateStyle(this._outlet, { x: dX }); + }, + + resolveAnimationState(event) { + let dX = event.totalX; + let { width, transitionAt, duration } = this; + let percentComplete = dX / width; + let absCompleted = Math.abs(percentComplete); + let remainingTime = (1 - absCompleted) * duration; + let isFromLeft = percentComplete > 0; + let availableNav = this.getProperties('canGoBack', 'canGoForward'); + + if (absCompleted >= transitionAt) { + if (isFromLeft && !availableNav.canGoBack) { + return this._cleanupAnimation(remainingTime); + } + + if (!isFromLeft && !availableNav.canGoForward) { + return this._cleanupAnimation(remainingTime); + } + + let outletClone = this._outlet.cloneNode(true); + let outDuration = getDuration(event, width); + + appendRange(this._main, outletClone.firstChild, outletClone.lastChild); + + this._outlet.style.display = 'none'; + this._outlet.style.visibility = 'hidden'; + updateStyle(this._outlet, { x: '0%' }); + + this._isTransitioning = true; + let outlet = this.element.removeChild(this._outlet); + let promises = [this.transition(isFromLeft)]; + + if (isFromLeft) { + promises.push( + carryMomentum(this._left, outDuration, { x: '0%' }), + carryMomentum(this._main, outDuration, { x: '100%' }) + ); + } else { + promises.push( + carryMomentum(this._right, outDuration, { x: '0%' }), + carryMomentum(this._main, outDuration, { x: '-100%' }) + ); + } + + return RSVP.all(promises) + .finally(() => { + this.element.insertBefore(outlet, this.element.lastElementChild); + outlet.style.display = ''; + outlet.style.visibility = ''; + + return this.resetTweens(false) + .then(() => { + if (this._main.firstChild) { + removeRange(this._main.firstChild, this._main.lastChild); + } + + this._finishTransition( + this.get('history').getProperties('current', 'next', 'previous') + ); + this._isTransitioning = false; + }); + }); + } + + return this._cleanupAnimation(remainingTime); + }, + + _cleanupAnimation(remainingTime) { + return this.resetTweens(remainingTime) + .then(() => { + if (this._main.firstChild) { + removeRange(this._main.firstChild, this._main.lastChild); + } + }); }, - panStart() { - console.log('pan start'); + _finishTransition(nextState) { + let previous = this.domFor(nextState.previous, 'previous'); + let next = this.domFor(nextState.next, 'next'); + + this._left.innerHTML = ''; + this._right.innerHTML = ''; + + if (previous) { + appendRange(this._left, previous.firstChild, previous.lastChild); + } + if (next) { + appendRange(this._right, next.firstChild, next.lastChild); + } }, - panLeft() { - console.log('pan left'); + resetTweens(duration) { + if (duration) { + return RSVP.all([ + tween(this._left, duration, { x: this._leftDefault }), + tween(this._main, duration, { x: 0 }), + tween(this._outlet, duration, { x: 0 }), + tween(this._right, duration, { x: this._rightDefault }) + ]); + } + + updateStyle(this._right, { x: this._rightDefault, visibility: 'hidden' }); + updateStyle(this._left, { x: this._leftDefault, visibility: 'hidden' }); + updateStyle(this._main, { x: '0%' }); + updateStyle(this._outlet, { x: '0%' }); + + return Promise.resolve(); }, - panRight() { - console.log('pan right'); + domForPrevious() { + let e = this.get('history'); + let t = this.get('currentRouteName'); + let r = e.get('previous'); + let n = e.segmentFor(t, r); + + return n ? n.dom.cloneNode(true) : false; }, - panEnd() { - console.log('pan end'); + domFor(e) { + let t = this.get('history'); + let r = this.get('currentRouteName'); + let n = t.segmentFor(r, e); + + return n ? n.dom.cloneNode(true) : false; }, willInsertElement() { @@ -45,10 +310,18 @@ export default Component.extend({ this._outlet = this.element.children[3]; }, + willDestroyElement() { + this._super(); + this._left = undefined; + this._main = undefined; + this._right = undefined; + this._outlet = undefined; + }, + setupLayer() { - this.layer = new Layer(this.element); + this.layer = new Layer(); this.layer.addRecognizer(new VerticalPan()); - this.layer.on('*', ({name, event}) => { + this.layer.on('*', ({ name, event }) => { if (this[name]) { this[name](event); } @@ -56,12 +329,87 @@ export default Component.extend({ }, didInsertElement() { + this.layer.element = this.element; this.get('gestures.manager').registerLayer(this.layer); + this.resetTweens(); }, init() { this._super(); this.setupLayer(); + let leftPer = (this.parallax * 100).toFixed(2); + let rightPer = 100 - leftPer; + + this._leftDefault = `-${leftPer}%`; + this._rightDefault = `${rightPer}%`; + + this.get('history').on('didTransition', (nextState) => { + if (!this._isTransitioning) { + this._finishTransition(nextState); + } + }); + + this.get('history').on('willTransition', (t) => { + // debugger; + }); + + this._fpsMeter(); } }); + +/* + var l = function() { + function e(e, t) { + var r = [], + n = true, + i = false, + a = void 0; + try { + for (var o, s = e[Symbol.iterator](); !(n = (o = s.next()).done) && (r.push(o.value), !t || r.length !== t); n = !0); + } catch (l) { + i = true, a = l + } finally { + try { + !n && s['return'] && s['return']() + } finally { + if (i) throw a + } + } + return r + } + return function(t, r) { + if (Array.isArray(t)) return t; + if (Symbol.iterator in Object(t)) return e(t, r); + throw new TypeError("Invalid attempt to destructure non-iterable instance") + } + }(); +*/ +/* + { + + _fpsMeter: function () { + var e = this; + 60 === this._frames.length && (window._frames = window._frames || [], window._frames.push(this._frames), window._frames.length > 15 && window._frames.shift(), this._frames = []), requestAnimationFrame(function (t) { + var r = (t - e._lastTime) / 1e3, + n = Math.round(1 / r); + e._frames.push({ + delta: r, + fps: n + }), e._lastTime = t; + var i = n; + if (e._frames.length > 5) { + var a = e._frames.slice(-6), + o = l(a, 6), + s = o[0], + u = o[1], + c = o[2], + d = o[3], + f = o[4], + h = o[5]; + i = (s.fps + u.fps + c.fps + d.fps + f.fps + h.fps) / 6 + } + e.set('fps', n), e.set('avg', i), e._fpsMeter() + }) + } +*/ diff --git a/addon/components/history-outlet/template.hbs b/addon/components/history-outlet/template.hbs index 4b271b25c..e17ba6cca 100644 --- a/addon/components/history-outlet/template.hbs +++ b/addon/components/history-outlet/template.hbs @@ -3,5 +3,8 @@ {{outlet}} {{#if debugMode}} - {{debug.fps}} / {{debug.avg}}fps + + (current | avg | low)
+ {{fps}} | {{avg}} | {{low}} fps +
{{/if}} diff --git a/addon/services/history.js b/addon/services/history.js new file mode 100644 index 000000000..37423af9c --- /dev/null +++ b/addon/services/history.js @@ -0,0 +1,198 @@ +import Ember from 'ember'; +import cloneRange from 'history/utils/dom/clone-range'; + +const { + A, + computed, + inject, + Service, + Evented + } = Ember; + +const { + Promise // jshint ignore:line + } = Ember.RSVP; + +const UNKNOWN_SEGMENT = false; +let STACK_ID = 0; + +export default Service.extend(Evented, { + routing: inject.service('-routing'), + router: computed.alias('routing.router'), + + cache: undefined, + stack: undefined, + seen: undefined, + _isHistoryOperation: false, + _nextState: undefined, + + previous: computed.alias('stack.lastObject'), + next: computed.alias('seen.lastObject'), + current: undefined, + + back() { + console.log('\n <=== BACK\n'); + let t = this.get('stack').get('lastObject'); + let r = this.get('current'); + + if (t) { + this._isHistoryOperation = !0; + this._nextState = { + next: r, + current: t, + previous: undefined + }; + + return this.get('router').transitionTo(t.url) + .finally(() => { + this._nextState = undefined; + this._isHistoryOperation = false; + console.log('________ COMPLETE???? ________'); + }); + } + + return Promise.reject('no history present'); + }, + + forward() { + console.log('\n FORWARD ===>\n'); + let t = this.get('seen.lastObject'); + let r = this.get('current'); + + if (t) { + this._isHistoryOperation = true; + this._nextState = { + previous: r, + current: t, + next: undefined + }; + + return this.get('router').transitionTo(t.url) + .finally(() => { + this._nextState = undefined; + this._isHistoryOperation = false; + }); + } + + return Promise.reject('no forward history present'); + }, + + segmentFor(e, t) { + if (!t || !t.segments) { + return UNKNOWN_SEGMENT; + } + + let r = t.segments.get(`${e}-main`); + + return r ? r.child || r : UNKNOWN_SEGMENT; + }, + + actions: { + + back() { + return this.back(); + }, + + forward() { + return this.forward(); + } + + }, + + init() { + function __someIterativeMethod(iterable) { + let r = new Map(); + let n = null; + + iterable.forEach(function(iteratedItem) { + let i = iteratedItem._state.outletState.render; + let a = `${i.name}-${i.outlet}`; + let o = { + name: i.name, + outlet: i.outlet, + key: a, + dom: __someClonedRange(iteratedItem), + parent: n, + child: null + }; + + if (n) { + n.child = o; + } + + n = o; + r.set(a, o); + + }); + + return r; + } + + function __someClonedRange(element) { + let t = cloneRange('outlet-segment', element.firstNode, element.lastNode); + + t.id = STACK_ID++; + return t; + } + + this._super(); + + this.set('stack', new A([])); + this.set('cache', new Map()); + this.set('seen', new A([])); + + const router = this.get('router'); + + router.on('willTransition', () => { + let t = this.get('current'); + + if (t) { + t.segments = __someIterativeMethod(router._toplevelView._outlets); + this.get('cache').set(t.url, t); + } + }); + + router.on('didTransition', () => { + if (this._isHistoryOperation) { + let nextState = this._nextState; + + if (nextState.previous) { + this.get('seen').popObject(); + this.set('current', nextState.current); + this.get('stack').pushObject(nextState.previous); + } else { + this.get('stack').popObject(); + this.set('current', nextState.current); + this.get('seen').pushObject(nextState.next); + } + + this.trigger( + 'didTransition', + this.getProperties('previous', 'next', 'current') + ); + + } else { + let t = router.get('_location') || router.get('location'); + let r = t.lastSetURL || router.get('url'); + let n = this.get('current'); + let i = { + url: r, + routeName: router.currentRouteName + }; + + this.set('current', i); + this.get('seen').clear(); + + if (n) { + this.get('stack').pushObject(n); + } + + this.trigger('didTransition', { + previous: n, + current: i, + next: undefined + }); + } + }); + } +}); diff --git a/addon/styles/addon.scss b/addon/styles/addon.scss index 273700db8..64a17ec17 100644 --- a/addon/styles/addon.scss +++ b/addon/styles/addon.scss @@ -4,7 +4,7 @@ touch-action: none; } -.gesture-no-touch { +[gesture-no-touch] { @include off(); * { @@ -15,30 +15,48 @@ @mixin fillBlock($position: absolute) { width: 100%; height: 100%; + min-height: 100%; top: 0; left: 0; position: $position; - display: block; + display: flex; + box-sizing: border-box; } @mixin willChange($start: 0) { will-change: transform; - transform: translateX($start); + transform: matrix(1, 0, 0, 1, 0, 0); +} + +@mixin clearfix() { + &:after { + display: block; + content: ' '; + width: 100%; + height: 0; + clear: both; + float: none; + position: relative; + } } history-outlet { - @include fillBlock('relative'); + @include fillBlock(); + @include clearfix(); + overflow:hidden; left { @include fillBlock(); z-index: 0; - willChange(-20%); + @include willChange(); + visibility: hidden; } right { @include fillBlock(); z-index: 0; - @include willChange(80%); + @include willChange(); + visibility: hidden; } main { @@ -51,9 +69,30 @@ history-outlet { @include fillBlock(); z-index: 1; @include willChange(); + @include clearfix(); } fps { - @include fillBlock(); + display: block; + position: fixed; + top: 0; + right: 0; + font-size: 0.75em; + background: rgba(255,255,255,.8); + padding: 0.5em; + margin: 0.5em; + text-align: center; + line-height: 2em; + width: 8em; + border-radius: 1em; + border: 1px solid #777; + z-index: 4 } } + +viewport { + display:block; + position:absolute; + width:100vw; + min-height:100vh +} diff --git a/addon/utils/dom/append-cached-range.js b/addon/utils/dom/append-cached-range.js new file mode 100644 index 000000000..61bd0d22a --- /dev/null +++ b/addon/utils/dom/append-cached-range.js @@ -0,0 +1,14 @@ +export default function appendCachedRange(element, range) { + const currentActiveElement = document.activeElement; + let referenceNode = element.lastChild || element.lastNode; + let parentNode = referenceNode ? referenceNode.parentNode : element; + + for (let i = 0; i < range.length; i++) { + parentNode.insertBefore(range[i], referenceNode); + } + + // reset focus + if (document.activeElement !== currentActiveElement) { + currentActiveElement.focus(); + } +}; diff --git a/addon/utils/dom/append-range.js b/addon/utils/dom/append-range.js new file mode 100644 index 000000000..6b17cb08a --- /dev/null +++ b/addon/utils/dom/append-range.js @@ -0,0 +1,17 @@ +export default function appendRange(element, firstNode, lastNode) { + const currentActiveElement = document.activeElement; + let referenceNode = element.lastChild || element.lastNode; + let parentNode = referenceNode ? referenceNode.parentNode : element; + let nextNode; + + while (firstNode) { + nextNode = firstNode.nextSibling; + parentNode.insertBefore(firstNode, referenceNode); + firstNode = firstNode !== lastNode ? nextNode : null; + } + + // reset focus + if (document.activeElement !== currentActiveElement) { + currentActiveElement.focus(); + } +}; diff --git a/addon/utils/dom/clone-range.js b/addon/utils/dom/clone-range.js new file mode 100644 index 000000000..c0e7dcc96 --- /dev/null +++ b/addon/utils/dom/clone-range.js @@ -0,0 +1,12 @@ +export default function cloneRange(tagName, firstNode, lastNode) { + const parent = document.createElement(tagName); + let nextNode; + + while (firstNode) { + nextNode = firstNode.nextSibling; + parent.appendChild(firstNode.cloneNode(true)); + firstNode = firstNode !== lastNode ? nextNode : null; + } + + return parent; +}; diff --git a/addon/utils/dom/remove-range.js b/addon/utils/dom/remove-range.js new file mode 100644 index 000000000..124da8cbf --- /dev/null +++ b/addon/utils/dom/remove-range.js @@ -0,0 +1,15 @@ +export default function removeRange(firstNode, lastNode) { + let node = lastNode; + + do { + let next = node.previousSibling; + + if (node.parentNode) { + node.parentNode.removeChild(node); + if (node === firstNode) { + break; + } + } + node = next; + } while (node); +} diff --git a/app/components/history-outlet.js b/app/components/history-outlet.js index dee074fa5..9b08ba1d4 100644 --- a/app/components/history-outlet.js +++ b/app/components/history-outlet.js @@ -1 +1 @@ -export { default } from 'history/components/history-outlet'; \ No newline at end of file +export { default } from 'history/components/history-outlet/component'; diff --git a/app/services/history.js b/app/services/history.js new file mode 100644 index 000000000..0fbc6a524 --- /dev/null +++ b/app/services/history.js @@ -0,0 +1 @@ +export { default } from 'history/services/history'; diff --git a/index.js b/index.js index 026832032..08dd9ca84 100644 --- a/index.js +++ b/index.js @@ -1,6 +1,55 @@ -/* jshint node: true */ +/* jshint node:true */ +/* global module, process */ 'use strict'; module.exports = { - name: 'history' + name: 'history', + + included: function(app, parentAddon) { + this._super.included.apply(this, arguments); + + // Quick fix for add-on nesting + // https://github.com/aexmachina/ember-cli-sass/blob/v5.3.0/index.js#L73-L75 + // see: https://github.com/ember-cli/ember-cli/issues/3718 + while (typeof app.import !== 'function' && (app.app || app.parent)) { + app = app.app || app.parent; + } + + // if app.import and parentAddon are blank, we're probably being consumed by an in-repo-addon + // or engine, for which the "bust through" technique above does not work. + if (typeof app.import !== 'function' && !parentAddon) { + if (app.registry && app.registry.app) { + app = app.registry.app; + } + } + + if (!parentAddon && typeof app.import !== 'function') { + throw new Error('ember-history is being used within another addon or engine and is' + + ' having trouble registering itself to the parent application.'); + } + + this.importDependencies(app); + }, + + isDevelopingAddon: function() { + return true; + }, + + importDependencies: function(app) { + if (arguments.length < 1) { + throw new Error('Application instance must be passed to import'); + } + + var vendor = this.treePaths.vendor; + + if (!process.env.EMBER_CLI_FASTBOOT) { + if (app.env === "production") { + app.import(app.bowerDirectory + '/gsap/src/minified/plugins/CSSPlugin.min.js', { prepend: true }); + } else { + app.import(app.bowerDirectory + '/gsap/src/uncompressed/plugins/CSSPlugin.js', { prepend: true }); + } + } + + app.import(vendor + '/shims/tweenlite.js'); + } }; diff --git a/package.json b/package.json index 99c0d0c20..88d9c6894 100644 --- a/package.json +++ b/package.json @@ -39,6 +39,7 @@ "ember-hammertime": "^1.0.3", "ember-load-initializers": "^0.5.1", "ember-resolver": "^2.0.3", + "ember-suave": "^2.0.1", "ember-tweenlite": "1.0.1", "express": "^4.13.4", "faker": "^3.1.0", diff --git a/tests/dummy/app/routes/components/swipe-box/component.js b/tests/dummy/app/routes/components/swipe-box/component.js index acb751b6f..acfc3ee6e 100644 --- a/tests/dummy/app/routes/components/swipe-box/component.js +++ b/tests/dummy/app/routes/components/swipe-box/component.js @@ -1,3 +1,4 @@ +/* global requestAnimationFrame */ import Ember from 'ember'; import layout from './template'; import RecognizerMixin from 'ember-gestures/mixins/recognizers'; @@ -25,7 +26,7 @@ export default Ember.Component.extend(RecognizerMixin, { updateAnimationState() { let { _dX, dX, element } = this; - TweenLite.set(element, { css: { x: `${_dX + dX}px` }}); + TweenLite.set(element, { css: { x: `${_dX + dX}px` } }); if (this.isPanning) { this._nextUpdate = requestAnimationFrame(() => { @@ -35,7 +36,7 @@ export default Ember.Component.extend(RecognizerMixin, { // this._dX = _dX + dX; this._nextUpdate = undefined; - TweenLite.to(element, .35, { css: { x: `0px` }}); + TweenLite.to(element, 0.35, { css: { x: `0px` } }); } }, diff --git a/tests/dummy/app/routes/items/route.js b/tests/dummy/app/routes/items/route.js index a179b967f..1b6430a2d 100644 --- a/tests/dummy/app/routes/items/route.js +++ b/tests/dummy/app/routes/items/route.js @@ -1,6 +1,8 @@ import Ember from 'ember'; const { + get, + set, Route } = Ember; @@ -8,6 +10,12 @@ export default Route.extend({ model() { return this.get('store').findAll('item'); + }, + + setupController(controller, model) { + this._super(controller, model); + + set(controller, 'currentRouteName', get(this, 'routeName')); } }); diff --git a/tests/dummy/app/routes/items/single/route.js b/tests/dummy/app/routes/items/single/route.js index 721cf6c1d..6eb31699d 100644 --- a/tests/dummy/app/routes/items/single/route.js +++ b/tests/dummy/app/routes/items/single/route.js @@ -7,7 +7,7 @@ const { export default Route.extend({ model(params) { - return this.get('store').findRecord(params.id); + return this.get('store').findRecord('item', params.id); } }); diff --git a/tests/dummy/app/routes/items/template.hbs b/tests/dummy/app/routes/items/template.hbs index 5a6ed73c5..7ccb15d6b 100644 --- a/tests/dummy/app/routes/items/template.hbs +++ b/tests/dummy/app/routes/items/template.hbs @@ -1,3 +1 @@ -{{#swipe-box}} - {{liquid-outlet "main"}} -{{/swipe-box}} \ No newline at end of file +{{history-outlet currentRouteName=currentRouteName}} \ No newline at end of file diff --git a/tests/dummy/app/styles/app.scss b/tests/dummy/app/styles/app.scss index e69de29bb..343aefb86 100644 --- a/tests/dummy/app/styles/app.scss +++ b/tests/dummy/app/styles/app.scss @@ -0,0 +1,47 @@ +html { + font-size:62.5%; +} + +body { + font-family: "Helvetica Neue", Helvetica, "Open Sans", sans-serif; + font-size: 1.8em; + color: #333; + margin: 0; +} + +.item-card { + font-size: 1em; + padding: 1em; + background: #ff00ff; + margin: 1em; + color: #fff; +} + +.bg-dark { + background: #333; +} + +.bg-green { + background: #80e545; +} + +history-outlet { + background: #000; + + left { + background: #f00; + } + + right { + background: #0f0; + } + + outlet { + background: #00f; + } + + main { + background: #ffff00; + } + +} diff --git a/tests/dummy/app/transitions.js b/tests/dummy/app/transitions.js index fff063440..0ddd88718 100644 --- a/tests/dummy/app/transitions.js +++ b/tests/dummy/app/transitions.js @@ -3,17 +3,18 @@ export default function() { // debug all this.transition = this.transition.bind(this, this.debug()); - /** + /* * Initial Render * * */ - // Rule 1 + // Rule 1 this.transition( this.onInitialRender(), this.use('fade', { duration: 500 }) ); + // Rule 2 this.transition( this.fromRoute('items.index'), this.use('to-left', { duration: 350 }), diff --git a/tests/dummy/config/environment.js b/tests/dummy/config/environment.js index c7000dbb4..6007c8862 100644 --- a/tests/dummy/config/environment.js +++ b/tests/dummy/config/environment.js @@ -1,4 +1,5 @@ /* jshint node: true */ +// jscs:disable module.exports = function(environment) { var ENV = { diff --git a/tests/helpers/module-for-acceptance.js b/tests/helpers/module-for-acceptance.js index 76996fd04..f9f7205ba 100644 --- a/tests/helpers/module-for-acceptance.js +++ b/tests/helpers/module-for-acceptance.js @@ -11,12 +11,13 @@ export default function(name, options = {}) { this.application = startApp(); if (options.beforeEach) { - return options.beforeEach.apply(this, arguments); + return options.beforeEach(...arguments); } }, afterEach() { - let afterEach = options.afterEach && options.afterEach.apply(this, arguments); + let afterEach = options.afterEach && options.afterEach(...arguments); + return Promise.resolve(afterEach).then(() => destroyApp(this.application)); } }); diff --git a/tests/unit/instance-initializers/gesture-recognition-test.js b/tests/unit/instance-initializers/gesture-recognition-test.js index 62dd97e0a..28def4b75 100644 --- a/tests/unit/instance-initializers/gesture-recognition-test.js +++ b/tests/unit/instance-initializers/gesture-recognition-test.js @@ -3,15 +3,20 @@ import { initialize } from 'dummy/instance-initializers/gesture-recognition'; import { module, test } from 'qunit'; import destroyApp from '../../helpers/destroy-app'; +const { + run, + Application + } = Ember; + module('Unit | Instance Initializer | gesture recognition', { - beforeEach: function() { - Ember.run(() => { - this.application = Ember.Application.create(); + beforeEach() { + run(() => { + this.application = Application.create(); this.appInstance = this.application.buildInstance(); }); }, - afterEach: function() { - Ember.run(this.appInstance, 'destroy'); + afterEach() { + run(this.appInstance, 'destroy'); destroyApp(this.application); } }); diff --git a/tests/unit/services/history-test.js b/tests/unit/services/history-test.js new file mode 100644 index 000000000..57b9803a2 --- /dev/null +++ b/tests/unit/services/history-test.js @@ -0,0 +1,12 @@ +import { moduleFor, test } from 'ember-qunit'; + +moduleFor('service:history', 'Unit | Service | history', { + // Specify the other units that are required for this test. + // needs: ['service:foo'] +}); + +// Replace this with your real tests. +test('it exists', function(assert) { + let service = this.subject(); + assert.ok(service); +}); From 9259dfb1f16418fa691c63ee27e99e202866258c Mon Sep 17 00:00:00 2001 From: Arjun Kathuria Date: Wed, 15 Jun 2016 21:43:39 +0530 Subject: [PATCH 41/61] style(code-review): adds the respective code review corrections as directed --- .jshintrc | 5 ++--- src/inputjs/compute-delta-xy.js | 6 ++++-- src/inputjs/compute-input-data.js | 3 +-- src/main.js | 2 ++ src/recognizers/swipe.js | 2 +- src/utils/utils-consts.js | 3 +-- 6 files changed, 11 insertions(+), 10 deletions(-) diff --git a/.jshintrc b/.jshintrc index f565275e5..d1dab2ec8 100644 --- a/.jshintrc +++ b/.jshintrc @@ -5,15 +5,14 @@ "indent": 2, "predef": [ "document", - "window", - "define", - "module" + "window" ], "browser": true, "boss": true, "curly": true, "debug": false, "devel": true, + "eqeqeq": true, "expr": true, "validthis": true, "evil": true, diff --git a/src/inputjs/compute-delta-xy.js b/src/inputjs/compute-delta-xy.js index b4ecda9b8..fefb5bd41 100644 --- a/src/inputjs/compute-delta-xy.js +++ b/src/inputjs/compute-delta-xy.js @@ -1,8 +1,10 @@ -import { INPUT_START,INPUT_END } from './input-consts'; +import { INPUT_START, INPUT_END } from './input-consts'; export default function computeDeltaXY(session, input) { let { center } = input; - let offset = session.offsetDelta || {}; // could be further deconstructed later on + // let { offsetDelta:offset = {}, prevDelta = {}, prevInput = {} } = session; + // jscs throwing error on defalut destructured values and without defaults tests fail + let offset = session.offsetDelta || {}; let prevDelta = session.prevDelta || {}; let prevInput = session.prevInput || {}; diff --git a/src/inputjs/compute-input-data.js b/src/inputjs/compute-input-data.js index 20217e86f..73b26940c 100644 --- a/src/inputjs/compute-input-data.js +++ b/src/inputjs/compute-input-data.js @@ -35,8 +35,7 @@ export default function computeInputData(manager, input) { session.firstMultiple = false; } - let { firstInput } = session; - let { firstMultiple } = session; + let { firstInput, firstMultiple } = session; let offsetCenter = firstMultiple ? firstMultiple.center : firstInput.center; let center = input.center = getCenter(pointers); diff --git a/src/main.js b/src/main.js index 15e21c50c..2672503c6 100644 --- a/src/main.js +++ b/src/main.js @@ -126,6 +126,7 @@ assign(Hammer, { let freeGlobal = (typeof window !== 'undefined' ? window : (typeof self !== 'undefined' ? self : {})); // jshint ignore:line freeGlobal.Hammer = Hammer; +/* jshint ignore:start */ if (typeof define === 'function' && define.amd) { define(function() { return Hammer; @@ -135,3 +136,4 @@ if (typeof define === 'function' && define.amd) { } else { window[exportName] = Hammer; } +/* jshint ignore:end */ diff --git a/src/recognizers/swipe.js b/src/recognizers/swipe.js index b78c1a726..e4b39798d 100644 --- a/src/recognizers/swipe.js +++ b/src/recognizers/swipe.js @@ -36,7 +36,7 @@ inherit(SwipeRecognizer, AttrRecognizer, { }, attrTest(input) { - let { options:{ direction } } = this; + let { direction } = this.options; let velocity; if (direction & (DIRECTION_HORIZONTAL | DIRECTION_VERTICAL)) { diff --git a/src/utils/utils-consts.js b/src/utils/utils-consts.js index 7054369d4..a2c30db35 100644 --- a/src/utils/utils-consts.js +++ b/src/utils/utils-consts.js @@ -3,8 +3,7 @@ const TEST_ELEMENT = document.createElement('div'); const TYPE_FUNCTION = 'function'; -const { round } = Math; -const { abs } = Math; +const { round, abs } = Math; const { now } = Date; export { From 16fd31742c0ca3f416950d3657de65ae6c6ba322 Mon Sep 17 00:00:00 2001 From: Chris Thoburn Date: Wed, 15 Jun 2016 11:15:39 -0500 Subject: [PATCH 42/61] minor touch ups --- addon/components/history-outlet/component.js | 60 +---------- addon/components/history-outlet/template.hbs | 2 +- addon/services/history.js | 106 +++++++++++-------- addon/utils/dom/viewport-aware-clone.js | 32 ++++++ tests/dummy/app/app.js | 21 +++- 5 files changed, 118 insertions(+), 103 deletions(-) create mode 100644 addon/utils/dom/viewport-aware-clone.js diff --git a/addon/components/history-outlet/component.js b/addon/components/history-outlet/component.js index 8b19ce372..3ce853567 100644 --- a/addon/components/history-outlet/component.js +++ b/addon/components/history-outlet/component.js @@ -78,7 +78,7 @@ export default Component.extend({ }), // fps meter - debugMode: true, + debugMode: false, _lastTime: undefined, _frames: undefined, fps: 0, @@ -353,63 +353,7 @@ export default Component.extend({ // debugger; }); - this._fpsMeter(); + // this._fpsMeter(); } }); - -/* - var l = function() { - function e(e, t) { - var r = [], - n = true, - i = false, - a = void 0; - try { - for (var o, s = e[Symbol.iterator](); !(n = (o = s.next()).done) && (r.push(o.value), !t || r.length !== t); n = !0); - } catch (l) { - i = true, a = l - } finally { - try { - !n && s['return'] && s['return']() - } finally { - if (i) throw a - } - } - return r - } - return function(t, r) { - if (Array.isArray(t)) return t; - if (Symbol.iterator in Object(t)) return e(t, r); - throw new TypeError("Invalid attempt to destructure non-iterable instance") - } - }(); -*/ -/* - { - - _fpsMeter: function () { - var e = this; - 60 === this._frames.length && (window._frames = window._frames || [], window._frames.push(this._frames), window._frames.length > 15 && window._frames.shift(), this._frames = []), requestAnimationFrame(function (t) { - var r = (t - e._lastTime) / 1e3, - n = Math.round(1 / r); - e._frames.push({ - delta: r, - fps: n - }), e._lastTime = t; - var i = n; - if (e._frames.length > 5) { - var a = e._frames.slice(-6), - o = l(a, 6), - s = o[0], - u = o[1], - c = o[2], - d = o[3], - f = o[4], - h = o[5]; - i = (s.fps + u.fps + c.fps + d.fps + f.fps + h.fps) / 6 - } - e.set('fps', n), e.set('avg', i), e._fpsMeter() - }) - } -*/ diff --git a/addon/components/history-outlet/template.hbs b/addon/components/history-outlet/template.hbs index e17ba6cca..ba41d5fc6 100644 --- a/addon/components/history-outlet/template.hbs +++ b/addon/components/history-outlet/template.hbs @@ -4,7 +4,7 @@ {{outlet}} {{#if debugMode}} - (current | avg | low)
+ (curr | avg | low)
{{fps}} | {{avg}} | {{low}} fps
{{/if}} diff --git a/addon/services/history.js b/addon/services/history.js index 37423af9c..dca365325 100644 --- a/addon/services/history.js +++ b/addon/services/history.js @@ -31,7 +31,6 @@ export default Service.extend(Evented, { current: undefined, back() { - console.log('\n <=== BACK\n'); let t = this.get('stack').get('lastObject'); let r = this.get('current'); @@ -47,7 +46,6 @@ export default Service.extend(Evented, { .finally(() => { this._nextState = undefined; this._isHistoryOperation = false; - console.log('________ COMPLETE???? ________'); }); } @@ -55,7 +53,6 @@ export default Service.extend(Evented, { }, forward() { - console.log('\n FORWARD ===>\n'); let t = this.get('seen.lastObject'); let r = this.get('current'); @@ -77,14 +74,37 @@ export default Service.extend(Evented, { return Promise.reject('no forward history present'); }, - segmentFor(e, t) { - if (!t || !t.segments) { + segmentFor(outletName, stackItem) { + if (!stackItem) { return UNKNOWN_SEGMENT; } - let r = t.segments.get(`${e}-main`); + const cache = this.get('cache'); + let data = cache.get(stackItem.url); - return r ? r.child || r : UNKNOWN_SEGMENT; + if (!data || !data.segments) { + return UNKNOWN_SEGMENT; + } + + let segment = data.segments.get(`${outletName}-main`); + + return segment ? segment.child || segment : UNKNOWN_SEGMENT; + }, + + updateCache(url, data) { + const cache = this.get('cache'); + + let stale = cache.get(url); + + if (stale) { + stale.segments.forEach((segment) => { + segment.dom = null; + segment.parent = null; + segment.child = null; + }); + } + + this.get('cache').set(url, data); }, actions: { @@ -100,39 +120,39 @@ export default Service.extend(Evented, { }, init() { - function __someIterativeMethod(iterable) { - let r = new Map(); - let n = null; - - iterable.forEach(function(iteratedItem) { - let i = iteratedItem._state.outletState.render; - let a = `${i.name}-${i.outlet}`; - let o = { - name: i.name, - outlet: i.outlet, - key: a, - dom: __someClonedRange(iteratedItem), - parent: n, + function walkOutlets(outlets) { + let segments = new Map(); + let lastStackItemSeen = null; + + outlets.forEach(function(outletMorph) { + let handler = outletMorph._state.outletState.render; + let key = `${handler.name}-${handler.outlet}`; + let segment = { + name: handler.name, + outlet: handler.outlet, + key: key, + dom: cloneOutlet(outletMorph), + parent: lastStackItemSeen, child: null }; - if (n) { - n.child = o; + if (lastStackItemSeen) { + lastStackItemSeen.child = segment; } - n = o; - r.set(a, o); + lastStackItemSeen = segment; + segments.set(key, segment); }); - return r; + return segments; } - function __someClonedRange(element) { - let t = cloneRange('outlet-segment', element.firstNode, element.lastNode); + function cloneOutlet(element) { + let outletElement = cloneRange('outlet-segment', element.firstNode, element.lastNode); - t.id = STACK_ID++; - return t; + outletElement.id = STACK_ID++; + return outletElement; } this._super(); @@ -144,11 +164,11 @@ export default Service.extend(Evented, { const router = this.get('router'); router.on('willTransition', () => { - let t = this.get('current'); + let currentStackItem = this.get('current'); - if (t) { - t.segments = __someIterativeMethod(router._toplevelView._outlets); - this.get('cache').set(t.url, t); + if (currentStackItem) { + let segments = walkOutlets(router._toplevelView._outlets); + this.updateCache(currentStackItem.url, { segments }); } }); @@ -172,24 +192,24 @@ export default Service.extend(Evented, { ); } else { - let t = router.get('_location') || router.get('location'); - let r = t.lastSetURL || router.get('url'); - let n = this.get('current'); - let i = { - url: r, + let location = router.get('_location') || router.get('location'); + let url = location.lastSetURL || router.get('url'); + let previousStackItem = this.get('current'); + let currentStackItem = { + url, routeName: router.currentRouteName }; - this.set('current', i); + this.set('current', currentStackItem); this.get('seen').clear(); - if (n) { - this.get('stack').pushObject(n); + if (previousStackItem) { + this.get('stack').pushObject(previousStackItem); } this.trigger('didTransition', { - previous: n, - current: i, + previous: previousStackItem, + current: currentStackItem, next: undefined }); } diff --git a/addon/utils/dom/viewport-aware-clone.js b/addon/utils/dom/viewport-aware-clone.js new file mode 100644 index 000000000..19fddc3fa --- /dev/null +++ b/addon/utils/dom/viewport-aware-clone.js @@ -0,0 +1,32 @@ +function isInViewport(element, viewport) { + let client = element.getBoundingClientRect(); + debugger; + + return true; +} + +function cloneElement(parent, element, viewport) { + parent.appendChild(element.cloneNode(true)); +} + + +export default function viewportAwareClone(tagName, firstNode, lastNode) { + const parent = document.createElement(tagName); + let nextNode; + let viewport = { + width: window.innerWidth, + height: window.innerHeight + }; + + while (firstNode) { + nextNode = firstNode.nextSibling; + if (isInViewport(firstNode, viewport)) { + cloneElement(parent, firstNode, viewport); + } else { + break; + } + firstNode = firstNode !== lastNode ? nextNode : null; + } + + return parent; +}; diff --git a/tests/dummy/app/app.js b/tests/dummy/app/app.js index 831ad6106..cedcf742b 100644 --- a/tests/dummy/app/app.js +++ b/tests/dummy/app/app.js @@ -10,7 +10,26 @@ Ember.MODEL_FACTORY_INJECTIONS = true; App = Ember.Application.extend({ modulePrefix: config.modulePrefix, podModulePrefix: config.podModulePrefix, - Resolver + Resolver, + customEvents: { + touchstart: null, + touchmove: null, + touchcancel: null, + touchend: null, + mousedown: null, + mouseenter: null, + mousemove: null, + mouseleave: null, + mouseup: null, + drag: null, + dragend: null, + dragenter: null, + dragleave: null, + dragover: null, + dragstart: null, + drop: null, + dblclick: null + } }); loadInitializers(App, config.modulePrefix); From 632d8bb4b8b95b4f8307db77bf5ebdd5d6de632c Mon Sep 17 00:00:00 2001 From: Arjun Kathuria Date: Thu, 16 Jun 2016 21:14:33 +0530 Subject: [PATCH 43/61] style(arrow functions): adds the nice ES6 arrow-function syntax for callbacks --- .jscsrc | 3 ++- src/input/touch.js | 2 +- src/main.js | 2 +- src/manager.js | 8 ++++---- src/recognizers/press.js | 2 +- src/recognizers/tap.js | 4 ++-- src/touchactionjs/get-touchaction-props.js | 4 ++-- src/touchactionjs/touchaction-constructor.js | 2 +- src/utils/add-event-listeners.js | 2 +- src/utils/extend.js | 2 +- src/utils/merge.js | 2 +- src/utils/remove-event-listeners.js | 2 +- src/utils/unique-array.js | 2 +- 13 files changed, 19 insertions(+), 18 deletions(-) diff --git a/.jscsrc b/.jscsrc index f3c50dc51..34c401bc6 100644 --- a/.jscsrc +++ b/.jscsrc @@ -5,5 +5,6 @@ "tests/**/assets", "node_modules/**" ], - "disallowConstOutsideModuleScope": false + "disallowConstOutsideModuleScope": false, + "requireArrowFunctions": true, } diff --git a/src/input/touch.js b/src/input/touch.js index 5e3708b82..9d02b1f8b 100644 --- a/src/input/touch.js +++ b/src/input/touch.js @@ -74,7 +74,7 @@ function getTouches(ev, type) { let { target } = this; // get target touches from touches - targetTouches = allTouches.filter(function(touch) { + targetTouches = allTouches.filter((touch) => { return hasParent(touch.target, target); }); diff --git a/src/main.js b/src/main.js index 2672503c6..0baa47e0e 100644 --- a/src/main.js +++ b/src/main.js @@ -128,7 +128,7 @@ freeGlobal.Hammer = Hammer; /* jshint ignore:start */ if (typeof define === 'function' && define.amd) { - define(function() { + define(() => { return Hammer; }); } else if (typeof module !== 'undefined' && module.exports) { diff --git a/src/manager.js b/src/manager.js index cb2b602b1..9a3de6096 100644 --- a/src/manager.js +++ b/src/manager.js @@ -41,7 +41,7 @@ function Manager(element, options) { toggleCssProps(this, true); - each(this.options.recognizers, function(item) { + each(this.options.recognizers, (item) => { let recognizer = this.add(new (item[0])(item[1])); item[2] && recognizer.recognizeWith(item[2]); item[3] && recognizer.requireFailure(item[3]); @@ -226,7 +226,7 @@ Manager.prototype = { } let { handlers } = this; - each(splitStr(events), function(event) { + each(splitStr(events), (event) => { handlers[event] = handlers[event] || []; handlers[event].push(handler); }); @@ -245,7 +245,7 @@ Manager.prototype = { } let { handlers } = this; - each(splitStr(events), function(event) { + each(splitStr(events), (event) => { if (!handler) { delete handlers[event]; } else { @@ -311,7 +311,7 @@ function toggleCssProps(manager, add) { return; } let prop; - each(manager.options.cssProps, function(value, name) { + each(manager.options.cssProps, (value, name) => { prop = prefixed(element.style, name); if (add) { manager.oldCssProps[prop] = element.style[prop]; diff --git a/src/recognizers/press.js b/src/recognizers/press.js index f8ee3271e..60f6153db 100644 --- a/src/recognizers/press.js +++ b/src/recognizers/press.js @@ -58,7 +58,7 @@ inherit(PressRecognizer, Recognizer, { this.reset(); } else if (input.eventType & INPUT_START) { this.reset(); - this._timer = setTimeoutContext(function() { + this._timer = setTimeoutContext(() => { this.state = STATE_RECOGNIZED; this.tryEmit(); }, options.time, this); diff --git a/src/recognizers/tap.js b/src/recognizers/tap.js index e11a981e4..774f6af1b 100644 --- a/src/recognizers/tap.js +++ b/src/recognizers/tap.js @@ -97,7 +97,7 @@ inherit(TapRecognizer, Recognizer, { if (!this.hasRequireFailures()) { return STATE_RECOGNIZED; } else { - this._timer = setTimeoutContext(function() { + this._timer = setTimeoutContext(() => { this.state = STATE_RECOGNIZED; this.tryEmit(); }, options.interval, this); @@ -109,7 +109,7 @@ inherit(TapRecognizer, Recognizer, { }, failTimeout() { - this._timer = setTimeoutContext(function() { + this._timer = setTimeoutContext(() => { this.state = STATE_FAILED; }, this.options.interval, this); return STATE_FAILED; diff --git a/src/touchactionjs/get-touchaction-props.js b/src/touchactionjs/get-touchaction-props.js index 3b695fd69..86f9fb3ad 100644 --- a/src/touchactionjs/get-touchaction-props.js +++ b/src/touchactionjs/get-touchaction-props.js @@ -6,11 +6,11 @@ export default function getTouchActionProps() { } let touchMap = {}; let cssSupports = window.CSS && window.CSS.supports; - ['auto', 'manipulation', 'pan-y', 'pan-x', 'pan-x pan-y', 'none'].forEach(function(val) { + ['auto', 'manipulation', 'pan-y', 'pan-x', 'pan-x pan-y', 'none'].forEach((val) => { // If css.supports is not supported but there is native touch-action assume it supports // all values. This is the case for IE 10 and 11. - touchMap[val] = cssSupports ? window.CSS.supports('touch-action', val) : true; + return touchMap[val] = cssSupports ? window.CSS.supports('touch-action', val) : true; }); return touchMap; } diff --git a/src/touchactionjs/touchaction-constructor.js b/src/touchactionjs/touchaction-constructor.js index 79f417bd9..f8425bb05 100644 --- a/src/touchactionjs/touchaction-constructor.js +++ b/src/touchactionjs/touchaction-constructor.js @@ -62,7 +62,7 @@ TouchAction.prototype = { */ compute() { let actions = []; - each(this.manager.recognizers, function(recognizer) { + each(this.manager.recognizers, (recognizer) => { if (boolOrFn(recognizer.options.enable, [recognizer])) { actions = actions.concat(recognizer.getTouchAction()); } diff --git a/src/utils/add-event-listeners.js b/src/utils/add-event-listeners.js index bbfad9ede..99b2da80c 100644 --- a/src/utils/add-event-listeners.js +++ b/src/utils/add-event-listeners.js @@ -8,7 +8,7 @@ import splitStr from './split-str'; * @param {Function} handler */ export default function addEventListeners(target, types, handler) { - each(splitStr(types), function(type) { + each(splitStr(types), (type) => { target.addEventListener(type, handler, false); }); } diff --git a/src/utils/extend.js b/src/utils/extend.js index 0b41be4c5..b3aa2372f 100644 --- a/src/utils/extend.js +++ b/src/utils/extend.js @@ -8,7 +8,7 @@ import deprecate from './deprecate'; * @param {Boolean} [merge=false] * @returns {Object} dest */ -const extend = deprecate(function extend(dest, src, merge) { +const extend = deprecate((dest, src, merge) => { let keys = Object.keys(src); let i = 0; while (i < keys.length) { diff --git a/src/utils/merge.js b/src/utils/merge.js index 333df4f86..015447d9c 100644 --- a/src/utils/merge.js +++ b/src/utils/merge.js @@ -8,7 +8,7 @@ import extend from './extend'; * @param {Object} src * @returns {Object} dest */ -const merge = deprecate(function merge(dest, src) { +const merge = deprecate((dest, src) => { return extend(dest, src, true); }, 'merge', 'Use `assign`.'); diff --git a/src/utils/remove-event-listeners.js b/src/utils/remove-event-listeners.js index 56fa66484..a26898743 100644 --- a/src/utils/remove-event-listeners.js +++ b/src/utils/remove-event-listeners.js @@ -8,7 +8,7 @@ import splitStr from './split-str'; * @param {Function} handler */ export default function removeEventListeners(target, types, handler) { - each(splitStr(types), function(type) { + each(splitStr(types), (type) => { target.removeEventListener(type, handler, false); }); } diff --git a/src/utils/unique-array.js b/src/utils/unique-array.js index de5144ce1..36a95aeb8 100644 --- a/src/utils/unique-array.js +++ b/src/utils/unique-array.js @@ -26,7 +26,7 @@ export default function uniqueArray(src, key, sort) { if (!key) { results = results.sort(); } else { - results = results.sort(function sortUniqueArray(a, b) { + results = results.sort((a, b) => { return a[key] > b[key]; }); } From 8f83ca665aaa2fb8e866b79b54504efa44f8dba7 Mon Sep 17 00:00:00 2001 From: Chris Thoburn Date: Fri, 17 Jun 2016 10:23:12 -0500 Subject: [PATCH 44/61] fix(chrome-perf): cancelable should be set on the event --- addon/-private/gestures/streams/stream.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addon/-private/gestures/streams/stream.js b/addon/-private/gestures/streams/stream.js index 87f74921b..eb7d3d840 100644 --- a/addon/-private/gestures/streams/stream.js +++ b/addon/-private/gestures/streams/stream.js @@ -27,7 +27,7 @@ export default class Stream { push(info) { // Improve Chrome Performance if (this.segments.length > 1 || this.series.length > 2) { - info.cancelable = false; + info.event.cancelable = false; } let lastEvent = this.series[this.series.length - 1]; From 0e65a08ca04864465aa60d5acc5d8b0eb5e342ae Mon Sep 17 00:00:00 2001 From: Chris Thoburn Date: Fri, 17 Jun 2016 11:47:09 -0500 Subject: [PATCH 45/61] adds perf utilities --- addon/-private/cache-list/index.js | 74 ++++++++++++++++++++++ addon/-private/ember/empty-object.js | 3 + addon/-private/ember/ext-require.js | 7 ++ addon/-private/ember/utils/identity.js | 18 ++++++ addon/-private/ember/utils/key-for-item.js | 31 +++++++++ 5 files changed, 133 insertions(+) create mode 100644 addon/-private/cache-list/index.js create mode 100644 addon/-private/ember/empty-object.js create mode 100644 addon/-private/ember/ext-require.js create mode 100644 addon/-private/ember/utils/identity.js create mode 100644 addon/-private/ember/utils/key-for-item.js diff --git a/addon/-private/cache-list/index.js b/addon/-private/cache-list/index.js new file mode 100644 index 000000000..5a71ca248 --- /dev/null +++ b/addon/-private/cache-list/index.js @@ -0,0 +1,74 @@ +import EmptyObject from '../ember/empty-object'; +const MAX_ARRAY_SIZE = 200; + +export default class CacheList { + + constructor() { + this.length = 0; + this._indeces = new Array(MAX_ARRAY_SIZE); + this._values = new Array(MAX_ARRAY_SIZE); + this._map = undefined; + } + + get(key) { + if (this.length < MAX_ARRAY_SIZE) { + let index = this._indeces.indexOf(key); + + if (index === -1) { + return undefined; + } + + return this._values[index]; + } + + return this._map.get(key); + } + + set(key, value) { + if (this.length < MAX_ARRAY_SIZE) { + let index = this._indeces.indexOf(key); + + if (index !== -1) { + this._values[index] = value; + return; + } + + index = this.length++; + + if (index !== MAX_ARRAY_SIZE) { + this._indeces[index] = key; + this._values[index] = value; + return; + } + + for (let i = 0; i < MAX_ARRAY_SIZE; i++) { + this._map = typeof Map !== 'undefined' ? new Map() : new EmptyObject(); + this._map.set(this._indeces[i], this._values[i]); + } + this._indeces = undefined; + this._values = undefined; + } + + this._map.set(key, value); + } + + remove(key) { + if (this.length < MAX_ARRAY_SIZE) { + let index = this._indeces.indexOf(key); + + if (index === -1) { + return undefined; + } + + let value = this._values[index]; + + this._indeces[index] = undefined; + this._values[index] = undefined; + + return value; + } + + return this._map.remove(key); + } + +} diff --git a/addon/-private/ember/empty-object.js b/addon/-private/ember/empty-object.js new file mode 100644 index 000000000..f802a084c --- /dev/null +++ b/addon/-private/ember/empty-object.js @@ -0,0 +1,3 @@ +import emberRequire from './ext-require'; + +export default emberRequire('ember-metal/empty_object'); diff --git a/addon/-private/ember/ext-require.js b/addon/-private/ember/ext-require.js new file mode 100644 index 000000000..a2bbedd3f --- /dev/null +++ b/addon/-private/ember/ext-require.js @@ -0,0 +1,7 @@ +import Ember from 'ember'; + +export default function(moduleName, exportName = 'default') { + let module = Ember.__loader.require(moduleName); + + return module[exportName]; +} diff --git a/addon/-private/ember/utils/identity.js b/addon/-private/ember/utils/identity.js new file mode 100644 index 000000000..d8bf63b09 --- /dev/null +++ b/addon/-private/ember/utils/identity.js @@ -0,0 +1,18 @@ +import Ember from 'ember'; + +const { + guidFor + } = Ember; + +export default function identity(item) { + let key; + const type = typeof item; + + if (type === 'string' || type === 'number') { + key = item; + } else { + key = guidFor(item); + } + + return key; +} diff --git a/addon/-private/ember/utils/key-for-item.js b/addon/-private/ember/utils/key-for-item.js new file mode 100644 index 000000000..cc2c48afa --- /dev/null +++ b/addon/-private/ember/utils/key-for-item.js @@ -0,0 +1,31 @@ +import Ember from 'ember'; +import identity from './identity'; + +const { + get + } = Ember; + +export default function keyForItem(item, index, keyPath = '@identity') { + let key; + + switch (keyPath) { + case '@index': + // allow 0 index + if (!index && index !== 0) { + throw new Error('No index was supplied to keyForItem'); + } + key = index; + break; + case '@identity': + key = identity(item); + break; + default: + key = get(item, keyPath); + } + + if (typeof key === 'number') { + key = String(key); + } + + return key; +} From 2f32fa065cd9e32a84d014fbdc51ea6a1abf8d53 Mon Sep 17 00:00:00 2001 From: Chris Thoburn Date: Fri, 17 Jun 2016 11:47:49 -0500 Subject: [PATCH 46/61] perf(recycle-pool): implements fast-array and uses them to manage recycle pools of volatile objects --- addon/-private/gestures/inputs/input.js | 2 +- .../gestures/recognizers/vertical-pan.js | 6 +- addon/-private/gestures/streams/fast-array.js | 52 ++++++++++++++++ .../-private/gestures/streams/stream-event.js | 19 ++++++ .../gestures/streams/stream-series.js | 38 ++++++++++++ addon/-private/gestures/streams/stream.js | 59 ++++++++++++------- 6 files changed, 150 insertions(+), 26 deletions(-) create mode 100644 addon/-private/gestures/streams/fast-array.js create mode 100644 addon/-private/gestures/streams/stream-series.js diff --git a/addon/-private/gestures/inputs/input.js b/addon/-private/gestures/inputs/input.js index ae7b395aa..bf8034b02 100644 --- a/addon/-private/gestures/inputs/input.js +++ b/addon/-private/gestures/inputs/input.js @@ -26,7 +26,7 @@ export default class Input { } start(event) { - let stream = new Stream(); + let stream = Stream.create(); const { streams } = this; // splice existing streams diff --git a/addon/-private/gestures/recognizers/vertical-pan.js b/addon/-private/gestures/recognizers/vertical-pan.js index d118f7471..f2d8c212f 100644 --- a/addon/-private/gestures/recognizers/vertical-pan.js +++ b/addon/-private/gestures/recognizers/vertical-pan.js @@ -17,9 +17,9 @@ export default class VerticalPan { this.stream = streams[streams.length - 1]; let { series } = this.stream; - for (let i = 0; i < series.length; i++) { - this.relay(series[i]); - } + series.forEach((event) => { + this.relay(event); + }); } relay(event) { diff --git a/addon/-private/gestures/streams/fast-array.js b/addon/-private/gestures/streams/fast-array.js new file mode 100644 index 000000000..401cd155a --- /dev/null +++ b/addon/-private/gestures/streams/fast-array.js @@ -0,0 +1,52 @@ +export const MAX_ARRAY_LENGTH = 200; + +export default class FastArray { + + constructor(length = MAX_ARRAY_LENGTH, name = 'Unknown Pool') { + this.init(length, name); + } + + init(length = MAX_ARRAY_LENGTH, name = 'Unknown Pool') { + this.name = name; + this.length = 0; + this._length = length; + this._data = new Array(length); + } + + get(index) { + if (index >= 0 && index < this.length) { + return this._data[index]; + } + + return undefined; + } + + forEach(cb) { + for (let i = 0; i < this.length; i++) { + cb(this._data[i], i); + } + } + + push(item) { + let index = this.length++; + + if (index === this._length) { + this._length *= 2; + this._data.length = this._length; + } + + this._data[index] = item; + } + + pop() { + let index = --this.length; + + if (index < 0) { + this.length = 0; + return undefined; + } + + return this._data[index]; + } + +} diff --git a/addon/-private/gestures/streams/stream-event.js b/addon/-private/gestures/streams/stream-event.js index ac6b49309..d64f69572 100644 --- a/addon/-private/gestures/streams/stream-event.js +++ b/addon/-private/gestures/streams/stream-event.js @@ -1,8 +1,14 @@ /* global Math, performance */ +import FastArray from './fast-array'; +const STREAM_EVENT_POOL = new FastArray(undefined, 'StreamEvent Pool'); export default class StreamEvent { constructor(name, info, prev) { + this.init(name, info, prev); + } + + init(name, info, prev) { this.name = name; this.element = info.event.target; this.source = info.event; @@ -126,10 +132,23 @@ export default class StreamEvent { this.silenced = true; } + static create(name, info, prev) { + let event = STREAM_EVENT_POOL.pop(); + + if (event) { + event.init(name, info, prev); + return event; + } + + return new StreamEvent(name, info, prev); + } + destroy() { this.source = undefined; this.prev = undefined; this.element = undefined; + + STREAM_EVENT_POOL.push(this); } } diff --git a/addon/-private/gestures/streams/stream-series.js b/addon/-private/gestures/streams/stream-series.js new file mode 100644 index 000000000..d8c5f00e3 --- /dev/null +++ b/addon/-private/gestures/streams/stream-series.js @@ -0,0 +1,38 @@ +import FastArray from './fast-array'; +import { MAX_ARRAY_SIZE } from './fast-array'; + +const STREAM_SERIES_POOL = new FastArray(10, 'StreamSeries Pool'); + +export default class StreamSeries extends FastArray { + + constructor() { + super(...arguments); + this._isDestroyed = false; + } + + static create(number = MAX_ARRAY_SIZE, name = 'StreamEvent to List') { + let series = STREAM_SERIES_POOL.pop(); + + if (series) { + series.init(number, name); + + return series; + } + + return new StreamSeries(number, name); + } + + destroy() { + if (!this._isDestroyed) { + this._isDestroyed = true; + + for (let j = 0; j < this.length; j++) { + this._data[j].destroy(); + this._data[j] = undefined; + } + + STREAM_SERIES_POOL.push(this); + } + } + +}; diff --git a/addon/-private/gestures/streams/stream.js b/addon/-private/gestures/streams/stream.js index eb7d3d840..b4de56c0e 100644 --- a/addon/-private/gestures/streams/stream.js +++ b/addon/-private/gestures/streams/stream.js @@ -1,11 +1,19 @@ import StreamEvent from './stream-event'; +import StreamSeries from './stream-series'; import MacroTask from '../utils/macro-task'; +import FastArray from './fast-array'; + +const STREAM_POOL = new FastArray(5, 'Stream Pool'); export default class Stream { constructor() { - this.segments = null; - this.series = null; + this.init(); + } + + init() { + this.segments = new FastArray(5, 'Segments'); + this.series = undefined; this._isDestroyed = false; this._isDestroying = false; this.active = false; @@ -13,25 +21,18 @@ export default class Stream { open(info) { this.active = true; - this.segments = []; - this.series = []; - + this.series = StreamSeries.create(); this.segments.push(this.series); - let streamEvent = new StreamEvent('start', info); + let streamEvent = StreamEvent.create('start', info); this.series.push(streamEvent); return streamEvent; } push(info) { - // Improve Chrome Performance - if (this.segments.length > 1 || this.series.length > 2) { - info.event.cancelable = false; - } - - let lastEvent = this.series[this.series.length - 1]; - let streamEvent = new StreamEvent('move', info, lastEvent); + let lastEvent = this.series.get(this.series.length - 1); + let streamEvent = StreamEvent.create('move', info, lastEvent); this.series.push(streamEvent); return streamEvent; @@ -39,8 +40,8 @@ export default class Stream { close(info) { this.active = false; - let lastEvent = this.series[this.series.length - 1]; - let streamEvent = new StreamEvent('end', info, lastEvent); + let lastEvent = this.series.get(this.series.length - 1); + let streamEvent = StreamEvent.create('end', info, lastEvent); this.series.push(streamEvent); @@ -51,14 +52,16 @@ export default class Stream { } silence() { - let [[down, initial]] = this.segments; + let series = this.segments.get(0); + let down = series.get(0); + let initial = series.get(1); down.silence(); initial.silence(); } split() { - this.series = []; + this.series = StreamSeries.create(); this.segments.push(this.series); } @@ -66,13 +69,25 @@ export default class Stream { if (!this._isDestroyed) { this._isDestroyed = true; this.series = undefined; - for (let i = 0; i < this.segments.length; i++) { - for (let j = 0; j < this.segments[i].length; j++) { - this.segments[i][j].destroy(); - } - } + + this.segments.forEach((series) => { + series.destroy(); + }); this.segments = undefined; + + STREAM_POOL.push(this); + } + } + + static create() { + let stream = STREAM_POOL.pop(); + + if (stream) { + stream.init(); + return stream; } + + return new Stream(); } } From 5c7f65343e84f5259d096fedb8e5e426b1964180 Mon Sep 17 00:00:00 2001 From: Chris Thoburn Date: Fri, 17 Jun 2016 11:55:01 -0500 Subject: [PATCH 47/61] feat(perf): don't super arguments when arguments are well known --- addon/-private/gestures/streams/stream-series.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addon/-private/gestures/streams/stream-series.js b/addon/-private/gestures/streams/stream-series.js index d8c5f00e3..d0174c602 100644 --- a/addon/-private/gestures/streams/stream-series.js +++ b/addon/-private/gestures/streams/stream-series.js @@ -5,8 +5,8 @@ const STREAM_SERIES_POOL = new FastArray(10, 'StreamSeries Pool'); export default class StreamSeries extends FastArray { - constructor() { - super(...arguments); + constructor(number = MAX_ARRAY_SIZE, name = 'StreamEvent to List') { + super(number, name); this._isDestroyed = false; } From 90fb6af7e6aeed7afdd1ee1f3df94a6b021a5364 Mon Sep 17 00:00:00 2001 From: Chris Thoburn Date: Fri, 17 Jun 2016 14:08:17 -0500 Subject: [PATCH 48/61] feat(perf): release Event objects sooner if we have no need for them, prevents larger GC events when a gesture completes --- addon/-private/gestures/streams/stream-event.js | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/addon/-private/gestures/streams/stream-event.js b/addon/-private/gestures/streams/stream-event.js index d64f69572..62c197f51 100644 --- a/addon/-private/gestures/streams/stream-event.js +++ b/addon/-private/gestures/streams/stream-event.js @@ -11,7 +11,8 @@ export default class StreamEvent { init(name, info, prev) { this.name = name; this.element = info.event.target; - this.source = info.event; + this._isImportantEvent = (name === 'end' || name === 'start' || (prev && prev.name === 'start')); + this._source = this._isImportantEvent ? info.event : undefined; this.silenced = false; this.prev = prev; @@ -127,9 +128,11 @@ export default class StreamEvent { // cancel any default behaviors from this event silence() { - this.source.preventDefault(); - this.source.stopPropagation(); - this.silenced = true; + if (this._source && this._source.cancelable) { + this._source.preventDefault(); + this._source.stopPropagation(); + this.silenced = true; + } } static create(name, info, prev) { @@ -144,7 +147,7 @@ export default class StreamEvent { } destroy() { - this.source = undefined; + this._source = undefined; this.prev = undefined; this.element = undefined; From 3a3255d89c5961fee2590eb4cde588ab3b87f3b8 Mon Sep 17 00:00:00 2001 From: Chris Thoburn Date: Fri, 17 Jun 2016 14:08:48 -0500 Subject: [PATCH 49/61] chore(dependencies): removes ember-tweenlite, which will be replaced by a custom animation core --- package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/package.json b/package.json index 88d9c6894..58b5bf639 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,6 @@ "ember-load-initializers": "^0.5.1", "ember-resolver": "^2.0.3", "ember-suave": "^2.0.1", - "ember-tweenlite": "1.0.1", "express": "^4.13.4", "faker": "^3.1.0", "flexi": "1.1.9", From 82530bce9f47738306b957fc19e91fcd9f6e6a67 Mon Sep 17 00:00:00 2001 From: Chris Thoburn Date: Fri, 17 Jun 2016 14:09:48 -0500 Subject: [PATCH 50/61] feat(animation): use the custom animation core instead of tweenlite --- addon/components/history-outlet/component.js | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/addon/components/history-outlet/component.js b/addon/components/history-outlet/component.js index 3ce853567..81111c8a6 100644 --- a/addon/components/history-outlet/component.js +++ b/addon/components/history-outlet/component.js @@ -3,7 +3,7 @@ import Ember from 'ember'; import layout from './template'; import Layer from 'history/-private/gestures/layer'; import VerticalPan from 'history/-private/gestures/recognizers/vertical-pan'; -import TweenLite from 'tweenlite'; +import Animation from 'history/-private/animation'; import removeRange from 'history/utils/dom/remove-range'; import appendRange from 'history/utils/dom/append-range'; @@ -14,19 +14,12 @@ const { RSVP } = Ember; -const assign = Ember.assign || Object.assign || Ember.merge; - function tween(element, time, options) { - return new Promise(function(resolve) { - options.onComplete = resolve; - TweenLite.to(element, time / 1000, options); - }); + return Animation.to(element, time, options); } function carryMomentum(element, duration, options) { - let opts = assign({ ease: Linear.easeOut }, options); - - return tween(element, duration, opts); + return tween(element, duration, options, { ease: 'ease-out' }); } function getDuration(streamEvent, width) { @@ -34,9 +27,7 @@ function getDuration(streamEvent, width) { } function updateStyle(element, css) { - let options = { immediateRender: true, css }; - - TweenLite.set(element, options); + Animation.set(element, css); } export default Component.extend({ From e5952a7b6a72f526f6d7fa2e3c77e53f0af65e71 Mon Sep 17 00:00:00 2001 From: Chris Thoburn Date: Fri, 17 Jun 2016 18:31:37 -0500 Subject: [PATCH 51/61] feat(animation): implements custom animation library --- addon/-private/animation/animation.js | 40 ++++++++ addon/-private/animation/element-style.js | 91 +++++++++++++++++++ addon/-private/animation/index.js | 3 + addon/-private/animation/style.js | 0 addon/-private/animation/transform-style.js | 65 +++++++++++++ .../-private/animation/utils/layout-props.js | 3 + .../animation/utils/transform-prop.js | 17 ++++ addon/-private/animation/value-transform.js | 55 +++++++++++ .../streams => cache-list}/fast-array.js | 0 addon/-private/cache-list/index.js | 40 +++++++- .../-private/gestures/streams/stream-event.js | 2 +- .../gestures/streams/stream-series.js | 4 +- addon/-private/gestures/streams/stream.js | 2 +- index.js | 44 --------- 14 files changed, 315 insertions(+), 51 deletions(-) create mode 100644 addon/-private/animation/animation.js create mode 100644 addon/-private/animation/element-style.js create mode 100644 addon/-private/animation/index.js create mode 100644 addon/-private/animation/style.js create mode 100644 addon/-private/animation/transform-style.js create mode 100644 addon/-private/animation/utils/layout-props.js create mode 100644 addon/-private/animation/utils/transform-prop.js create mode 100644 addon/-private/animation/value-transform.js rename addon/-private/{gestures/streams => cache-list}/fast-array.js (100%) diff --git a/addon/-private/animation/animation.js b/addon/-private/animation/animation.js new file mode 100644 index 000000000..60779bf9f --- /dev/null +++ b/addon/-private/animation/animation.js @@ -0,0 +1,40 @@ +import CacheList from '../cache-list'; +import ElementStyle from './element-style'; + +export default class Animation { + + constructor() { + this.cache = new CacheList(); + } + + // We dumb + to(element, time, styles, options) { + this.setImmediate(element, styles); + return Promise.resolve(); + } + + set(element, styles) { + this.setImmediate(element, styles); + } + + setImmediate(element, styles) { + let meta = this.getElementMeta(element, styles); + + meta.applyStyles(element); + } + + getElementMeta(element, styles) { + let id = element.id; + let meta; + + if (!id || !(meta = this.cache.get(id))) { + meta = new ElementStyle(styles, element); + this.cache.set(id, meta); + } else { + meta.setStyles(styles); + } + + return meta; + } + +} diff --git a/addon/-private/animation/element-style.js b/addon/-private/animation/element-style.js new file mode 100644 index 000000000..a0ecdd5e6 --- /dev/null +++ b/addon/-private/animation/element-style.js @@ -0,0 +1,91 @@ +import TransformStyle from './transform-style'; +import CacheList from '../cache-list'; +import ValueTransform from './value-transform'; +import TRANSFORM_PROP from './utils/transform-prop'; +import LAYOUT_PROPS from './utils/layout-props'; + +let ANIMATION_ID = 1; +const ANIMATION_KEY = 'eca'; +const TRANSFORM_STYLES = ['x','y']; +const NUMERIC_STYLES = [ + 'top' , 'left', 'right', 'bottom', + 'width', 'height' +]; + +export default class ElementStyle { + + constructor(values = {}, element) { + this.init(values, element); + } + + init(values, element) { + this.changes = new CacheList(); + this.hasTransform = false; + this.srcStyle = window.getComputedStyle(element); + this.transformStyle = new TransformStyle(this.srcStyle.transform); + this.setStyles(values); + + this.animationId = ANIMATION_ID++; + this.elementId = element.id = element.id || `${ANIMATION_KEY}-${this.animationId}`; + } + + setStyles(styles) { + let keys = Object.keys(styles); + + for (let i = 0; i < keys.length; i++) { + this.set(keys[i], styles[keys[i]]); + } + } + + set(prop, val) { + if (TRANSFORM_STYLES.indexOf(prop) !== -1) { + this._setTransform(prop, val); + } else if (LAYOUT_PROPS.indexOf(prop) !== -1) { + this._set(prop, val); + } else { + throw new Error('Invalid Style Property'); + } + } + + _setTransform(prop, val) { + this.hasTransform = true; + let valueTransform = ElementStyle.parseNumber(val); + + this.transformStyle[prop] = valueTransform.affect(this.transformStyle[prop]); + } + + _set(prop, val) { + let cached = this.changes.get(prop); + + if (NUMERIC_STYLES.indexOf(prop) !== -1) { + val = ElementStyle.parseNumber(val).affect(cached, true); + } + + this.changes.set(prop, val); + } + + applyStyles(element) { + element = element || ElementStyle.getElement(this.elementId); + + if (!element) { + return; + } + + this.changes.forEach((value, key) => { + element.style[key] = value || ''; + }); + + if (this.hasTransform) { + element.style[TRANSFORM_PROP] = this.transformStyle.toString(); + } + } + + static getElement(id) { + return document.getElementById(id); + } + + static parseNumber(maybeNumber, canUseCalc = false) { + return new ValueTransform(maybeNumber, canUseCalc); + } + +} diff --git a/addon/-private/animation/index.js b/addon/-private/animation/index.js new file mode 100644 index 000000000..a8a75af6b --- /dev/null +++ b/addon/-private/animation/index.js @@ -0,0 +1,3 @@ +import Animation from './animation'; + +export default new Animation(); diff --git a/addon/-private/animation/style.js b/addon/-private/animation/style.js new file mode 100644 index 000000000..e69de29bb diff --git a/addon/-private/animation/transform-style.js b/addon/-private/animation/transform-style.js new file mode 100644 index 000000000..51ba2daa4 --- /dev/null +++ b/addon/-private/animation/transform-style.js @@ -0,0 +1,65 @@ +export const TRANSLATE_X_TEST = /translateX\(([^\)]+)\)/; +export const TRANSLATE_Y_TEST = /translateY\(([^\)]+)\)/; +export const TRANSLATE_TEST = /translate\(([^\),\s]+)(,\s*)?([^\)]*)?\)/; +export const MATRIX_TEST = /matrix\(([^\),\s]+),\s*([^\)]*),\s*([^\)]*),\s*([^\)]*),\s*([^\)]*),\s*([^\)]*)\)/; + +export default class TransformStyle { + + constructor(transformString) { + this.x = 0; + this.y = 0; + + if (transformString) { + this.fromString(transformString); + } + } + + fromString(str = '') { + let match; + // match translateY + if (match = str.match(TRANSLATE_Y_TEST)) { + this.y = match[1]; + return; + } + + // match translateX + if (match = str.match(TRANSLATE_X_TEST)) { + this.x = match[1]; + return; + } + + // match translate + if (match = str.match(TRANSLATE_TEST)) { + this.x = match[1]; + this.y = match[3]; + return; + } + + // match matrix + if (match = str.match(MATRIX_TEST)) { + this.x = match[5]; + this.y = match[6]; + return; + } + + // error out + throw new Error('Unsupported Starting Transform'); + } + + toString() { + if (!this.x) { + if (!this.y) { + return ''; + } + + return `translateY(${this.y})`; + } + + if (this.y) { + return `translate(${this.x}, ${this.y})`; + } + + return `translateX(${this.y})`; + } + +} diff --git a/addon/-private/animation/utils/layout-props.js b/addon/-private/animation/utils/layout-props.js new file mode 100644 index 000000000..4c61525f9 --- /dev/null +++ b/addon/-private/animation/utils/layout-props.js @@ -0,0 +1,3 @@ +const LAYOUT_PROPS = Object.keys(document.body.style); + +export default LAYOUT_PROPS; diff --git a/addon/-private/animation/utils/transform-prop.js b/addon/-private/animation/utils/transform-prop.js new file mode 100644 index 000000000..d9a4de765 --- /dev/null +++ b/addon/-private/animation/utils/transform-prop.js @@ -0,0 +1,17 @@ +// Determine Vendor Prefix +export const VENDORS = ['Webkit', 'Moz', 'ms']; + +let transformProp = 'transform'; + +if (! ('transform' in document.body.style)) { + for (let i = 0; i < VENDORS.length; i++) { + let prop = `${VENDORS[i]}Transform`; + + if (prop in document.body.style) { + transformProp = prop; + break; + } + } +} + +export default transformProp; diff --git a/addon/-private/animation/value-transform.js b/addon/-private/animation/value-transform.js new file mode 100644 index 000000000..21d69dc27 --- /dev/null +++ b/addon/-private/animation/value-transform.js @@ -0,0 +1,55 @@ +export const NUMBER_MATCH = /^([\-|\+])?(=)?([0-9]*\.?[0-9]*)(.*)/; + +export default class ValueTransform { + + constructor(maybeNumber, canUseCalc = false) { + let info = ValueTransform.parse(maybeNumber); + + this.canUseCalc = canUseCalc; + this.isPositive = info.isPositive; + this.isAdditive = info.isAdditive; + this.amount = info.amount; + this.unit = info.unit; + } + + static parse(maybeNumber) { + let numStr = (maybeNumber || 0).toString(); + let match = numStr.match(NUMBER_MATCH); + + if (!match) { + throw new Error('Unmatchable Number'); + } + + let positive = !match[1] || match[1] === '+'; + + return { + isPositive: positive, + isAdditive: !!match[2], + amount: (positive ? 1 : -1) * parseFloat(match[3]).toFixed(3), + unit: match[4] || 'px' + }; + } + + affect(num) { + if (!this.isAdditive) { + return `${this.amount}${this.unit}`; + } + + let baseline = ValueTransform.parse(num); + if (this.unit && baseline.unit !== this.unit) { + if (this.canUseCalc) { + // return calc combo + return `calc(${baseline.amount}${baseline.unit} ${this.amount}${this.unit})`; + } + + // return non calc combo + return `${this.amount}${this.unit}`; + } + + // return join + let newNum = baseline.amount + this.amount; + + return `${newNum}${this.unit}`; + } + +} diff --git a/addon/-private/gestures/streams/fast-array.js b/addon/-private/cache-list/fast-array.js similarity index 100% rename from addon/-private/gestures/streams/fast-array.js rename to addon/-private/cache-list/fast-array.js diff --git a/addon/-private/cache-list/index.js b/addon/-private/cache-list/index.js index 5a71ca248..e6785d3e0 100644 --- a/addon/-private/cache-list/index.js +++ b/addon/-private/cache-list/index.js @@ -1,15 +1,38 @@ import EmptyObject from '../ember/empty-object'; +import FastArray from './fast-array'; + const MAX_ARRAY_SIZE = 200; export default class CacheList { - constructor() { + constructor(length = MAX_ARRAY_SIZE) { this.length = 0; - this._indeces = new Array(MAX_ARRAY_SIZE); - this._values = new Array(MAX_ARRAY_SIZE); + this.maxLength = length; + this._indeces = new Array(length); + this._values = new Array(length); this._map = undefined; } + forEach(cb) { + if (this.length >= MAX_ARRAY_SIZE) { + if (this._map instanceof EmptyObject) { + for (let i in this._map) { + cb(this._map[i], i); + } + } else { + this._map.forEach(cb); + } + } else { + for (let i = 0; i < this.length; i++) { + let key; + + if (key = this._indeces[i]) { + cb(this._values[i], key); + } + } + } + } + get(key) { if (this.length < MAX_ARRAY_SIZE) { let index = this._indeces.indexOf(key); @@ -36,6 +59,17 @@ export default class CacheList { index = this.length++; if (index !== MAX_ARRAY_SIZE) { + if (index === this.maxLength) { + let len = this.maxLength * 2; + + if (len > MAX_ARRAY_SIZE) { + len = MAX_ARRAY_SIZE; + } + + this.maxLength = len; + this._indeces.length = len; + this._values.length = len; + } this._indeces[index] = key; this._values[index] = value; return; diff --git a/addon/-private/gestures/streams/stream-event.js b/addon/-private/gestures/streams/stream-event.js index 62c197f51..553a89eb2 100644 --- a/addon/-private/gestures/streams/stream-event.js +++ b/addon/-private/gestures/streams/stream-event.js @@ -1,5 +1,5 @@ /* global Math, performance */ -import FastArray from './fast-array'; +import FastArray from '../../cache-list/fast-array'; const STREAM_EVENT_POOL = new FastArray(undefined, 'StreamEvent Pool'); export default class StreamEvent { diff --git a/addon/-private/gestures/streams/stream-series.js b/addon/-private/gestures/streams/stream-series.js index d0174c602..05bab0378 100644 --- a/addon/-private/gestures/streams/stream-series.js +++ b/addon/-private/gestures/streams/stream-series.js @@ -1,5 +1,5 @@ -import FastArray from './fast-array'; -import { MAX_ARRAY_SIZE } from './fast-array'; +import FastArray from '../../cache-list/fast-array'; +import { MAX_ARRAY_SIZE } from '../../cache-list/fast-array'; const STREAM_SERIES_POOL = new FastArray(10, 'StreamSeries Pool'); diff --git a/addon/-private/gestures/streams/stream.js b/addon/-private/gestures/streams/stream.js index b4de56c0e..a11b590d0 100644 --- a/addon/-private/gestures/streams/stream.js +++ b/addon/-private/gestures/streams/stream.js @@ -1,7 +1,7 @@ import StreamEvent from './stream-event'; import StreamSeries from './stream-series'; import MacroTask from '../utils/macro-task'; -import FastArray from './fast-array'; +import FastArray from '../../cache-list/fast-array'; const STREAM_POOL = new FastArray(5, 'Stream Pool'); diff --git a/index.js b/index.js index 08dd9ca84..bcfe71d0e 100644 --- a/index.js +++ b/index.js @@ -5,51 +5,7 @@ module.exports = { name: 'history', - included: function(app, parentAddon) { - this._super.included.apply(this, arguments); - - // Quick fix for add-on nesting - // https://github.com/aexmachina/ember-cli-sass/blob/v5.3.0/index.js#L73-L75 - // see: https://github.com/ember-cli/ember-cli/issues/3718 - while (typeof app.import !== 'function' && (app.app || app.parent)) { - app = app.app || app.parent; - } - - // if app.import and parentAddon are blank, we're probably being consumed by an in-repo-addon - // or engine, for which the "bust through" technique above does not work. - if (typeof app.import !== 'function' && !parentAddon) { - if (app.registry && app.registry.app) { - app = app.registry.app; - } - } - - if (!parentAddon && typeof app.import !== 'function') { - throw new Error('ember-history is being used within another addon or engine and is' + - ' having trouble registering itself to the parent application.'); - } - - this.importDependencies(app); - }, - isDevelopingAddon: function() { return true; - }, - - importDependencies: function(app) { - if (arguments.length < 1) { - throw new Error('Application instance must be passed to import'); - } - - var vendor = this.treePaths.vendor; - - if (!process.env.EMBER_CLI_FASTBOOT) { - if (app.env === "production") { - app.import(app.bowerDirectory + '/gsap/src/minified/plugins/CSSPlugin.min.js', { prepend: true }); - } else { - app.import(app.bowerDirectory + '/gsap/src/uncompressed/plugins/CSSPlugin.js', { prepend: true }); - } - } - - app.import(vendor + '/shims/tweenlite.js'); } }; From 1cfdc53a96b429a920ab042922e73feb9c34cc7b Mon Sep 17 00:00:00 2001 From: Chris Thoburn Date: Fri, 17 Jun 2016 20:34:53 -0500 Subject: [PATCH 52/61] feat(pan): fixes horizontal pan, implements vertical pan --- .../gestures/recognizers/horizontal-pan.js | 53 +++++++++++++++++++ .../gestures/recognizers/vertical-pan.js | 11 ++-- addon/components/history-outlet/component.js | 4 +- 3 files changed, 59 insertions(+), 9 deletions(-) create mode 100644 addon/-private/gestures/recognizers/horizontal-pan.js diff --git a/addon/-private/gestures/recognizers/horizontal-pan.js b/addon/-private/gestures/recognizers/horizontal-pan.js new file mode 100644 index 000000000..8a0762ce9 --- /dev/null +++ b/addon/-private/gestures/recognizers/horizontal-pan.js @@ -0,0 +1,53 @@ + +export default class HorizontalPan { + constructor(options) { + this.name = 'horizontal-pan'; + this.options = options; + this.layer = undefined; + this.stream = undefined; + + this.isRecognizing = false; + } + + beginRecognizing(input, streams, streamEvent) { + this.isRecognizing = true; + + this.stream = streams[streams.length - 1]; + let { series } = this.stream; + + series.forEach((event) => { + this.relay(event); + }); + } + + relay(event) { + if (event.name === 'start') { + this.layer.emit({ name: 'panStart', event }); + + } else if (event.name === 'end') { + this.isRecognizing = false; + this.layer.emit({ name: 'panEnd', event }); + this.stream = undefined; + + } else if (event.totalX < 0 || event.prev.totalX < 0) { + this.layer.emit({ name: 'panLeft', event }); + + } else { + this.layer.emit({ name: 'panRight', event }); + } + } + + emit(name, event) { + this.layer.emit({ name, event }); + } + + recognize(input, streams, streamEvent) { + if (this.isRecognizing) { + this.relay(streamEvent); + } else if (streamEvent.totalY === 0 && streamEvent.totalX !== 0) { + this.beginRecognizing(input, streams, streamEvent); + } + + return this.isRecognizing; + } +} diff --git a/addon/-private/gestures/recognizers/vertical-pan.js b/addon/-private/gestures/recognizers/vertical-pan.js index f2d8c212f..a2fa59b99 100644 --- a/addon/-private/gestures/recognizers/vertical-pan.js +++ b/addon/-private/gestures/recognizers/vertical-pan.js @@ -1,7 +1,5 @@ - export default class VerticalPan { - constructor(options) { this.name = 'vertical-pan'; this.options = options; @@ -31,11 +29,11 @@ export default class VerticalPan { this.layer.emit({ name: 'panEnd', event }); this.stream = undefined; - } else if (event.totalX < 0 || event.prev.totalX < 0) { - this.layer.emit({ name: 'panLeft', event }); + } else if (event.totalY < 0 || event.prev.totalY < 0) { + this.layer.emit({ name: 'panUp', event }); } else { - this.layer.emit({ name: 'panRight', event }); + this.layer.emit({ name: 'panDown', event }); } } @@ -46,11 +44,10 @@ export default class VerticalPan { recognize(input, streams, streamEvent) { if (this.isRecognizing) { this.relay(streamEvent); - } else if (streamEvent.totalY === 0 && streamEvent.totalX !== 0) { + } else if (streamEvent.totalX === 0 && streamEvent.totalY !== 0) { this.beginRecognizing(input, streams, streamEvent); } return this.isRecognizing; } - } diff --git a/addon/components/history-outlet/component.js b/addon/components/history-outlet/component.js index 81111c8a6..7777e6f56 100644 --- a/addon/components/history-outlet/component.js +++ b/addon/components/history-outlet/component.js @@ -2,7 +2,7 @@ import Ember from 'ember'; import layout from './template'; import Layer from 'history/-private/gestures/layer'; -import VerticalPan from 'history/-private/gestures/recognizers/vertical-pan'; +import HorizontalPan from 'history/-private/gestures/recognizers/horizontal-pan'; import Animation from 'history/-private/animation'; import removeRange from 'history/utils/dom/remove-range'; import appendRange from 'history/utils/dom/append-range'; @@ -311,7 +311,7 @@ export default Component.extend({ setupLayer() { this.layer = new Layer(); - this.layer.addRecognizer(new VerticalPan()); + this.layer.addRecognizer(new HorizontalPan()); this.layer.on('*', ({ name, event }) => { if (this[name]) { this[name](event); From dc85133ff23d84f4d4bc316eede87999ed5ca40c Mon Sep 17 00:00:00 2001 From: Arjun Kathuria Date: Wed, 22 Jun 2016 04:07:55 +0530 Subject: [PATCH 53/61] fix(jscs): Bump up ember-suave to 3.0.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b11578c9a..ea821c6f0 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,7 @@ "devDependencies": { "babel-preset-es2015-rollup": "^1.1.1", "changelogplease": "^1.2.0", - "ember-suave": "3.0.0", + "ember-suave": "3.0.1", "git-tags": "^0.2.4", "grunt": "0.4.x", "grunt-banner": "^0.2.3", From e5d388e3123c406ad1f422b333226faf4d5fe4d3 Mon Sep 17 00:00:00 2001 From: Christopher Garrett Date: Fri, 24 Jun 2016 17:09:28 -0700 Subject: [PATCH 54/61] chore(dependencies): pulls perf data structures out into the perf-primitives library --- addon/-private/animation/animation.js | 4 +- addon/-private/animation/element-style.js | 4 +- addon/-private/cache-list/fast-array.js | 52 --------- addon/-private/cache-list/index.js | 108 ------------------ .../-private/gestures/streams/stream-event.js | 2 +- .../gestures/streams/stream-series.js | 8 +- addon/-private/gestures/streams/stream.js | 2 +- package.json | 3 +- 8 files changed, 12 insertions(+), 171 deletions(-) delete mode 100644 addon/-private/cache-list/fast-array.js delete mode 100644 addon/-private/cache-list/index.js diff --git a/addon/-private/animation/animation.js b/addon/-private/animation/animation.js index 60779bf9f..f4be0e555 100644 --- a/addon/-private/animation/animation.js +++ b/addon/-private/animation/animation.js @@ -1,10 +1,10 @@ -import CacheList from '../cache-list'; +import HashMap from 'perf-primitives/hash-map'; import ElementStyle from './element-style'; export default class Animation { constructor() { - this.cache = new CacheList(); + this.cache = new HashMap(); } // We dumb diff --git a/addon/-private/animation/element-style.js b/addon/-private/animation/element-style.js index a0ecdd5e6..2d494f090 100644 --- a/addon/-private/animation/element-style.js +++ b/addon/-private/animation/element-style.js @@ -1,5 +1,5 @@ import TransformStyle from './transform-style'; -import CacheList from '../cache-list'; +import HashMap from 'perf-primitives/hash-map'; import ValueTransform from './value-transform'; import TRANSFORM_PROP from './utils/transform-prop'; import LAYOUT_PROPS from './utils/layout-props'; @@ -19,7 +19,7 @@ export default class ElementStyle { } init(values, element) { - this.changes = new CacheList(); + this.changes = new HashMap(); this.hasTransform = false; this.srcStyle = window.getComputedStyle(element); this.transformStyle = new TransformStyle(this.srcStyle.transform); diff --git a/addon/-private/cache-list/fast-array.js b/addon/-private/cache-list/fast-array.js deleted file mode 100644 index 401cd155a..000000000 --- a/addon/-private/cache-list/fast-array.js +++ /dev/null @@ -1,52 +0,0 @@ -export const MAX_ARRAY_LENGTH = 200; - -export default class FastArray { - - constructor(length = MAX_ARRAY_LENGTH, name = 'Unknown Pool') { - this.init(length, name); - } - - init(length = MAX_ARRAY_LENGTH, name = 'Unknown Pool') { - this.name = name; - this.length = 0; - this._length = length; - this._data = new Array(length); - } - - get(index) { - if (index >= 0 && index < this.length) { - return this._data[index]; - } - - return undefined; - } - - forEach(cb) { - for (let i = 0; i < this.length; i++) { - cb(this._data[i], i); - } - } - - push(item) { - let index = this.length++; - - if (index === this._length) { - this._length *= 2; - this._data.length = this._length; - } - - this._data[index] = item; - } - - pop() { - let index = --this.length; - - if (index < 0) { - this.length = 0; - return undefined; - } - - return this._data[index]; - } - -} diff --git a/addon/-private/cache-list/index.js b/addon/-private/cache-list/index.js deleted file mode 100644 index e6785d3e0..000000000 --- a/addon/-private/cache-list/index.js +++ /dev/null @@ -1,108 +0,0 @@ -import EmptyObject from '../ember/empty-object'; -import FastArray from './fast-array'; - -const MAX_ARRAY_SIZE = 200; - -export default class CacheList { - - constructor(length = MAX_ARRAY_SIZE) { - this.length = 0; - this.maxLength = length; - this._indeces = new Array(length); - this._values = new Array(length); - this._map = undefined; - } - - forEach(cb) { - if (this.length >= MAX_ARRAY_SIZE) { - if (this._map instanceof EmptyObject) { - for (let i in this._map) { - cb(this._map[i], i); - } - } else { - this._map.forEach(cb); - } - } else { - for (let i = 0; i < this.length; i++) { - let key; - - if (key = this._indeces[i]) { - cb(this._values[i], key); - } - } - } - } - - get(key) { - if (this.length < MAX_ARRAY_SIZE) { - let index = this._indeces.indexOf(key); - - if (index === -1) { - return undefined; - } - - return this._values[index]; - } - - return this._map.get(key); - } - - set(key, value) { - if (this.length < MAX_ARRAY_SIZE) { - let index = this._indeces.indexOf(key); - - if (index !== -1) { - this._values[index] = value; - return; - } - - index = this.length++; - - if (index !== MAX_ARRAY_SIZE) { - if (index === this.maxLength) { - let len = this.maxLength * 2; - - if (len > MAX_ARRAY_SIZE) { - len = MAX_ARRAY_SIZE; - } - - this.maxLength = len; - this._indeces.length = len; - this._values.length = len; - } - this._indeces[index] = key; - this._values[index] = value; - return; - } - - for (let i = 0; i < MAX_ARRAY_SIZE; i++) { - this._map = typeof Map !== 'undefined' ? new Map() : new EmptyObject(); - this._map.set(this._indeces[i], this._values[i]); - } - this._indeces = undefined; - this._values = undefined; - } - - this._map.set(key, value); - } - - remove(key) { - if (this.length < MAX_ARRAY_SIZE) { - let index = this._indeces.indexOf(key); - - if (index === -1) { - return undefined; - } - - let value = this._values[index]; - - this._indeces[index] = undefined; - this._values[index] = undefined; - - return value; - } - - return this._map.remove(key); - } - -} diff --git a/addon/-private/gestures/streams/stream-event.js b/addon/-private/gestures/streams/stream-event.js index 553a89eb2..02997bdcd 100644 --- a/addon/-private/gestures/streams/stream-event.js +++ b/addon/-private/gestures/streams/stream-event.js @@ -1,5 +1,5 @@ /* global Math, performance */ -import FastArray from '../../cache-list/fast-array'; +import FastArray from 'perf-primitives/fast-array'; const STREAM_EVENT_POOL = new FastArray(undefined, 'StreamEvent Pool'); export default class StreamEvent { diff --git a/addon/-private/gestures/streams/stream-series.js b/addon/-private/gestures/streams/stream-series.js index 05bab0378..ffe792c73 100644 --- a/addon/-private/gestures/streams/stream-series.js +++ b/addon/-private/gestures/streams/stream-series.js @@ -1,16 +1,16 @@ -import FastArray from '../../cache-list/fast-array'; -import { MAX_ARRAY_SIZE } from '../../cache-list/fast-array'; +import FastArray from 'perf-primitives/fast-array'; +import { SMALL_ARRAY_LENGTH } from 'perf-primitives/-constants'; const STREAM_SERIES_POOL = new FastArray(10, 'StreamSeries Pool'); export default class StreamSeries extends FastArray { - constructor(number = MAX_ARRAY_SIZE, name = 'StreamEvent to List') { + constructor(number = SMALL_ARRAY_LENGTH, name = 'StreamEvent to List') { super(number, name); this._isDestroyed = false; } - static create(number = MAX_ARRAY_SIZE, name = 'StreamEvent to List') { + static create(number = SMALL_ARRAY_LENGTH, name = 'StreamEvent to List') { let series = STREAM_SERIES_POOL.pop(); if (series) { diff --git a/addon/-private/gestures/streams/stream.js b/addon/-private/gestures/streams/stream.js index a11b590d0..99dc6ca0b 100644 --- a/addon/-private/gestures/streams/stream.js +++ b/addon/-private/gestures/streams/stream.js @@ -1,7 +1,7 @@ import StreamEvent from './stream-event'; import StreamSeries from './stream-series'; import MacroTask from '../utils/macro-task'; -import FastArray from '../../cache-list/fast-array'; +import FastArray from 'perf-primitives/fast-array'; const STREAM_POOL = new FastArray(5, 'Stream Pool'); diff --git a/package.json b/package.json index 58b5bf639..ef07c4a7d 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,8 @@ "liquid-fire": "0.23.1", "loader.js": "^4.0.1", "morgan": "^1.7.0", - "object-assign": "^4.1.0" + "object-assign": "^4.1.0", + "perf-primitives": "runspired/perf-primitives" }, "keywords": [ "ember-addon" From bc7d025f48c21c0b1fdac3c17fb50e3c14d80ce1 Mon Sep 17 00:00:00 2001 From: Christopher Garrett Date: Wed, 22 Jun 2016 15:59:47 -0700 Subject: [PATCH 55/61] refactor(gestures): Refactors gestures to use streams per pointer --- addon/-private/gestures/inputs/input.js | 104 ++++++++++-------- addon/-private/gestures/inputs/mouse.js | 17 ++- addon/-private/gestures/inputs/touch.js | 35 ++++-- addon/-private/gestures/layer.js | 4 +- addon/-private/gestures/manager.js | 4 +- .../gestures/recognizers/horizontal-pan.js | 10 +- .../-private/gestures/streams/stream-event.js | 11 +- .../gestures/streams/stream-series.js | 14 ++- addon/-private/gestures/streams/stream.js | 35 ++++-- .../app/routes/items/single/template.hbs | 3 +- 10 files changed, 150 insertions(+), 87 deletions(-) diff --git a/addon/-private/gestures/inputs/input.js b/addon/-private/gestures/inputs/input.js index bf8034b02..90686a742 100644 --- a/addon/-private/gestures/inputs/input.js +++ b/addon/-private/gestures/inputs/input.js @@ -1,17 +1,21 @@ import Stream from '../streams/stream'; import StreamEvent from '../streams/stream-event'; +import HashMap from 'perf-primitives/hash-map'; export default class Input { constructor(element, manager) { this.element = element; - this.streams = []; - this.attached = false; this.handler = null; this.handlerStack = []; + + this.attached = false; this.streaming = false; this.hasMoved = false; - this._nextEvent = undefined; + + this.openStreams = 0; + this.streams = new HashMap(); + this._nextEvents = new HashMap(); this._handlers = { start: null, update: null, end: null, interrupt: null }; this.manager = manager; @@ -19,54 +23,60 @@ export default class Input { this.attach(); } - _bind(name) { + _bind(name, ...args) { const { _handlers } = this; - return _handlers[name] = this[name].bind(this); + return _handlers[name] = this[name].bind(this, ...args); + } + + extractThen(name, event) { + this[name](this.extract(event)); } - start(event) { - let stream = Stream.create(); + extractManyThen(name, event) { + this.extractMany(event).forEach(this[name].bind(this)); + } + + start(eventInfo) { + let stream = Stream.create({ + pointerId: eventInfo.pointerId, + originX: eventInfo.x, + originY: eventInfo.y + }); + const { streams } = this; - // splice existing streams - for (let i = 0; i < streams.length; i++) { - // console.log('splitting existing stream'); - streams[i].split(); - } + streams.forEach((stream) => stream.split()); this.streaming = true; - streams.push(stream); + this.openStreams++; + streams.set(stream.pointerId, stream); // console.log('opening new stream'); - let streamEvent = stream.open({ - x: event.clientX, - y: event.clientY, - event - }); + let streamEvent = stream.open(eventInfo); if (this.handler) { this.handlerStack.push(this.handler); this.handler = null; } - this.manager.recognize(this, streams, streamEvent); + this.manager.recognize(this, streams, stream, streamEvent); this._poll(); } - trigger(streamEvent) { + trigger(stream, streamEvent) { if (this.handler) { - this.handler.recognize(this, this.streams, streamEvent); + this.handler.recognize(this, this.streams, stream, streamEvent); } else { - this.manager.recognize(this, this.streams, streamEvent); + this.manager.recognize(this, this.streams, stream, streamEvent); } } - _update(event) { + _update(eventInfo) { // console.log('updating'); let { streams } = this; - let [stream] = streams; + let stream = streams.get(eventInfo.pointerId); let streamEvent; if (!this.streaming) { @@ -74,14 +84,10 @@ export default class Input { } // console.log('closing stream'); - streamEvent = stream.close({ - x: event.clientX, - y: event.clientY, - event - }); + streamEvent = stream.close(eventInfo); this.hasMoved = false; - this.trigger(streamEvent); + this.trigger(stream, streamEvent); let wasRecognizing = this.handler; @@ -89,32 +95,27 @@ export default class Input { // vacate this stream // console.log('removing stream'); - streams.pop(); + streams.delete(stream.pointerId); + this.openStreams--; - if (wasRecognizing && !streams.length) { + if (wasRecognizing && this.openStreams === 0) { this.manager.endInputRecognition(); } } else { - streamEvent = stream.push({ - x: event.clientX, - y: event.clientY, - event - }); + streamEvent = stream.push(eventInfo); - this.trigger(streamEvent); + this.trigger(stream, streamEvent); } } _poll() { return void requestAnimationFrame(() => { - let event = this._nextEvent; - - if (event) { + this._nextEvents.forEach((event, key) => { this._update(event); - this._nextEvent = undefined; - } + this._nextEvents.delete(key); + }); if (this.streaming) { this._poll(); @@ -122,15 +123,16 @@ export default class Input { }); } - update(event) { + update(eventInfo) { if (!this.streaming) { return; } - this._nextEvent = event; + this._nextEvents.set(eventInfo.pointerId, eventInfo); + if (!this.hasMoved) { this.hasMoved = true; - this._update(event); + this._update(eventInfo); } } @@ -138,7 +140,7 @@ export default class Input { if (this.streaming) { // console.log('received close event'); this.streaming = false; - this._nextEvent = event; + this._nextEvents.set(event.pointerId, event); } } @@ -154,6 +156,14 @@ export default class Input { } } + extract() { + throw new Error('Interface Method Not Implemented'); + } + + extractMany() { + throw new Error('Interface Method Not Implemented'); + } + attach() { throw new Error('Interface Method Not Implemented'); } diff --git a/addon/-private/gestures/inputs/mouse.js b/addon/-private/gestures/inputs/mouse.js index 6b60842e9..53b820595 100644 --- a/addon/-private/gestures/inputs/mouse.js +++ b/addon/-private/gestures/inputs/mouse.js @@ -3,6 +3,15 @@ import SUPPORTS_PASSIVE from '../utils/supports-passive'; export default class MouseInput extends Input { + extract(event) { + return { + pointerId: 'MOUSE_POINTER', + x: event.clientX, + y: event.clientY, + event + }; + } + attach() { if (this.attached) { return; @@ -11,10 +20,10 @@ export default class MouseInput extends Input { let opts = SUPPORTS_PASSIVE ? { capture: true, passive: true } : true; - element.addEventListener('mousedown', this._bind('start'), opts); - element.addEventListener('mouseup', this._bind('end'), opts); - element.addEventListener('mouseexit', this._bind('interrupt'), opts); - element.addEventListener('mousemove', this._bind('update'), opts); + element.addEventListener('mousedown', this._bind('extractThen', 'start'), opts); + element.addEventListener('mouseup', this._bind('extractThen', 'end'), opts); + element.addEventListener('mouseexit', this._bind('extractThen', 'interrupt'), opts); + element.addEventListener('mousemove', this._bind('extractThen', 'update'), opts); this.attached = true; } diff --git a/addon/-private/gestures/inputs/touch.js b/addon/-private/gestures/inputs/touch.js index 15bcd1a0d..c47b9fc59 100644 --- a/addon/-private/gestures/inputs/touch.js +++ b/addon/-private/gestures/inputs/touch.js @@ -2,30 +2,47 @@ import Input from './input'; export default class TouchInput extends Input { + extract(event) { + return extractTouch(event.changedTouches[0], event); + } + + extractMany(event) { + return Array.prototype.slice.call(event.changedTouches).map((touch) => extractTouch(touch, event)); + } + attach() { if (this.attached) { return; } const { element } = this; - element.addEventListener('mousedown', this._bind('start') , true); - element.addEventListener('mouseup', this._bind('end') , true); - element.addEventListener('mouseexit', this._bind('interrupt') , true); - element.addEventListener('mousemove', this._bind('update') , true); + element.addEventListener('touchstart', this._bind('extractThen', 'start') , true); + element.addEventListener('touchend', this._bind('extractThen', 'end') , true); + element.addEventListener('touchcancel', this._bind('extractThen', 'interrupt') , true); + element.addEventListener('touchmove', this._bind('extractManyThen', 'update') , true); this.attached = true; } deattach() { - if (this.attached) { + if (!this.attached) { return; } const { element, _handlers } = this; - element.removeEventListener('mousedown', _handlers.start , true); - element.removeEventListener('mouseup', _handlers.end , true); - element.removeEventListener('mouseexit', _handlers.interrupt , true); - element.removeEventListener('mousemove', _handlers.update , true); + element.removeEventListener('touchstart', _handlers.start , true); + element.removeEventListener('touchend', _handlers.end , true); + element.removeEventListener('touchcancel', _handlers.interrupt , true); + element.removeEventListener('touchmove', _handlers.update , true); } } + +function extractTouch(touch, event) { + return { + pointerId: touch.identifier, + x: touch.clientX, + y: touch.clientY, + event + }; +} diff --git a/addon/-private/gestures/layer.js b/addon/-private/gestures/layer.js index 6bc13fa0c..34df7ebfb 100644 --- a/addon/-private/gestures/layer.js +++ b/addon/-private/gestures/layer.js @@ -7,13 +7,13 @@ export default class Layer { this._handlers = {}; } - recognize(input, streams, streamEvent) { + recognize(input, streams, stream, streamEvent) { let { recognizers } = this; for (let i = 0; i < recognizers.length; i++) { let recognizer = recognizers[i]; - if (recognizer.recognize(input, streams, streamEvent)) { + if (recognizer.recognize(input, streams, stream, streamEvent)) { input.handler = recognizer; return true; } diff --git a/addon/-private/gestures/manager.js b/addon/-private/gestures/manager.js index cc95f30ff..e37abf92d 100644 --- a/addon/-private/gestures/manager.js +++ b/addon/-private/gestures/manager.js @@ -34,11 +34,11 @@ export default class Manager { this.inputs[name] = new InputClass(this.rootElement, this); } - recognize(input, streams, streamEvent) { + recognize(input, streams, stream, streamEvent) { let layer = this._findParentLayer(streamEvent.element); while (layer) { - if (layer.recognize(input, streams, streamEvent)) { + if (layer.recognize(input, streams, stream, streamEvent)) { this.startInputRecognition(); break; } diff --git a/addon/-private/gestures/recognizers/horizontal-pan.js b/addon/-private/gestures/recognizers/horizontal-pan.js index 8a0762ce9..f2e91e3a7 100644 --- a/addon/-private/gestures/recognizers/horizontal-pan.js +++ b/addon/-private/gestures/recognizers/horizontal-pan.js @@ -9,10 +9,10 @@ export default class HorizontalPan { this.isRecognizing = false; } - beginRecognizing(input, streams, streamEvent) { + beginRecognizing(input, stream, streamEvent) { this.isRecognizing = true; - this.stream = streams[streams.length - 1]; + this.stream = stream; let { series } = this.stream; series.forEach((event) => { @@ -41,11 +41,11 @@ export default class HorizontalPan { this.layer.emit({ name, event }); } - recognize(input, streams, streamEvent) { + recognize(input, streams, stream, streamEvent) { if (this.isRecognizing) { this.relay(streamEvent); - } else if (streamEvent.totalY === 0 && streamEvent.totalX !== 0) { - this.beginRecognizing(input, streams, streamEvent); + } else if (input.openStreams === 1 && streamEvent.totalY === 0 && streamEvent.totalX !== 0) { + this.beginRecognizing(input, stream, streamEvent); } return this.isRecognizing; diff --git a/addon/-private/gestures/streams/stream-event.js b/addon/-private/gestures/streams/stream-event.js index 02997bdcd..f49d7e90b 100644 --- a/addon/-private/gestures/streams/stream-event.js +++ b/addon/-private/gestures/streams/stream-event.js @@ -15,6 +15,7 @@ export default class StreamEvent { this._source = this._isImportantEvent ? info.event : undefined; this.silenced = false; this.prev = prev; + this.pointerId = info.pointerId; // time this.time = performance.now(); @@ -25,11 +26,17 @@ export default class StreamEvent { this.y = info.y; // deltas off of origin event - this.originX = prev ? (prev.originX || prev.x) : info.x; - this.originY = prev ? (prev.originY || prev.y) : info.y; + this.originX = info.originX; + this.originY = info.originY; this.totalX = info.x - this.originX; this.totalY = info.y - this.originY; + // deltas off the segment + this.segmentOriginX = info.segmentOriginX; + this.segmentOriginY = info.segmentOriginY; + this.segmentX = info.x - this.segmentOriginX; + this.segmentY = info.y - this.segmentOriginY; + // deltas off of last event this.dX = prev ? info.x - prev.x : 0; this.dY = prev ? info.y - prev.y : 0; diff --git a/addon/-private/gestures/streams/stream-series.js b/addon/-private/gestures/streams/stream-series.js index ffe792c73..638c17e93 100644 --- a/addon/-private/gestures/streams/stream-series.js +++ b/addon/-private/gestures/streams/stream-series.js @@ -5,21 +5,27 @@ const STREAM_SERIES_POOL = new FastArray(10, 'StreamSeries Pool'); export default class StreamSeries extends FastArray { - constructor(number = SMALL_ARRAY_LENGTH, name = 'StreamEvent to List') { + constructor(values, number = SMALL_ARRAY_LENGTH, name = 'StreamEvent to List') { super(number, name); this._isDestroyed = false; } - static create(number = SMALL_ARRAY_LENGTH, name = 'StreamEvent to List') { + init({ originX, originY }, length, name) { + super.init(length, name); + this.originX = originX; + this.originY = originY; + } + + static create(values, number = SMALL_ARRAY_LENGTH, name = 'StreamEvent to List') { let series = STREAM_SERIES_POOL.pop(); if (series) { - series.init(number, name); + series.init(values, number, name); return series; } - return new StreamSeries(number, name); + return new StreamSeries(values, number, name); } destroy() { diff --git a/addon/-private/gestures/streams/stream.js b/addon/-private/gestures/streams/stream.js index 99dc6ca0b..c5ace5847 100644 --- a/addon/-private/gestures/streams/stream.js +++ b/addon/-private/gestures/streams/stream.js @@ -7,24 +7,27 @@ const STREAM_POOL = new FastArray(5, 'Stream Pool'); export default class Stream { - constructor() { - this.init(); + constructor(values) { + this.init(values); } - init() { + init({ pointerId, originX, originY }) { this.segments = new FastArray(5, 'Segments'); this.series = undefined; this._isDestroyed = false; this._isDestroying = false; this.active = false; + this.pointerId = pointerId; + this.originX = originX; + this.originY = originY; } open(info) { this.active = true; - this.series = StreamSeries.create(); + this.series = StreamSeries.create({ originX: info.x, originY: info.y }); this.segments.push(this.series); - let streamEvent = StreamEvent.create('start', info); + let streamEvent = StreamEvent.create('start', this._addContextToInfo(info)); this.series.push(streamEvent); return streamEvent; @@ -32,7 +35,7 @@ export default class Stream { push(info) { let lastEvent = this.series.get(this.series.length - 1); - let streamEvent = StreamEvent.create('move', info, lastEvent); + let streamEvent = StreamEvent.create('move', this._addContextToInfo(info), lastEvent); this.series.push(streamEvent); return streamEvent; @@ -41,7 +44,7 @@ export default class Stream { close(info) { this.active = false; let lastEvent = this.series.get(this.series.length - 1); - let streamEvent = StreamEvent.create('end', info, lastEvent); + let streamEvent = StreamEvent.create('end', this._addContextToInfo(info), lastEvent); this.series.push(streamEvent); @@ -61,7 +64,8 @@ export default class Stream { } split() { - this.series = StreamSeries.create(); + let lastEvent = this.series.get(this.series.length - 1); + this.series = StreamSeries.create({ originX: lastEvent.x, originY: lastEvent.y }); this.segments.push(this.series); } @@ -79,15 +83,24 @@ export default class Stream { } } - static create() { + _addContextToInfo(info) { + info.originX = this.originX; + info.originY = this.originY; + info.segmentOriginX = this.series.originX; + info.segmentOriginY = this.series.originY; + + return info; + } + + static create(values) { let stream = STREAM_POOL.pop(); if (stream) { - stream.init(); + stream.init(values); return stream; } - return new Stream(); + return new Stream(values); } } diff --git a/tests/dummy/app/routes/items/single/template.hbs b/tests/dummy/app/routes/items/single/template.hbs index 106f4a3f6..e2c43148a 100644 --- a/tests/dummy/app/routes/items/single/template.hbs +++ b/tests/dummy/app/routes/items/single/template.hbs @@ -3,4 +3,5 @@

{{model.description}}

- \ No newline at end of file + {{link-to 'Back' 'items'}} + From dc0999f3e96cd31a864a109e92b5912d281d5924 Mon Sep 17 00:00:00 2001 From: Arjun Kathuria Date: Tue, 28 Jun 2016 01:34:43 +0530 Subject: [PATCH 56/61] chore(coffee to js): converts Gruntfile.coffee to Gruntfile.js for better consistency and Bumps up a few old package versions to newer ones --- Gruntfile.coffee | 95 ---------------------------------------- Gruntfile.js | 110 +++++++++++++++++++++++++++++++++++++++++++++++ package.json | 16 +++---- 3 files changed, 118 insertions(+), 103 deletions(-) delete mode 100644 Gruntfile.coffee create mode 100644 Gruntfile.js diff --git a/Gruntfile.coffee b/Gruntfile.coffee deleted file mode 100644 index 232100915..000000000 --- a/Gruntfile.coffee +++ /dev/null @@ -1,95 +0,0 @@ -babel = require('rollup-plugin-babel'); -module.exports = (grunt) -> - grunt.initConfig - pkg: grunt.file.readJSON 'package.json' - - usebanner: - taskName: - options: - position: 'top' - banner: ' -/*! <%= pkg.title || pkg.name %> - v<%= pkg.version %> - <%= grunt.template.today("yyyy-mm-dd") %>\n - * <%= pkg.homepage %>\n - *\n - * Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author.name %>;\n - * Licensed under the <%= pkg.license %> license */' - linebreak: true - files: - src: ['./hammer.js','./hammer.min.js'] - - rollup: - options: - format: 'es6' - plugins: [ babel({exclude: 'node_modules/**'}) ] - intro: " (function(window, document, exportName, undefined) { \n'use strict';" - outro: "})(window, document, 'Hammer');" - files: - dest: 'hammer.js' - src: 'src/main.js' - - uglify: - min: - options: - report: 'gzip' - sourceMap: 'hammer.min.map' - files: - 'hammer.min.js': ['hammer.js'] - - 'string-replace': - version: - files: - 'hammer.js': 'hammer.js' - options: - replacements: [ - pattern: '{{PKG_VERSION}}' - replacement: '<%= pkg.version %>' - ] - - jshint: - options: - jshintrc: true - build: - src: ['hammer.js'] - - jscs: - src: [ - 'src/**/*.js' - ] - options: - config: "./.jscsrc" - force: true - - watch: - scripts: - files: ['src/**/*.js'] - tasks: ['rollup','string-replace','uglify','jshint','jscs'] - options: - interrupt: true - - connect: - server: - options: - hostname: "0.0.0.0" - port: 8000 - - qunit: - all: ['tests/unit/index.html'] - - - # Load tasks - grunt.loadNpmTasks 'grunt-rollup'; - grunt.loadNpmTasks 'grunt-contrib-uglify' - grunt.loadNpmTasks 'grunt-contrib-qunit' - grunt.loadNpmTasks 'grunt-contrib-watch' - grunt.loadNpmTasks 'grunt-contrib-jshint' - grunt.loadNpmTasks 'grunt-contrib-connect' - grunt.loadNpmTasks 'grunt-string-replace' - grunt.loadNpmTasks 'grunt-banner' - grunt.loadNpmTasks 'grunt-jscs' - - # Default task(s) - grunt.registerTask 'default', ['connect', 'watch'] - grunt.registerTask 'default-test', ['connect', 'uglify:test', 'watch'] - grunt.registerTask 'build', ['rollup','string-replace', 'uglify:min', 'usebanner', 'test'] - grunt.registerTask 'test', ['jshint', 'jscs','qunit'] - grunt.registerTask 'test-travis', ['build'] diff --git a/Gruntfile.js b/Gruntfile.js new file mode 100644 index 000000000..1e0de644d --- /dev/null +++ b/Gruntfile.js @@ -0,0 +1,110 @@ +var babel = require('rollup-plugin-babel'); + +module.exports = function(grunt) { + grunt.initConfig({ + pkg: grunt.file.readJSON('package.json'), + usebanner: { + taskName: { + options: { + position: 'top', + banner: '/*! <%= pkg.title || pkg.name %> - v<%= pkg.version %> - <%= grunt.template.today("yyyy-mm-dd") %>\n * <%= pkg.homepage %>\n *\n * Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author.name %>;\n * Licensed under the <%= pkg.license %> license */', + linebreak: true + }, + files: { + src: ['./hammer.js', './hammer.min.js'] + } + } + }, + rollup: { + options: { + format: 'es6', + plugins: [ + babel({ + exclude: 'node_modules/**' + }) + ], + intro: " (function(window, document, exportName, undefined) { \n'use strict';", + outro: "})(window, document, 'Hammer');" + }, + files: { + dest: 'hammer.js', + src: 'src/main.js' + } + }, + uglify: { + min: { + options: { + report: 'gzip', + sourceMap: 'hammer.min.map' + }, + files: { + 'hammer.min.js': ['hammer.js'] + } + } + }, + 'string-replace': { + version: { + files: { + 'hammer.js': 'hammer.js' + }, + options: { + replacements: [ + { + pattern: '{{PKG_VERSION}}', + replacement: '<%= pkg.version %>' + } + ] + } + } + }, + jshint: { + options: { + jshintrc: true + }, + build: { + src: ['hammer.js'] + } + }, + jscs: { + src: ['src/**/*.js'], + options: { + config: "./.jscsrc", + force: true + } + }, + watch: { + scripts: { + files: ['src/**/*.js'], + tasks: ['rollup', 'string-replace', 'uglify', 'jshint', 'jscs'], + options: { + interrupt: true + } + } + }, + connect: { + server: { + options: { + hostname: "0.0.0.0", + port: 8000 + } + } + }, + qunit: { + all: ['tests/unit/index.html'] + } + }); + grunt.loadNpmTasks('grunt-rollup'); + grunt.loadNpmTasks('grunt-contrib-uglify'); + grunt.loadNpmTasks('grunt-contrib-qunit'); + grunt.loadNpmTasks('grunt-contrib-watch'); + grunt.loadNpmTasks('grunt-contrib-jshint'); + grunt.loadNpmTasks('grunt-contrib-connect'); + grunt.loadNpmTasks('grunt-string-replace'); + grunt.loadNpmTasks('grunt-banner'); + grunt.loadNpmTasks('grunt-jscs'); + grunt.registerTask('default', ['connect', 'watch']); + grunt.registerTask('default-test', ['connect', 'uglify:test', 'watch']); + grunt.registerTask('build', ['rollup', 'string-replace', 'uglify:min', 'usebanner', 'test']); + grunt.registerTask('test', ['jshint', 'jscs', 'qunit']); + grunt.registerTask('test-travis', ['build']); +}; diff --git a/package.json b/package.json index ea821c6f0..0e9384ee6 100644 --- a/package.json +++ b/package.json @@ -34,18 +34,18 @@ "devDependencies": { "babel-preset-es2015-rollup": "^1.1.1", "changelogplease": "^1.2.0", - "ember-suave": "3.0.1", + "ember-suave": "^3.0.1", "git-tags": "^0.2.4", - "grunt": "0.4.x", - "grunt-banner": "^0.2.3", - "grunt-contrib-connect": "0.7.x", + "grunt": "1.0.x", + "grunt-banner": "^0.6.0", + "grunt-contrib-connect": "^1.0.0", "grunt-contrib-jshint": "^1.0.0", - "grunt-contrib-qunit": "^0.5.1", + "grunt-contrib-qunit": "^1.2.0", "grunt-contrib-uglify": "^1.0.0", - "grunt-contrib-watch": "0.6.x", - "grunt-jscs": "3.0.0", + "grunt-contrib-watch": "^1.0.0", + "grunt-jscs": "^3.0.0", "grunt-rollup": "^0.7.1", - "grunt-string-replace": "^0.2.7", + "grunt-string-replace": "^1.2.x", "hammer-simulator": "git://github.com/hammerjs/simulator#master", "jquery-hammerjs": "2.0.x", "rollup": "^0.26.3", From c1d6807d8e7c2569592a694b08ba2250eb6aee26 Mon Sep 17 00:00:00 2001 From: Arjun Kathuria Date: Fri, 1 Jul 2016 00:06:39 +0530 Subject: [PATCH 57/61] feat(ES6 classes): adds the ES6 class syntax and functionality --- .jscsrc | 1 + .jshintrc | 3 +- .travis.yml | 4 +- src/hammer.js | 26 ++++---- src/input/mouse.js | 21 +++---- src/input/pointerevent.js | 22 +++---- src/input/singletouch.js | 22 +++---- src/input/touch.js | 22 +++---- src/input/touchmouse.js | 31 +++++----- src/inputjs/create-input-instance.js | 8 +-- src/inputjs/input-constructor.js | 45 +++++++------- src/main.js | 34 +++++------ src/manager.js | 64 ++++++++++---------- src/recognizerjs/recognizer-constructor.js | 57 +++++++++-------- src/recognizers/attribute.js | 35 ++++++----- src/recognizers/pan.js | 43 +++++++------ src/recognizers/pinch.js | 35 ++++++----- src/recognizers/press.js | 39 ++++++------ src/recognizers/rotate.js | 31 +++++----- src/recognizers/swipe.js | 39 ++++++------ src/recognizers/tap.js | 60 +++++++++--------- src/touchactionjs/touchaction-constructor.js | 22 +++---- tests/unit/test_hammer.js | 45 ++++++++------ tests/unit/test_jquery_plugin.js | 2 +- 24 files changed, 345 insertions(+), 366 deletions(-) diff --git a/.jscsrc b/.jscsrc index 34c401bc6..bdfe07c49 100644 --- a/.jscsrc +++ b/.jscsrc @@ -7,4 +7,5 @@ ], "disallowConstOutsideModuleScope": false, "requireArrowFunctions": true, + "disallowEmptyBlocks": false } diff --git a/.jshintrc b/.jshintrc index d1dab2ec8..7a0378b38 100644 --- a/.jshintrc +++ b/.jshintrc @@ -36,5 +36,6 @@ "unused": true, "-W116": true, "-W080": true, - "-W038": true + "-W038": true, + "proto": true } diff --git a/.travis.yml b/.travis.yml index 308d9a6e8..b686d4bf4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,6 @@ language: node_js node_js: - - "0.10" + - "0.12" sudo: false @@ -8,4 +8,4 @@ before_script: - npm install -g grunt-cli script: - - grunt test-travis \ No newline at end of file + - grunt test-travis diff --git a/src/hammer.js b/src/hammer.js index 5eee80235..c016ee27d 100644 --- a/src/hammer.js +++ b/src/hammer.js @@ -1,13 +1,13 @@ import ifUndefined from './utils/if-undefined'; import { TOUCH_ACTION_COMPUTE } from './touchactionjs/touchaction-Consts'; import { DIRECTION_HORIZONTAL } from './inputjs/input-consts'; -import { RotateRecognizer } from './recognizers/rotate'; -import { PinchRecognizer } from './recognizers/pinch'; -import { SwipeRecognizer } from './recognizers/swipe'; -import { PanRecognizer } from './recognizers/pan'; -import { TapRecognizer } from './recognizers/tap'; -import { PressRecognizer } from './recognizers/press'; -import { Manager } from './manager'; +import RotateRecognizer from './recognizers/rotate'; +import PinchRecognizer from './recognizers/pinch'; +import SwipeRecognizer from './recognizers/swipe'; +import PanRecognizer from './recognizers/pan'; +import TapRecognizer from './recognizers/tap'; +import PressRecognizer from './recognizers/press'; +import Manager from './manager'; /** * @private @@ -16,10 +16,12 @@ import { Manager } from './manager'; * @param {Object} [options] * @constructor */ -function Hammer(element, options) { - options = options || {}; - options.recognizers = ifUndefined(options.recognizers, Hammer.defaults.preset); - return new Manager(element, options); +export default class Hammer { + constructor(element, options) { + options = options || {}; + options.recognizers = ifUndefined(options.recognizers, Hammer.defaults.preset); + return new Manager(element, options); + } } /** @@ -153,5 +155,3 @@ Hammer.defaults = { tapHighlightColor: 'rgba(0,0,0,0)' } }; - -export { Hammer }; diff --git a/src/input/mouse.js b/src/input/mouse.js index e537e74b8..5ef0ebf97 100644 --- a/src/input/mouse.js +++ b/src/input/mouse.js @@ -4,8 +4,7 @@ import { INPUT_END, INPUT_TYPE_MOUSE } from '../inputjs/input-consts'; -import { Input } from '../inputjs/input-constructor'; -import inherit from '../utils/inherit'; +import Input from '../inputjs/input-constructor'; const MOUSE_INPUT_MAP = { mousedown: INPUT_START, @@ -22,16 +21,16 @@ const MOUSE_WINDOW_EVENTS = 'mousemove mouseup'; * @constructor * @extends Input */ -function MouseInput() { - this.evEl = MOUSE_ELEMENT_EVENTS; - this.evWin = MOUSE_WINDOW_EVENTS; +export default class MouseInput extends Input { + constructor() { + super(...arguments); - this.pressed = false; // mousedown state + this.evEl = MOUSE_ELEMENT_EVENTS; + this.evWin = MOUSE_WINDOW_EVENTS; - Input.apply(this, arguments); -} + this.pressed = false; // mousedown state + } -inherit(MouseInput, Input, { /** * @private * handle mouse events @@ -65,6 +64,4 @@ inherit(MouseInput, Input, { srcEvent: ev }); } -}); - -export { MouseInput }; +} diff --git a/src/input/pointerevent.js b/src/input/pointerevent.js index 1298582de..78ef8943a 100644 --- a/src/input/pointerevent.js +++ b/src/input/pointerevent.js @@ -8,8 +8,7 @@ import { INPUT_TYPE_PEN, INPUT_TYPE_KINECT } from '../inputjs/input-consts'; -import { Input } from '../inputjs/input-constructor'; -import inherit from '../utils/inherit'; +import Input from '../inputjs/input-constructor'; import inArray from '../utils/in-array'; const POINTER_INPUT_MAP = { @@ -43,16 +42,15 @@ if (window.MSPointerEvent && !window.PointerEvent) { * @constructor * @extends Input */ -function PointerEventInput() { - this.evEl = POINTER_ELEMENT_EVENTS; - this.evWin = POINTER_WINDOW_EVENTS; +export default class PointerEventInput extends Input { + constructor() { + super(...arguments); + this.evEl = POINTER_ELEMENT_EVENTS; + this.evWin = POINTER_WINDOW_EVENTS; - Input.apply(this, arguments); - - this.store = (this.manager.session.pointerEvents = []); -} + this.store = (this.manager.session.pointerEvents = []); + } -inherit(PointerEventInput, Input, { /** * @private * handle mouse events @@ -101,6 +99,4 @@ inherit(PointerEventInput, Input, { store.splice(storeIndex, 1); } } -}); - -export { PointerEventInput }; +} diff --git a/src/input/singletouch.js b/src/input/singletouch.js index 2e12e5af0..bc315985d 100644 --- a/src/input/singletouch.js +++ b/src/input/singletouch.js @@ -5,8 +5,7 @@ import { INPUT_CANCEL, INPUT_TYPE_TOUCH } from '../inputjs/input-consts'; -import { Input } from '../inputjs/input-constructor'; -import inherit from '../utils/inherit'; +import Input from '../inputjs/input-constructor'; import toArray from '../utils/to-array'; import uniqueArray from '../utils/unique-array'; @@ -26,15 +25,16 @@ const SINGLE_TOUCH_WINDOW_EVENTS = 'touchstart touchmove touchend touchcancel'; * @constructor * @extends Input */ -function SingleTouchInput() { - this.evTarget = SINGLE_TOUCH_TARGET_EVENTS; - this.evWin = SINGLE_TOUCH_WINDOW_EVENTS; - this.started = false; +export default class SingleTouchInput extends Input { + constructor() { + super(...arguments); + this.evTarget = SINGLE_TOUCH_TARGET_EVENTS; + this.evWin = SINGLE_TOUCH_WINDOW_EVENTS; + this.started = false; - Input.apply(this, arguments); -} + Input.apply(this, arguments); + } -inherit(SingleTouchInput, Input, { handler(ev) { let type = SINGLE_TOUCH_INPUT_MAP[ev.type]; @@ -61,7 +61,7 @@ inherit(SingleTouchInput, Input, { srcEvent: ev }); } -}); +} /** * @private @@ -80,5 +80,3 @@ function normalizeSingleTouches(ev, type) { return [all, changed]; } - -export { SingleTouchInput }; diff --git a/src/input/touch.js b/src/input/touch.js index 9d02b1f8b..b482a15e1 100644 --- a/src/input/touch.js +++ b/src/input/touch.js @@ -5,8 +5,7 @@ import { INPUT_CANCEL, INPUT_TYPE_TOUCH } from '../inputjs/input-consts'; -import { Input } from '../inputjs/input-constructor'; -import inherit from '../utils/inherit'; +import Input from '../inputjs/input-constructor'; import toArray from '../utils/to-array'; import hasParent from '../utils/has-parent'; import uniqueArray from '../utils/unique-array'; @@ -26,14 +25,17 @@ const TOUCH_TARGET_EVENTS = 'touchstart touchmove touchend touchcancel'; * @constructor * @extends Input */ -function TouchInput() { - this.evTarget = TOUCH_TARGET_EVENTS; - this.targetIds = {}; +export default class TouchInput extends Input { - Input.apply(this, arguments); -} + constructor() { + TouchInput.prototype.evTarget = TOUCH_TARGET_EVENTS; + TouchInput.prototype.targetIds = {}; + super(...arguments); + + this.evTarget = TOUCH_TARGET_EVENTS; + this.targetIds = {}; + } -inherit(TouchInput, Input, { handler(ev) { let type = TOUCH_INPUT_MAP[ev.type]; let touches = getTouches.call(this, ev, type); @@ -48,7 +50,7 @@ inherit(TouchInput, Input, { srcEvent: ev }); } -}); +} /** * @private @@ -111,5 +113,3 @@ function getTouches(ev, type) { changedTargetTouches ]; } - -export { TouchInput }; diff --git a/src/input/touchmouse.js b/src/input/touchmouse.js index 446325555..f771d4774 100644 --- a/src/input/touchmouse.js +++ b/src/input/touchmouse.js @@ -1,8 +1,7 @@ -import { Input } from '../inputjs/input-constructor'; -import inherit from '../utils/inherit'; +import Input from '../inputjs/input-constructor'; import bindFn from '../utils/bind-fn'; -import { TouchInput } from './touch'; -import { MouseInput } from './mouse'; +import TouchInput from './touch'; +import MouseInput from './mouse'; import { INPUT_START, INPUT_END, @@ -25,18 +24,18 @@ import { const DEDUP_TIMEOUT = 2500; const DEDUP_DISTANCE = 25; -function TouchMouseInput() { - Input.apply(this, arguments); +export default class TouchMouseInput extends Input { + constructor() { + super(...arguments); - let handler = bindFn(this.handler, this); - this.touch = new TouchInput(this.manager, handler); - this.mouse = new MouseInput(this.manager, handler); + let handler = bindFn(this.handler, this); + this.touch = new TouchInput(this.manager, handler); + this.mouse = new MouseInput(this.manager, handler); - this.primaryTouch = null; - this.lastTouches = []; -} + this.primaryTouch = null; + this.lastTouches = []; + } -inherit(TouchMouseInput, Input, { /** * @private * handle mouse and touch events @@ -60,7 +59,7 @@ inherit(TouchMouseInput, Input, { } this.callback(manager, inputEvent, inputData); - }, + } /** * @private @@ -70,7 +69,7 @@ inherit(TouchMouseInput, Input, { this.touch.destroy(); this.mouse.destroy(); } -}); +} function recordTouches(eventType, eventData) { if (eventType & INPUT_START) { @@ -110,5 +109,3 @@ function isSyntheticEvent(eventData) { } return false; } - -export { TouchMouseInput }; diff --git a/src/inputjs/create-input-instance.js b/src/inputjs/create-input-instance.js index 9abdf1091..977dc05a1 100644 --- a/src/inputjs/create-input-instance.js +++ b/src/inputjs/create-input-instance.js @@ -1,9 +1,9 @@ import { SUPPORT_POINTER_EVENTS,SUPPORT_ONLY_TOUCH,SUPPORT_TOUCH } from './input-consts'; import inputHandler from './input-handler'; -import { PointerEventInput } from '../input/pointerevent'; -import { TouchInput } from '../input/touch'; -import { MouseInput } from '../input/mouse'; -import { TouchMouseInput } from '../input/touchmouse'; +import PointerEventInput from '../input/pointerevent'; +import TouchInput from '../input/touch'; +import MouseInput from '../input/mouse'; +import TouchMouseInput from '../input/touchmouse'; /** * @private diff --git a/src/inputjs/input-constructor.js b/src/inputjs/input-constructor.js index 41c99ac89..1a1caa9b0 100644 --- a/src/inputjs/input-constructor.js +++ b/src/inputjs/input-constructor.js @@ -11,32 +11,31 @@ import getWindowForElement from '../utils/get-window-for-element'; * @returns {Input} * @constructor */ -function Input(manager, callback) { - let self = this; - this.manager = manager; - this.callback = callback; - this.element = manager.element; - this.target = manager.options.inputTarget; +export default class Input { + constructor(manager, callback) { + let self = this; + this.manager = manager; + this.callback = callback; + this.element = manager.element; + this.target = manager.options.inputTarget; + + // smaller wrapper around the handler, for the scope and the enabled state of the manager, + // so when disabled the input events are completely bypassed. + this.domHandler = function(ev) { + if (boolOrFn(manager.options.enable, [manager])) { + self.handler(ev); + } + }; + + this.init(); - // smaller wrapper around the handler, for the scope and the enabled state of the manager, - // so when disabled the input events are completely bypassed. - this.domHandler = function(ev) { - if (boolOrFn(manager.options.enable, [manager])) { - self.handler(ev); - } - }; - - this.init(); - -} - -Input.prototype = { + } /** * @private * should handle the inputEvent data and trigger the callback * @virtual */ - handler() { }, + handler() { } /** * @private @@ -46,7 +45,7 @@ Input.prototype = { this.evEl && addEventListeners(this.element, this.evEl, this.domHandler); this.evTarget && addEventListeners(this.target, this.evTarget, this.domHandler); this.evWin && addEventListeners(getWindowForElement(this.element), this.evWin, this.domHandler); - }, + } /** * @private @@ -57,6 +56,4 @@ Input.prototype = { this.evTarget && removeEventListeners(this.target, this.evTarget, this.domHandler); this.evWin && removeEventListeners(getWindowForElement(this.element), this.evWin, this.domHandler); } -}; - -export { Input }; +} diff --git a/src/main.js b/src/main.js index 0baa47e0e..c2bfb791e 100644 --- a/src/main.js +++ b/src/main.js @@ -1,4 +1,4 @@ -import { Hammer } from './hammer'; +import Hammer from './hammer'; import assign from './utils/assign'; import { INPUT_START, @@ -26,23 +26,23 @@ import { DIRECTION_ALL } from './inputjs/input-consts'; -import { Manager } from './manager'; -import { Input } from './inputjs/input-constructor'; -import { TouchAction } from './touchactionjs/touchaction-constructor'; -import { TouchInput } from './input/touch'; -import { MouseInput } from './input/mouse'; -import { PointerEventInput } from './input/pointerevent'; -import { SingleTouchInput } from './input/singletouch'; -import { TouchMouseInput } from './input/touchmouse'; +import Manager from './manager'; +import Input from './inputjs/input-constructor'; +import TouchAction from './touchactionjs/touchaction-constructor'; +import TouchInput from './input/touch'; +import MouseInput from './input/mouse'; +import PointerEventInput from './input/pointerevent'; +import SingleTouchInput from './input/singletouch'; +import TouchMouseInput from './input/touchmouse'; -import { Recognizer } from './recognizerjs/recognizer-constructor'; -import { AttrRecognizer } from './recognizers/attribute'; -import { TapRecognizer } from './recognizers/tap'; -import { PanRecognizer } from './recognizers/pan'; -import { SwipeRecognizer } from './recognizers/swipe'; -import { PinchRecognizer } from './recognizers/pinch'; -import { RotateRecognizer } from './recognizers/rotate'; -import { PressRecognizer } from './recognizers/press'; +import Recognizer from './recognizerjs/recognizer-constructor'; +import AttrRecognizer from './recognizers/attribute'; +import TapRecognizer from './recognizers/tap'; +import PanRecognizer from './recognizers/pan'; +import SwipeRecognizer from './recognizers/swipe'; +import PinchRecognizer from './recognizers/pinch'; +import RotateRecognizer from './recognizers/rotate'; +import PressRecognizer from './recognizers/press'; import addEventListeners from './utils/add-event-listeners'; import removeEventListeners from './utils/remove-event-listeners'; diff --git a/src/manager.js b/src/manager.js index 9a3de6096..278449f15 100644 --- a/src/manager.js +++ b/src/manager.js @@ -1,13 +1,13 @@ import assign from './utils/assign'; -import { Hammer } from './hammer'; -import { TouchAction } from './touchactionjs/touchaction-constructor'; +import Hammer from './hammer'; +import TouchAction from './touchactionjs/touchaction-constructor'; import createInputInstance from './inputjs/create-input-instance'; import each from './utils/each'; import inArray from './utils/in-array'; import invokeArrayArg from './utils/invoke-array-arg'; import splitStr from './utils/split-str'; import prefixed from './utils/prefixed'; -import { Recognizer } from './recognizerjs/recognizer-constructor'; +import Recognizer from './recognizerjs/recognizer-constructor'; import { STATE_BEGAN, STATE_ENDED, @@ -25,30 +25,30 @@ const FORCED_STOP = 2; * @param {Object} [options] * @constructor */ -function Manager(element, options) { - this.options = assign({}, Hammer.defaults, options || {}); +export default class Manager { + constructor(element, options) { + this.options = assign({}, Hammer.defaults, options || {}); - this.options.inputTarget = this.options.inputTarget || element; + this.options.inputTarget = this.options.inputTarget || element; - this.handlers = {}; - this.session = {}; - this.recognizers = []; - this.oldCssProps = {}; + this.handlers = {}; + this.session = {}; + this.recognizers = []; + this.oldCssProps = {}; - this.element = element; - this.input = createInputInstance(this); - this.touchAction = new TouchAction(this, this.options.touchAction); + this.element = element; + this.input = createInputInstance(this); + this.touchAction = new TouchAction(this, this.options.touchAction); - toggleCssProps(this, true); + toggleCssProps(this, true); - each(this.options.recognizers, (item) => { - let recognizer = this.add(new (item[0])(item[1])); - item[2] && recognizer.recognizeWith(item[2]); - item[3] && recognizer.requireFailure(item[3]); - }, this); -} + each(this.options.recognizers, (item) => { + let recognizer = this.add(new (item[0])(item[1])); + item[2] && recognizer.recognizeWith(item[2]); + item[3] && recognizer.requireFailure(item[3]); + }, this); + } -Manager.prototype = { /** * @private * set options @@ -69,7 +69,7 @@ Manager.prototype = { this.input.init(); } return this; - }, + } /** * @private @@ -80,7 +80,7 @@ Manager.prototype = { */ stop(force) { this.session.stopped = force ? FORCED_STOP : STOP; - }, + } /** * @private @@ -137,7 +137,7 @@ Manager.prototype = { } i++; } - }, + } /** * @private @@ -157,7 +157,7 @@ Manager.prototype = { } } return null; - }, + } /** * @private add a recognizer to the manager @@ -181,7 +181,7 @@ Manager.prototype = { this.touchAction.update(); return recognizer; - }, + } /** * @private @@ -208,7 +208,7 @@ Manager.prototype = { } return this; - }, + } /** * @private @@ -231,7 +231,7 @@ Manager.prototype = { handlers[event].push(handler); }); return this; - }, + } /** * @private unbind event, leave emit blank to remove all handlers @@ -253,7 +253,7 @@ Manager.prototype = { } }); return this; - }, + } /** * @private emit event to the listeners @@ -282,7 +282,7 @@ Manager.prototype = { handlers[i](data); i++; } - }, + } /** * @private @@ -297,7 +297,7 @@ Manager.prototype = { this.input.destroy(); this.element = null; } -}; +} /** * @private @@ -337,5 +337,3 @@ function triggerDomEvent(event, data) { gestureEvent.gesture = data; data.target.dispatchEvent(gestureEvent); } - -export { Manager }; diff --git a/src/recognizerjs/recognizer-constructor.js b/src/recognizerjs/recognizer-constructor.js index 3612c3cca..8939596a0 100644 --- a/src/recognizerjs/recognizer-constructor.js +++ b/src/recognizerjs/recognizer-constructor.js @@ -52,29 +52,30 @@ import stateStr from './state-str'; * @constructor * @param {Object} options */ -function Recognizer(options) { - this.options = assign({}, this.defaults, options || {}); +export default class Recognizer { + constructor(options) { + this.options = assign({}, this.defaults, options || {}); - this.id = uniqueId(); + this.id = uniqueId(); - this.manager = null; + this.manager = null; - // default is enable true - this.options.enable = ifUndefined(this.options.enable, true); + // default is enable true + this.options.enable = ifUndefined(this.options.enable, true); - this.state = STATE_POSSIBLE; + this.state = STATE_POSSIBLE; - this.simultaneous = {}; - this.requireFail = []; -} - -Recognizer.prototype = { + this.simultaneous = {}; + this.requireFail = []; + } /** * @private * @virtual * @type {Object} */ - defaults: {}, + get defaults() { + return {}; + } /** * @private @@ -88,7 +89,7 @@ Recognizer.prototype = { // also update the touchAction, in case something changed about the directions/enabled state this.manager && this.manager.touchAction.update(); return this; - }, + } /** * @private @@ -108,7 +109,7 @@ Recognizer.prototype = { otherRecognizer.recognizeWith(this); } return this; - }, + } /** * @private @@ -124,7 +125,7 @@ Recognizer.prototype = { otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this); delete this.simultaneous[otherRecognizer.id]; return this; - }, + } /** * @private @@ -144,7 +145,7 @@ Recognizer.prototype = { otherRecognizer.requireFailure(this); } return this; - }, + } /** * @private @@ -163,7 +164,7 @@ Recognizer.prototype = { this.requireFail.splice(index, 1); } return this; - }, + } /** * @private @@ -172,7 +173,7 @@ Recognizer.prototype = { */ hasRequireFailures() { return this.requireFail.length > 0; - }, + } /** * @private @@ -182,7 +183,7 @@ Recognizer.prototype = { */ canRecognizeWith(otherRecognizer) { return !!this.simultaneous[otherRecognizer.id]; - }, + } /** * @private @@ -213,7 +214,7 @@ Recognizer.prototype = { if (state >= STATE_ENDED) { emit(self.options.event + stateStr(state)); } - }, + } /** * @private @@ -228,7 +229,7 @@ Recognizer.prototype = { } // it's failing anyway this.state = STATE_FAILED; - }, + } /** * @private @@ -244,7 +245,7 @@ Recognizer.prototype = { i++; } return true; - }, + } /** * @private @@ -275,7 +276,7 @@ Recognizer.prototype = { if (this.state & (STATE_BEGAN | STATE_CHANGED | STATE_ENDED | STATE_CANCELLED)) { this.tryEmit(inputDataClone); } - }, + } /** * @private @@ -287,7 +288,7 @@ Recognizer.prototype = { */ /* jshint ignore:start */ - process(inputData) { }, + process(inputData) { } /* jshint ignore:end */ /** @@ -296,7 +297,7 @@ Recognizer.prototype = { * @virtual * @returns {Array} */ - getTouchAction() { }, + getTouchAction() { } /** * @private @@ -305,6 +306,4 @@ Recognizer.prototype = { * @virtual */ reset() { } -}; - -export { Recognizer }; +} diff --git a/src/recognizers/attribute.js b/src/recognizers/attribute.js index f1a7bca2f..b2474a681 100644 --- a/src/recognizers/attribute.js +++ b/src/recognizers/attribute.js @@ -1,5 +1,4 @@ -import inherit from '../utils/inherit'; -import { Recognizer } from '../recognizerjs/recognizer-constructor'; +import Recognizer from '../recognizerjs/recognizer-constructor'; import { STATE_BEGAN, STATE_CHANGED, @@ -18,24 +17,26 @@ import { * @constructor * @extends Recognizer */ -function AttrRecognizer() { - Recognizer.apply(this, arguments); -} +export default class AttrRecognizer extends Recognizer { + constructor() { + super(...arguments); + } -inherit(AttrRecognizer, Recognizer, { /** * @private * @namespace * @memberof AttrRecognizer */ - defaults: { - /** - * @private - * @type {Number} - * @default 1 - */ - pointers: 1 - }, + get defaults() { + return { + /** + * @private + * @type {Number} + * @default 1 + */ + pointers: 1 + }; + } /** * @private @@ -47,7 +48,7 @@ inherit(AttrRecognizer, Recognizer, { attrTest(input) { let optionPointers = this.options.pointers; return optionPointers === 0 || input.pointers.length === optionPointers; - }, + } /** * @private @@ -76,6 +77,4 @@ inherit(AttrRecognizer, Recognizer, { } return STATE_FAILED; } -}); - -export { AttrRecognizer }; +} diff --git a/src/recognizers/pan.js b/src/recognizers/pan.js index 4edc00865..228c6b1c9 100644 --- a/src/recognizers/pan.js +++ b/src/recognizers/pan.js @@ -1,5 +1,4 @@ -import { AttrRecognizer } from './attribute'; -import inherit from '../utils/inherit'; +import AttrRecognizer from './attribute'; import { DIRECTION_ALL, DIRECTION_HORIZONTAL, @@ -21,25 +20,27 @@ import directionStr from '../recognizerjs/direction-str'; * @constructor * @extends AttrRecognizer */ -function PanRecognizer() { - AttrRecognizer.apply(this, arguments); +export default class PanRecognizer extends AttrRecognizer { + constructor() { + super(...arguments); - this.pX = null; - this.pY = null; -} + this.pX = null; + this.pY = null; + } -inherit(PanRecognizer, AttrRecognizer, { /** * @private * @namespace * @memberof PanRecognizer */ - defaults: { - event: 'pan', - threshold: 10, - pointers: 1, - direction: DIRECTION_ALL - }, + get defaults() { + return { + event: 'pan', + threshold: 10, + pointers: 1, + direction: DIRECTION_ALL + }; + } getTouchAction() { let { options:{ direction } } = this; @@ -51,7 +52,7 @@ inherit(PanRecognizer, AttrRecognizer, { actions.push(TOUCH_ACTION_PAN_X); } return actions; - }, + } directionTest(input) { let { options } = this; @@ -75,12 +76,12 @@ inherit(PanRecognizer, AttrRecognizer, { } input.direction = direction; return hasMoved && distance > options.threshold && direction & options.direction; - }, + } attrTest(input) { - return AttrRecognizer.prototype.attrTest.call(this, input) && + return AttrRecognizer.prototype.attrTest.call(this, input) && // replace with a super call (this.state & STATE_BEGAN || (!(this.state & STATE_BEGAN) && this.directionTest(input))); - }, + } emit(input) { @@ -92,8 +93,6 @@ inherit(PanRecognizer, AttrRecognizer, { if (direction) { input.additionalEvent = this.options.event + direction; } - this._super.emit.call(this, input); + super.emit(input); } -}); - -export { PanRecognizer }; +} diff --git a/src/recognizers/pinch.js b/src/recognizers/pinch.js index 02e6c1901..a409a92be 100644 --- a/src/recognizers/pinch.js +++ b/src/recognizers/pinch.js @@ -1,5 +1,4 @@ -import { AttrRecognizer } from './attribute'; -import inherit from '../utils/inherit'; +import AttrRecognizer from './attribute'; import { TOUCH_ACTION_NONE } from '../touchactionjs/touchaction-Consts'; import { STATE_BEGAN } from '../recognizerjs/recognizer-consts'; @@ -10,38 +9,38 @@ import { STATE_BEGAN } from '../recognizerjs/recognizer-consts'; * @constructor * @extends AttrRecognizer */ -function PinchRecognizer() { - AttrRecognizer.apply(this, arguments); -} +export default class PinchRecognizer extends AttrRecognizer { + constructor() { + super(...arguments); + } -inherit(PinchRecognizer, AttrRecognizer, { /** * @private * @namespace * @memberof PinchRecognizer */ - defaults: { - event: 'pinch', - threshold: 0, - pointers: 2 - }, + get defaults() { + return { + event: 'pinch', + threshold: 0, + pointers: 2 + }; + } getTouchAction() { return [TOUCH_ACTION_NONE]; - }, + } attrTest(input) { - return this._super.attrTest.call(this, input) && + return super.attrTest(input) && (Math.abs(input.scale - 1) > this.options.threshold || this.state & STATE_BEGAN); - }, + } emit(input) { if (input.scale !== 1) { let inOut = input.scale < 1 ? 'in' : 'out'; input.additionalEvent = this.options.event + inOut; } - this._super.emit.call(this, input); + super.emit(input); } -}); - -export { PinchRecognizer }; +} diff --git a/src/recognizers/press.js b/src/recognizers/press.js index 60f6153db..a51123ce9 100644 --- a/src/recognizers/press.js +++ b/src/recognizers/press.js @@ -1,9 +1,8 @@ -import { Recognizer } from '../recognizerjs/recognizer-constructor'; +import Recognizer from '../recognizerjs/recognizer-constructor'; import { STATE_RECOGNIZED, STATE_FAILED } from '../recognizerjs/recognizer-consts'; -import inherit from '../utils/inherit'; import { now } from '../utils/utils-consts'; import setTimeoutContext from '../utils/set-timeout-context'; import { TOUCH_ACTION_AUTO } from '../touchactionjs/touchaction-Consts'; @@ -20,29 +19,31 @@ import { * @constructor * @extends Recognizer */ -function PressRecognizer() { - Recognizer.apply(this, arguments); +export default class PressRecognizer extends Recognizer { + constructor() { + super(...arguments); - this._timer = null; - this._input = null; -} + this._timer = null; + this._input = null; + } -inherit(PressRecognizer, Recognizer, { /** * @private * @namespace * @memberof PressRecognizer */ - defaults: { - event: 'press', - pointers: 1, - time: 251, // minimal time of the pointer to be pressed - threshold: 9 // a minimal movement is ok, but keep it low - }, + get defaults() { + return { + event: 'press', + pointers: 1, + time: 251, // minimal time of the pointer to be pressed + threshold: 9 // a minimal movement is ok, but keep it low + }; + } getTouchAction() { return [TOUCH_ACTION_AUTO]; - }, + } process(input) { let { options } = this; @@ -66,11 +67,11 @@ inherit(PressRecognizer, Recognizer, { return STATE_RECOGNIZED; } return STATE_FAILED; - }, + } reset() { clearTimeout(this._timer); - }, + } emit(input) { if (this.state !== STATE_RECOGNIZED) { @@ -84,6 +85,4 @@ inherit(PressRecognizer, Recognizer, { this.manager.emit(this.options.event, this._input); } } -}); - -export { PressRecognizer }; +} diff --git a/src/recognizers/rotate.js b/src/recognizers/rotate.js index e6d9ec4e4..96b51d1fd 100644 --- a/src/recognizers/rotate.js +++ b/src/recognizers/rotate.js @@ -1,5 +1,4 @@ -import { AttrRecognizer } from './attribute'; -import inherit from '../utils/inherit'; +import AttrRecognizer from './attribute'; import { TOUCH_ACTION_NONE } from '../touchactionjs/touchaction-Consts'; import { STATE_BEGAN } from '../recognizerjs/recognizer-consts'; @@ -10,30 +9,30 @@ import { STATE_BEGAN } from '../recognizerjs/recognizer-consts'; * @constructor * @extends AttrRecognizer */ -function RotateRecognizer() { - AttrRecognizer.apply(this, arguments); -} +export default class RotateRecognizer extends AttrRecognizer { + constructor() { + super(...arguments); + } -inherit(RotateRecognizer, AttrRecognizer, { /** * @private * @namespace * @memberof RotateRecognizer */ - defaults: { - event: 'rotate', - threshold: 0, - pointers: 2 - }, + get defaults() { + return { + event: 'rotate', + threshold: 0, + pointers: 2 + }; + } getTouchAction() { return [TOUCH_ACTION_NONE]; - }, + } attrTest(input) { - return this._super.attrTest.call(this, input) && + return super.attrTest(input) && (Math.abs(input.rotation) > this.options.threshold || this.state & STATE_BEGAN); } -}); - -export {RotateRecognizer}; +} diff --git a/src/recognizers/swipe.js b/src/recognizers/swipe.js index e4b39798d..1c81036e0 100644 --- a/src/recognizers/swipe.js +++ b/src/recognizers/swipe.js @@ -1,8 +1,7 @@ -import { AttrRecognizer } from '../recognizers/attribute'; -import inherit from '../utils/inherit'; +import AttrRecognizer from '../recognizers/attribute'; import { abs } from '../utils/utils-consts'; import { DIRECTION_HORIZONTAL,DIRECTION_VERTICAL } from '../inputjs/input-consts'; -import { PanRecognizer } from './pan'; +import PanRecognizer from './pan'; import { INPUT_END } from '../inputjs/input-consts'; import directionStr from '../recognizerjs/direction-str'; @@ -13,27 +12,29 @@ import directionStr from '../recognizerjs/direction-str'; * @constructor * @extends AttrRecognizer */ -function SwipeRecognizer() { - AttrRecognizer.apply(this, arguments); -} +export default class SwipeRecognizer extends AttrRecognizer{ + constructor() { + super(...arguments); + } -inherit(SwipeRecognizer, AttrRecognizer, { /** * @private * @namespace * @memberof SwipeRecognizer */ - defaults: { - event: 'swipe', - threshold: 10, - velocity: 0.3, - direction: DIRECTION_HORIZONTAL | DIRECTION_VERTICAL, - pointers: 1 - }, + get defaults() { + return { + event: 'swipe', + threshold: 10, + velocity: 0.3, + direction: DIRECTION_HORIZONTAL | DIRECTION_VERTICAL, + pointers: 1 + }; + } getTouchAction() { return PanRecognizer.prototype.getTouchAction.call(this); - }, + } attrTest(input) { let { direction } = this.options; @@ -47,12 +48,12 @@ inherit(SwipeRecognizer, AttrRecognizer, { velocity = input.overallVelocityY; } - return this._super.attrTest.call(this, input) && + return super.attrTest(input) && direction & input.offsetDirection && input.distance > this.options.threshold && input.maxPointers === this.options.pointers && abs(velocity) > this.options.velocity && input.eventType & INPUT_END; - }, + } emit(input) { let direction = directionStr(input.offsetDirection); @@ -62,6 +63,4 @@ inherit(SwipeRecognizer, AttrRecognizer, { this.manager.emit(this.options.event, input); } -}); - -export { SwipeRecognizer }; +} diff --git a/src/recognizers/tap.js b/src/recognizers/tap.js index 774f6af1b..e838d8d4b 100644 --- a/src/recognizers/tap.js +++ b/src/recognizers/tap.js @@ -1,6 +1,5 @@ -import inherit from '../utils/inherit'; import setTimeoutContext from '../utils/set-timeout-context'; -import { Recognizer } from '../recognizerjs/recognizer-constructor'; +import Recognizer from '../recognizerjs/recognizer-constructor'; import { TOUCH_ACTION_MANIPULATION } from '../touchactionjs/touchaction-Consts'; import {INPUT_START,INPUT_END } from '../inputjs/input-consts'; import { @@ -21,38 +20,39 @@ import getDistance from '../inputjs/get-distance'; * @constructor * @extends Recognizer */ -function TapRecognizer() { - Recognizer.apply(this, arguments); - - // previous time and center, - // used for tap counting - this.pTime = false; - this.pCenter = false; - - this._timer = null; - this._input = null; - this.count = 0; -} +export default class TapRecognizer extends Recognizer { + constructor() { + super(...arguments); + // previous time and center, + // used for tap counting + this.pTime = false; + this.pCenter = false; + + this._timer = null; + this._input = null; + this.count = 0; + } -inherit(TapRecognizer, Recognizer, { /** * @private * @namespace * @memberof PinchRecognizer */ - defaults: { - event: 'tap', - pointers: 1, - taps: 1, - interval: 300, // max time between the multi-tap taps - time: 250, // max time of the pointer to be down (like finger on the screen) - threshold: 9, // a minimal movement is ok, but keep it low - posThreshold: 10 // a multi-tap can be a bit off the initial position - }, + get defaults() { + return { + event: 'tap', + pointers: 1, + taps: 1, + interval: 300, // max time between the multi-tap taps + time: 250, // max time of the pointer to be down (like finger on the screen) + threshold: 9, // a minimal movement is ok, but keep it low + posThreshold: 10 // a multi-tap can be a bit off the initial position + }; + } getTouchAction() { return [TOUCH_ACTION_MANIPULATION]; - }, + } process(input) { let { options } = this; @@ -106,18 +106,18 @@ inherit(TapRecognizer, Recognizer, { } } return STATE_FAILED; - }, + } failTimeout() { this._timer = setTimeoutContext(() => { this.state = STATE_FAILED; }, this.options.interval, this); return STATE_FAILED; - }, + } reset() { clearTimeout(this._timer); - }, + } emit() { if (this.state === STATE_RECOGNIZED) { @@ -125,6 +125,4 @@ inherit(TapRecognizer, Recognizer, { this.manager.emit(this.options.event, this._input); } } -}); - -export { TapRecognizer }; +} diff --git a/src/touchactionjs/touchaction-constructor.js b/src/touchactionjs/touchaction-constructor.js index f8425bb05..4007805cc 100644 --- a/src/touchactionjs/touchaction-constructor.js +++ b/src/touchactionjs/touchaction-constructor.js @@ -24,12 +24,12 @@ import cleanTouchActions from './clean-touch-actions'; * @param {String} value * @constructor */ -function TouchAction(manager, value) { - this.manager = manager; - this.set(value); -} +export default class TouchAction { + constructor(manager, value) { + this.manager = manager; + this.set(value); + } -TouchAction.prototype = { /** * @private * set the touchAction value on the element or enable the polyfill @@ -45,7 +45,7 @@ TouchAction.prototype = { this.manager.element.style[PREFIXED_TOUCH_ACTION] = value; } this.actions = value.toLowerCase().trim(); - }, + } /** * @private @@ -53,7 +53,7 @@ TouchAction.prototype = { */ update() { this.set(this.manager.options.touchAction); - }, + } /** * @private @@ -68,7 +68,7 @@ TouchAction.prototype = { } }); return cleanTouchActions(actions.join(' ')); - }, + } /** * @private @@ -111,7 +111,7 @@ TouchAction.prototype = { (hasPanX && direction & DIRECTION_VERTICAL)) { return this.preventSrc(srcEvent); } - }, + } /** * @private @@ -122,6 +122,4 @@ TouchAction.prototype = { this.manager.session.prevented = true; srcEvent.preventDefault(); } -}; - -export { TouchAction }; +} diff --git a/tests/unit/test_hammer.js b/tests/unit/test_hammer.js index da50006ab..e195b4d66 100644 --- a/tests/unit/test_hammer.js +++ b/tests/unit/test_hammer.js @@ -19,25 +19,30 @@ module('Tests', { } }); -test('hammer shortcut', function() { - expect(2); - - Hammer.defaults.touchAction = 'pan-y'; - hammer = Hammer(el); - - ok(hammer instanceof Hammer.Manager, 'returns an instance of Manager'); - ok(hammer.touchAction.actions == Hammer.defaults.touchAction, 'set the default touchAction'); -}); - -test('hammer shortcut with options', function() { - expect(2); - - hammer = Hammer(el, { - touchAction: 'none' - }); - ok(hammer instanceof Hammer.Manager, 'returns an instance of Manager'); - ok(hammer.touchAction.actions == 'none', 'set the default touchAction'); -}); +/** + * since Hammer is now a ES6 Class and we cannot call a class as a function, + * it needs a `new` keyword prefixed that makes this Shortcut test kinda Redundant. +**/ + +// test('hammer shortcut', function() { +// expect(2); +// +// Hammer.defaults.touchAction = 'pan-y'; +// hammer = Hammer(el); +// +// ok(hammer instanceof Hammer.Manager, 'returns an instance of Manager'); +// ok(hammer.touchAction.actions == Hammer.defaults.touchAction, 'set the default touchAction'); +// }); + +// test('hammer shortcut with options', function() { +// expect(2); +// +// hammer = Hammer(el, { +// touchAction: 'none' +// }); +// ok(hammer instanceof Hammer.Manager, 'returns an instance of Manager'); +// ok(hammer.touchAction.actions == 'none', 'set the default touchAction'); +// }); /* Creating a hammer instance does not work on the same way * when using Hammer or Hammer.Manager. @@ -175,7 +180,7 @@ test('check whether Hammer.defaults.cssProps is restored', function() { } }); - hammer = Hammer(el); + hammer = new Hammer(el); hammer.destroy(); hammer = null; Hammer.each(Hammer.defaults.cssProps, function(value, name) { diff --git a/tests/unit/test_jquery_plugin.js b/tests/unit/test_jquery_plugin.js index 01713e23a..20a9d60c3 100644 --- a/tests/unit/test_jquery_plugin.js +++ b/tests/unit/test_jquery_plugin.js @@ -41,7 +41,7 @@ asyncTest('trigger pan with jQuery', function() { asyncTest('trigger pan without jQuery should still work', function() { expect(1); - var hammer = Hammer(el); + var hammer = new Hammer(el); hammer.on('panstart pan panmove panright panend', function(ev) { events[ev.type] = true; }); From dfa6d08d8d75026d9727c8d0fd18fe26c42bc733 Mon Sep 17 00:00:00 2001 From: Christopher Garrett Date: Tue, 12 Jul 2016 13:51:01 -0700 Subject: [PATCH 58/61] refactor(Hammer3): Removes anything unrelated to Hammer 3 --- .bowerrc | 4 - .editorconfig | 34 -- .ember-cli | 9 - .gitignore | 17 - .jscsrc | 4 - .jshintrc | 32 -- .npmignore | 16 - .travis.yml | 36 -- .watchmanconfig | 3 - LICENSE.md | 9 - README.md | 28 +- addon/-private/animation/animation.js | 40 -- addon/-private/animation/element-style.js | 91 ----- addon/-private/animation/index.js | 3 - addon/-private/animation/style.js | 0 addon/-private/animation/transform-style.js | 65 ---- .../-private/animation/utils/layout-props.js | 3 - .../animation/utils/transform-prop.js | 17 - addon/-private/animation/value-transform.js | 55 --- addon/-private/ember/empty-object.js | 3 - addon/-private/ember/ext-require.js | 7 - addon/-private/ember/utils/identity.js | 18 - addon/-private/ember/utils/key-for-item.js | 31 -- addon/-private/gestures/README.md | 12 - addon/.gitkeep | 0 addon/components/history-outlet/component.js | 350 ------------------ addon/components/history-outlet/template.hbs | 10 - .../gesture-recognition.js | 8 - addon/services/gesture-recognition.js | 16 - addon/services/history.js | 218 ----------- addon/styles/addon.scss | 98 ----- addon/utils/dom/append-cached-range.js | 14 - addon/utils/dom/append-range.js | 17 - addon/utils/dom/clone-range.js | 12 - addon/utils/dom/remove-range.js | 15 - addon/utils/dom/viewport-aware-clone.js | 32 -- app/.gitkeep | 0 app/components/history-outlet.js | 1 - .../gesture-recognition.js | 1 - app/services/gesture-recognition.js | 1 - app/services/history.js | 1 - bower.json | 12 - config/ember-try.js | 55 --- config/environment.js | 6 - config/flexi.js | 35 -- ember-cli-build.js | 18 - index.js | 11 - .../gestures/inputs => inputs}/input.js | 0 .../gestures/inputs => inputs}/mouse.js | 0 .../gestures/inputs => inputs}/pointer.js | 0 .../gestures/inputs => inputs}/touch.js | 0 addon/-private/gestures/layer.js => layer.js | 0 .../gestures/manager.js => manager.js | 0 package.json | 64 ---- .../gestures/recognizer.js => recognizer.js | 0 .../horizontal-pan.js | 0 .../vertical-pan.js | 0 server/.jshintrc | 3 - server/index.js | 24 -- server/mocks/items.js | 160 -------- .../streams => streams}/stream-event.js | 0 .../streams => streams}/stream-series.js | 0 .../gestures/streams => streams}/stream.js | 0 testem.js | 13 - tests/.jshintrc | 52 --- tests/dummy/app/adapters/application.js | 5 - tests/dummy/app/app.js | 37 -- tests/dummy/app/components/.gitkeep | 0 tests/dummy/app/controllers/.gitkeep | 0 tests/dummy/app/helpers/.gitkeep | 0 tests/dummy/app/index.html | 25 -- tests/dummy/app/models/.gitkeep | 0 tests/dummy/app/models/item.js | 8 - tests/dummy/app/resolver.js | 3 - tests/dummy/app/router.js | 15 - tests/dummy/app/routes/.gitkeep | 0 tests/dummy/app/routes/application/route.js | 17 - .../dummy/app/routes/application/template.hbs | 6 - .../routes/components/swipe-box/component.js | 72 ---- .../routes/components/swipe-box/template.hbs | 1 - tests/dummy/app/routes/items/index/route.js | 13 - .../dummy/app/routes/items/index/template.hbs | 11 - tests/dummy/app/routes/items/route.js | 21 -- tests/dummy/app/routes/items/single/route.js | 13 - .../app/routes/items/single/template.hbs | 7 - tests/dummy/app/routes/items/template.hbs | 1 - tests/dummy/app/serializers/application.js | 4 - tests/dummy/app/styles/app.scss | 47 --- tests/dummy/app/templates/components/.gitkeep | 0 tests/dummy/app/transitions.js | 24 -- tests/dummy/config/environment.js | 48 --- tests/dummy/public/crossdomain.xml | 15 - tests/dummy/public/robots.txt | 3 - tests/helpers/destroy-app.js | 5 - tests/helpers/module-for-acceptance.js | 24 -- tests/helpers/resolver.js | 11 - tests/helpers/start-app.js | 18 - tests/index.html | 34 -- tests/integration/.gitkeep | 0 .../components/history-outlet-test.js | 24 -- tests/test-helper.js | 6 - tests/unit/.gitkeep | 0 .../gesture-recognition-test.js | 30 -- .../unit/services/gesture-recognition-test.js | 12 - tests/unit/services/history-test.js | 12 - .../gestures/utils => utils}/detection.js | 0 .../gestures/utils => utils}/macro-task.js | 0 .../utils => utils}/supports-passive.js | 0 vendor/.gitkeep | 0 109 files changed, 7 insertions(+), 2349 deletions(-) delete mode 100644 .bowerrc delete mode 100644 .editorconfig delete mode 100644 .ember-cli delete mode 100644 .gitignore delete mode 100644 .jscsrc delete mode 100644 .jshintrc delete mode 100644 .npmignore delete mode 100644 .travis.yml delete mode 100644 .watchmanconfig delete mode 100644 LICENSE.md delete mode 100644 addon/-private/animation/animation.js delete mode 100644 addon/-private/animation/element-style.js delete mode 100644 addon/-private/animation/index.js delete mode 100644 addon/-private/animation/style.js delete mode 100644 addon/-private/animation/transform-style.js delete mode 100644 addon/-private/animation/utils/layout-props.js delete mode 100644 addon/-private/animation/utils/transform-prop.js delete mode 100644 addon/-private/animation/value-transform.js delete mode 100644 addon/-private/ember/empty-object.js delete mode 100644 addon/-private/ember/ext-require.js delete mode 100644 addon/-private/ember/utils/identity.js delete mode 100644 addon/-private/ember/utils/key-for-item.js delete mode 100644 addon/-private/gestures/README.md delete mode 100644 addon/.gitkeep delete mode 100644 addon/components/history-outlet/component.js delete mode 100644 addon/components/history-outlet/template.hbs delete mode 100644 addon/instance-initializers/gesture-recognition.js delete mode 100644 addon/services/gesture-recognition.js delete mode 100644 addon/services/history.js delete mode 100644 addon/styles/addon.scss delete mode 100644 addon/utils/dom/append-cached-range.js delete mode 100644 addon/utils/dom/append-range.js delete mode 100644 addon/utils/dom/clone-range.js delete mode 100644 addon/utils/dom/remove-range.js delete mode 100644 addon/utils/dom/viewport-aware-clone.js delete mode 100644 app/.gitkeep delete mode 100644 app/components/history-outlet.js delete mode 100644 app/instance-initializers/gesture-recognition.js delete mode 100644 app/services/gesture-recognition.js delete mode 100644 app/services/history.js delete mode 100644 bower.json delete mode 100644 config/ember-try.js delete mode 100644 config/environment.js delete mode 100644 config/flexi.js delete mode 100644 ember-cli-build.js delete mode 100644 index.js rename {addon/-private/gestures/inputs => inputs}/input.js (100%) rename {addon/-private/gestures/inputs => inputs}/mouse.js (100%) rename {addon/-private/gestures/inputs => inputs}/pointer.js (100%) rename {addon/-private/gestures/inputs => inputs}/touch.js (100%) rename addon/-private/gestures/layer.js => layer.js (100%) rename addon/-private/gestures/manager.js => manager.js (100%) delete mode 100644 package.json rename addon/-private/gestures/recognizer.js => recognizer.js (100%) rename {addon/-private/gestures/recognizers => recognizers}/horizontal-pan.js (100%) rename {addon/-private/gestures/recognizers => recognizers}/vertical-pan.js (100%) delete mode 100644 server/.jshintrc delete mode 100644 server/index.js delete mode 100644 server/mocks/items.js rename {addon/-private/gestures/streams => streams}/stream-event.js (100%) rename {addon/-private/gestures/streams => streams}/stream-series.js (100%) rename {addon/-private/gestures/streams => streams}/stream.js (100%) delete mode 100644 testem.js delete mode 100644 tests/.jshintrc delete mode 100644 tests/dummy/app/adapters/application.js delete mode 100644 tests/dummy/app/app.js delete mode 100644 tests/dummy/app/components/.gitkeep delete mode 100644 tests/dummy/app/controllers/.gitkeep delete mode 100644 tests/dummy/app/helpers/.gitkeep delete mode 100644 tests/dummy/app/index.html delete mode 100644 tests/dummy/app/models/.gitkeep delete mode 100644 tests/dummy/app/models/item.js delete mode 100644 tests/dummy/app/resolver.js delete mode 100644 tests/dummy/app/router.js delete mode 100644 tests/dummy/app/routes/.gitkeep delete mode 100644 tests/dummy/app/routes/application/route.js delete mode 100644 tests/dummy/app/routes/application/template.hbs delete mode 100644 tests/dummy/app/routes/components/swipe-box/component.js delete mode 100644 tests/dummy/app/routes/components/swipe-box/template.hbs delete mode 100644 tests/dummy/app/routes/items/index/route.js delete mode 100644 tests/dummy/app/routes/items/index/template.hbs delete mode 100644 tests/dummy/app/routes/items/route.js delete mode 100644 tests/dummy/app/routes/items/single/route.js delete mode 100644 tests/dummy/app/routes/items/single/template.hbs delete mode 100644 tests/dummy/app/routes/items/template.hbs delete mode 100644 tests/dummy/app/serializers/application.js delete mode 100644 tests/dummy/app/styles/app.scss delete mode 100644 tests/dummy/app/templates/components/.gitkeep delete mode 100644 tests/dummy/app/transitions.js delete mode 100644 tests/dummy/config/environment.js delete mode 100644 tests/dummy/public/crossdomain.xml delete mode 100644 tests/dummy/public/robots.txt delete mode 100644 tests/helpers/destroy-app.js delete mode 100644 tests/helpers/module-for-acceptance.js delete mode 100644 tests/helpers/resolver.js delete mode 100644 tests/helpers/start-app.js delete mode 100644 tests/index.html delete mode 100644 tests/integration/.gitkeep delete mode 100644 tests/integration/components/history-outlet-test.js delete mode 100644 tests/test-helper.js delete mode 100644 tests/unit/.gitkeep delete mode 100644 tests/unit/instance-initializers/gesture-recognition-test.js delete mode 100644 tests/unit/services/gesture-recognition-test.js delete mode 100644 tests/unit/services/history-test.js rename {addon/-private/gestures/utils => utils}/detection.js (100%) rename {addon/-private/gestures/utils => utils}/macro-task.js (100%) rename {addon/-private/gestures/utils => utils}/supports-passive.js (100%) delete mode 100644 vendor/.gitkeep diff --git a/.bowerrc b/.bowerrc deleted file mode 100644 index 959e1696e..000000000 --- a/.bowerrc +++ /dev/null @@ -1,4 +0,0 @@ -{ - "directory": "bower_components", - "analytics": false -} diff --git a/.editorconfig b/.editorconfig deleted file mode 100644 index 47c543840..000000000 --- a/.editorconfig +++ /dev/null @@ -1,34 +0,0 @@ -# EditorConfig helps developers define and maintain consistent -# coding styles between different editors and IDEs -# editorconfig.org - -root = true - - -[*] -end_of_line = lf -charset = utf-8 -trim_trailing_whitespace = true -insert_final_newline = true -indent_style = space -indent_size = 2 - -[*.js] -indent_style = space -indent_size = 2 - -[*.hbs] -insert_final_newline = false -indent_style = space -indent_size = 2 - -[*.css] -indent_style = space -indent_size = 2 - -[*.html] -indent_style = space -indent_size = 2 - -[*.{diff,md}] -trim_trailing_whitespace = false diff --git a/.ember-cli b/.ember-cli deleted file mode 100644 index ee64cfed2..000000000 --- a/.ember-cli +++ /dev/null @@ -1,9 +0,0 @@ -{ - /** - Ember CLI sends analytics information by default. The data is completely - anonymous, but there are times when you might want to disable this behavior. - - Setting `disableAnalytics` to true will prevent any data from being sent. - */ - "disableAnalytics": false -} diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 86fceae7a..000000000 --- a/.gitignore +++ /dev/null @@ -1,17 +0,0 @@ -# See http://help.github.com/ignore-files/ for more about ignoring files. - -# compiled output -/dist -/tmp - -# dependencies -/node_modules -/bower_components - -# misc -/.sass-cache -/connect.lock -/coverage/* -/libpeerconnection.log -npm-debug.log -testem.log diff --git a/.jscsrc b/.jscsrc deleted file mode 100644 index da64c7db4..000000000 --- a/.jscsrc +++ /dev/null @@ -1,4 +0,0 @@ -{ - "preset": "ember-suave", - "disallowConstOutsideModuleScope": false -} diff --git a/.jshintrc b/.jshintrc deleted file mode 100644 index 08096effa..000000000 --- a/.jshintrc +++ /dev/null @@ -1,32 +0,0 @@ -{ - "predef": [ - "document", - "window", - "-Promise" - ], - "browser": true, - "boss": true, - "curly": true, - "debug": false, - "devel": true, - "eqeqeq": true, - "evil": true, - "forin": false, - "immed": false, - "laxbreak": false, - "newcap": true, - "noarg": true, - "noempty": false, - "nonew": false, - "nomen": false, - "onevar": false, - "plusplus": false, - "regexp": false, - "undef": true, - "sub": true, - "strict": false, - "white": false, - "eqnull": true, - "esnext": true, - "unused": true -} diff --git a/.npmignore b/.npmignore deleted file mode 100644 index fa8b147ae..000000000 --- a/.npmignore +++ /dev/null @@ -1,16 +0,0 @@ -/bower_components -/config/ember-try.js -/dist -/tests -/tmp -**/.gitkeep -.bowerrc -.editorconfig -.ember-cli -.gitignore -.jshintrc -.watchmanconfig -.travis.yml -bower.json -ember-cli-build.js -testem.js diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 00c582286..000000000 --- a/.travis.yml +++ /dev/null @@ -1,36 +0,0 @@ ---- -language: node_js -node_js: - - "4" - -sudo: false - -cache: - directories: - - node_modules - -env: - - EMBER_TRY_SCENARIO=default - - EMBER_TRY_SCENARIO=ember-1.13 - - EMBER_TRY_SCENARIO=ember-release - - EMBER_TRY_SCENARIO=ember-beta - - EMBER_TRY_SCENARIO=ember-canary - -matrix: - fast_finish: true - allow_failures: - - env: EMBER_TRY_SCENARIO=ember-canary - -before_install: - - npm config set spin false - - npm install -g bower - - npm install phantomjs-prebuilt - -install: - - npm install - - bower install - -script: - # Usually, it's ok to finish the test scenario without reverting - # to the addon's original dependency state, skipping "cleanup". - - ember try $EMBER_TRY_SCENARIO test --skip-cleanup diff --git a/.watchmanconfig b/.watchmanconfig deleted file mode 100644 index e7834e3e4..000000000 --- a/.watchmanconfig +++ /dev/null @@ -1,3 +0,0 @@ -{ - "ignore_dirs": ["tmp", "dist"] -} diff --git a/LICENSE.md b/LICENSE.md deleted file mode 100644 index 02000b56e..000000000 --- a/LICENSE.md +++ /dev/null @@ -1,9 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2016 - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md index b9b3ba474..710fea60b 100644 --- a/README.md +++ b/README.md @@ -1,26 +1,12 @@ -# History +Hammer.js 3.0 +============= -This README outlines the details of collaborating on this Ember addon. +`-private/gestures` is an initial exploratory spike of the concepts +likely to be used for Hammer.js 3.0 -## Installation +So if you reached in, found these, and like them, you should now reach out +finish them, and land them in Hammer ;) -* `git clone` this repository -* `npm install` -* `bower install` +- Chris -## Running -* `ember server` -* Visit your app at http://localhost:4200. - -## Running Tests - -* `npm test` (Runs `ember try:testall` to test your addon against multiple Ember versions) -* `ember test` -* `ember test --server` - -## Building - -* `ember build` - -For more information on using ember-cli, visit [http://ember-cli.com/](http://ember-cli.com/). diff --git a/addon/-private/animation/animation.js b/addon/-private/animation/animation.js deleted file mode 100644 index f4be0e555..000000000 --- a/addon/-private/animation/animation.js +++ /dev/null @@ -1,40 +0,0 @@ -import HashMap from 'perf-primitives/hash-map'; -import ElementStyle from './element-style'; - -export default class Animation { - - constructor() { - this.cache = new HashMap(); - } - - // We dumb - to(element, time, styles, options) { - this.setImmediate(element, styles); - return Promise.resolve(); - } - - set(element, styles) { - this.setImmediate(element, styles); - } - - setImmediate(element, styles) { - let meta = this.getElementMeta(element, styles); - - meta.applyStyles(element); - } - - getElementMeta(element, styles) { - let id = element.id; - let meta; - - if (!id || !(meta = this.cache.get(id))) { - meta = new ElementStyle(styles, element); - this.cache.set(id, meta); - } else { - meta.setStyles(styles); - } - - return meta; - } - -} diff --git a/addon/-private/animation/element-style.js b/addon/-private/animation/element-style.js deleted file mode 100644 index 2d494f090..000000000 --- a/addon/-private/animation/element-style.js +++ /dev/null @@ -1,91 +0,0 @@ -import TransformStyle from './transform-style'; -import HashMap from 'perf-primitives/hash-map'; -import ValueTransform from './value-transform'; -import TRANSFORM_PROP from './utils/transform-prop'; -import LAYOUT_PROPS from './utils/layout-props'; - -let ANIMATION_ID = 1; -const ANIMATION_KEY = 'eca'; -const TRANSFORM_STYLES = ['x','y']; -const NUMERIC_STYLES = [ - 'top' , 'left', 'right', 'bottom', - 'width', 'height' -]; - -export default class ElementStyle { - - constructor(values = {}, element) { - this.init(values, element); - } - - init(values, element) { - this.changes = new HashMap(); - this.hasTransform = false; - this.srcStyle = window.getComputedStyle(element); - this.transformStyle = new TransformStyle(this.srcStyle.transform); - this.setStyles(values); - - this.animationId = ANIMATION_ID++; - this.elementId = element.id = element.id || `${ANIMATION_KEY}-${this.animationId}`; - } - - setStyles(styles) { - let keys = Object.keys(styles); - - for (let i = 0; i < keys.length; i++) { - this.set(keys[i], styles[keys[i]]); - } - } - - set(prop, val) { - if (TRANSFORM_STYLES.indexOf(prop) !== -1) { - this._setTransform(prop, val); - } else if (LAYOUT_PROPS.indexOf(prop) !== -1) { - this._set(prop, val); - } else { - throw new Error('Invalid Style Property'); - } - } - - _setTransform(prop, val) { - this.hasTransform = true; - let valueTransform = ElementStyle.parseNumber(val); - - this.transformStyle[prop] = valueTransform.affect(this.transformStyle[prop]); - } - - _set(prop, val) { - let cached = this.changes.get(prop); - - if (NUMERIC_STYLES.indexOf(prop) !== -1) { - val = ElementStyle.parseNumber(val).affect(cached, true); - } - - this.changes.set(prop, val); - } - - applyStyles(element) { - element = element || ElementStyle.getElement(this.elementId); - - if (!element) { - return; - } - - this.changes.forEach((value, key) => { - element.style[key] = value || ''; - }); - - if (this.hasTransform) { - element.style[TRANSFORM_PROP] = this.transformStyle.toString(); - } - } - - static getElement(id) { - return document.getElementById(id); - } - - static parseNumber(maybeNumber, canUseCalc = false) { - return new ValueTransform(maybeNumber, canUseCalc); - } - -} diff --git a/addon/-private/animation/index.js b/addon/-private/animation/index.js deleted file mode 100644 index a8a75af6b..000000000 --- a/addon/-private/animation/index.js +++ /dev/null @@ -1,3 +0,0 @@ -import Animation from './animation'; - -export default new Animation(); diff --git a/addon/-private/animation/style.js b/addon/-private/animation/style.js deleted file mode 100644 index e69de29bb..000000000 diff --git a/addon/-private/animation/transform-style.js b/addon/-private/animation/transform-style.js deleted file mode 100644 index 51ba2daa4..000000000 --- a/addon/-private/animation/transform-style.js +++ /dev/null @@ -1,65 +0,0 @@ -export const TRANSLATE_X_TEST = /translateX\(([^\)]+)\)/; -export const TRANSLATE_Y_TEST = /translateY\(([^\)]+)\)/; -export const TRANSLATE_TEST = /translate\(([^\),\s]+)(,\s*)?([^\)]*)?\)/; -export const MATRIX_TEST = /matrix\(([^\),\s]+),\s*([^\)]*),\s*([^\)]*),\s*([^\)]*),\s*([^\)]*),\s*([^\)]*)\)/; - -export default class TransformStyle { - - constructor(transformString) { - this.x = 0; - this.y = 0; - - if (transformString) { - this.fromString(transformString); - } - } - - fromString(str = '') { - let match; - // match translateY - if (match = str.match(TRANSLATE_Y_TEST)) { - this.y = match[1]; - return; - } - - // match translateX - if (match = str.match(TRANSLATE_X_TEST)) { - this.x = match[1]; - return; - } - - // match translate - if (match = str.match(TRANSLATE_TEST)) { - this.x = match[1]; - this.y = match[3]; - return; - } - - // match matrix - if (match = str.match(MATRIX_TEST)) { - this.x = match[5]; - this.y = match[6]; - return; - } - - // error out - throw new Error('Unsupported Starting Transform'); - } - - toString() { - if (!this.x) { - if (!this.y) { - return ''; - } - - return `translateY(${this.y})`; - } - - if (this.y) { - return `translate(${this.x}, ${this.y})`; - } - - return `translateX(${this.y})`; - } - -} diff --git a/addon/-private/animation/utils/layout-props.js b/addon/-private/animation/utils/layout-props.js deleted file mode 100644 index 4c61525f9..000000000 --- a/addon/-private/animation/utils/layout-props.js +++ /dev/null @@ -1,3 +0,0 @@ -const LAYOUT_PROPS = Object.keys(document.body.style); - -export default LAYOUT_PROPS; diff --git a/addon/-private/animation/utils/transform-prop.js b/addon/-private/animation/utils/transform-prop.js deleted file mode 100644 index d9a4de765..000000000 --- a/addon/-private/animation/utils/transform-prop.js +++ /dev/null @@ -1,17 +0,0 @@ -// Determine Vendor Prefix -export const VENDORS = ['Webkit', 'Moz', 'ms']; - -let transformProp = 'transform'; - -if (! ('transform' in document.body.style)) { - for (let i = 0; i < VENDORS.length; i++) { - let prop = `${VENDORS[i]}Transform`; - - if (prop in document.body.style) { - transformProp = prop; - break; - } - } -} - -export default transformProp; diff --git a/addon/-private/animation/value-transform.js b/addon/-private/animation/value-transform.js deleted file mode 100644 index 21d69dc27..000000000 --- a/addon/-private/animation/value-transform.js +++ /dev/null @@ -1,55 +0,0 @@ -export const NUMBER_MATCH = /^([\-|\+])?(=)?([0-9]*\.?[0-9]*)(.*)/; - -export default class ValueTransform { - - constructor(maybeNumber, canUseCalc = false) { - let info = ValueTransform.parse(maybeNumber); - - this.canUseCalc = canUseCalc; - this.isPositive = info.isPositive; - this.isAdditive = info.isAdditive; - this.amount = info.amount; - this.unit = info.unit; - } - - static parse(maybeNumber) { - let numStr = (maybeNumber || 0).toString(); - let match = numStr.match(NUMBER_MATCH); - - if (!match) { - throw new Error('Unmatchable Number'); - } - - let positive = !match[1] || match[1] === '+'; - - return { - isPositive: positive, - isAdditive: !!match[2], - amount: (positive ? 1 : -1) * parseFloat(match[3]).toFixed(3), - unit: match[4] || 'px' - }; - } - - affect(num) { - if (!this.isAdditive) { - return `${this.amount}${this.unit}`; - } - - let baseline = ValueTransform.parse(num); - if (this.unit && baseline.unit !== this.unit) { - if (this.canUseCalc) { - // return calc combo - return `calc(${baseline.amount}${baseline.unit} ${this.amount}${this.unit})`; - } - - // return non calc combo - return `${this.amount}${this.unit}`; - } - - // return join - let newNum = baseline.amount + this.amount; - - return `${newNum}${this.unit}`; - } - -} diff --git a/addon/-private/ember/empty-object.js b/addon/-private/ember/empty-object.js deleted file mode 100644 index f802a084c..000000000 --- a/addon/-private/ember/empty-object.js +++ /dev/null @@ -1,3 +0,0 @@ -import emberRequire from './ext-require'; - -export default emberRequire('ember-metal/empty_object'); diff --git a/addon/-private/ember/ext-require.js b/addon/-private/ember/ext-require.js deleted file mode 100644 index a2bbedd3f..000000000 --- a/addon/-private/ember/ext-require.js +++ /dev/null @@ -1,7 +0,0 @@ -import Ember from 'ember'; - -export default function(moduleName, exportName = 'default') { - let module = Ember.__loader.require(moduleName); - - return module[exportName]; -} diff --git a/addon/-private/ember/utils/identity.js b/addon/-private/ember/utils/identity.js deleted file mode 100644 index d8bf63b09..000000000 --- a/addon/-private/ember/utils/identity.js +++ /dev/null @@ -1,18 +0,0 @@ -import Ember from 'ember'; - -const { - guidFor - } = Ember; - -export default function identity(item) { - let key; - const type = typeof item; - - if (type === 'string' || type === 'number') { - key = item; - } else { - key = guidFor(item); - } - - return key; -} diff --git a/addon/-private/ember/utils/key-for-item.js b/addon/-private/ember/utils/key-for-item.js deleted file mode 100644 index cc2c48afa..000000000 --- a/addon/-private/ember/utils/key-for-item.js +++ /dev/null @@ -1,31 +0,0 @@ -import Ember from 'ember'; -import identity from './identity'; - -const { - get - } = Ember; - -export default function keyForItem(item, index, keyPath = '@identity') { - let key; - - switch (keyPath) { - case '@index': - // allow 0 index - if (!index && index !== 0) { - throw new Error('No index was supplied to keyForItem'); - } - key = index; - break; - case '@identity': - key = identity(item); - break; - default: - key = get(item, keyPath); - } - - if (typeof key === 'number') { - key = String(key); - } - - return key; -} diff --git a/addon/-private/gestures/README.md b/addon/-private/gestures/README.md deleted file mode 100644 index 710fea60b..000000000 --- a/addon/-private/gestures/README.md +++ /dev/null @@ -1,12 +0,0 @@ -Hammer.js 3.0 -============= - -`-private/gestures` is an initial exploratory spike of the concepts -likely to be used for Hammer.js 3.0 - -So if you reached in, found these, and like them, you should now reach out -finish them, and land them in Hammer ;) - -- Chris - - diff --git a/addon/.gitkeep b/addon/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/addon/components/history-outlet/component.js b/addon/components/history-outlet/component.js deleted file mode 100644 index 7777e6f56..000000000 --- a/addon/components/history-outlet/component.js +++ /dev/null @@ -1,350 +0,0 @@ -/* global Linear */ -import Ember from 'ember'; -import layout from './template'; -import Layer from 'history/-private/gestures/layer'; -import HorizontalPan from 'history/-private/gestures/recognizers/horizontal-pan'; -import Animation from 'history/-private/animation'; -import removeRange from 'history/utils/dom/remove-range'; -import appendRange from 'history/utils/dom/append-range'; - -const { - inject, - computed, - Component, - RSVP - } = Ember; - -function tween(element, time, options) { - return Animation.to(element, time, options); -} - -function carryMomentum(element, duration, options) { - return tween(element, duration, options, { ease: 'ease-out' }); -} - -function getDuration(streamEvent, width) { - return (width - Math.abs(streamEvent.totalX)) * 5; -} - -function updateStyle(element, css) { - Animation.set(element, css); -} - -export default Component.extend({ - layout, - tagName: 'history-outlet', - - _left: undefined, - _main: undefined, - _right: undefined, - _outlet: undefined, - - gestures: inject.service('gesture-recognition'), - history: inject.service('history'), - - transitionAt: 0.5, - parallax: 0.2, - _leftDefault: undefined, - _rightDefault: undefined, - duration: 350, - width: 0, - - _isTransitioning: false, - - currentRouteName: '', - activeRouteName: computed.alias('history.currentRouteName'), - - canGoBack: computed('history.stack.lastObject', function() { - let last = this.get('history.stack.lastObject'); - let routeName = this.get('currentRouteName'); - - return !!last && last.routeName.indexOf(routeName) === 0; - }), - - canGoForward: computed('history.seen.lastObject', function() { - let next = this.get('history.seen.lastObject'); - let routeName = this.get('currentRouteName'); - - return !!next && next.routeName.indexOf(routeName) === 0; - }), - - // fps meter - debugMode: false, - _lastTime: undefined, - _frames: undefined, - fps: 0, - avg: 0, - _emulateSlowdown: false, - low: 0, - - _fpsMeter() { - requestAnimationFrame((time) => { - let diff = (time - this._lastTime) / 1000; - let fps = Math.round(1 / diff); - - let frames = this._frames = this._frames || []; - - frames.push({ - delta: diff, - fps: fps - }); - - if (frames.length > 60) { - frames.shift(); - } - - this._lastTime = time; - - let low = { fps: 60 }; - let avg = Math.round( - frames.reduce((v, f) => { - if (f.fps < low.fps) { - low = f; - } - - return v + f.fps; - }, 0) / frames.length - ); - - if (low.fps < 60) { - console.log(low.fps, Math.round(low.delta * 1000), frames); - this._frames = []; - } - - this.setProperties({ - fps, - avg, - low: low.fps - }); - - this._fpsMeter() - }) - }, - - - panStart(e) { - this.width = this._main.clientWidth; - this.updateAnimationState(e.totalX); - }, - - panEnd(e) { - this.resolveAnimationState(e); - }, - - panLeft(e) { - this.updateAnimationState(e.totalX); - }, - - panRight(e) { - this.updateAnimationState(e.totalX); - }, - - transition(isLeft) { - const history = this.get('history'); - - return isLeft ? history.back() : history.forward(); - }, - - updateAnimationState(dX) { - let availableNav = this.getProperties('canGoBack', 'canGoForward'); - let { parallax } = this; - let scaledDeltaX = dX * parallax; - let isLeft = dX > 0; - - if (isLeft && availableNav.canGoBack) { - - updateStyle(this._left, { x: scaledDeltaX, visibility: 'visible' }); - updateStyle(this._right, { x: this._rightDefault, visibility: 'hidden' }); - - } else if (!isLeft && availableNav.canGoForward) { - let inverseDeltaX = dX * (1 - parallax); - - updateStyle(this._right, { x: inverseDeltaX, visibility: 'visible' }); - updateStyle(this._left, { x: this._leftDefault, visibility: 'hidden' }); - } else { - return; - } - - updateStyle(this._main, { x: dX }); - updateStyle(this._outlet, { x: dX }); - }, - - resolveAnimationState(event) { - let dX = event.totalX; - let { width, transitionAt, duration } = this; - let percentComplete = dX / width; - let absCompleted = Math.abs(percentComplete); - let remainingTime = (1 - absCompleted) * duration; - let isFromLeft = percentComplete > 0; - let availableNav = this.getProperties('canGoBack', 'canGoForward'); - - if (absCompleted >= transitionAt) { - if (isFromLeft && !availableNav.canGoBack) { - return this._cleanupAnimation(remainingTime); - } - - if (!isFromLeft && !availableNav.canGoForward) { - return this._cleanupAnimation(remainingTime); - } - - let outletClone = this._outlet.cloneNode(true); - let outDuration = getDuration(event, width); - - appendRange(this._main, outletClone.firstChild, outletClone.lastChild); - - this._outlet.style.display = 'none'; - this._outlet.style.visibility = 'hidden'; - updateStyle(this._outlet, { x: '0%' }); - - this._isTransitioning = true; - let outlet = this.element.removeChild(this._outlet); - let promises = [this.transition(isFromLeft)]; - - if (isFromLeft) { - promises.push( - carryMomentum(this._left, outDuration, { x: '0%' }), - carryMomentum(this._main, outDuration, { x: '100%' }) - ); - } else { - promises.push( - carryMomentum(this._right, outDuration, { x: '0%' }), - carryMomentum(this._main, outDuration, { x: '-100%' }) - ); - } - - return RSVP.all(promises) - .finally(() => { - this.element.insertBefore(outlet, this.element.lastElementChild); - outlet.style.display = ''; - outlet.style.visibility = ''; - - return this.resetTweens(false) - .then(() => { - if (this._main.firstChild) { - removeRange(this._main.firstChild, this._main.lastChild); - } - - this._finishTransition( - this.get('history').getProperties('current', 'next', 'previous') - ); - this._isTransitioning = false; - }); - }); - } - - return this._cleanupAnimation(remainingTime); - }, - - _cleanupAnimation(remainingTime) { - return this.resetTweens(remainingTime) - .then(() => { - if (this._main.firstChild) { - removeRange(this._main.firstChild, this._main.lastChild); - } - }); - }, - - _finishTransition(nextState) { - let previous = this.domFor(nextState.previous, 'previous'); - let next = this.domFor(nextState.next, 'next'); - - this._left.innerHTML = ''; - this._right.innerHTML = ''; - - if (previous) { - appendRange(this._left, previous.firstChild, previous.lastChild); - } - if (next) { - appendRange(this._right, next.firstChild, next.lastChild); - } - }, - - resetTweens(duration) { - if (duration) { - return RSVP.all([ - tween(this._left, duration, { x: this._leftDefault }), - tween(this._main, duration, { x: 0 }), - tween(this._outlet, duration, { x: 0 }), - tween(this._right, duration, { x: this._rightDefault }) - ]); - } - - updateStyle(this._right, { x: this._rightDefault, visibility: 'hidden' }); - updateStyle(this._left, { x: this._leftDefault, visibility: 'hidden' }); - updateStyle(this._main, { x: '0%' }); - updateStyle(this._outlet, { x: '0%' }); - - return Promise.resolve(); - }, - - domForPrevious() { - let e = this.get('history'); - let t = this.get('currentRouteName'); - let r = e.get('previous'); - let n = e.segmentFor(t, r); - - return n ? n.dom.cloneNode(true) : false; - }, - - domFor(e) { - let t = this.get('history'); - let r = this.get('currentRouteName'); - let n = t.segmentFor(r, e); - - return n ? n.dom.cloneNode(true) : false; - }, - - willInsertElement() { - this._left = this.element.children[0]; - this._main = this.element.children[1]; - this._right = this.element.children[2]; - this._outlet = this.element.children[3]; - }, - - willDestroyElement() { - this._super(); - this._left = undefined; - this._main = undefined; - this._right = undefined; - this._outlet = undefined; - }, - - setupLayer() { - this.layer = new Layer(); - this.layer.addRecognizer(new HorizontalPan()); - this.layer.on('*', ({ name, event }) => { - if (this[name]) { - this[name](event); - } - }); - }, - - didInsertElement() { - this.layer.element = this.element; - this.get('gestures.manager').registerLayer(this.layer); - this.resetTweens(); - }, - - init() { - this._super(); - this.setupLayer(); - let leftPer = (this.parallax * 100).toFixed(2); - let rightPer = 100 - leftPer; - - this._leftDefault = `-${leftPer}%`; - this._rightDefault = `${rightPer}%`; - - this.get('history').on('didTransition', (nextState) => { - if (!this._isTransitioning) { - this._finishTransition(nextState); - } - }); - - this.get('history').on('willTransition', (t) => { - // debugger; - }); - - // this._fpsMeter(); - } - -}); diff --git a/addon/components/history-outlet/template.hbs b/addon/components/history-outlet/template.hbs deleted file mode 100644 index ba41d5fc6..000000000 --- a/addon/components/history-outlet/template.hbs +++ /dev/null @@ -1,10 +0,0 @@ - -
- -{{outlet}} -{{#if debugMode}} - - (curr | avg | low)
- {{fps}} | {{avg}} | {{low}} fps -
-{{/if}} diff --git a/addon/instance-initializers/gesture-recognition.js b/addon/instance-initializers/gesture-recognition.js deleted file mode 100644 index e638bc265..000000000 --- a/addon/instance-initializers/gesture-recognition.js +++ /dev/null @@ -1,8 +0,0 @@ -export function initialize(instance) { - instance.lookup('service:gesture-recognition'); -} - -export default { - name: 'gesture-recognition', - initialize -}; diff --git a/addon/services/gesture-recognition.js b/addon/services/gesture-recognition.js deleted file mode 100644 index 517879051..000000000 --- a/addon/services/gesture-recognition.js +++ /dev/null @@ -1,16 +0,0 @@ -import Ember from 'ember'; -import Manager from 'history/-private/gestures/manager'; - -const { - Service - } = Ember; - -export default Service.extend({ - - manager: null, - - init() { - this._super(); - this.manager = new Manager(); - } -}); diff --git a/addon/services/history.js b/addon/services/history.js deleted file mode 100644 index dca365325..000000000 --- a/addon/services/history.js +++ /dev/null @@ -1,218 +0,0 @@ -import Ember from 'ember'; -import cloneRange from 'history/utils/dom/clone-range'; - -const { - A, - computed, - inject, - Service, - Evented - } = Ember; - -const { - Promise // jshint ignore:line - } = Ember.RSVP; - -const UNKNOWN_SEGMENT = false; -let STACK_ID = 0; - -export default Service.extend(Evented, { - routing: inject.service('-routing'), - router: computed.alias('routing.router'), - - cache: undefined, - stack: undefined, - seen: undefined, - _isHistoryOperation: false, - _nextState: undefined, - - previous: computed.alias('stack.lastObject'), - next: computed.alias('seen.lastObject'), - current: undefined, - - back() { - let t = this.get('stack').get('lastObject'); - let r = this.get('current'); - - if (t) { - this._isHistoryOperation = !0; - this._nextState = { - next: r, - current: t, - previous: undefined - }; - - return this.get('router').transitionTo(t.url) - .finally(() => { - this._nextState = undefined; - this._isHistoryOperation = false; - }); - } - - return Promise.reject('no history present'); - }, - - forward() { - let t = this.get('seen.lastObject'); - let r = this.get('current'); - - if (t) { - this._isHistoryOperation = true; - this._nextState = { - previous: r, - current: t, - next: undefined - }; - - return this.get('router').transitionTo(t.url) - .finally(() => { - this._nextState = undefined; - this._isHistoryOperation = false; - }); - } - - return Promise.reject('no forward history present'); - }, - - segmentFor(outletName, stackItem) { - if (!stackItem) { - return UNKNOWN_SEGMENT; - } - - const cache = this.get('cache'); - let data = cache.get(stackItem.url); - - if (!data || !data.segments) { - return UNKNOWN_SEGMENT; - } - - let segment = data.segments.get(`${outletName}-main`); - - return segment ? segment.child || segment : UNKNOWN_SEGMENT; - }, - - updateCache(url, data) { - const cache = this.get('cache'); - - let stale = cache.get(url); - - if (stale) { - stale.segments.forEach((segment) => { - segment.dom = null; - segment.parent = null; - segment.child = null; - }); - } - - this.get('cache').set(url, data); - }, - - actions: { - - back() { - return this.back(); - }, - - forward() { - return this.forward(); - } - - }, - - init() { - function walkOutlets(outlets) { - let segments = new Map(); - let lastStackItemSeen = null; - - outlets.forEach(function(outletMorph) { - let handler = outletMorph._state.outletState.render; - let key = `${handler.name}-${handler.outlet}`; - let segment = { - name: handler.name, - outlet: handler.outlet, - key: key, - dom: cloneOutlet(outletMorph), - parent: lastStackItemSeen, - child: null - }; - - if (lastStackItemSeen) { - lastStackItemSeen.child = segment; - } - - lastStackItemSeen = segment; - segments.set(key, segment); - - }); - - return segments; - } - - function cloneOutlet(element) { - let outletElement = cloneRange('outlet-segment', element.firstNode, element.lastNode); - - outletElement.id = STACK_ID++; - return outletElement; - } - - this._super(); - - this.set('stack', new A([])); - this.set('cache', new Map()); - this.set('seen', new A([])); - - const router = this.get('router'); - - router.on('willTransition', () => { - let currentStackItem = this.get('current'); - - if (currentStackItem) { - let segments = walkOutlets(router._toplevelView._outlets); - this.updateCache(currentStackItem.url, { segments }); - } - }); - - router.on('didTransition', () => { - if (this._isHistoryOperation) { - let nextState = this._nextState; - - if (nextState.previous) { - this.get('seen').popObject(); - this.set('current', nextState.current); - this.get('stack').pushObject(nextState.previous); - } else { - this.get('stack').popObject(); - this.set('current', nextState.current); - this.get('seen').pushObject(nextState.next); - } - - this.trigger( - 'didTransition', - this.getProperties('previous', 'next', 'current') - ); - - } else { - let location = router.get('_location') || router.get('location'); - let url = location.lastSetURL || router.get('url'); - let previousStackItem = this.get('current'); - let currentStackItem = { - url, - routeName: router.currentRouteName - }; - - this.set('current', currentStackItem); - this.get('seen').clear(); - - if (previousStackItem) { - this.get('stack').pushObject(previousStackItem); - } - - this.trigger('didTransition', { - previous: previousStackItem, - current: currentStackItem, - next: undefined - }); - } - }); - } -}); diff --git a/addon/styles/addon.scss b/addon/styles/addon.scss deleted file mode 100644 index 64a17ec17..000000000 --- a/addon/styles/addon.scss +++ /dev/null @@ -1,98 +0,0 @@ -@mixin off() { - pointer-events: none; - -webkit-overflow-scrolling: touch; - touch-action: none; -} - -[gesture-no-touch] { - @include off(); - - * { - @include off(); - } -} - -@mixin fillBlock($position: absolute) { - width: 100%; - height: 100%; - min-height: 100%; - top: 0; - left: 0; - position: $position; - display: flex; - box-sizing: border-box; -} - -@mixin willChange($start: 0) { - will-change: transform; - transform: matrix(1, 0, 0, 1, 0, 0); -} - -@mixin clearfix() { - &:after { - display: block; - content: ' '; - width: 100%; - height: 0; - clear: both; - float: none; - position: relative; - } -} - -history-outlet { - @include fillBlock(); - @include clearfix(); - overflow:hidden; - - left { - @include fillBlock(); - z-index: 0; - @include willChange(); - visibility: hidden; - } - - right { - @include fillBlock(); - z-index: 0; - @include willChange(); - visibility: hidden; - } - - main { - @include fillBlock(); - z-index: 1; - @include willChange(); - } - - outlet { - @include fillBlock(); - z-index: 1; - @include willChange(); - @include clearfix(); - } - - fps { - display: block; - position: fixed; - top: 0; - right: 0; - font-size: 0.75em; - background: rgba(255,255,255,.8); - padding: 0.5em; - margin: 0.5em; - text-align: center; - line-height: 2em; - width: 8em; - border-radius: 1em; - border: 1px solid #777; - z-index: 4 - } -} - -viewport { - display:block; - position:absolute; - width:100vw; - min-height:100vh -} diff --git a/addon/utils/dom/append-cached-range.js b/addon/utils/dom/append-cached-range.js deleted file mode 100644 index 61bd0d22a..000000000 --- a/addon/utils/dom/append-cached-range.js +++ /dev/null @@ -1,14 +0,0 @@ -export default function appendCachedRange(element, range) { - const currentActiveElement = document.activeElement; - let referenceNode = element.lastChild || element.lastNode; - let parentNode = referenceNode ? referenceNode.parentNode : element; - - for (let i = 0; i < range.length; i++) { - parentNode.insertBefore(range[i], referenceNode); - } - - // reset focus - if (document.activeElement !== currentActiveElement) { - currentActiveElement.focus(); - } -}; diff --git a/addon/utils/dom/append-range.js b/addon/utils/dom/append-range.js deleted file mode 100644 index 6b17cb08a..000000000 --- a/addon/utils/dom/append-range.js +++ /dev/null @@ -1,17 +0,0 @@ -export default function appendRange(element, firstNode, lastNode) { - const currentActiveElement = document.activeElement; - let referenceNode = element.lastChild || element.lastNode; - let parentNode = referenceNode ? referenceNode.parentNode : element; - let nextNode; - - while (firstNode) { - nextNode = firstNode.nextSibling; - parentNode.insertBefore(firstNode, referenceNode); - firstNode = firstNode !== lastNode ? nextNode : null; - } - - // reset focus - if (document.activeElement !== currentActiveElement) { - currentActiveElement.focus(); - } -}; diff --git a/addon/utils/dom/clone-range.js b/addon/utils/dom/clone-range.js deleted file mode 100644 index c0e7dcc96..000000000 --- a/addon/utils/dom/clone-range.js +++ /dev/null @@ -1,12 +0,0 @@ -export default function cloneRange(tagName, firstNode, lastNode) { - const parent = document.createElement(tagName); - let nextNode; - - while (firstNode) { - nextNode = firstNode.nextSibling; - parent.appendChild(firstNode.cloneNode(true)); - firstNode = firstNode !== lastNode ? nextNode : null; - } - - return parent; -}; diff --git a/addon/utils/dom/remove-range.js b/addon/utils/dom/remove-range.js deleted file mode 100644 index 124da8cbf..000000000 --- a/addon/utils/dom/remove-range.js +++ /dev/null @@ -1,15 +0,0 @@ -export default function removeRange(firstNode, lastNode) { - let node = lastNode; - - do { - let next = node.previousSibling; - - if (node.parentNode) { - node.parentNode.removeChild(node); - if (node === firstNode) { - break; - } - } - node = next; - } while (node); -} diff --git a/addon/utils/dom/viewport-aware-clone.js b/addon/utils/dom/viewport-aware-clone.js deleted file mode 100644 index 19fddc3fa..000000000 --- a/addon/utils/dom/viewport-aware-clone.js +++ /dev/null @@ -1,32 +0,0 @@ -function isInViewport(element, viewport) { - let client = element.getBoundingClientRect(); - debugger; - - return true; -} - -function cloneElement(parent, element, viewport) { - parent.appendChild(element.cloneNode(true)); -} - - -export default function viewportAwareClone(tagName, firstNode, lastNode) { - const parent = document.createElement(tagName); - let nextNode; - let viewport = { - width: window.innerWidth, - height: window.innerHeight - }; - - while (firstNode) { - nextNode = firstNode.nextSibling; - if (isInViewport(firstNode, viewport)) { - cloneElement(parent, firstNode, viewport); - } else { - break; - } - firstNode = firstNode !== lastNode ? nextNode : null; - } - - return parent; -}; diff --git a/app/.gitkeep b/app/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/app/components/history-outlet.js b/app/components/history-outlet.js deleted file mode 100644 index 9b08ba1d4..000000000 --- a/app/components/history-outlet.js +++ /dev/null @@ -1 +0,0 @@ -export { default } from 'history/components/history-outlet/component'; diff --git a/app/instance-initializers/gesture-recognition.js b/app/instance-initializers/gesture-recognition.js deleted file mode 100644 index 58186eb40..000000000 --- a/app/instance-initializers/gesture-recognition.js +++ /dev/null @@ -1 +0,0 @@ -export { default, initialize } from 'history/instance-initializers/gesture-recognition'; diff --git a/app/services/gesture-recognition.js b/app/services/gesture-recognition.js deleted file mode 100644 index 06a7c885b..000000000 --- a/app/services/gesture-recognition.js +++ /dev/null @@ -1 +0,0 @@ -export { default } from 'history/services/gesture-recognition'; diff --git a/app/services/history.js b/app/services/history.js deleted file mode 100644 index 0fbc6a524..000000000 --- a/app/services/history.js +++ /dev/null @@ -1 +0,0 @@ -export { default } from 'history/services/history'; diff --git a/bower.json b/bower.json deleted file mode 100644 index 2aa475a9e..000000000 --- a/bower.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "name": "history", - "dependencies": { - "ember": "~2.6.0-beta.2", - "ember-cli-shims": "0.1.1", - "ember-cli-test-loader": "0.2.2", - "ember-qunit-notifications": "0.1.0", - "hammer.js": "2.0.6", - "hammer-time": "1.0.0", - "gsap": "1.18.2" - } -} diff --git a/config/ember-try.js b/config/ember-try.js deleted file mode 100644 index 014f603d6..000000000 --- a/config/ember-try.js +++ /dev/null @@ -1,55 +0,0 @@ -/*jshint node:true*/ -module.exports = { - scenarios: [ - { - name: 'default', - bower: { - dependencies: { } - } - }, - { - name: 'ember-1.13', - bower: { - dependencies: { - 'ember': '~1.13.0' - }, - resolutions: { - 'ember': '~1.13.0' - } - } - }, - { - name: 'ember-release', - bower: { - dependencies: { - 'ember': 'components/ember#release' - }, - resolutions: { - 'ember': 'release' - } - } - }, - { - name: 'ember-beta', - bower: { - dependencies: { - 'ember': 'components/ember#beta' - }, - resolutions: { - 'ember': 'beta' - } - } - }, - { - name: 'ember-canary', - bower: { - dependencies: { - 'ember': 'components/ember#canary' - }, - resolutions: { - 'ember': 'canary' - } - } - } - ] -}; diff --git a/config/environment.js b/config/environment.js deleted file mode 100644 index 28a787b62..000000000 --- a/config/environment.js +++ /dev/null @@ -1,6 +0,0 @@ -/*jshint node:true*/ -'use strict'; - -module.exports = function(/* environment, appConfig */) { - return { }; -}; diff --git a/config/flexi.js b/config/flexi.js deleted file mode 100644 index c789400bc..000000000 --- a/config/flexi.js +++ /dev/null @@ -1,35 +0,0 @@ -/* jshint node:true */ -module.exports = { - - // breakpoints, order does not matter, they will be sorted by `begin` - // `name` is used for layout names and booleans on the device/layout service - // `prefix` is used for column classes, column attributes, and container breakpoint classes - // `begin` is the pixel value at which this breakpoint becomes active - breakpoints: [ - { name: 'mobile', prefix: 'xs', begin: 0 }, - { name: 'tablet', prefix: 'sm', begin: 768 }, - { name: 'desktop', prefix: 'md', begin: 992 }, - { name: 'huge', prefix: 'lg', begin: 1200 } - ], - - // the number of columns for the grid - columns: 12, - - // optional, used for column classes: '--' - columnPrefix: 'col', - - // if false, @media css is not included - includeMediaCSS: true, - - // if false, default element styles are not included - includeElementCSS: true, - - // if true, will convert layout attributes on non-layout elements to classes as well - transformAllElementLayoutAttributes: false, - - // grid and layout element gutters - gutterPadding: '.5rem', - - // if false, no styles are included (trumps 'includeMediaCSS' and 'includeElementCSS') - includeCSS: true -}; diff --git a/ember-cli-build.js b/ember-cli-build.js deleted file mode 100644 index 4ac391379..000000000 --- a/ember-cli-build.js +++ /dev/null @@ -1,18 +0,0 @@ -/*jshint node:true*/ -/* global require, module */ -var EmberAddon = require('ember-cli/lib/broccoli/ember-addon'); - -module.exports = function(defaults) { - var app = new EmberAddon(defaults, { - // Add options here - }); - - /* - This build file specifies the options for the dummy test app of this - addon, located in `/tests/dummy` - This build file does *not* influence how the addon or the app using it - behave. You most likely want to be modifying `./index.js` or app's build file - */ - - return app.toTree(); -}; diff --git a/index.js b/index.js deleted file mode 100644 index bcfe71d0e..000000000 --- a/index.js +++ /dev/null @@ -1,11 +0,0 @@ -/* jshint node:true */ -/* global module, process */ -'use strict'; - -module.exports = { - name: 'history', - - isDevelopingAddon: function() { - return true; - } -}; diff --git a/addon/-private/gestures/inputs/input.js b/inputs/input.js similarity index 100% rename from addon/-private/gestures/inputs/input.js rename to inputs/input.js diff --git a/addon/-private/gestures/inputs/mouse.js b/inputs/mouse.js similarity index 100% rename from addon/-private/gestures/inputs/mouse.js rename to inputs/mouse.js diff --git a/addon/-private/gestures/inputs/pointer.js b/inputs/pointer.js similarity index 100% rename from addon/-private/gestures/inputs/pointer.js rename to inputs/pointer.js diff --git a/addon/-private/gestures/inputs/touch.js b/inputs/touch.js similarity index 100% rename from addon/-private/gestures/inputs/touch.js rename to inputs/touch.js diff --git a/addon/-private/gestures/layer.js b/layer.js similarity index 100% rename from addon/-private/gestures/layer.js rename to layer.js diff --git a/addon/-private/gestures/manager.js b/manager.js similarity index 100% rename from addon/-private/gestures/manager.js rename to manager.js diff --git a/package.json b/package.json deleted file mode 100644 index ef07c4a7d..000000000 --- a/package.json +++ /dev/null @@ -1,64 +0,0 @@ -{ - "name": "history", - "version": "0.0.0", - "description": "The default blueprint for ember-cli addons.", - "directories": { - "doc": "doc", - "test": "tests" - }, - "scripts": { - "build": "ember build", - "start": "ember server", - "test": "ember try:each" - }, - "repository": "", - "engines": { - "node": ">= 0.10.0" - }, - "author": "", - "license": "MIT", - "devDependencies": { - "body-parser": "^1.15.1", - "broccoli-asset-rev": "^2.4.2", - "ember-ajax": "^2.0.1", - "ember-cli": "2.6.0-beta.2", - "ember-cli-app-version": "^1.0.0", - "ember-cli-dependency-checker": "^1.2.0", - "ember-cli-htmlbars-inline-precompile": "^0.3.1", - "ember-cli-inject-live-reload": "^1.4.0", - "ember-cli-jshint": "^1.0.0", - "ember-cli-qunit": "^1.4.0", - "ember-cli-release": "0.2.8", - "ember-cli-sri": "^2.1.0", - "ember-cli-uglify": "^1.2.0", - "ember-cli-version-checker": "^1.1.6", - "ember-data": "^2.6.0-beta.1", - "ember-disable-prototype-extensions": "^1.1.0", - "ember-export-application-global": "^1.0.5", - "ember-gestures": "0.4.2", - "ember-hammertime": "^1.0.3", - "ember-load-initializers": "^0.5.1", - "ember-resolver": "^2.0.3", - "ember-suave": "^2.0.1", - "express": "^4.13.4", - "faker": "^3.1.0", - "flexi": "1.1.9", - "glob": "^4.5.3", - "liquid-fire": "0.23.1", - "loader.js": "^4.0.1", - "morgan": "^1.7.0", - "object-assign": "^4.1.0", - "perf-primitives": "runspired/perf-primitives" - }, - "keywords": [ - "ember-addon" - ], - "dependencies": { - "ember-cli-sass": "5.3.1", - "ember-cli-htmlbars": "^1.0.3", - "ember-cli-babel": "^5.1.6" - }, - "ember-addon": { - "configPath": "tests/dummy/config" - } -} diff --git a/addon/-private/gestures/recognizer.js b/recognizer.js similarity index 100% rename from addon/-private/gestures/recognizer.js rename to recognizer.js diff --git a/addon/-private/gestures/recognizers/horizontal-pan.js b/recognizers/horizontal-pan.js similarity index 100% rename from addon/-private/gestures/recognizers/horizontal-pan.js rename to recognizers/horizontal-pan.js diff --git a/addon/-private/gestures/recognizers/vertical-pan.js b/recognizers/vertical-pan.js similarity index 100% rename from addon/-private/gestures/recognizers/vertical-pan.js rename to recognizers/vertical-pan.js diff --git a/server/.jshintrc b/server/.jshintrc deleted file mode 100644 index c1f2978bc..000000000 --- a/server/.jshintrc +++ /dev/null @@ -1,3 +0,0 @@ -{ - "node": true -} diff --git a/server/index.js b/server/index.js deleted file mode 100644 index 8068c75eb..000000000 --- a/server/index.js +++ /dev/null @@ -1,24 +0,0 @@ -/*jshint node:true*/ - -// To use it create some files under `mocks/` -// e.g. `server/mocks/ember-hamsters.js` -// -// module.exports = function(app) { -// app.get('/ember-hamsters', function(req, res) { -// res.send('hello'); -// }); -// }; - -module.exports = function(app) { - var globSync = require('glob').sync; - var mocks = globSync('./mocks/**/*.js', { cwd: __dirname }).map(require); - var proxies = globSync('./proxies/**/*.js', { cwd: __dirname }).map(require); - - // Log proxy requests - var morgan = require('morgan'); - app.use(morgan('dev')); - - mocks.forEach(function(route) { route(app); }); - proxies.forEach(function(route) { route(app); }); - -}; diff --git a/server/mocks/items.js b/server/mocks/items.js deleted file mode 100644 index e1b0a8baf..000000000 --- a/server/mocks/items.js +++ /dev/null @@ -1,160 +0,0 @@ -/*jshint node:true*/ -var faker = require('faker'); -var assign = require('object-assign'); -var bodyParser = require('body-parser'); - -function between(min, max) { - return Math.floor(Math.random() * (max + 1 - min) + min); -} - -var MODEL_DEFAULTS = { - __deleted: false -}; - -function itemFactory() { - return assign({ - id: null, - title: faker.lorem.words(between(3, 8)), - description: faker.lorem.sentences(between(2, 5)) - }, MODEL_DEFAULTS); -} - -function Store(factory, type) { - this._recordMap = {}; - this._records = []; - this._nextID = 0; - this._schema = factory; - this._type = type; -} - -Store.prototype.clone = function clone(records) { - return records.map(function(record) { - return assign({}, record); - }); -}; - -Store.prototype.serializeOne = function serializeOne(record) { - return { - data: { - id: record.id, - type: this._type, - attributes: assign({}, record) - } - }; -}; - -Store.prototype.normalizeOne = function normalizeOne(record) { - var values = record.data && record.data.attributes ? record.data.attributes : {}; - - delete values.id; - - return values; -}; - -Store.prototype.serializeMany = function serializeMany(records) { - var _this = this; - var data = records.map(function(record) { - return _this.serializeOne(record).data; - }); - - return { data: data }; -}; - -Store.prototype.findRecord = function findRecord(id) { - var record = this._recordMap[id]; - - if (!record || record.__deleted) { - throw new Error(404); - } - - return this.serializeOne(record); -}; - -Store.prototype.createRecord = function createRecord(data) { - var record = {}; - - if (!data) { - throw new Error(500); - } - - var values = this.normalizeOne(data); - - assign(record, this._schema(), values, { id: this._nextID++ }); - this._records.push(record); - this._recordMap[record.id] = record; - - return this.serializeOne(record); -}; - -Store.prototype.findAll = function findAll() { - return this.serializeMany(this._records.filter(function(record) { - return !record.__deleted; - })); -}; - -Store.prototype.deleteRecord = function deleteRecord(id) { - var record = this._recordMap[id]; - - if (!record || record.__deleted) { - throw new Error(500); - } - - record.__deleted = true; -}; - -Store.prototype.updateRecord = function updateRecord(id, data) { - var record = this._recordMap[id]; - - if (!data || !record || record.__deleted) { - throw new Error(500); - } - - var values = this.normalizeOne(data); - - assign(record, values); - - return this.serializeOne(record); -}; - -module.exports = function(app) { - var express = require('express'); - var itemsRouter = express.Router(); - var store = new Store(itemFactory, 'items'); - - for (var i = 0; i < 50; i++) { - store.createRecord({}); - } - - itemsRouter.get('/', function(req, res) { - res.send(store.findAll()); - }); - - itemsRouter.post('/', function(req, res) { - res.status(201).send(store.createRecord(req.body)); - }); - - itemsRouter.get('/:id', function(req, res) { - res.send(store.findRecord(req.params.id)); - }); - - itemsRouter.put('/:id', function(req, res) { - res.send(store.updateRecord(req.params.id, req.body)); - }); - - itemsRouter.delete('/:id', function(req, res) { - store.deleteRecord(req.params.id); - res.status(204).end(); - }); - - // The POST and PUT call will not contain a request body - // because the body-parser is not included by default. - // To use req.body, run: - - // npm install --save-dev body-parser - - // After installing, you need to `use` the body-parser for - // this mock uncommenting the following line: - // - app.use('/api/items', bodyParser.json()); - app.use('/api/items', itemsRouter); -}; diff --git a/addon/-private/gestures/streams/stream-event.js b/streams/stream-event.js similarity index 100% rename from addon/-private/gestures/streams/stream-event.js rename to streams/stream-event.js diff --git a/addon/-private/gestures/streams/stream-series.js b/streams/stream-series.js similarity index 100% rename from addon/-private/gestures/streams/stream-series.js rename to streams/stream-series.js diff --git a/addon/-private/gestures/streams/stream.js b/streams/stream.js similarity index 100% rename from addon/-private/gestures/streams/stream.js rename to streams/stream.js diff --git a/testem.js b/testem.js deleted file mode 100644 index 26044b2f8..000000000 --- a/testem.js +++ /dev/null @@ -1,13 +0,0 @@ -/*jshint node:true*/ -module.exports = { - "framework": "qunit", - "test_page": "tests/index.html?hidepassed", - "disable_watching": true, - "launch_in_ci": [ - "PhantomJS" - ], - "launch_in_dev": [ - "PhantomJS", - "Chrome" - ] -}; diff --git a/tests/.jshintrc b/tests/.jshintrc deleted file mode 100644 index 6ec0b7c15..000000000 --- a/tests/.jshintrc +++ /dev/null @@ -1,52 +0,0 @@ -{ - "predef": [ - "document", - "window", - "location", - "setTimeout", - "$", - "-Promise", - "define", - "console", - "visit", - "exists", - "fillIn", - "click", - "keyEvent", - "triggerEvent", - "find", - "findWithAssert", - "wait", - "DS", - "andThen", - "currentURL", - "currentPath", - "currentRouteName" - ], - "node": false, - "browser": false, - "boss": true, - "curly": true, - "debug": false, - "devel": false, - "eqeqeq": true, - "evil": true, - "forin": false, - "immed": false, - "laxbreak": false, - "newcap": true, - "noarg": true, - "noempty": false, - "nonew": false, - "nomen": false, - "onevar": false, - "plusplus": false, - "regexp": false, - "undef": true, - "sub": true, - "strict": false, - "white": false, - "eqnull": true, - "esnext": true, - "unused": true -} diff --git a/tests/dummy/app/adapters/application.js b/tests/dummy/app/adapters/application.js deleted file mode 100644 index b37ab130e..000000000 --- a/tests/dummy/app/adapters/application.js +++ /dev/null @@ -1,5 +0,0 @@ -import JSONAPIAdapter from 'ember-data/adapters/json-api'; - -export default JSONAPIAdapter.extend({ - namespace: 'api' -}); diff --git a/tests/dummy/app/app.js b/tests/dummy/app/app.js deleted file mode 100644 index cedcf742b..000000000 --- a/tests/dummy/app/app.js +++ /dev/null @@ -1,37 +0,0 @@ -import Ember from 'ember'; -import Resolver from './resolver'; -import loadInitializers from 'ember-load-initializers'; -import config from './config/environment'; - -let App; - -Ember.MODEL_FACTORY_INJECTIONS = true; - -App = Ember.Application.extend({ - modulePrefix: config.modulePrefix, - podModulePrefix: config.podModulePrefix, - Resolver, - customEvents: { - touchstart: null, - touchmove: null, - touchcancel: null, - touchend: null, - mousedown: null, - mouseenter: null, - mousemove: null, - mouseleave: null, - mouseup: null, - drag: null, - dragend: null, - dragenter: null, - dragleave: null, - dragover: null, - dragstart: null, - drop: null, - dblclick: null - } -}); - -loadInitializers(App, config.modulePrefix); - -export default App; diff --git a/tests/dummy/app/components/.gitkeep b/tests/dummy/app/components/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/dummy/app/controllers/.gitkeep b/tests/dummy/app/controllers/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/dummy/app/helpers/.gitkeep b/tests/dummy/app/helpers/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/dummy/app/index.html b/tests/dummy/app/index.html deleted file mode 100644 index c9b432708..000000000 --- a/tests/dummy/app/index.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - Dummy - - - - {{content-for "head"}} - - - - - {{content-for "head-footer"}} - - - {{content-for "body"}} - - - - - {{content-for "body-footer"}} - - diff --git a/tests/dummy/app/models/.gitkeep b/tests/dummy/app/models/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/dummy/app/models/item.js b/tests/dummy/app/models/item.js deleted file mode 100644 index fa2ed4bce..000000000 --- a/tests/dummy/app/models/item.js +++ /dev/null @@ -1,8 +0,0 @@ -import Model from 'ember-data/model'; -import attr from 'ember-data/attr'; -// import { belongsTo, hasMany } from 'ember-data/relationships'; - -export default Model.extend({ - title: attr(), - description: attr() -}); diff --git a/tests/dummy/app/resolver.js b/tests/dummy/app/resolver.js deleted file mode 100644 index 2fb563d6c..000000000 --- a/tests/dummy/app/resolver.js +++ /dev/null @@ -1,3 +0,0 @@ -import Resolver from 'ember-resolver'; - -export default Resolver; diff --git a/tests/dummy/app/router.js b/tests/dummy/app/router.js deleted file mode 100644 index 8bf2e61b4..000000000 --- a/tests/dummy/app/router.js +++ /dev/null @@ -1,15 +0,0 @@ -import Ember from 'ember'; -import config from './config/environment'; - -const Router = Ember.Router.extend({ - location: config.locationType, - rootURL: config.rootURL -}); - -Router.map(function() { - this.route('items', { path: '/' }, function() { - this.route('single', { path: '/:id' }); - }); -}); - -export default Router; diff --git a/tests/dummy/app/routes/.gitkeep b/tests/dummy/app/routes/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/dummy/app/routes/application/route.js b/tests/dummy/app/routes/application/route.js deleted file mode 100644 index 8251ca090..000000000 --- a/tests/dummy/app/routes/application/route.js +++ /dev/null @@ -1,17 +0,0 @@ -import Ember from 'ember'; - -const { - get, - Route, - set - } = Ember; - -export default Route.extend({ - - setupController(controller, model) { - this._super(controller, model); - - set(controller, 'currentRouteName', get(this, 'routeName')); - } - -}); diff --git a/tests/dummy/app/routes/application/template.hbs b/tests/dummy/app/routes/application/template.hbs deleted file mode 100644 index c68fcde9f..000000000 --- a/tests/dummy/app/routes/application/template.hbs +++ /dev/null @@ -1,6 +0,0 @@ - - {{!-- - {{history-outlet currentRouteName=currentRouteName}} - --}} - {{outlet}} - \ No newline at end of file diff --git a/tests/dummy/app/routes/components/swipe-box/component.js b/tests/dummy/app/routes/components/swipe-box/component.js deleted file mode 100644 index acfc3ee6e..000000000 --- a/tests/dummy/app/routes/components/swipe-box/component.js +++ /dev/null @@ -1,72 +0,0 @@ -/* global requestAnimationFrame */ -import Ember from 'ember'; -import layout from './template'; -import RecognizerMixin from 'ember-gestures/mixins/recognizers'; -import TweenLite from 'tweenlite'; - -export default Ember.Component.extend(RecognizerMixin, { - layout, - - recognizers: 'pan', - - isPanning: false, - _nextUpdate: undefined, - dX: 0, - _dX: 0, - - startAnimating() { - if (!this._nextUpdate) { - this.isPanning = true; - this._nextUpdate = requestAnimationFrame(() => { - this.updateAnimationState(); - }); - } - }, - - updateAnimationState() { - let { _dX, dX, element } = this; - - TweenLite.set(element, { css: { x: `${_dX + dX}px` } }); - - if (this.isPanning) { - this._nextUpdate = requestAnimationFrame(() => { - this.updateAnimationState(); - }); - } else { - // this._dX = _dX + dX; - this._nextUpdate = undefined; - - TweenLite.to(element, 0.35, { css: { x: `0px` } }); - - } - }, - - panStart() { - this.dX = 0; - this.startAnimating(); - }, - - panEnd(e) { - let { deltaX } = e.originalEvent.gesture; - - this.dX = deltaX; - this.isPanning = false; - }, - - panLeft(e) { - if (this.isPanning) { - let { deltaX } = e.originalEvent.gesture; - - this.dX = deltaX; - } - }, - - panRight(e) { - if (this.isPanning) { - let { deltaX } = e.originalEvent.gesture; - - this.dX = deltaX; - } - } - -}); diff --git a/tests/dummy/app/routes/components/swipe-box/template.hbs b/tests/dummy/app/routes/components/swipe-box/template.hbs deleted file mode 100644 index 889d9eead..000000000 --- a/tests/dummy/app/routes/components/swipe-box/template.hbs +++ /dev/null @@ -1 +0,0 @@ -{{yield}} diff --git a/tests/dummy/app/routes/items/index/route.js b/tests/dummy/app/routes/items/index/route.js deleted file mode 100644 index c738b98a6..000000000 --- a/tests/dummy/app/routes/items/index/route.js +++ /dev/null @@ -1,13 +0,0 @@ -import Ember from 'ember'; - -const { - Route - } = Ember; - -export default Route.extend({ - - model() { - return this.modelFor('items'); - } - -}); diff --git a/tests/dummy/app/routes/items/index/template.hbs b/tests/dummy/app/routes/items/index/template.hbs deleted file mode 100644 index e188ed56f..000000000 --- a/tests/dummy/app/routes/items/index/template.hbs +++ /dev/null @@ -1,11 +0,0 @@ -
    - {{#each model as |item|}} -
  • -

    - {{#link-to 'items.single' item}} - {{item.title}} - {{/link-to}} -

    -
  • - {{/each}} -
\ No newline at end of file diff --git a/tests/dummy/app/routes/items/route.js b/tests/dummy/app/routes/items/route.js deleted file mode 100644 index 1b6430a2d..000000000 --- a/tests/dummy/app/routes/items/route.js +++ /dev/null @@ -1,21 +0,0 @@ -import Ember from 'ember'; - -const { - get, - set, - Route - } = Ember; - -export default Route.extend({ - - model() { - return this.get('store').findAll('item'); - }, - - setupController(controller, model) { - this._super(controller, model); - - set(controller, 'currentRouteName', get(this, 'routeName')); - } - -}); diff --git a/tests/dummy/app/routes/items/single/route.js b/tests/dummy/app/routes/items/single/route.js deleted file mode 100644 index 6eb31699d..000000000 --- a/tests/dummy/app/routes/items/single/route.js +++ /dev/null @@ -1,13 +0,0 @@ -import Ember from 'ember'; - -const { - Route - } = Ember; - -export default Route.extend({ - - model(params) { - return this.get('store').findRecord('item', params.id); - } - -}); diff --git a/tests/dummy/app/routes/items/single/template.hbs b/tests/dummy/app/routes/items/single/template.hbs deleted file mode 100644 index e2c43148a..000000000 --- a/tests/dummy/app/routes/items/single/template.hbs +++ /dev/null @@ -1,7 +0,0 @@ - -

{{model.title}}

-

- {{model.description}} -

- {{link-to 'Back' 'items'}} -
diff --git a/tests/dummy/app/routes/items/template.hbs b/tests/dummy/app/routes/items/template.hbs deleted file mode 100644 index 7ccb15d6b..000000000 --- a/tests/dummy/app/routes/items/template.hbs +++ /dev/null @@ -1 +0,0 @@ -{{history-outlet currentRouteName=currentRouteName}} \ No newline at end of file diff --git a/tests/dummy/app/serializers/application.js b/tests/dummy/app/serializers/application.js deleted file mode 100644 index 4678cc2c3..000000000 --- a/tests/dummy/app/serializers/application.js +++ /dev/null @@ -1,4 +0,0 @@ -import JSONAPISerializer from 'ember-data/serializers/json-api'; - -export default JSONAPISerializer.extend({ -}); diff --git a/tests/dummy/app/styles/app.scss b/tests/dummy/app/styles/app.scss deleted file mode 100644 index 343aefb86..000000000 --- a/tests/dummy/app/styles/app.scss +++ /dev/null @@ -1,47 +0,0 @@ -html { - font-size:62.5%; -} - -body { - font-family: "Helvetica Neue", Helvetica, "Open Sans", sans-serif; - font-size: 1.8em; - color: #333; - margin: 0; -} - -.item-card { - font-size: 1em; - padding: 1em; - background: #ff00ff; - margin: 1em; - color: #fff; -} - -.bg-dark { - background: #333; -} - -.bg-green { - background: #80e545; -} - -history-outlet { - background: #000; - - left { - background: #f00; - } - - right { - background: #0f0; - } - - outlet { - background: #00f; - } - - main { - background: #ffff00; - } - -} diff --git a/tests/dummy/app/templates/components/.gitkeep b/tests/dummy/app/templates/components/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/dummy/app/transitions.js b/tests/dummy/app/transitions.js deleted file mode 100644 index 0ddd88718..000000000 --- a/tests/dummy/app/transitions.js +++ /dev/null @@ -1,24 +0,0 @@ -export default function() { - - // debug all - this.transition = this.transition.bind(this, this.debug()); - - /* - * Initial Render - * - * - */ - // Rule 1 - this.transition( - this.onInitialRender(), - this.use('fade', { duration: 500 }) - ); - - // Rule 2 - this.transition( - this.fromRoute('items.index'), - this.use('to-left', { duration: 350 }), - this.reverse('to-right', { duration: 350 }) - ); - -} diff --git a/tests/dummy/config/environment.js b/tests/dummy/config/environment.js deleted file mode 100644 index 6007c8862..000000000 --- a/tests/dummy/config/environment.js +++ /dev/null @@ -1,48 +0,0 @@ -/* jshint node: true */ -// jscs:disable - -module.exports = function(environment) { - var ENV = { - modulePrefix: 'dummy', - podModulePrefix: 'dummy/routes', - environment: environment, - rootURL: '/', - locationType: 'auto', - EmberENV: { - FEATURES: { - // Here you can enable experimental features on an ember canary build - // e.g. 'with-controller': true - } - }, - - APP: { - // Here you can pass flags/options to your application instance - // when it is created - } - }; - - if (environment === 'development') { - // ENV.APP.LOG_RESOLVER = true; - // ENV.APP.LOG_ACTIVE_GENERATION = true; - // ENV.APP.LOG_TRANSITIONS = true; - // ENV.APP.LOG_TRANSITIONS_INTERNAL = true; - // ENV.APP.LOG_VIEW_LOOKUPS = true; - } - - if (environment === 'test') { - // Testem prefers this... - ENV.locationType = 'none'; - - // keep test console output quieter - ENV.APP.LOG_ACTIVE_GENERATION = false; - ENV.APP.LOG_VIEW_LOOKUPS = false; - - ENV.APP.rootElement = '#ember-testing'; - } - - if (environment === 'production') { - - } - - return ENV; -}; diff --git a/tests/dummy/public/crossdomain.xml b/tests/dummy/public/crossdomain.xml deleted file mode 100644 index 0c16a7a07..000000000 --- a/tests/dummy/public/crossdomain.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - diff --git a/tests/dummy/public/robots.txt b/tests/dummy/public/robots.txt deleted file mode 100644 index f5916452e..000000000 --- a/tests/dummy/public/robots.txt +++ /dev/null @@ -1,3 +0,0 @@ -# http://www.robotstxt.org -User-agent: * -Disallow: diff --git a/tests/helpers/destroy-app.js b/tests/helpers/destroy-app.js deleted file mode 100644 index c3d4d1abb..000000000 --- a/tests/helpers/destroy-app.js +++ /dev/null @@ -1,5 +0,0 @@ -import Ember from 'ember'; - -export default function destroyApp(application) { - Ember.run(application, 'destroy'); -} diff --git a/tests/helpers/module-for-acceptance.js b/tests/helpers/module-for-acceptance.js deleted file mode 100644 index f9f7205ba..000000000 --- a/tests/helpers/module-for-acceptance.js +++ /dev/null @@ -1,24 +0,0 @@ -import { module } from 'qunit'; -import Ember from 'ember'; -import startApp from '../helpers/start-app'; -import destroyApp from '../helpers/destroy-app'; - -const { RSVP: { Promise } } = Ember; - -export default function(name, options = {}) { - module(name, { - beforeEach() { - this.application = startApp(); - - if (options.beforeEach) { - return options.beforeEach(...arguments); - } - }, - - afterEach() { - let afterEach = options.afterEach && options.afterEach(...arguments); - - return Promise.resolve(afterEach).then(() => destroyApp(this.application)); - } - }); -} diff --git a/tests/helpers/resolver.js b/tests/helpers/resolver.js deleted file mode 100644 index b208d38d0..000000000 --- a/tests/helpers/resolver.js +++ /dev/null @@ -1,11 +0,0 @@ -import Resolver from '../../resolver'; -import config from '../../config/environment'; - -const resolver = Resolver.create(); - -resolver.namespace = { - modulePrefix: config.modulePrefix, - podModulePrefix: config.podModulePrefix -}; - -export default resolver; diff --git a/tests/helpers/start-app.js b/tests/helpers/start-app.js deleted file mode 100644 index e098f1d5b..000000000 --- a/tests/helpers/start-app.js +++ /dev/null @@ -1,18 +0,0 @@ -import Ember from 'ember'; -import Application from '../../app'; -import config from '../../config/environment'; - -export default function startApp(attrs) { - let application; - - let attributes = Ember.merge({}, config.APP); - attributes = Ember.merge(attributes, attrs); // use defaults, but you can override; - - Ember.run(() => { - application = Application.create(attributes); - application.setupForTesting(); - application.injectTestHelpers(); - }); - - return application; -} diff --git a/tests/index.html b/tests/index.html deleted file mode 100644 index 9ce2d7e5e..000000000 --- a/tests/index.html +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - Dummy Tests - - - - {{content-for "head"}} - {{content-for "test-head"}} - - - - - - {{content-for "head-footer"}} - {{content-for "test-head-footer"}} - - - {{content-for "body"}} - {{content-for "test-body"}} - - - - - - - - - {{content-for "body-footer"}} - {{content-for "test-body-footer"}} - - diff --git a/tests/integration/.gitkeep b/tests/integration/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/integration/components/history-outlet-test.js b/tests/integration/components/history-outlet-test.js deleted file mode 100644 index 337f5a3a7..000000000 --- a/tests/integration/components/history-outlet-test.js +++ /dev/null @@ -1,24 +0,0 @@ -import { moduleForComponent, test } from 'ember-qunit'; -import hbs from 'htmlbars-inline-precompile'; - -moduleForComponent('history-outlet', 'Integration | Component | history outlet', { - integration: true -}); - -test('it renders', function(assert) { - // Set any properties with this.set('myProperty', 'value'); - // Handle any actions with this.on('myAction', function(val) { ... }); - - this.render(hbs`{{history-outlet}}`); - - assert.equal(this.$().text().trim(), ''); - - // Template block usage: - this.render(hbs` - {{#history-outlet}} - template block text - {{/history-outlet}} - `); - - assert.equal(this.$().text().trim(), 'template block text'); -}); diff --git a/tests/test-helper.js b/tests/test-helper.js deleted file mode 100644 index e6cfb70fe..000000000 --- a/tests/test-helper.js +++ /dev/null @@ -1,6 +0,0 @@ -import resolver from './helpers/resolver'; -import { - setResolver -} from 'ember-qunit'; - -setResolver(resolver); diff --git a/tests/unit/.gitkeep b/tests/unit/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/unit/instance-initializers/gesture-recognition-test.js b/tests/unit/instance-initializers/gesture-recognition-test.js deleted file mode 100644 index 28def4b75..000000000 --- a/tests/unit/instance-initializers/gesture-recognition-test.js +++ /dev/null @@ -1,30 +0,0 @@ -import Ember from 'ember'; -import { initialize } from 'dummy/instance-initializers/gesture-recognition'; -import { module, test } from 'qunit'; -import destroyApp from '../../helpers/destroy-app'; - -const { - run, - Application - } = Ember; - -module('Unit | Instance Initializer | gesture recognition', { - beforeEach() { - run(() => { - this.application = Application.create(); - this.appInstance = this.application.buildInstance(); - }); - }, - afterEach() { - run(this.appInstance, 'destroy'); - destroyApp(this.application); - } -}); - -// Replace this with your real tests. -test('it works', function(assert) { - initialize(this.appInstance); - - // you would normally confirm the results of the initializer here - assert.ok(true); -}); diff --git a/tests/unit/services/gesture-recognition-test.js b/tests/unit/services/gesture-recognition-test.js deleted file mode 100644 index ee24a975d..000000000 --- a/tests/unit/services/gesture-recognition-test.js +++ /dev/null @@ -1,12 +0,0 @@ -import { moduleFor, test } from 'ember-qunit'; - -moduleFor('service:gesture-recognition', 'Unit | Service | gesture recognition', { - // Specify the other units that are required for this test. - // needs: ['service:foo'] -}); - -// Replace this with your real tests. -test('it exists', function(assert) { - let service = this.subject(); - assert.ok(service); -}); diff --git a/tests/unit/services/history-test.js b/tests/unit/services/history-test.js deleted file mode 100644 index 57b9803a2..000000000 --- a/tests/unit/services/history-test.js +++ /dev/null @@ -1,12 +0,0 @@ -import { moduleFor, test } from 'ember-qunit'; - -moduleFor('service:history', 'Unit | Service | history', { - // Specify the other units that are required for this test. - // needs: ['service:foo'] -}); - -// Replace this with your real tests. -test('it exists', function(assert) { - let service = this.subject(); - assert.ok(service); -}); diff --git a/addon/-private/gestures/utils/detection.js b/utils/detection.js similarity index 100% rename from addon/-private/gestures/utils/detection.js rename to utils/detection.js diff --git a/addon/-private/gestures/utils/macro-task.js b/utils/macro-task.js similarity index 100% rename from addon/-private/gestures/utils/macro-task.js rename to utils/macro-task.js diff --git a/addon/-private/gestures/utils/supports-passive.js b/utils/supports-passive.js similarity index 100% rename from addon/-private/gestures/utils/supports-passive.js rename to utils/supports-passive.js diff --git a/vendor/.gitkeep b/vendor/.gitkeep deleted file mode 100644 index e69de29bb..000000000 From 8a7773e6e788ffa6016dc6bfbafdacc7f9d75dd0 Mon Sep 17 00:00:00 2001 From: Christopher Garrett Date: Tue, 12 Jul 2016 14:21:04 -0700 Subject: [PATCH 59/61] Remove Hammer 2 source --- src/.babelrc | 3 - src/hammer.js | 157 -------- src/input/mouse.js | 67 ---- src/input/pointerevent.js | 102 ------ src/input/singletouch.js | 82 ----- src/input/touch.js | 115 ------ src/input/touchmouse.js | 111 ------ src/inputjs/compute-delta-xy.js | 25 -- src/inputjs/compute-input-data.js | 70 ---- src/inputjs/compute-interval-input-data.js | 43 --- src/inputjs/create-input-instance.js | 31 -- src/inputjs/get-angle.js | 18 - src/inputjs/get-center.js | 33 -- src/inputjs/get-direction.js | 20 -- src/inputjs/get-distance.js | 19 - src/inputjs/get-rotation.js | 13 - src/inputjs/get-scale.js | 13 - src/inputjs/get-velocity.js | 14 - src/inputjs/input-constructor.js | 59 --- src/inputjs/input-consts.js | 58 --- src/inputjs/input-handler.js | 36 -- src/inputjs/simple-clone-input-data.js | 30 -- src/main.js | 139 ------- src/manager.js | 339 ------------------ src/recognizerjs/direction-str.js | 25 -- .../get-recognizer-by-name-if-manager.js | 14 - src/recognizerjs/recognizer-constructor.js | 309 ---------------- src/recognizerjs/recognizer-consts.js | 17 - src/recognizerjs/state-str.js | 25 -- src/recognizers/attribute.js | 80 ----- src/recognizers/pan.js | 98 ----- src/recognizers/pinch.js | 46 --- src/recognizers/press.js | 88 ----- src/recognizers/rotate.js | 38 -- src/recognizers/swipe.js | 66 ---- src/recognizers/tap.js | 128 ------- src/touchactionjs/clean-touch-actions.js | 44 --- src/touchactionjs/get-touchaction-props.js | 16 - src/touchactionjs/touchaction-Consts.js | 27 -- src/touchactionjs/touchaction-constructor.js | 125 ------- src/utils/add-event-listeners.js | 14 - src/utils/assign.js | 33 -- src/utils/bind-fn.js | 12 - src/utils/bool-or-fn.js | 15 - src/utils/deprecate.js | 23 -- src/utils/each.js | 28 -- src/utils/extend.js | 23 -- src/utils/get-window-for-element.js | 10 - src/utils/has-parent.js | 17 - src/utils/if-undefined.js | 10 - src/utils/in-array.js | 22 -- src/utils/in-str.js | 10 - src/utils/inherit.js | 20 -- src/utils/invoke-array-arg.js | 18 - src/utils/merge.js | 15 - src/utils/prefixed.js | 25 -- src/utils/remove-event-listeners.js | 14 - src/utils/set-timeout-context.js | 13 - src/utils/split-str.js | 10 - src/utils/to-array.js | 9 - src/utils/unique-array.js | 36 -- src/utils/unique-id.js | 9 - src/utils/utils-consts.js | 16 - 63 files changed, 3145 deletions(-) delete mode 100644 src/.babelrc delete mode 100644 src/hammer.js delete mode 100644 src/input/mouse.js delete mode 100644 src/input/pointerevent.js delete mode 100644 src/input/singletouch.js delete mode 100644 src/input/touch.js delete mode 100644 src/input/touchmouse.js delete mode 100644 src/inputjs/compute-delta-xy.js delete mode 100644 src/inputjs/compute-input-data.js delete mode 100644 src/inputjs/compute-interval-input-data.js delete mode 100644 src/inputjs/create-input-instance.js delete mode 100644 src/inputjs/get-angle.js delete mode 100644 src/inputjs/get-center.js delete mode 100644 src/inputjs/get-direction.js delete mode 100644 src/inputjs/get-distance.js delete mode 100644 src/inputjs/get-rotation.js delete mode 100644 src/inputjs/get-scale.js delete mode 100644 src/inputjs/get-velocity.js delete mode 100644 src/inputjs/input-constructor.js delete mode 100644 src/inputjs/input-consts.js delete mode 100644 src/inputjs/input-handler.js delete mode 100644 src/inputjs/simple-clone-input-data.js delete mode 100644 src/main.js delete mode 100644 src/manager.js delete mode 100644 src/recognizerjs/direction-str.js delete mode 100644 src/recognizerjs/get-recognizer-by-name-if-manager.js delete mode 100644 src/recognizerjs/recognizer-constructor.js delete mode 100644 src/recognizerjs/recognizer-consts.js delete mode 100644 src/recognizerjs/state-str.js delete mode 100644 src/recognizers/attribute.js delete mode 100644 src/recognizers/pan.js delete mode 100644 src/recognizers/pinch.js delete mode 100644 src/recognizers/press.js delete mode 100644 src/recognizers/rotate.js delete mode 100644 src/recognizers/swipe.js delete mode 100644 src/recognizers/tap.js delete mode 100644 src/touchactionjs/clean-touch-actions.js delete mode 100644 src/touchactionjs/get-touchaction-props.js delete mode 100644 src/touchactionjs/touchaction-Consts.js delete mode 100644 src/touchactionjs/touchaction-constructor.js delete mode 100644 src/utils/add-event-listeners.js delete mode 100644 src/utils/assign.js delete mode 100644 src/utils/bind-fn.js delete mode 100644 src/utils/bool-or-fn.js delete mode 100644 src/utils/deprecate.js delete mode 100644 src/utils/each.js delete mode 100644 src/utils/extend.js delete mode 100644 src/utils/get-window-for-element.js delete mode 100644 src/utils/has-parent.js delete mode 100644 src/utils/if-undefined.js delete mode 100644 src/utils/in-array.js delete mode 100644 src/utils/in-str.js delete mode 100644 src/utils/inherit.js delete mode 100644 src/utils/invoke-array-arg.js delete mode 100644 src/utils/merge.js delete mode 100644 src/utils/prefixed.js delete mode 100644 src/utils/remove-event-listeners.js delete mode 100644 src/utils/set-timeout-context.js delete mode 100644 src/utils/split-str.js delete mode 100644 src/utils/to-array.js delete mode 100644 src/utils/unique-array.js delete mode 100644 src/utils/unique-id.js delete mode 100644 src/utils/utils-consts.js diff --git a/src/.babelrc b/src/.babelrc deleted file mode 100644 index 1d9cdd528..000000000 --- a/src/.babelrc +++ /dev/null @@ -1,3 +0,0 @@ -{ - "presets": ["es2015-rollup"] -} diff --git a/src/hammer.js b/src/hammer.js deleted file mode 100644 index c016ee27d..000000000 --- a/src/hammer.js +++ /dev/null @@ -1,157 +0,0 @@ -import ifUndefined from './utils/if-undefined'; -import { TOUCH_ACTION_COMPUTE } from './touchactionjs/touchaction-Consts'; -import { DIRECTION_HORIZONTAL } from './inputjs/input-consts'; -import RotateRecognizer from './recognizers/rotate'; -import PinchRecognizer from './recognizers/pinch'; -import SwipeRecognizer from './recognizers/swipe'; -import PanRecognizer from './recognizers/pan'; -import TapRecognizer from './recognizers/tap'; -import PressRecognizer from './recognizers/press'; -import Manager from './manager'; - -/** - * @private - * Simple way to create a manager with a default set of recognizers. - * @param {HTMLElement} element - * @param {Object} [options] - * @constructor - */ -export default class Hammer { - constructor(element, options) { - options = options || {}; - options.recognizers = ifUndefined(options.recognizers, Hammer.defaults.preset); - return new Manager(element, options); - } -} - -/** - * @private - * @const {string} - */ -Hammer.VERSION = '{{PKG_VERSION}}'; - -/** - * @private - * default settings - * @namespace - */ -Hammer.defaults = { - /** - * @private - * set if DOM events are being triggered. - * But this is slower and unused by simple implementations, so disabled by default. - * @type {Boolean} - * @default false - */ - domEvents: false, - - /** - * @private - * The value for the touchAction property/fallback. - * When set to `compute` it will magically set the correct value based on the added recognizers. - * @type {String} - * @default compute - */ - touchAction: TOUCH_ACTION_COMPUTE, - - /** - * @private - * @type {Boolean} - * @default true - */ - enable: true, - - /** - * @private - * EXPERIMENTAL FEATURE -- can be removed/changed - * Change the parent input target element. - * If Null, then it is being set the to main element. - * @type {Null|EventTarget} - * @default null - */ - inputTarget: null, - - /** - * @private - * force an input class - * @type {Null|Function} - * @default null - */ - inputClass: null, - - /** - * @private - * Default recognizer setup when calling `Hammer()` - * When creating a new Manager these will be skipped. - * @type {Array} - */ - preset: [ - // RecognizerClass, options, [recognizeWith, ...], [requireFailure, ...] - [RotateRecognizer, { enable: false }], - [PinchRecognizer, { enable: false }, ['rotate']], - [SwipeRecognizer, { direction: DIRECTION_HORIZONTAL }], - [PanRecognizer, { direction: DIRECTION_HORIZONTAL }, ['swipe']], - [TapRecognizer], - [TapRecognizer, { event: 'doubletap', taps: 2 }, ['tap']], - [PressRecognizer] - ], - - /** - * @private - * Some CSS properties can be used to improve the working of Hammer. - * Add them to this method and they will be set when creating a new Manager. - * @namespace - */ - cssProps: { - /** - * @private - * Disables text selection to improve the dragging gesture. Mainly for desktop browsers. - * @type {String} - * @default 'none' - */ - userSelect: 'none', - - /** - * @private - * Disable the Windows Phone grippers when pressing an element. - * @type {String} - * @default 'none' - */ - touchSelect: 'none', - - /** - * @private - * Disables the default callout shown when you touch and hold a touch target. - * On iOS, when you touch and hold a touch target such as a link, Safari displays - * a callout containing information about the link. This property allows you to disable that callout. - * @type {String} - * @default 'none' - */ - touchCallout: 'none', - - /** - * @private - * Specifies whether zooming is enabled. Used by IE10> - * @type {String} - * @default 'none' - */ - contentZooming: 'none', - - /** - * @private - * Specifies that an entire element should be draggable instead of its contents. Mainly for desktop browsers. - * @type {String} - * @default 'none' - */ - userDrag: 'none', - - /** - * @private - * Overrides the highlight color shown when the user taps a link or a JavaScript - * clickable element in iOS. This property obeys the alpha value, if specified. - * @type {String} - * @default 'rgba(0,0,0,0)' - */ - tapHighlightColor: 'rgba(0,0,0,0)' - } -}; diff --git a/src/input/mouse.js b/src/input/mouse.js deleted file mode 100644 index 5ef0ebf97..000000000 --- a/src/input/mouse.js +++ /dev/null @@ -1,67 +0,0 @@ -import { - INPUT_START, - INPUT_MOVE, - INPUT_END, - INPUT_TYPE_MOUSE -} from '../inputjs/input-consts'; -import Input from '../inputjs/input-constructor'; - -const MOUSE_INPUT_MAP = { - mousedown: INPUT_START, - mousemove: INPUT_MOVE, - mouseup: INPUT_END -}; - -const MOUSE_ELEMENT_EVENTS = 'mousedown'; -const MOUSE_WINDOW_EVENTS = 'mousemove mouseup'; - -/** - * @private - * Mouse events input - * @constructor - * @extends Input - */ -export default class MouseInput extends Input { - constructor() { - super(...arguments); - - this.evEl = MOUSE_ELEMENT_EVENTS; - this.evWin = MOUSE_WINDOW_EVENTS; - - this.pressed = false; // mousedown state - } - - /** - * @private - * handle mouse events - * @param {Object} ev - */ - handler(ev) { - let eventType = MOUSE_INPUT_MAP[ev.type]; - - // on start we want to have the left mouse button down - if (eventType & INPUT_START && ev.button === 0) { - this.pressed = true; - } - - if (eventType & INPUT_MOVE && ev.which !== 1) { - eventType = INPUT_END; - } - - // mouse must be down - if (!this.pressed) { - return; - } - - if (eventType & INPUT_END) { - this.pressed = false; - } - - this.callback(this.manager, eventType, { - pointers: [ev], - changedPointers: [ev], - pointerType: INPUT_TYPE_MOUSE, - srcEvent: ev - }); - } -} diff --git a/src/input/pointerevent.js b/src/input/pointerevent.js deleted file mode 100644 index 78ef8943a..000000000 --- a/src/input/pointerevent.js +++ /dev/null @@ -1,102 +0,0 @@ -import { - INPUT_START, - INPUT_END, - INPUT_CANCEL, - INPUT_MOVE, - INPUT_TYPE_TOUCH, - INPUT_TYPE_MOUSE, - INPUT_TYPE_PEN, - INPUT_TYPE_KINECT -} from '../inputjs/input-consts'; -import Input from '../inputjs/input-constructor'; -import inArray from '../utils/in-array'; - -const POINTER_INPUT_MAP = { - pointerdown: INPUT_START, - pointermove: INPUT_MOVE, - pointerup: INPUT_END, - pointercancel: INPUT_CANCEL, - pointerout: INPUT_CANCEL -}; - -// in IE10 the pointer types is defined as an enum -const IE10_POINTER_TYPE_ENUM = { - 2: INPUT_TYPE_TOUCH, - 3: INPUT_TYPE_PEN, - 4: INPUT_TYPE_MOUSE, - 5: INPUT_TYPE_KINECT // see https://twitter.com/jacobrossi/status/480596438489890816 -}; - -let POINTER_ELEMENT_EVENTS = 'pointerdown'; -let POINTER_WINDOW_EVENTS = 'pointermove pointerup pointercancel'; - -// IE10 has prefixed support, and case-sensitive -if (window.MSPointerEvent && !window.PointerEvent) { - POINTER_ELEMENT_EVENTS = 'MSPointerDown'; - POINTER_WINDOW_EVENTS = 'MSPointerMove MSPointerUp MSPointerCancel'; -} - -/** - * @private - * Pointer events input - * @constructor - * @extends Input - */ -export default class PointerEventInput extends Input { - constructor() { - super(...arguments); - this.evEl = POINTER_ELEMENT_EVENTS; - this.evWin = POINTER_WINDOW_EVENTS; - - this.store = (this.manager.session.pointerEvents = []); - } - - /** - * @private - * handle mouse events - * @param {Object} ev - */ - handler(ev) { - let { store } = this; - let removePointer = false; - - let eventTypeNormalized = ev.type.toLowerCase().replace('ms', ''); - let eventType = POINTER_INPUT_MAP[eventTypeNormalized]; - let pointerType = IE10_POINTER_TYPE_ENUM[ev.pointerType] || ev.pointerType; - - let isTouch = (pointerType === INPUT_TYPE_TOUCH); - - // get index of the event in the store - let storeIndex = inArray(store, ev.pointerId, 'pointerId'); - - // start and mouse must be down - if (eventType & INPUT_START && (ev.button === 0 || isTouch)) { - if (storeIndex < 0) { - store.push(ev); - storeIndex = store.length - 1; - } - } else if (eventType & (INPUT_END | INPUT_CANCEL)) { - removePointer = true; - } - - // it not found, so the pointer hasn't been down (so it's probably a hover) - if (storeIndex < 0) { - return; - } - - // update the event in the store - store[storeIndex] = ev; - - this.callback(this.manager, eventType, { - pointers: store, - changedPointers: [ev], - pointerType, - srcEvent: ev - }); - - if (removePointer) { - // remove from the store - store.splice(storeIndex, 1); - } - } -} diff --git a/src/input/singletouch.js b/src/input/singletouch.js deleted file mode 100644 index bc315985d..000000000 --- a/src/input/singletouch.js +++ /dev/null @@ -1,82 +0,0 @@ -import { - INPUT_START, - INPUT_MOVE, - INPUT_END, - INPUT_CANCEL, - INPUT_TYPE_TOUCH -} from '../inputjs/input-consts'; -import Input from '../inputjs/input-constructor'; -import toArray from '../utils/to-array'; -import uniqueArray from '../utils/unique-array'; - -const SINGLE_TOUCH_INPUT_MAP = { - touchstart: INPUT_START, - touchmove: INPUT_MOVE, - touchend: INPUT_END, - touchcancel: INPUT_CANCEL -}; - -const SINGLE_TOUCH_TARGET_EVENTS = 'touchstart'; -const SINGLE_TOUCH_WINDOW_EVENTS = 'touchstart touchmove touchend touchcancel'; - -/** - * @private - * Touch events input - * @constructor - * @extends Input - */ -export default class SingleTouchInput extends Input { - constructor() { - super(...arguments); - this.evTarget = SINGLE_TOUCH_TARGET_EVENTS; - this.evWin = SINGLE_TOUCH_WINDOW_EVENTS; - this.started = false; - - Input.apply(this, arguments); - } - - handler(ev) { - let type = SINGLE_TOUCH_INPUT_MAP[ev.type]; - - // should we handle the touch events? - if (type === INPUT_START) { - this.started = true; - } - - if (!this.started) { - return; - } - - let touches = normalizeSingleTouches.call(this, ev, type); - - // when done, reset the started state - if (type & (INPUT_END | INPUT_CANCEL) && touches[0].length - touches[1].length === 0) { - this.started = false; - } - - this.callback(this.manager, type, { - pointers: touches[0], - changedPointers: touches[1], - pointerType: INPUT_TYPE_TOUCH, - srcEvent: ev - }); - } -} - -/** - * @private - * @this {TouchInput} - * @param {Object} ev - * @param {Number} type flag - * @returns {undefined|Array} [all, changed] - */ -function normalizeSingleTouches(ev, type) { - let all = toArray(ev.touches); - let changed = toArray(ev.changedTouches); - - if (type & (INPUT_END | INPUT_CANCEL)) { - all = uniqueArray(all.concat(changed), 'identifier', true); - } - - return [all, changed]; -} diff --git a/src/input/touch.js b/src/input/touch.js deleted file mode 100644 index b482a15e1..000000000 --- a/src/input/touch.js +++ /dev/null @@ -1,115 +0,0 @@ -import { - INPUT_START, - INPUT_MOVE, - INPUT_END, - INPUT_CANCEL, - INPUT_TYPE_TOUCH -} from '../inputjs/input-consts'; -import Input from '../inputjs/input-constructor'; -import toArray from '../utils/to-array'; -import hasParent from '../utils/has-parent'; -import uniqueArray from '../utils/unique-array'; - -const TOUCH_INPUT_MAP = { - touchstart: INPUT_START, - touchmove: INPUT_MOVE, - touchend: INPUT_END, - touchcancel: INPUT_CANCEL -}; - -const TOUCH_TARGET_EVENTS = 'touchstart touchmove touchend touchcancel'; - -/** - * @private - * Multi-user touch events input - * @constructor - * @extends Input - */ -export default class TouchInput extends Input { - - constructor() { - TouchInput.prototype.evTarget = TOUCH_TARGET_EVENTS; - TouchInput.prototype.targetIds = {}; - super(...arguments); - - this.evTarget = TOUCH_TARGET_EVENTS; - this.targetIds = {}; - } - - handler(ev) { - let type = TOUCH_INPUT_MAP[ev.type]; - let touches = getTouches.call(this, ev, type); - if (!touches) { - return; - } - - this.callback(this.manager, type, { - pointers: touches[0], - changedPointers: touches[1], - pointerType: INPUT_TYPE_TOUCH, - srcEvent: ev - }); - } -} - -/** - * @private - * @this {TouchInput} - * @param {Object} ev - * @param {Number} type flag - * @returns {undefined|Array} [all, changed] - */ -function getTouches(ev, type) { - let allTouches = toArray(ev.touches); - let { targetIds } = this; - - // when there is only one touch, the process can be simplified - if (type & (INPUT_START | INPUT_MOVE) && allTouches.length === 1) { - targetIds[allTouches[0].identifier] = true; - return [allTouches, allTouches]; - } - - let i; - let targetTouches; - let changedTouches = toArray(ev.changedTouches); - let changedTargetTouches = []; - let { target } = this; - - // get target touches from touches - targetTouches = allTouches.filter((touch) => { - return hasParent(touch.target, target); - }); - - // collect touches - if (type === INPUT_START) { - i = 0; - while (i < targetTouches.length) { - targetIds[targetTouches[i].identifier] = true; - i++; - } - } - - // filter changed touches to only contain touches that exist in the collected target ids - i = 0; - while (i < changedTouches.length) { - if (targetIds[changedTouches[i].identifier]) { - changedTargetTouches.push(changedTouches[i]); - } - - // cleanup removed touches - if (type & (INPUT_END | INPUT_CANCEL)) { - delete targetIds[changedTouches[i].identifier]; - } - i++; - } - - if (!changedTargetTouches.length) { - return; - } - - return [ - // merge targetTouches with changedTargetTouches so it contains ALL touches, including 'end' and 'cancel' - uniqueArray(targetTouches.concat(changedTargetTouches), 'identifier', true), - changedTargetTouches - ]; -} diff --git a/src/input/touchmouse.js b/src/input/touchmouse.js deleted file mode 100644 index f771d4774..000000000 --- a/src/input/touchmouse.js +++ /dev/null @@ -1,111 +0,0 @@ -import Input from '../inputjs/input-constructor'; -import bindFn from '../utils/bind-fn'; -import TouchInput from './touch'; -import MouseInput from './mouse'; -import { - INPUT_START, - INPUT_END, - INPUT_CANCEL, - INPUT_TYPE_TOUCH, - INPUT_TYPE_MOUSE -} from '../inputjs/input-consts'; - -/** - * @private - * Combined touch and mouse input - * - * Touch has a higher priority then mouse, and while touching no mouse events are allowed. - * This because touch devices also emit mouse events while doing a touch. - * - * @constructor - * @extends Input - */ - -const DEDUP_TIMEOUT = 2500; -const DEDUP_DISTANCE = 25; - -export default class TouchMouseInput extends Input { - constructor() { - super(...arguments); - - let handler = bindFn(this.handler, this); - this.touch = new TouchInput(this.manager, handler); - this.mouse = new MouseInput(this.manager, handler); - - this.primaryTouch = null; - this.lastTouches = []; - } - - /** - * @private - * handle mouse and touch events - * @param {Hammer} manager - * @param {String} inputEvent - * @param {Object} inputData - */ - handler(manager, inputEvent, inputData) { - let isTouch = (inputData.pointerType === INPUT_TYPE_TOUCH); - let isMouse = (inputData.pointerType === INPUT_TYPE_MOUSE); - - if (isMouse && inputData.sourceCapabilities && inputData.sourceCapabilities.firesTouchEvents) { - return; - } - - // when we're in a touch event, record touches to de-dupe synthetic mouse event - if (isTouch) { - recordTouches.call(this, inputEvent, inputData); - } else if (isMouse && isSyntheticEvent.call(this, inputData)) { - return; - } - - this.callback(manager, inputEvent, inputData); - } - - /** - * @private - * remove the event listeners - */ - destroy() { - this.touch.destroy(); - this.mouse.destroy(); - } -} - -function recordTouches(eventType, eventData) { - if (eventType & INPUT_START) { - this.primaryTouch = eventData.changedPointers[0].identifier; - setLastTouch.call(this, eventData); - } else if (eventType & (INPUT_END | INPUT_CANCEL)) { - setLastTouch.call(this, eventData); - } -} - -function setLastTouch(eventData) { - let { changedPointers:[touch] } = eventData; - if (touch.identifier === this.primaryTouch) { - let lastTouch = { x: touch.clientX, y: touch.clientY }; - this.lastTouches.push(lastTouch); - let lts = this.lastTouches; - let removeLastTouch = function() { - let i = lts.indexOf(lastTouch); - if (i > -1) { - lts.splice(i, 1); - } - }; - setTimeout(removeLastTouch, DEDUP_TIMEOUT); - } -} - -function isSyntheticEvent(eventData) { - let x = eventData.srcEvent.clientX; - let y = eventData.srcEvent.clientY; - for (let i = 0; i < this.lastTouches.length; i++) { - let t = this.lastTouches[i]; - let dx = Math.abs(x - t.x); - let dy = Math.abs(y - t.y); - if (dx <= DEDUP_DISTANCE && dy <= DEDUP_DISTANCE) { - return true; - } - } - return false; -} diff --git a/src/inputjs/compute-delta-xy.js b/src/inputjs/compute-delta-xy.js deleted file mode 100644 index fefb5bd41..000000000 --- a/src/inputjs/compute-delta-xy.js +++ /dev/null @@ -1,25 +0,0 @@ -import { INPUT_START, INPUT_END } from './input-consts'; - -export default function computeDeltaXY(session, input) { - let { center } = input; - // let { offsetDelta:offset = {}, prevDelta = {}, prevInput = {} } = session; - // jscs throwing error on defalut destructured values and without defaults tests fail - let offset = session.offsetDelta || {}; - let prevDelta = session.prevDelta || {}; - let prevInput = session.prevInput || {}; - - if (input.eventType === INPUT_START || prevInput.eventType === INPUT_END) { - prevDelta = session.prevDelta = { - x: prevInput.deltaX || 0, - y: prevInput.deltaY || 0 - }; - - offset = session.offsetDelta = { - x: center.x, - y: center.y - }; - } - - input.deltaX = prevDelta.x + (center.x - offset.x); - input.deltaY = prevDelta.y + (center.y - offset.y); -} diff --git a/src/inputjs/compute-input-data.js b/src/inputjs/compute-input-data.js deleted file mode 100644 index 73b26940c..000000000 --- a/src/inputjs/compute-input-data.js +++ /dev/null @@ -1,70 +0,0 @@ -import { now } from '../utils/utils-consts'; -import { abs } from '../utils/utils-consts'; -import hasParent from '../utils/has-parent'; -import simpleCloneInputData from './simple-clone-input-data'; -import getCenter from './get-center'; -import getDistance from './get-distance'; -import getAngle from './get-angle'; -import getDirection from './get-direction'; -import computeDeltaXY from './compute-delta-xy'; -import getVelocity from './get-velocity'; -import getScale from './get-scale'; -import getRotation from './get-rotation'; -import computeIntervalInputData from './compute-interval-input-data'; - -/** -* @private - * extend the data with some usable properties like scale, rotate, velocity etc - * @param {Object} manager - * @param {Object} input - */ -export default function computeInputData(manager, input) { - let { session } = manager; - let { pointers } = input; - let { length:pointersLength } = pointers; - - // store the first input to calculate the distance and direction - if (!session.firstInput) { - session.firstInput = simpleCloneInputData(input); - } - - // to compute scale and rotation we need to store the multiple touches - if (pointersLength > 1 && !session.firstMultiple) { - session.firstMultiple = simpleCloneInputData(input); - } else if (pointersLength === 1) { - session.firstMultiple = false; - } - - let { firstInput, firstMultiple } = session; - let offsetCenter = firstMultiple ? firstMultiple.center : firstInput.center; - - let center = input.center = getCenter(pointers); - input.timeStamp = now(); - input.deltaTime = input.timeStamp - firstInput.timeStamp; - - input.angle = getAngle(offsetCenter, center); - input.distance = getDistance(offsetCenter, center); - - computeDeltaXY(session, input); - input.offsetDirection = getDirection(input.deltaX, input.deltaY); - - let overallVelocity = getVelocity(input.deltaTime, input.deltaX, input.deltaY); - input.overallVelocityX = overallVelocity.x; - input.overallVelocityY = overallVelocity.y; - input.overallVelocity = (abs(overallVelocity.x) > abs(overallVelocity.y)) ? overallVelocity.x : overallVelocity.y; - - input.scale = firstMultiple ? getScale(firstMultiple.pointers, pointers) : 1; - input.rotation = firstMultiple ? getRotation(firstMultiple.pointers, pointers) : 0; - - input.maxPointers = !session.prevInput ? input.pointers.length : ((input.pointers.length > - session.prevInput.maxPointers) ? input.pointers.length : session.prevInput.maxPointers); - - computeIntervalInputData(session, input); - - // find the correct target - let target = manager.element; - if (hasParent(input.srcEvent.target, target)) { - target = input.srcEvent.target; - } - input.target = target; -} diff --git a/src/inputjs/compute-interval-input-data.js b/src/inputjs/compute-interval-input-data.js deleted file mode 100644 index eb5746a31..000000000 --- a/src/inputjs/compute-interval-input-data.js +++ /dev/null @@ -1,43 +0,0 @@ -import { INPUT_CANCEL,COMPUTE_INTERVAL } from './input-consts'; -import { abs } from '../utils/utils-consts'; -import getVelocity from './get-velocity'; -import getDirection from './get-direction'; - -/** - * @private - * velocity is calculated every x ms - * @param {Object} session - * @param {Object} input - */ -export default function computeIntervalInputData(session, input) { - let last = session.lastInterval || input; - let deltaTime = input.timeStamp - last.timeStamp; - let velocity; - let velocityX; - let velocityY; - let direction; - - if (input.eventType !== INPUT_CANCEL && (deltaTime > COMPUTE_INTERVAL || last.velocity === undefined)) { - let deltaX = input.deltaX - last.deltaX; - let deltaY = input.deltaY - last.deltaY; - - let v = getVelocity(deltaTime, deltaX, deltaY); - velocityX = v.x; - velocityY = v.y; - velocity = (abs(v.x) > abs(v.y)) ? v.x : v.y; - direction = getDirection(deltaX, deltaY); - - session.lastInterval = input; - } else { - // use latest velocity info if it doesn't overtake a minimum period - velocity = last.velocity; - velocityX = last.velocityX; - velocityY = last.velocityY; - direction = last.direction; - } - - input.velocity = velocity; - input.velocityX = velocityX; - input.velocityY = velocityY; - input.direction = direction; -} diff --git a/src/inputjs/create-input-instance.js b/src/inputjs/create-input-instance.js deleted file mode 100644 index 977dc05a1..000000000 --- a/src/inputjs/create-input-instance.js +++ /dev/null @@ -1,31 +0,0 @@ -import { SUPPORT_POINTER_EVENTS,SUPPORT_ONLY_TOUCH,SUPPORT_TOUCH } from './input-consts'; -import inputHandler from './input-handler'; -import PointerEventInput from '../input/pointerevent'; -import TouchInput from '../input/touch'; -import MouseInput from '../input/mouse'; -import TouchMouseInput from '../input/touchmouse'; - -/** - * @private - * create new input type manager - * called by the Manager constructor - * @param {Hammer} manager - * @returns {Input} - */ -export default function createInputInstance(manager) { - let Type; - // let inputClass = manager.options.inputClass; - let { options:{ inputClass } } = manager; - if (inputClass) { - Type = inputClass; - } else if (SUPPORT_POINTER_EVENTS) { - Type = PointerEventInput; - } else if (SUPPORT_ONLY_TOUCH) { - Type = TouchInput; - } else if (!SUPPORT_TOUCH) { - Type = MouseInput; - } else { - Type = TouchMouseInput; - } - return new (Type)(manager, inputHandler); -} diff --git a/src/inputjs/get-angle.js b/src/inputjs/get-angle.js deleted file mode 100644 index 0015c23aa..000000000 --- a/src/inputjs/get-angle.js +++ /dev/null @@ -1,18 +0,0 @@ -import { PROPS_XY } from './input-consts'; - -/** - * @private - * calculate the angle between two coordinates - * @param {Object} p1 - * @param {Object} p2 - * @param {Array} [props] containing x and y keys - * @return {Number} angle - */ -export default function getAngle(p1, p2, props) { - if (!props) { - props = PROPS_XY; - } - let x = p2[props[0]] - p1[props[0]]; - let y = p2[props[1]] - p1[props[1]]; - return Math.atan2(y, x) * 180 / Math.PI; -} diff --git a/src/inputjs/get-center.js b/src/inputjs/get-center.js deleted file mode 100644 index 225b1ec07..000000000 --- a/src/inputjs/get-center.js +++ /dev/null @@ -1,33 +0,0 @@ -import { round } from '../utils/utils-consts'; - -/** - * @private - * get the center of all the pointers - * @param {Array} pointers - * @return {Object} center contains `x` and `y` properties - */ -export default function getCenter(pointers) { - let pointersLength = pointers.length; - - // no need to loop when only one touch - if (pointersLength === 1) { - return { - x: round(pointers[0].clientX), - y: round(pointers[0].clientY) - }; - } - - let x = 0; - let y = 0; - let i = 0; - while (i < pointersLength) { - x += pointers[i].clientX; - y += pointers[i].clientY; - i++; - } - - return { - x: round(x / pointersLength), - y: round(y / pointersLength) - }; -} diff --git a/src/inputjs/get-direction.js b/src/inputjs/get-direction.js deleted file mode 100644 index cf577a888..000000000 --- a/src/inputjs/get-direction.js +++ /dev/null @@ -1,20 +0,0 @@ -import { abs } from '../utils/utils-consts'; -import { DIRECTION_NONE,DIRECTION_LEFT,DIRECTION_RIGHT,DIRECTION_UP,DIRECTION_DOWN } from './input-consts'; - -/** - * @private - * get the direction between two points - * @param {Number} x - * @param {Number} y - * @return {Number} direction - */ -export default function getDirection(x, y) { - if (x === y) { - return DIRECTION_NONE; - } - - if (abs(x) >= abs(y)) { - return x < 0 ? DIRECTION_LEFT : DIRECTION_RIGHT; - } - return y < 0 ? DIRECTION_UP : DIRECTION_DOWN; -} diff --git a/src/inputjs/get-distance.js b/src/inputjs/get-distance.js deleted file mode 100644 index 066ea89c6..000000000 --- a/src/inputjs/get-distance.js +++ /dev/null @@ -1,19 +0,0 @@ -import { PROPS_XY } from './input-consts'; - -/** - * @private - * calculate the absolute distance between two points - * @param {Object} p1 {x, y} - * @param {Object} p2 {x, y} - * @param {Array} [props] containing x and y keys - * @return {Number} distance - */ -export default function getDistance(p1, p2, props) { - if (!props) { - props = PROPS_XY; - } - let x = p2[props[0]] - p1[props[0]]; - let y = p2[props[1]] - p1[props[1]]; - - return Math.sqrt((x * x) + (y * y)); -} diff --git a/src/inputjs/get-rotation.js b/src/inputjs/get-rotation.js deleted file mode 100644 index d507ae9da..000000000 --- a/src/inputjs/get-rotation.js +++ /dev/null @@ -1,13 +0,0 @@ -import getAngle from './get-angle'; -import { PROPS_CLIENT_XY } from './input-consts'; - -/** - * @private - * calculate the rotation degrees between two pointersets - * @param {Array} start array of pointers - * @param {Array} end array of pointers - * @return {Number} rotation - */ -export default function getRotation(start, end) { - return getAngle(end[1], end[0], PROPS_CLIENT_XY) + getAngle(start[1], start[0], PROPS_CLIENT_XY); -} diff --git a/src/inputjs/get-scale.js b/src/inputjs/get-scale.js deleted file mode 100644 index 840e68388..000000000 --- a/src/inputjs/get-scale.js +++ /dev/null @@ -1,13 +0,0 @@ -import { PROPS_CLIENT_XY } from './input-consts'; -import getDistance from './get-distance'; -/** - * @private - * calculate the scale factor between two pointersets - * no scale is 1, and goes down to 0 when pinched together, and bigger when pinched out - * @param {Array} start array of pointers - * @param {Array} end array of pointers - * @return {Number} scale - */ -export default function getScale(start, end) { - return getDistance(end[0], end[1], PROPS_CLIENT_XY) / getDistance(start[0], start[1], PROPS_CLIENT_XY); -} diff --git a/src/inputjs/get-velocity.js b/src/inputjs/get-velocity.js deleted file mode 100644 index 589a2d222..000000000 --- a/src/inputjs/get-velocity.js +++ /dev/null @@ -1,14 +0,0 @@ -/** - * @private - * calculate the velocity between two points. unit is in px per ms. - * @param {Number} deltaTime - * @param {Number} x - * @param {Number} y - * @return {Object} velocity `x` and `y` - */ -export default function getVelocity(deltaTime, x, y) { - return { - x: x / deltaTime || 0, - y: y / deltaTime || 0 - }; -} diff --git a/src/inputjs/input-constructor.js b/src/inputjs/input-constructor.js deleted file mode 100644 index 1a1caa9b0..000000000 --- a/src/inputjs/input-constructor.js +++ /dev/null @@ -1,59 +0,0 @@ -import boolOrFn from '../utils/bool-or-fn'; -import addEventListeners from '../utils/add-event-listeners'; -import removeEventListeners from '../utils/remove-event-listeners'; -import getWindowForElement from '../utils/get-window-for-element'; - -/** - * @private - * create new input type manager - * @param {Manager} manager - * @param {Function} callback - * @returns {Input} - * @constructor - */ -export default class Input { - constructor(manager, callback) { - let self = this; - this.manager = manager; - this.callback = callback; - this.element = manager.element; - this.target = manager.options.inputTarget; - - // smaller wrapper around the handler, for the scope and the enabled state of the manager, - // so when disabled the input events are completely bypassed. - this.domHandler = function(ev) { - if (boolOrFn(manager.options.enable, [manager])) { - self.handler(ev); - } - }; - - this.init(); - - } - /** - * @private - * should handle the inputEvent data and trigger the callback - * @virtual - */ - handler() { } - - /** - * @private - * bind the events - */ - init() { - this.evEl && addEventListeners(this.element, this.evEl, this.domHandler); - this.evTarget && addEventListeners(this.target, this.evTarget, this.domHandler); - this.evWin && addEventListeners(getWindowForElement(this.element), this.evWin, this.domHandler); - } - - /** - * @private - * unbind the events - */ - destroy() { - this.evEl && removeEventListeners(this.element, this.evEl, this.domHandler); - this.evTarget && removeEventListeners(this.target, this.evTarget, this.domHandler); - this.evWin && removeEventListeners(getWindowForElement(this.element), this.evWin, this.domHandler); - } -} diff --git a/src/inputjs/input-consts.js b/src/inputjs/input-consts.js deleted file mode 100644 index 69c3bfbee..000000000 --- a/src/inputjs/input-consts.js +++ /dev/null @@ -1,58 +0,0 @@ -import prefixed from '../utils/prefixed'; - -const MOBILE_REGEX = /mobile|tablet|ip(ad|hone|od)|android/i; - -const SUPPORT_TOUCH = ('ontouchstart' in window); -const SUPPORT_POINTER_EVENTS = prefixed(window, 'PointerEvent') !== undefined; -const SUPPORT_ONLY_TOUCH = SUPPORT_TOUCH && MOBILE_REGEX.test(navigator.userAgent); - -const INPUT_TYPE_TOUCH = 'touch'; -const INPUT_TYPE_PEN = 'pen'; -const INPUT_TYPE_MOUSE = 'mouse'; -const INPUT_TYPE_KINECT = 'kinect'; - -const COMPUTE_INTERVAL = 25; - -const INPUT_START = 1; -const INPUT_MOVE = 2; -const INPUT_END = 4; -const INPUT_CANCEL = 8; - -const DIRECTION_NONE = 1; -const DIRECTION_LEFT = 2; -const DIRECTION_RIGHT = 4; -const DIRECTION_UP = 8; -const DIRECTION_DOWN = 16; - -const DIRECTION_HORIZONTAL = DIRECTION_LEFT | DIRECTION_RIGHT; -const DIRECTION_VERTICAL = DIRECTION_UP | DIRECTION_DOWN; -const DIRECTION_ALL = DIRECTION_HORIZONTAL | DIRECTION_VERTICAL; - -const PROPS_XY = ['x', 'y']; -const PROPS_CLIENT_XY = ['clientX', 'clientY']; - -export { - MOBILE_REGEX, - SUPPORT_ONLY_TOUCH, - SUPPORT_POINTER_EVENTS, - SUPPORT_TOUCH, - INPUT_TYPE_KINECT, - INPUT_TYPE_MOUSE, - INPUT_TYPE_PEN, - INPUT_TYPE_TOUCH, - COMPUTE_INTERVAL, - INPUT_START, - INPUT_MOVE, - INPUT_END, - INPUT_CANCEL, - DIRECTION_NONE, - DIRECTION_LEFT, - DIRECTION_RIGHT, - DIRECTION_UP, - DIRECTION_DOWN, - DIRECTION_HORIZONTAL, - DIRECTION_VERTICAL, - DIRECTION_ALL, - PROPS_XY, - PROPS_CLIENT_XY -}; diff --git a/src/inputjs/input-handler.js b/src/inputjs/input-handler.js deleted file mode 100644 index 8c75d92c9..000000000 --- a/src/inputjs/input-handler.js +++ /dev/null @@ -1,36 +0,0 @@ -import { INPUT_START,INPUT_END,INPUT_CANCEL } from './input-consts'; -import computeInputData from './compute-input-data'; - -/** - * @private - * handle input events - * @param {Manager} manager - * @param {String} eventType - * @param {Object} input - */ -export default function inputHandler(manager, eventType, input) { - let pointersLen = input.pointers.length; - let changedPointersLen = input.changedPointers.length; - let isFirst = (eventType & INPUT_START && (pointersLen - changedPointersLen === 0)); - let isFinal = (eventType & (INPUT_END | INPUT_CANCEL) && (pointersLen - changedPointersLen === 0)); - - input.isFirst = !!isFirst; - input.isFinal = !!isFinal; - - if (isFirst) { - manager.session = {}; - } - - // source event is the normalized value of the domEvents - // like 'touchstart, mouseup, pointerdown' - input.eventType = eventType; - - // compute scale, rotation etc - computeInputData(manager, input); - - // emit secret event - manager.emit('hammer.input', input); - - manager.recognize(input); - manager.session.prevInput = input; -} diff --git a/src/inputjs/simple-clone-input-data.js b/src/inputjs/simple-clone-input-data.js deleted file mode 100644 index 270c531f3..000000000 --- a/src/inputjs/simple-clone-input-data.js +++ /dev/null @@ -1,30 +0,0 @@ -import { now,round } from '../utils/utils-consts'; -import getCenter from './get-center'; - -/** - * @private - * create a simple clone from the input used for storage of firstInput and firstMultiple - * @param {Object} input - * @returns {Object} clonedInputData - */ -export default function simpleCloneInputData(input) { - // make a simple copy of the pointers because we will get a reference if we don't - // we only need clientXY for the calculations - let pointers = []; - let i = 0; - while (i < input.pointers.length) { - pointers[i] = { - clientX: round(input.pointers[i].clientX), - clientY: round(input.pointers[i].clientY) - }; - i++; - } - - return { - timeStamp: now(), - pointers, - center: getCenter(pointers), - deltaX: input.deltaX, - deltaY: input.deltaY - }; -} diff --git a/src/main.js b/src/main.js deleted file mode 100644 index c2bfb791e..000000000 --- a/src/main.js +++ /dev/null @@ -1,139 +0,0 @@ -import Hammer from './hammer'; -import assign from './utils/assign'; -import { - INPUT_START, - INPUT_MOVE, - INPUT_END, - INPUT_CANCEL -} from './inputjs/input-consts'; -import { - STATE_POSSIBLE, - STATE_BEGAN, - STATE_CHANGED, - STATE_ENDED, - STATE_RECOGNIZED, - STATE_CANCELLED, - STATE_FAILED -} from './recognizerjs/recognizer-consts'; -import { - DIRECTION_NONE, - DIRECTION_LEFT, - DIRECTION_RIGHT, - DIRECTION_UP, - DIRECTION_DOWN, - DIRECTION_HORIZONTAL, - DIRECTION_VERTICAL, - DIRECTION_ALL -} from './inputjs/input-consts'; - -import Manager from './manager'; -import Input from './inputjs/input-constructor'; -import TouchAction from './touchactionjs/touchaction-constructor'; -import TouchInput from './input/touch'; -import MouseInput from './input/mouse'; -import PointerEventInput from './input/pointerevent'; -import SingleTouchInput from './input/singletouch'; -import TouchMouseInput from './input/touchmouse'; - -import Recognizer from './recognizerjs/recognizer-constructor'; -import AttrRecognizer from './recognizers/attribute'; -import TapRecognizer from './recognizers/tap'; -import PanRecognizer from './recognizers/pan'; -import SwipeRecognizer from './recognizers/swipe'; -import PinchRecognizer from './recognizers/pinch'; -import RotateRecognizer from './recognizers/rotate'; -import PressRecognizer from './recognizers/press'; - -import addEventListeners from './utils/add-event-listeners'; -import removeEventListeners from './utils/remove-event-listeners'; -import each from './utils/each'; -import merge from './utils/merge'; -import extend from './utils/extend'; -import inherit from './utils/inherit'; -import bindFn from './utils/bind-fn'; -import prefixed from './utils/prefixed'; -import toArray from'./utils/to-array'; -import uniqueArray from'./utils/unique-array'; -import splitStr from'./utils/split-str'; -import inArray from'./utils/in-array'; -import boolOrFn from'./utils/bool-or-fn'; -import hasParent from'./utils/has-parent'; - -// this prevents errors when Hammer is loaded in the presence of an AMD -// style loader but by script tag, not by the loader. - -assign(Hammer, { - INPUT_START, - INPUT_MOVE, - INPUT_END, - INPUT_CANCEL, - - STATE_POSSIBLE, - STATE_BEGAN, - STATE_CHANGED, - STATE_ENDED, - STATE_RECOGNIZED, - STATE_CANCELLED, - STATE_FAILED, - - DIRECTION_NONE, - DIRECTION_LEFT, - DIRECTION_RIGHT, - DIRECTION_UP, - DIRECTION_DOWN, - DIRECTION_HORIZONTAL, - DIRECTION_VERTICAL, - DIRECTION_ALL, - - Manager, - Input, - TouchAction, - - TouchInput, - MouseInput, - PointerEventInput, - TouchMouseInput, - SingleTouchInput, - - Recognizer, - AttrRecognizer, - Tap: TapRecognizer, - Pan: PanRecognizer, - Swipe: SwipeRecognizer, - Pinch: PinchRecognizer, - Rotate: RotateRecognizer, - Press: PressRecognizer, - - on: addEventListeners, - off: removeEventListeners, - each, - merge, - extend, - assign, - inherit, - bindFn, - prefixed, - toArray, - inArray, - uniqueArray, - splitStr, - boolOrFn, - hasParent, - addEventListeners, - removeEventListeners -}); - -let freeGlobal = (typeof window !== 'undefined' ? window : (typeof self !== 'undefined' ? self : {})); // jshint ignore:line -freeGlobal.Hammer = Hammer; - -/* jshint ignore:start */ -if (typeof define === 'function' && define.amd) { - define(() => { - return Hammer; - }); -} else if (typeof module !== 'undefined' && module.exports) { - module.exports = Hammer; -} else { - window[exportName] = Hammer; -} -/* jshint ignore:end */ diff --git a/src/manager.js b/src/manager.js deleted file mode 100644 index 278449f15..000000000 --- a/src/manager.js +++ /dev/null @@ -1,339 +0,0 @@ -import assign from './utils/assign'; -import Hammer from './hammer'; -import TouchAction from './touchactionjs/touchaction-constructor'; -import createInputInstance from './inputjs/create-input-instance'; -import each from './utils/each'; -import inArray from './utils/in-array'; -import invokeArrayArg from './utils/invoke-array-arg'; -import splitStr from './utils/split-str'; -import prefixed from './utils/prefixed'; -import Recognizer from './recognizerjs/recognizer-constructor'; -import { - STATE_BEGAN, - STATE_ENDED, - STATE_CHANGED, - STATE_RECOGNIZED -} from './recognizerjs/recognizer-consts'; - -const STOP = 1; -const FORCED_STOP = 2; - -/** -* @private - * Manager - * @param {HTMLElement} element - * @param {Object} [options] - * @constructor - */ -export default class Manager { - constructor(element, options) { - this.options = assign({}, Hammer.defaults, options || {}); - - this.options.inputTarget = this.options.inputTarget || element; - - this.handlers = {}; - this.session = {}; - this.recognizers = []; - this.oldCssProps = {}; - - this.element = element; - this.input = createInputInstance(this); - this.touchAction = new TouchAction(this, this.options.touchAction); - - toggleCssProps(this, true); - - each(this.options.recognizers, (item) => { - let recognizer = this.add(new (item[0])(item[1])); - item[2] && recognizer.recognizeWith(item[2]); - item[3] && recognizer.requireFailure(item[3]); - }, this); - } - - /** - * @private - * set options - * @param {Object} options - * @returns {Manager} - */ - set(options) { - assign(this.options, options); - - // Options that need a little more setup - if (options.touchAction) { - this.touchAction.update(); - } - if (options.inputTarget) { - // Clean up existing event listeners and reinitialize - this.input.destroy(); - this.input.target = options.inputTarget; - this.input.init(); - } - return this; - } - - /** - * @private - * stop recognizing for this session. - * This session will be discarded, when a new [input]start event is fired. - * When forced, the recognizer cycle is stopped immediately. - * @param {Boolean} [force] - */ - stop(force) { - this.session.stopped = force ? FORCED_STOP : STOP; - } - - /** - * @private - * run the recognizers! - * called by the inputHandler function on every movement of the pointers (touches) - * it walks through all the recognizers and tries to detect the gesture that is being made - * @param {Object} inputData - */ - recognize(inputData) { - let { session } = this; - if (session.stopped) { - return; - } - - // run the touch-action polyfill - this.touchAction.preventDefaults(inputData); - - let recognizer; - let { recognizers } = this; - - // this holds the recognizer that is being recognized. - // so the recognizer's state needs to be BEGAN, CHANGED, ENDED or RECOGNIZED - // if no recognizer is detecting a thing, it is set to `null` - let { curRecognizer } = session; - - // reset when the last recognizer is recognized - // or when we're in a new session - if (!curRecognizer || (curRecognizer && curRecognizer.state & STATE_RECOGNIZED)) { - curRecognizer = session.curRecognizer = null; - } - - let i = 0; - while (i < recognizers.length) { - recognizer = recognizers[i]; - - // find out if we are allowed try to recognize the input for this one. - // 1. allow if the session is NOT forced stopped (see the .stop() method) - // 2. allow if we still haven't recognized a gesture in this session, or the this recognizer is the one - // that is being recognized. - // 3. allow if the recognizer is allowed to run simultaneous with the current recognized recognizer. - // this can be setup with the `recognizeWith()` method on the recognizer. - if (session.stopped !== FORCED_STOP && (// 1 - !curRecognizer || recognizer === curRecognizer || // 2 - recognizer.canRecognizeWith(curRecognizer))) { // 3 - recognizer.recognize(inputData); - } else { - recognizer.reset(); - } - - // if the recognizer has been recognizing the input as a valid gesture, we want to store this one as the - // current active recognizer. but only if we don't already have an active recognizer - if (!curRecognizer && recognizer.state & (STATE_BEGAN | STATE_CHANGED | STATE_ENDED)) { - curRecognizer = session.curRecognizer = recognizer; - } - i++; - } - } - - /** - * @private - * get a recognizer by its event name. - * @param {Recognizer|String} recognizer - * @returns {Recognizer|Null} - */ - get(recognizer) { - if (recognizer instanceof Recognizer) { - return recognizer; - } - - let { recognizers } = this; - for (let i = 0; i < recognizers.length; i++) { - if (recognizers[i].options.event === recognizer) { - return recognizers[i]; - } - } - return null; - } - - /** - * @private add a recognizer to the manager - * existing recognizers with the same event name will be removed - * @param {Recognizer} recognizer - * @returns {Recognizer|Manager} - */ - add(recognizer) { - if (invokeArrayArg(recognizer, 'add', this)) { - return this; - } - - // remove existing - let existing = this.get(recognizer.options.event); - if (existing) { - this.remove(existing); - } - - this.recognizers.push(recognizer); - recognizer.manager = this; - - this.touchAction.update(); - return recognizer; - } - - /** - * @private - * remove a recognizer by name or instance - * @param {Recognizer|String} recognizer - * @returns {Manager} - */ - remove(recognizer) { - if (invokeArrayArg(recognizer, 'remove', this)) { - return this; - } - - recognizer = this.get(recognizer); - - // let's make sure this recognizer exists - if (recognizer) { - let { recognizers } = this; - let index = inArray(recognizers, recognizer); - - if (index !== -1) { - recognizers.splice(index, 1); - this.touchAction.update(); - } - } - - return this; - } - - /** - * @private - * bind event - * @param {String} events - * @param {Function} handler - * @returns {EventEmitter} this - */ - on(events, handler) { - if (events === undefined) { - return; - } - if (handler === undefined) { - return; - } - - let { handlers } = this; - each(splitStr(events), (event) => { - handlers[event] = handlers[event] || []; - handlers[event].push(handler); - }); - return this; - } - - /** - * @private unbind event, leave emit blank to remove all handlers - * @param {String} events - * @param {Function} [handler] - * @returns {EventEmitter} this - */ - off(events, handler) { - if (events === undefined) { - return; - } - - let { handlers } = this; - each(splitStr(events), (event) => { - if (!handler) { - delete handlers[event]; - } else { - handlers[event] && handlers[event].splice(inArray(handlers[event], handler), 1); - } - }); - return this; - } - - /** - * @private emit event to the listeners - * @param {String} event - * @param {Object} data - */ - emit(event, data) { - // we also want to trigger dom events - if (this.options.domEvents) { - triggerDomEvent(event, data); - } - - // no handlers, so skip it all - let handlers = this.handlers[event] && this.handlers[event].slice(); - if (!handlers || !handlers.length) { - return; - } - - data.type = event; - data.preventDefault = function() { - data.srcEvent.preventDefault(); - }; - - let i = 0; - while (i < handlers.length) { - handlers[i](data); - i++; - } - } - - /** - * @private - * destroy the manager and unbinds all events - * it doesn't unbind dom events, that is the user own responsibility - */ - destroy() { - this.element && toggleCssProps(this, false); - - this.handlers = {}; - this.session = {}; - this.input.destroy(); - this.element = null; - } -} - -/** - * @private - * add/remove the css properties as defined in manager.options.cssProps - * @param {Manager} manager - * @param {Boolean} add - */ -function toggleCssProps(manager, add) { - let { element } = manager; - if (!element.style) { - return; - } - let prop; - each(manager.options.cssProps, (value, name) => { - prop = prefixed(element.style, name); - if (add) { - manager.oldCssProps[prop] = element.style[prop]; - element.style[prop] = value; - } else { - element.style[prop] = manager.oldCssProps[prop] || ''; - } - }); - if (!add) { - manager.oldCssProps = {}; - } -} - -/** - * @private - * trigger dom event - * @param {String} event - * @param {Object} data - */ -function triggerDomEvent(event, data) { - let gestureEvent = document.createEvent('Event'); - gestureEvent.initEvent(event, true, true); - gestureEvent.gesture = data; - data.target.dispatchEvent(gestureEvent); -} diff --git a/src/recognizerjs/direction-str.js b/src/recognizerjs/direction-str.js deleted file mode 100644 index 1dfd21806..000000000 --- a/src/recognizerjs/direction-str.js +++ /dev/null @@ -1,25 +0,0 @@ -import { - DIRECTION_LEFT, - DIRECTION_RIGHT, - DIRECTION_UP, - DIRECTION_DOWN -} from '../inputjs/input-consts'; - -/** - * @private - * direction cons to string - * @param {constant} direction - * @returns {String} - */ -export default function directionStr(direction) { - if (direction === DIRECTION_DOWN) { - return 'down'; - } else if (direction === DIRECTION_UP) { - return 'up'; - } else if (direction === DIRECTION_LEFT) { - return 'left'; - } else if (direction === DIRECTION_RIGHT) { - return 'right'; - } - return ''; -} diff --git a/src/recognizerjs/get-recognizer-by-name-if-manager.js b/src/recognizerjs/get-recognizer-by-name-if-manager.js deleted file mode 100644 index 395236c39..000000000 --- a/src/recognizerjs/get-recognizer-by-name-if-manager.js +++ /dev/null @@ -1,14 +0,0 @@ -/** - * @private - * get a recognizer by name if it is bound to a manager - * @param {Recognizer|String} otherRecognizer - * @param {Recognizer} recognizer - * @returns {Recognizer} - */ -export default function getRecognizerByNameIfManager(otherRecognizer, recognizer) { - let { manager } = recognizer; - if (manager) { - return manager.get(otherRecognizer); - } - return otherRecognizer; -} diff --git a/src/recognizerjs/recognizer-constructor.js b/src/recognizerjs/recognizer-constructor.js deleted file mode 100644 index 8939596a0..000000000 --- a/src/recognizerjs/recognizer-constructor.js +++ /dev/null @@ -1,309 +0,0 @@ -import { - STATE_POSSIBLE, - STATE_ENDED, - STATE_FAILED, - STATE_RECOGNIZED, - STATE_CANCELLED, - STATE_BEGAN, - STATE_CHANGED -} from './recognizer-consts'; -import assign from '../utils/assign'; -import uniqueId from '../utils/unique-id'; -import ifUndefined from '../utils/if-undefined'; -import invokeArrayArg from '../utils/invoke-array-arg'; -import inArray from '../utils/in-array'; -import boolOrFn from '../utils/bool-or-fn'; -import getRecognizerByNameIfManager from './get-recognizer-by-name-if-manager'; -import stateStr from './state-str'; - -/** - * @private - * Recognizer flow explained; * - * All recognizers have the initial state of POSSIBLE when a input session starts. - * The definition of a input session is from the first input until the last input, with all it's movement in it. * - * Example session for mouse-input: mousedown -> mousemove -> mouseup - * - * On each recognizing cycle (see Manager.recognize) the .recognize() method is executed - * which determines with state it should be. - * - * If the recognizer has the state FAILED, CANCELLED or RECOGNIZED (equals ENDED), it is reset to - * POSSIBLE to give it another change on the next cycle. - * - * Possible - * | - * +-----+---------------+ - * | | - * +-----+-----+ | - * | | | - * Failed Cancelled | - * +-------+------+ - * | | - * Recognized Began - * | - * Changed - * | - * Ended/Recognized - */ - -/** - * @private - * Recognizer - * Every recognizer needs to extend from this class. - * @constructor - * @param {Object} options - */ -export default class Recognizer { - constructor(options) { - this.options = assign({}, this.defaults, options || {}); - - this.id = uniqueId(); - - this.manager = null; - - // default is enable true - this.options.enable = ifUndefined(this.options.enable, true); - - this.state = STATE_POSSIBLE; - - this.simultaneous = {}; - this.requireFail = []; - } - /** - * @private - * @virtual - * @type {Object} - */ - get defaults() { - return {}; - } - - /** - * @private - * set options - * @param {Object} options - * @return {Recognizer} - */ - set(options) { - assign(this.options, options); - - // also update the touchAction, in case something changed about the directions/enabled state - this.manager && this.manager.touchAction.update(); - return this; - } - - /** - * @private - * recognize simultaneous with an other recognizer. - * @param {Recognizer} otherRecognizer - * @returns {Recognizer} this - */ - recognizeWith(otherRecognizer) { - if (invokeArrayArg(otherRecognizer, 'recognizeWith', this)) { - return this; - } - - let { simultaneous } = this; - otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this); - if (!simultaneous[otherRecognizer.id]) { - simultaneous[otherRecognizer.id] = otherRecognizer; - otherRecognizer.recognizeWith(this); - } - return this; - } - - /** - * @private - * drop the simultaneous link. it doesnt remove the link on the other recognizer. - * @param {Recognizer} otherRecognizer - * @returns {Recognizer} this - */ - dropRecognizeWith(otherRecognizer) { - if (invokeArrayArg(otherRecognizer, 'dropRecognizeWith', this)) { - return this; - } - - otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this); - delete this.simultaneous[otherRecognizer.id]; - return this; - } - - /** - * @private - * recognizer can only run when an other is failing - * @param {Recognizer} otherRecognizer - * @returns {Recognizer} this - */ - requireFailure(otherRecognizer) { - if (invokeArrayArg(otherRecognizer, 'requireFailure', this)) { - return this; - } - - let { requireFail } = this; - otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this); - if (inArray(requireFail, otherRecognizer) === -1) { - requireFail.push(otherRecognizer); - otherRecognizer.requireFailure(this); - } - return this; - } - - /** - * @private - * drop the requireFailure link. it does not remove the link on the other recognizer. - * @param {Recognizer} otherRecognizer - * @returns {Recognizer} this - */ - dropRequireFailure(otherRecognizer) { - if (invokeArrayArg(otherRecognizer, 'dropRequireFailure', this)) { - return this; - } - - otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this); - let index = inArray(this.requireFail, otherRecognizer); - if (index > -1) { - this.requireFail.splice(index, 1); - } - return this; - } - - /** - * @private - * has require failures boolean - * @returns {boolean} - */ - hasRequireFailures() { - return this.requireFail.length > 0; - } - - /** - * @private - * if the recognizer can recognize simultaneous with an other recognizer - * @param {Recognizer} otherRecognizer - * @returns {Boolean} - */ - canRecognizeWith(otherRecognizer) { - return !!this.simultaneous[otherRecognizer.id]; - } - - /** - * @private - * You should use `tryEmit` instead of `emit` directly to check - * that all the needed recognizers has failed before emitting. - * @param {Object} input - */ - emit(input) { - let self = this; - let { state } = this; - - function emit(event) { - self.manager.emit(event, input); - } - - // 'panstart' and 'panmove' - if (state < STATE_ENDED) { - emit(self.options.event + stateStr(state)); - } - - emit(self.options.event); // simple 'eventName' events - - if (input.additionalEvent) { // additional event(panleft, panright, pinchin, pinchout...) - emit(input.additionalEvent); - } - - // panend and pancancel - if (state >= STATE_ENDED) { - emit(self.options.event + stateStr(state)); - } - } - - /** - * @private - * Check that all the require failure recognizers has failed, - * if true, it emits a gesture event, - * otherwise, setup the state to FAILED. - * @param {Object} input - */ - tryEmit(input) { - if (this.canEmit()) { - return this.emit(input); - } - // it's failing anyway - this.state = STATE_FAILED; - } - - /** - * @private - * can we emit? - * @returns {boolean} - */ - canEmit() { - let i = 0; - while (i < this.requireFail.length) { - if (!(this.requireFail[i].state & (STATE_FAILED | STATE_POSSIBLE))) { - return false; - } - i++; - } - return true; - } - - /** - * @private - * update the recognizer - * @param {Object} inputData - */ - recognize(inputData) { - // make a new copy of the inputData - // so we can change the inputData without messing up the other recognizers - let inputDataClone = assign({}, inputData); - - // is is enabled and allow recognizing? - if (!boolOrFn(this.options.enable, [this, inputDataClone])) { - this.reset(); - this.state = STATE_FAILED; - return; - } - - // reset when we've reached the end - if (this.state & (STATE_RECOGNIZED | STATE_CANCELLED | STATE_FAILED)) { - this.state = STATE_POSSIBLE; - } - - this.state = this.process(inputDataClone); - - // the recognizer has recognized a gesture - // so trigger an event - if (this.state & (STATE_BEGAN | STATE_CHANGED | STATE_ENDED | STATE_CANCELLED)) { - this.tryEmit(inputDataClone); - } - } - - /** - * @private - * return the state of the recognizer - * the actual recognizing happens in this method - * @virtual - * @param {Object} inputData - * @returns {constant} STATE - */ - - /* jshint ignore:start */ - process(inputData) { } - /* jshint ignore:end */ - - /** - * @private - * return the preferred touch-action - * @virtual - * @returns {Array} - */ - getTouchAction() { } - - /** - * @private - * called when the gesture isn't allowed to recognize - * like when another is being recognized or it is disabled - * @virtual - */ - reset() { } -} diff --git a/src/recognizerjs/recognizer-consts.js b/src/recognizerjs/recognizer-consts.js deleted file mode 100644 index 7b1aa340c..000000000 --- a/src/recognizerjs/recognizer-consts.js +++ /dev/null @@ -1,17 +0,0 @@ -const STATE_POSSIBLE = 1; -const STATE_BEGAN = 2; -const STATE_CHANGED = 4; -const STATE_ENDED = 8; -const STATE_RECOGNIZED = STATE_ENDED; -const STATE_CANCELLED = 16; -const STATE_FAILED = 32; - -export { - STATE_POSSIBLE, - STATE_BEGAN, - STATE_CHANGED, - STATE_ENDED, - STATE_RECOGNIZED, - STATE_CANCELLED, - STATE_FAILED -}; diff --git a/src/recognizerjs/state-str.js b/src/recognizerjs/state-str.js deleted file mode 100644 index e37c58497..000000000 --- a/src/recognizerjs/state-str.js +++ /dev/null @@ -1,25 +0,0 @@ -import { - STATE_CANCELLED, - STATE_ENDED, - STATE_CHANGED, - STATE_BEGAN -} from './recognizer-consts'; - -/** - * @private - * get a usable string, used as event postfix - * @param {constant} state - * @returns {String} state - */ -export default function stateStr(state) { - if (state & STATE_CANCELLED) { - return 'cancel'; - } else if (state & STATE_ENDED) { - return 'end'; - } else if (state & STATE_CHANGED) { - return 'move'; - } else if (state & STATE_BEGAN) { - return 'start'; - } - return ''; -} diff --git a/src/recognizers/attribute.js b/src/recognizers/attribute.js deleted file mode 100644 index b2474a681..000000000 --- a/src/recognizers/attribute.js +++ /dev/null @@ -1,80 +0,0 @@ -import Recognizer from '../recognizerjs/recognizer-constructor'; -import { - STATE_BEGAN, - STATE_CHANGED, - STATE_CANCELLED, - STATE_ENDED, - STATE_FAILED -} from '../recognizerjs/recognizer-consts'; -import { - INPUT_CANCEL, - INPUT_END -} from '../inputjs/input-consts'; - -/** - * @private - * This recognizer is just used as a base for the simple attribute recognizers. - * @constructor - * @extends Recognizer - */ -export default class AttrRecognizer extends Recognizer { - constructor() { - super(...arguments); - } - - /** - * @private - * @namespace - * @memberof AttrRecognizer - */ - get defaults() { - return { - /** - * @private - * @type {Number} - * @default 1 - */ - pointers: 1 - }; - } - - /** - * @private - * Used to check if it the recognizer receives valid input, like input.distance > 10. - * @memberof AttrRecognizer - * @param {Object} input - * @returns {Boolean} recognized - */ - attrTest(input) { - let optionPointers = this.options.pointers; - return optionPointers === 0 || input.pointers.length === optionPointers; - } - - /** - * @private - * Process the input and return the state for the recognizer - * @memberof AttrRecognizer - * @param {Object} input - * @returns {*} State - */ - process(input) { - let { state } = this; - let { eventType } = input; - - let isRecognized = state & (STATE_BEGAN | STATE_CHANGED); - let isValid = this.attrTest(input); - - // on cancel input and we've recognized before, return STATE_CANCELLED - if (isRecognized && (eventType & INPUT_CANCEL || !isValid)) { - return state | STATE_CANCELLED; - } else if (isRecognized || isValid) { - if (eventType & INPUT_END) { - return state | STATE_ENDED; - } else if (!(state & STATE_BEGAN)) { - return STATE_BEGAN; - } - return state | STATE_CHANGED; - } - return STATE_FAILED; - } -} diff --git a/src/recognizers/pan.js b/src/recognizers/pan.js deleted file mode 100644 index 228c6b1c9..000000000 --- a/src/recognizers/pan.js +++ /dev/null @@ -1,98 +0,0 @@ -import AttrRecognizer from './attribute'; -import { - DIRECTION_ALL, - DIRECTION_HORIZONTAL, - DIRECTION_VERTICAL, - DIRECTION_NONE, - DIRECTION_UP, - DIRECTION_DOWN, - DIRECTION_LEFT, - DIRECTION_RIGHT -} from '../inputjs/input-consts'; -import { STATE_BEGAN } from '../recognizerjs/recognizer-consts'; -import { TOUCH_ACTION_PAN_X,TOUCH_ACTION_PAN_Y } from '../touchactionjs/touchaction-Consts'; -import directionStr from '../recognizerjs/direction-str'; - -/** - * @private - * Pan - * Recognized when the pointer is down and moved in the allowed direction. - * @constructor - * @extends AttrRecognizer - */ -export default class PanRecognizer extends AttrRecognizer { - constructor() { - super(...arguments); - - this.pX = null; - this.pY = null; - } - - /** - * @private - * @namespace - * @memberof PanRecognizer - */ - get defaults() { - return { - event: 'pan', - threshold: 10, - pointers: 1, - direction: DIRECTION_ALL - }; - } - - getTouchAction() { - let { options:{ direction } } = this; - let actions = []; - if (direction & DIRECTION_HORIZONTAL) { - actions.push(TOUCH_ACTION_PAN_Y); - } - if (direction & DIRECTION_VERTICAL) { - actions.push(TOUCH_ACTION_PAN_X); - } - return actions; - } - - directionTest(input) { - let { options } = this; - let hasMoved = true; - let { distance } = input; - let { direction } = input; - let x = input.deltaX; - let y = input.deltaY; - - // lock to axis? - if (!(direction & options.direction)) { - if (options.direction & DIRECTION_HORIZONTAL) { - direction = (x === 0) ? DIRECTION_NONE : (x < 0) ? DIRECTION_LEFT : DIRECTION_RIGHT; - hasMoved = x !== this.pX; - distance = Math.abs(input.deltaX); - } else { - direction = (y === 0) ? DIRECTION_NONE : (y < 0) ? DIRECTION_UP : DIRECTION_DOWN; - hasMoved = y !== this.pY; - distance = Math.abs(input.deltaY); - } - } - input.direction = direction; - return hasMoved && distance > options.threshold && direction & options.direction; - } - - attrTest(input) { - return AttrRecognizer.prototype.attrTest.call(this, input) && // replace with a super call - (this.state & STATE_BEGAN || (!(this.state & STATE_BEGAN) && this.directionTest(input))); - } - - emit(input) { - - this.pX = input.deltaX; - this.pY = input.deltaY; - - let direction = directionStr(input.direction); - - if (direction) { - input.additionalEvent = this.options.event + direction; - } - super.emit(input); - } -} diff --git a/src/recognizers/pinch.js b/src/recognizers/pinch.js deleted file mode 100644 index a409a92be..000000000 --- a/src/recognizers/pinch.js +++ /dev/null @@ -1,46 +0,0 @@ -import AttrRecognizer from './attribute'; -import { TOUCH_ACTION_NONE } from '../touchactionjs/touchaction-Consts'; -import { STATE_BEGAN } from '../recognizerjs/recognizer-consts'; - -/** - * @private - * Pinch - * Recognized when two or more pointers are moving toward (zoom-in) or away from each other (zoom-out). - * @constructor - * @extends AttrRecognizer - */ -export default class PinchRecognizer extends AttrRecognizer { - constructor() { - super(...arguments); - } - - /** - * @private - * @namespace - * @memberof PinchRecognizer - */ - get defaults() { - return { - event: 'pinch', - threshold: 0, - pointers: 2 - }; - } - - getTouchAction() { - return [TOUCH_ACTION_NONE]; - } - - attrTest(input) { - return super.attrTest(input) && - (Math.abs(input.scale - 1) > this.options.threshold || this.state & STATE_BEGAN); - } - - emit(input) { - if (input.scale !== 1) { - let inOut = input.scale < 1 ? 'in' : 'out'; - input.additionalEvent = this.options.event + inOut; - } - super.emit(input); - } -} diff --git a/src/recognizers/press.js b/src/recognizers/press.js deleted file mode 100644 index a51123ce9..000000000 --- a/src/recognizers/press.js +++ /dev/null @@ -1,88 +0,0 @@ -import Recognizer from '../recognizerjs/recognizer-constructor'; -import { - STATE_RECOGNIZED, - STATE_FAILED -} from '../recognizerjs/recognizer-consts'; -import { now } from '../utils/utils-consts'; -import setTimeoutContext from '../utils/set-timeout-context'; -import { TOUCH_ACTION_AUTO } from '../touchactionjs/touchaction-Consts'; -import { - INPUT_START, - INPUT_END, - INPUT_CANCEL -} from '../inputjs/input-consts'; - -/** - * @private - * Press - * Recognized when the pointer is down for x ms without any movement. - * @constructor - * @extends Recognizer - */ -export default class PressRecognizer extends Recognizer { - constructor() { - super(...arguments); - - this._timer = null; - this._input = null; - } - - /** - * @private - * @namespace - * @memberof PressRecognizer - */ - get defaults() { - return { - event: 'press', - pointers: 1, - time: 251, // minimal time of the pointer to be pressed - threshold: 9 // a minimal movement is ok, but keep it low - }; - } - - getTouchAction() { - return [TOUCH_ACTION_AUTO]; - } - - process(input) { - let { options } = this; - let validPointers = input.pointers.length === options.pointers; - let validMovement = input.distance < options.threshold; - let validTime = input.deltaTime > options.time; - - this._input = input; - - // we only allow little movement - // and we've reached an end event, so a tap is possible - if (!validMovement || !validPointers || (input.eventType & (INPUT_END | INPUT_CANCEL) && !validTime)) { - this.reset(); - } else if (input.eventType & INPUT_START) { - this.reset(); - this._timer = setTimeoutContext(() => { - this.state = STATE_RECOGNIZED; - this.tryEmit(); - }, options.time, this); - } else if (input.eventType & INPUT_END) { - return STATE_RECOGNIZED; - } - return STATE_FAILED; - } - - reset() { - clearTimeout(this._timer); - } - - emit(input) { - if (this.state !== STATE_RECOGNIZED) { - return; - } - - if (input && (input.eventType & INPUT_END)) { - this.manager.emit(`${this.options.event}up`, input); - } else { - this._input.timeStamp = now(); - this.manager.emit(this.options.event, this._input); - } - } -} diff --git a/src/recognizers/rotate.js b/src/recognizers/rotate.js deleted file mode 100644 index 96b51d1fd..000000000 --- a/src/recognizers/rotate.js +++ /dev/null @@ -1,38 +0,0 @@ -import AttrRecognizer from './attribute'; -import { TOUCH_ACTION_NONE } from '../touchactionjs/touchaction-Consts'; -import { STATE_BEGAN } from '../recognizerjs/recognizer-consts'; - -/** - * @private - * Rotate - * Recognized when two or more pointer are moving in a circular motion. - * @constructor - * @extends AttrRecognizer - */ -export default class RotateRecognizer extends AttrRecognizer { - constructor() { - super(...arguments); - } - - /** - * @private - * @namespace - * @memberof RotateRecognizer - */ - get defaults() { - return { - event: 'rotate', - threshold: 0, - pointers: 2 - }; - } - - getTouchAction() { - return [TOUCH_ACTION_NONE]; - } - - attrTest(input) { - return super.attrTest(input) && - (Math.abs(input.rotation) > this.options.threshold || this.state & STATE_BEGAN); - } -} diff --git a/src/recognizers/swipe.js b/src/recognizers/swipe.js deleted file mode 100644 index 1c81036e0..000000000 --- a/src/recognizers/swipe.js +++ /dev/null @@ -1,66 +0,0 @@ -import AttrRecognizer from '../recognizers/attribute'; -import { abs } from '../utils/utils-consts'; -import { DIRECTION_HORIZONTAL,DIRECTION_VERTICAL } from '../inputjs/input-consts'; -import PanRecognizer from './pan'; -import { INPUT_END } from '../inputjs/input-consts'; -import directionStr from '../recognizerjs/direction-str'; - -/** - * @private - * Swipe - * Recognized when the pointer is moving fast (velocity), with enough distance in the allowed direction. - * @constructor - * @extends AttrRecognizer - */ -export default class SwipeRecognizer extends AttrRecognizer{ - constructor() { - super(...arguments); - } - - /** - * @private - * @namespace - * @memberof SwipeRecognizer - */ - get defaults() { - return { - event: 'swipe', - threshold: 10, - velocity: 0.3, - direction: DIRECTION_HORIZONTAL | DIRECTION_VERTICAL, - pointers: 1 - }; - } - - getTouchAction() { - return PanRecognizer.prototype.getTouchAction.call(this); - } - - attrTest(input) { - let { direction } = this.options; - let velocity; - - if (direction & (DIRECTION_HORIZONTAL | DIRECTION_VERTICAL)) { - velocity = input.overallVelocity; - } else if (direction & DIRECTION_HORIZONTAL) { - velocity = input.overallVelocityX; - } else if (direction & DIRECTION_VERTICAL) { - velocity = input.overallVelocityY; - } - - return super.attrTest(input) && - direction & input.offsetDirection && - input.distance > this.options.threshold && - input.maxPointers === this.options.pointers && - abs(velocity) > this.options.velocity && input.eventType & INPUT_END; - } - - emit(input) { - let direction = directionStr(input.offsetDirection); - if (direction) { - this.manager.emit(this.options.event + direction, input); - } - - this.manager.emit(this.options.event, input); - } -} diff --git a/src/recognizers/tap.js b/src/recognizers/tap.js deleted file mode 100644 index e838d8d4b..000000000 --- a/src/recognizers/tap.js +++ /dev/null @@ -1,128 +0,0 @@ -import setTimeoutContext from '../utils/set-timeout-context'; -import Recognizer from '../recognizerjs/recognizer-constructor'; -import { TOUCH_ACTION_MANIPULATION } from '../touchactionjs/touchaction-Consts'; -import {INPUT_START,INPUT_END } from '../inputjs/input-consts'; -import { - STATE_RECOGNIZED, - STATE_BEGAN, - STATE_FAILED -} from '../recognizerjs/recognizer-consts'; -import getDistance from '../inputjs/get-distance'; - -/** - * @private - * A tap is recognized when the pointer is doing a small tap/click. Multiple taps are recognized if they occur - * between the given interval and position. The delay option can be used to recognize multi-taps without firing - * a single tap. - * - * The eventData from the emitted event contains the property `tapCount`, which contains the amount of - * multi-taps being recognized. - * @constructor - * @extends Recognizer - */ -export default class TapRecognizer extends Recognizer { - constructor() { - super(...arguments); - // previous time and center, - // used for tap counting - this.pTime = false; - this.pCenter = false; - - this._timer = null; - this._input = null; - this.count = 0; - } - - /** - * @private - * @namespace - * @memberof PinchRecognizer - */ - get defaults() { - return { - event: 'tap', - pointers: 1, - taps: 1, - interval: 300, // max time between the multi-tap taps - time: 250, // max time of the pointer to be down (like finger on the screen) - threshold: 9, // a minimal movement is ok, but keep it low - posThreshold: 10 // a multi-tap can be a bit off the initial position - }; - } - - getTouchAction() { - return [TOUCH_ACTION_MANIPULATION]; - } - - process(input) { - let { options } = this; - - let validPointers = input.pointers.length === options.pointers; - let validMovement = input.distance < options.threshold; - let validTouchTime = input.deltaTime < options.time; - - this.reset(); - - if ((input.eventType & INPUT_START) && (this.count === 0)) { - return this.failTimeout(); - } - - // we only allow little movement - // and we've reached an end event, so a tap is possible - if (validMovement && validTouchTime && validPointers) { - if (input.eventType !== INPUT_END) { - return this.failTimeout(); - } - - let validInterval = this.pTime ? (input.timeStamp - this.pTime < options.interval) : true; - let validMultiTap = !this.pCenter || getDistance(this.pCenter, input.center) < options.posThreshold; - - this.pTime = input.timeStamp; - this.pCenter = input.center; - - if (!validMultiTap || !validInterval) { - this.count = 1; - } else { - this.count += 1; - } - - this._input = input; - - // if tap count matches we have recognized it, - // else it has began recognizing... - let tapCount = this.count % options.taps; - if (tapCount === 0) { - // no failing requirements, immediately trigger the tap event - // or wait as long as the multitap interval to trigger - if (!this.hasRequireFailures()) { - return STATE_RECOGNIZED; - } else { - this._timer = setTimeoutContext(() => { - this.state = STATE_RECOGNIZED; - this.tryEmit(); - }, options.interval, this); - return STATE_BEGAN; - } - } - } - return STATE_FAILED; - } - - failTimeout() { - this._timer = setTimeoutContext(() => { - this.state = STATE_FAILED; - }, this.options.interval, this); - return STATE_FAILED; - } - - reset() { - clearTimeout(this._timer); - } - - emit() { - if (this.state === STATE_RECOGNIZED) { - this._input.tapCount = this.count; - this.manager.emit(this.options.event, this._input); - } - } -} diff --git a/src/touchactionjs/clean-touch-actions.js b/src/touchactionjs/clean-touch-actions.js deleted file mode 100644 index 2244fd816..000000000 --- a/src/touchactionjs/clean-touch-actions.js +++ /dev/null @@ -1,44 +0,0 @@ -import inStr from '../utils/in-str'; -import { - TOUCH_ACTION_NONE, - TOUCH_ACTION_PAN_X, - TOUCH_ACTION_PAN_Y, - TOUCH_ACTION_MANIPULATION, - TOUCH_ACTION_AUTO -} from './touchaction-Consts'; - -/** - * @private - * when the touchActions are collected they are not a valid value, so we need to clean things up. * - * @param {String} actions - * @returns {*} - */ -export default function cleanTouchActions(actions) { - // none - if (inStr(actions, TOUCH_ACTION_NONE)) { - return TOUCH_ACTION_NONE; - } - - let hasPanX = inStr(actions, TOUCH_ACTION_PAN_X); - let hasPanY = inStr(actions, TOUCH_ACTION_PAN_Y); - - // if both pan-x and pan-y are set (different recognizers - // for different directions, e.g. horizontal pan but vertical swipe?) - // we need none (as otherwise with pan-x pan-y combined none of these - // recognizers will work, since the browser would handle all panning - if (hasPanX && hasPanY) { - return TOUCH_ACTION_NONE; - } - - // pan-x OR pan-y - if (hasPanX || hasPanY) { - return hasPanX ? TOUCH_ACTION_PAN_X : TOUCH_ACTION_PAN_Y; - } - - // manipulation - if (inStr(actions, TOUCH_ACTION_MANIPULATION)) { - return TOUCH_ACTION_MANIPULATION; - } - - return TOUCH_ACTION_AUTO; -} diff --git a/src/touchactionjs/get-touchaction-props.js b/src/touchactionjs/get-touchaction-props.js deleted file mode 100644 index 86f9fb3ad..000000000 --- a/src/touchactionjs/get-touchaction-props.js +++ /dev/null @@ -1,16 +0,0 @@ -import { NATIVE_TOUCH_ACTION } from './touchaction-Consts'; - -export default function getTouchActionProps() { - if (!NATIVE_TOUCH_ACTION) { - return false; - } - let touchMap = {}; - let cssSupports = window.CSS && window.CSS.supports; - ['auto', 'manipulation', 'pan-y', 'pan-x', 'pan-x pan-y', 'none'].forEach((val) => { - - // If css.supports is not supported but there is native touch-action assume it supports - // all values. This is the case for IE 10 and 11. - return touchMap[val] = cssSupports ? window.CSS.supports('touch-action', val) : true; - }); - return touchMap; -} diff --git a/src/touchactionjs/touchaction-Consts.js b/src/touchactionjs/touchaction-Consts.js deleted file mode 100644 index 2259e321a..000000000 --- a/src/touchactionjs/touchaction-Consts.js +++ /dev/null @@ -1,27 +0,0 @@ -import prefixed from '../utils/prefixed'; -import { TEST_ELEMENT } from '../utils/utils-consts'; -import getTouchActionProps from './get-touchaction-props'; - -const PREFIXED_TOUCH_ACTION = prefixed(TEST_ELEMENT.style, 'touchAction'); -const NATIVE_TOUCH_ACTION = PREFIXED_TOUCH_ACTION !== undefined; - -// magical touchAction value -const TOUCH_ACTION_COMPUTE = 'compute'; -const TOUCH_ACTION_AUTO = 'auto'; -const TOUCH_ACTION_MANIPULATION = 'manipulation'; // not implemented -const TOUCH_ACTION_NONE = 'none'; -const TOUCH_ACTION_PAN_X = 'pan-x'; -const TOUCH_ACTION_PAN_Y = 'pan-y'; -const TOUCH_ACTION_MAP = getTouchActionProps(); - -export { - PREFIXED_TOUCH_ACTION, - NATIVE_TOUCH_ACTION, - TOUCH_ACTION_AUTO, - TOUCH_ACTION_COMPUTE, - TOUCH_ACTION_MANIPULATION, - TOUCH_ACTION_NONE, - TOUCH_ACTION_PAN_X, - TOUCH_ACTION_PAN_Y, - TOUCH_ACTION_MAP -}; diff --git a/src/touchactionjs/touchaction-constructor.js b/src/touchactionjs/touchaction-constructor.js deleted file mode 100644 index 4007805cc..000000000 --- a/src/touchactionjs/touchaction-constructor.js +++ /dev/null @@ -1,125 +0,0 @@ -import { - TOUCH_ACTION_COMPUTE, - TOUCH_ACTION_MAP, - NATIVE_TOUCH_ACTION, - PREFIXED_TOUCH_ACTION, - TOUCH_ACTION_NONE, - TOUCH_ACTION_PAN_X, - TOUCH_ACTION_PAN_Y -} from './touchaction-Consts'; -import { - DIRECTION_VERTICAL, - DIRECTION_HORIZONTAL -} from '../inputjs/input-consts'; -import each from '../utils/each'; -import boolOrFn from '../utils/bool-or-fn'; -import inStr from '../utils/in-str'; -import cleanTouchActions from './clean-touch-actions'; - -/** - * @private - * Touch Action - * sets the touchAction property or uses the js alternative - * @param {Manager} manager - * @param {String} value - * @constructor - */ -export default class TouchAction { - constructor(manager, value) { - this.manager = manager; - this.set(value); - } - - /** - * @private - * set the touchAction value on the element or enable the polyfill - * @param {String} value - */ - set(value) { - // find out the touch-action by the event handlers - if (value === TOUCH_ACTION_COMPUTE) { - value = this.compute(); - } - - if (NATIVE_TOUCH_ACTION && this.manager.element.style && TOUCH_ACTION_MAP[value]) { - this.manager.element.style[PREFIXED_TOUCH_ACTION] = value; - } - this.actions = value.toLowerCase().trim(); - } - - /** - * @private - * just re-set the touchAction value - */ - update() { - this.set(this.manager.options.touchAction); - } - - /** - * @private - * compute the value for the touchAction property based on the recognizer's settings - * @returns {String} value - */ - compute() { - let actions = []; - each(this.manager.recognizers, (recognizer) => { - if (boolOrFn(recognizer.options.enable, [recognizer])) { - actions = actions.concat(recognizer.getTouchAction()); - } - }); - return cleanTouchActions(actions.join(' ')); - } - - /** - * @private - * this method is called on each input cycle and provides the preventing of the browser behavior - * @param {Object} input - */ - preventDefaults(input) { - let { srcEvent } = input; - let direction = input.offsetDirection; - - // if the touch action did prevented once this session - if (this.manager.session.prevented) { - srcEvent.preventDefault(); - return; - } - - let { actions } = this; - let hasNone = inStr(actions, TOUCH_ACTION_NONE) && !TOUCH_ACTION_MAP[TOUCH_ACTION_NONE]; - let hasPanY = inStr(actions, TOUCH_ACTION_PAN_Y) && !TOUCH_ACTION_MAP[TOUCH_ACTION_PAN_Y]; - let hasPanX = inStr(actions, TOUCH_ACTION_PAN_X) && !TOUCH_ACTION_MAP[TOUCH_ACTION_PAN_X]; - - if (hasNone) { - // do not prevent defaults if this is a tap gesture - let isTapPointer = input.pointers.length === 1; - let isTapMovement = input.distance < 2; - let isTapTouchTime = input.deltaTime < 250; - - if (isTapPointer && isTapMovement && isTapTouchTime) { - return; - } - } - - if (hasPanX && hasPanY) { - // `pan-x pan-y` means browser handles all scrolling/panning, do not prevent - return; - } - - if (hasNone || - (hasPanY && direction & DIRECTION_HORIZONTAL) || - (hasPanX && direction & DIRECTION_VERTICAL)) { - return this.preventSrc(srcEvent); - } - } - - /** - * @private - * call preventDefault to prevent the browser's default behavior (scrolling in most cases) - * @param {Object} srcEvent - */ - preventSrc(srcEvent) { - this.manager.session.prevented = true; - srcEvent.preventDefault(); - } -} diff --git a/src/utils/add-event-listeners.js b/src/utils/add-event-listeners.js deleted file mode 100644 index 99b2da80c..000000000 --- a/src/utils/add-event-listeners.js +++ /dev/null @@ -1,14 +0,0 @@ -import each from './each'; -import splitStr from './split-str'; -/** - * @private - * addEventListener with multiple events at once - * @param {EventTarget} target - * @param {String} types - * @param {Function} handler - */ -export default function addEventListeners(target, types, handler) { - each(splitStr(types), (type) => { - target.addEventListener(type, handler, false); - }); -} diff --git a/src/utils/assign.js b/src/utils/assign.js deleted file mode 100644 index 8cc50220a..000000000 --- a/src/utils/assign.js +++ /dev/null @@ -1,33 +0,0 @@ -/** - * @private - * extend object. - * means that properties in dest will be overwritten by the ones in src. - * @param {Object} target - * @param {...Object} objects_to_assign - * @returns {Object} target - */ -let assign; -if (typeof Object.assign !== 'function') { - assign = function assign(target) { - if (target === undefined || target === null) { - throw new TypeError('Cannot convert undefined or null to object'); - } - - let output = Object(target); - for (let index = 1; index < arguments.length; index++) { - const source = arguments[index]; - if (source !== undefined && source !== null) { - for (const nextKey in source) { - if (source.hasOwnProperty(nextKey)) { - output[nextKey] = source[nextKey]; - } - } - } - } - return output; - }; -} else { - assign = Object.assign; -} - -export default assign; diff --git a/src/utils/bind-fn.js b/src/utils/bind-fn.js deleted file mode 100644 index b915d84a6..000000000 --- a/src/utils/bind-fn.js +++ /dev/null @@ -1,12 +0,0 @@ -/** - * @private - * simple function bind - * @param {Function} fn - * @param {Object} context - * @returns {Function} - */ -export default function bindFn(fn, context) { - return function boundFn() { - return fn.apply(context, arguments); - }; -} diff --git a/src/utils/bool-or-fn.js b/src/utils/bool-or-fn.js deleted file mode 100644 index b57ebb517..000000000 --- a/src/utils/bool-or-fn.js +++ /dev/null @@ -1,15 +0,0 @@ -import { TYPE_FUNCTION } from './utils-consts'; -/** - * @private - * let a boolean value also be a function that must return a boolean - * this first item in args will be used as the context - * @param {Boolean|Function} val - * @param {Array} [args] - * @returns {Boolean} - */ -export default function boolOrFn(val, args) { - if (typeof val === TYPE_FUNCTION) { - return val.apply(args ? args[0] || undefined : undefined, args); - } - return val; -} diff --git a/src/utils/deprecate.js b/src/utils/deprecate.js deleted file mode 100644 index 8f896375f..000000000 --- a/src/utils/deprecate.js +++ /dev/null @@ -1,23 +0,0 @@ -/** - * @private - * wrap a method with a deprecation warning and stack trace - * @param {Function} method - * @param {String} name - * @param {String} message - * @returns {Function} A new function wrapping the supplied method. - */ -export default function deprecate(method, name, message) { - let deprecationMessage = `DEPRECATED METHOD: ${name}\n${message} AT \n`; - return function() { - let e = new Error('get-stack-trace'); - let stack = e && e.stack ? e.stack.replace(/^[^\(]+?[\n$]/gm, '') - .replace(/^\s+at\s+/gm, '') - .replace(/^Object.\s*\(/gm, '{anonymous}()@') : 'Unknown Stack Trace'; - - let log = window.console && (window.console.warn || window.console.log); - if (log) { - log.call(window.console, deprecationMessage, stack); - } - return method.apply(this, arguments); - }; -} diff --git a/src/utils/each.js b/src/utils/each.js deleted file mode 100644 index dd124bb3a..000000000 --- a/src/utils/each.js +++ /dev/null @@ -1,28 +0,0 @@ -/** - * @private - * walk objects and arrays - * @param {Object} obj - * @param {Function} iterator - * @param {Object} context - */ -export default function each(obj, iterator, context) { - let i; - - if (!obj) { - return; - } - - if (obj.forEach) { - obj.forEach(iterator, context); - } else if (obj.length !== undefined) { - i = 0; - while (i < obj.length) { - iterator.call(context, obj[i], i, obj); - i++; - } - } else { - for (i in obj) { - obj.hasOwnProperty(i) && iterator.call(context, obj[i], i, obj); - } - } -} diff --git a/src/utils/extend.js b/src/utils/extend.js deleted file mode 100644 index b3aa2372f..000000000 --- a/src/utils/extend.js +++ /dev/null @@ -1,23 +0,0 @@ -import deprecate from './deprecate'; -/** - * @private - * extend object. - * means that properties in dest will be overwritten by the ones in src. - * @param {Object} dest - * @param {Object} src - * @param {Boolean} [merge=false] - * @returns {Object} dest - */ -const extend = deprecate((dest, src, merge) => { - let keys = Object.keys(src); - let i = 0; - while (i < keys.length) { - if (!merge || (merge && dest[keys[i]] === undefined)) { - dest[keys[i]] = src[keys[i]]; - } - i++; - } - return dest; -}, 'extend', 'Use `assign`.'); - -export default extend; diff --git a/src/utils/get-window-for-element.js b/src/utils/get-window-for-element.js deleted file mode 100644 index f63cc409b..000000000 --- a/src/utils/get-window-for-element.js +++ /dev/null @@ -1,10 +0,0 @@ -/** - * @private - * get the window object of an element - * @param {HTMLElement} element - * @returns {DocumentView|Window} - */ -export default function getWindowForElement(element) { - let doc = element.ownerDocument || element; - return (doc.defaultView || doc.parentWindow || window); -} diff --git a/src/utils/has-parent.js b/src/utils/has-parent.js deleted file mode 100644 index 0e52d5329..000000000 --- a/src/utils/has-parent.js +++ /dev/null @@ -1,17 +0,0 @@ -/** - * @private - * find if a node is in the given parent - * @method hasParent - * @param {HTMLElement} node - * @param {HTMLElement} parent - * @return {Boolean} found - */ -export default function hasParent(node, parent) { - while (node) { - if (node === parent) { - return true; - } - node = node.parentNode; - } - return false; -} diff --git a/src/utils/if-undefined.js b/src/utils/if-undefined.js deleted file mode 100644 index 72ea9218d..000000000 --- a/src/utils/if-undefined.js +++ /dev/null @@ -1,10 +0,0 @@ -/** - * @private - * use the val2 when val1 is undefined - * @param {*} val1 - * @param {*} val2 - * @returns {*} - */ -export default function ifUndefined(val1, val2) { - return (val1 === undefined) ? val2 : val1; -} diff --git a/src/utils/in-array.js b/src/utils/in-array.js deleted file mode 100644 index 11f7769e5..000000000 --- a/src/utils/in-array.js +++ /dev/null @@ -1,22 +0,0 @@ -/** - * @private - * find if a array contains the object using indexOf or a simple polyFill - * @param {Array} src - * @param {String} find - * @param {String} [findByKey] - * @return {Boolean|Number} false when not found, or the index - */ -export default function inArray(src, find, findByKey) { - if (src.indexOf && !findByKey) { - return src.indexOf(find); - } else { - let i = 0; - while (i < src.length) { - if ((findByKey && src[i][findByKey] == find) || (!findByKey && src[i] === find)) {// do not use === here, test fails - return i; - } - i++; - } - return -1; - } -} diff --git a/src/utils/in-str.js b/src/utils/in-str.js deleted file mode 100644 index c45fb4f32..000000000 --- a/src/utils/in-str.js +++ /dev/null @@ -1,10 +0,0 @@ -/** - * @private - * small indexOf wrapper - * @param {String} str - * @param {String} find - * @returns {Boolean} found - */ -export default function inStr(str, find) { - return str.indexOf(find) > -1; -} diff --git a/src/utils/inherit.js b/src/utils/inherit.js deleted file mode 100644 index 1780b175d..000000000 --- a/src/utils/inherit.js +++ /dev/null @@ -1,20 +0,0 @@ -import assign from './assign'; -/** - * @private - * simple class inheritance - * @param {Function} child - * @param {Function} base - * @param {Object} [properties] - */ -export default function inherit(child, base, properties) { - let baseP = base.prototype; - let childP; - - childP = child.prototype = Object.create(baseP); - childP.constructor = child; - childP._super = baseP; - - if (properties) { - assign(childP, properties); - } -} diff --git a/src/utils/invoke-array-arg.js b/src/utils/invoke-array-arg.js deleted file mode 100644 index 7f909ab6c..000000000 --- a/src/utils/invoke-array-arg.js +++ /dev/null @@ -1,18 +0,0 @@ -import each from './each'; -/** - * @private - * if the argument is an array, we want to execute the fn on each entry - * if it aint an array we don't want to do a thing. - * this is used by all the methods that accept a single and array argument. - * @param {*|Array} arg - * @param {String} fn - * @param {Object} [context] - * @returns {Boolean} - */ -export default function invokeArrayArg(arg, fn, context) { - if (Array.isArray(arg)) { - each(arg, context[fn], context); - return true; - } - return false; -} diff --git a/src/utils/merge.js b/src/utils/merge.js deleted file mode 100644 index 015447d9c..000000000 --- a/src/utils/merge.js +++ /dev/null @@ -1,15 +0,0 @@ -import deprecate from './deprecate'; -import extend from './extend'; -/** - * @private - * merge the values from src in the dest. - * means that properties that exist in dest will not be overwritten by src - * @param {Object} dest - * @param {Object} src - * @returns {Object} dest - */ -const merge = deprecate((dest, src) => { - return extend(dest, src, true); -}, 'merge', 'Use `assign`.'); - -export default merge; diff --git a/src/utils/prefixed.js b/src/utils/prefixed.js deleted file mode 100644 index 9f4fd2602..000000000 --- a/src/utils/prefixed.js +++ /dev/null @@ -1,25 +0,0 @@ -import { VENDOR_PREFIXES } from './utils-consts'; -/** - * @private - * get the prefixed property - * @param {Object} obj - * @param {String} property - * @returns {String|Undefined} prefixed - */ -export default function prefixed(obj, property) { - let prefix; - let prop; - let camelProp = property[0].toUpperCase() + property.slice(1); - - let i = 0; - while (i < VENDOR_PREFIXES.length) { - prefix = VENDOR_PREFIXES[i]; - prop = (prefix) ? prefix + camelProp : property; - - if (prop in obj) { - return prop; - } - i++; - } - return undefined; -} diff --git a/src/utils/remove-event-listeners.js b/src/utils/remove-event-listeners.js deleted file mode 100644 index a26898743..000000000 --- a/src/utils/remove-event-listeners.js +++ /dev/null @@ -1,14 +0,0 @@ -import each from './each'; -import splitStr from './split-str'; -/** - * @private - * removeEventListener with multiple events at once - * @param {EventTarget} target - * @param {String} types - * @param {Function} handler - */ -export default function removeEventListeners(target, types, handler) { - each(splitStr(types), (type) => { - target.removeEventListener(type, handler, false); - }); -} diff --git a/src/utils/set-timeout-context.js b/src/utils/set-timeout-context.js deleted file mode 100644 index 9f461bb46..000000000 --- a/src/utils/set-timeout-context.js +++ /dev/null @@ -1,13 +0,0 @@ -import bindFn from './bind-fn'; - -/** - * @private - * set a timeout with a given scope - * @param {Function} fn - * @param {Number} timeout - * @param {Object} context - * @returns {number} - */ -export default function setTimeoutContext(fn, timeout, context) { - return setTimeout(bindFn(fn, context), timeout); -} diff --git a/src/utils/split-str.js b/src/utils/split-str.js deleted file mode 100644 index 352e73fb6..000000000 --- a/src/utils/split-str.js +++ /dev/null @@ -1,10 +0,0 @@ -/** - * @private - * split string on whitespace - * @param {String} str - * @returns {Array} words - */ - -export default function splitStr(str) { - return str.trim().split(/\s+/g); -} diff --git a/src/utils/to-array.js b/src/utils/to-array.js deleted file mode 100644 index 8187e8326..000000000 --- a/src/utils/to-array.js +++ /dev/null @@ -1,9 +0,0 @@ -/** - * @private - * convert array-like objects to real arrays - * @param {Object} obj - * @returns {Array} - */ -export default function toArray(obj) { - return Array.prototype.slice.call(obj, 0); -} diff --git a/src/utils/unique-array.js b/src/utils/unique-array.js deleted file mode 100644 index 36a95aeb8..000000000 --- a/src/utils/unique-array.js +++ /dev/null @@ -1,36 +0,0 @@ -import inArray from './in-array'; - -/** - * @private - * unique array with objects based on a key (like 'id') or just by the array's value - * @param {Array} src [{id:1},{id:2},{id:1}] - * @param {String} [key] - * @param {Boolean} [sort=False] - * @returns {Array} [{id:1},{id:2}] - */ -export default function uniqueArray(src, key, sort) { - let results = []; - let values = []; - let i = 0; - - while (i < src.length) { - let val = key ? src[i][key] : src[i]; - if (inArray(values, val) < 0) { - results.push(src[i]); - } - values[i] = val; - i++; - } - - if (sort) { - if (!key) { - results = results.sort(); - } else { - results = results.sort((a, b) => { - return a[key] > b[key]; - }); - } - } - - return results; -} diff --git a/src/utils/unique-id.js b/src/utils/unique-id.js deleted file mode 100644 index 10916ab10..000000000 --- a/src/utils/unique-id.js +++ /dev/null @@ -1,9 +0,0 @@ -/** - * @private - * get a unique id - * @returns {number} uniqueId - */ -let _uniqueId = 1; -export default function uniqueId() { - return _uniqueId++; -} diff --git a/src/utils/utils-consts.js b/src/utils/utils-consts.js deleted file mode 100644 index a2c30db35..000000000 --- a/src/utils/utils-consts.js +++ /dev/null @@ -1,16 +0,0 @@ -const VENDOR_PREFIXES = ['', 'webkit', 'Moz', 'MS', 'ms', 'o']; -const TEST_ELEMENT = document.createElement('div'); - -const TYPE_FUNCTION = 'function'; - -const { round, abs } = Math; -const { now } = Date; - -export { - VENDOR_PREFIXES, - TEST_ELEMENT, - TYPE_FUNCTION, - round, - abs, - now -}; From 7a6937ec65d4137abde6dfea833391b02ecc95ab Mon Sep 17 00:00:00 2001 From: Christopher Garrett Date: Tue, 12 Jul 2016 15:01:02 -0700 Subject: [PATCH 60/61] refactor(Hammer 3): Begins Hammer 3 dev branch Splices in the Hammer 3 experiment from `ember-history` and updates the build system to work with the new files. Adds a `main.js` file which exposes a minimal API for Hammer 3. --- .babelrc | 3 +++ Gruntfile.js | 6 +++--- package.json | 3 ++- src/README.md | 12 ----------- src/inputs/input.js | 2 +- src/inputs/pointer.js | 0 src/main.js | 41 ++++++++++++++++++++++++++++++++++++ src/manager.js | 3 +-- src/streams/stream-event.js | 2 +- src/streams/stream-series.js | 4 ++-- src/streams/stream.js | 2 +- src/utils/assign.js | 33 +++++++++++++++++++++++++++++ 12 files changed, 88 insertions(+), 23 deletions(-) create mode 100644 .babelrc delete mode 100644 src/README.md delete mode 100644 src/inputs/pointer.js create mode 100644 src/main.js create mode 100644 src/utils/assign.js diff --git a/.babelrc b/.babelrc new file mode 100644 index 000000000..1d9cdd528 --- /dev/null +++ b/.babelrc @@ -0,0 +1,3 @@ +{ + "presets": ["es2015-rollup"] +} diff --git a/Gruntfile.js b/Gruntfile.js index 1e0de644d..f9a98433f 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -1,4 +1,5 @@ var babel = require('rollup-plugin-babel'); +var nodeResolve = require('rollup-plugin-node-resolve'); module.exports = function(grunt) { grunt.initConfig({ @@ -19,9 +20,8 @@ module.exports = function(grunt) { options: { format: 'es6', plugins: [ - babel({ - exclude: 'node_modules/**' - }) + nodeResolve(), + babel() ], intro: " (function(window, document, exportName, undefined) { \n'use strict';", outro: "})(window, document, 'Hammer');" diff --git a/package.json b/package.json index 0e9384ee6..5688e6bf6 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,8 @@ "hammer-simulator": "git://github.com/hammerjs/simulator#master", "jquery-hammerjs": "2.0.x", "rollup": "^0.26.3", - "rollup-plugin-babel": "^2.4.0" + "rollup-plugin-babel": "^2.4.0", + "rollup-plugin-node-resolve": "^1.7.1" }, "main": "hammer.js", "engines": { diff --git a/src/README.md b/src/README.md deleted file mode 100644 index 710fea60b..000000000 --- a/src/README.md +++ /dev/null @@ -1,12 +0,0 @@ -Hammer.js 3.0 -============= - -`-private/gestures` is an initial exploratory spike of the concepts -likely to be used for Hammer.js 3.0 - -So if you reached in, found these, and like them, you should now reach out -finish them, and land them in Hammer ;) - -- Chris - - diff --git a/src/inputs/input.js b/src/inputs/input.js index 90686a742..332bd1aaa 100644 --- a/src/inputs/input.js +++ b/src/inputs/input.js @@ -1,6 +1,6 @@ import Stream from '../streams/stream'; import StreamEvent from '../streams/stream-event'; -import HashMap from 'perf-primitives/hash-map'; +import HashMap from 'perf-primitives/addon/hash-map'; export default class Input { diff --git a/src/inputs/pointer.js b/src/inputs/pointer.js deleted file mode 100644 index e69de29bb..000000000 diff --git a/src/main.js b/src/main.js new file mode 100644 index 000000000..3e908e536 --- /dev/null +++ b/src/main.js @@ -0,0 +1,41 @@ +import Input from './inputs/input'; +import Layer from './layer'; +import Manager from './manager'; +import Recognizer from './recognizer'; + +import MouseInput from './inputs/mouse'; +import TouchInput from './inputs/touch'; + +import HorizontalPanRecognizer from './recognizers/horizontal-pan'; +import VerticalPanRecognizer from './recognizers/vertical-pan'; + +// this prevents errors when Hammer is loaded in the presence of an AMD +// style loader but by script tag, not by the loader. + +let Hammer = { + Input, + Layer, + Manager, + Recognizer, + + MouseInput, + TouchInput, + + HorizontalPanRecognizer, + VerticalPanRecognizer +}; + +let freeGlobal = (typeof window !== 'undefined' ? window : (typeof self !== 'undefined' ? self : {})); // jshint ignore:line +freeGlobal.Hammer = Hammer; + +/* jshint ignore:start */ +if (typeof define === 'function' && define.amd) { + define(() => { + return Hammer; + }); +} else if (typeof module !== 'undefined' && module.exports) { + module.exports = Hammer; +} else { + window[exportName] = Hammer; +} +/* jshint ignore:end */ diff --git a/src/manager.js b/src/manager.js index e37abf92d..af57823f6 100644 --- a/src/manager.js +++ b/src/manager.js @@ -1,7 +1,6 @@ import { availableInputs } from './utils/detection'; -import Ember from 'ember'; +import assign from './utils/assign'; -const assign = Ember.assign || Object.assign || Ember.merge; const DEFAULT_OPTIONS = { inputs: availableInputs() }; diff --git a/src/streams/stream-event.js b/src/streams/stream-event.js index f49d7e90b..8c0eab2ad 100644 --- a/src/streams/stream-event.js +++ b/src/streams/stream-event.js @@ -1,5 +1,5 @@ /* global Math, performance */ -import FastArray from 'perf-primitives/fast-array'; +import FastArray from 'perf-primitives/addon/fast-array'; const STREAM_EVENT_POOL = new FastArray(undefined, 'StreamEvent Pool'); export default class StreamEvent { diff --git a/src/streams/stream-series.js b/src/streams/stream-series.js index 638c17e93..88d580c90 100644 --- a/src/streams/stream-series.js +++ b/src/streams/stream-series.js @@ -1,5 +1,5 @@ -import FastArray from 'perf-primitives/fast-array'; -import { SMALL_ARRAY_LENGTH } from 'perf-primitives/-constants'; +import FastArray from 'perf-primitives/addon/fast-array'; +import { SMALL_ARRAY_LENGTH } from 'perf-primitives/addon/-constants'; const STREAM_SERIES_POOL = new FastArray(10, 'StreamSeries Pool'); diff --git a/src/streams/stream.js b/src/streams/stream.js index c5ace5847..8c6136054 100644 --- a/src/streams/stream.js +++ b/src/streams/stream.js @@ -1,7 +1,7 @@ import StreamEvent from './stream-event'; import StreamSeries from './stream-series'; import MacroTask from '../utils/macro-task'; -import FastArray from 'perf-primitives/fast-array'; +import FastArray from 'perf-primitives/addon/fast-array'; const STREAM_POOL = new FastArray(5, 'Stream Pool'); diff --git a/src/utils/assign.js b/src/utils/assign.js new file mode 100644 index 000000000..8cc50220a --- /dev/null +++ b/src/utils/assign.js @@ -0,0 +1,33 @@ +/** + * @private + * extend object. + * means that properties in dest will be overwritten by the ones in src. + * @param {Object} target + * @param {...Object} objects_to_assign + * @returns {Object} target + */ +let assign; +if (typeof Object.assign !== 'function') { + assign = function assign(target) { + if (target === undefined || target === null) { + throw new TypeError('Cannot convert undefined or null to object'); + } + + let output = Object(target); + for (let index = 1; index < arguments.length; index++) { + const source = arguments[index]; + if (source !== undefined && source !== null) { + for (const nextKey in source) { + if (source.hasOwnProperty(nextKey)) { + output[nextKey] = source[nextKey]; + } + } + } + } + return output; + }; +} else { + assign = Object.assign; +} + +export default assign; From f8b29476dd5bfcdbf277fe3cd13f1455ba9bd5f3 Mon Sep 17 00:00:00 2001 From: Christopher Garrett Date: Tue, 12 Jul 2016 16:49:34 -0700 Subject: [PATCH 61/61] fix(build): clean up code to pass jshint and jscs, add new builds --- README.md | 4 +- hammer.js | 3586 ++++++++++------------------- hammer.min.js | 4 +- hammer.min.js.map | 2 +- hammer.min.map | 1 - package.json | 2 +- src/layer.js | 2 +- src/main.js | 2 +- src/recognizers/horizontal-pan.js | 4 +- src/recognizers/vertical-pan.js | 4 +- src/streams/stream-event.js | 2 - src/streams/stream-series.js | 2 + src/streams/stream.js | 4 +- 13 files changed, 1195 insertions(+), 2424 deletions(-) delete mode 100644 hammer.min.map diff --git a/README.md b/README.md index e7bf8b8f0..9d857b572 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Hammer.js 2.0.6 +# Hammer.js 3.0.0 [![Build Status](https://travis-ci.org/hammerjs/hammer.js.svg)](https://travis-ci.org/hammerjs/hammer.js) @@ -47,5 +47,5 @@ For PRs. ## Building -You can get the pre-build versions from the Hammer.js website, or do this by yourself running +You can get the pre-build versions from the Hammer.js website, or do this by yourself running `npm install -g grunt-cli && npm install && grunt build` diff --git a/hammer.js b/hammer.js index 00d2965eb..53f5f9045 100644 --- a/hammer.js +++ b/hammer.js @@ -1,2643 +1,1413 @@ -/*! Hammer.JS - v2.0.7 - 2016-04-22 +/*! Hammer.JS - v2.0.8 - 2016-07-12 * http://hammerjs.github.io/ * * Copyright (c) 2016 Jorik Tangelder; * Licensed under the MIT license */ -(function(window, document, exportName, undefined) { - 'use strict'; - -var VENDOR_PREFIXES = ['', 'webkit', 'Moz', 'MS', 'ms', 'o']; -var TEST_ELEMENT = document.createElement('div'); - -var TYPE_FUNCTION = 'function'; - -var round = Math.round; -var abs = Math.abs; -var now = Date.now; - -/** - * set a timeout with a given scope - * @param {Function} fn - * @param {Number} timeout - * @param {Object} context - * @returns {number} - */ -function setTimeoutContext(fn, timeout, context) { - return setTimeout(bindFn(fn, context), timeout); -} +(function(window, document, exportName, undefined) { +'use strict'; +var SMALL_ARRAY_LENGTH = 200; +var UNDEFINED_KEY = Object.create(null); + +var classCallCheck = function (instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } +}; -/** - * if the argument is an array, we want to execute the fn on each entry - * if it aint an array we don't want to do a thing. - * this is used by all the methods that accept a single and array argument. - * @param {*|Array} arg - * @param {String} fn - * @param {Object} [context] - * @returns {Boolean} - */ -function invokeArrayArg(arg, fn, context) { - if (Array.isArray(arg)) { - each(arg, context[fn], context); - return true; +var createClass = function () { + function defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) descriptor.writable = true; + Object.defineProperty(target, descriptor.key, descriptor); } - return false; -} + } -/** - * walk objects and arrays - * @param {Object} obj - * @param {Function} iterator - * @param {Object} context - */ -function each(obj, iterator, context) { - var i; + return function (Constructor, protoProps, staticProps) { + if (protoProps) defineProperties(Constructor.prototype, protoProps); + if (staticProps) defineProperties(Constructor, staticProps); + return Constructor; + }; +}(); - if (!obj) { - return; - } +var get = function get(object, property, receiver) { + if (object === null) object = Function.prototype; + var desc = Object.getOwnPropertyDescriptor(object, property); - if (obj.forEach) { - obj.forEach(iterator, context); - } else if (obj.length !== undefined) { - i = 0; - while (i < obj.length) { - iterator.call(context, obj[i], i, obj); - i++; - } + if (desc === undefined) { + var parent = Object.getPrototypeOf(object); + + if (parent === null) { + return undefined; } else { - for (i in obj) { - obj.hasOwnProperty(i) && iterator.call(context, obj[i], i, obj); - } + return get(parent, property, receiver); } -} + } else if ("value" in desc) { + return desc.value; + } else { + var getter = desc.get; -/** - * wrap a method with a deprecation warning and stack trace - * @param {Function} method - * @param {String} name - * @param {String} message - * @returns {Function} A new function wrapping the supplied method. - */ -function deprecate(method, name, message) { - var deprecationMessage = 'DEPRECATED METHOD: ' + name + '\n' + message + ' AT \n'; - return function() { - var e = new Error('get-stack-trace'); - var stack = e && e.stack ? e.stack.replace(/^[^\(]+?[\n$]/gm, '') - .replace(/^\s+at\s+/gm, '') - .replace(/^Object.\s*\(/gm, '{anonymous}()@') : 'Unknown Stack Trace'; - - var log = window.console && (window.console.warn || window.console.log); - if (log) { - log.call(window.console, deprecationMessage, stack); - } - return method.apply(this, arguments); - }; -} - -/** - * extend object. - * means that properties in dest will be overwritten by the ones in src. - * @param {Object} target - * @param {...Object} objects_to_assign - * @returns {Object} target - */ -var assign; -if (typeof Object.assign !== 'function') { - assign = function assign(target) { - if (target === undefined || target === null) { - throw new TypeError('Cannot convert undefined or null to object'); - } + if (getter === undefined) { + return undefined; + } - var output = Object(target); - for (var index = 1; index < arguments.length; index++) { - var source = arguments[index]; - if (source !== undefined && source !== null) { - for (var nextKey in source) { - if (source.hasOwnProperty(nextKey)) { - output[nextKey] = source[nextKey]; - } - } - } - } - return output; - }; -} else { - assign = Object.assign; -} + return getter.call(receiver); + } +}; -/** - * extend object. - * means that properties in dest will be overwritten by the ones in src. - * @param {Object} dest - * @param {Object} src - * @param {Boolean} [merge=false] - * @returns {Object} dest - */ -var extend = deprecate(function extend(dest, src, merge) { - var keys = Object.keys(src); - var i = 0; - while (i < keys.length) { - if (!merge || (merge && dest[keys[i]] === undefined)) { - dest[keys[i]] = src[keys[i]]; - } - i++; +var inherits = function (subClass, superClass) { + if (typeof superClass !== "function" && superClass !== null) { + throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); + } + + subClass.prototype = Object.create(superClass && superClass.prototype, { + constructor: { + value: subClass, + enumerable: false, + writable: true, + configurable: true } - return dest; -}, 'extend', 'Use `assign`.'); - -/** - * merge the values from src in the dest. - * means that properties that exist in dest will not be overwritten by src - * @param {Object} dest - * @param {Object} src - * @returns {Object} dest - */ -var merge = deprecate(function merge(dest, src) { - return extend(dest, src, true); -}, 'merge', 'Use `assign`.'); + }); + if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; +}; -/** - * simple class inheritance - * @param {Function} child - * @param {Function} base - * @param {Object} [properties] - */ -function inherit(child, base, properties) { - var baseP = base.prototype, - childP; +var possibleConstructorReturn = function (self, call) { + if (!self) { + throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); + } - childP = child.prototype = Object.create(baseP); - childP.constructor = child; - childP._super = baseP; + return call && (typeof call === "object" || typeof call === "function") ? call : self; +}; - if (properties) { - assign(childP, properties); +var FastArray = function () { + function FastArray() { + var length = arguments.length <= 0 || arguments[0] === undefined ? SMALL_ARRAY_LENGTH : arguments[0]; + var name = arguments.length <= 1 || arguments[1] === undefined ? 'Unknown Pool' : arguments[1]; + classCallCheck(this, FastArray); + + this.init(length, name); + } + + createClass(FastArray, [{ + key: 'init', + value: function init() { + var length = arguments.length <= 0 || arguments[0] === undefined ? SMALL_ARRAY_LENGTH : arguments[0]; + var name = arguments.length <= 1 || arguments[1] === undefined ? 'Unknown Pool' : arguments[1]; + + this.name = name; + this.length = 0; + this._length = length; + this._data = new Array(length); } -} - -/** - * simple function bind - * @param {Function} fn - * @param {Object} context - * @returns {Function} - */ -function bindFn(fn, context) { - return function boundFn() { - return fn.apply(context, arguments); - }; -} - -/** - * let a boolean value also be a function that must return a boolean - * this first item in args will be used as the context - * @param {Boolean|Function} val - * @param {Array} [args] - * @returns {Boolean} - */ -function boolOrFn(val, args) { - if (typeof val == TYPE_FUNCTION) { - return val.apply(args ? args[0] || undefined : undefined, args); + }, { + key: 'get', + value: function get(index) { + if (index >= 0 && index < this.length) { + return this._data[index]; + } + + return undefined; } - return val; -} - -/** - * use the val2 when val1 is undefined - * @param {*} val1 - * @param {*} val2 - * @returns {*} - */ -function ifUndefined(val1, val2) { - return (val1 === undefined) ? val2 : val1; -} - -/** - * addEventListener with multiple events at once - * @param {EventTarget} target - * @param {String} types - * @param {Function} handler - */ -function addEventListeners(target, types, handler) { - each(splitStr(types), function(type) { - target.addEventListener(type, handler, false); - }); -} + }, { + key: 'set', + value: function set(index, value) { + if (index > this.length) { + throw new Error("Index is out of array bounds."); + } + + if (index === this.length) { + this.length++; + } + + this._data[index] = value; + } + }, { + key: 'forEach', + value: function forEach(cb) { + for (var i = 0; i < this.length; i++) { + cb(this._data[i], i); + } + } + }, { + key: 'emptyEach', + value: function emptyEach(cb) { + for (var i = 0; i < this.length; i++) { + cb(this._data[i], i); + this._data[i] = undefined; + } + + this.length = 0; + } + }, { + key: 'mapInPlace', + value: function mapInPlace(cb) { + for (var i = 0; i < this.length; i++) { + this._data[i] = cb(this._data[i], i); + } + } + }, { + key: 'map', + value: function map(cb) { + var arr = new FastArray(this._length, this.name); -/** - * removeEventListener with multiple events at once - * @param {EventTarget} target - * @param {String} types - * @param {Function} handler - */ -function removeEventListeners(target, types, handler) { - each(splitStr(types), function(type) { - target.removeEventListener(type, handler, false); - }); -} + for (var i = 0; i < this.length; i++) { + arr._data[i] = cb(this._data[i], i); + } -/** - * find if a node is in the given parent - * @method hasParent - * @param {HTMLElement} node - * @param {HTMLElement} parent - * @return {Boolean} found - */ -function hasParent(node, parent) { - while (node) { - if (node == parent) { - return true; - } - node = node.parentNode; + return arr; } - return false; -} + }, { + key: 'push', + value: function push(item) { + var index = this.length++; -/** - * small indexOf wrapper - * @param {String} str - * @param {String} find - * @returns {Boolean} found - */ -function inStr(str, find) { - return str.indexOf(find) > -1; -} + if (index === this._length) { + this._length *= 2; + this._data.length = this._length; + } -/** - * split string on whitespace - * @param {String} str - * @returns {Array} words - */ -function splitStr(str) { - return str.trim().split(/\s+/g); -} - -/** - * find if a array contains the object using indexOf or a simple polyFill - * @param {Array} src - * @param {String} find - * @param {String} [findByKey] - * @return {Boolean|Number} false when not found, or the index - */ -function inArray(src, find, findByKey) { - if (src.indexOf && !findByKey) { - return src.indexOf(find); - } else { - var i = 0; - while (i < src.length) { - if ((findByKey && src[i][findByKey] == find) || (!findByKey && src[i] === find)) { - return i; - } - i++; - } - return -1; + this._data[index] = item; } -} + }, { + key: 'pop', + value: function pop() { + var index = --this.length; -/** - * convert array-like objects to real arrays - * @param {Object} obj - * @returns {Array} - */ -function toArray(obj) { - return Array.prototype.slice.call(obj, 0); -} + if (index < 0) { + this.length = 0; + return undefined; + } -/** - * unique array with objects based on a key (like 'id') or just by the array's value - * @param {Array} src [{id:1},{id:2},{id:1}] - * @param {String} [key] - * @param {Boolean} [sort=False] - * @returns {Array} [{id:1},{id:2}] - */ -function uniqueArray(src, key, sort) { - var results = []; - var values = []; - var i = 0; - - while (i < src.length) { - var val = key ? src[i][key] : src[i]; - if (inArray(values, val) < 0) { - results.push(src[i]); - } - values[i] = val; - i++; + return this._data[index]; } - - if (sort) { - if (!key) { - results = results.sort(); - } else { - results = results.sort(function sortUniqueArray(a, b) { - return a[key] > b[key]; - }); - } + }]); + return FastArray; +}(); + +var STREAM_EVENT_POOL = new FastArray(undefined, 'StreamEvent Pool'); + +var StreamEvent = function () { + function StreamEvent(name, info, prev) { + classCallCheck(this, StreamEvent); + + this.init(name, info, prev); + } + + createClass(StreamEvent, [{ + key: 'init', + value: function init(name, info, prev) { + this.name = name; + this.element = info.event.target; + this._isImportantEvent = name === 'end' || name === 'start' || prev && prev.name === 'start'; + this._source = this._isImportantEvent ? info.event : undefined; + this.silenced = false; + this.prev = prev; + this.pointerId = info.pointerId; + + // time + this.time = performance.now(); + this.dT = prev ? this.time - prev.time : 0; + + // current position (clientX/Y) + this.x = info.x; + this.y = info.y; + + // deltas off of origin event + this.originX = info.originX; + this.originY = info.originY; + this.totalX = info.x - this.originX; + this.totalY = info.y - this.originY; + + // deltas off the segment + this.segmentOriginX = info.segmentOriginX; + this.segmentOriginY = info.segmentOriginY; + this.segmentX = info.x - this.segmentOriginX; + this.segmentY = info.y - this.segmentOriginY; + + // deltas off of last event + this.dX = prev ? info.x - prev.x : 0; + this.dY = prev ? info.y - prev.y : 0; + + // prediction values + this.acceleration = 0; + this.aX = 0; + this.aY = 0; + + this.velocity = 0; + this.vX = 0; + this.vY = 0; + + this.nextX = 0; + this.nextY = 0; } + }, { + key: 'getAccelerationX', + value: function getAccelerationX() { + var dT = this.dT; + var prev = this.prev; - return results; -} - -/** - * get the prefixed property - * @param {Object} obj - * @param {String} property - * @returns {String|Undefined} prefixed - */ -function prefixed(obj, property) { - var prefix, prop; - var camelProp = property[0].toUpperCase() + property.slice(1); + var vX = this.getVelocityX(); + var _vX = prev.vX; - var i = 0; - while (i < VENDOR_PREFIXES.length) { - prefix = VENDOR_PREFIXES[i]; - prop = (prefix) ? prefix + camelProp : property; - if (prop in obj) { - return prop; - } - i++; + return this.aX = (vX - _vX) / dT; } - return undefined; -} - -/** - * get a unique id - * @returns {number} uniqueId - */ -var _uniqueId = 1; -function uniqueId() { - return _uniqueId++; -} - -/** - * get the window object of an element - * @param {HTMLElement} element - * @returns {DocumentView|Window} - */ -function getWindowForElement(element) { - var doc = element.ownerDocument || element; - return (doc.defaultView || doc.parentWindow || window); -} - -var MOBILE_REGEX = /mobile|tablet|ip(ad|hone|od)|android/i; + }, { + key: 'getAccelerationY', + value: function getAccelerationY() { + var dT = this.dT; + var prev = this.prev; -var SUPPORT_TOUCH = ('ontouchstart' in window); -var SUPPORT_POINTER_EVENTS = prefixed(window, 'PointerEvent') !== undefined; -var SUPPORT_ONLY_TOUCH = SUPPORT_TOUCH && MOBILE_REGEX.test(navigator.userAgent); + var vY = this.getVelocityY(); + var _vY = prev.vY; -var INPUT_TYPE_TOUCH = 'touch'; -var INPUT_TYPE_PEN = 'pen'; -var INPUT_TYPE_MOUSE = 'mouse'; -var INPUT_TYPE_KINECT = 'kinect'; -var COMPUTE_INTERVAL = 25; - -var INPUT_START = 1; -var INPUT_MOVE = 2; -var INPUT_END = 4; -var INPUT_CANCEL = 8; + return this.aY = (vY - _vY) / dT; + } + }, { + key: 'getAcceleration', + value: function getAcceleration() { + var aX = this.getAccelerationX(); + var aY = this.getAccelerationY(); + var acceleration = this.acceleration = Math.sqrt(aX * aX + aY * aY); + + return { aX: aX, aY: aY, acceleration: acceleration }; + } + }, { + key: 'getVelocityX', + value: function getVelocityX() { + var dX = this.dX; + var dT = this.dT; -var DIRECTION_NONE = 1; -var DIRECTION_LEFT = 2; -var DIRECTION_RIGHT = 4; -var DIRECTION_UP = 8; -var DIRECTION_DOWN = 16; -var DIRECTION_HORIZONTAL = DIRECTION_LEFT | DIRECTION_RIGHT; -var DIRECTION_VERTICAL = DIRECTION_UP | DIRECTION_DOWN; -var DIRECTION_ALL = DIRECTION_HORIZONTAL | DIRECTION_VERTICAL; + return this.vX = dX / dT; + } + }, { + key: 'getVelocityY', + value: function getVelocityY() { + var dY = this.dY; + var dT = this.dT; -var PROPS_XY = ['x', 'y']; -var PROPS_CLIENT_XY = ['clientX', 'clientY']; -/** - * create new input type manager - * @param {Manager} manager - * @param {Function} callback - * @returns {Input} - * @constructor - */ -function Input(manager, callback) { - var self = this; - this.manager = manager; - this.callback = callback; - this.element = manager.element; - this.target = manager.options.inputTarget; - - // smaller wrapper around the handler, for the scope and the enabled state of the manager, - // so when disabled the input events are completely bypassed. - this.domHandler = function(ev) { - if (boolOrFn(manager.options.enable, [manager])) { - self.handler(ev); - } - }; + return this.vY = dY / dT; + } + }, { + key: 'getVelocity', + value: function getVelocity() { + var vX = this.getVelocityX(); + var vY = this.getVelocityY(); + var velocity = this.velocity = Math.sqrt(vX * vX + vY * vY); + + return { vX: vX, vY: vY, velocity: velocity }; + } + }, { + key: 'predictX', + value: function predictX() { + var aX = this.getAccelerationX(); + var x = this.x; + var dX = this.dX; + var vX = this.vX; + var dT = this.dT; + var totalX = this.totalX; + + // distance = initial distance + velocity * time + 1/2 acceleration * time^2 + + var nextDeltaX = Math.round(vX * dT + 0.5 * aX * dT * dT); + var nextdX = dX + nextDeltaX; + var nextX = x + nextDeltaX; + var nextTotalX = totalX + nextDeltaX; + + return this.nextX = { x: nextX, dX: nextdX, totalX: nextTotalX }; + } + }, { + key: 'predictY', + value: function predictY() { + var aY = this.getAccelerationY(); + var y = this.y; + var dY = this.dY; + var vY = this.vY; + var dT = this.dT; + var totalY = this.totalY; + + // distance = initial distance + velocity * time + 1/2 acceleration * time^2 + + var nextDeltaY = Math.round(vY * dT + 0.5 * aY * dT * dT); + var nextdY = dY + nextDeltaY; + var nextY = y + nextDeltaY; + var nextTotalY = totalY + nextDeltaY; + + return this.nextY = { y: nextY, dY: nextdY, totalY: nextTotalY }; + } + }, { + key: 'predict', + value: function predict() { + var nextX = this.predictX(); + var nextY = this.predictY(); - this.init(); + return { x: nextX, y: nextY }; + } -} + // cancel any default behaviors from this event -Input.prototype = { - /** - * should handle the inputEvent data and trigger the callback - * @virtual - */ - handler: function() { }, - - /** - * bind the events - */ - init: function() { - this.evEl && addEventListeners(this.element, this.evEl, this.domHandler); - this.evTarget && addEventListeners(this.target, this.evTarget, this.domHandler); - this.evWin && addEventListeners(getWindowForElement(this.element), this.evWin, this.domHandler); - }, - - /** - * unbind the events - */ - destroy: function() { - this.evEl && removeEventListeners(this.element, this.evEl, this.domHandler); - this.evTarget && removeEventListeners(this.target, this.evTarget, this.domHandler); - this.evWin && removeEventListeners(getWindowForElement(this.element), this.evWin, this.domHandler); + }, { + key: 'silence', + value: function silence() { + if (this._source && this._source.cancelable) { + this._source.preventDefault(); + this._source.stopPropagation(); + this.silenced = true; + } } -}; - -/** - * create new input type manager - * called by the Manager constructor - * @param {Hammer} manager - * @returns {Input} - */ -function createInputInstance(manager) { - var Type; - var inputClass = manager.options.inputClass; - - if (inputClass) { - Type = inputClass; - } else if (SUPPORT_POINTER_EVENTS) { - Type = PointerEventInput; - } else if (SUPPORT_ONLY_TOUCH) { - Type = TouchInput; - } else if (!SUPPORT_TOUCH) { - Type = MouseInput; - } else { - Type = TouchMouseInput; + }, { + key: 'destroy', + value: function destroy() { + this._source = undefined; + this.prev = undefined; + this.element = undefined; + + STREAM_EVENT_POOL.push(this); } - return new (Type)(manager, inputHandler); -} - -/** - * handle input events - * @param {Manager} manager - * @param {String} eventType - * @param {Object} input - */ -function inputHandler(manager, eventType, input) { - var pointersLen = input.pointers.length; - var changedPointersLen = input.changedPointers.length; - var isFirst = (eventType & INPUT_START && (pointersLen - changedPointersLen === 0)); - var isFinal = (eventType & (INPUT_END | INPUT_CANCEL) && (pointersLen - changedPointersLen === 0)); + }], [{ + key: 'create', + value: function create(name, info, prev) { + var event = STREAM_EVENT_POOL.pop(); - input.isFirst = !!isFirst; - input.isFinal = !!isFinal; + if (event) { + event.init(name, info, prev); + return event; + } - if (isFirst) { - manager.session = {}; + return new StreamEvent(name, info, prev); } + }]); + return StreamEvent; +}(); - // source event is the normalized value of the domEvents - // like 'touchstart, mouseup, pointerdown' - input.eventType = eventType; +var STREAM_SERIES_POOL = new FastArray(10, 'StreamSeries Pool'); - // compute scale, rotation etc - computeInputData(manager, input); +var StreamSeries = function (_FastArray) { + inherits(StreamSeries, _FastArray); - // emit secret event - manager.emit('hammer.input', input); + function StreamSeries(values) { + var number = arguments.length <= 1 || arguments[1] === undefined ? SMALL_ARRAY_LENGTH : arguments[1]; + var name = arguments.length <= 2 || arguments[2] === undefined ? 'StreamEvent to List' : arguments[2]; + classCallCheck(this, StreamSeries); - manager.recognize(input); - manager.session.prevInput = input; -} + var _this = possibleConstructorReturn(this, Object.getPrototypeOf(StreamSeries).call(this, number, name)); -/** - * extend the data with some usable properties like scale, rotate, velocity etc - * @param {Object} manager - * @param {Object} input - */ -function computeInputData(manager, input) { - var session = manager.session; - var pointers = input.pointers; - var pointersLength = pointers.length; + _this.init(values, number, name); + _this._isDestroyed = false; + return _this; + } - // store the first input to calculate the distance and direction - if (!session.firstInput) { - session.firstInput = simpleCloneInputData(input); - } + createClass(StreamSeries, [{ + key: 'init', + value: function init(_ref, length, name) { + var originX = _ref.originX; + var originY = _ref.originY; - // to compute scale and rotation we need to store the multiple touches - if (pointersLength > 1 && !session.firstMultiple) { - session.firstMultiple = simpleCloneInputData(input); - } else if (pointersLength === 1) { - session.firstMultiple = false; + get(Object.getPrototypeOf(StreamSeries.prototype), 'init', this).call(this, length, name); + this.originX = originX; + this.originY = originY; } + }, { + key: 'destroy', + value: function destroy() { + if (!this._isDestroyed) { + this._isDestroyed = true; - var firstInput = session.firstInput; - var firstMultiple = session.firstMultiple; - var offsetCenter = firstMultiple ? firstMultiple.center : firstInput.center; - - var center = input.center = getCenter(pointers); - input.timeStamp = now(); - input.deltaTime = input.timeStamp - firstInput.timeStamp; - - input.angle = getAngle(offsetCenter, center); - input.distance = getDistance(offsetCenter, center); - - computeDeltaXY(session, input); - input.offsetDirection = getDirection(input.deltaX, input.deltaY); + for (var j = 0; j < this.length; j++) { + this._data[j].destroy(); + this._data[j] = undefined; + } - var overallVelocity = getVelocity(input.deltaTime, input.deltaX, input.deltaY); - input.overallVelocityX = overallVelocity.x; - input.overallVelocityY = overallVelocity.y; - input.overallVelocity = (abs(overallVelocity.x) > abs(overallVelocity.y)) ? overallVelocity.x : overallVelocity.y; + STREAM_SERIES_POOL.push(this); + } + } + }], [{ + key: 'create', + value: function create(values) { + var number = arguments.length <= 1 || arguments[1] === undefined ? SMALL_ARRAY_LENGTH : arguments[1]; + var name = arguments.length <= 2 || arguments[2] === undefined ? 'StreamEvent to List' : arguments[2]; - input.scale = firstMultiple ? getScale(firstMultiple.pointers, pointers) : 1; - input.rotation = firstMultiple ? getRotation(firstMultiple.pointers, pointers) : 0; + var series = STREAM_SERIES_POOL.pop(); - input.maxPointers = !session.prevInput ? input.pointers.length : ((input.pointers.length > - session.prevInput.maxPointers) ? input.pointers.length : session.prevInput.maxPointers); + if (series) { + series.init(values, number, name); - computeIntervalInputData(session, input); + return series; + } - // find the correct target - var target = manager.element; - if (hasParent(input.srcEvent.target, target)) { - target = input.srcEvent.target; + return new StreamSeries(values, number, name); } - input.target = target; -} + }]); + return StreamSeries; +}(FastArray); -function computeDeltaXY(session, input) { - var center = input.center; - var offset = session.offsetDelta || {}; - var prevDelta = session.prevDelta || {}; - var prevInput = session.prevInput || {}; +var MacroTask = function MacroTask(job) { + classCallCheck(this, MacroTask); - if (input.eventType === INPUT_START || prevInput.eventType === INPUT_END) { - prevDelta = session.prevDelta = { - x: prevInput.deltaX || 0, - y: prevInput.deltaY || 0 - }; + setTimeout(job, 0); +}; - offset = session.offsetDelta = { - x: center.x, - y: center.y - }; +var STREAM_POOL = new FastArray(5, 'Stream Pool'); + +var Stream = function () { + function Stream(values) { + classCallCheck(this, Stream); + + this.init(values); + } + + createClass(Stream, [{ + key: 'init', + value: function init(_ref) { + var pointerId = _ref.pointerId; + var originX = _ref.originX; + var originY = _ref.originY; + + this.segments = new FastArray(5, 'Segments'); + this.series = undefined; + this._isDestroyed = false; + this._isDestroying = false; + this.active = false; + this.pointerId = pointerId; + this.originX = originX; + this.originY = originY; } + }, { + key: 'open', + value: function open(info) { + this.active = true; + this.series = StreamSeries.create({ originX: info.x, originY: info.y }); + this.segments.push(this.series); - input.deltaX = prevDelta.x + (center.x - offset.x); - input.deltaY = prevDelta.y + (center.y - offset.y); -} + var streamEvent = StreamEvent.create('start', this._addContextToInfo(info)); -/** - * velocity is calculated every x ms - * @param {Object} session - * @param {Object} input - */ -function computeIntervalInputData(session, input) { - var last = session.lastInterval || input, - deltaTime = input.timeStamp - last.timeStamp, - velocity, velocityX, velocityY, direction; - - if (input.eventType != INPUT_CANCEL && (deltaTime > COMPUTE_INTERVAL || last.velocity === undefined)) { - var deltaX = input.deltaX - last.deltaX; - var deltaY = input.deltaY - last.deltaY; - - var v = getVelocity(deltaTime, deltaX, deltaY); - velocityX = v.x; - velocityY = v.y; - velocity = (abs(v.x) > abs(v.y)) ? v.x : v.y; - direction = getDirection(deltaX, deltaY); - - session.lastInterval = input; - } else { - // use latest velocity info if it doesn't overtake a minimum period - velocity = last.velocity; - velocityX = last.velocityX; - velocityY = last.velocityY; - direction = last.direction; + this.series.push(streamEvent); + return streamEvent; + } + }, { + key: 'push', + value: function push(info) { + var lastEvent = this.series.get(this.series.length - 1); + var streamEvent = StreamEvent.create('move', this._addContextToInfo(info), lastEvent); + + this.series.push(streamEvent); + return streamEvent; } + }, { + key: 'close', + value: function close(info) { + var _this = this; - input.velocity = velocity; - input.velocityX = velocityX; - input.velocityY = velocityY; - input.direction = direction; -} + this.active = false; + var lastEvent = this.series.get(this.series.length - 1); + var streamEvent = StreamEvent.create('end', this._addContextToInfo(info), lastEvent); -/** - * create a simple clone from the input used for storage of firstInput and firstMultiple - * @param {Object} input - * @returns {Object} clonedInputData - */ -function simpleCloneInputData(input) { - // make a simple copy of the pointers because we will get a reference if we don't - // we only need clientXY for the calculations - var pointers = []; - var i = 0; - while (i < input.pointers.length) { - pointers[i] = { - clientX: round(input.pointers[i].clientX), - clientY: round(input.pointers[i].clientY) - }; - i++; - } - - return { - timeStamp: now(), - pointers: pointers, - center: getCenter(pointers), - deltaX: input.deltaX, - deltaY: input.deltaY - }; -} + this.series.push(streamEvent); -/** - * get the center of all the pointers - * @param {Array} pointers - * @return {Object} center contains `x` and `y` properties - */ -function getCenter(pointers) { - var pointersLength = pointers.length; + this._isDestroying = true; + new MacroTask(function () { + _this.destroy(); + }); - // no need to loop when only one touch - if (pointersLength === 1) { - return { - x: round(pointers[0].clientX), - y: round(pointers[0].clientY) - }; + return streamEvent; } - - var x = 0, y = 0, i = 0; - while (i < pointersLength) { - x += pointers[i].clientX; - y += pointers[i].clientY; - i++; + }, { + key: 'silence', + value: function silence() { + var series = this.segments.get(0); + var down = series.get(0); + var initial = series.get(1); + + down.silence(); + initial.silence(); } - - return { - x: round(x / pointersLength), - y: round(y / pointersLength) - }; -} - -/** - * calculate the velocity between two points. unit is in px per ms. - * @param {Number} deltaTime - * @param {Number} x - * @param {Number} y - * @return {Object} velocity `x` and `y` - */ -function getVelocity(deltaTime, x, y) { - return { - x: x / deltaTime || 0, - y: y / deltaTime || 0 - }; -} - -/** - * get the direction between two points - * @param {Number} x - * @param {Number} y - * @return {Number} direction - */ -function getDirection(x, y) { - if (x === y) { - return DIRECTION_NONE; + }, { + key: 'split', + value: function split() { + var lastEvent = this.series.get(this.series.length - 1); + this.series = StreamSeries.create({ originX: lastEvent.x, originY: lastEvent.y }); + this.segments.push(this.series); } + }, { + key: 'destroy', + value: function destroy() { + if (!this._isDestroyed) { + this._isDestroyed = true; + this.series = undefined; + + this.segments.forEach(function (series) { + series.destroy(); + }); + this.segments = undefined; - if (abs(x) >= abs(y)) { - return x < 0 ? DIRECTION_LEFT : DIRECTION_RIGHT; + STREAM_POOL.push(this); + } } - return y < 0 ? DIRECTION_UP : DIRECTION_DOWN; -} - -/** - * calculate the absolute distance between two points - * @param {Object} p1 {x, y} - * @param {Object} p2 {x, y} - * @param {Array} [props] containing x and y keys - * @return {Number} distance - */ -function getDistance(p1, p2, props) { - if (!props) { - props = PROPS_XY; + }, { + key: '_addContextToInfo', + value: function _addContextToInfo(info) { + info.originX = this.originX; + info.originY = this.originY; + info.segmentOriginX = this.series.originX; + info.segmentOriginY = this.series.originY; + + return info; } - var x = p2[props[0]] - p1[props[0]], - y = p2[props[1]] - p1[props[1]]; + }], [{ + key: 'create', + value: function create(values) { + var stream = STREAM_POOL.pop(); - return Math.sqrt((x * x) + (y * y)); -} + if (stream) { + stream.init(values); + return stream; + } -/** - * calculate the angle between two coordinates - * @param {Object} p1 - * @param {Object} p2 - * @param {Array} [props] containing x and y keys - * @return {Number} angle - */ -function getAngle(p1, p2, props) { - if (!props) { - props = PROPS_XY; + return new Stream(values); } - var x = p2[props[0]] - p1[props[0]], - y = p2[props[1]] - p1[props[1]]; - return Math.atan2(y, x) * 180 / Math.PI; -} - -/** - * calculate the rotation degrees between two pointersets - * @param {Array} start array of pointers - * @param {Array} end array of pointers - * @return {Number} rotation - */ -function getRotation(start, end) { - return getAngle(end[1], end[0], PROPS_CLIENT_XY) + getAngle(start[1], start[0], PROPS_CLIENT_XY); -} - -/** - * calculate the scale factor between two pointersets - * no scale is 1, and goes down to 0 when pinched together, and bigger when pinched out - * @param {Array} start array of pointers - * @param {Array} end array of pointers - * @return {Number} scale - */ -function getScale(start, end) { - return getDistance(end[0], end[1], PROPS_CLIENT_XY) / getDistance(start[0], start[1], PROPS_CLIENT_XY); -} - -var MOUSE_INPUT_MAP = { - mousedown: INPUT_START, - mousemove: INPUT_MOVE, - mouseup: INPUT_END -}; - -var MOUSE_ELEMENT_EVENTS = 'mousedown'; -var MOUSE_WINDOW_EVENTS = 'mousemove mouseup'; + }]); + return Stream; +}(); + +// All Credit for this goes to the Ember.js Core Team + +// This exists because `Object.create(null)` is absurdly slow compared +// to `new EmptyObject()`. In either case, you want a null prototype +// when you're treating the object instances as arbitrary dictionaries +// and don't want your keys colliding with build-in methods on the +// default object prototype. + +var proto = Object.create(null, { + // without this, we will always still end up with (new + // EmptyObject()).constructor === Object + constructor: { + value: undefined, + enumerable: false, + writable: true + } +}); -/** - * Mouse events input - * @constructor - * @extends Input - */ -function MouseInput() { - this.evEl = MOUSE_ELEMENT_EVENTS; - this.evWin = MOUSE_WINDOW_EVENTS; +function EmptyObject() {} +EmptyObject.prototype = proto; - this.pressed = false; // mousedown state +var HashMap = function () { + function HashMap(entries) { + classCallCheck(this, HashMap); - Input.apply(this, arguments); -} + this._data = new EmptyObject(); -inherit(MouseInput, Input, { - /** - * handle mouse events - * @param {Object} ev - */ - handler: function MEhandler(ev) { - var eventType = MOUSE_INPUT_MAP[ev.type]; - - // on start we want to have the left mouse button down - if (eventType & INPUT_START && ev.button === 0) { - this.pressed = true; - } - - if (eventType & INPUT_MOVE && ev.which !== 1) { - eventType = INPUT_END; - } + if (entries) { + for (var i = 0; i < entries.length; i++) { + this.data[entries[i][0]] = entries[i][1]; + } + } + } - // mouse must be down - if (!this.pressed) { - return; + createClass(HashMap, [{ + key: 'forEach', + value: function forEach(cb) { + for (var key in this._data) { + // skip undefined + if (this._data[key] !== UNDEFINED_KEY) { + cb(this._data[key], key); } + } - if (eventType & INPUT_END) { - this.pressed = false; - } + return this; + } + }, { + key: 'get', + value: function get(key) { + var val = this._data[key]; - this.callback(this.manager, eventType, { - pointers: [ev], - changedPointers: [ev], - pointerType: INPUT_TYPE_MOUSE, - srcEvent: ev - }); + return val === UNDEFINED_KEY ? undefined : val; } -}); + }, { + key: 'set', + value: function set(key, value) { + this._data[key] = value; -var POINTER_INPUT_MAP = { - pointerdown: INPUT_START, - pointermove: INPUT_MOVE, - pointerup: INPUT_END, - pointercancel: INPUT_CANCEL, - pointerout: INPUT_CANCEL -}; + return this; + } + }, { + key: 'delete', + value: function _delete(key) { + this._data[key] = UNDEFINED_KEY; -// in IE10 the pointer types is defined as an enum -var IE10_POINTER_TYPE_ENUM = { - 2: INPUT_TYPE_TOUCH, - 3: INPUT_TYPE_PEN, - 4: INPUT_TYPE_MOUSE, - 5: INPUT_TYPE_KINECT // see https://twitter.com/jacobrossi/status/480596438489890816 -}; + return true; + } + }]); + return HashMap; +}(); -var POINTER_ELEMENT_EVENTS = 'pointerdown'; -var POINTER_WINDOW_EVENTS = 'pointermove pointerup pointercancel'; +var Input = function () { + function Input(element, manager) { + classCallCheck(this, Input); -// IE10 has prefixed support, and case-sensitive -if (window.MSPointerEvent && !window.PointerEvent) { - POINTER_ELEMENT_EVENTS = 'MSPointerDown'; - POINTER_WINDOW_EVENTS = 'MSPointerMove MSPointerUp MSPointerCancel'; -} + this.element = element; + this.handler = null; + this.handlerStack = []; -/** - * Pointer events input - * @constructor - * @extends Input - */ -function PointerEventInput() { - this.evEl = POINTER_ELEMENT_EVENTS; - this.evWin = POINTER_WINDOW_EVENTS; + this.attached = false; + this.streaming = false; + this.hasMoved = false; - Input.apply(this, arguments); + this.openStreams = 0; + this.streams = new HashMap(); + this._nextEvents = new HashMap(); - this.store = (this.manager.session.pointerEvents = []); -} + this._handlers = { start: null, update: null, end: null, interrupt: null }; + this.manager = manager; -inherit(PointerEventInput, Input, { - /** - * handle mouse events - * @param {Object} ev - */ - handler: function PEhandler(ev) { - var store = this.store; - var removePointer = false; - - var eventTypeNormalized = ev.type.toLowerCase().replace('ms', ''); - var eventType = POINTER_INPUT_MAP[eventTypeNormalized]; - var pointerType = IE10_POINTER_TYPE_ENUM[ev.pointerType] || ev.pointerType; - - var isTouch = (pointerType == INPUT_TYPE_TOUCH); - - // get index of the event in the store - var storeIndex = inArray(store, ev.pointerId, 'pointerId'); - - // start and mouse must be down - if (eventType & INPUT_START && (ev.button === 0 || isTouch)) { - if (storeIndex < 0) { - store.push(ev); - storeIndex = store.length - 1; - } - } else if (eventType & (INPUT_END | INPUT_CANCEL)) { - removePointer = true; - } + this.attach(); + } - // it not found, so the pointer hasn't been down (so it's probably a hover) - if (storeIndex < 0) { - return; - } + createClass(Input, [{ + key: '_bind', + value: function _bind(name) { + var _name; - // update the event in the store - store[storeIndex] = ev; + var _handlers = this._handlers; - this.callback(this.manager, eventType, { - pointers: store, - changedPointers: [ev], - pointerType: pointerType, - srcEvent: ev - }); + for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { + args[_key - 1] = arguments[_key]; + } - if (removePointer) { - // remove from the store - store.splice(storeIndex, 1); - } + return _handlers[name] = (_name = this[name]).bind.apply(_name, [this].concat(args)); } -}); - -var SINGLE_TOUCH_INPUT_MAP = { - touchstart: INPUT_START, - touchmove: INPUT_MOVE, - touchend: INPUT_END, - touchcancel: INPUT_CANCEL -}; - -var SINGLE_TOUCH_TARGET_EVENTS = 'touchstart'; -var SINGLE_TOUCH_WINDOW_EVENTS = 'touchstart touchmove touchend touchcancel'; + }, { + key: 'extractThen', + value: function extractThen(name, event) { + this[name](this.extract(event)); + } + }, { + key: 'extractManyThen', + value: function extractManyThen(name, event) { + this.extractMany(event).forEach(this[name].bind(this)); + } + }, { + key: 'start', + value: function start(eventInfo) { + var stream = Stream.create({ + pointerId: eventInfo.pointerId, + originX: eventInfo.x, + originY: eventInfo.y + }); -/** - * Touch events input - * @constructor - * @extends Input - */ -function SingleTouchInput() { - this.evTarget = SINGLE_TOUCH_TARGET_EVENTS; - this.evWin = SINGLE_TOUCH_WINDOW_EVENTS; - this.started = false; + var streams = this.streams; - Input.apply(this, arguments); -} -inherit(SingleTouchInput, Input, { - handler: function TEhandler(ev) { - var type = SINGLE_TOUCH_INPUT_MAP[ev.type]; + streams.forEach(function (stream) { + return stream.split(); + }); - // should we handle the touch events? - if (type === INPUT_START) { - this.started = true; - } + this.streaming = true; - if (!this.started) { - return; - } + this.openStreams++; + streams.set(stream.pointerId, stream); + // console.log('opening new stream'); + var streamEvent = stream.open(eventInfo); - var touches = normalizeSingleTouches.call(this, ev, type); + if (this.handler) { + this.handlerStack.push(this.handler); + this.handler = null; + } - // when done, reset the started state - if (type & (INPUT_END | INPUT_CANCEL) && touches[0].length - touches[1].length === 0) { - this.started = false; - } + this.manager.recognize(this, streams, stream, streamEvent); - this.callback(this.manager, type, { - pointers: touches[0], - changedPointers: touches[1], - pointerType: INPUT_TYPE_TOUCH, - srcEvent: ev - }); + this._poll(); } -}); - -/** - * @this {TouchInput} - * @param {Object} ev - * @param {Number} type flag - * @returns {undefined|Array} [all, changed] - */ -function normalizeSingleTouches(ev, type) { - var all = toArray(ev.touches); - var changed = toArray(ev.changedTouches); - - if (type & (INPUT_END | INPUT_CANCEL)) { - all = uniqueArray(all.concat(changed), 'identifier', true); + }, { + key: 'trigger', + value: function trigger(stream, streamEvent) { + if (this.handler) { + this.handler.recognize(this, this.streams, stream, streamEvent); + } else { + this.manager.recognize(this, this.streams, stream, streamEvent); + } } + }, { + key: '_update', + value: function _update(eventInfo) { + // console.log('updating'); + var streams = this.streams; - return [all, changed]; -} + var stream = streams.get(eventInfo.pointerId); + var streamEvent = void 0; -var TOUCH_INPUT_MAP = { - touchstart: INPUT_START, - touchmove: INPUT_MOVE, - touchend: INPUT_END, - touchcancel: INPUT_CANCEL -}; + if (!this.streaming) { + if (!this.handler) {} + // console.log('closing stream'); + streamEvent = stream.close(eventInfo); -var TOUCH_TARGET_EVENTS = 'touchstart touchmove touchend touchcancel'; + this.hasMoved = false; + this.trigger(stream, streamEvent); -/** - * Multi-user touch events input - * @constructor - * @extends Input - */ -function TouchInput() { - this.evTarget = TOUCH_TARGET_EVENTS; - this.targetIds = {}; + var wasRecognizing = this.handler; - Input.apply(this, arguments); -} + this.handler = null; -inherit(TouchInput, Input, { - handler: function MTEhandler(ev) { - var type = TOUCH_INPUT_MAP[ev.type]; - var touches = getTouches.call(this, ev, type); - if (!touches) { - return; + // vacate this stream + // console.log('removing stream'); + streams.delete(stream.pointerId); + this.openStreams--; + + if (wasRecognizing && this.openStreams === 0) { + this.manager.endInputRecognition(); } + } else { + streamEvent = stream.push(eventInfo); - this.callback(this.manager, type, { - pointers: touches[0], - changedPointers: touches[1], - pointerType: INPUT_TYPE_TOUCH, - srcEvent: ev - }); + this.trigger(stream, streamEvent); + } } -}); + }, { + key: '_poll', + value: function _poll() { + var _this = this; + + return void requestAnimationFrame(function () { + _this._nextEvents.forEach(function (event, key) { + _this._update(event); + _this._nextEvents.delete(key); + }); -/** - * @this {TouchInput} - * @param {Object} ev - * @param {Number} type flag - * @returns {undefined|Array} [all, changed] - */ -function getTouches(ev, type) { - var allTouches = toArray(ev.touches); - var targetIds = this.targetIds; - - // when there is only one touch, the process can be simplified - if (type & (INPUT_START | INPUT_MOVE) && allTouches.length === 1) { - targetIds[allTouches[0].identifier] = true; - return [allTouches, allTouches]; - } - - var i, - targetTouches, - changedTouches = toArray(ev.changedTouches), - changedTargetTouches = [], - target = this.target; - - // get target touches from touches - targetTouches = allTouches.filter(function(touch) { - return hasParent(touch.target, target); - }); - - // collect touches - if (type === INPUT_START) { - i = 0; - while (i < targetTouches.length) { - targetIds[targetTouches[i].identifier] = true; - i++; + if (_this.streaming) { + _this._poll(); } + }); } + }, { + key: 'update', + value: function update(eventInfo) { + if (!this.streaming) { + return; + } - // filter changed touches to only contain touches that exist in the collected target ids - i = 0; - while (i < changedTouches.length) { - if (targetIds[changedTouches[i].identifier]) { - changedTargetTouches.push(changedTouches[i]); - } + this._nextEvents.set(eventInfo.pointerId, eventInfo); - // cleanup removed touches - if (type & (INPUT_END | INPUT_CANCEL)) { - delete targetIds[changedTouches[i].identifier]; - } - i++; + if (!this.hasMoved) { + this.hasMoved = true; + this._update(eventInfo); + } } - - if (!changedTargetTouches.length) { - return; + }, { + key: '_close', + value: function _close(event) { + if (this.streaming) { + // console.log('received close event'); + this.streaming = false; + this._nextEvents.set(event.pointerId, event); + } } - - return [ - // merge targetTouches with changedTargetTouches so it contains ALL touches, including 'end' and 'cancel' - uniqueArray(targetTouches.concat(changedTargetTouches), 'identifier', true), - changedTargetTouches - ]; -} - -/** - * Combined touch and mouse input - * - * Touch has a higher priority then mouse, and while touching no mouse events are allowed. - * This because touch devices also emit mouse events while doing a touch. - * - * @constructor - * @extends Input - */ - -var DEDUP_TIMEOUT = 2500; -var DEDUP_DISTANCE = 25; - -function TouchMouseInput() { - Input.apply(this, arguments); - - var handler = bindFn(this.handler, this); - this.touch = new TouchInput(this.manager, handler); - this.mouse = new MouseInput(this.manager, handler); - - this.primaryTouch = null; - this.lastTouches = []; -} - -inherit(TouchMouseInput, Input, { - /** - * handle mouse and touch events - * @param {Hammer} manager - * @param {String} inputEvent - * @param {Object} inputData - */ - handler: function TMEhandler(manager, inputEvent, inputData) { - var isTouch = (inputData.pointerType == INPUT_TYPE_TOUCH), - isMouse = (inputData.pointerType == INPUT_TYPE_MOUSE); - - if (isMouse && inputData.sourceCapabilities && inputData.sourceCapabilities.firesTouchEvents) { - return; - } - - // when we're in a touch event, record touches to de-dupe synthetic mouse event - if (isTouch) { - recordTouches.call(this, inputEvent, inputData); - } else if (isMouse && isSyntheticEvent.call(this, inputData)) { - return; - } - - this.callback(manager, inputEvent, inputData); - }, - - /** - * remove the event listeners - */ - destroy: function destroy() { - this.touch.destroy(); - this.mouse.destroy(); + }, { + key: 'end', + value: function end(event) { + if (this.streaming) { + this._close(event); + } } -}); - -function recordTouches(eventType, eventData) { - if (eventType & INPUT_START) { - this.primaryTouch = eventData.changedPointers[0].identifier; - setLastTouch.call(this, eventData); - } else if (eventType & (INPUT_END | INPUT_CANCEL)) { - setLastTouch.call(this, eventData); + }, { + key: 'interrupt', + value: function interrupt(event) { + if (this.streaming) { + this._close(event); + } } -} - -function setLastTouch(eventData) { - var touch = eventData.changedPointers[0]; - - if (touch.identifier === this.primaryTouch) { - var lastTouch = {x: touch.clientX, y: touch.clientY}; - this.lastTouches.push(lastTouch); - var lts = this.lastTouches; - var removeLastTouch = function() { - var i = lts.indexOf(lastTouch); - if (i > -1) { - lts.splice(i, 1); - } - }; - setTimeout(removeLastTouch, DEDUP_TIMEOUT); + }, { + key: 'extract', + value: function extract() { + throw new Error('Interface Method Not Implemented'); } -} - -function isSyntheticEvent(eventData) { - var x = eventData.srcEvent.clientX, y = eventData.srcEvent.clientY; - for (var i = 0; i < this.lastTouches.length; i++) { - var t = this.lastTouches[i]; - var dx = Math.abs(x - t.x), dy = Math.abs(y - t.y); - if (dx <= DEDUP_DISTANCE && dy <= DEDUP_DISTANCE) { - return true; - } + }, { + key: 'extractMany', + value: function extractMany() { + throw new Error('Interface Method Not Implemented'); } - return false; -} - -var PREFIXED_TOUCH_ACTION = prefixed(TEST_ELEMENT.style, 'touchAction'); -var NATIVE_TOUCH_ACTION = PREFIXED_TOUCH_ACTION !== undefined; - -// magical touchAction value -var TOUCH_ACTION_COMPUTE = 'compute'; -var TOUCH_ACTION_AUTO = 'auto'; -var TOUCH_ACTION_MANIPULATION = 'manipulation'; // not implemented -var TOUCH_ACTION_NONE = 'none'; -var TOUCH_ACTION_PAN_X = 'pan-x'; -var TOUCH_ACTION_PAN_Y = 'pan-y'; -var TOUCH_ACTION_MAP = getTouchActionProps(); - -/** - * Touch Action - * sets the touchAction property or uses the js alternative - * @param {Manager} manager - * @param {String} value - * @constructor - */ -function TouchAction(manager, value) { - this.manager = manager; - this.set(value); -} - -TouchAction.prototype = { - /** - * set the touchAction value on the element or enable the polyfill - * @param {String} value - */ - set: function(value) { - // find out the touch-action by the event handlers - if (value == TOUCH_ACTION_COMPUTE) { - value = this.compute(); - } - - if (NATIVE_TOUCH_ACTION && this.manager.element.style && TOUCH_ACTION_MAP[value]) { - this.manager.element.style[PREFIXED_TOUCH_ACTION] = value; - } - this.actions = value.toLowerCase().trim(); - }, - - /** - * just re-set the touchAction value - */ - update: function() { - this.set(this.manager.options.touchAction); - }, - - /** - * compute the value for the touchAction property based on the recognizer's settings - * @returns {String} value - */ - compute: function() { - var actions = []; - each(this.manager.recognizers, function(recognizer) { - if (boolOrFn(recognizer.options.enable, [recognizer])) { - actions = actions.concat(recognizer.getTouchAction()); - } - }); - return cleanTouchActions(actions.join(' ')); - }, - - /** - * this method is called on each input cycle and provides the preventing of the browser behavior - * @param {Object} input - */ - preventDefaults: function(input) { - var srcEvent = input.srcEvent; - var direction = input.offsetDirection; - - // if the touch action did prevented once this session - if (this.manager.session.prevented) { - srcEvent.preventDefault(); - return; - } + }, { + key: 'attach', + value: function attach() { + throw new Error('Interface Method Not Implemented'); + } + }, { + key: 'deattach', + value: function deattach() { + throw new Error('Interface Method Not Implemented'); + } + }, { + key: 'destroy', + value: function destroy() { + this.deattach(); + this.manager = null; + this.element = null; + this.streams = null; + this.handler = null; + } + }]); + return Input; +}(); - var actions = this.actions; - var hasNone = inStr(actions, TOUCH_ACTION_NONE) && !TOUCH_ACTION_MAP[TOUCH_ACTION_NONE]; - var hasPanY = inStr(actions, TOUCH_ACTION_PAN_Y) && !TOUCH_ACTION_MAP[TOUCH_ACTION_PAN_Y]; - var hasPanX = inStr(actions, TOUCH_ACTION_PAN_X) && !TOUCH_ACTION_MAP[TOUCH_ACTION_PAN_X]; +var Layer = function () { + function Layer(element) { + classCallCheck(this, Layer); - if (hasNone) { - //do not prevent defaults if this is a tap gesture + this.element = element; + this.recognizers = []; + this._handlers = {}; + } - var isTapPointer = input.pointers.length === 1; - var isTapMovement = input.distance < 2; - var isTapTouchTime = input.deltaTime < 250; + createClass(Layer, [{ + key: 'recognize', + value: function recognize(input, streams, stream, streamEvent) { + var recognizers = this.recognizers; - if (isTapPointer && isTapMovement && isTapTouchTime) { - return; - } - } - if (hasPanX && hasPanY) { - // `pan-x pan-y` means browser handles all scrolling/panning, do not prevent - return; - } + for (var i = 0; i < recognizers.length; i++) { + var recognizer = recognizers[i]; - if (hasNone || - (hasPanY && direction & DIRECTION_HORIZONTAL) || - (hasPanX && direction & DIRECTION_VERTICAL)) { - return this.preventSrc(srcEvent); + if (recognizer.recognize(input, streams, stream, streamEvent)) { + input.handler = recognizer; + return true; } - }, + } - /** - * call preventDefault to prevent the browser's default behavior (scrolling in most cases) - * @param {Object} srcEvent - */ - preventSrc: function(srcEvent) { - this.manager.session.prevented = true; - srcEvent.preventDefault(); + return false; } -}; - -/** - * when the touchActions are collected they are not a valid value, so we need to clean things up. * - * @param {String} actions - * @returns {*} - */ -function cleanTouchActions(actions) { - // none - if (inStr(actions, TOUCH_ACTION_NONE)) { - return TOUCH_ACTION_NONE; + }, { + key: 'addRecognizer', + value: function addRecognizer(recognizerInstance) { + recognizerInstance.layer = this; + this.recognizers.push(recognizerInstance); } + }, { + key: 'emit', + value: function emit(e) { + var name = e.name; - var hasPanX = inStr(actions, TOUCH_ACTION_PAN_X); - var hasPanY = inStr(actions, TOUCH_ACTION_PAN_Y); + var handlers = (this._handlers['*'] || []).concat(this._handlers[name] || []); - // if both pan-x and pan-y are set (different recognizers - // for different directions, e.g. horizontal pan but vertical swipe?) - // we need none (as otherwise with pan-x pan-y combined none of these - // recognizers will work, since the browser would handle all panning - if (hasPanX && hasPanY) { - return TOUCH_ACTION_NONE; + for (var i = 0; i < handlers.length; i++) { + handlers[i].call(null, e); + } } - - // pan-x OR pan-y - if (hasPanX || hasPanY) { - return hasPanX ? TOUCH_ACTION_PAN_X : TOUCH_ACTION_PAN_Y; + }, { + key: 'on', + value: function on(event, handler) { + this._handlers[event] = this._handlers[event] || []; + this._handlers[event].push(handler); } - - // manipulation - if (inStr(actions, TOUCH_ACTION_MANIPULATION)) { - return TOUCH_ACTION_MANIPULATION; + }, { + key: 'off', + value: function off() {} + }]); + return Layer; +}(); + +var TouchInput = function (_Input) { + inherits(TouchInput, _Input); + + function TouchInput() { + classCallCheck(this, TouchInput); + return possibleConstructorReturn(this, Object.getPrototypeOf(TouchInput).apply(this, arguments)); + } + + createClass(TouchInput, [{ + key: 'extract', + value: function extract(event) { + return extractTouch(event.changedTouches[0], event); } - - return TOUCH_ACTION_AUTO; -} - -function getTouchActionProps() { - if (!NATIVE_TOUCH_ACTION) { - return false; + }, { + key: 'extractMany', + value: function extractMany(event) { + return Array.prototype.slice.call(event.changedTouches).map(function (touch) { + return extractTouch(touch, event); + }); } - var touchMap = {}; - var cssSupports = window.CSS && window.CSS.supports; - ['auto', 'manipulation', 'pan-y', 'pan-x', 'pan-x pan-y', 'none'].forEach(function(val) { + }, { + key: 'attach', + value: function attach() { + if (this.attached) { + return; + } + var element = this.element; - // If css.supports is not supported but there is native touch-action assume it supports - // all values. This is the case for IE 10 and 11. - touchMap[val] = cssSupports ? window.CSS.supports('touch-action', val) : true; - }); - return touchMap; -} -/** - * Recognizer flow explained; * - * All recognizers have the initial state of POSSIBLE when a input session starts. - * The definition of a input session is from the first input until the last input, with all it's movement in it. * - * Example session for mouse-input: mousedown -> mousemove -> mouseup - * - * On each recognizing cycle (see Manager.recognize) the .recognize() method is executed - * which determines with state it should be. - * - * If the recognizer has the state FAILED, CANCELLED or RECOGNIZED (equals ENDED), it is reset to - * POSSIBLE to give it another change on the next cycle. - * - * Possible - * | - * +-----+---------------+ - * | | - * +-----+-----+ | - * | | | - * Failed Cancelled | - * +-------+------+ - * | | - * Recognized Began - * | - * Changed - * | - * Ended/Recognized - */ -var STATE_POSSIBLE = 1; -var STATE_BEGAN = 2; -var STATE_CHANGED = 4; -var STATE_ENDED = 8; -var STATE_RECOGNIZED = STATE_ENDED; -var STATE_CANCELLED = 16; -var STATE_FAILED = 32; + element.addEventListener('touchstart', this._bind('extractThen', 'start'), true); + element.addEventListener('touchend', this._bind('extractThen', 'end'), true); + element.addEventListener('touchcancel', this._bind('extractThen', 'interrupt'), true); + element.addEventListener('touchmove', this._bind('extractManyThen', 'update'), true); -/** - * Recognizer - * Every recognizer needs to extend from this class. - * @constructor - * @param {Object} options - */ -function Recognizer(options) { - this.options = assign({}, this.defaults, options || {}); + this.attached = true; + } + }, { + key: 'deattach', + value: function deattach() { + if (!this.attached) { + return; + } + var element = this.element; + var _handlers = this._handlers; - this.id = uniqueId(); - this.manager = null; + element.removeEventListener('touchstart', _handlers.start, true); + element.removeEventListener('touchend', _handlers.end, true); + element.removeEventListener('touchcancel', _handlers.interrupt, true); + element.removeEventListener('touchmove', _handlers.update, true); + } + }]); + return TouchInput; +}(Input); - // default is enable true - this.options.enable = ifUndefined(this.options.enable, true); +function extractTouch(touch, event) { + return { + pointerId: touch.identifier, + x: touch.clientX, + y: touch.clientY, + event: event + }; +} - this.state = STATE_POSSIBLE; +var supportsPassive = false; - this.simultaneous = {}; - this.requireFail = []; -} +try { + var opts = Object.defineProperty({}, 'passive', { + get: function get() { + supportsPassive = true; + } + }); + + window.addEventListener('test', null, opts); +} catch (e) {} + +var SUPPORTS_PASSIVE = supportsPassive; + +var MouseInput = function (_Input) { + inherits(MouseInput, _Input); + + function MouseInput() { + classCallCheck(this, MouseInput); + return possibleConstructorReturn(this, Object.getPrototypeOf(MouseInput).apply(this, arguments)); + } + + createClass(MouseInput, [{ + key: 'extract', + value: function extract(event) { + return { + pointerId: 'MOUSE_POINTER', + x: event.clientX, + y: event.clientY, + event: event + }; + } + }, { + key: 'attach', + value: function attach() { + if (this.attached) { + return; + } + var element = this.element; -Recognizer.prototype = { - /** - * @virtual - * @type {Object} - */ - defaults: {}, - - /** - * set options - * @param {Object} options - * @return {Recognizer} - */ - set: function(options) { - assign(this.options, options); - - // also update the touchAction, in case something changed about the directions/enabled state - this.manager && this.manager.touchAction.update(); - return this; - }, - - /** - * recognize simultaneous with an other recognizer. - * @param {Recognizer} otherRecognizer - * @returns {Recognizer} this - */ - recognizeWith: function(otherRecognizer) { - if (invokeArrayArg(otherRecognizer, 'recognizeWith', this)) { - return this; - } - var simultaneous = this.simultaneous; - otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this); - if (!simultaneous[otherRecognizer.id]) { - simultaneous[otherRecognizer.id] = otherRecognizer; - otherRecognizer.recognizeWith(this); - } - return this; - }, - - /** - * drop the simultaneous link. it doesnt remove the link on the other recognizer. - * @param {Recognizer} otherRecognizer - * @returns {Recognizer} this - */ - dropRecognizeWith: function(otherRecognizer) { - if (invokeArrayArg(otherRecognizer, 'dropRecognizeWith', this)) { - return this; - } + var opts = SUPPORTS_PASSIVE ? { capture: true, passive: true } : true; - otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this); - delete this.simultaneous[otherRecognizer.id]; - return this; - }, - - /** - * recognizer can only run when an other is failing - * @param {Recognizer} otherRecognizer - * @returns {Recognizer} this - */ - requireFailure: function(otherRecognizer) { - if (invokeArrayArg(otherRecognizer, 'requireFailure', this)) { - return this; - } + element.addEventListener('mousedown', this._bind('extractThen', 'start'), opts); + element.addEventListener('mouseup', this._bind('extractThen', 'end'), opts); + element.addEventListener('mouseexit', this._bind('extractThen', 'interrupt'), opts); + element.addEventListener('mousemove', this._bind('extractThen', 'update'), opts); - var requireFail = this.requireFail; - otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this); - if (inArray(requireFail, otherRecognizer) === -1) { - requireFail.push(otherRecognizer); - otherRecognizer.requireFailure(this); - } - return this; - }, - - /** - * drop the requireFailure link. it does not remove the link on the other recognizer. - * @param {Recognizer} otherRecognizer - * @returns {Recognizer} this - */ - dropRequireFailure: function(otherRecognizer) { - if (invokeArrayArg(otherRecognizer, 'dropRequireFailure', this)) { - return this; - } + this.attached = true; + } + }, { + key: 'deattach', + value: function deattach() { + if (this.attached) { + return; + } + var element = this.element; + var _handlers = this._handlers; - otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this); - var index = inArray(this.requireFail, otherRecognizer); - if (index > -1) { - this.requireFail.splice(index, 1); - } - return this; - }, - - /** - * has require failures boolean - * @returns {boolean} - */ - hasRequireFailures: function() { - return this.requireFail.length > 0; - }, - - /** - * if the recognizer can recognize simultaneous with an other recognizer - * @param {Recognizer} otherRecognizer - * @returns {Boolean} - */ - canRecognizeWith: function(otherRecognizer) { - return !!this.simultaneous[otherRecognizer.id]; - }, - - /** - * You should use `tryEmit` instead of `emit` directly to check - * that all the needed recognizers has failed before emitting. - * @param {Object} input - */ - emit: function(input) { - var self = this; - var state = this.state; - - function emit(event) { - self.manager.emit(event, input); - } - // 'panstart' and 'panmove' - if (state < STATE_ENDED) { - emit(self.options.event + stateStr(state)); - } + var opts = SUPPORTS_PASSIVE ? { capture: true, passive: true } : true; - emit(self.options.event); // simple 'eventName' events + element.removeEventListener('mousedown', _handlers.start, opts); + element.removeEventListener('mouseup', _handlers.end, opts); + element.removeEventListener('mouseexit', _handlers.interrupt, opts); + element.removeEventListener('mousemove', _handlers.update, opts); + } + }]); + return MouseInput; +}(Input); - if (input.additionalEvent) { // additional event(panleft, panright, pinchin, pinchout...) - emit(input.additionalEvent); - } +// import PointerInput from './inputs/pointer'; - // panend and pancancel - if (state >= STATE_ENDED) { - emit(self.options.event + stateStr(state)); - } - }, - - /** - * Check that all the require failure recognizers has failed, - * if true, it emits a gesture event, - * otherwise, setup the state to FAILED. - * @param {Object} input - */ - tryEmit: function(input) { - if (this.canEmit()) { - return this.emit(input); - } - // it's failing anyway - this.state = STATE_FAILED; - }, - - /** - * can we emit? - * @returns {boolean} - */ - canEmit: function() { - var i = 0; - while (i < this.requireFail.length) { - if (!(this.requireFail[i].state & (STATE_FAILED | STATE_POSSIBLE))) { - return false; - } - i++; - } - return true; - }, - - /** - * update the recognizer - * @param {Object} inputData - */ - recognize: function(inputData) { - // make a new copy of the inputData - // so we can change the inputData without messing up the other recognizers - var inputDataClone = assign({}, inputData); - - // is is enabled and allow recognizing? - if (!boolOrFn(this.options.enable, [this, inputDataClone])) { - this.reset(); - this.state = STATE_FAILED; - return; - } +var MAY_SUPPORT_TOUCH = 'ontouchstart' in window || // html5 browsers +navigator.maxTouchPoints > 0 || // future IE +navigator.msMaxTouchPoints > 0; // current IE10 - // reset when we've reached the end - if (this.state & (STATE_RECOGNIZED | STATE_CANCELLED | STATE_FAILED)) { - this.state = STATE_POSSIBLE; - } +var MAY_SUPPORT_MOUSE = true; - this.state = this.process(inputDataClone); +// const SUPPORT_POINTER_EVENTS = prefixed(window, 'PointerEvent') !== undefined; - // the recognizer has recognized a gesture - // so trigger an event - if (this.state & (STATE_BEGAN | STATE_CHANGED | STATE_ENDED | STATE_CANCELLED)) { - this.tryEmit(inputDataClone); - } - }, - - /** - * return the state of the recognizer - * the actual recognizing happens in this method - * @virtual - * @param {Object} inputData - * @returns {Const} STATE - */ - process: function(inputData) { }, // jshint ignore:line - - /** - * return the preferred touch-action - * @virtual - * @returns {Array} - */ - getTouchAction: function() { }, - - /** - * called when the gesture isn't allowed to recognize - * like when another is being recognized or it is disabled - * @virtual - */ - reset: function() { } -}; +function availableInputs() { + var inputs = {}; -/** - * get a usable string, used as event postfix - * @param {Const} state - * @returns {String} state - */ -function stateStr(state) { - if (state & STATE_CANCELLED) { - return 'cancel'; - } else if (state & STATE_ENDED) { - return 'end'; - } else if (state & STATE_CHANGED) { - return 'move'; - } else if (state & STATE_BEGAN) { - return 'start'; - } - return ''; -} + if (MAY_SUPPORT_MOUSE) { + inputs.mouse = MouseInput; + } -/** - * direction cons to string - * @param {Const} direction - * @returns {String} - */ -function directionStr(direction) { - if (direction == DIRECTION_DOWN) { - return 'down'; - } else if (direction == DIRECTION_UP) { - return 'up'; - } else if (direction == DIRECTION_LEFT) { - return 'left'; - } else if (direction == DIRECTION_RIGHT) { - return 'right'; - } - return ''; -} + if (MAY_SUPPORT_TOUCH) { + inputs.touch = TouchInput; + } -/** - * get a recognizer by name if it is bound to a manager - * @param {Recognizer|String} otherRecognizer - * @param {Recognizer} recognizer - * @returns {Recognizer} - */ -function getRecognizerByNameIfManager(otherRecognizer, recognizer) { - var manager = recognizer.manager; - if (manager) { - return manager.get(otherRecognizer); - } - return otherRecognizer; + return inputs; } /** - * This recognizer is just used as a base for the simple attribute recognizers. - * @constructor - * @extends Recognizer + * @private + * extend object. + * means that properties in dest will be overwritten by the ones in src. + * @param {Object} target + * @param {...Object} objects_to_assign + * @returns {Object} target */ -function AttrRecognizer() { - Recognizer.apply(this, arguments); -} +var assign = void 0; +if (typeof Object.assign !== 'function') { + assign = function assign(target) { + if (target === undefined || target === null) { + throw new TypeError('Cannot convert undefined or null to object'); + } -inherit(AttrRecognizer, Recognizer, { - /** - * @namespace - * @memberof AttrRecognizer - */ - defaults: { - /** - * @type {Number} - * @default 1 - */ - pointers: 1 - }, - - /** - * Used to check if it the recognizer receives valid input, like input.distance > 10. - * @memberof AttrRecognizer - * @param {Object} input - * @returns {Boolean} recognized - */ - attrTest: function(input) { - var optionPointers = this.options.pointers; - return optionPointers === 0 || input.pointers.length === optionPointers; - }, - - /** - * Process the input and return the state for the recognizer - * @memberof AttrRecognizer - * @param {Object} input - * @returns {*} State - */ - process: function(input) { - var state = this.state; - var eventType = input.eventType; - - var isRecognized = state & (STATE_BEGAN | STATE_CHANGED); - var isValid = this.attrTest(input); - - // on cancel input and we've recognized before, return STATE_CANCELLED - if (isRecognized && (eventType & INPUT_CANCEL || !isValid)) { - return state | STATE_CANCELLED; - } else if (isRecognized || isValid) { - if (eventType & INPUT_END) { - return state | STATE_ENDED; - } else if (!(state & STATE_BEGAN)) { - return STATE_BEGAN; - } - return state | STATE_CHANGED; + var output = Object(target); + for (var index = 1; index < arguments.length; index++) { + var source = arguments[index]; + if (source !== undefined && source !== null) { + for (var nextKey in source) { + if (source.hasOwnProperty(nextKey)) { + output[nextKey] = source[nextKey]; + } } - return STATE_FAILED; + } } -}); - -/** - * Pan - * Recognized when the pointer is down and moved in the allowed direction. - * @constructor - * @extends AttrRecognizer - */ -function PanRecognizer() { - AttrRecognizer.apply(this, arguments); - - this.pX = null; - this.pY = null; + return output; + }; +} else { + assign = Object.assign; } -inherit(PanRecognizer, AttrRecognizer, { - /** - * @namespace - * @memberof PanRecognizer - */ - defaults: { - event: 'pan', - threshold: 10, - pointers: 1, - direction: DIRECTION_ALL - }, - - getTouchAction: function() { - var direction = this.options.direction; - var actions = []; - if (direction & DIRECTION_HORIZONTAL) { - actions.push(TOUCH_ACTION_PAN_Y); - } - if (direction & DIRECTION_VERTICAL) { - actions.push(TOUCH_ACTION_PAN_X); - } - return actions; - }, - - directionTest: function(input) { - var options = this.options; - var hasMoved = true; - var distance = input.distance; - var direction = input.direction; - var x = input.deltaX; - var y = input.deltaY; - - // lock to axis? - if (!(direction & options.direction)) { - if (options.direction & DIRECTION_HORIZONTAL) { - direction = (x === 0) ? DIRECTION_NONE : (x < 0) ? DIRECTION_LEFT : DIRECTION_RIGHT; - hasMoved = x != this.pX; - distance = Math.abs(input.deltaX); - } else { - direction = (y === 0) ? DIRECTION_NONE : (y < 0) ? DIRECTION_UP : DIRECTION_DOWN; - hasMoved = y != this.pY; - distance = Math.abs(input.deltaY); - } - } - input.direction = direction; - return hasMoved && distance > options.threshold && direction & options.direction; - }, +var assign$1 = assign; - attrTest: function(input) { - return AttrRecognizer.prototype.attrTest.call(this, input) && - (this.state & STATE_BEGAN || (!(this.state & STATE_BEGAN) && this.directionTest(input))); - }, +var DEFAULT_OPTIONS = { + inputs: availableInputs() +}; - emit: function(input) { +var Manager = function () { + function Manager(rootElement, options) { + classCallCheck(this, Manager); - this.pX = input.deltaX; - this.pY = input.deltaY; + this.rootElement = rootElement || window; + this.layers = new WeakMap(); + this._recognizedInputs = 0; + this.isRecognizing = false; - var direction = directionStr(input.direction); + this.inputs = {}; + this.options = assign$1({}, DEFAULT_OPTIONS, options || {}); - if (direction) { - input.additionalEvent = this.options.event + direction; - } - this._super.emit.call(this, input); - } -}); + if (this.options.inputs) { + var inputs = Object.keys(this.options.inputs); -/** - * Pinch - * Recognized when two or more pointers are moving toward (zoom-in) or away from each other (zoom-out). - * @constructor - * @extends AttrRecognizer - */ -function PinchRecognizer() { - AttrRecognizer.apply(this, arguments); -} + for (var i = 0; i < inputs.length; i++) { + var name = inputs[i]; + var InputClass = this.options.inputs[name]; -inherit(PinchRecognizer, AttrRecognizer, { - /** - * @namespace - * @memberof PinchRecognizer - */ - defaults: { - event: 'pinch', - threshold: 0, - pointers: 2 - }, - - getTouchAction: function() { - return [TOUCH_ACTION_NONE]; - }, - - attrTest: function(input) { - return this._super.attrTest.call(this, input) && - (Math.abs(input.scale - 1) > this.options.threshold || this.state & STATE_BEGAN); - }, - - emit: function(input) { - if (input.scale !== 1) { - var inOut = input.scale < 1 ? 'in' : 'out'; - input.additionalEvent = this.options.event + inOut; - } - this._super.emit.call(this, input); + this.registerInput(name, InputClass); + } } -}); + } -/** - * Press - * Recognized when the pointer is down for x ms without any movement. - * @constructor - * @extends Recognizer - */ -function PressRecognizer() { - Recognizer.apply(this, arguments); - - this._timer = null; - this._input = null; -} - -inherit(PressRecognizer, Recognizer, { - /** - * @namespace - * @memberof PressRecognizer - */ - defaults: { - event: 'press', - pointers: 1, - time: 251, // minimal time of the pointer to be pressed - threshold: 9 // a minimal movement is ok, but keep it low - }, - - getTouchAction: function() { - return [TOUCH_ACTION_AUTO]; - }, - - process: function(input) { - var options = this.options; - var validPointers = input.pointers.length === options.pointers; - var validMovement = input.distance < options.threshold; - var validTime = input.deltaTime > options.time; - - this._input = input; - - // we only allow little movement - // and we've reached an end event, so a tap is possible - if (!validMovement || !validPointers || (input.eventType & (INPUT_END | INPUT_CANCEL) && !validTime)) { - this.reset(); - } else if (input.eventType & INPUT_START) { - this.reset(); - this._timer = setTimeoutContext(function() { - this.state = STATE_RECOGNIZED; - this.tryEmit(); - }, options.time, this); - } else if (input.eventType & INPUT_END) { - return STATE_RECOGNIZED; - } - return STATE_FAILED; - }, - - reset: function() { - clearTimeout(this._timer); - }, - - emit: function(input) { - if (this.state !== STATE_RECOGNIZED) { - return; - } - - if (input && (input.eventType & INPUT_END)) { - this.manager.emit(this.options.event + 'up', input); - } else { - this._input.timeStamp = now(); - this.manager.emit(this.options.event, this._input); - } + createClass(Manager, [{ + key: 'registerInput', + value: function registerInput(name, InputClass) { + this.inputs[name] = new InputClass(this.rootElement, this); } -}); - -/** - * Rotate - * Recognized when two or more pointer are moving in a circular motion. - * @constructor - * @extends AttrRecognizer - */ -function RotateRecognizer() { - AttrRecognizer.apply(this, arguments); -} - -inherit(RotateRecognizer, AttrRecognizer, { - /** - * @namespace - * @memberof RotateRecognizer - */ - defaults: { - event: 'rotate', - threshold: 0, - pointers: 2 - }, - - getTouchAction: function() { - return [TOUCH_ACTION_NONE]; - }, - - attrTest: function(input) { - return this._super.attrTest.call(this, input) && - (Math.abs(input.rotation) > this.options.threshold || this.state & STATE_BEGAN); + }, { + key: 'recognize', + value: function recognize(input, streams, stream, streamEvent) { + var layer = this._findParentLayer(streamEvent.element); + + while (layer) { + if (layer.recognize(input, streams, stream, streamEvent)) { + this.startInputRecognition(); + break; + } + layer = layer.parent; + } + + if (this.isRecognizing && streamEvent.name === 'end') { + this.endInputRecognition(); + } } -}); + }, { + key: 'startInputRecognition', + value: function startInputRecognition() { + this._recognizedInputs++; + if (this._recognizedInputs === 1) { + this.isRecognizing = true; + document.body.setAttribute('gesture-no-touch', 'true'); + } + } + }, { + key: 'endInputRecognition', + value: function endInputRecognition() { + this._recognizedInputs--; + if (this._recognizedInputs === 0) { + this.isRecognizing = false; + document.body.removeAttribute('gesture-no-touch'); + } + } + }, { + key: 'unregisterInput', + value: function unregisterInput(name) { + var input = this.inputs[name]; + + if (input) { + this.inputs[name] = null; + input.destroy(); + } + } + }, { + key: 'registerLayer', + value: function registerLayer(layer) { + layer.element.setAttribute('gesture-layer', true); + this.layers.set(layer.element, layer); + + layer.parent = this._findParentLayer(layer.element.parentNode); + + // insert into linked layer list + if (layer.parent) { + layer.child = layer.parent.child; + layer.parent.child = layer; + } + } + }, { + key: 'forgetLayer', + value: function forgetLayer(layer) { + this.layers.delete(layer.element); -/** - * Swipe - * Recognized when the pointer is moving fast (velocity), with enough distance in the allowed direction. - * @constructor - * @extends AttrRecognizer - */ -function SwipeRecognizer() { - AttrRecognizer.apply(this, arguments); -} + // join parent/child + if (layer.parent && layer.child) { + layer.parent.child = layer.child; -inherit(SwipeRecognizer, AttrRecognizer, { - /** - * @namespace - * @memberof SwipeRecognizer - */ - defaults: { - event: 'swipe', - threshold: 10, - velocity: 0.3, - direction: DIRECTION_HORIZONTAL | DIRECTION_VERTICAL, - pointers: 1 - }, - - getTouchAction: function() { - return PanRecognizer.prototype.getTouchAction.call(this); - }, - - attrTest: function(input) { - var direction = this.options.direction; - var velocity; - - if (direction & (DIRECTION_HORIZONTAL | DIRECTION_VERTICAL)) { - velocity = input.overallVelocity; - } else if (direction & DIRECTION_HORIZONTAL) { - velocity = input.overallVelocityX; - } else if (direction & DIRECTION_VERTICAL) { - velocity = input.overallVelocityY; + // unlink parent/child + } else { + if (layer.parent) { + layer.parent.child = null; } - - return this._super.attrTest.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; - }, - - emit: function(input) { - var direction = directionStr(input.offsetDirection); - if (direction) { - this.manager.emit(this.options.event + direction, input); + if (layer.child) { + layer.child.parent = null; } - - this.manager.emit(this.options.event, input); + } } -}); - -/** - * A tap is ecognized when the pointer is doing a small tap/click. Multiple taps are recognized if they occur - * between the given interval and position. The delay option can be used to recognize multi-taps without firing - * a single tap. - * - * The eventData from the emitted event contains the property `tapCount`, which contains the amount of - * multi-taps being recognized. - * @constructor - * @extends Recognizer - */ -function TapRecognizer() { - Recognizer.apply(this, arguments); - - // previous time and center, - // used for tap counting - this.pTime = false; - this.pCenter = false; - - this._timer = null; - this._input = null; - this.count = 0; -} + }, { + key: '_findParentLayer', + value: function _findParentLayer(element) { + do { + if (element && element.hasAttribute('gesture-layer')) { + var layer = this.layers.get(element); -inherit(TapRecognizer, Recognizer, { - /** - * @namespace - * @memberof PinchRecognizer - */ - defaults: { - event: 'tap', - pointers: 1, - taps: 1, - interval: 300, // max time between the multi-tap taps - time: 250, // max time of the pointer to be down (like finger on the screen) - threshold: 9, // a minimal movement is ok, but keep it low - posThreshold: 10 // a multi-tap can be a bit off the initial position - }, - - getTouchAction: function() { - return [TOUCH_ACTION_MANIPULATION]; - }, - - process: function(input) { - var options = this.options; - - var validPointers = input.pointers.length === options.pointers; - var validMovement = input.distance < options.threshold; - var validTouchTime = input.deltaTime < options.time; - - this.reset(); - - if ((input.eventType & INPUT_START) && (this.count === 0)) { - return this.failTimeout(); + if (layer) { + return layer; + } } + } while (element && element !== document.body && (element = element.parentNode)); - // we only allow little movement - // and we've reached an end event, so a tap is possible - if (validMovement && validTouchTime && validPointers) { - if (input.eventType != INPUT_END) { - return this.failTimeout(); - } - - var validInterval = this.pTime ? (input.timeStamp - this.pTime < options.interval) : true; - var validMultiTap = !this.pCenter || getDistance(this.pCenter, input.center) < options.posThreshold; - - this.pTime = input.timeStamp; - this.pCenter = input.center; - - if (!validMultiTap || !validInterval) { - this.count = 1; - } else { - this.count += 1; - } - - this._input = input; - - // if tap count matches we have recognized it, - // else it has began recognizing... - var tapCount = this.count % options.taps; - if (tapCount === 0) { - // no failing requirements, immediately trigger the tap event - // or wait as long as the multitap interval to trigger - if (!this.hasRequireFailures()) { - return STATE_RECOGNIZED; - } else { - this._timer = setTimeoutContext(function() { - this.state = STATE_RECOGNIZED; - this.tryEmit(); - }, options.interval, this); - return STATE_BEGAN; - } - } - } - return STATE_FAILED; - }, - - failTimeout: function() { - this._timer = setTimeoutContext(function() { - this.state = STATE_FAILED; - }, this.options.interval, this); - return STATE_FAILED; - }, - - reset: function() { - clearTimeout(this._timer); - }, - - emit: function() { - if (this.state == STATE_RECOGNIZED) { - this._input.tapCount = this.count; - this.manager.emit(this.options.event, this._input); - } + return null; } -}); + }, { + key: '_teardown', + value: function _teardown() { + this.streams.touch.destroy(); + this.streams.mouse.destroy(); -/** - * Simple way to create a manager with a default set of recognizers. - * @param {HTMLElement} element - * @param {Object} [options] - * @constructor - */ -function Hammer(element, options) { - options = options || {}; - options.recognizers = ifUndefined(options.recognizers, Hammer.defaults.preset); - return new Manager(element, options); -} + this.layers.forEach(function (layer) { + layer.destroy(); + }); -/** - * @const {string} - */ -Hammer.VERSION = '2.0.7'; - -/** - * default settings - * @namespace - */ -Hammer.defaults = { - /** - * set if DOM events are being triggered. - * But this is slower and unused by simple implementations, so disabled by default. - * @type {Boolean} - * @default false - */ - domEvents: false, - - /** - * The value for the touchAction property/fallback. - * When set to `compute` it will magically set the correct value based on the added recognizers. - * @type {String} - * @default compute - */ - touchAction: TOUCH_ACTION_COMPUTE, - - /** - * @type {Boolean} - * @default true - */ - enable: true, - - /** - * EXPERIMENTAL FEATURE -- can be removed/changed - * Change the parent input target element. - * If Null, then it is being set the to main element. - * @type {Null|EventTarget} - * @default null - */ - inputTarget: null, - - /** - * force an input class - * @type {Null|Function} - * @default null - */ - inputClass: null, - - /** - * Default recognizer setup when calling `Hammer()` - * When creating a new Manager these will be skipped. - * @type {Array} - */ - preset: [ - // RecognizerClass, options, [recognizeWith, ...], [requireFailure, ...] - [RotateRecognizer, {enable: false}], - [PinchRecognizer, {enable: false}, ['rotate']], - [SwipeRecognizer, {direction: DIRECTION_HORIZONTAL}], - [PanRecognizer, {direction: DIRECTION_HORIZONTAL}, ['swipe']], - [TapRecognizer], - [TapRecognizer, {event: 'doubletap', taps: 2}, ['tap']], - [PressRecognizer] - ], - - /** - * Some CSS properties can be used to improve the working of Hammer. - * Add them to this method and they will be set when creating a new Manager. - * @namespace - */ - cssProps: { - /** - * Disables text selection to improve the dragging gesture. Mainly for desktop browsers. - * @type {String} - * @default 'none' - */ - userSelect: 'none', - - /** - * Disable the Windows Phone grippers when pressing an element. - * @type {String} - * @default 'none' - */ - touchSelect: 'none', - - /** - * Disables the default callout shown when you touch and hold a touch target. - * On iOS, when you touch and hold a touch target such as a link, Safari displays - * a callout containing information about the link. This property allows you to disable that callout. - * @type {String} - * @default 'none' - */ - touchCallout: 'none', - - /** - * Specifies whether zooming is enabled. Used by IE10> - * @type {String} - * @default 'none' - */ - contentZooming: 'none', - - /** - * Specifies that an entire element should be draggable instead of its contents. Mainly for desktop browsers. - * @type {String} - * @default 'none' - */ - userDrag: 'none', - - /** - * Overrides the highlight color shown when the user taps a link or a JavaScript - * clickable element in iOS. This property obeys the alpha value, if specified. - * @type {String} - * @default 'rgba(0,0,0,0)' - */ - tapHighlightColor: 'rgba(0,0,0,0)' + this.layers = null; } -}; - -var STOP = 1; -var FORCED_STOP = 2; - -/** - * Manager - * @param {HTMLElement} element - * @param {Object} [options] - * @constructor - */ -function Manager(element, options) { - this.options = assign({}, Hammer.defaults, options || {}); - - this.options.inputTarget = this.options.inputTarget || element; - - this.handlers = {}; - this.session = {}; - this.recognizers = []; - this.oldCssProps = {}; - - this.element = element; - this.input = createInputInstance(this); - this.touchAction = new TouchAction(this, this.options.touchAction); - - toggleCssProps(this, true); - - each(this.options.recognizers, function(item) { - var recognizer = this.add(new (item[0])(item[1])); - item[2] && recognizer.recognizeWith(item[2]); - item[3] && recognizer.requireFailure(item[3]); - }, this); -} - -Manager.prototype = { - /** - * set options - * @param {Object} options - * @returns {Manager} - */ - set: function(options) { - assign(this.options, options); - - // Options that need a little more setup - if (options.touchAction) { - this.touchAction.update(); - } - if (options.inputTarget) { - // Clean up existing event listeners and reinitialize - this.input.destroy(); - this.input.target = options.inputTarget; - this.input.init(); - } - return this; - }, - - /** - * stop recognizing for this session. - * This session will be discarded, when a new [input]start event is fired. - * When forced, the recognizer cycle is stopped immediately. - * @param {Boolean} [force] - */ - stop: function(force) { - this.session.stopped = force ? FORCED_STOP : STOP; - }, - - /** - * run the recognizers! - * called by the inputHandler function on every movement of the pointers (touches) - * it walks through all the recognizers and tries to detect the gesture that is being made - * @param {Object} inputData - */ - recognize: function(inputData) { - var session = this.session; - if (session.stopped) { - return; - } + }, { + key: 'destroy', + value: function destroy() { + this._teardown(); + } + }], [{ + key: 'create', + value: function create() { + return new Manager(); + } + }]); + return Manager; +}(); - // run the touch-action polyfill - this.touchAction.preventDefaults(inputData); +var Recognizer = function Recognizer(name) { + classCallCheck(this, Recognizer); - var recognizer; - var recognizers = this.recognizers; + this.name = name; +}; - // this holds the recognizer that is being recognized. - // so the recognizer's state needs to be BEGAN, CHANGED, ENDED or RECOGNIZED - // if no recognizer is detecting a thing, it is set to `null` - var curRecognizer = session.curRecognizer; +var HorizontalPan = function () { + function HorizontalPan(options) { + classCallCheck(this, HorizontalPan); - // reset when the last recognizer is recognized - // or when we're in a new session - if (!curRecognizer || (curRecognizer && curRecognizer.state & STATE_RECOGNIZED)) { - curRecognizer = session.curRecognizer = null; - } + this.name = 'horizontal-pan'; + this.options = options; + this.layer = undefined; + this.stream = undefined; - var i = 0; - while (i < recognizers.length) { - recognizer = recognizers[i]; - - // find out if we are allowed try to recognize the input for this one. - // 1. allow if the session is NOT forced stopped (see the .stop() method) - // 2. allow if we still haven't recognized a gesture in this session, or the this recognizer is the one - // that is being recognized. - // 3. allow if the recognizer is allowed to run simultaneous with the current recognized recognizer. - // this can be setup with the `recognizeWith()` method on the recognizer. - if (session.stopped !== FORCED_STOP && ( // 1 - !curRecognizer || recognizer == curRecognizer || // 2 - recognizer.canRecognizeWith(curRecognizer))) { // 3 - recognizer.recognize(inputData); - } else { - recognizer.reset(); - } - - // if the recognizer has been recognizing the input as a valid gesture, we want to store this one as the - // current active recognizer. but only if we don't already have an active recognizer - if (!curRecognizer && recognizer.state & (STATE_BEGAN | STATE_CHANGED | STATE_ENDED)) { - curRecognizer = session.curRecognizer = recognizer; - } - i++; - } - }, - - /** - * get a recognizer by its event name. - * @param {Recognizer|String} recognizer - * @returns {Recognizer|Null} - */ - get: function(recognizer) { - if (recognizer instanceof Recognizer) { - return recognizer; - } + this.isRecognizing = false; + } - var recognizers = this.recognizers; - for (var i = 0; i < recognizers.length; i++) { - if (recognizers[i].options.event == recognizer) { - return recognizers[i]; - } - } - return null; - }, - - /** - * add a recognizer to the manager - * existing recognizers with the same event name will be removed - * @param {Recognizer} recognizer - * @returns {Recognizer|Manager} - */ - add: function(recognizer) { - if (invokeArrayArg(recognizer, 'add', this)) { - return this; - } + createClass(HorizontalPan, [{ + key: 'beginRecognizing', + value: function beginRecognizing(input, stream) { + var _this = this; - // remove existing - var existing = this.get(recognizer.options.event); - if (existing) { - this.remove(existing); - } + this.isRecognizing = true; - this.recognizers.push(recognizer); - recognizer.manager = this; - - this.touchAction.update(); - return recognizer; - }, - - /** - * remove a recognizer by name or instance - * @param {Recognizer|String} recognizer - * @returns {Manager} - */ - remove: function(recognizer) { - if (invokeArrayArg(recognizer, 'remove', this)) { - return this; - } - - recognizer = this.get(recognizer); + this.stream = stream; + var series = this.stream.series; - // let's make sure this recognizer exists - if (recognizer) { - var recognizers = this.recognizers; - var index = inArray(recognizers, recognizer); - if (index !== -1) { - recognizers.splice(index, 1); - this.touchAction.update(); - } - } + series.forEach(function (event) { + _this.relay(event); + }); + } + }, { + key: 'relay', + value: function relay(event) { + if (event.name === 'start') { + this.layer.emit({ name: 'panStart', event: event }); + } else if (event.name === 'end') { + this.isRecognizing = false; + this.layer.emit({ name: 'panEnd', event: event }); + this.stream = undefined; + } else if (event.totalX < 0 || event.prev.totalX < 0) { + this.layer.emit({ name: 'panLeft', event: event }); + } else { + this.layer.emit({ name: 'panRight', event: event }); + } + } + }, { + key: 'emit', + value: function emit(name, event) { + this.layer.emit({ name: name, event: event }); + } + }, { + key: 'recognize', + value: function recognize(input, streams, stream, streamEvent) { + if (this.isRecognizing) { + this.relay(streamEvent); + } else if (input.openStreams === 1 && streamEvent.totalY === 0 && streamEvent.totalX !== 0) { + this.beginRecognizing(input, stream); + } + + return this.isRecognizing; + } + }]); + return HorizontalPan; +}(); - return this; - }, - - /** - * bind event - * @param {String} events - * @param {Function} handler - * @returns {EventEmitter} this - */ - on: function(events, handler) { - if (events === undefined) { - return; - } - if (handler === undefined) { - return; - } +var VerticalPan = function () { + function VerticalPan(options) { + classCallCheck(this, VerticalPan); - var handlers = this.handlers; - each(splitStr(events), function(event) { - handlers[event] = handlers[event] || []; - handlers[event].push(handler); - }); - return this; - }, - - /** - * unbind event, leave emit blank to remove all handlers - * @param {String} events - * @param {Function} [handler] - * @returns {EventEmitter} this - */ - off: function(events, handler) { - if (events === undefined) { - return; - } + this.name = 'vertical-pan'; + this.options = options; + this.layer = undefined; + this.stream = undefined; - var handlers = this.handlers; - each(splitStr(events), function(event) { - if (!handler) { - delete handlers[event]; - } else { - handlers[event] && handlers[event].splice(inArray(handlers[event], handler), 1); - } - }); - return this; - }, - - /** - * emit event to the listeners - * @param {String} event - * @param {Object} data - */ - emit: function(event, data) { - // we also want to trigger dom events - if (this.options.domEvents) { - triggerDomEvent(event, data); - } + this.isRecognizing = false; + } - // no handlers, so skip it all - var handlers = this.handlers[event] && this.handlers[event].slice(); - if (!handlers || !handlers.length) { - return; - } + createClass(VerticalPan, [{ + key: 'beginRecognizing', + value: function beginRecognizing(input, streams) { + var _this = this; - data.type = event; - data.preventDefault = function() { - data.srcEvent.preventDefault(); - }; + this.isRecognizing = true; - var i = 0; - while (i < handlers.length) { - handlers[i](data); - i++; - } - }, + this.stream = streams[streams.length - 1]; + var series = this.stream.series; - /** - * destroy the manager and unbinds all events - * it doesn't unbind dom events, that is the user own responsibility - */ - destroy: function() { - this.element && toggleCssProps(this, false); - this.handlers = {}; - this.session = {}; - this.input.destroy(); - this.element = null; + series.forEach(function (event) { + _this.relay(event); + }); } -}; - -/** - * add/remove the css properties as defined in manager.options.cssProps - * @param {Manager} manager - * @param {Boolean} add - */ -function toggleCssProps(manager, add) { - var element = manager.element; - if (!element.style) { - return; + }, { + key: 'relay', + value: function relay(event) { + if (event.name === 'start') { + this.layer.emit({ name: 'panStart', event: event }); + } else if (event.name === 'end') { + this.isRecognizing = false; + this.layer.emit({ name: 'panEnd', event: event }); + this.stream = undefined; + } else if (event.totalY < 0 || event.prev.totalY < 0) { + this.layer.emit({ name: 'panUp', event: event }); + } else { + this.layer.emit({ name: 'panDown', event: event }); + } } - var prop; - each(manager.options.cssProps, function(value, name) { - prop = prefixed(element.style, name); - if (add) { - manager.oldCssProps[prop] = element.style[prop]; - element.style[prop] = value; - } else { - element.style[prop] = manager.oldCssProps[prop] || ''; - } - }); - if (!add) { - manager.oldCssProps = {}; + }, { + key: 'emit', + value: function emit(name, event) { + this.layer.emit({ name: name, event: event }); } -} + }, { + key: 'recognize', + value: function recognize(input, streams, streamEvent) { + if (this.isRecognizing) { + this.relay(streamEvent); + } else if (streamEvent.totalX === 0 && streamEvent.totalY !== 0) { + this.beginRecognizing(input, streams); + } + + return this.isRecognizing; + } + }]); + return VerticalPan; +}(); -/** - * trigger dom event - * @param {String} event - * @param {Object} data - */ -function triggerDomEvent(event, data) { - var gestureEvent = document.createEvent('Event'); - gestureEvent.initEvent(event, true, true); - gestureEvent.gesture = data; - data.target.dispatchEvent(gestureEvent); -} +// this prevents errors when Hammer is loaded in the presence of an AMD +// style loader but by script tag, not by the loader. -assign(Hammer, { - INPUT_START: INPUT_START, - INPUT_MOVE: INPUT_MOVE, - INPUT_END: INPUT_END, - INPUT_CANCEL: INPUT_CANCEL, - - STATE_POSSIBLE: STATE_POSSIBLE, - STATE_BEGAN: STATE_BEGAN, - STATE_CHANGED: STATE_CHANGED, - STATE_ENDED: STATE_ENDED, - STATE_RECOGNIZED: STATE_RECOGNIZED, - STATE_CANCELLED: STATE_CANCELLED, - STATE_FAILED: STATE_FAILED, - - DIRECTION_NONE: DIRECTION_NONE, - DIRECTION_LEFT: DIRECTION_LEFT, - DIRECTION_RIGHT: DIRECTION_RIGHT, - DIRECTION_UP: DIRECTION_UP, - DIRECTION_DOWN: DIRECTION_DOWN, - DIRECTION_HORIZONTAL: DIRECTION_HORIZONTAL, - DIRECTION_VERTICAL: DIRECTION_VERTICAL, - DIRECTION_ALL: DIRECTION_ALL, - - Manager: Manager, - Input: Input, - TouchAction: TouchAction, - - TouchInput: TouchInput, - MouseInput: MouseInput, - PointerEventInput: PointerEventInput, - TouchMouseInput: TouchMouseInput, - SingleTouchInput: SingleTouchInput, - - Recognizer: Recognizer, - AttrRecognizer: AttrRecognizer, - Tap: TapRecognizer, - Pan: PanRecognizer, - Swipe: SwipeRecognizer, - Pinch: PinchRecognizer, - Rotate: RotateRecognizer, - Press: PressRecognizer, - - on: addEventListeners, - off: removeEventListeners, - each: each, - merge: merge, - extend: extend, - assign: assign, - inherit: inherit, - bindFn: bindFn, - prefixed: prefixed -}); +var Hammer = { // jshint ignore:line + Input: Input, + Layer: Layer, + Manager: Manager, + Recognizer: Recognizer, -// this prevents errors when Hammer is loaded in the presence of an AMD -// style loader but by script tag, not by the loader. -var freeGlobal = (typeof window !== 'undefined' ? window : (typeof self !== 'undefined' ? self : {})); // jshint ignore:line -freeGlobal.Hammer = Hammer; + MouseInput: MouseInput, + TouchInput: TouchInput, + HorizontalPanRecognizer: HorizontalPan, + VerticalPanRecognizer: VerticalPan +}; + +/* jshint ignore:start */ if (typeof define === 'function' && define.amd) { - define(function() { - return Hammer; - }); -} else if (typeof module != 'undefined' && module.exports) { - module.exports = Hammer; + define(function () { + return Hammer; + }); +} else if (typeof module !== 'undefined' && module.exports) { + module.exports = Hammer; } else { - window[exportName] = Hammer; + window[exportName] = Hammer; } - -})(window, document, 'Hammer'); +/* jshint ignore:end */ +})(window, document, 'Hammer'); \ No newline at end of file diff --git a/hammer.min.js b/hammer.min.js index 34a8c86fb..8a3643ae9 100644 --- a/hammer.min.js +++ b/hammer.min.js @@ -1,7 +1,7 @@ -/*! Hammer.JS - v2.0.7 - 2016-04-22 +/*! Hammer.JS - v2.0.8 - 2016-07-12 * http://hammerjs.github.io/ * * Copyright (c) 2016 Jorik Tangelder; * Licensed under the MIT license */ -!function(a,b,c,d){"use strict";function e(a,b,c){return setTimeout(j(a,c),b)}function f(a,b,c){return Array.isArray(a)?(g(a,c[b],c),!0):!1}function g(a,b,c){var e;if(a)if(a.forEach)a.forEach(b,c);else if(a.length!==d)for(e=0;e\s*\(/gm,"{anonymous}()@"):"Unknown Stack Trace",f=a.console&&(a.console.warn||a.console.log);return f&&f.call(a.console,e,d),b.apply(this,arguments)}}function i(a,b,c){var d,e=b.prototype;d=a.prototype=Object.create(e),d.constructor=a,d._super=e,c&&la(d,c)}function j(a,b){return function(){return a.apply(b,arguments)}}function k(a,b){return typeof a==oa?a.apply(b?b[0]||d:d,b):a}function l(a,b){return a===d?b:a}function m(a,b,c){g(q(b),function(b){a.addEventListener(b,c,!1)})}function n(a,b,c){g(q(b),function(b){a.removeEventListener(b,c,!1)})}function o(a,b){for(;a;){if(a==b)return!0;a=a.parentNode}return!1}function p(a,b){return a.indexOf(b)>-1}function q(a){return a.trim().split(/\s+/g)}function r(a,b,c){if(a.indexOf&&!c)return a.indexOf(b);for(var d=0;dc[b]}):d.sort()),d}function u(a,b){for(var c,e,f=b[0].toUpperCase()+b.slice(1),g=0;g1&&!c.firstMultiple?c.firstMultiple=D(b):1===e&&(c.firstMultiple=!1);var f=c.firstInput,g=c.firstMultiple,h=g?g.center:f.center,i=b.center=E(d);b.timeStamp=ra(),b.deltaTime=b.timeStamp-f.timeStamp,b.angle=I(h,i),b.distance=H(h,i),B(c,b),b.offsetDirection=G(b.deltaX,b.deltaY);var j=F(b.deltaTime,b.deltaX,b.deltaY);b.overallVelocityX=j.x,b.overallVelocityY=j.y,b.overallVelocity=qa(j.x)>qa(j.y)?j.x:j.y,b.scale=g?K(g.pointers,d):1,b.rotation=g?J(g.pointers,d):0,b.maxPointers=c.prevInput?b.pointers.length>c.prevInput.maxPointers?b.pointers.length:c.prevInput.maxPointers:b.pointers.length,C(c,b);var k=a.element;o(b.srcEvent.target,k)&&(k=b.srcEvent.target),b.target=k}function B(a,b){var c=b.center,d=a.offsetDelta||{},e=a.prevDelta||{},f=a.prevInput||{};b.eventType!==Ea&&f.eventType!==Ga||(e=a.prevDelta={x:f.deltaX||0,y:f.deltaY||0},d=a.offsetDelta={x:c.x,y:c.y}),b.deltaX=e.x+(c.x-d.x),b.deltaY=e.y+(c.y-d.y)}function C(a,b){var c,e,f,g,h=a.lastInterval||b,i=b.timeStamp-h.timeStamp;if(b.eventType!=Ha&&(i>Da||h.velocity===d)){var j=b.deltaX-h.deltaX,k=b.deltaY-h.deltaY,l=F(i,j,k);e=l.x,f=l.y,c=qa(l.x)>qa(l.y)?l.x:l.y,g=G(j,k),a.lastInterval=b}else c=h.velocity,e=h.velocityX,f=h.velocityY,g=h.direction;b.velocity=c,b.velocityX=e,b.velocityY=f,b.direction=g}function D(a){for(var b=[],c=0;ce;)c+=a[e].clientX,d+=a[e].clientY,e++;return{x:pa(c/b),y:pa(d/b)}}function F(a,b,c){return{x:b/a||0,y:c/a||0}}function G(a,b){return a===b?Ia:qa(a)>=qa(b)?0>a?Ja:Ka:0>b?La:Ma}function H(a,b,c){c||(c=Qa);var d=b[c[0]]-a[c[0]],e=b[c[1]]-a[c[1]];return Math.sqrt(d*d+e*e)}function I(a,b,c){c||(c=Qa);var d=b[c[0]]-a[c[0]],e=b[c[1]]-a[c[1]];return 180*Math.atan2(e,d)/Math.PI}function J(a,b){return I(b[1],b[0],Ra)+I(a[1],a[0],Ra)}function K(a,b){return H(b[0],b[1],Ra)/H(a[0],a[1],Ra)}function L(){this.evEl=Ta,this.evWin=Ua,this.pressed=!1,x.apply(this,arguments)}function M(){this.evEl=Xa,this.evWin=Ya,x.apply(this,arguments),this.store=this.manager.session.pointerEvents=[]}function N(){this.evTarget=$a,this.evWin=_a,this.started=!1,x.apply(this,arguments)}function O(a,b){var c=s(a.touches),d=s(a.changedTouches);return b&(Ga|Ha)&&(c=t(c.concat(d),"identifier",!0)),[c,d]}function P(){this.evTarget=bb,this.targetIds={},x.apply(this,arguments)}function Q(a,b){var c=s(a.touches),d=this.targetIds;if(b&(Ea|Fa)&&1===c.length)return d[c[0].identifier]=!0,[c,c];var e,f,g=s(a.changedTouches),h=[],i=this.target;if(f=c.filter(function(a){return o(a.target,i)}),b===Ea)for(e=0;e-1&&d.splice(a,1)};setTimeout(e,cb)}}function U(a){for(var b=a.srcEvent.clientX,c=a.srcEvent.clientY,d=0;d=f&&db>=g)return!0}return!1}function V(a,b){this.manager=a,this.set(b)}function W(a){if(p(a,jb))return jb;var b=p(a,kb),c=p(a,lb);return b&&c?jb:b||c?b?kb:lb:p(a,ib)?ib:hb}function X(){if(!fb)return!1;var b={},c=a.CSS&&a.CSS.supports;return["auto","manipulation","pan-y","pan-x","pan-x pan-y","none"].forEach(function(d){b[d]=c?a.CSS.supports("touch-action",d):!0}),b}function Y(a){this.options=la({},this.defaults,a||{}),this.id=v(),this.manager=null,this.options.enable=l(this.options.enable,!0),this.state=nb,this.simultaneous={},this.requireFail=[]}function Z(a){return a&sb?"cancel":a&qb?"end":a&pb?"move":a&ob?"start":""}function $(a){return a==Ma?"down":a==La?"up":a==Ja?"left":a==Ka?"right":""}function _(a,b){var c=b.manager;return c?c.get(a):a}function aa(){Y.apply(this,arguments)}function ba(){aa.apply(this,arguments),this.pX=null,this.pY=null}function ca(){aa.apply(this,arguments)}function da(){Y.apply(this,arguments),this._timer=null,this._input=null}function ea(){aa.apply(this,arguments)}function fa(){aa.apply(this,arguments)}function ga(){Y.apply(this,arguments),this.pTime=!1,this.pCenter=!1,this._timer=null,this._input=null,this.count=0}function ha(a,b){return b=b||{},b.recognizers=l(b.recognizers,ha.defaults.preset),new ia(a,b)}function ia(a,b){this.options=la({},ha.defaults,b||{}),this.options.inputTarget=this.options.inputTarget||a,this.handlers={},this.session={},this.recognizers=[],this.oldCssProps={},this.element=a,this.input=y(this),this.touchAction=new V(this,this.options.touchAction),ja(this,!0),g(this.options.recognizers,function(a){var b=this.add(new a[0](a[1]));a[2]&&b.recognizeWith(a[2]),a[3]&&b.requireFailure(a[3])},this)}function ja(a,b){var c=a.element;if(c.style){var d;g(a.options.cssProps,function(e,f){d=u(c.style,f),b?(a.oldCssProps[d]=c.style[d],c.style[d]=e):c.style[d]=a.oldCssProps[d]||""}),b||(a.oldCssProps={})}}function ka(a,c){var d=b.createEvent("Event");d.initEvent(a,!0,!0),d.gesture=c,c.target.dispatchEvent(d)}var la,ma=["","webkit","Moz","MS","ms","o"],na=b.createElement("div"),oa="function",pa=Math.round,qa=Math.abs,ra=Date.now;la="function"!=typeof Object.assign?function(a){if(a===d||null===a)throw new TypeError("Cannot convert undefined or null to object");for(var b=Object(a),c=1;ch&&(b.push(a),h=b.length-1):e&(Ga|Ha)&&(c=!0),0>h||(b[h]=a,this.callback(this.manager,e,{pointers:b,changedPointers:[a],pointerType:f,srcEvent:a}),c&&b.splice(h,1))}});var Za={touchstart:Ea,touchmove:Fa,touchend:Ga,touchcancel:Ha},$a="touchstart",_a="touchstart touchmove touchend touchcancel";i(N,x,{handler:function(a){var b=Za[a.type];if(b===Ea&&(this.started=!0),this.started){var c=O.call(this,a,b);b&(Ga|Ha)&&c[0].length-c[1].length===0&&(this.started=!1),this.callback(this.manager,b,{pointers:c[0],changedPointers:c[1],pointerType:za,srcEvent:a})}}});var ab={touchstart:Ea,touchmove:Fa,touchend:Ga,touchcancel:Ha},bb="touchstart touchmove touchend touchcancel";i(P,x,{handler:function(a){var b=ab[a.type],c=Q.call(this,a,b);c&&this.callback(this.manager,b,{pointers:c[0],changedPointers:c[1],pointerType:za,srcEvent:a})}});var cb=2500,db=25;i(R,x,{handler:function(a,b,c){var d=c.pointerType==za,e=c.pointerType==Ba;if(!(e&&c.sourceCapabilities&&c.sourceCapabilities.firesTouchEvents)){if(d)S.call(this,b,c);else if(e&&U.call(this,c))return;this.callback(a,b,c)}},destroy:function(){this.touch.destroy(),this.mouse.destroy()}});var eb=u(na.style,"touchAction"),fb=eb!==d,gb="compute",hb="auto",ib="manipulation",jb="none",kb="pan-x",lb="pan-y",mb=X();V.prototype={set:function(a){a==gb&&(a=this.compute()),fb&&this.manager.element.style&&mb[a]&&(this.manager.element.style[eb]=a),this.actions=a.toLowerCase().trim()},update:function(){this.set(this.manager.options.touchAction)},compute:function(){var a=[];return g(this.manager.recognizers,function(b){k(b.options.enable,[b])&&(a=a.concat(b.getTouchAction()))}),W(a.join(" "))},preventDefaults:function(a){var b=a.srcEvent,c=a.offsetDirection;if(this.manager.session.prevented)return void b.preventDefault();var d=this.actions,e=p(d,jb)&&!mb[jb],f=p(d,lb)&&!mb[lb],g=p(d,kb)&&!mb[kb];if(e){var h=1===a.pointers.length,i=a.distance<2,j=a.deltaTime<250;if(h&&i&&j)return}return g&&f?void 0:e||f&&c&Na||g&&c&Oa?this.preventSrc(b):void 0},preventSrc:function(a){this.manager.session.prevented=!0,a.preventDefault()}};var nb=1,ob=2,pb=4,qb=8,rb=qb,sb=16,tb=32;Y.prototype={defaults:{},set:function(a){return la(this.options,a),this.manager&&this.manager.touchAction.update(),this},recognizeWith:function(a){if(f(a,"recognizeWith",this))return this;var b=this.simultaneous;return a=_(a,this),b[a.id]||(b[a.id]=a,a.recognizeWith(this)),this},dropRecognizeWith:function(a){return f(a,"dropRecognizeWith",this)?this:(a=_(a,this),delete this.simultaneous[a.id],this)},requireFailure:function(a){if(f(a,"requireFailure",this))return this;var b=this.requireFail;return a=_(a,this),-1===r(b,a)&&(b.push(a),a.requireFailure(this)),this},dropRequireFailure:function(a){if(f(a,"dropRequireFailure",this))return this;a=_(a,this);var b=r(this.requireFail,a);return b>-1&&this.requireFail.splice(b,1),this},hasRequireFailures:function(){return this.requireFail.length>0},canRecognizeWith:function(a){return!!this.simultaneous[a.id]},emit:function(a){function b(b){c.manager.emit(b,a)}var c=this,d=this.state;qb>d&&b(c.options.event+Z(d)),b(c.options.event),a.additionalEvent&&b(a.additionalEvent),d>=qb&&b(c.options.event+Z(d))},tryEmit:function(a){return this.canEmit()?this.emit(a):void(this.state=tb)},canEmit:function(){for(var a=0;af?Ja:Ka,c=f!=this.pX,d=Math.abs(a.deltaX)):(e=0===g?Ia:0>g?La:Ma,c=g!=this.pY,d=Math.abs(a.deltaY))),a.direction=e,c&&d>b.threshold&&e&b.direction},attrTest:function(a){return aa.prototype.attrTest.call(this,a)&&(this.state&ob||!(this.state&ob)&&this.directionTest(a))},emit:function(a){this.pX=a.deltaX,this.pY=a.deltaY;var b=$(a.direction);b&&(a.additionalEvent=this.options.event+b),this._super.emit.call(this,a)}}),i(ca,aa,{defaults:{event:"pinch",threshold:0,pointers:2},getTouchAction:function(){return[jb]},attrTest:function(a){return this._super.attrTest.call(this,a)&&(Math.abs(a.scale-1)>this.options.threshold||this.state&ob)},emit:function(a){if(1!==a.scale){var b=a.scale<1?"in":"out";a.additionalEvent=this.options.event+b}this._super.emit.call(this,a)}}),i(da,Y,{defaults:{event:"press",pointers:1,time:251,threshold:9},getTouchAction:function(){return[hb]},process:function(a){var b=this.options,c=a.pointers.length===b.pointers,d=a.distanceb.time;if(this._input=a,!d||!c||a.eventType&(Ga|Ha)&&!f)this.reset();else if(a.eventType&Ea)this.reset(),this._timer=e(function(){this.state=rb,this.tryEmit()},b.time,this);else if(a.eventType&Ga)return rb;return tb},reset:function(){clearTimeout(this._timer)},emit:function(a){this.state===rb&&(a&&a.eventType&Ga?this.manager.emit(this.options.event+"up",a):(this._input.timeStamp=ra(),this.manager.emit(this.options.event,this._input)))}}),i(ea,aa,{defaults:{event:"rotate",threshold:0,pointers:2},getTouchAction:function(){return[jb]},attrTest:function(a){return this._super.attrTest.call(this,a)&&(Math.abs(a.rotation)>this.options.threshold||this.state&ob)}}),i(fa,aa,{defaults:{event:"swipe",threshold:10,velocity:.3,direction:Na|Oa,pointers:1},getTouchAction:function(){return ba.prototype.getTouchAction.call(this)},attrTest:function(a){var b,c=this.options.direction;return c&(Na|Oa)?b=a.overallVelocity:c&Na?b=a.overallVelocityX:c&Oa&&(b=a.overallVelocityY),this._super.attrTest.call(this,a)&&c&a.offsetDirection&&a.distance>this.options.threshold&&a.maxPointers==this.options.pointers&&qa(b)>this.options.velocity&&a.eventType&Ga},emit:function(a){var b=$(a.offsetDirection);b&&this.manager.emit(this.options.event+b,a),this.manager.emit(this.options.event,a)}}),i(ga,Y,{defaults:{event:"tap",pointers:1,taps:1,interval:300,time:250,threshold:9,posThreshold:10},getTouchAction:function(){return[ib]},process:function(a){var b=this.options,c=a.pointers.length===b.pointers,d=a.distance=0&&athis.length)throw new Error("Index is out of array bounds.");a===this.length&&this.length++,this._data[a]=b}},{key:"forEach",value:function(a){for(var b=0;b1?d-1:0),f=1;f0||navigator.msMaxTouchPoints>0,H=!0,I=void 0;I="function"!=typeof Object.assign?function(a){if(a===d||null===a)throw new TypeError("Cannot convert undefined or null to object");for(var b=Object(a),c=1;c { this.destroy(); }); + new MacroTask(() => { + this.destroy(); + }); return streamEvent; }