const Interactable = require('./Interactable');
const Interaction = require('./Interaction');
const scope = require('./scope');
const is = require('./utils/is');
const events = require('./utils/events');
const browser = require('./utils/browser');
const { nodeContains, matchesSelector } = require('./utils/domUtils');
/**
* Returns or sets whether to prevent the browser's default behaviour in
* response to pointer events. Can be set to:
* - `'always'` to always prevent
* - `'never'` to never prevent
* - `'auto'` to let interact.js try to determine what would be best
*
* @param {string} [newValue] `true`, `false` or `'auto'`
* @return {string | Interactable} The current setting or this Interactable
*/
Interactable.prototype.preventDefault = function (newValue) {
if (/^(always|never|auto)$/.test(newValue)) {
this.options.preventDefault = newValue;
return this;
}
if (is.bool(newValue)) {
this.options.preventDefault = newValue? 'always' : 'never';
return this;
}
return this.options.preventDefault;
};
Interactable.prototype.checkAndPreventDefault = function (event) {
const setting = this.options.preventDefault;
if (setting === 'never') { return; }
if (setting === 'always') {
event.preventDefault();
return;
}
// setting === 'auto'
// don't preventDefault of touch{start,move} events if the browser supports passive
// events listeners. CSS touch-action and user-selecct should be used instead
if (events.supportsPassive
&& /^touch(start|move)$/.test(event.type)
&& !browser.isIOS) {
return;
}
// don't preventDefault of pointerdown events
if (/^(mouse|pointer|touch)*(down|start)/i.test(event.type)) {
return;
}
// don't preventDefault on editable elements
if (is.element(event.target)
&& matchesSelector(event.target, 'input,select,textarea,[contenteditable=true],[contenteditable=true] *')) {
return;
}
event.preventDefault();
};
function onInteractionEvent ({ interaction, event }) {
if (interaction.target) {
interaction.target.checkAndPreventDefault(event);
}
}
for (const eventSignal of ['down', 'move', 'up', 'cancel']) {
Interaction.signals.on(eventSignal, onInteractionEvent);
}
// prevent native HTML5 drag on interact.js target elements
Interaction.docEvents.dragstart = function preventNativeDrag (event) {
for (const interaction of scope.interactions) {
if (interaction.element
&& (interaction.element === event.target
|| nodeContains(interaction.element, event.target))) {
interaction.target.checkAndPreventDefault(event);
return;
}
}
};