2
* what-input - A global utility for tracking the current input method (mouse, keyboard or touch).
4
* @link https://github.com/ten1seven/what-input
7
(function webpackUniversalModuleDefinition(root, factory) {
8
if(typeof exports === 'object' && typeof module === 'object')
9
module.exports = factory();
10
else if(typeof define === 'function' && define.amd)
11
define("whatInput", [], factory);
12
else if(typeof exports === 'object')
13
exports["whatInput"] = factory();
15
root["whatInput"] = factory();
17
return /******/ (function(modules) { // webpackBootstrap
18
/******/ // The module cache
19
/******/ var installedModules = {};
21
/******/ // The require function
22
/******/ function __webpack_require__(moduleId) {
24
/******/ // Check if module is in cache
25
/******/ if(installedModules[moduleId])
26
/******/ return installedModules[moduleId].exports;
28
/******/ // Create a new module (and put it into the cache)
29
/******/ var module = installedModules[moduleId] = {
31
/******/ id: moduleId,
32
/******/ loaded: false
35
/******/ // Execute the module function
36
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
38
/******/ // Flag the module as loaded
39
/******/ module.loaded = true;
41
/******/ // Return the exports of the module
42
/******/ return module.exports;
46
/******/ // expose the modules object (__webpack_modules__)
47
/******/ __webpack_require__.m = modules;
49
/******/ // expose the module cache
50
/******/ __webpack_require__.c = installedModules;
52
/******/ // __webpack_public_path__
53
/******/ __webpack_require__.p = "";
55
/******/ // Load entry module and return exports
56
/******/ return __webpack_require__(0);
58
/************************************************************************/
61
/***/ (function(module, exports) {
65
module.exports = function () {
67
* bail out if there is no document or window
68
* (i.e. in a node/non-DOM environment)
70
* Return a stubbed API instead
72
if (typeof document === 'undefined' || typeof window === 'undefined') {
74
// always return "initial" because no interaction will ever be detected
80
element: function element() {
85
ignoreKeys: function ignoreKeys() {},
88
specificKeys: function specificKeys() {},
91
registerOnChange: function registerOnChange() {},
94
unRegisterOnChange: function unRegisterOnChange() {}
102
// cache document.documentElement
103
var docElem = document.documentElement;
105
// currently focused dom element
106
var currentElement = null;
108
// last used input type
109
var currentInput = 'initial';
111
// last used input intent
112
var currentIntent = currentInput;
114
// check for sessionStorage support
115
// then check for session variables and use if available
117
if (window.sessionStorage.getItem('what-input')) {
118
currentInput = window.sessionStorage.getItem('what-input');
121
if (window.sessionStorage.getItem('what-intent')) {
122
currentIntent = window.sessionStorage.getItem('what-intent');
126
// event buffer timer
127
var eventTimer = null;
130
var formInputs = ['input', 'select', 'textarea'];
132
// empty array for holding callback functions
133
var functionList = [];
135
// list of modifier keys commonly used with the mouse and
136
// can be safely ignored to prevent false keyboard detection
137
var ignoreMap = [16, // shift
140
91, // Windows key / left Apple cmd
141
93 // Windows menu / right Apple cmd
144
var specificMap = [];
146
// mapping of events to input types
152
MSPointerDown: 'pointer',
153
MSPointerMove: 'pointer',
154
pointerdown: 'pointer',
155
pointermove: 'pointer',
158
// boolean: true if touch buffer is active
159
};var isBuffering = false;
161
// boolean: true if the page is being scrolled
162
var isScrolling = false;
164
// store current mouse position
169
// map of IE 10 pointer events
172
3: 'touch', // treat pen like touch
175
// check support for passive event listeners
176
};var supportsPassive = false;
179
var opts = Object.defineProperty({}, 'passive', {
180
get: function get() {
181
supportsPassive = true;
185
window.addEventListener('test', null, opts);
192
var setUp = function setUp() {
193
// add correct mouse wheel event mapping to `inputMap`
194
inputMap[detectWheel()] = 'mouse';
205
var addListeners = function addListeners() {
206
// `pointermove`, `MSPointerMove`, `mousemove` and mouse wheel event binding
207
// can only demonstrate potential, but not actual, interaction
208
// and are treated separately
209
var options = supportsPassive ? { passive: true } : false;
211
// pointer events (mouse, pen, touch)
212
if (window.PointerEvent) {
213
window.addEventListener('pointerdown', setInput);
214
window.addEventListener('pointermove', setIntent);
215
} else if (window.MSPointerEvent) {
216
window.addEventListener('MSPointerDown', setInput);
217
window.addEventListener('MSPointerMove', setIntent);
220
window.addEventListener('mousedown', setInput);
221
window.addEventListener('mousemove', setIntent);
224
if ('ontouchstart' in window) {
225
window.addEventListener('touchstart', eventBuffer, options);
226
window.addEventListener('touchend', setInput);
231
window.addEventListener(detectWheel(), setIntent, options);
234
window.addEventListener('keydown', eventBuffer);
235
window.addEventListener('keyup', eventBuffer);
238
window.addEventListener('focusin', setElement);
239
window.addEventListener('focusout', clearElement);
242
// checks conditions before updating new input
243
var setInput = function setInput(event) {
244
// only execute if the event buffer timer isn't running
246
var eventKey = event.which;
247
var value = inputMap[event.type];
249
if (value === 'pointer') {
250
value = pointerType(event);
253
var ignoreMatch = !specificMap.length && ignoreMap.indexOf(eventKey) === -1;
255
var specificMatch = specificMap.length && specificMap.indexOf(eventKey) !== -1;
257
var shouldUpdate = value === 'keyboard' && eventKey && (ignoreMatch || specificMatch) || value === 'mouse' || value === 'touch';
259
if (currentInput !== value && shouldUpdate) {
260
currentInput = value;
263
window.sessionStorage.setItem('what-input', currentInput);
269
if (currentIntent !== value && shouldUpdate) {
270
// preserve intent for keyboard typing in form fields
271
var activeElem = document.activeElement;
272
var notFormInput = activeElem && activeElem.nodeName && formInputs.indexOf(activeElem.nodeName.toLowerCase()) === -1;
275
currentIntent = value;
278
window.sessionStorage.setItem('what-intent', currentIntent);
287
// updates the doc and `inputTypes` array with new input
288
var doUpdate = function doUpdate(which) {
289
docElem.setAttribute('data-what' + which, which === 'input' ? currentInput : currentIntent);
291
fireFunctions(which);
294
// updates input intent for `mousemove` and `pointermove`
295
var setIntent = function setIntent(event) {
296
// test to see if `mousemove` happened relative to the screen to detect scrolling versus mousemove
297
detectScrolling(event);
299
// only execute if the event buffer timer isn't running
300
// or scrolling isn't happening
301
if (!isBuffering && !isScrolling) {
302
var value = inputMap[event.type];
303
if (value === 'pointer') {
304
value = pointerType(event);
307
if (currentIntent !== value) {
308
currentIntent = value;
311
window.sessionStorage.setItem('what-intent', currentIntent);
319
var setElement = function setElement(event) {
320
if (!event.target.nodeName) {
321
// If nodeName is undefined, clear the element
322
// This can happen if click inside an <svg> element.
327
currentElement = event.target.nodeName.toLowerCase();
328
docElem.setAttribute('data-whatelement', currentElement);
330
if (event.target.classList && event.target.classList.length) {
331
docElem.setAttribute('data-whatclasses', event.target.classList.toString().replace(' ', ','));
335
var clearElement = function clearElement() {
336
currentElement = null;
338
docElem.removeAttribute('data-whatelement');
339
docElem.removeAttribute('data-whatclasses');
342
// buffers events that frequently also fire mouse events
343
var eventBuffer = function eventBuffer(event) {
344
// set the current input
347
// clear the timer if it happens to be running
348
window.clearTimeout(eventTimer);
350
// set the isBuffering to `true`
354
eventTimer = window.setTimeout(function () {
355
// if the timer runs out, set isBuffering back to `false`
364
var pointerType = function pointerType(event) {
365
if (typeof event.pointerType === 'number') {
366
return pointerMap[event.pointerType];
368
// treat pen like touch
369
return event.pointerType === 'pen' ? 'touch' : event.pointerType;
373
// detect version of mouse wheel event to use
374
// via https://developer.mozilla.org/en-US/docs/Web/Events/wheel
375
var detectWheel = function detectWheel() {
376
var wheelType = void 0;
378
// Modern browsers support "wheel"
379
if ('onwheel' in document.createElement('div')) {
382
// Webkit and IE support at least "mousewheel"
383
// or assume that remaining browsers are older Firefox
384
wheelType = document.onmousewheel !== undefined ? 'mousewheel' : 'DOMMouseScroll';
390
// runs callback functions
391
var fireFunctions = function fireFunctions(type) {
392
for (var i = 0, len = functionList.length; i < len; i++) {
393
if (functionList[i].type === type) {
394
functionList[i].fn.call(undefined, type === 'input' ? currentInput : currentIntent);
399
// finds matching element in an object
400
var objPos = function objPos(match) {
401
for (var i = 0, len = functionList.length; i < len; i++) {
402
if (functionList[i].fn === match) {
408
var detectScrolling = function detectScrolling(event) {
409
if (mousePos['x'] !== event.screenX || mousePos['y'] !== event.screenY) {
412
mousePos['x'] = event.screenX;
413
mousePos['y'] = event.screenY;
423
// don't start script unless browser cuts the mustard
424
// (also passes if polyfills are used)
425
if ('addEventListener' in window && Array.prototype.indexOf) {
434
// returns string: the current input type
435
// opt: 'intent'|'input'
436
// 'input' (default): returns the same value as the `data-whatinput` attribute
437
// 'intent': includes `data-whatintent` value if it's different than `data-whatinput`
438
ask: function ask(opt) {
439
return opt === 'intent' ? currentIntent : currentInput;
442
// returns string: the currently focused element or null
443
element: function element() {
444
return currentElement;
447
// overwrites ignored keys with provided array
448
ignoreKeys: function ignoreKeys(arr) {
452
// overwrites specific char keys to update on
453
specificKeys: function specificKeys(arr) {
457
// attach functions to input and intent "events"
458
// funct: function to fire on change
459
// eventType: 'input'|'intent'
460
registerOnChange: function registerOnChange(fn, eventType) {
463
type: eventType || 'input'
467
unRegisterOnChange: function unRegisterOnChange(fn) {
468
var position = objPos(fn);
470
if (position || position === 0) {
471
functionList.splice(position, 1);
b'\\ No newline at end of file'