bpmn-js 16.5.0 → 17.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * bpmn-js - bpmn-modeler v16.5.0
2
+ * bpmn-js - bpmn-modeler v17.0.0
3
3
  *
4
4
  * Copyright (c) 2014-present, camunda Services GmbH
5
5
  *
@@ -8,7 +8,7 @@
8
8
  *
9
9
  * Source Code: https://github.com/bpmn-io/bpmn-js
10
10
  *
11
- * Date: 2024-01-30
11
+ * Date: 2024-02-06
12
12
  */
13
13
  (function (global, factory) {
14
14
  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
@@ -2100,7 +2100,7 @@
2100
2100
 
2101
2101
  }
2102
2102
 
2103
- function get$1(element) {
2103
+ function get(element) {
2104
2104
  var child = element.firstChild,
2105
2105
  output = [];
2106
2106
 
@@ -2128,7 +2128,7 @@
2128
2128
 
2129
2129
  return element;
2130
2130
  } else {
2131
- return get$1(element);
2131
+ return get(element);
2132
2132
  }
2133
2133
  }
2134
2134
 
@@ -2920,7 +2920,7 @@
2920
2920
  * @typedef {import('../model/Types').Element} Element
2921
2921
  * @typedef {import('../model/Types').Shape} Shape
2922
2922
  *
2923
- * @typedef {import('../../type/Types').Rect} Rect
2923
+ * @typedef {import('../util/Types').Rect} Rect
2924
2924
  *
2925
2925
  * @typedef { {
2926
2926
  * allShapes: Record<string, Shape>,
@@ -4653,6 +4653,7 @@
4653
4653
  * @typedef {import('../core/Types').ConnectionLike} Connection
4654
4654
  *
4655
4655
  * @typedef {import('../util/Types').DirectionTRBL} DirectionTRBL
4656
+ * @typedef {import('../util/Types').Intersect} Intersect
4656
4657
  * @typedef {import('../util/Types').Point} Point
4657
4658
  * @typedef {import('../util/Types').Rect} Rect
4658
4659
  * @typedef {import('../util/Types').RectTRBL} RectTRBL
@@ -4822,7 +4823,7 @@
4822
4823
  * @param {Rect} reference
4823
4824
  * @param {Point|number} padding
4824
4825
  *
4825
- * @return {DirectionTRBL} the orientation; one of top, top-left, left, ..., bottom, right or intersect.
4826
+ * @return {DirectionTRBL|Intersect} the orientation; one of top, top-left, left, ..., bottom, right or intersect.
4826
4827
  */
4827
4828
  function getOrientation(rect, reference, padding) {
4828
4829
 
@@ -23270,8 +23271,8 @@
23270
23271
  var isSelected = selection.isSelected(element),
23271
23272
  isMultiSelect = selection.get().length > 1;
23272
23273
 
23273
- // Add to selection if CTRL or SHIFT pressed
23274
- var add = hasPrimaryModifier(event) || hasSecondaryModifier(event);
23274
+ // Add to selection if SHIFT pressed
23275
+ var add = hasSecondaryModifier(event);
23275
23276
 
23276
23277
  if (isSelected && isMultiSelect) {
23277
23278
  if (add) {
@@ -26434,3071 +26435,6 @@
26434
26435
  NavigatedViewer.prototype._navigationModules
26435
26436
  );
26436
26437
 
26437
- function getDefaultExportFromCjs (x) {
26438
- return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
26439
- }
26440
-
26441
- var hammer = {exports: {}};
26442
-
26443
- /*! Hammer.JS - v2.0.7 - 2016-04-22
26444
- * http://hammerjs.github.io/
26445
- *
26446
- * Copyright (c) 2016 Jorik Tangelder;
26447
- * Licensed under the MIT license */
26448
-
26449
- (function (module) {
26450
- (function(window, document, exportName, undefined$1) {
26451
-
26452
- var VENDOR_PREFIXES = ['', 'webkit', 'Moz', 'MS', 'ms', 'o'];
26453
- var TEST_ELEMENT = document.createElement('div');
26454
-
26455
- var TYPE_FUNCTION = 'function';
26456
-
26457
- var round = Math.round;
26458
- var abs = Math.abs;
26459
- var now = Date.now;
26460
-
26461
- /**
26462
- * set a timeout with a given scope
26463
- * @param {Function} fn
26464
- * @param {Number} timeout
26465
- * @param {Object} context
26466
- * @returns {number}
26467
- */
26468
- function setTimeoutContext(fn, timeout, context) {
26469
- return setTimeout(bindFn(fn, context), timeout);
26470
- }
26471
-
26472
- /**
26473
- * if the argument is an array, we want to execute the fn on each entry
26474
- * if it aint an array we don't want to do a thing.
26475
- * this is used by all the methods that accept a single and array argument.
26476
- * @param {*|Array} arg
26477
- * @param {String} fn
26478
- * @param {Object} [context]
26479
- * @returns {Boolean}
26480
- */
26481
- function invokeArrayArg(arg, fn, context) {
26482
- if (Array.isArray(arg)) {
26483
- each(arg, context[fn], context);
26484
- return true;
26485
- }
26486
- return false;
26487
- }
26488
-
26489
- /**
26490
- * walk objects and arrays
26491
- * @param {Object} obj
26492
- * @param {Function} iterator
26493
- * @param {Object} context
26494
- */
26495
- function each(obj, iterator, context) {
26496
- var i;
26497
-
26498
- if (!obj) {
26499
- return;
26500
- }
26501
-
26502
- if (obj.forEach) {
26503
- obj.forEach(iterator, context);
26504
- } else if (obj.length !== undefined$1) {
26505
- i = 0;
26506
- while (i < obj.length) {
26507
- iterator.call(context, obj[i], i, obj);
26508
- i++;
26509
- }
26510
- } else {
26511
- for (i in obj) {
26512
- obj.hasOwnProperty(i) && iterator.call(context, obj[i], i, obj);
26513
- }
26514
- }
26515
- }
26516
-
26517
- /**
26518
- * wrap a method with a deprecation warning and stack trace
26519
- * @param {Function} method
26520
- * @param {String} name
26521
- * @param {String} message
26522
- * @returns {Function} A new function wrapping the supplied method.
26523
- */
26524
- function deprecate(method, name, message) {
26525
- var deprecationMessage = 'DEPRECATED METHOD: ' + name + '\n' + message + ' AT \n';
26526
- return function() {
26527
- var e = new Error('get-stack-trace');
26528
- var stack = e && e.stack ? e.stack.replace(/^[^\(]+?[\n$]/gm, '')
26529
- .replace(/^\s+at\s+/gm, '')
26530
- .replace(/^Object.<anonymous>\s*\(/gm, '{anonymous}()@') : 'Unknown Stack Trace';
26531
-
26532
- var log = window.console && (window.console.warn || window.console.log);
26533
- if (log) {
26534
- log.call(window.console, deprecationMessage, stack);
26535
- }
26536
- return method.apply(this, arguments);
26537
- };
26538
- }
26539
-
26540
- /**
26541
- * extend object.
26542
- * means that properties in dest will be overwritten by the ones in src.
26543
- * @param {Object} target
26544
- * @param {...Object} objects_to_assign
26545
- * @returns {Object} target
26546
- */
26547
- var assign;
26548
- if (typeof Object.assign !== 'function') {
26549
- assign = function assign(target) {
26550
- if (target === undefined$1 || target === null) {
26551
- throw new TypeError('Cannot convert undefined or null to object');
26552
- }
26553
-
26554
- var output = Object(target);
26555
- for (var index = 1; index < arguments.length; index++) {
26556
- var source = arguments[index];
26557
- if (source !== undefined$1 && source !== null) {
26558
- for (var nextKey in source) {
26559
- if (source.hasOwnProperty(nextKey)) {
26560
- output[nextKey] = source[nextKey];
26561
- }
26562
- }
26563
- }
26564
- }
26565
- return output;
26566
- };
26567
- } else {
26568
- assign = Object.assign;
26569
- }
26570
-
26571
- /**
26572
- * extend object.
26573
- * means that properties in dest will be overwritten by the ones in src.
26574
- * @param {Object} dest
26575
- * @param {Object} src
26576
- * @param {Boolean} [merge=false]
26577
- * @returns {Object} dest
26578
- */
26579
- var extend = deprecate(function extend(dest, src, merge) {
26580
- var keys = Object.keys(src);
26581
- var i = 0;
26582
- while (i < keys.length) {
26583
- if (!merge || (merge && dest[keys[i]] === undefined$1)) {
26584
- dest[keys[i]] = src[keys[i]];
26585
- }
26586
- i++;
26587
- }
26588
- return dest;
26589
- }, 'extend', 'Use `assign`.');
26590
-
26591
- /**
26592
- * merge the values from src in the dest.
26593
- * means that properties that exist in dest will not be overwritten by src
26594
- * @param {Object} dest
26595
- * @param {Object} src
26596
- * @returns {Object} dest
26597
- */
26598
- var merge = deprecate(function merge(dest, src) {
26599
- return extend(dest, src, true);
26600
- }, 'merge', 'Use `assign`.');
26601
-
26602
- /**
26603
- * simple class inheritance
26604
- * @param {Function} child
26605
- * @param {Function} base
26606
- * @param {Object} [properties]
26607
- */
26608
- function inherit(child, base, properties) {
26609
- var baseP = base.prototype,
26610
- childP;
26611
-
26612
- childP = child.prototype = Object.create(baseP);
26613
- childP.constructor = child;
26614
- childP._super = baseP;
26615
-
26616
- if (properties) {
26617
- assign(childP, properties);
26618
- }
26619
- }
26620
-
26621
- /**
26622
- * simple function bind
26623
- * @param {Function} fn
26624
- * @param {Object} context
26625
- * @returns {Function}
26626
- */
26627
- function bindFn(fn, context) {
26628
- return function boundFn() {
26629
- return fn.apply(context, arguments);
26630
- };
26631
- }
26632
-
26633
- /**
26634
- * let a boolean value also be a function that must return a boolean
26635
- * this first item in args will be used as the context
26636
- * @param {Boolean|Function} val
26637
- * @param {Array} [args]
26638
- * @returns {Boolean}
26639
- */
26640
- function boolOrFn(val, args) {
26641
- if (typeof val == TYPE_FUNCTION) {
26642
- return val.apply(args ? args[0] || undefined$1 : undefined$1, args);
26643
- }
26644
- return val;
26645
- }
26646
-
26647
- /**
26648
- * use the val2 when val1 is undefined
26649
- * @param {*} val1
26650
- * @param {*} val2
26651
- * @returns {*}
26652
- */
26653
- function ifUndefined(val1, val2) {
26654
- return (val1 === undefined$1) ? val2 : val1;
26655
- }
26656
-
26657
- /**
26658
- * addEventListener with multiple events at once
26659
- * @param {EventTarget} target
26660
- * @param {String} types
26661
- * @param {Function} handler
26662
- */
26663
- function addEventListeners(target, types, handler) {
26664
- each(splitStr(types), function(type) {
26665
- target.addEventListener(type, handler, false);
26666
- });
26667
- }
26668
-
26669
- /**
26670
- * removeEventListener with multiple events at once
26671
- * @param {EventTarget} target
26672
- * @param {String} types
26673
- * @param {Function} handler
26674
- */
26675
- function removeEventListeners(target, types, handler) {
26676
- each(splitStr(types), function(type) {
26677
- target.removeEventListener(type, handler, false);
26678
- });
26679
- }
26680
-
26681
- /**
26682
- * find if a node is in the given parent
26683
- * @method hasParent
26684
- * @param {HTMLElement} node
26685
- * @param {HTMLElement} parent
26686
- * @return {Boolean} found
26687
- */
26688
- function hasParent(node, parent) {
26689
- while (node) {
26690
- if (node == parent) {
26691
- return true;
26692
- }
26693
- node = node.parentNode;
26694
- }
26695
- return false;
26696
- }
26697
-
26698
- /**
26699
- * small indexOf wrapper
26700
- * @param {String} str
26701
- * @param {String} find
26702
- * @returns {Boolean} found
26703
- */
26704
- function inStr(str, find) {
26705
- return str.indexOf(find) > -1;
26706
- }
26707
-
26708
- /**
26709
- * split string on whitespace
26710
- * @param {String} str
26711
- * @returns {Array} words
26712
- */
26713
- function splitStr(str) {
26714
- return str.trim().split(/\s+/g);
26715
- }
26716
-
26717
- /**
26718
- * find if a array contains the object using indexOf or a simple polyFill
26719
- * @param {Array} src
26720
- * @param {String} find
26721
- * @param {String} [findByKey]
26722
- * @return {Boolean|Number} false when not found, or the index
26723
- */
26724
- function inArray(src, find, findByKey) {
26725
- if (src.indexOf && !findByKey) {
26726
- return src.indexOf(find);
26727
- } else {
26728
- var i = 0;
26729
- while (i < src.length) {
26730
- if ((findByKey && src[i][findByKey] == find) || (!findByKey && src[i] === find)) {
26731
- return i;
26732
- }
26733
- i++;
26734
- }
26735
- return -1;
26736
- }
26737
- }
26738
-
26739
- /**
26740
- * convert array-like objects to real arrays
26741
- * @param {Object} obj
26742
- * @returns {Array}
26743
- */
26744
- function toArray(obj) {
26745
- return Array.prototype.slice.call(obj, 0);
26746
- }
26747
-
26748
- /**
26749
- * unique array with objects based on a key (like 'id') or just by the array's value
26750
- * @param {Array} src [{id:1},{id:2},{id:1}]
26751
- * @param {String} [key]
26752
- * @param {Boolean} [sort=False]
26753
- * @returns {Array} [{id:1},{id:2}]
26754
- */
26755
- function uniqueArray(src, key, sort) {
26756
- var results = [];
26757
- var values = [];
26758
- var i = 0;
26759
-
26760
- while (i < src.length) {
26761
- var val = key ? src[i][key] : src[i];
26762
- if (inArray(values, val) < 0) {
26763
- results.push(src[i]);
26764
- }
26765
- values[i] = val;
26766
- i++;
26767
- }
26768
-
26769
- if (sort) {
26770
- if (!key) {
26771
- results = results.sort();
26772
- } else {
26773
- results = results.sort(function sortUniqueArray(a, b) {
26774
- return a[key] > b[key];
26775
- });
26776
- }
26777
- }
26778
-
26779
- return results;
26780
- }
26781
-
26782
- /**
26783
- * get the prefixed property
26784
- * @param {Object} obj
26785
- * @param {String} property
26786
- * @returns {String|Undefined} prefixed
26787
- */
26788
- function prefixed(obj, property) {
26789
- var prefix, prop;
26790
- var camelProp = property[0].toUpperCase() + property.slice(1);
26791
-
26792
- var i = 0;
26793
- while (i < VENDOR_PREFIXES.length) {
26794
- prefix = VENDOR_PREFIXES[i];
26795
- prop = (prefix) ? prefix + camelProp : property;
26796
-
26797
- if (prop in obj) {
26798
- return prop;
26799
- }
26800
- i++;
26801
- }
26802
- return undefined$1;
26803
- }
26804
-
26805
- /**
26806
- * get a unique id
26807
- * @returns {number} uniqueId
26808
- */
26809
- var _uniqueId = 1;
26810
- function uniqueId() {
26811
- return _uniqueId++;
26812
- }
26813
-
26814
- /**
26815
- * get the window object of an element
26816
- * @param {HTMLElement} element
26817
- * @returns {DocumentView|Window}
26818
- */
26819
- function getWindowForElement(element) {
26820
- var doc = element.ownerDocument || element;
26821
- return (doc.defaultView || doc.parentWindow || window);
26822
- }
26823
-
26824
- var MOBILE_REGEX = /mobile|tablet|ip(ad|hone|od)|android/i;
26825
-
26826
- var SUPPORT_TOUCH = ('ontouchstart' in window);
26827
- var SUPPORT_POINTER_EVENTS = prefixed(window, 'PointerEvent') !== undefined$1;
26828
- var SUPPORT_ONLY_TOUCH = SUPPORT_TOUCH && MOBILE_REGEX.test(navigator.userAgent);
26829
-
26830
- var INPUT_TYPE_TOUCH = 'touch';
26831
- var INPUT_TYPE_PEN = 'pen';
26832
- var INPUT_TYPE_MOUSE = 'mouse';
26833
- var INPUT_TYPE_KINECT = 'kinect';
26834
-
26835
- var COMPUTE_INTERVAL = 25;
26836
-
26837
- var INPUT_START = 1;
26838
- var INPUT_MOVE = 2;
26839
- var INPUT_END = 4;
26840
- var INPUT_CANCEL = 8;
26841
-
26842
- var DIRECTION_NONE = 1;
26843
- var DIRECTION_LEFT = 2;
26844
- var DIRECTION_RIGHT = 4;
26845
- var DIRECTION_UP = 8;
26846
- var DIRECTION_DOWN = 16;
26847
-
26848
- var DIRECTION_HORIZONTAL = DIRECTION_LEFT | DIRECTION_RIGHT;
26849
- var DIRECTION_VERTICAL = DIRECTION_UP | DIRECTION_DOWN;
26850
- var DIRECTION_ALL = DIRECTION_HORIZONTAL | DIRECTION_VERTICAL;
26851
-
26852
- var PROPS_XY = ['x', 'y'];
26853
- var PROPS_CLIENT_XY = ['clientX', 'clientY'];
26854
-
26855
- /**
26856
- * create new input type manager
26857
- * @param {Manager} manager
26858
- * @param {Function} callback
26859
- * @returns {Input}
26860
- * @constructor
26861
- */
26862
- function Input(manager, callback) {
26863
- var self = this;
26864
- this.manager = manager;
26865
- this.callback = callback;
26866
- this.element = manager.element;
26867
- this.target = manager.options.inputTarget;
26868
-
26869
- // smaller wrapper around the handler, for the scope and the enabled state of the manager,
26870
- // so when disabled the input events are completely bypassed.
26871
- this.domHandler = function(ev) {
26872
- if (boolOrFn(manager.options.enable, [manager])) {
26873
- self.handler(ev);
26874
- }
26875
- };
26876
-
26877
- this.init();
26878
-
26879
- }
26880
-
26881
- Input.prototype = {
26882
- /**
26883
- * should handle the inputEvent data and trigger the callback
26884
- * @virtual
26885
- */
26886
- handler: function() { },
26887
-
26888
- /**
26889
- * bind the events
26890
- */
26891
- init: function() {
26892
- this.evEl && addEventListeners(this.element, this.evEl, this.domHandler);
26893
- this.evTarget && addEventListeners(this.target, this.evTarget, this.domHandler);
26894
- this.evWin && addEventListeners(getWindowForElement(this.element), this.evWin, this.domHandler);
26895
- },
26896
-
26897
- /**
26898
- * unbind the events
26899
- */
26900
- destroy: function() {
26901
- this.evEl && removeEventListeners(this.element, this.evEl, this.domHandler);
26902
- this.evTarget && removeEventListeners(this.target, this.evTarget, this.domHandler);
26903
- this.evWin && removeEventListeners(getWindowForElement(this.element), this.evWin, this.domHandler);
26904
- }
26905
- };
26906
-
26907
- /**
26908
- * create new input type manager
26909
- * called by the Manager constructor
26910
- * @param {Hammer} manager
26911
- * @returns {Input}
26912
- */
26913
- function createInputInstance(manager) {
26914
- var Type;
26915
- var inputClass = manager.options.inputClass;
26916
-
26917
- if (inputClass) {
26918
- Type = inputClass;
26919
- } else if (SUPPORT_POINTER_EVENTS) {
26920
- Type = PointerEventInput;
26921
- } else if (SUPPORT_ONLY_TOUCH) {
26922
- Type = TouchInput;
26923
- } else if (!SUPPORT_TOUCH) {
26924
- Type = MouseInput;
26925
- } else {
26926
- Type = TouchMouseInput;
26927
- }
26928
- return new (Type)(manager, inputHandler);
26929
- }
26930
-
26931
- /**
26932
- * handle input events
26933
- * @param {Manager} manager
26934
- * @param {String} eventType
26935
- * @param {Object} input
26936
- */
26937
- function inputHandler(manager, eventType, input) {
26938
- var pointersLen = input.pointers.length;
26939
- var changedPointersLen = input.changedPointers.length;
26940
- var isFirst = (eventType & INPUT_START && (pointersLen - changedPointersLen === 0));
26941
- var isFinal = (eventType & (INPUT_END | INPUT_CANCEL) && (pointersLen - changedPointersLen === 0));
26942
-
26943
- input.isFirst = !!isFirst;
26944
- input.isFinal = !!isFinal;
26945
-
26946
- if (isFirst) {
26947
- manager.session = {};
26948
- }
26949
-
26950
- // source event is the normalized value of the domEvents
26951
- // like 'touchstart, mouseup, pointerdown'
26952
- input.eventType = eventType;
26953
-
26954
- // compute scale, rotation etc
26955
- computeInputData(manager, input);
26956
-
26957
- // emit secret event
26958
- manager.emit('hammer.input', input);
26959
-
26960
- manager.recognize(input);
26961
- manager.session.prevInput = input;
26962
- }
26963
-
26964
- /**
26965
- * extend the data with some usable properties like scale, rotate, velocity etc
26966
- * @param {Object} manager
26967
- * @param {Object} input
26968
- */
26969
- function computeInputData(manager, input) {
26970
- var session = manager.session;
26971
- var pointers = input.pointers;
26972
- var pointersLength = pointers.length;
26973
-
26974
- // store the first input to calculate the distance and direction
26975
- if (!session.firstInput) {
26976
- session.firstInput = simpleCloneInputData(input);
26977
- }
26978
-
26979
- // to compute scale and rotation we need to store the multiple touches
26980
- if (pointersLength > 1 && !session.firstMultiple) {
26981
- session.firstMultiple = simpleCloneInputData(input);
26982
- } else if (pointersLength === 1) {
26983
- session.firstMultiple = false;
26984
- }
26985
-
26986
- var firstInput = session.firstInput;
26987
- var firstMultiple = session.firstMultiple;
26988
- var offsetCenter = firstMultiple ? firstMultiple.center : firstInput.center;
26989
-
26990
- var center = input.center = getCenter(pointers);
26991
- input.timeStamp = now();
26992
- input.deltaTime = input.timeStamp - firstInput.timeStamp;
26993
-
26994
- input.angle = getAngle(offsetCenter, center);
26995
- input.distance = getDistance(offsetCenter, center);
26996
-
26997
- computeDeltaXY(session, input);
26998
- input.offsetDirection = getDirection(input.deltaX, input.deltaY);
26999
-
27000
- var overallVelocity = getVelocity(input.deltaTime, input.deltaX, input.deltaY);
27001
- input.overallVelocityX = overallVelocity.x;
27002
- input.overallVelocityY = overallVelocity.y;
27003
- input.overallVelocity = (abs(overallVelocity.x) > abs(overallVelocity.y)) ? overallVelocity.x : overallVelocity.y;
27004
-
27005
- input.scale = firstMultiple ? getScale(firstMultiple.pointers, pointers) : 1;
27006
- input.rotation = firstMultiple ? getRotation(firstMultiple.pointers, pointers) : 0;
27007
-
27008
- input.maxPointers = !session.prevInput ? input.pointers.length : ((input.pointers.length >
27009
- session.prevInput.maxPointers) ? input.pointers.length : session.prevInput.maxPointers);
27010
-
27011
- computeIntervalInputData(session, input);
27012
-
27013
- // find the correct target
27014
- var target = manager.element;
27015
- if (hasParent(input.srcEvent.target, target)) {
27016
- target = input.srcEvent.target;
27017
- }
27018
- input.target = target;
27019
- }
27020
-
27021
- function computeDeltaXY(session, input) {
27022
- var center = input.center;
27023
- var offset = session.offsetDelta || {};
27024
- var prevDelta = session.prevDelta || {};
27025
- var prevInput = session.prevInput || {};
27026
-
27027
- if (input.eventType === INPUT_START || prevInput.eventType === INPUT_END) {
27028
- prevDelta = session.prevDelta = {
27029
- x: prevInput.deltaX || 0,
27030
- y: prevInput.deltaY || 0
27031
- };
27032
-
27033
- offset = session.offsetDelta = {
27034
- x: center.x,
27035
- y: center.y
27036
- };
27037
- }
27038
-
27039
- input.deltaX = prevDelta.x + (center.x - offset.x);
27040
- input.deltaY = prevDelta.y + (center.y - offset.y);
27041
- }
27042
-
27043
- /**
27044
- * velocity is calculated every x ms
27045
- * @param {Object} session
27046
- * @param {Object} input
27047
- */
27048
- function computeIntervalInputData(session, input) {
27049
- var last = session.lastInterval || input,
27050
- deltaTime = input.timeStamp - last.timeStamp,
27051
- velocity, velocityX, velocityY, direction;
27052
-
27053
- if (input.eventType != INPUT_CANCEL && (deltaTime > COMPUTE_INTERVAL || last.velocity === undefined$1)) {
27054
- var deltaX = input.deltaX - last.deltaX;
27055
- var deltaY = input.deltaY - last.deltaY;
27056
-
27057
- var v = getVelocity(deltaTime, deltaX, deltaY);
27058
- velocityX = v.x;
27059
- velocityY = v.y;
27060
- velocity = (abs(v.x) > abs(v.y)) ? v.x : v.y;
27061
- direction = getDirection(deltaX, deltaY);
27062
-
27063
- session.lastInterval = input;
27064
- } else {
27065
- // use latest velocity info if it doesn't overtake a minimum period
27066
- velocity = last.velocity;
27067
- velocityX = last.velocityX;
27068
- velocityY = last.velocityY;
27069
- direction = last.direction;
27070
- }
27071
-
27072
- input.velocity = velocity;
27073
- input.velocityX = velocityX;
27074
- input.velocityY = velocityY;
27075
- input.direction = direction;
27076
- }
27077
-
27078
- /**
27079
- * create a simple clone from the input used for storage of firstInput and firstMultiple
27080
- * @param {Object} input
27081
- * @returns {Object} clonedInputData
27082
- */
27083
- function simpleCloneInputData(input) {
27084
- // make a simple copy of the pointers because we will get a reference if we don't
27085
- // we only need clientXY for the calculations
27086
- var pointers = [];
27087
- var i = 0;
27088
- while (i < input.pointers.length) {
27089
- pointers[i] = {
27090
- clientX: round(input.pointers[i].clientX),
27091
- clientY: round(input.pointers[i].clientY)
27092
- };
27093
- i++;
27094
- }
27095
-
27096
- return {
27097
- timeStamp: now(),
27098
- pointers: pointers,
27099
- center: getCenter(pointers),
27100
- deltaX: input.deltaX,
27101
- deltaY: input.deltaY
27102
- };
27103
- }
27104
-
27105
- /**
27106
- * get the center of all the pointers
27107
- * @param {Array} pointers
27108
- * @return {Object} center contains `x` and `y` properties
27109
- */
27110
- function getCenter(pointers) {
27111
- var pointersLength = pointers.length;
27112
-
27113
- // no need to loop when only one touch
27114
- if (pointersLength === 1) {
27115
- return {
27116
- x: round(pointers[0].clientX),
27117
- y: round(pointers[0].clientY)
27118
- };
27119
- }
27120
-
27121
- var x = 0, y = 0, i = 0;
27122
- while (i < pointersLength) {
27123
- x += pointers[i].clientX;
27124
- y += pointers[i].clientY;
27125
- i++;
27126
- }
27127
-
27128
- return {
27129
- x: round(x / pointersLength),
27130
- y: round(y / pointersLength)
27131
- };
27132
- }
27133
-
27134
- /**
27135
- * calculate the velocity between two points. unit is in px per ms.
27136
- * @param {Number} deltaTime
27137
- * @param {Number} x
27138
- * @param {Number} y
27139
- * @return {Object} velocity `x` and `y`
27140
- */
27141
- function getVelocity(deltaTime, x, y) {
27142
- return {
27143
- x: x / deltaTime || 0,
27144
- y: y / deltaTime || 0
27145
- };
27146
- }
27147
-
27148
- /**
27149
- * get the direction between two points
27150
- * @param {Number} x
27151
- * @param {Number} y
27152
- * @return {Number} direction
27153
- */
27154
- function getDirection(x, y) {
27155
- if (x === y) {
27156
- return DIRECTION_NONE;
27157
- }
27158
-
27159
- if (abs(x) >= abs(y)) {
27160
- return x < 0 ? DIRECTION_LEFT : DIRECTION_RIGHT;
27161
- }
27162
- return y < 0 ? DIRECTION_UP : DIRECTION_DOWN;
27163
- }
27164
-
27165
- /**
27166
- * calculate the absolute distance between two points
27167
- * @param {Object} p1 {x, y}
27168
- * @param {Object} p2 {x, y}
27169
- * @param {Array} [props] containing x and y keys
27170
- * @return {Number} distance
27171
- */
27172
- function getDistance(p1, p2, props) {
27173
- if (!props) {
27174
- props = PROPS_XY;
27175
- }
27176
- var x = p2[props[0]] - p1[props[0]],
27177
- y = p2[props[1]] - p1[props[1]];
27178
-
27179
- return Math.sqrt((x * x) + (y * y));
27180
- }
27181
-
27182
- /**
27183
- * calculate the angle between two coordinates
27184
- * @param {Object} p1
27185
- * @param {Object} p2
27186
- * @param {Array} [props] containing x and y keys
27187
- * @return {Number} angle
27188
- */
27189
- function getAngle(p1, p2, props) {
27190
- if (!props) {
27191
- props = PROPS_XY;
27192
- }
27193
- var x = p2[props[0]] - p1[props[0]],
27194
- y = p2[props[1]] - p1[props[1]];
27195
- return Math.atan2(y, x) * 180 / Math.PI;
27196
- }
27197
-
27198
- /**
27199
- * calculate the rotation degrees between two pointersets
27200
- * @param {Array} start array of pointers
27201
- * @param {Array} end array of pointers
27202
- * @return {Number} rotation
27203
- */
27204
- function getRotation(start, end) {
27205
- return getAngle(end[1], end[0], PROPS_CLIENT_XY) + getAngle(start[1], start[0], PROPS_CLIENT_XY);
27206
- }
27207
-
27208
- /**
27209
- * calculate the scale factor between two pointersets
27210
- * no scale is 1, and goes down to 0 when pinched together, and bigger when pinched out
27211
- * @param {Array} start array of pointers
27212
- * @param {Array} end array of pointers
27213
- * @return {Number} scale
27214
- */
27215
- function getScale(start, end) {
27216
- return getDistance(end[0], end[1], PROPS_CLIENT_XY) / getDistance(start[0], start[1], PROPS_CLIENT_XY);
27217
- }
27218
-
27219
- var MOUSE_INPUT_MAP = {
27220
- mousedown: INPUT_START,
27221
- mousemove: INPUT_MOVE,
27222
- mouseup: INPUT_END
27223
- };
27224
-
27225
- var MOUSE_ELEMENT_EVENTS = 'mousedown';
27226
- var MOUSE_WINDOW_EVENTS = 'mousemove mouseup';
27227
-
27228
- /**
27229
- * Mouse events input
27230
- * @constructor
27231
- * @extends Input
27232
- */
27233
- function MouseInput() {
27234
- this.evEl = MOUSE_ELEMENT_EVENTS;
27235
- this.evWin = MOUSE_WINDOW_EVENTS;
27236
-
27237
- this.pressed = false; // mousedown state
27238
-
27239
- Input.apply(this, arguments);
27240
- }
27241
-
27242
- inherit(MouseInput, Input, {
27243
- /**
27244
- * handle mouse events
27245
- * @param {Object} ev
27246
- */
27247
- handler: function MEhandler(ev) {
27248
- var eventType = MOUSE_INPUT_MAP[ev.type];
27249
-
27250
- // on start we want to have the left mouse button down
27251
- if (eventType & INPUT_START && ev.button === 0) {
27252
- this.pressed = true;
27253
- }
27254
-
27255
- if (eventType & INPUT_MOVE && ev.which !== 1) {
27256
- eventType = INPUT_END;
27257
- }
27258
-
27259
- // mouse must be down
27260
- if (!this.pressed) {
27261
- return;
27262
- }
27263
-
27264
- if (eventType & INPUT_END) {
27265
- this.pressed = false;
27266
- }
27267
-
27268
- this.callback(this.manager, eventType, {
27269
- pointers: [ev],
27270
- changedPointers: [ev],
27271
- pointerType: INPUT_TYPE_MOUSE,
27272
- srcEvent: ev
27273
- });
27274
- }
27275
- });
27276
-
27277
- var POINTER_INPUT_MAP = {
27278
- pointerdown: INPUT_START,
27279
- pointermove: INPUT_MOVE,
27280
- pointerup: INPUT_END,
27281
- pointercancel: INPUT_CANCEL,
27282
- pointerout: INPUT_CANCEL
27283
- };
27284
-
27285
- // in IE10 the pointer types is defined as an enum
27286
- var IE10_POINTER_TYPE_ENUM = {
27287
- 2: INPUT_TYPE_TOUCH,
27288
- 3: INPUT_TYPE_PEN,
27289
- 4: INPUT_TYPE_MOUSE,
27290
- 5: INPUT_TYPE_KINECT // see https://twitter.com/jacobrossi/status/480596438489890816
27291
- };
27292
-
27293
- var POINTER_ELEMENT_EVENTS = 'pointerdown';
27294
- var POINTER_WINDOW_EVENTS = 'pointermove pointerup pointercancel';
27295
-
27296
- // IE10 has prefixed support, and case-sensitive
27297
- if (window.MSPointerEvent && !window.PointerEvent) {
27298
- POINTER_ELEMENT_EVENTS = 'MSPointerDown';
27299
- POINTER_WINDOW_EVENTS = 'MSPointerMove MSPointerUp MSPointerCancel';
27300
- }
27301
-
27302
- /**
27303
- * Pointer events input
27304
- * @constructor
27305
- * @extends Input
27306
- */
27307
- function PointerEventInput() {
27308
- this.evEl = POINTER_ELEMENT_EVENTS;
27309
- this.evWin = POINTER_WINDOW_EVENTS;
27310
-
27311
- Input.apply(this, arguments);
27312
-
27313
- this.store = (this.manager.session.pointerEvents = []);
27314
- }
27315
-
27316
- inherit(PointerEventInput, Input, {
27317
- /**
27318
- * handle mouse events
27319
- * @param {Object} ev
27320
- */
27321
- handler: function PEhandler(ev) {
27322
- var store = this.store;
27323
- var removePointer = false;
27324
-
27325
- var eventTypeNormalized = ev.type.toLowerCase().replace('ms', '');
27326
- var eventType = POINTER_INPUT_MAP[eventTypeNormalized];
27327
- var pointerType = IE10_POINTER_TYPE_ENUM[ev.pointerType] || ev.pointerType;
27328
-
27329
- var isTouch = (pointerType == INPUT_TYPE_TOUCH);
27330
-
27331
- // get index of the event in the store
27332
- var storeIndex = inArray(store, ev.pointerId, 'pointerId');
27333
-
27334
- // start and mouse must be down
27335
- if (eventType & INPUT_START && (ev.button === 0 || isTouch)) {
27336
- if (storeIndex < 0) {
27337
- store.push(ev);
27338
- storeIndex = store.length - 1;
27339
- }
27340
- } else if (eventType & (INPUT_END | INPUT_CANCEL)) {
27341
- removePointer = true;
27342
- }
27343
-
27344
- // it not found, so the pointer hasn't been down (so it's probably a hover)
27345
- if (storeIndex < 0) {
27346
- return;
27347
- }
27348
-
27349
- // update the event in the store
27350
- store[storeIndex] = ev;
27351
-
27352
- this.callback(this.manager, eventType, {
27353
- pointers: store,
27354
- changedPointers: [ev],
27355
- pointerType: pointerType,
27356
- srcEvent: ev
27357
- });
27358
-
27359
- if (removePointer) {
27360
- // remove from the store
27361
- store.splice(storeIndex, 1);
27362
- }
27363
- }
27364
- });
27365
-
27366
- var SINGLE_TOUCH_INPUT_MAP = {
27367
- touchstart: INPUT_START,
27368
- touchmove: INPUT_MOVE,
27369
- touchend: INPUT_END,
27370
- touchcancel: INPUT_CANCEL
27371
- };
27372
-
27373
- var SINGLE_TOUCH_TARGET_EVENTS = 'touchstart';
27374
- var SINGLE_TOUCH_WINDOW_EVENTS = 'touchstart touchmove touchend touchcancel';
27375
-
27376
- /**
27377
- * Touch events input
27378
- * @constructor
27379
- * @extends Input
27380
- */
27381
- function SingleTouchInput() {
27382
- this.evTarget = SINGLE_TOUCH_TARGET_EVENTS;
27383
- this.evWin = SINGLE_TOUCH_WINDOW_EVENTS;
27384
- this.started = false;
27385
-
27386
- Input.apply(this, arguments);
27387
- }
27388
-
27389
- inherit(SingleTouchInput, Input, {
27390
- handler: function TEhandler(ev) {
27391
- var type = SINGLE_TOUCH_INPUT_MAP[ev.type];
27392
-
27393
- // should we handle the touch events?
27394
- if (type === INPUT_START) {
27395
- this.started = true;
27396
- }
27397
-
27398
- if (!this.started) {
27399
- return;
27400
- }
27401
-
27402
- var touches = normalizeSingleTouches.call(this, ev, type);
27403
-
27404
- // when done, reset the started state
27405
- if (type & (INPUT_END | INPUT_CANCEL) && touches[0].length - touches[1].length === 0) {
27406
- this.started = false;
27407
- }
27408
-
27409
- this.callback(this.manager, type, {
27410
- pointers: touches[0],
27411
- changedPointers: touches[1],
27412
- pointerType: INPUT_TYPE_TOUCH,
27413
- srcEvent: ev
27414
- });
27415
- }
27416
- });
27417
-
27418
- /**
27419
- * @this {TouchInput}
27420
- * @param {Object} ev
27421
- * @param {Number} type flag
27422
- * @returns {undefined|Array} [all, changed]
27423
- */
27424
- function normalizeSingleTouches(ev, type) {
27425
- var all = toArray(ev.touches);
27426
- var changed = toArray(ev.changedTouches);
27427
-
27428
- if (type & (INPUT_END | INPUT_CANCEL)) {
27429
- all = uniqueArray(all.concat(changed), 'identifier', true);
27430
- }
27431
-
27432
- return [all, changed];
27433
- }
27434
-
27435
- var TOUCH_INPUT_MAP = {
27436
- touchstart: INPUT_START,
27437
- touchmove: INPUT_MOVE,
27438
- touchend: INPUT_END,
27439
- touchcancel: INPUT_CANCEL
27440
- };
27441
-
27442
- var TOUCH_TARGET_EVENTS = 'touchstart touchmove touchend touchcancel';
27443
-
27444
- /**
27445
- * Multi-user touch events input
27446
- * @constructor
27447
- * @extends Input
27448
- */
27449
- function TouchInput() {
27450
- this.evTarget = TOUCH_TARGET_EVENTS;
27451
- this.targetIds = {};
27452
-
27453
- Input.apply(this, arguments);
27454
- }
27455
-
27456
- inherit(TouchInput, Input, {
27457
- handler: function MTEhandler(ev) {
27458
- var type = TOUCH_INPUT_MAP[ev.type];
27459
- var touches = getTouches.call(this, ev, type);
27460
- if (!touches) {
27461
- return;
27462
- }
27463
-
27464
- this.callback(this.manager, type, {
27465
- pointers: touches[0],
27466
- changedPointers: touches[1],
27467
- pointerType: INPUT_TYPE_TOUCH,
27468
- srcEvent: ev
27469
- });
27470
- }
27471
- });
27472
-
27473
- /**
27474
- * @this {TouchInput}
27475
- * @param {Object} ev
27476
- * @param {Number} type flag
27477
- * @returns {undefined|Array} [all, changed]
27478
- */
27479
- function getTouches(ev, type) {
27480
- var allTouches = toArray(ev.touches);
27481
- var targetIds = this.targetIds;
27482
-
27483
- // when there is only one touch, the process can be simplified
27484
- if (type & (INPUT_START | INPUT_MOVE) && allTouches.length === 1) {
27485
- targetIds[allTouches[0].identifier] = true;
27486
- return [allTouches, allTouches];
27487
- }
27488
-
27489
- var i,
27490
- targetTouches,
27491
- changedTouches = toArray(ev.changedTouches),
27492
- changedTargetTouches = [],
27493
- target = this.target;
27494
-
27495
- // get target touches from touches
27496
- targetTouches = allTouches.filter(function(touch) {
27497
- return hasParent(touch.target, target);
27498
- });
27499
-
27500
- // collect touches
27501
- if (type === INPUT_START) {
27502
- i = 0;
27503
- while (i < targetTouches.length) {
27504
- targetIds[targetTouches[i].identifier] = true;
27505
- i++;
27506
- }
27507
- }
27508
-
27509
- // filter changed touches to only contain touches that exist in the collected target ids
27510
- i = 0;
27511
- while (i < changedTouches.length) {
27512
- if (targetIds[changedTouches[i].identifier]) {
27513
- changedTargetTouches.push(changedTouches[i]);
27514
- }
27515
-
27516
- // cleanup removed touches
27517
- if (type & (INPUT_END | INPUT_CANCEL)) {
27518
- delete targetIds[changedTouches[i].identifier];
27519
- }
27520
- i++;
27521
- }
27522
-
27523
- if (!changedTargetTouches.length) {
27524
- return;
27525
- }
27526
-
27527
- return [
27528
- // merge targetTouches with changedTargetTouches so it contains ALL touches, including 'end' and 'cancel'
27529
- uniqueArray(targetTouches.concat(changedTargetTouches), 'identifier', true),
27530
- changedTargetTouches
27531
- ];
27532
- }
27533
-
27534
- /**
27535
- * Combined touch and mouse input
27536
- *
27537
- * Touch has a higher priority then mouse, and while touching no mouse events are allowed.
27538
- * This because touch devices also emit mouse events while doing a touch.
27539
- *
27540
- * @constructor
27541
- * @extends Input
27542
- */
27543
-
27544
- var DEDUP_TIMEOUT = 2500;
27545
- var DEDUP_DISTANCE = 25;
27546
-
27547
- function TouchMouseInput() {
27548
- Input.apply(this, arguments);
27549
-
27550
- var handler = bindFn(this.handler, this);
27551
- this.touch = new TouchInput(this.manager, handler);
27552
- this.mouse = new MouseInput(this.manager, handler);
27553
-
27554
- this.primaryTouch = null;
27555
- this.lastTouches = [];
27556
- }
27557
-
27558
- inherit(TouchMouseInput, Input, {
27559
- /**
27560
- * handle mouse and touch events
27561
- * @param {Hammer} manager
27562
- * @param {String} inputEvent
27563
- * @param {Object} inputData
27564
- */
27565
- handler: function TMEhandler(manager, inputEvent, inputData) {
27566
- var isTouch = (inputData.pointerType == INPUT_TYPE_TOUCH),
27567
- isMouse = (inputData.pointerType == INPUT_TYPE_MOUSE);
27568
-
27569
- if (isMouse && inputData.sourceCapabilities && inputData.sourceCapabilities.firesTouchEvents) {
27570
- return;
27571
- }
27572
-
27573
- // when we're in a touch event, record touches to de-dupe synthetic mouse event
27574
- if (isTouch) {
27575
- recordTouches.call(this, inputEvent, inputData);
27576
- } else if (isMouse && isSyntheticEvent.call(this, inputData)) {
27577
- return;
27578
- }
27579
-
27580
- this.callback(manager, inputEvent, inputData);
27581
- },
27582
-
27583
- /**
27584
- * remove the event listeners
27585
- */
27586
- destroy: function destroy() {
27587
- this.touch.destroy();
27588
- this.mouse.destroy();
27589
- }
27590
- });
27591
-
27592
- function recordTouches(eventType, eventData) {
27593
- if (eventType & INPUT_START) {
27594
- this.primaryTouch = eventData.changedPointers[0].identifier;
27595
- setLastTouch.call(this, eventData);
27596
- } else if (eventType & (INPUT_END | INPUT_CANCEL)) {
27597
- setLastTouch.call(this, eventData);
27598
- }
27599
- }
27600
-
27601
- function setLastTouch(eventData) {
27602
- var touch = eventData.changedPointers[0];
27603
-
27604
- if (touch.identifier === this.primaryTouch) {
27605
- var lastTouch = {x: touch.clientX, y: touch.clientY};
27606
- this.lastTouches.push(lastTouch);
27607
- var lts = this.lastTouches;
27608
- var removeLastTouch = function() {
27609
- var i = lts.indexOf(lastTouch);
27610
- if (i > -1) {
27611
- lts.splice(i, 1);
27612
- }
27613
- };
27614
- setTimeout(removeLastTouch, DEDUP_TIMEOUT);
27615
- }
27616
- }
27617
-
27618
- function isSyntheticEvent(eventData) {
27619
- var x = eventData.srcEvent.clientX, y = eventData.srcEvent.clientY;
27620
- for (var i = 0; i < this.lastTouches.length; i++) {
27621
- var t = this.lastTouches[i];
27622
- var dx = Math.abs(x - t.x), dy = Math.abs(y - t.y);
27623
- if (dx <= DEDUP_DISTANCE && dy <= DEDUP_DISTANCE) {
27624
- return true;
27625
- }
27626
- }
27627
- return false;
27628
- }
27629
-
27630
- var PREFIXED_TOUCH_ACTION = prefixed(TEST_ELEMENT.style, 'touchAction');
27631
- var NATIVE_TOUCH_ACTION = PREFIXED_TOUCH_ACTION !== undefined$1;
27632
-
27633
- // magical touchAction value
27634
- var TOUCH_ACTION_COMPUTE = 'compute';
27635
- var TOUCH_ACTION_AUTO = 'auto';
27636
- var TOUCH_ACTION_MANIPULATION = 'manipulation'; // not implemented
27637
- var TOUCH_ACTION_NONE = 'none';
27638
- var TOUCH_ACTION_PAN_X = 'pan-x';
27639
- var TOUCH_ACTION_PAN_Y = 'pan-y';
27640
- var TOUCH_ACTION_MAP = getTouchActionProps();
27641
-
27642
- /**
27643
- * Touch Action
27644
- * sets the touchAction property or uses the js alternative
27645
- * @param {Manager} manager
27646
- * @param {String} value
27647
- * @constructor
27648
- */
27649
- function TouchAction(manager, value) {
27650
- this.manager = manager;
27651
- this.set(value);
27652
- }
27653
-
27654
- TouchAction.prototype = {
27655
- /**
27656
- * set the touchAction value on the element or enable the polyfill
27657
- * @param {String} value
27658
- */
27659
- set: function(value) {
27660
- // find out the touch-action by the event handlers
27661
- if (value == TOUCH_ACTION_COMPUTE) {
27662
- value = this.compute();
27663
- }
27664
-
27665
- if (NATIVE_TOUCH_ACTION && this.manager.element.style && TOUCH_ACTION_MAP[value]) {
27666
- this.manager.element.style[PREFIXED_TOUCH_ACTION] = value;
27667
- }
27668
- this.actions = value.toLowerCase().trim();
27669
- },
27670
-
27671
- /**
27672
- * just re-set the touchAction value
27673
- */
27674
- update: function() {
27675
- this.set(this.manager.options.touchAction);
27676
- },
27677
-
27678
- /**
27679
- * compute the value for the touchAction property based on the recognizer's settings
27680
- * @returns {String} value
27681
- */
27682
- compute: function() {
27683
- var actions = [];
27684
- each(this.manager.recognizers, function(recognizer) {
27685
- if (boolOrFn(recognizer.options.enable, [recognizer])) {
27686
- actions = actions.concat(recognizer.getTouchAction());
27687
- }
27688
- });
27689
- return cleanTouchActions(actions.join(' '));
27690
- },
27691
-
27692
- /**
27693
- * this method is called on each input cycle and provides the preventing of the browser behavior
27694
- * @param {Object} input
27695
- */
27696
- preventDefaults: function(input) {
27697
- var srcEvent = input.srcEvent;
27698
- var direction = input.offsetDirection;
27699
-
27700
- // if the touch action did prevented once this session
27701
- if (this.manager.session.prevented) {
27702
- srcEvent.preventDefault();
27703
- return;
27704
- }
27705
-
27706
- var actions = this.actions;
27707
- var hasNone = inStr(actions, TOUCH_ACTION_NONE) && !TOUCH_ACTION_MAP[TOUCH_ACTION_NONE];
27708
- var hasPanY = inStr(actions, TOUCH_ACTION_PAN_Y) && !TOUCH_ACTION_MAP[TOUCH_ACTION_PAN_Y];
27709
- var hasPanX = inStr(actions, TOUCH_ACTION_PAN_X) && !TOUCH_ACTION_MAP[TOUCH_ACTION_PAN_X];
27710
-
27711
- if (hasNone) {
27712
- //do not prevent defaults if this is a tap gesture
27713
-
27714
- var isTapPointer = input.pointers.length === 1;
27715
- var isTapMovement = input.distance < 2;
27716
- var isTapTouchTime = input.deltaTime < 250;
27717
-
27718
- if (isTapPointer && isTapMovement && isTapTouchTime) {
27719
- return;
27720
- }
27721
- }
27722
-
27723
- if (hasPanX && hasPanY) {
27724
- // `pan-x pan-y` means browser handles all scrolling/panning, do not prevent
27725
- return;
27726
- }
27727
-
27728
- if (hasNone ||
27729
- (hasPanY && direction & DIRECTION_HORIZONTAL) ||
27730
- (hasPanX && direction & DIRECTION_VERTICAL)) {
27731
- return this.preventSrc(srcEvent);
27732
- }
27733
- },
27734
-
27735
- /**
27736
- * call preventDefault to prevent the browser's default behavior (scrolling in most cases)
27737
- * @param {Object} srcEvent
27738
- */
27739
- preventSrc: function(srcEvent) {
27740
- this.manager.session.prevented = true;
27741
- srcEvent.preventDefault();
27742
- }
27743
- };
27744
-
27745
- /**
27746
- * when the touchActions are collected they are not a valid value, so we need to clean things up. *
27747
- * @param {String} actions
27748
- * @returns {*}
27749
- */
27750
- function cleanTouchActions(actions) {
27751
- // none
27752
- if (inStr(actions, TOUCH_ACTION_NONE)) {
27753
- return TOUCH_ACTION_NONE;
27754
- }
27755
-
27756
- var hasPanX = inStr(actions, TOUCH_ACTION_PAN_X);
27757
- var hasPanY = inStr(actions, TOUCH_ACTION_PAN_Y);
27758
-
27759
- // if both pan-x and pan-y are set (different recognizers
27760
- // for different directions, e.g. horizontal pan but vertical swipe?)
27761
- // we need none (as otherwise with pan-x pan-y combined none of these
27762
- // recognizers will work, since the browser would handle all panning
27763
- if (hasPanX && hasPanY) {
27764
- return TOUCH_ACTION_NONE;
27765
- }
27766
-
27767
- // pan-x OR pan-y
27768
- if (hasPanX || hasPanY) {
27769
- return hasPanX ? TOUCH_ACTION_PAN_X : TOUCH_ACTION_PAN_Y;
27770
- }
27771
-
27772
- // manipulation
27773
- if (inStr(actions, TOUCH_ACTION_MANIPULATION)) {
27774
- return TOUCH_ACTION_MANIPULATION;
27775
- }
27776
-
27777
- return TOUCH_ACTION_AUTO;
27778
- }
27779
-
27780
- function getTouchActionProps() {
27781
- if (!NATIVE_TOUCH_ACTION) {
27782
- return false;
27783
- }
27784
- var touchMap = {};
27785
- var cssSupports = window.CSS && window.CSS.supports;
27786
- ['auto', 'manipulation', 'pan-y', 'pan-x', 'pan-x pan-y', 'none'].forEach(function(val) {
27787
-
27788
- // If css.supports is not supported but there is native touch-action assume it supports
27789
- // all values. This is the case for IE 10 and 11.
27790
- touchMap[val] = cssSupports ? window.CSS.supports('touch-action', val) : true;
27791
- });
27792
- return touchMap;
27793
- }
27794
-
27795
- /**
27796
- * Recognizer flow explained; *
27797
- * All recognizers have the initial state of POSSIBLE when a input session starts.
27798
- * The definition of a input session is from the first input until the last input, with all it's movement in it. *
27799
- * Example session for mouse-input: mousedown -> mousemove -> mouseup
27800
- *
27801
- * On each recognizing cycle (see Manager.recognize) the .recognize() method is executed
27802
- * which determines with state it should be.
27803
- *
27804
- * If the recognizer has the state FAILED, CANCELLED or RECOGNIZED (equals ENDED), it is reset to
27805
- * POSSIBLE to give it another change on the next cycle.
27806
- *
27807
- * Possible
27808
- * |
27809
- * +-----+---------------+
27810
- * | |
27811
- * +-----+-----+ |
27812
- * | | |
27813
- * Failed Cancelled |
27814
- * +-------+------+
27815
- * | |
27816
- * Recognized Began
27817
- * |
27818
- * Changed
27819
- * |
27820
- * Ended/Recognized
27821
- */
27822
- var STATE_POSSIBLE = 1;
27823
- var STATE_BEGAN = 2;
27824
- var STATE_CHANGED = 4;
27825
- var STATE_ENDED = 8;
27826
- var STATE_RECOGNIZED = STATE_ENDED;
27827
- var STATE_CANCELLED = 16;
27828
- var STATE_FAILED = 32;
27829
-
27830
- /**
27831
- * Recognizer
27832
- * Every recognizer needs to extend from this class.
27833
- * @constructor
27834
- * @param {Object} options
27835
- */
27836
- function Recognizer(options) {
27837
- this.options = assign({}, this.defaults, options || {});
27838
-
27839
- this.id = uniqueId();
27840
-
27841
- this.manager = null;
27842
-
27843
- // default is enable true
27844
- this.options.enable = ifUndefined(this.options.enable, true);
27845
-
27846
- this.state = STATE_POSSIBLE;
27847
-
27848
- this.simultaneous = {};
27849
- this.requireFail = [];
27850
- }
27851
-
27852
- Recognizer.prototype = {
27853
- /**
27854
- * @virtual
27855
- * @type {Object}
27856
- */
27857
- defaults: {},
27858
-
27859
- /**
27860
- * set options
27861
- * @param {Object} options
27862
- * @return {Recognizer}
27863
- */
27864
- set: function(options) {
27865
- assign(this.options, options);
27866
-
27867
- // also update the touchAction, in case something changed about the directions/enabled state
27868
- this.manager && this.manager.touchAction.update();
27869
- return this;
27870
- },
27871
-
27872
- /**
27873
- * recognize simultaneous with an other recognizer.
27874
- * @param {Recognizer} otherRecognizer
27875
- * @returns {Recognizer} this
27876
- */
27877
- recognizeWith: function(otherRecognizer) {
27878
- if (invokeArrayArg(otherRecognizer, 'recognizeWith', this)) {
27879
- return this;
27880
- }
27881
-
27882
- var simultaneous = this.simultaneous;
27883
- otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this);
27884
- if (!simultaneous[otherRecognizer.id]) {
27885
- simultaneous[otherRecognizer.id] = otherRecognizer;
27886
- otherRecognizer.recognizeWith(this);
27887
- }
27888
- return this;
27889
- },
27890
-
27891
- /**
27892
- * drop the simultaneous link. it doesnt remove the link on the other recognizer.
27893
- * @param {Recognizer} otherRecognizer
27894
- * @returns {Recognizer} this
27895
- */
27896
- dropRecognizeWith: function(otherRecognizer) {
27897
- if (invokeArrayArg(otherRecognizer, 'dropRecognizeWith', this)) {
27898
- return this;
27899
- }
27900
-
27901
- otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this);
27902
- delete this.simultaneous[otherRecognizer.id];
27903
- return this;
27904
- },
27905
-
27906
- /**
27907
- * recognizer can only run when an other is failing
27908
- * @param {Recognizer} otherRecognizer
27909
- * @returns {Recognizer} this
27910
- */
27911
- requireFailure: function(otherRecognizer) {
27912
- if (invokeArrayArg(otherRecognizer, 'requireFailure', this)) {
27913
- return this;
27914
- }
27915
-
27916
- var requireFail = this.requireFail;
27917
- otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this);
27918
- if (inArray(requireFail, otherRecognizer) === -1) {
27919
- requireFail.push(otherRecognizer);
27920
- otherRecognizer.requireFailure(this);
27921
- }
27922
- return this;
27923
- },
27924
-
27925
- /**
27926
- * drop the requireFailure link. it does not remove the link on the other recognizer.
27927
- * @param {Recognizer} otherRecognizer
27928
- * @returns {Recognizer} this
27929
- */
27930
- dropRequireFailure: function(otherRecognizer) {
27931
- if (invokeArrayArg(otherRecognizer, 'dropRequireFailure', this)) {
27932
- return this;
27933
- }
27934
-
27935
- otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this);
27936
- var index = inArray(this.requireFail, otherRecognizer);
27937
- if (index > -1) {
27938
- this.requireFail.splice(index, 1);
27939
- }
27940
- return this;
27941
- },
27942
-
27943
- /**
27944
- * has require failures boolean
27945
- * @returns {boolean}
27946
- */
27947
- hasRequireFailures: function() {
27948
- return this.requireFail.length > 0;
27949
- },
27950
-
27951
- /**
27952
- * if the recognizer can recognize simultaneous with an other recognizer
27953
- * @param {Recognizer} otherRecognizer
27954
- * @returns {Boolean}
27955
- */
27956
- canRecognizeWith: function(otherRecognizer) {
27957
- return !!this.simultaneous[otherRecognizer.id];
27958
- },
27959
-
27960
- /**
27961
- * You should use `tryEmit` instead of `emit` directly to check
27962
- * that all the needed recognizers has failed before emitting.
27963
- * @param {Object} input
27964
- */
27965
- emit: function(input) {
27966
- var self = this;
27967
- var state = this.state;
27968
-
27969
- function emit(event) {
27970
- self.manager.emit(event, input);
27971
- }
27972
-
27973
- // 'panstart' and 'panmove'
27974
- if (state < STATE_ENDED) {
27975
- emit(self.options.event + stateStr(state));
27976
- }
27977
-
27978
- emit(self.options.event); // simple 'eventName' events
27979
-
27980
- if (input.additionalEvent) { // additional event(panleft, panright, pinchin, pinchout...)
27981
- emit(input.additionalEvent);
27982
- }
27983
-
27984
- // panend and pancancel
27985
- if (state >= STATE_ENDED) {
27986
- emit(self.options.event + stateStr(state));
27987
- }
27988
- },
27989
-
27990
- /**
27991
- * Check that all the require failure recognizers has failed,
27992
- * if true, it emits a gesture event,
27993
- * otherwise, setup the state to FAILED.
27994
- * @param {Object} input
27995
- */
27996
- tryEmit: function(input) {
27997
- if (this.canEmit()) {
27998
- return this.emit(input);
27999
- }
28000
- // it's failing anyway
28001
- this.state = STATE_FAILED;
28002
- },
28003
-
28004
- /**
28005
- * can we emit?
28006
- * @returns {boolean}
28007
- */
28008
- canEmit: function() {
28009
- var i = 0;
28010
- while (i < this.requireFail.length) {
28011
- if (!(this.requireFail[i].state & (STATE_FAILED | STATE_POSSIBLE))) {
28012
- return false;
28013
- }
28014
- i++;
28015
- }
28016
- return true;
28017
- },
28018
-
28019
- /**
28020
- * update the recognizer
28021
- * @param {Object} inputData
28022
- */
28023
- recognize: function(inputData) {
28024
- // make a new copy of the inputData
28025
- // so we can change the inputData without messing up the other recognizers
28026
- var inputDataClone = assign({}, inputData);
28027
-
28028
- // is is enabled and allow recognizing?
28029
- if (!boolOrFn(this.options.enable, [this, inputDataClone])) {
28030
- this.reset();
28031
- this.state = STATE_FAILED;
28032
- return;
28033
- }
28034
-
28035
- // reset when we've reached the end
28036
- if (this.state & (STATE_RECOGNIZED | STATE_CANCELLED | STATE_FAILED)) {
28037
- this.state = STATE_POSSIBLE;
28038
- }
28039
-
28040
- this.state = this.process(inputDataClone);
28041
-
28042
- // the recognizer has recognized a gesture
28043
- // so trigger an event
28044
- if (this.state & (STATE_BEGAN | STATE_CHANGED | STATE_ENDED | STATE_CANCELLED)) {
28045
- this.tryEmit(inputDataClone);
28046
- }
28047
- },
28048
-
28049
- /**
28050
- * return the state of the recognizer
28051
- * the actual recognizing happens in this method
28052
- * @virtual
28053
- * @param {Object} inputData
28054
- * @returns {Const} STATE
28055
- */
28056
- process: function(inputData) { }, // jshint ignore:line
28057
-
28058
- /**
28059
- * return the preferred touch-action
28060
- * @virtual
28061
- * @returns {Array}
28062
- */
28063
- getTouchAction: function() { },
28064
-
28065
- /**
28066
- * called when the gesture isn't allowed to recognize
28067
- * like when another is being recognized or it is disabled
28068
- * @virtual
28069
- */
28070
- reset: function() { }
28071
- };
28072
-
28073
- /**
28074
- * get a usable string, used as event postfix
28075
- * @param {Const} state
28076
- * @returns {String} state
28077
- */
28078
- function stateStr(state) {
28079
- if (state & STATE_CANCELLED) {
28080
- return 'cancel';
28081
- } else if (state & STATE_ENDED) {
28082
- return 'end';
28083
- } else if (state & STATE_CHANGED) {
28084
- return 'move';
28085
- } else if (state & STATE_BEGAN) {
28086
- return 'start';
28087
- }
28088
- return '';
28089
- }
28090
-
28091
- /**
28092
- * direction cons to string
28093
- * @param {Const} direction
28094
- * @returns {String}
28095
- */
28096
- function directionStr(direction) {
28097
- if (direction == DIRECTION_DOWN) {
28098
- return 'down';
28099
- } else if (direction == DIRECTION_UP) {
28100
- return 'up';
28101
- } else if (direction == DIRECTION_LEFT) {
28102
- return 'left';
28103
- } else if (direction == DIRECTION_RIGHT) {
28104
- return 'right';
28105
- }
28106
- return '';
28107
- }
28108
-
28109
- /**
28110
- * get a recognizer by name if it is bound to a manager
28111
- * @param {Recognizer|String} otherRecognizer
28112
- * @param {Recognizer} recognizer
28113
- * @returns {Recognizer}
28114
- */
28115
- function getRecognizerByNameIfManager(otherRecognizer, recognizer) {
28116
- var manager = recognizer.manager;
28117
- if (manager) {
28118
- return manager.get(otherRecognizer);
28119
- }
28120
- return otherRecognizer;
28121
- }
28122
-
28123
- /**
28124
- * This recognizer is just used as a base for the simple attribute recognizers.
28125
- * @constructor
28126
- * @extends Recognizer
28127
- */
28128
- function AttrRecognizer() {
28129
- Recognizer.apply(this, arguments);
28130
- }
28131
-
28132
- inherit(AttrRecognizer, Recognizer, {
28133
- /**
28134
- * @namespace
28135
- * @memberof AttrRecognizer
28136
- */
28137
- defaults: {
28138
- /**
28139
- * @type {Number}
28140
- * @default 1
28141
- */
28142
- pointers: 1
28143
- },
28144
-
28145
- /**
28146
- * Used to check if it the recognizer receives valid input, like input.distance > 10.
28147
- * @memberof AttrRecognizer
28148
- * @param {Object} input
28149
- * @returns {Boolean} recognized
28150
- */
28151
- attrTest: function(input) {
28152
- var optionPointers = this.options.pointers;
28153
- return optionPointers === 0 || input.pointers.length === optionPointers;
28154
- },
28155
-
28156
- /**
28157
- * Process the input and return the state for the recognizer
28158
- * @memberof AttrRecognizer
28159
- * @param {Object} input
28160
- * @returns {*} State
28161
- */
28162
- process: function(input) {
28163
- var state = this.state;
28164
- var eventType = input.eventType;
28165
-
28166
- var isRecognized = state & (STATE_BEGAN | STATE_CHANGED);
28167
- var isValid = this.attrTest(input);
28168
-
28169
- // on cancel input and we've recognized before, return STATE_CANCELLED
28170
- if (isRecognized && (eventType & INPUT_CANCEL || !isValid)) {
28171
- return state | STATE_CANCELLED;
28172
- } else if (isRecognized || isValid) {
28173
- if (eventType & INPUT_END) {
28174
- return state | STATE_ENDED;
28175
- } else if (!(state & STATE_BEGAN)) {
28176
- return STATE_BEGAN;
28177
- }
28178
- return state | STATE_CHANGED;
28179
- }
28180
- return STATE_FAILED;
28181
- }
28182
- });
28183
-
28184
- /**
28185
- * Pan
28186
- * Recognized when the pointer is down and moved in the allowed direction.
28187
- * @constructor
28188
- * @extends AttrRecognizer
28189
- */
28190
- function PanRecognizer() {
28191
- AttrRecognizer.apply(this, arguments);
28192
-
28193
- this.pX = null;
28194
- this.pY = null;
28195
- }
28196
-
28197
- inherit(PanRecognizer, AttrRecognizer, {
28198
- /**
28199
- * @namespace
28200
- * @memberof PanRecognizer
28201
- */
28202
- defaults: {
28203
- event: 'pan',
28204
- threshold: 10,
28205
- pointers: 1,
28206
- direction: DIRECTION_ALL
28207
- },
28208
-
28209
- getTouchAction: function() {
28210
- var direction = this.options.direction;
28211
- var actions = [];
28212
- if (direction & DIRECTION_HORIZONTAL) {
28213
- actions.push(TOUCH_ACTION_PAN_Y);
28214
- }
28215
- if (direction & DIRECTION_VERTICAL) {
28216
- actions.push(TOUCH_ACTION_PAN_X);
28217
- }
28218
- return actions;
28219
- },
28220
-
28221
- directionTest: function(input) {
28222
- var options = this.options;
28223
- var hasMoved = true;
28224
- var distance = input.distance;
28225
- var direction = input.direction;
28226
- var x = input.deltaX;
28227
- var y = input.deltaY;
28228
-
28229
- // lock to axis?
28230
- if (!(direction & options.direction)) {
28231
- if (options.direction & DIRECTION_HORIZONTAL) {
28232
- direction = (x === 0) ? DIRECTION_NONE : (x < 0) ? DIRECTION_LEFT : DIRECTION_RIGHT;
28233
- hasMoved = x != this.pX;
28234
- distance = Math.abs(input.deltaX);
28235
- } else {
28236
- direction = (y === 0) ? DIRECTION_NONE : (y < 0) ? DIRECTION_UP : DIRECTION_DOWN;
28237
- hasMoved = y != this.pY;
28238
- distance = Math.abs(input.deltaY);
28239
- }
28240
- }
28241
- input.direction = direction;
28242
- return hasMoved && distance > options.threshold && direction & options.direction;
28243
- },
28244
-
28245
- attrTest: function(input) {
28246
- return AttrRecognizer.prototype.attrTest.call(this, input) &&
28247
- (this.state & STATE_BEGAN || (!(this.state & STATE_BEGAN) && this.directionTest(input)));
28248
- },
28249
-
28250
- emit: function(input) {
28251
-
28252
- this.pX = input.deltaX;
28253
- this.pY = input.deltaY;
28254
-
28255
- var direction = directionStr(input.direction);
28256
-
28257
- if (direction) {
28258
- input.additionalEvent = this.options.event + direction;
28259
- }
28260
- this._super.emit.call(this, input);
28261
- }
28262
- });
28263
-
28264
- /**
28265
- * Pinch
28266
- * Recognized when two or more pointers are moving toward (zoom-in) or away from each other (zoom-out).
28267
- * @constructor
28268
- * @extends AttrRecognizer
28269
- */
28270
- function PinchRecognizer() {
28271
- AttrRecognizer.apply(this, arguments);
28272
- }
28273
-
28274
- inherit(PinchRecognizer, AttrRecognizer, {
28275
- /**
28276
- * @namespace
28277
- * @memberof PinchRecognizer
28278
- */
28279
- defaults: {
28280
- event: 'pinch',
28281
- threshold: 0,
28282
- pointers: 2
28283
- },
28284
-
28285
- getTouchAction: function() {
28286
- return [TOUCH_ACTION_NONE];
28287
- },
28288
-
28289
- attrTest: function(input) {
28290
- return this._super.attrTest.call(this, input) &&
28291
- (Math.abs(input.scale - 1) > this.options.threshold || this.state & STATE_BEGAN);
28292
- },
28293
-
28294
- emit: function(input) {
28295
- if (input.scale !== 1) {
28296
- var inOut = input.scale < 1 ? 'in' : 'out';
28297
- input.additionalEvent = this.options.event + inOut;
28298
- }
28299
- this._super.emit.call(this, input);
28300
- }
28301
- });
28302
-
28303
- /**
28304
- * Press
28305
- * Recognized when the pointer is down for x ms without any movement.
28306
- * @constructor
28307
- * @extends Recognizer
28308
- */
28309
- function PressRecognizer() {
28310
- Recognizer.apply(this, arguments);
28311
-
28312
- this._timer = null;
28313
- this._input = null;
28314
- }
28315
-
28316
- inherit(PressRecognizer, Recognizer, {
28317
- /**
28318
- * @namespace
28319
- * @memberof PressRecognizer
28320
- */
28321
- defaults: {
28322
- event: 'press',
28323
- pointers: 1,
28324
- time: 251, // minimal time of the pointer to be pressed
28325
- threshold: 9 // a minimal movement is ok, but keep it low
28326
- },
28327
-
28328
- getTouchAction: function() {
28329
- return [TOUCH_ACTION_AUTO];
28330
- },
28331
-
28332
- process: function(input) {
28333
- var options = this.options;
28334
- var validPointers = input.pointers.length === options.pointers;
28335
- var validMovement = input.distance < options.threshold;
28336
- var validTime = input.deltaTime > options.time;
28337
-
28338
- this._input = input;
28339
-
28340
- // we only allow little movement
28341
- // and we've reached an end event, so a tap is possible
28342
- if (!validMovement || !validPointers || (input.eventType & (INPUT_END | INPUT_CANCEL) && !validTime)) {
28343
- this.reset();
28344
- } else if (input.eventType & INPUT_START) {
28345
- this.reset();
28346
- this._timer = setTimeoutContext(function() {
28347
- this.state = STATE_RECOGNIZED;
28348
- this.tryEmit();
28349
- }, options.time, this);
28350
- } else if (input.eventType & INPUT_END) {
28351
- return STATE_RECOGNIZED;
28352
- }
28353
- return STATE_FAILED;
28354
- },
28355
-
28356
- reset: function() {
28357
- clearTimeout(this._timer);
28358
- },
28359
-
28360
- emit: function(input) {
28361
- if (this.state !== STATE_RECOGNIZED) {
28362
- return;
28363
- }
28364
-
28365
- if (input && (input.eventType & INPUT_END)) {
28366
- this.manager.emit(this.options.event + 'up', input);
28367
- } else {
28368
- this._input.timeStamp = now();
28369
- this.manager.emit(this.options.event, this._input);
28370
- }
28371
- }
28372
- });
28373
-
28374
- /**
28375
- * Rotate
28376
- * Recognized when two or more pointer are moving in a circular motion.
28377
- * @constructor
28378
- * @extends AttrRecognizer
28379
- */
28380
- function RotateRecognizer() {
28381
- AttrRecognizer.apply(this, arguments);
28382
- }
28383
-
28384
- inherit(RotateRecognizer, AttrRecognizer, {
28385
- /**
28386
- * @namespace
28387
- * @memberof RotateRecognizer
28388
- */
28389
- defaults: {
28390
- event: 'rotate',
28391
- threshold: 0,
28392
- pointers: 2
28393
- },
28394
-
28395
- getTouchAction: function() {
28396
- return [TOUCH_ACTION_NONE];
28397
- },
28398
-
28399
- attrTest: function(input) {
28400
- return this._super.attrTest.call(this, input) &&
28401
- (Math.abs(input.rotation) > this.options.threshold || this.state & STATE_BEGAN);
28402
- }
28403
- });
28404
-
28405
- /**
28406
- * Swipe
28407
- * Recognized when the pointer is moving fast (velocity), with enough distance in the allowed direction.
28408
- * @constructor
28409
- * @extends AttrRecognizer
28410
- */
28411
- function SwipeRecognizer() {
28412
- AttrRecognizer.apply(this, arguments);
28413
- }
28414
-
28415
- inherit(SwipeRecognizer, AttrRecognizer, {
28416
- /**
28417
- * @namespace
28418
- * @memberof SwipeRecognizer
28419
- */
28420
- defaults: {
28421
- event: 'swipe',
28422
- threshold: 10,
28423
- velocity: 0.3,
28424
- direction: DIRECTION_HORIZONTAL | DIRECTION_VERTICAL,
28425
- pointers: 1
28426
- },
28427
-
28428
- getTouchAction: function() {
28429
- return PanRecognizer.prototype.getTouchAction.call(this);
28430
- },
28431
-
28432
- attrTest: function(input) {
28433
- var direction = this.options.direction;
28434
- var velocity;
28435
-
28436
- if (direction & (DIRECTION_HORIZONTAL | DIRECTION_VERTICAL)) {
28437
- velocity = input.overallVelocity;
28438
- } else if (direction & DIRECTION_HORIZONTAL) {
28439
- velocity = input.overallVelocityX;
28440
- } else if (direction & DIRECTION_VERTICAL) {
28441
- velocity = input.overallVelocityY;
28442
- }
28443
-
28444
- return this._super.attrTest.call(this, input) &&
28445
- direction & input.offsetDirection &&
28446
- input.distance > this.options.threshold &&
28447
- input.maxPointers == this.options.pointers &&
28448
- abs(velocity) > this.options.velocity && input.eventType & INPUT_END;
28449
- },
28450
-
28451
- emit: function(input) {
28452
- var direction = directionStr(input.offsetDirection);
28453
- if (direction) {
28454
- this.manager.emit(this.options.event + direction, input);
28455
- }
28456
-
28457
- this.manager.emit(this.options.event, input);
28458
- }
28459
- });
28460
-
28461
- /**
28462
- * A tap is ecognized when the pointer is doing a small tap/click. Multiple taps are recognized if they occur
28463
- * between the given interval and position. The delay option can be used to recognize multi-taps without firing
28464
- * a single tap.
28465
- *
28466
- * The eventData from the emitted event contains the property `tapCount`, which contains the amount of
28467
- * multi-taps being recognized.
28468
- * @constructor
28469
- * @extends Recognizer
28470
- */
28471
- function TapRecognizer() {
28472
- Recognizer.apply(this, arguments);
28473
-
28474
- // previous time and center,
28475
- // used for tap counting
28476
- this.pTime = false;
28477
- this.pCenter = false;
28478
-
28479
- this._timer = null;
28480
- this._input = null;
28481
- this.count = 0;
28482
- }
28483
-
28484
- inherit(TapRecognizer, Recognizer, {
28485
- /**
28486
- * @namespace
28487
- * @memberof PinchRecognizer
28488
- */
28489
- defaults: {
28490
- event: 'tap',
28491
- pointers: 1,
28492
- taps: 1,
28493
- interval: 300, // max time between the multi-tap taps
28494
- time: 250, // max time of the pointer to be down (like finger on the screen)
28495
- threshold: 9, // a minimal movement is ok, but keep it low
28496
- posThreshold: 10 // a multi-tap can be a bit off the initial position
28497
- },
28498
-
28499
- getTouchAction: function() {
28500
- return [TOUCH_ACTION_MANIPULATION];
28501
- },
28502
-
28503
- process: function(input) {
28504
- var options = this.options;
28505
-
28506
- var validPointers = input.pointers.length === options.pointers;
28507
- var validMovement = input.distance < options.threshold;
28508
- var validTouchTime = input.deltaTime < options.time;
28509
-
28510
- this.reset();
28511
-
28512
- if ((input.eventType & INPUT_START) && (this.count === 0)) {
28513
- return this.failTimeout();
28514
- }
28515
-
28516
- // we only allow little movement
28517
- // and we've reached an end event, so a tap is possible
28518
- if (validMovement && validTouchTime && validPointers) {
28519
- if (input.eventType != INPUT_END) {
28520
- return this.failTimeout();
28521
- }
28522
-
28523
- var validInterval = this.pTime ? (input.timeStamp - this.pTime < options.interval) : true;
28524
- var validMultiTap = !this.pCenter || getDistance(this.pCenter, input.center) < options.posThreshold;
28525
-
28526
- this.pTime = input.timeStamp;
28527
- this.pCenter = input.center;
28528
-
28529
- if (!validMultiTap || !validInterval) {
28530
- this.count = 1;
28531
- } else {
28532
- this.count += 1;
28533
- }
28534
-
28535
- this._input = input;
28536
-
28537
- // if tap count matches we have recognized it,
28538
- // else it has began recognizing...
28539
- var tapCount = this.count % options.taps;
28540
- if (tapCount === 0) {
28541
- // no failing requirements, immediately trigger the tap event
28542
- // or wait as long as the multitap interval to trigger
28543
- if (!this.hasRequireFailures()) {
28544
- return STATE_RECOGNIZED;
28545
- } else {
28546
- this._timer = setTimeoutContext(function() {
28547
- this.state = STATE_RECOGNIZED;
28548
- this.tryEmit();
28549
- }, options.interval, this);
28550
- return STATE_BEGAN;
28551
- }
28552
- }
28553
- }
28554
- return STATE_FAILED;
28555
- },
28556
-
28557
- failTimeout: function() {
28558
- this._timer = setTimeoutContext(function() {
28559
- this.state = STATE_FAILED;
28560
- }, this.options.interval, this);
28561
- return STATE_FAILED;
28562
- },
28563
-
28564
- reset: function() {
28565
- clearTimeout(this._timer);
28566
- },
28567
-
28568
- emit: function() {
28569
- if (this.state == STATE_RECOGNIZED) {
28570
- this._input.tapCount = this.count;
28571
- this.manager.emit(this.options.event, this._input);
28572
- }
28573
- }
28574
- });
28575
-
28576
- /**
28577
- * Simple way to create a manager with a default set of recognizers.
28578
- * @param {HTMLElement} element
28579
- * @param {Object} [options]
28580
- * @constructor
28581
- */
28582
- function Hammer(element, options) {
28583
- options = options || {};
28584
- options.recognizers = ifUndefined(options.recognizers, Hammer.defaults.preset);
28585
- return new Manager(element, options);
28586
- }
28587
-
28588
- /**
28589
- * @const {string}
28590
- */
28591
- Hammer.VERSION = '2.0.7';
28592
-
28593
- /**
28594
- * default settings
28595
- * @namespace
28596
- */
28597
- Hammer.defaults = {
28598
- /**
28599
- * set if DOM events are being triggered.
28600
- * But this is slower and unused by simple implementations, so disabled by default.
28601
- * @type {Boolean}
28602
- * @default false
28603
- */
28604
- domEvents: false,
28605
-
28606
- /**
28607
- * The value for the touchAction property/fallback.
28608
- * When set to `compute` it will magically set the correct value based on the added recognizers.
28609
- * @type {String}
28610
- * @default compute
28611
- */
28612
- touchAction: TOUCH_ACTION_COMPUTE,
28613
-
28614
- /**
28615
- * @type {Boolean}
28616
- * @default true
28617
- */
28618
- enable: true,
28619
-
28620
- /**
28621
- * EXPERIMENTAL FEATURE -- can be removed/changed
28622
- * Change the parent input target element.
28623
- * If Null, then it is being set the to main element.
28624
- * @type {Null|EventTarget}
28625
- * @default null
28626
- */
28627
- inputTarget: null,
28628
-
28629
- /**
28630
- * force an input class
28631
- * @type {Null|Function}
28632
- * @default null
28633
- */
28634
- inputClass: null,
28635
-
28636
- /**
28637
- * Default recognizer setup when calling `Hammer()`
28638
- * When creating a new Manager these will be skipped.
28639
- * @type {Array}
28640
- */
28641
- preset: [
28642
- // RecognizerClass, options, [recognizeWith, ...], [requireFailure, ...]
28643
- [RotateRecognizer, {enable: false}],
28644
- [PinchRecognizer, {enable: false}, ['rotate']],
28645
- [SwipeRecognizer, {direction: DIRECTION_HORIZONTAL}],
28646
- [PanRecognizer, {direction: DIRECTION_HORIZONTAL}, ['swipe']],
28647
- [TapRecognizer],
28648
- [TapRecognizer, {event: 'doubletap', taps: 2}, ['tap']],
28649
- [PressRecognizer]
28650
- ],
28651
-
28652
- /**
28653
- * Some CSS properties can be used to improve the working of Hammer.
28654
- * Add them to this method and they will be set when creating a new Manager.
28655
- * @namespace
28656
- */
28657
- cssProps: {
28658
- /**
28659
- * Disables text selection to improve the dragging gesture. Mainly for desktop browsers.
28660
- * @type {String}
28661
- * @default 'none'
28662
- */
28663
- userSelect: 'none',
28664
-
28665
- /**
28666
- * Disable the Windows Phone grippers when pressing an element.
28667
- * @type {String}
28668
- * @default 'none'
28669
- */
28670
- touchSelect: 'none',
28671
-
28672
- /**
28673
- * Disables the default callout shown when you touch and hold a touch target.
28674
- * On iOS, when you touch and hold a touch target such as a link, Safari displays
28675
- * a callout containing information about the link. This property allows you to disable that callout.
28676
- * @type {String}
28677
- * @default 'none'
28678
- */
28679
- touchCallout: 'none',
28680
-
28681
- /**
28682
- * Specifies whether zooming is enabled. Used by IE10>
28683
- * @type {String}
28684
- * @default 'none'
28685
- */
28686
- contentZooming: 'none',
28687
-
28688
- /**
28689
- * Specifies that an entire element should be draggable instead of its contents. Mainly for desktop browsers.
28690
- * @type {String}
28691
- * @default 'none'
28692
- */
28693
- userDrag: 'none',
28694
-
28695
- /**
28696
- * Overrides the highlight color shown when the user taps a link or a JavaScript
28697
- * clickable element in iOS. This property obeys the alpha value, if specified.
28698
- * @type {String}
28699
- * @default 'rgba(0,0,0,0)'
28700
- */
28701
- tapHighlightColor: 'rgba(0,0,0,0)'
28702
- }
28703
- };
28704
-
28705
- var STOP = 1;
28706
- var FORCED_STOP = 2;
28707
-
28708
- /**
28709
- * Manager
28710
- * @param {HTMLElement} element
28711
- * @param {Object} [options]
28712
- * @constructor
28713
- */
28714
- function Manager(element, options) {
28715
- this.options = assign({}, Hammer.defaults, options || {});
28716
-
28717
- this.options.inputTarget = this.options.inputTarget || element;
28718
-
28719
- this.handlers = {};
28720
- this.session = {};
28721
- this.recognizers = [];
28722
- this.oldCssProps = {};
28723
-
28724
- this.element = element;
28725
- this.input = createInputInstance(this);
28726
- this.touchAction = new TouchAction(this, this.options.touchAction);
28727
-
28728
- toggleCssProps(this, true);
28729
-
28730
- each(this.options.recognizers, function(item) {
28731
- var recognizer = this.add(new (item[0])(item[1]));
28732
- item[2] && recognizer.recognizeWith(item[2]);
28733
- item[3] && recognizer.requireFailure(item[3]);
28734
- }, this);
28735
- }
28736
-
28737
- Manager.prototype = {
28738
- /**
28739
- * set options
28740
- * @param {Object} options
28741
- * @returns {Manager}
28742
- */
28743
- set: function(options) {
28744
- assign(this.options, options);
28745
-
28746
- // Options that need a little more setup
28747
- if (options.touchAction) {
28748
- this.touchAction.update();
28749
- }
28750
- if (options.inputTarget) {
28751
- // Clean up existing event listeners and reinitialize
28752
- this.input.destroy();
28753
- this.input.target = options.inputTarget;
28754
- this.input.init();
28755
- }
28756
- return this;
28757
- },
28758
-
28759
- /**
28760
- * stop recognizing for this session.
28761
- * This session will be discarded, when a new [input]start event is fired.
28762
- * When forced, the recognizer cycle is stopped immediately.
28763
- * @param {Boolean} [force]
28764
- */
28765
- stop: function(force) {
28766
- this.session.stopped = force ? FORCED_STOP : STOP;
28767
- },
28768
-
28769
- /**
28770
- * run the recognizers!
28771
- * called by the inputHandler function on every movement of the pointers (touches)
28772
- * it walks through all the recognizers and tries to detect the gesture that is being made
28773
- * @param {Object} inputData
28774
- */
28775
- recognize: function(inputData) {
28776
- var session = this.session;
28777
- if (session.stopped) {
28778
- return;
28779
- }
28780
-
28781
- // run the touch-action polyfill
28782
- this.touchAction.preventDefaults(inputData);
28783
-
28784
- var recognizer;
28785
- var recognizers = this.recognizers;
28786
-
28787
- // this holds the recognizer that is being recognized.
28788
- // so the recognizer's state needs to be BEGAN, CHANGED, ENDED or RECOGNIZED
28789
- // if no recognizer is detecting a thing, it is set to `null`
28790
- var curRecognizer = session.curRecognizer;
28791
-
28792
- // reset when the last recognizer is recognized
28793
- // or when we're in a new session
28794
- if (!curRecognizer || (curRecognizer && curRecognizer.state & STATE_RECOGNIZED)) {
28795
- curRecognizer = session.curRecognizer = null;
28796
- }
28797
-
28798
- var i = 0;
28799
- while (i < recognizers.length) {
28800
- recognizer = recognizers[i];
28801
-
28802
- // find out if we are allowed try to recognize the input for this one.
28803
- // 1. allow if the session is NOT forced stopped (see the .stop() method)
28804
- // 2. allow if we still haven't recognized a gesture in this session, or the this recognizer is the one
28805
- // that is being recognized.
28806
- // 3. allow if the recognizer is allowed to run simultaneous with the current recognized recognizer.
28807
- // this can be setup with the `recognizeWith()` method on the recognizer.
28808
- if (session.stopped !== FORCED_STOP && ( // 1
28809
- !curRecognizer || recognizer == curRecognizer || // 2
28810
- recognizer.canRecognizeWith(curRecognizer))) { // 3
28811
- recognizer.recognize(inputData);
28812
- } else {
28813
- recognizer.reset();
28814
- }
28815
-
28816
- // if the recognizer has been recognizing the input as a valid gesture, we want to store this one as the
28817
- // current active recognizer. but only if we don't already have an active recognizer
28818
- if (!curRecognizer && recognizer.state & (STATE_BEGAN | STATE_CHANGED | STATE_ENDED)) {
28819
- curRecognizer = session.curRecognizer = recognizer;
28820
- }
28821
- i++;
28822
- }
28823
- },
28824
-
28825
- /**
28826
- * get a recognizer by its event name.
28827
- * @param {Recognizer|String} recognizer
28828
- * @returns {Recognizer|Null}
28829
- */
28830
- get: function(recognizer) {
28831
- if (recognizer instanceof Recognizer) {
28832
- return recognizer;
28833
- }
28834
-
28835
- var recognizers = this.recognizers;
28836
- for (var i = 0; i < recognizers.length; i++) {
28837
- if (recognizers[i].options.event == recognizer) {
28838
- return recognizers[i];
28839
- }
28840
- }
28841
- return null;
28842
- },
28843
-
28844
- /**
28845
- * add a recognizer to the manager
28846
- * existing recognizers with the same event name will be removed
28847
- * @param {Recognizer} recognizer
28848
- * @returns {Recognizer|Manager}
28849
- */
28850
- add: function(recognizer) {
28851
- if (invokeArrayArg(recognizer, 'add', this)) {
28852
- return this;
28853
- }
28854
-
28855
- // remove existing
28856
- var existing = this.get(recognizer.options.event);
28857
- if (existing) {
28858
- this.remove(existing);
28859
- }
28860
-
28861
- this.recognizers.push(recognizer);
28862
- recognizer.manager = this;
28863
-
28864
- this.touchAction.update();
28865
- return recognizer;
28866
- },
28867
-
28868
- /**
28869
- * remove a recognizer by name or instance
28870
- * @param {Recognizer|String} recognizer
28871
- * @returns {Manager}
28872
- */
28873
- remove: function(recognizer) {
28874
- if (invokeArrayArg(recognizer, 'remove', this)) {
28875
- return this;
28876
- }
28877
-
28878
- recognizer = this.get(recognizer);
28879
-
28880
- // let's make sure this recognizer exists
28881
- if (recognizer) {
28882
- var recognizers = this.recognizers;
28883
- var index = inArray(recognizers, recognizer);
28884
-
28885
- if (index !== -1) {
28886
- recognizers.splice(index, 1);
28887
- this.touchAction.update();
28888
- }
28889
- }
28890
-
28891
- return this;
28892
- },
28893
-
28894
- /**
28895
- * bind event
28896
- * @param {String} events
28897
- * @param {Function} handler
28898
- * @returns {EventEmitter} this
28899
- */
28900
- on: function(events, handler) {
28901
- if (events === undefined$1) {
28902
- return;
28903
- }
28904
- if (handler === undefined$1) {
28905
- return;
28906
- }
28907
-
28908
- var handlers = this.handlers;
28909
- each(splitStr(events), function(event) {
28910
- handlers[event] = handlers[event] || [];
28911
- handlers[event].push(handler);
28912
- });
28913
- return this;
28914
- },
28915
-
28916
- /**
28917
- * unbind event, leave emit blank to remove all handlers
28918
- * @param {String} events
28919
- * @param {Function} [handler]
28920
- * @returns {EventEmitter} this
28921
- */
28922
- off: function(events, handler) {
28923
- if (events === undefined$1) {
28924
- return;
28925
- }
28926
-
28927
- var handlers = this.handlers;
28928
- each(splitStr(events), function(event) {
28929
- if (!handler) {
28930
- delete handlers[event];
28931
- } else {
28932
- handlers[event] && handlers[event].splice(inArray(handlers[event], handler), 1);
28933
- }
28934
- });
28935
- return this;
28936
- },
28937
-
28938
- /**
28939
- * emit event to the listeners
28940
- * @param {String} event
28941
- * @param {Object} data
28942
- */
28943
- emit: function(event, data) {
28944
- // we also want to trigger dom events
28945
- if (this.options.domEvents) {
28946
- triggerDomEvent(event, data);
28947
- }
28948
-
28949
- // no handlers, so skip it all
28950
- var handlers = this.handlers[event] && this.handlers[event].slice();
28951
- if (!handlers || !handlers.length) {
28952
- return;
28953
- }
28954
-
28955
- data.type = event;
28956
- data.preventDefault = function() {
28957
- data.srcEvent.preventDefault();
28958
- };
28959
-
28960
- var i = 0;
28961
- while (i < handlers.length) {
28962
- handlers[i](data);
28963
- i++;
28964
- }
28965
- },
28966
-
28967
- /**
28968
- * destroy the manager and unbinds all events
28969
- * it doesn't unbind dom events, that is the user own responsibility
28970
- */
28971
- destroy: function() {
28972
- this.element && toggleCssProps(this, false);
28973
-
28974
- this.handlers = {};
28975
- this.session = {};
28976
- this.input.destroy();
28977
- this.element = null;
28978
- }
28979
- };
28980
-
28981
- /**
28982
- * add/remove the css properties as defined in manager.options.cssProps
28983
- * @param {Manager} manager
28984
- * @param {Boolean} add
28985
- */
28986
- function toggleCssProps(manager, add) {
28987
- var element = manager.element;
28988
- if (!element.style) {
28989
- return;
28990
- }
28991
- var prop;
28992
- each(manager.options.cssProps, function(value, name) {
28993
- prop = prefixed(element.style, name);
28994
- if (add) {
28995
- manager.oldCssProps[prop] = element.style[prop];
28996
- element.style[prop] = value;
28997
- } else {
28998
- element.style[prop] = manager.oldCssProps[prop] || '';
28999
- }
29000
- });
29001
- if (!add) {
29002
- manager.oldCssProps = {};
29003
- }
29004
- }
29005
-
29006
- /**
29007
- * trigger dom event
29008
- * @param {String} event
29009
- * @param {Object} data
29010
- */
29011
- function triggerDomEvent(event, data) {
29012
- var gestureEvent = document.createEvent('Event');
29013
- gestureEvent.initEvent(event, true, true);
29014
- gestureEvent.gesture = data;
29015
- data.target.dispatchEvent(gestureEvent);
29016
- }
29017
-
29018
- assign(Hammer, {
29019
- INPUT_START: INPUT_START,
29020
- INPUT_MOVE: INPUT_MOVE,
29021
- INPUT_END: INPUT_END,
29022
- INPUT_CANCEL: INPUT_CANCEL,
29023
-
29024
- STATE_POSSIBLE: STATE_POSSIBLE,
29025
- STATE_BEGAN: STATE_BEGAN,
29026
- STATE_CHANGED: STATE_CHANGED,
29027
- STATE_ENDED: STATE_ENDED,
29028
- STATE_RECOGNIZED: STATE_RECOGNIZED,
29029
- STATE_CANCELLED: STATE_CANCELLED,
29030
- STATE_FAILED: STATE_FAILED,
29031
-
29032
- DIRECTION_NONE: DIRECTION_NONE,
29033
- DIRECTION_LEFT: DIRECTION_LEFT,
29034
- DIRECTION_RIGHT: DIRECTION_RIGHT,
29035
- DIRECTION_UP: DIRECTION_UP,
29036
- DIRECTION_DOWN: DIRECTION_DOWN,
29037
- DIRECTION_HORIZONTAL: DIRECTION_HORIZONTAL,
29038
- DIRECTION_VERTICAL: DIRECTION_VERTICAL,
29039
- DIRECTION_ALL: DIRECTION_ALL,
29040
-
29041
- Manager: Manager,
29042
- Input: Input,
29043
- TouchAction: TouchAction,
29044
-
29045
- TouchInput: TouchInput,
29046
- MouseInput: MouseInput,
29047
- PointerEventInput: PointerEventInput,
29048
- TouchMouseInput: TouchMouseInput,
29049
- SingleTouchInput: SingleTouchInput,
29050
-
29051
- Recognizer: Recognizer,
29052
- AttrRecognizer: AttrRecognizer,
29053
- Tap: TapRecognizer,
29054
- Pan: PanRecognizer,
29055
- Swipe: SwipeRecognizer,
29056
- Pinch: PinchRecognizer,
29057
- Rotate: RotateRecognizer,
29058
- Press: PressRecognizer,
29059
-
29060
- on: addEventListeners,
29061
- off: removeEventListeners,
29062
- each: each,
29063
- merge: merge,
29064
- extend: extend,
29065
- assign: assign,
29066
- inherit: inherit,
29067
- bindFn: bindFn,
29068
- prefixed: prefixed
29069
- });
29070
-
29071
- // this prevents errors when Hammer is loaded in the presence of an AMD
29072
- // style loader but by script tag, not by the loader.
29073
- var freeGlobal = (typeof window !== 'undefined' ? window : (typeof self !== 'undefined' ? self : {})); // jshint ignore:line
29074
- freeGlobal.Hammer = Hammer;
29075
-
29076
- if (typeof undefined$1 === 'function' && undefined$1.amd) {
29077
- undefined$1(function() {
29078
- return Hammer;
29079
- });
29080
- } else if (module.exports) {
29081
- module.exports = Hammer;
29082
- } else {
29083
- window[exportName] = Hammer;
29084
- }
29085
-
29086
- })(window, document, 'Hammer');
29087
- } (hammer));
29088
-
29089
- var hammerExports = hammer.exports;
29090
- var Hammer = /*@__PURE__*/getDefaultExportFromCjs(hammerExports);
29091
-
29092
- /**
29093
- * @typedef {import('didi').Injector} Injector
29094
- *
29095
- * @typedef {import('../../core/Canvas').default} Canvas
29096
- * @typedef {import('../../core/ElementRegistry').default} ElementRegistry
29097
- * @typedef {import('../../core/EventBus').default} EventBus
29098
- * @typedef {import('../interaction-events/InteractionEvents').default} InteractionEvents
29099
- */
29100
-
29101
- var MIN_ZOOM = 0.2,
29102
- MAX_ZOOM = 4;
29103
-
29104
- var mouseEvents = [
29105
- 'mousedown',
29106
- 'mouseup',
29107
- 'mouseover',
29108
- 'mouseout',
29109
- 'click',
29110
- 'dblclick'
29111
- ];
29112
-
29113
- function get(service, injector) {
29114
- return injector.get(service, false);
29115
- }
29116
-
29117
- function stopEvent(event) {
29118
-
29119
- event.preventDefault();
29120
-
29121
- if (typeof event.stopPropagation === 'function') {
29122
- event.stopPropagation();
29123
- } else if (event.srcEvent && typeof event.srcEvent.stopPropagation === 'function') {
29124
-
29125
- // iPhone & iPad
29126
- event.srcEvent.stopPropagation();
29127
- }
29128
-
29129
- if (typeof event.stopImmediatePropagation === 'function') {
29130
- event.stopImmediatePropagation();
29131
- }
29132
- }
29133
-
29134
-
29135
- function createTouchRecognizer(node) {
29136
-
29137
- function stopMouse(event$1) {
29138
-
29139
- forEach$1(mouseEvents, function(e) {
29140
- event.bind(node, e, stopEvent, true);
29141
- });
29142
- }
29143
-
29144
- function allowMouse(event$1) {
29145
- setTimeout(function() {
29146
- forEach$1(mouseEvents, function(e) {
29147
- event.unbind(node, e, stopEvent, true);
29148
- });
29149
- }, 500);
29150
- }
29151
-
29152
- event.bind(node, 'touchstart', stopMouse, true);
29153
- event.bind(node, 'touchend', allowMouse, true);
29154
- event.bind(node, 'touchcancel', allowMouse, true);
29155
-
29156
- // A touch event recognizer that handles
29157
- // touch events only (we know, we can already handle
29158
- // mouse events out of the box)
29159
-
29160
- var recognizer = new Hammer.Manager(node, {
29161
- inputClass: Hammer.TouchInput,
29162
- recognizers: [],
29163
- domEvents: true
29164
- });
29165
-
29166
-
29167
- var tap = new Hammer.Tap();
29168
- var pan = new Hammer.Pan({ threshold: 10 });
29169
- var press = new Hammer.Press();
29170
- var pinch = new Hammer.Pinch();
29171
-
29172
- var doubleTap = new Hammer.Tap({ event: 'doubletap', taps: 2 });
29173
-
29174
- pinch.requireFailure(pan);
29175
- pinch.requireFailure(press);
29176
-
29177
- recognizer.add([ pan, press, pinch, doubleTap, tap ]);
29178
-
29179
- recognizer.reset = function(force) {
29180
- var recognizers = this.recognizers,
29181
- session = this.session;
29182
-
29183
- if (session.stopped) {
29184
- return;
29185
- }
29186
-
29187
- recognizer.stop(force);
29188
-
29189
- setTimeout(function() {
29190
- var i, r;
29191
- for (i = 0; (r = recognizers[i]); i++) {
29192
- r.reset();
29193
- r.state = 8; // FAILED STATE
29194
- }
29195
-
29196
- session.curRecognizer = null;
29197
- }, 0);
29198
- };
29199
-
29200
- recognizer.on('hammer.input', function(event) {
29201
- if (event.srcEvent.defaultPrevented) {
29202
- recognizer.reset(true);
29203
- }
29204
- });
29205
-
29206
- return recognizer;
29207
- }
29208
-
29209
- /**
29210
- * A plugin that provides touch events for elements.
29211
- *
29212
- * @param {Injector} injector
29213
- * @param {Canvas} canvas
29214
- * @param {EventBus} eventBus
29215
- * @param {ElementRegistry} elementRegistry
29216
- * @param {InteractionEvents} interactionEvents
29217
- */
29218
- function TouchInteractionEvents(
29219
- injector, canvas, eventBus,
29220
- elementRegistry, interactionEvents) {
29221
-
29222
- // optional integrations
29223
- var dragging = get('dragging', injector),
29224
- move = get('move', injector),
29225
- contextPad = get('contextPad', injector),
29226
- palette = get('palette', injector);
29227
-
29228
- // the touch recognizer
29229
- var recognizer;
29230
-
29231
- function handler(type, buttonType) {
29232
-
29233
- return function(event) {
29234
-
29235
- var gfx = getGfx(event.target),
29236
- element = gfx && elementRegistry.get(gfx);
29237
-
29238
- // translate into an actual mouse click event
29239
- if (buttonType) {
29240
- event.srcEvent.button = buttonType;
29241
- }
29242
-
29243
- return interactionEvents.fire(type, event, element);
29244
- };
29245
- }
29246
-
29247
-
29248
- function getGfx(target) {
29249
- var node = closest(target, 'svg, .djs-element', true);
29250
- return node;
29251
- }
29252
-
29253
- function initEvents(svg) {
29254
-
29255
- // touch recognizer
29256
- recognizer = createTouchRecognizer(svg);
29257
-
29258
- function startGrabCanvas(event) {
29259
-
29260
- var lx = 0, ly = 0;
29261
-
29262
- function update(e) {
29263
-
29264
- var dx = e.deltaX - lx,
29265
- dy = e.deltaY - ly;
29266
-
29267
- canvas.scroll({ dx: dx, dy: dy });
29268
-
29269
- lx = e.deltaX;
29270
- ly = e.deltaY;
29271
- }
29272
-
29273
- function end(e) {
29274
- recognizer.off('panmove', update);
29275
- recognizer.off('panend', end);
29276
- recognizer.off('pancancel', end);
29277
- }
29278
-
29279
- recognizer.on('panmove', update);
29280
- recognizer.on('panend', end);
29281
- recognizer.on('pancancel', end);
29282
- }
29283
-
29284
- function startGrab(event) {
29285
-
29286
- var gfx = getGfx(event.target),
29287
- element = gfx && elementRegistry.get(gfx);
29288
-
29289
- // recognizer
29290
- if (move && canvas.getRootElement() !== element) {
29291
- return move.start(event, element, true);
29292
- } else {
29293
- startGrabCanvas();
29294
- }
29295
- }
29296
-
29297
- function startZoom(e) {
29298
-
29299
- var zoom = canvas.zoom(),
29300
- mid = e.center;
29301
-
29302
- function update(e) {
29303
-
29304
- var ratio = 1 - (1 - e.scale) / 1.50,
29305
- newZoom = Math.max(MIN_ZOOM, Math.min(MAX_ZOOM, ratio * zoom));
29306
-
29307
- canvas.zoom(newZoom, mid);
29308
-
29309
- stopEvent(e);
29310
- }
29311
-
29312
- function end(e) {
29313
- recognizer.off('pinchmove', update);
29314
- recognizer.off('pinchend', end);
29315
- recognizer.off('pinchcancel', end);
29316
-
29317
- recognizer.reset(true);
29318
- }
29319
-
29320
- recognizer.on('pinchmove', update);
29321
- recognizer.on('pinchend', end);
29322
- recognizer.on('pinchcancel', end);
29323
- }
29324
-
29325
- recognizer.on('tap', handler('element.click'));
29326
- recognizer.on('doubletap', handler('element.dblclick', 1));
29327
-
29328
- recognizer.on('panstart', startGrab);
29329
- recognizer.on('press', startGrab);
29330
-
29331
- recognizer.on('pinchstart', startZoom);
29332
- }
29333
-
29334
- if (dragging) {
29335
-
29336
- // simulate hover during dragging
29337
- eventBus.on('drag.move', function(event) {
29338
-
29339
- var originalEvent = event.originalEvent;
29340
-
29341
- if (!originalEvent || originalEvent instanceof MouseEvent) {
29342
- return;
29343
- }
29344
-
29345
- var position = toPoint(originalEvent);
29346
-
29347
- // this gets really expensive ...
29348
- var node = document.elementFromPoint(position.x, position.y),
29349
- gfx = getGfx(node),
29350
- element = gfx && elementRegistry.get(gfx);
29351
-
29352
- if (element !== event.hover) {
29353
- if (event.hover) {
29354
- dragging.out(event);
29355
- }
29356
-
29357
- if (element) {
29358
- dragging.hover({ element: element, gfx: gfx });
29359
-
29360
- event.hover = element;
29361
- event.hoverGfx = gfx;
29362
- }
29363
- }
29364
- });
29365
- }
29366
-
29367
- if (contextPad) {
29368
-
29369
- eventBus.on('contextPad.create', function(event) {
29370
- var node = event.pad.html;
29371
-
29372
- // touch recognizer
29373
- var padRecognizer = createTouchRecognizer(node);
29374
-
29375
- padRecognizer.on('panstart', function(event) {
29376
- contextPad.trigger('dragstart', event, true);
29377
- });
29378
-
29379
- padRecognizer.on('press', function(event) {
29380
- contextPad.trigger('dragstart', event, true);
29381
- });
29382
-
29383
- padRecognizer.on('tap', function(event) {
29384
- contextPad.trigger('click', event);
29385
- });
29386
- });
29387
- }
29388
-
29389
- if (palette) {
29390
- eventBus.on('palette.create', function(event) {
29391
- var node = event.container;
29392
-
29393
- // touch recognizer
29394
- var padRecognizer = createTouchRecognizer(node);
29395
-
29396
- padRecognizer.on('panstart', function(event) {
29397
- palette.trigger('dragstart', event, true);
29398
- });
29399
-
29400
- padRecognizer.on('press', function(event) {
29401
- palette.trigger('dragstart', event, true);
29402
- });
29403
-
29404
- padRecognizer.on('tap', function(event) {
29405
- palette.trigger('click', event);
29406
- });
29407
- });
29408
- }
29409
-
29410
- eventBus.on('canvas.init', function(event) {
29411
- initEvents(event.svg);
29412
- });
29413
- }
29414
-
29415
-
29416
- TouchInteractionEvents.$inject = [
29417
- 'injector',
29418
- 'canvas',
29419
- 'eventBus',
29420
- 'elementRegistry',
29421
- 'interactionEvents',
29422
- 'touchFix'
29423
- ];
29424
-
29425
- /**
29426
- * @typedef {import('../../core/EventBus').default} EventBus
29427
- */
29428
-
29429
- /**
29430
- * @param {EventBus} eventBus
29431
- */
29432
- function TouchFix(eventBus) {
29433
-
29434
- var self = this;
29435
-
29436
- eventBus.on('canvas.init', function(e) {
29437
- self.addBBoxMarker(e.svg);
29438
- });
29439
- }
29440
-
29441
- TouchFix.$inject = [ 'eventBus' ];
29442
-
29443
-
29444
- /**
29445
- * Safari mobile (iOS 7) does not fire touchstart event in <SVG> element
29446
- * if there is no shape between 0,0 and viewport elements origin.
29447
- *
29448
- * So touchstart event is only fired when the <g class="viewport"> element was hit.
29449
- * Putting an element over and below the 'viewport' fixes that behavior.
29450
- *
29451
- * @param {SVGElement} svg
29452
- */
29453
- TouchFix.prototype.addBBoxMarker = function(svg) {
29454
-
29455
- var markerStyle = {
29456
- fill: 'none',
29457
- class: 'outer-bound-marker'
29458
- };
29459
-
29460
- var rect1 = create$1('rect');
29461
- attr(rect1, {
29462
- x: -10000,
29463
- y: 10000,
29464
- width: 10,
29465
- height: 10
29466
- });
29467
- attr(rect1, markerStyle);
29468
-
29469
- append(svg, rect1);
29470
-
29471
- var rect2 = create$1('rect');
29472
- attr(rect2, {
29473
- x: 10000,
29474
- y: 10000,
29475
- width: 10,
29476
- height: 10
29477
- });
29478
- attr(rect2, markerStyle);
29479
-
29480
- append(svg, rect2);
29481
- };
29482
-
29483
- /**
29484
- * @type { import('didi').ModuleDeclaration }
29485
- */
29486
- var TouchModule$1 = {
29487
- __depends__: [ InteractionEventsModule$1 ],
29488
- __init__: [ 'touchInteractionEvents' ],
29489
- touchInteractionEvents: [ 'type', TouchInteractionEvents ],
29490
- touchFix: [ 'type', TouchFix ]
29491
- };
29492
-
29493
- /**
29494
- * @type { import('didi').ModuleDeclaration }
29495
- */
29496
- var TouchModule = {
29497
- __depends__: [
29498
- TouchModule$1
29499
- ]
29500
- };
29501
-
29502
26438
  /**
29503
26439
  * @typedef {import('../../model/Types').Element} Element
29504
26440
  *
@@ -30441,6 +27377,7 @@
30441
27377
  /**
30442
27378
  * @typedef {import('./PopupMenuProvider').PopupMenuEntry} PopupMenuEntry
30443
27379
  * @typedef {import('./PopupMenuProvider').PopupMenuHeaderEntry} PopupMenuHeaderEntry
27380
+ * @typedef {import('./PopupMenuProvider').PopupMenuEmptyPlaceholderProvider | import('./PopupMenuProvider').PopupMenuEmptyPlaceholder} PopupMenuEmptyPlaceholder
30444
27381
  *
30445
27382
  * @typedef {import('../../util/Types').Point} Point
30446
27383
  */
@@ -30457,6 +27394,7 @@
30457
27394
  * @param {number} props.scale
30458
27395
  * @param {string} [props.title]
30459
27396
  * @param {boolean} [props.search]
27397
+ * @param {PopupMenuEmptyPlaceholder} [props.emptyPlaceholder]
30460
27398
  * @param {number} [props.width]
30461
27399
  */
30462
27400
  function PopupMenuComponent(props) {
@@ -30470,6 +27408,7 @@
30470
27408
  width,
30471
27409
  scale,
30472
27410
  search,
27411
+ emptyPlaceholder,
30473
27412
  entries: originalEntries,
30474
27413
  onOpened,
30475
27414
  onClosed
@@ -30502,18 +27441,17 @@
30502
27441
  return false;
30503
27442
  }
30504
27443
 
30505
- const search = [
27444
+ const searchableFields = [
30506
27445
  entry.description || '',
30507
27446
  entry.label || '',
30508
27447
  entry.search || ''
30509
- ]
30510
- .join('---')
30511
- .toLowerCase();
27448
+ ].map(string => string.toLowerCase());
30512
27449
 
27450
+ // every word of `value` should be included in one of the searchable fields
30513
27451
  return value
30514
27452
  .toLowerCase()
30515
27453
  .split(/\s/g)
30516
- .every(term => search.includes(term));
27454
+ .every(word => searchableFields.some(field => field.includes(word)));
30517
27455
  };
30518
27456
 
30519
27457
  return originalEntries.filter(filter);
@@ -30618,7 +27556,7 @@
30618
27556
  onKeyup=${ handleKey }
30619
27557
  onKeydown=${ handleKeyDown }
30620
27558
  className=${ className }
30621
- position=${position}
27559
+ position=${ position }
30622
27560
  width=${ width }
30623
27561
  scale=${ scale }
30624
27562
  >
@@ -30666,8 +27604,8 @@
30666
27604
  onAction=${ onSelect }
30667
27605
  />
30668
27606
  </div>
30669
- ${ entries.length === 0 && m$1`
30670
- <div class="djs-popup-no-results">No matching entries found.</div>
27607
+ ${ emptyPlaceholder && entries.length === 0 && m$1`
27608
+ <div class="djs-popup-no-results">${ isFunction(emptyPlaceholder) ? emptyPlaceholder(value) : emptyPlaceholder }</div>
30671
27609
  ` }
30672
27610
  ` }
30673
27611
  </${PopupMenuWrapper}>
@@ -30732,7 +27670,7 @@
30732
27670
  ref=${ popupRef }
30733
27671
  tabIndex="-1"
30734
27672
  >
30735
- ${children}
27673
+ ${ children }
30736
27674
  </div>
30737
27675
  </div>
30738
27676
  `;
@@ -30842,6 +27780,7 @@
30842
27780
  className,
30843
27781
  entries,
30844
27782
  headerEntries,
27783
+ emptyPlaceholder,
30845
27784
  options
30846
27785
  } = this._current;
30847
27786
 
@@ -30871,6 +27810,7 @@
30871
27810
  className=${ className }
30872
27811
  entries=${ entriesArray }
30873
27812
  headerEntries=${ headerEntriesArray }
27813
+ emptyPlaceholder=${ emptyPlaceholder }
30874
27814
  scale=${ scale }
30875
27815
  onOpened=${ this._onOpened.bind(this) }
30876
27816
  onClosed=${ this._onClosed.bind(this) }
@@ -30909,7 +27849,8 @@
30909
27849
 
30910
27850
  const {
30911
27851
  entries,
30912
- headerEntries
27852
+ headerEntries,
27853
+ emptyPlaceholder
30913
27854
  } = this._getContext(target, providerId);
30914
27855
 
30915
27856
  this._current = {
@@ -30918,6 +27859,7 @@
30918
27859
  target,
30919
27860
  entries,
30920
27861
  headerEntries,
27862
+ emptyPlaceholder,
30921
27863
  container: this._createContainer({ provider: providerId }),
30922
27864
  options
30923
27865
  };
@@ -30942,9 +27884,12 @@
30942
27884
 
30943
27885
  const headerEntries = this._getHeaderEntries(target, providers);
30944
27886
 
27887
+ const emptyPlaceholder = this._getEmptyPlaceholder(providers);
27888
+
30945
27889
  return {
30946
27890
  entries,
30947
27891
  headerEntries,
27892
+ emptyPlaceholder,
30948
27893
  empty: !(
30949
27894
  Object.keys(entries).length ||
30950
27895
  Object.keys(headerEntries).length
@@ -31247,6 +28192,16 @@
31247
28192
  };
31248
28193
 
31249
28194
 
28195
+ PopupMenu.prototype._getEmptyPlaceholder = function(providers) {
28196
+
28197
+ const provider = providers.find(
28198
+ provider => isFunction(provider.getEmptyPlaceholder)
28199
+ );
28200
+
28201
+ return provider && provider.getEmptyPlaceholder();
28202
+ };
28203
+
28204
+
31250
28205
  /**
31251
28206
  * Check if the popup menu is open.
31252
28207
  *
@@ -31727,7 +28682,7 @@
31727
28682
  * @param {Shape} source
31728
28683
  * @param {Shape} element
31729
28684
  * @param {Point} position
31730
- * @param {(element: Element, position: Point, connectedAtPosition: Element) => Element} getNextPosition
28685
+ * @param {(element: Element, position: Point, connectedAtPosition: Element) => Point} getNextPosition
31731
28686
  *
31732
28687
  * @return {Point}
31733
28688
  */
@@ -31788,10 +28743,14 @@
31788
28743
  }
31789
28744
 
31790
28745
  /**
31791
- * Return target at given position, if defined.
28746
+ * Return connected element at given position and within given bounds. Takes
28747
+ * connected elements from host and attachers into account, too.
31792
28748
  *
31793
- * This takes connected elements from host and attachers
31794
- * into account, too.
28749
+ * @param {Shape} source
28750
+ * @param {Point} position
28751
+ * @param {Shape} element
28752
+ *
28753
+ * @return {Shape|undefined}
31795
28754
  */
31796
28755
  function getConnectedAtPosition(source, position, element) {
31797
28756
 
@@ -31827,7 +28786,7 @@
31827
28786
  * @param {(connection: Connection) => boolean} [hints.filter]
31828
28787
  * @param {(connection: Connection) => number} [hints.getWeight]
31829
28788
  * @param {number} [hints.maxDistance]
31830
- * @param {string} [hints.reference]
28789
+ * @param {'start'|'center'|'end'} [hints.reference]
31831
28790
  *
31832
28791
  * @return {number}
31833
28792
  */
@@ -31951,13 +28910,13 @@
31951
28910
  }
31952
28911
 
31953
28912
  /**
31954
- * Returns all connected elements around the given source.
28913
+ * Returns all elements connected to given source.
31955
28914
  *
31956
28915
  * This includes:
31957
28916
  *
31958
- * - connected elements
31959
- * - host connected elements
31960
- * - attachers connected elements
28917
+ * - elements connected to source
28918
+ * - elements connected to host if source is an attacher
28919
+ * - elements connected to attachers if source is a host
31961
28920
  *
31962
28921
  * @param {Shape} source
31963
28922
  *
@@ -31980,6 +28939,13 @@
31980
28939
  return allConnected;
31981
28940
  }
31982
28941
 
28942
+ /**
28943
+ * Get all connected elements.
28944
+ *
28945
+ * @param {Shape} element
28946
+ *
28947
+ * @returns {Shape[]}
28948
+ */
31983
28949
  function getConnected(element) {
31984
28950
  return getTargets(element).concat(getSources(element));
31985
28951
  }
@@ -37946,7 +34912,7 @@
37946
34912
 
37947
34913
  /**
37948
34914
  * Only call the given function when the event
37949
- * touches a bpmn:DataInputAssociation.
34915
+ * changes a bpmn:DataInputAssociation.
37950
34916
  *
37951
34917
  * @param {Function} fn
37952
34918
  * @return {Function}
@@ -64779,6 +61745,8 @@
64779
61745
  * @typedef {import('../mouse/Mouse').default} Mouse
64780
61746
  * @typedef {import('../selection/Selection').default} Selection
64781
61747
  * @typedef {import('../tool-manager/ToolManager').default} ToolManager
61748
+ *
61749
+ * @typedef {import('../../util/Types').Rect} Rect
64782
61750
  */
64783
61751
 
64784
61752
  var LASSO_TOOL_CURSOR = 'crosshair';
@@ -64867,7 +61835,9 @@
64867
61835
 
64868
61836
  // lasso interaction implementation
64869
61837
 
64870
- eventBus.on('lasso.end', function(event) {
61838
+ eventBus.on('lasso.end', 0, function(event) {
61839
+
61840
+ var context = event.context;
64871
61841
 
64872
61842
  var bbox = toBBox(event);
64873
61843
 
@@ -64875,7 +61845,9 @@
64875
61845
  return element;
64876
61846
  });
64877
61847
 
64878
- self.select(elements, bbox);
61848
+ var add = hasSecondaryModifier(event);
61849
+
61850
+ self.select(elements, bbox, add ? context.selection : []);
64879
61851
  });
64880
61852
 
64881
61853
  eventBus.on('lasso.start', function(event) {
@@ -64884,6 +61856,8 @@
64884
61856
 
64885
61857
  context.bbox = toBBox(event);
64886
61858
  visuals.create(context);
61859
+
61860
+ context.selection = selection.get();
64887
61861
  });
64888
61862
 
64889
61863
  eventBus.on('lasso.move', function(event) {
@@ -64927,7 +61901,12 @@
64927
61901
  'mouse'
64928
61902
  ];
64929
61903
 
64930
-
61904
+ /**
61905
+ * Activate lasso.
61906
+ *
61907
+ * @param {MouseEvent} event
61908
+ * @param {boolean} [autoActivate=false]
61909
+ */
64931
61910
  LassoTool.prototype.activateLasso = function(event, autoActivate) {
64932
61911
 
64933
61912
  this._dragging.init(event, 'lasso', {
@@ -64939,6 +61918,12 @@
64939
61918
  });
64940
61919
  };
64941
61920
 
61921
+ /**
61922
+ * Activate selection.
61923
+ *
61924
+ * @param {MouseEvent} event
61925
+ * @param {boolean} [autoActivate=false]
61926
+ */
64942
61927
  LassoTool.prototype.activateSelection = function(event, autoActivate) {
64943
61928
 
64944
61929
  this._dragging.init(event, 'lasso.selection', {
@@ -64947,16 +61932,30 @@
64947
61932
  cursor: LASSO_TOOL_CURSOR,
64948
61933
  data: {
64949
61934
  context: {}
64950
- }
61935
+ },
61936
+ keepSelection: true
64951
61937
  });
64952
61938
  };
64953
61939
 
64954
- LassoTool.prototype.select = function(elements, bbox) {
61940
+ /**
61941
+ * Select elements within the given bounds.
61942
+ *
61943
+ * @param {Element[]} elements
61944
+ * @param {Rect} bbox
61945
+ * @param {Element[]} [previousSelection]
61946
+ */
61947
+ LassoTool.prototype.select = function(elements, bbox, previousSelection = []) {
64955
61948
  var selectedElements = getEnclosedElements(elements, bbox);
64956
61949
 
64957
- this._selection.select(values(selectedElements));
61950
+ this._selection.select([
61951
+ ...previousSelection,
61952
+ ...values(selectedElements)
61953
+ ]);
64958
61954
  };
64959
61955
 
61956
+ /**
61957
+ * Toggle the lasso tool.
61958
+ */
64960
61959
  LassoTool.prototype.toggle = function() {
64961
61960
  if (this.isActive()) {
64962
61961
  return this._dragging.cancel();
@@ -64967,6 +61966,11 @@
64967
61966
  this.activateSelection(mouseEvent, !!mouseEvent);
64968
61967
  };
64969
61968
 
61969
+ /**
61970
+ * Check if the lasso tool is active.
61971
+ *
61972
+ * @returns {boolean}
61973
+ */
64970
61974
  LassoTool.prototype.isActive = function() {
64971
61975
  var context = this._dragging.context();
64972
61976
 
@@ -64974,7 +61978,6 @@
64974
61978
  };
64975
61979
 
64976
61980
 
64977
-
64978
61981
  function toBBox(event) {
64979
61982
 
64980
61983
  var start = {
@@ -67775,7 +64778,6 @@
67775
64778
  // non-modeling components
67776
64779
  KeyboardMoveModule,
67777
64780
  MoveCanvasModule,
67778
- TouchModule,
67779
64781
  ZoomScrollModule
67780
64782
  ];
67781
64783