foundation-ultimate
Version:
The Ultimate Foundation Package with both FoundationApps and Foundation Sites Included
221 lines (169 loc) • 4.75 kB
JavaScript
;(function(root, factory) {
if (typeof define === 'function' && define.amd) {
define([], function() {
return (factory());
});
} else if (typeof exports === 'object') {
module.exports = factory();
} else {
root.whatInput = factory();
}
} (this, function() {
'use strict';
/*
---------------
variables
---------------
*/
// array of actively pressed keys
var activeKeys = [];
// cache document.body
var body = document.body;
// boolean: true if touch buffer timer is running
var buffer = false;
// the last used input type
var currentInput = null;
// array of form elements that take keyboard input
var formInputs = [
'input',
'select',
'textarea'
];
// user-set flag to allow typing in form fields to be recorded
var formTyping = body.hasAttribute('data-whatinput-formtyping');
// mapping of events to input types
var inputMap = {
'keydown': 'keyboard',
'mousedown': 'mouse',
'mouseenter': 'mouse',
'touchstart': 'touch',
'pointerdown': 'pointer',
'MSPointerDown': 'pointer'
};
// array of all used input types
var inputTypes = [];
// mapping of key codes to common name
var keyMap = {
9: 'tab',
13: 'enter',
16: 'shift',
27: 'esc',
32: 'space',
37: 'left',
38: 'up',
39: 'right',
40: 'down'
};
// map of IE 10 pointer events
var pointerMap = {
2: 'touch',
3: 'touch', // treat pen like touch
4: 'mouse'
};
// touch buffer timer
var timer;
/*
---------------
functions
---------------
*/
function bufferInput(event) {
clearTimeout(timer);
setInput(event);
buffer = true;
timer = setTimeout(function() {
buffer = false;
}, 1000);
}
function immediateInput(event) {
if (!buffer) setInput(event);
}
function setInput(event) {
var eventKey = key(event);
var eventTarget = target(event);
var value = inputMap[event.type];
if (value === 'pointer') value = pointerType(event);
if (currentInput !== value) {
if (
// only if the user flag isn't set
!formTyping &&
// only if currentInput has a value
currentInput &&
// only if the input is `keyboard`
value === 'keyboard' &&
// not if the key is `TAB`
keyMap[eventKey] !== 'tab' &&
// only if the target is one of the elements in `formInputs`
formInputs.indexOf(eventTarget.nodeName.toLowerCase()) >= 0
) {
// ignore keyboard typing on form elements
} else {
currentInput = value;
body.setAttribute('data-whatinput', currentInput);
if (inputTypes.indexOf(currentInput) === -1) inputTypes.push(currentInput);
}
}
if (value === 'keyboard') logKeys(eventKey);
}
function key(event) {
return (event.keyCode) ? event.keyCode : event.which;
}
function target(event) {
return event.target || event.srcElement;
}
function pointerType(event) {
return (typeof event.pointerType === 'number') ? pointerMap[event.pointerType] : event.pointerType;
}
// keyboard logging
function logKeys(eventKey) {
if (activeKeys.indexOf(keyMap[eventKey]) === -1 && keyMap[eventKey]) activeKeys.push(keyMap[eventKey]);
}
function unLogKeys(event) {
var eventKey = key(event);
var arrayPos = activeKeys.indexOf(keyMap[eventKey]);
if (arrayPos !== -1) activeKeys.splice(arrayPos, 1);
}
function bindEvents() {
// pointer/mouse
var mouseEvent = 'mousedown';
if (window.PointerEvent) {
mouseEvent = 'pointerdown';
} else if (window.MSPointerEvent) {
mouseEvent = 'MSPointerDown';
}
body.addEventListener(mouseEvent, immediateInput);
body.addEventListener('mouseenter', immediateInput);
// touch
if ('ontouchstart' in window) {
body.addEventListener('touchstart', bufferInput);
}
// keyboard
body.addEventListener('keydown', immediateInput);
document.addEventListener('keyup', unLogKeys);
}
/*
---------------
init
don't start script unless browser cuts the mustard,
also passes if polyfills are used
---------------
*/
if ('addEventListener' in window && Array.prototype.indexOf) {
bindEvents();
}
/*
---------------
api
---------------
*/
return {
// returns string: the current input type
ask: function() { return currentInput; },
// returns array: currently pressed keys
keys: function() { return activeKeys; },
// returns array: all the detected input types
types: function() { return inputTypes; },
// accepts string: manually set the input type
set: setInput
};
}));