UNPKG

6.3 kBJavaScriptView Raw
1/** @module interact */
2
3const browser = require('./utils/browser');
4const events = require('./utils/events');
5const utils = require('./utils');
6const scope = require('./scope');
7const Interactable = require('./Interactable');
8const Interaction = require('./Interaction');
9
10const globalEvents = {};
11
12/**
13 * ```js
14 * interact('#draggable').draggable(true);
15 *
16 * var rectables = interact('rect');
17 * rectables
18 * .gesturable(true)
19 * .on('gesturemove', function (event) {
20 * // ...
21 * });
22 * ```
23 *
24 * The methods of this variable can be used to set elements as interactables
25 * and also to change various default settings.
26 *
27 * Calling it as a function and passing an element or a valid CSS selector
28 * string returns an Interactable object which has various methods to configure
29 * it.
30 *
31 * @global
32 *
33 * @param {Element | string} element The HTML or SVG Element to interact with
34 * or CSS selector
35 * @return {Interactable}
36 */
37function interact (element, options) {
38 let interactable = scope.interactables.get(element, options);
39
40 if (!interactable) {
41 interactable = new Interactable(element, options);
42 interactable.events.global = globalEvents;
43 }
44
45 return interactable;
46}
47
48/**
49 * Check if an element or selector has been set with the {@link interact}
50 * function
51 *
52 * @alias module:interact.isSet
53 *
54 * @param {Element} element The Element being searched for
55 * @return {boolean} Indicates if the element or CSS selector was previously
56 * passed to interact
57*/
58interact.isSet = function (element, options) {
59 return scope.interactables.indexOfElement(element, options && options.context) !== -1;
60};
61
62/**
63 * Add a global listener for an InteractEvent or adds a DOM event to `document`
64 *
65 * @alias module:interact.on
66 *
67 * @param {string | array | object} type The types of events to listen for
68 * @param {function} listener The function event (s)
69 * @param {object | boolean} [options] object or useCapture flag for
70 * addEventListener
71 * @return {object} interact
72 */
73interact.on = function (type, listener, options) {
74 if (utils.is.string(type) && type.search(' ') !== -1) {
75 type = type.trim().split(/ +/);
76 }
77
78 if (utils.is.array(type)) {
79 for (const eventType of type) {
80 interact.on(eventType, listener, options);
81 }
82
83 return interact;
84 }
85
86 if (utils.is.object(type)) {
87 for (const prop in type) {
88 interact.on(prop, type[prop], listener);
89 }
90
91 return interact;
92 }
93
94 // if it is an InteractEvent type, add listener to globalEvents
95 if (utils.contains(Interactable.eventTypes, type)) {
96 // if this type of event was never bound
97 if (!globalEvents[type]) {
98 globalEvents[type] = [listener];
99 }
100 else {
101 globalEvents[type].push(listener);
102 }
103 }
104 // If non InteractEvent type, addEventListener to document
105 else {
106 events.add(scope.document, type, listener, { options });
107 }
108
109 return interact;
110};
111
112/**
113 * Removes a global InteractEvent listener or DOM event from `document`
114 *
115 * @alias module:interact.off
116 *
117 * @param {string | array | object} type The types of events that were listened
118 * for
119 * @param {function} listener The listener function to be removed
120 * @param {object | boolean} options [options] object or useCapture flag for
121 * removeEventListener
122 * @return {object} interact
123 */
124interact.off = function (type, listener, options) {
125 if (utils.is.string(type) && type.search(' ') !== -1) {
126 type = type.trim().split(/ +/);
127 }
128
129 if (utils.is.array(type)) {
130 for (const eventType of type) {
131 interact.off(eventType, listener, options);
132 }
133
134 return interact;
135 }
136
137 if (utils.is.object(type)) {
138 for (const prop in type) {
139 interact.off(prop, type[prop], listener);
140 }
141
142 return interact;
143 }
144
145 if (!utils.contains(Interactable.eventTypes, type)) {
146 events.remove(scope.document, type, listener, options);
147 }
148 else {
149 let index;
150
151 if (type in globalEvents
152 && (index = globalEvents[type].indexOf(listener)) !== -1) {
153 globalEvents[type].splice(index, 1);
154 }
155 }
156
157 return interact;
158};
159
160/**
161 * Returns an object which exposes internal data
162
163 * @alias module:interact.debug
164 *
165 * @return {object} An object with properties that outline the current state
166 * and expose internal functions and variables
167 */
168interact.debug = function () {
169 return scope;
170};
171
172// expose the functions used to calculate multi-touch properties
173interact.getPointerAverage = utils.pointerAverage;
174interact.getTouchBBox = utils.touchBBox;
175interact.getTouchDistance = utils.touchDistance;
176interact.getTouchAngle = utils.touchAngle;
177
178interact.getElementRect = utils.getElementRect;
179interact.getElementClientRect = utils.getElementClientRect;
180interact.matchesSelector = utils.matchesSelector;
181interact.closest = utils.closest;
182
183/**
184 * @alias module:interact.supportsTouch
185 *
186 * @return {boolean} Whether or not the browser supports touch input
187 */
188interact.supportsTouch = function () {
189 return browser.supportsTouch;
190};
191
192/**
193 * @alias module:interact.supportsPointerEvent
194 *
195 * @return {boolean} Whether or not the browser supports PointerEvents
196 */
197interact.supportsPointerEvent = function () {
198 return browser.supportsPointerEvent;
199};
200
201/**
202 * Cancels all interactions (end events are not fired)
203 *
204 * @alias module:interact.stop
205 *
206 * @param {Event} event An event on which to call preventDefault()
207 * @return {object} interact
208 */
209interact.stop = function (event) {
210 for (let i = scope.interactions.length - 1; i >= 0; i--) {
211 scope.interactions[i].stop(event);
212 }
213
214 return interact;
215};
216
217/**
218 * Returns or sets the distance the pointer must be moved before an action
219 * sequence occurs. This also affects tolerance for tap events.
220 *
221 * @alias module:interact.pointerMoveTolerance
222 *
223 * @param {number} [newValue] The movement from the start position must be greater than this value
224 * @return {interact | number}
225 */
226interact.pointerMoveTolerance = function (newValue) {
227 if (utils.is.number(newValue)) {
228 Interaction.pointerMoveTolerance = newValue;
229
230 return interact;
231 }
232
233 return Interaction.pointerMoveTolerance;
234};
235
236interact.addDocument = scope.addDocument;
237interact.removeDocument = scope.removeDocument;
238
239scope.interact = interact;
240
241module.exports = interact;