1;(function(root, factory) { 2 if (typeof define === 'function' && define.amd) { 3 define([], function() { 4 return (factory()); 5 }); 6 } else if (typeof exports === 'object') { 7 module.exports = factory(); 8 } else { 9 root.whatInput = factory(); 10 } 11} (this, function() { 12 'use strict'; 13 14 15 /* 16 --------------- 17 variables 18 --------------- 19 */ 20 21 // array of actively pressed keys 22 var activeKeys = []; 23 24 // cache document.body 25 var body = document.body; 26 27 // boolean: true if touch buffer timer is running 28 var buffer = false; 29 30 // the last used input type 31 var currentInput = null; 32 33 // array of form elements that take keyboard input 34 var formInputs = [ 35 'input', 36 'select', 37 'textarea' 38 ]; 39 40 // user-set flag to allow typing in form fields to be recorded 41 var formTyping = body.hasAttribute('data-whatinput-formtyping'); 42 43 // mapping of events to input types 44 var inputMap = { 45 'keydown': 'keyboard', 46 'mousedown': 'mouse', 47 'mouseenter': 'mouse', 48 'touchstart': 'touch', 49 'pointerdown': 'pointer', 50 'MSPointerDown': 'pointer' 51 }; 52 53 // array of all used input types 54 var inputTypes = []; 55 56 // mapping of key codes to common name 57 var keyMap = { 58 9: 'tab', 59 13: 'enter', 60 16: 'shift', 61 27: 'esc', 62 32: 'space', 63 37: 'left', 64 38: 'up', 65 39: 'right', 66 40: 'down' 67 }; 68 69 // map of IE 10 pointer events 70 var pointerMap = { 71 2: 'touch', 72 3: 'touch', // treat pen like touch 73 4: 'mouse' 74 }; 75 76 // touch buffer timer 77 var timer; 78 79 80 /* 81 --------------- 82 functions 83 --------------- 84 */ 85 86 function bufferInput(event) { 87 clearTimeout(timer); 88 89 setInput(event); 90 91 buffer = true; 92 timer = setTimeout(function() { 93 buffer = false; 94 }, 1000); 95 } 96 97 function immediateInput(event) { 98 if (!buffer) setInput(event); 99 } 100 101 function setInput(event) { 102 var eventKey = key(event); 103 var eventTarget = target(event); 104 var value = inputMap[event.type]; 105 if (value === 'pointer') value = pointerType(event); 106 107 if (currentInput !== value) { 108 if ( 109 // only if the user flag isn't set 110 !formTyping && 111 112 // only if currentInput has a value 113 currentInput && 114 115 // only if the input is `keyboard` 116 value === 'keyboard' && 117 118 // not if the key is `TAB` 119 keyMap[eventKey] !== 'tab' && 120 121 // only if the target is one of the elements in `formInputs` 122 formInputs.indexOf(eventTarget.nodeName.toLowerCase()) >= 0 123 ) { 124 // ignore keyboard typing on form elements 125 } else { 126 currentInput = value; 127 body.setAttribute('data-whatinput', currentInput); 128 129 if (inputTypes.indexOf(currentInput) === -1) inputTypes.push(currentInput); 130 } 131 } 132 133 if (value === 'keyboard') logKeys(eventKey); 134 } 135 136 function key(event) { 137 return (event.keyCode) ? event.keyCode : event.which; 138 } 139 140 function target(event) { 141 return event.target || event.srcElement; 142 } 143 144 function pointerType(event) { 145 return (typeof event.pointerType === 'number') ? pointerMap[event.pointerType] : event.pointerType; 146 } 147 148 // keyboard logging 149 function logKeys(eventKey) { 150 if (activeKeys.indexOf(keyMap[eventKey]) === -1 && keyMap[eventKey]) activeKeys.push(keyMap[eventKey]); 151 } 152 153 function unLogKeys(event) { 154 var eventKey = key(event); 155 var arrayPos = activeKeys.indexOf(keyMap[eventKey]); 156 157 if (arrayPos !== -1) activeKeys.splice(arrayPos, 1); 158 } 159 160 function bindEvents() { 161 162 // pointer/mouse 163 var mouseEvent = 'mousedown'; 164 165 if (window.PointerEvent) { 166 mouseEvent = 'pointerdown'; 167 } else if (window.MSPointerEvent) { 168 mouseEvent = 'MSPointerDown'; 169 } 170 171 body.addEventListener(mouseEvent, immediateInput); 172 body.addEventListener('mouseenter', immediateInput); 173 174 // touch 175 if ('ontouchstart' in document.documentElement) { 176 body.addEventListener('touchstart', bufferInput); 177 } 178 179 // keyboard 180 body.addEventListener('keydown', immediateInput); 181 document.addEventListener('keyup', unLogKeys); 182 } 183 184 185 /* 186 --------------- 187 init 188 189 don't start script unless browser cuts the mustard, 190 also passes if polyfills are used 191 --------------- 192 */ 193 194 if ('addEventListener' in window && Array.prototype.indexOf) { 195 bindEvents(); 196 } 197 198 199 /* 200 --------------- 201 api 202 --------------- 203 */ 204 205 return { 206 207 // returns string: the current input type 208 ask: function() { return currentInput; }, 209 210 // returns array: currently pressed keys 211 keys: function() { return activeKeys; }, 212 213 // returns array: all the detected input types 214 types: function() { return inputTypes; }, 215 216 // accepts string: manually set the input type 217 set: setInput 218 }; 219 220}));
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.