springroll-keyboard
Version:
Keyboard is a plugin for [SpringRoll](http://github.com/SpringRoll/SpringRoll). It is designed to make working with the keyboard outside of text editing easier. Keyboard has capabilities for detecting key presses and releases, tracking pressed keys, custo
1,933 lines (1,876 loc) • 73 kB
JavaScript
/*! Keyboard 0.1.5 */
/**
* @namespace springroll
*/
(function()
{
//A stripped down version of Detect.js, just for browser family and OS
/*
* Detect.js: User-Agent Parser
* https://github.com/darcyclarke/Detect.js
* Dual licensed under the MIT and GPL licenses.
*
* @version 2.2.1
* @author Darcy Clarke
* @url http://darcyclarke.me
* @createdat Thu Feb 13 2014 11:36:42 GMT+0000 (WET)
*
* Based on UA-Parser (https://github.com/tobie/ua-parser) by Tobie Langel
*
* Example Usage:
* var agentInfo = detect.parse(navigator.userAgent);
* console.log(agentInfo.browser.family); // Chrome
*
*/
// Shim Array.prototype.map if necessary
// Production steps of ECMA-262, Edition 5, 15.4.4.19
// Reference: http://es5.github.com/#x15.4.4.19
/*if (!Array.prototype.map) {
Array.prototype.map = function(callback, thisArg) {
var T, A, k;
if (this == null) {
throw new TypeError(" this is null or not defined");
}
// 1. Let O be the result of calling ToObject passing the |this| value as the argument.
var O = Object(this);
// 2. Let lenValue be the result of calling the Get internal method of O with the argument "length".
// 3. Let len be ToUint32(lenValue).
var len = O.length >>> 0;
// 4. If IsCallable(callback) is false, throw a TypeError exception.
// See: http://es5.github.com/#x9.11
if (typeof callback !== "function") {
throw new TypeError(callback + " is not a function");
}
// 5. If thisArg was supplied, let T be thisArg; else let T be undefined.
if (thisArg) {
T = thisArg;
}
// 6. Let A be a new array created as if by the expression new Array(len) where Array is
// the standard built-in constructor with that name and len is the value of len.
A = new Array(len);
// 7. Let k be 0
k = 0;
// 8. Repeat, while k < len
while (k < len) {
var kValue, mappedValue;
// a. Let Pk be ToString(k).
// This is implicit for LHS operands of the in operator
// b. Let kPresent be the result of calling the HasProperty internal method of O with argument Pk.
// This step can be combined with c
// c. If kPresent is true, then
if (k in O) {
// i. Let kValue be the result of calling the Get internal method of O with argument Pk.
kValue = O[k];
// ii. Let mappedValue be the result of calling the Call internal method of callback
// with T as the this value and argument list containing kValue, k, and O.
mappedValue = callback.call(T, kValue, k, O);
// iii. Call the DefineOwnProperty internal method of A with arguments
// Pk, Property Descriptor {Value: mappedValue, : true, Enumerable: true, Configurable: true},
// and false.
// In browsers that support Object.defineProperty, use the following:
// Object.defineProperty(A, Pk, { value: mappedValue, writable: true, enumerable: true, configurable: true });
// For best browser support, use the following:
A[k] = mappedValue;
}
// d. Increase k by 1.
k++;
}
// 9. return A
return A;
};
}*/
// Detect
var detect = function() {
// Context
var _this = function() {};
// Regexes
var regexes = {
browser_parsers: [ /*{
regex: "^(Opera)/(\\d+)\\.(\\d+) \\(Nintendo Wii",
family_replacement: "Wii",
manufacturer: "Nintendo"
}, {
regex: "(SeaMonkey|Camino)/(\\d+)\\.(\\d+)\\.?([ab]?\\d+[a-z]*)",
family_replacement: "Camino",
other: true
},*/ {
regex: "(Pale[Mm]oon)/(\\d+)\\.(\\d+)\\.?(\\d+)?",
family_replacement: "Pale Moon (Firefox Variant)",
other: true
}, {
regex: "(Fennec)/(\\d+)\\.(\\d+)\\.?([ab]?\\d+[a-z]*)",
family_replacement: "Firefox Mobile"
}, {
regex: "(Fennec)/(\\d+)\\.(\\d+)(pre)",
family_replacment: "Firefox Mobile"
}, {
regex: "(Fennec)/(\\d+)\\.(\\d+)",
family_replacement: "Firefox Mobile"
}, {
regex: "Mobile.*(Firefox)/(\\d+)\\.(\\d+)",
family_replacement: "Firefox Mobile"
}, {
regex: "(Namoroka|Shiretoko|Minefield)/(\\d+)\\.(\\d+)\\.(\\d+(?:pre)?)",
family_replacement: "Firefox ($1)"
}, {
regex: "(Firefox)/(\\d+)\\.(\\d+)(a\\d+[a-z]*)",
family_replacement: "Firefox Alpha"
}, {
regex: "(Firefox)/(\\d+)\\.(\\d+)(b\\d+[a-z]*)",
family_replacement: "Firefox Beta"
}, {
regex: "(Firefox)-(?:\\d+\\.\\d+)?/(\\d+)\\.(\\d+)(a\\d+[a-z]*)",
family_replacement: "Firefox Alpha"
}, {
regex: "(Firefox)-(?:\\d+\\.\\d+)?/(\\d+)\\.(\\d+)(b\\d+[a-z]*)",
family_replacement: "Firefox Beta"
}, {
regex: "(Namoroka|Shiretoko|Minefield)/(\\d+)\\.(\\d+)([ab]\\d+[a-z]*)?",
family_replacement: "Firefox ($1)"
}, {
regex: "(Firefox).*Tablet browser (\\d+)\\.(\\d+)\\.(\\d+)",
family_replacement: "MicroB",
tablet: true
}, {
regex: "(MozillaDeveloperPreview)/(\\d+)\\.(\\d+)([ab]\\d+[a-z]*)?"
}, /*{
regex: "(Flock)/(\\d+)\\.(\\d+)(b\\d+?)",
family_replacement: "Flock",
other: true
}, {
regex: "(RockMelt)/(\\d+)\\.(\\d+)\\.(\\d+)",
family_replacement: "Rockmelt",
other: true
}, {
regex: "(Navigator)/(\\d+)\\.(\\d+)\\.(\\d+)",
family_replacement: "Netscape"
}, {
regex: "(Navigator)/(\\d+)\\.(\\d+)([ab]\\d+)",
family_replacement: "Netscape"
}, {
regex: "(Netscape6)/(\\d+)\\.(\\d+)\\.(\\d+)",
family_replacement: "Netscape"
}, {
regex: "(MyIBrow)/(\\d+)\\.(\\d+)",
family_replacement: "My Internet Browser",
other: true
}, {
regex: "(Opera Tablet).*Version/(\\d+)\\.(\\d+)(?:\\.(\\d+))?",
family_replacement: "Opera Tablet",
tablet: true
}, {
regex: "(Opera)/.+Opera Mobi.+Version/(\\d+)\\.(\\d+)",
family_replacement: "Opera Mobile"
}, {
regex: "Opera Mobi",
family_replacement: "Opera Mobile"
}, {
regex: "(Opera Mini)/(\\d+)\\.(\\d+)",
family_replacement: "Opera Mini"
}, {
regex: "(Opera Mini)/att/(\\d+)\\.(\\d+)",
family_replacement: "Opera Mini"
}, {
regex: "(Opera)/9.80.*Version/(\\d+)\\.(\\d+)(?:\\.(\\d+))?",
family_replacement: "Opera"
}, {
regex: "(webOSBrowser)/(\\d+)\\.(\\d+)",
family_replacement: "webOS"
}, {
regex: "(webOS)/(\\d+)\\.(\\d+)",
family_replacement: "webOS"
}, {
regex: "(wOSBrowser).+TouchPad/(\\d+)\\.(\\d+)",
family_replacement: "webOS TouchPad"
}, {
regex: "(luakit)",
family_replacement: "LuaKit",
other: true
}, {
regex: "(Lightning)/(\\d+)\\.(\\d+)([ab]?\\d+[a-z]*)",
family_replacement: "Lightning",
other: true
}, {
regex: "(Firefox)/(\\d+)\\.(\\d+)\\.(\\d+(?:pre)?) \\(Swiftfox\\)",
family_replacement: "Swiftfox",
other: true
}, {
regex: "(Firefox)/(\\d+)\\.(\\d+)([ab]\\d+[a-z]*)? \\(Swiftfox\\)",
family_replacement: "Swiftfox",
other: true
}, {
regex: "rekonq",
family_replacement: "Rekonq",
other: true
}, {
regex: "(conkeror|Conkeror)/(\\d+)\\.(\\d+)\\.?(\\d+)?",
family_replacement: "Conkeror",
other: true
}, {
regex: "(konqueror)/(\\d+)\\.(\\d+)\\.(\\d+)",
family_replacement: "Konqueror",
other: true
}, {
regex: "(WeTab)-Browser",
family_replacement: "WeTab",
other: true
}, {
regex: "(Comodo_Dragon)/(\\d+)\\.(\\d+)\\.(\\d+)",
family_replacement: "Comodo Dragon",
other: true
}, {
regex: "(YottaaMonitor)",
family_replacement: "Yottaa Monitor",
other: true
}, {
regex: "(Kindle)/(\\d+)\\.(\\d+)",
family_replacement: "Kindle"
}, {
regex: "(Symphony) (\\d+).(\\d+)",
family_replacement: "Symphony",
other: true
}, {
regex: "Minimo",
family_replacement: "Minimo",
other: true
},*/ {
regex: "(CrMo)/(\\d+)\\.(\\d+)\\.(\\d+)\\.(\\d+)",
family_replacement: "Chrome Mobile"
}, {
regex: "(CriOS)/(\\d+)\\.(\\d+)\\.(\\d+)\\.(\\d+)",
family_replacement: "Chrome Mobile iOS"
}, {
regex: "(Chrome)/(\\d+)\\.(\\d+)\\.(\\d+)\\.(\\d+) Mobile",
family_replacement: "Chrome Mobile"
}, {
regex: "(chromeframe)/(\\d+)\\.(\\d+)\\.(\\d+)",
family_replacement: "Chrome Frame"
},/* {
regex: "(UC Browser)(\\d+)\\.(\\d+)\\.(\\d+)",
family_replacement: "UC Browser",
other: true
}, {
regex: "(SLP Browser)/(\\d+)\\.(\\d+)",
family_replacement: "Tizen Browser",
other: true
}, {
regex: "(Epiphany)/(\\d+)\\.(\\d+).(\\d+)",
family_replacement: "Epiphany",
other: true
}, {
regex: "(SE 2\\.X) MetaSr (\\d+)\\.(\\d+)",
family_replacement: "Sogou Explorer",
other: true
}, {
regex: "(Pingdom.com_bot_version_)(\\d+)\\.(\\d+)",
family_replacement: "PingdomBot",
other: true
}, {
regex: "(facebookexternalhit)/(\\d+)\\.(\\d+)",
family_replacement: "FacebookBot"
}, {
regex: "Facebot",
family_replacement: "FacebookBot"
}, {
regex: "(Twitterbot)/(\\d+)\\.(\\d+)",
family_replacement: "TwitterBot"
},*/ {
regex: "(AdobeAIR|Chromium|FireWeb|Jasmine|ANTGalio|Midori|Fresco|Lobo|PaleMoon|Maxthon|Lynx|OmniWeb|Dillo|Camino|Demeter|Fluid|Fennec|Shiira|Sunrise|Chrome|Flock|Netscape|Lunascape|WebPilot|NetFront|Netfront|Konqueror|SeaMonkey|Kazehakase|Vienna|Iceape|Iceweasel|IceWeasel|Iron|K-Meleon|Sleipnir|Galeon|GranParadiso|Opera Mini|iCab|NetNewsWire|ThunderBrowse|Iron|Iris|UP\\.Browser|Bunjaloo|Google Earth|Raven for Mac)/(\\d+)\\.(\\d+)\\.(\\d+)"
}, {
regex: "(Bolt|Jasmine|IceCat|Skyfire|Midori|Maxthon|Lynx|Arora|IBrowse|Dillo|Camino|Shiira|Fennec|Phoenix|Chrome|Flock|Netscape|Lunascape|Epiphany|WebPilot|Opera Mini|Opera|NetFront|Netfront|Konqueror|Googlebot|SeaMonkey|Kazehakase|Vienna|Iceape|Iceweasel|IceWeasel|Iron|K-Meleon|Sleipnir|Galeon|GranParadiso|iCab|NetNewsWire|Iron|Space Bison|Stainless|Orca|Dolfin|BOLT|Minimo|Tizen Browser|Polaris)/(\\d+)\\.(\\d+)"
}, {
regex: "(iRider|Crazy Browser|SkipStone|iCab|Lunascape|Sleipnir|Maemo Browser) (\\d+)\\.(\\d+)\\.(\\d+)"
}, {
regex: "(iCab|Lunascape|Opera|Android|Jasmine|Polaris|BREW) (\\d+)\\.(\\d+)\\.?(\\d+)?"
}, /*{
regex: "(Android) Donut",
v2_replacement: "2",
v1_replacement: "1"
}, {
regex: "(Android) Eclair",
v2_replacement: "1",
v1_replacement: "2"
}, {
regex: "(Android) Froyo",
v2_replacement: "2",
v1_replacement: "2"
}, {
regex: "(Android) Gingerbread",
v2_replacement: "3",
v1_replacement: "2"
}, {
regex: "(Android) Honeycomb",
v1_replacement: "3"
}, */{
regex: "(IEMobile)[ /](\\d+)\\.(\\d+)",
family_replacement: "IE Mobile"
}, {
regex: "(MSIE) (\\d+)\\.(\\d+).*XBLWP7",
family_replacement: "IE Large Screen"
}, {
regex: "(Firefox)/(\\d+)\\.(\\d+)\\.(\\d+)"
}, {
regex: "(Firefox)/(\\d+)\\.(\\d+)(pre|[ab]\\d+[a-z]*)?"
},/* {
regex: "(Obigo)InternetBrowser",
other: true
}, {
regex: "(Obigo)\\-Browser",
other: true
}, {
regex: "(Obigo|OBIGO)[^\\d]*(\\d+)(?:.(\\d+))?",
other: true
}, {
regex: "(MAXTHON|Maxthon) (\\d+)\\.(\\d+)",
family_replacement: "Maxthon",
other: true
}, {
regex: "(Maxthon|MyIE2|Uzbl|Shiira)",
v1_replacement: "0",
other: true
}, {
regex: "(PLAYSTATION) (\\d+)",
family_replacement: "PlayStation",
manufacturer: "Sony"
}, {
regex: "(PlayStation Portable)[^\\d]+(\\d+).(\\d+)",
manufacturer: "Sony"
}, {
regex: "(BrowseX) \\((\\d+)\\.(\\d+)\\.(\\d+)",
other: true
}, {
regex: "(POLARIS)/(\\d+)\\.(\\d+)",
family_replacement: "Polaris",
other: true
}, {
regex: "(Embider)/(\\d+)\\.(\\d+)",
family_replacement: "Polaris",
other: true
}, {
regex: "(BonEcho)/(\\d+)\\.(\\d+)\\.(\\d+)",
family_replacement: "Bon Echo",
other: true
},*/ {
regex: "(iPod).+Version/(\\d+)\\.(\\d+)\\.(\\d+)",
family_replacement: "Mobile Safari",
manufacturer: "Apple"
}, {
regex: "(iPod).*Version/(\\d+)\\.(\\d+)",
family_replacement: "Mobile Safari",
manufacturer: "Apple"
}, {
regex: "(iPod)",
family_replacement: "Mobile Safari",
manufacturer: "Apple"
}, {
regex: "(iPhone).*Version/(\\d+)\\.(\\d+)\\.(\\d+)",
family_replacement: "Mobile Safari",
manufacturer: "Apple"
}, {
regex: "(iPhone).*Version/(\\d+)\\.(\\d+)",
family_replacement: "Mobile Safari",
manufacturer: "Apple"
}, {
regex: "(iPhone)",
family_replacement: "Mobile Safari",
manufacturer: "Apple"
}, {
regex: "(iPad).*Version/(\\d+)\\.(\\d+)\\.(\\d+)",
family_replacement: "Mobile Safari",
tablet: true,
manufacturer: "Apple"
}, {
regex: "(iPad).*Version/(\\d+)\\.(\\d+)",
family_replacement: "Mobile Safari",
tablet: true,
manufacturer: "Apple"
}, {
regex: "(iPad)",
family_replacement: "Mobile Safari",
tablet: true,
manufacturer: "Apple"
},/* {
regex: "(AvantGo) (\\d+).(\\d+)",
other: true
}, {
regex: "(Avant)",
v1_replacement: "1",
other: true
}, {
regex: "^(Nokia)",
family_replacement: "Nokia Services (WAP) Browser",
manufacturer: "Nokia"
}, {
regex: "(NokiaBrowser)/(\\d+)\\.(\\d+).(\\d+)\\.(\\d+)",
manufacturer: "Nokia"
}, {
regex: "(NokiaBrowser)/(\\d+)\\.(\\d+).(\\d+)",
manufacturer: "Nokia"
}, {
regex: "(NokiaBrowser)/(\\d+)\\.(\\d+)",
manufacturer: "Nokia"
}, {
regex: "(BrowserNG)/(\\d+)\\.(\\d+).(\\d+)",
family_replacement: "NokiaBrowser",
manufacturer: "Nokia"
}, {
regex: "(Series60)/5\\.0",
v2_replacement: "0",
v1_replacement: "7",
family_replacement: "NokiaBrowser",
manufacturer: "Nokia"
}, {
regex: "(Series60)/(\\d+)\\.(\\d+)",
family_replacement: "Nokia OSS Browser",
manufacturer: "Nokia"
}, {
regex: "(S40OviBrowser)/(\\d+)\\.(\\d+)\\.(\\d+)\\.(\\d+)",
family_replacement: "Nokia Series 40 Ovi Browser",
manufacturer: "Nokia"
}, {
regex: "(Nokia)[EN]?(\\d+)",
manufacturer: "Nokia"
}, {
regex: "(PlayBook).+RIM Tablet OS (\\d+)\\.(\\d+)\\.(\\d+)",
family_replacement: "Blackberry WebKit",
tablet: true,
manufacturer: "Nokia"
}, {
regex: "(Black[bB]erry).+Version/(\\d+)\\.(\\d+)\\.(\\d+)",
family_replacement: "Blackberry WebKit",
manufacturer: "RIM"
}, {
regex: "(Black[bB]erry)\\s?(\\d+)",
family_replacement: "Blackberry",
manufacturer: "RIM"
}, {
regex: "(OmniWeb)/v(\\d+)\\.(\\d+)",
other: true
}, {
regex: "(Blazer)/(\\d+)\\.(\\d+)",
family_replacement: "Palm Blazer",
manufacturer: "Palm"
}, {
regex: "(Pre)/(\\d+)\\.(\\d+)",
family_replacement: "Palm Pre",
manufacturer: "Palm"
}, {
regex: "(Links) \\((\\d+)\\.(\\d+)",
other: true
}, {
regex: "(QtWeb) Internet Browser/(\\d+)\\.(\\d+)",
other: true
},*/ {
regex: "(Silk)/(\\d+)\\.(\\d+)(?:\\.([0-9\\-]+))?",
other: true,
tablet: true
}, {
regex: "(AppleWebKit)/(\\d+)\\.?(\\d+)?\\+ .* Version/\\d+\\.\\d+.\\d+ Safari/",
family_replacement: "WebKit Nightly"
}, {
regex: "(Version)/(\\d+)\\.(\\d+)(?:\\.(\\d+))?.*Safari/",
family_replacement: "Safari"
}, {
regex: "(Safari)/\\d+"
}, /*{
regex: "(OLPC)/Update(\\d+)\\.(\\d+)",
other: true
}, {
regex: "(OLPC)/Update()\\.(\\d+)",
v1_replacement: "0",
other: true
}, {
regex: "(SEMC\\-Browser)/(\\d+)\\.(\\d+)",
other: true
}, {
regex: "(Teleca)",
family_replacement: "Teleca Browser",
other: true
},*/ {
regex: "Trident(.*)rv.(\\d+)\\.(\\d+)",
family_replacement: "IE"
}, {
regex: "(MSIE) (\\d+)\\.(\\d+)",
family_replacement: "IE"
} ],
os_parsers: [ {
regex: "(Android) (\\d+)\\.(\\d+)(?:[.\\-]([a-z0-9]+))?"
}, {
regex: "(Android)\\-(\\d+)\\.(\\d+)(?:[.\\-]([a-z0-9]+))?"
}, {
regex: "(Android) Donut",
os_v2_replacement: "2",
os_v1_replacement: "1"
}, {
regex: "(Android) Eclair",
os_v2_replacement: "1",
os_v1_replacement: "2"
}, {
regex: "(Android) Froyo",
os_v2_replacement: "2",
os_v1_replacement: "2"
}, {
regex: "(Android) Gingerbread",
os_v2_replacement: "3",
os_v1_replacement: "2"
}, {
regex: "(Android) Honeycomb",
os_v1_replacement: "3"
}, {
regex: "(Silk-Accelerated=[a-z]{4,5})",
os_replacement: "Android"
}, {
regex: "(Windows Phone 6\\.5)"
}, {
regex: "(Windows (?:NT 5\\.2|NT 5\\.1))",
os_replacement: "Windows XP"
}, {
regex: "(XBLWP7)",
os_replacement: "Windows Phone OS"
}, {
regex: "(Windows NT 6\\.1)",
os_replacement: "Windows 7"
}, {
regex: "(Windows NT 6\\.0)",
os_replacement: "Windows Vista"
}, {
regex: "(Windows 98|Windows XP|Windows ME|Windows 95|Windows CE|Windows 7|Windows NT 4\\.0|Windows Vista|Windows 2000)"
}, {
regex: "(Windows NT 6\\.2)",
os_replacement: "Windows 8"
}, {
regex: "(Windows Phone 8)",
os_replacement: "Windows Phone 8"
}, {
regex: "(Windows NT 5\\.0)",
os_replacement: "Windows 2000"
}, {
regex: "(Windows Phone OS) (\\d+)\\.(\\d+)"
}, {
regex: "(Windows ?Mobile)",
os_replacement: "Windows Mobile"
}, {
regex: "(WinNT4.0)",
os_replacement: "Windows NT 4.0"
}, {
regex: "(Win98)",
os_replacement: "Windows 98"
}, {
regex: "(Tizen)/(\\d+)\\.(\\d+)",
other: true
}, {
regex: "(Mac OS X) (\\d+)[_.](\\d+)(?:[_.](\\d+))?",
manufacturer: "Apple"
}, {
regex: "(?:PPC|Intel) (Mac OS X)",
manufacturer: "Apple"
}, {
regex: "(CPU OS|iPhone OS) (\\d+)_(\\d+)(?:_(\\d+))?",
os_replacement: "iOS",
manufacturer: "Apple"
}, {
regex: "(iPhone|iPad|iPod); Opera",
os_replacement: "iOS",
manufacturer: "Apple"
}, {
regex: "(iPad); Opera",
tablet: true,
manufacturer: "Apple"
}, {
regex: "(iPhone|iPad|iPod).*Mac OS X.*Version/(\\d+)\\.(\\d+)",
os_replacement: "iOS",
manufacturer: "Apple"
}, /*{
regex: "(CrOS) [a-z0-9_]+ (\\d+)\\.(\\d+)(?:\\.(\\d+))?",
os_replacement: "Chrome OS"
}, {
regex: "(Debian)-(\\d+)\\.(\\d+)\\.(\\d+)(?:\\.(\\d+))?",
other: true
}, {
regex: "(Linux Mint)(?:/(\\d+))?",
other: true
}, {
regex: "(Mandriva)(?: Linux)?/(\\d+)\\.(\\d+)\\.(\\d+)(?:\\.(\\d+))?",
other: true
}, {
regex: "(Symbian[Oo][Ss])/(\\d+)\\.(\\d+)",
os_replacement: "Symbian OS"
}, {
regex: "(Symbian/3).+NokiaBrowser/7\\.3",
os_replacement: "Symbian^3 Anna"
}, {
regex: "(Symbian/3).+NokiaBrowser/7\\.4",
os_replacement: "Symbian^3 Belle"
}, {
regex: "(Symbian/3)",
os_replacement: "Symbian^3"
}, {
regex: "(Series 60|SymbOS|S60)",
os_replacement: "Symbian OS"
}, {
regex: "(MeeGo)",
other: true
}, {
regex: "Symbian [Oo][Ss]",
os_replacement: "Symbian OS"
}, {
regex: "(Black[Bb]erry)[0-9a-z]+/(\\d+)\\.(\\d+)\\.(\\d+)(?:\\.(\\d+))?",
os_replacement: "BlackBerry OS",
manufacturer: "RIM"
}, {
regex: "(Black[Bb]erry).+Version/(\\d+)\\.(\\d+)\\.(\\d+)(?:\\.(\\d+))?",
os_replacement: "BlackBerry OS",
manufacturer: "RIM"
}, {
regex: "(RIM Tablet OS) (\\d+)\\.(\\d+)\\.(\\d+)",
os_replacement: "BlackBerry Tablet OS",
tablet: true,
manufacturer: "RIM"
}, {
regex: "(Play[Bb]ook)",
os_replacement: "BlackBerry Tablet OS",
tablet: true,
manufacturer: "RIM"
}, {
regex: "(Black[Bb]erry)",
os_replacement: "Blackberry OS",
manufacturer: "RIM"
}, {
regex: "(webOS|hpwOS)/(\\d+)\\.(\\d+)(?:\\.(\\d+))?",
os_replacement: "webOS"
}, {
regex: "(SUSE|Fedora|Red Hat|PCLinuxOS)/(\\d+)\\.(\\d+)\\.(\\d+)\\.(\\d+)",
other: true
}, {
regex: "(SUSE|Fedora|Red Hat|Puppy|PCLinuxOS|CentOS)/(\\d+)\\.(\\d+)\\.(\\d+)",
other: true
},*/ {
regex: "(Ubuntu|Kindle|Bada|Lubuntu|BackTrack|Red Hat|Slackware)/(\\d+)\\.(\\d+)"
}, {
regex: "(Windows|OpenBSD|FreeBSD|NetBSD|Ubuntu|Kubuntu|Android|Arch Linux|CentOS|WeTab|Slackware)"
}, {
regex: "(Linux|BSD)",
other: true
} ],
mobile_os_families: [ "Windows Phone 6.5", "Windows CE", "Symbian OS" ],
/*device_parsers: [ {
regex: "HTC ([A-Z][a-z0-9]+) Build",
device_replacement: "HTC $1",
manufacturer: "HTC"
}, {
regex: "HTC ([A-Z][a-z0-9 ]+) \\d+\\.\\d+\\.\\d+\\.\\d+",
device_replacement: "HTC $1",
manufacturer: "HTC"
}, {
regex: "HTC_Touch_([A-Za-z0-9]+)",
device_replacement: "HTC Touch ($1)",
manufacturer: "HTC"
}, {
regex: "USCCHTC(\\d+)",
device_replacement: "HTC $1 (US Cellular)",
manufacturer: "HTC"
}, {
regex: "Sprint APA(9292)",
device_replacement: "HTC $1 (Sprint)",
manufacturer: "HTC"
}, {
regex: "HTC ([A-Za-z0-9]+ [A-Z])",
device_replacement: "HTC $1",
manufacturer: "HTC"
}, {
regex: "HTC-([A-Za-z0-9]+)",
device_replacement: "HTC $1",
manufacturer: "HTC"
}, {
regex: "HTC_([A-Za-z0-9]+)",
device_replacement: "HTC $1",
manufacturer: "HTC"
}, {
regex: "HTC ([A-Za-z0-9]+)",
device_replacement: "HTC $1",
manufacturer: "HTC"
}, {
regex: "(ADR[A-Za-z0-9]+)",
device_replacement: "HTC $1",
manufacturer: "HTC"
}, {
regex: "(HTC)",
manufacturer: "HTC"
}, {
regex: "SonyEricsson([A-Za-z0-9]+)/",
device_replacement: "Ericsson $1",
other: true,
manufacturer: "Sony"
}, {
regex: "Android[\\- ][\\d]+\\.[\\d]+\\; [A-Za-z]{2}\\-[A-Za-z]{2}\\; WOWMobile (.+) Build"
}, {
regex: "Android[\\- ][\\d]+\\.[\\d]+\\.[\\d]+; [A-Za-z]{2}\\-[A-Za-z]{2}\\; (.+) Build"
}, {
regex: "Android[\\- ][\\d]+\\.[\\d]+\\-update1\\; [A-Za-z]{2}\\-[A-Za-z]{2}\\; (.+) Build"
}, {
regex: "Android[\\- ][\\d]+\\.[\\d]+\\; [A-Za-z]{2}\\-[A-Za-z]{2}\\; (.+) Build"
}, {
regex: "Android[\\- ][\\d]+\\.[\\d]+\\.[\\d]+; (.+) Build"
}, {
regex: "NokiaN([0-9]+)",
device_replacement: "Nokia N$1",
manufacturer: "Nokia"
}, {
regex: "Nokia([A-Za-z0-9\\v-]+)",
device_replacement: "Nokia $1",
manufacturer: "Nokia"
}, {
regex: "NOKIA ([A-Za-z0-9\\-]+)",
device_replacement: "Nokia $1",
manufacturer: "Nokia"
}, {
regex: "Nokia ([A-Za-z0-9\\-]+)",
device_replacement: "Nokia $1",
manufacturer: "Nokia"
}, {
regex: "Lumia ([A-Za-z0-9\\-]+)",
device_replacement: "Lumia $1",
manufacturer: "Nokia"
}, {
regex: "Symbian",
device_replacement: "Nokia",
manufacturer: "Nokia"
}, {
regex: "(PlayBook).+RIM Tablet OS",
device_replacement: "Blackberry Playbook",
tablet: true,
manufacturer: "RIM"
}, {
regex: "(Black[Bb]erry [0-9]+);",
manufacturer: "RIM"
}, {
regex: "Black[Bb]erry([0-9]+)",
device_replacement: "BlackBerry $1",
manufacturer: "RIM"
}, {
regex: "(Pre)/(\\d+)\\.(\\d+)",
device_replacement: "Palm Pre",
manufacturer: "Palm"
}, {
regex: "(Pixi)/(\\d+)\\.(\\d+)",
device_replacement: "Palm Pixi",
manufacturer: "Palm"
}, {
regex: "(Touchpad)/(\\d+)\\.(\\d+)",
device_replacement: "HP Touchpad",
manufacturer: "HP"
}, {
regex: "HPiPAQ([A-Za-z0-9]+)/(\\d+).(\\d+)",
device_replacement: "HP iPAQ $1",
manufacturer: "HP"
}, {
regex: "Palm([A-Za-z0-9]+)",
device_replacement: "Palm $1",
manufacturer: "Palm"
}, {
regex: "Treo([A-Za-z0-9]+)",
device_replacement: "Palm Treo $1",
manufacturer: "Palm"
}, {
regex: "webOS.*(P160UNA)/(\\d+).(\\d+)",
device_replacement: "HP Veer",
manufacturer: "HP"
}, {
regex: "(Kindle Fire)",
manufacturer: "Amazon"
}, {
regex: "(Kindle)",
manufacturer: "Amazon"
}, {
regex: "(Silk)/(\\d+)\\.(\\d+)(?:\\.([0-9\\-]+))?",
device_replacement: "Kindle Fire",
tablet: true,
manufacturer: "Amazon"
}, {
regex: "(iPad) Simulator;",
manufacturer: "Apple"
}, {
regex: "(iPad);",
manufacturer: "Apple"
}, {
regex: "(iPod);",
manufacturer: "Apple"
}, {
regex: "(iPhone) Simulator;",
manufacturer: "Apple"
}, {
regex: "(iPhone);",
manufacturer: "Apple"
}, {
regex: "Nexus\\ ([A-Za-z0-9\\-]+)",
device_replacement: "Nexus $1"
}, {
regex: "acer_([A-Za-z0-9]+)_",
device_replacement: "Acer $1",
manufacturer: "Acer"
}, {
regex: "acer_([A-Za-z0-9]+)_",
device_replacement: "Acer $1",
manufacturer: "Acer"
}, {
regex: "Amoi\\-([A-Za-z0-9]+)",
device_replacement: "Amoi $1",
other: true,
manufacturer: "Amoi"
}, {
regex: "AMOI\\-([A-Za-z0-9]+)",
device_replacement: "Amoi $1",
other: true,
manufacturer: "Amoi"
}, {
regex: "Asus\\-([A-Za-z0-9]+)",
device_replacement: "Asus $1",
manufacturer: "Asus"
}, {
regex: "ASUS\\-([A-Za-z0-9]+)",
device_replacement: "Asus $1",
manufacturer: "Asus"
}, {
regex: "BIRD\\-([A-Za-z0-9]+)",
device_replacement: "Bird $1",
other: true
}, {
regex: "BIRD\\.([A-Za-z0-9]+)",
device_replacement: "Bird $1",
other: true
}, {
regex: "BIRD ([A-Za-z0-9]+)",
device_replacement: "Bird $1",
other: true
}, {
regex: "Dell ([A-Za-z0-9]+)",
device_replacement: "Dell $1",
manufacturer: "Dell"
}, {
regex: "DoCoMo/2\\.0 ([A-Za-z0-9]+)",
device_replacement: "DoCoMo $1",
other: true
}, {
regex: "([A-Za-z0-9]+)\\_W\\;FOMA",
device_replacement: "DoCoMo $1",
other: true
}, {
regex: "([A-Za-z0-9]+)\\;FOMA",
device_replacement: "DoCoMo $1",
other: true
}, {
regex: "vodafone([A-Za-z0-9]+)",
device_replacement: "Huawei Vodafone $1",
other: true
}, {
regex: "i\\-mate ([A-Za-z0-9]+)",
device_replacement: "i-mate $1",
other: true
}, {
regex: "Kyocera\\-([A-Za-z0-9]+)",
device_replacement: "Kyocera $1",
other: true
}, {
regex: "KWC\\-([A-Za-z0-9]+)",
device_replacement: "Kyocera $1",
other: true
}, {
regex: "Lenovo\\-([A-Za-z0-9]+)",
device_replacement: "Lenovo $1",
manufacturer: "Lenovo"
}, {
regex: "Lenovo\\_([A-Za-z0-9]+)",
device_replacement: "Lenovo $1",
manufacturer: "Levovo"
}, {
regex: "LG/([A-Za-z0-9]+)",
device_replacement: "LG $1",
manufacturer: "LG"
}, {
regex: "LG-LG([A-Za-z0-9]+)",
device_replacement: "LG $1",
manufacturer: "LG"
}, {
regex: "LGE-LG([A-Za-z0-9]+)",
device_replacement: "LG $1",
manufacturer: "LG"
}, {
regex: "LGE VX([A-Za-z0-9]+)",
device_replacement: "LG $1",
manufacturer: "LG"
}, {
regex: "LG ([A-Za-z0-9]+)",
device_replacement: "LG $1",
manufacturer: "LG"
}, {
regex: "LGE LG\\-AX([A-Za-z0-9]+)",
device_replacement: "LG $1",
manufacturer: "LG"
}, {
regex: "LG\\-([A-Za-z0-9]+)",
device_replacement: "LG $1",
manufacturer: "LG"
}, {
regex: "LGE\\-([A-Za-z0-9]+)",
device_replacement: "LG $1",
manufacturer: "LG"
}, {
regex: "LG([A-Za-z0-9]+)",
device_replacement: "LG $1",
manufacturer: "LG"
}, {
regex: "(KIN)\\.One (\\d+)\\.(\\d+)",
device_replacement: "Microsoft $1"
}, {
regex: "(KIN)\\.Two (\\d+)\\.(\\d+)",
device_replacement: "Microsoft $1"
}, {
regex: "(Motorola)\\-([A-Za-z0-9]+)",
manufacturer: "Motorola"
}, {
regex: "MOTO\\-([A-Za-z0-9]+)",
device_replacement: "Motorola $1",
manufacturer: "Motorola"
}, {
regex: "MOT\\-([A-Za-z0-9]+)",
device_replacement: "Motorola $1",
manufacturer: "Motorola"
}, {
regex: "Philips([A-Za-z0-9]+)",
device_replacement: "Philips $1",
manufacturer: "Philips"
}, {
regex: "Philips ([A-Za-z0-9]+)",
device_replacement: "Philips $1",
manufacturer: "Philips"
}, {
regex: "SAMSUNG-([A-Za-z0-9\\-]+)",
device_replacement: "Samsung $1",
manufacturer: "Samsung"
}, {
regex: "SAMSUNG\\; ([A-Za-z0-9\\-]+)",
device_replacement: "Samsung $1",
manufacturer: "Samsung"
}, {
regex: "Softbank/1\\.0/([A-Za-z0-9]+)",
device_replacement: "Softbank $1",
other: true
}, {
regex: "Softbank/2\\.0/([A-Za-z0-9]+)",
device_replacement: "Softbank $1",
other: true
}, {
regex: "(hiptop|avantgo|plucker|xiino|blazer|elaine|up.browser|up.link|mmp|smartphone|midp|wap|vodafone|o2|pocket|mobile|pda)",
device_replacement: "Generic Smartphone"
}, {
regex: "^(1207|3gso|4thp|501i|502i|503i|504i|505i|506i|6310|6590|770s|802s|a wa|acer|acs\\-|airn|alav|asus|attw|au\\-m|aur |aus |abac|acoo|aiko|alco|alca|amoi|anex|anny|anyw|aptu|arch|argo|bell|bird|bw\\-n|bw\\-u|beck|benq|bilb|blac|c55/|cdm\\-|chtm|capi|comp|cond|craw|dall|dbte|dc\\-s|dica|ds\\-d|ds12|dait|devi|dmob|doco|dopo|el49|erk0|esl8|ez40|ez60|ez70|ezos|ezze|elai|emul|eric|ezwa|fake|fly\\-|fly\\_|g\\-mo|g1 u|g560|gf\\-5|grun|gene|go.w|good|grad|hcit|hd\\-m|hd\\-p|hd\\-t|hei\\-|hp i|hpip|hs\\-c|htc |htc\\-|htca|htcg)",
device_replacement: "Generic Feature Phone"
}, {
regex: "^(htcp|htcs|htct|htc\\_|haie|hita|huaw|hutc|i\\-20|i\\-go|i\\-ma|i230|iac|iac\\-|iac/|ig01|im1k|inno|iris|jata|java|kddi|kgt|kgt/|kpt |kwc\\-|klon|lexi|lg g|lg\\-a|lg\\-b|lg\\-c|lg\\-d|lg\\-f|lg\\-g|lg\\-k|lg\\-l|lg\\-m|lg\\-o|lg\\-p|lg\\-s|lg\\-t|lg\\-u|lg\\-w|lg/k|lg/l|lg/u|lg50|lg54|lge\\-|lge/|lynx|leno|m1\\-w|m3ga|m50/|maui|mc01|mc21|mcca|medi|meri|mio8|mioa|mo01|mo02|mode|modo|mot |mot\\-|mt50|mtp1|mtv |mate|maxo|merc|mits|mobi|motv|mozz|n100|n101|n102|n202|n203|n300|n302|n500|n502|n505|n700|n701|n710|nec\\-|nem\\-|newg|neon)",
device_replacement: "Generic Feature Phone"
}, {
regex: "^(netf|noki|nzph|o2 x|o2\\-x|opwv|owg1|opti|oran|ot\\-s|p800|pand|pg\\-1|pg\\-2|pg\\-3|pg\\-6|pg\\-8|pg\\-c|pg13|phil|pn\\-2|pt\\-g|palm|pana|pire|pock|pose|psio|qa\\-a|qc\\-2|qc\\-3|qc\\-5|qc\\-7|qc07|qc12|qc21|qc32|qc60|qci\\-|qwap|qtek|r380|r600|raks|rim9|rove|s55/|sage|sams|sc01|sch\\-|scp\\-|sdk/|se47|sec\\-|sec0|sec1|semc|sgh\\-|shar|sie\\-|sk\\-0|sl45|slid|smb3|smt5|sp01|sph\\-|spv |spv\\-|sy01|samm|sany|sava|scoo|send|siem|smar|smit|soft|sony|t\\-mo|t218|t250|t600|t610|t618|tcl\\-|tdg\\-|telm|tim\\-|ts70|tsm\\-|tsm3|tsm5|tx\\-9|tagt)",
device_replacement: "Generic Feature Phone"
}, {
regex: "^(talk|teli|topl|tosh|up.b|upg1|utst|v400|v750|veri|vk\\-v|vk40|vk50|vk52|vk53|vm40|vx98|virg|vite|voda|vulc|w3c |w3c\\-|wapj|wapp|wapu|wapm|wig |wapi|wapr|wapv|wapy|wapa|waps|wapt|winc|winw|wonu|x700|xda2|xdag|yas\\-|your|zte\\-|zeto|aste|audi|avan|blaz|brew|brvw|bumb|ccwa|cell|cldc|cmd\\-|dang|eml2|fetc|hipt|http|ibro|idea|ikom|ipaq|jbro|jemu|jigs|keji|kyoc|kyok|libw|m\\-cr|midp|mmef|moto|mwbp|mywa|newt|nok6|o2im|pant|pdxg|play|pluc|port|prox|rozo|sama|seri|smal|symb|treo|upsi|vx52|vx53|vx60|vx61|vx70|vx80|vx81|vx83|vx85|wap\\-|webc|whit|wmlb|xda\\-|xda\\_)",
device_replacement: "Generic Feature Phone"
}, {
regex: "(bot|borg|google(^tv)|yahoo|slurp|msnbot|msrbot|openbot|archiver|netresearch|lycos|scooter|altavista|teoma|gigabot|baiduspider|blitzbot|oegp|charlotte|furlbot|http%20client|polybot|htdig|ichiro|mogimogi|larbin|pompos|scrubby|searchsight|seekbot|semanticdiscovery|silk|snappy|speedy|spider|voila|vortex|voyager|zao|zeal|fast\\-webcrawler|converacrawler|dataparksearch|findlinks)",
device_replacement: "Spider"
} ],*/
mobile_browser_families: [ "Firefox Mobile", "Opera Mobile", "Opera Mini", "Mobile Safari", "webOS", "IE Mobile", "Playstation Portable", "Nokia", "Blackberry", "Palm", "Silk", "Android", "Maemo", "Obigo", "Netfront", "AvantGo", "Teleca", "SEMC-Browser", "Bolt", "Iris", "UP.Browser", "Symphony", "Minimo", "Bunjaloo", "Jasmine", "Dolfin", "Polaris", "BREW", "Chrome Mobile", "Chrome Mobile iOS", "UC Browser", "Tizen Browser" ]
};
// Parsers
_this.parsers = [ /*"device_parsers",*/ "browser_parsers", "os_parsers", "mobile_os_families", "mobile_browser_families" ];
// Types
_this.types = [ "browser", "os"/*, "device"*/ ];
// Regular Expressions
_this.regexes = regexes || function() {
var results = {};
_this.parsers.map(function(parser) {
results[parser] = [];
});
return results;
}();
// Families
_this.families = function() {
var results = {};
_this.types.map(function(type) {
results[type] = [];
});
return results;
}();
// Utility Variables
var ArrayProto = Array.prototype, ObjProto = Object.prototype,
FuncProto = Function.prototype, nativeForEach = ArrayProto.forEach,
nativeIndexOf = ArrayProto.indexOf;
// Find Utility
var find = function(ua, obj) {
var ret = {};
for (var i = 0; i < obj.length; i++) {
ret = obj[i](ua);
if (ret) {
break;
}
}
return ret;
};
// Remove Utility
var remove = function(arr, props) {
each(arr, function(obj) {
each(props, function(prop) {
delete obj[prop];
});
});
};
// Contains Utility
var contains = function(obj, target) {
var found = false;
if (!obj) return found;
if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1;
found = any(obj, function(value) {
return value === target;
});
return found;
};
// Each Utility
var forEach, each;
each = forEach = function(obj, iterator, context) {
if (!obj) return;
if (nativeForEach && obj.forEach === nativeForEach) {
obj.forEach(iterator, context);
} else if (obj.length === +obj.length) {
for (var i = 0, l = obj.length; i < l; i++) {
iterator.call(context, obj[i], i, obj);
}
} else {
for (var key in obj) {
if (_.has(obj, key)) {
iterator.call(context, obj[key], key, obj);
}
}
}
};
// Extend Utiltiy
var extend = function(obj) {
each(slice.call(arguments, 1), function(source) {
for (var prop in source) {
obj[prop] = source[prop];
}
});
return obj;
};
// Check String Utility
var check = function(str) {
return !!(str && typeof str != "undefined" && !str);
};
// To Version String Utility
var toVersionString = function(obj) {
var output = "";
obj = obj || {};
if (check(obj)) {
if (check(obj.major)) {
output += obj.major;
if (check(obj.minor)) {
output += "." + obj.minor;
if (check(obj.patch)) {
output += "." + obj.patch;
}
}
}
}
return output;
};
// To String Utility
var toString = function(obj) {
obj = obj || {};
var suffix = toVersionString(obj);
if (suffix) suffix = " " + suffix;
return obj && check(obj.family) ? obj.family + suffix : "";
};
// Parse User-Agent String
_this.parse = function(ua) {
// Parsers Utility
var parsers = function(type) {
return _this.regexes[type + "_parsers"].map(function(obj) {
var regexp = new RegExp(obj.regex), rep = obj[(type === "browser" ? "family" : type) + "_replacement"], major_rep = obj.major_version_replacement;
function parser(ua) {
var m = ua.match(regexp);
if (!m) return null;
var ret = {};
ret.family = (rep ? rep.replace("$1", m[1]) : m[1]) || "other";
/*ret.major = parseInt(major_rep ? major_rep : m[2]) || null;
ret.minor = m[3] ? parseInt(m[3]) : null;
ret.patch = m[4] ? parseInt(m[4]) : null;*/
ret.tablet = obj.tablet;
//ret.man = obj.manufacturer || null;
return ret;
}
return parser;
});
};
// User Agent
var UserAgent = function() {};
// Browsers Parsed
var browser_parsers = parsers("browser");
// Operating Systems Parsed
var os_parsers = parsers("os");
// Devices Parsed
//var device_parsers = parsers("device");
// Set Agent
var a = new UserAgent();
// Remember the original user agent string
a.source = ua;
// Set Browser
a.browser = find(ua, browser_parsers);
if (/*check(*/a.browser/*)*/) {
a.browser.name = toString(a.browser);
a.browser.version = toVersionString(a.browser);
} else {
a.browser = {};
}
// Set OS
a.os = find(ua, os_parsers);
if (/*check(*/a.os/*)*/) {
a.os.name = toString(a.os);
a.os.version = toVersionString(a.os);
} else {
a.os = {};
}
// Set Device
/*a.device = find(ua, device_parsers);
if (check(a.device)) {
a.device.name = toString(a.device);
a.device.version = toVersionString(a.device);
} else {
a.device = {
tablet: false,
family: "Other"
};
}*/
// Determine Device Type
var mobile_agents = {};
var mobile_browser_families = _this.regexes.mobile_browser_families.map(function(str) {
mobile_agents[str] = true;
});
var mobile_os_families = _this.regexes.mobile_os_families.map(function(str) {
mobile_agents[str] = true;
});
// Is Spider
/*if (a.browser.family === "Spider") {
a.device.type = "Spider";
} else if (a.browser.tablet || a.os.tablet || a.device.tablet) {
a.device.type = "Tablet";
} else if (mobile_agents.hasOwnProperty(a.browser.family)) {
a.device.type = "Mobile";
} else {
a.device.type = "Desktop";
}*/
// Determine Device Manufacturer
//a.device.manufacturer = a.browser.man || a.os.man || a.device.man || null;
// Cleanup Objects
remove([ a.browser, a.os/*, a.device*/ ], [ "tablet", "man" ]);
// Return Agent
return a;
};
// Return context
return _this;
};
// Export the Underscore object for **Node.js** and **"CommonJS"**,
// backwards-compatibility for the old `require()` API. If we're not
// CommonJS, add `_` to the global object via a string identifier
// the Closure Compiler "advanced" mode. Registration as an AMD
// via define() happens at the end of this file
/*if (typeof exports !== "undefined") {
if (typeof module !== "undefined" && module.exports) {
exports = module.exports = detect;
}
exports.detect = detect;
} else {
root["detect"] = detect;
}
// AMD define happens at the end for compatibility with AMD
// that don't enforce next-turn semantics on modules
if (typeof define === "function" && define.amd) {
define(function(require) {
return detect;
});
}*/
// Assign to namespace
namespace('springroll').Detect = detect();
}());
/**
* @namespace springroll.keyboard
*/
(function()
{
var parsed = include('springroll.Detect').parse(navigator.userAgent);
var browser, os;
if(parsed.browser.family.indexOf("Safari") >= 0)
{
browser = "Safari";
}
else if(parsed.browser.family.indexOf("Firefox") >= 0)
{
browser = "Firefox";
}
else if(parsed.browser.family.indexOf("IE") >= 0)
{
browser = "IE";
}
else//Assume browser with the qualities of Chrome
{
browser = "Chrome";
}
if(parsed.os.name.indexOf("Windows") >= 0)
{
os = "Windows";
}
else if(parsed.os.name.indexOf("Mac") >= 0)
{
os = "Mac";
}
else if(parsed.os.name.indexOf("iOS") >= 0)
{
//iOS would probably report the same as OSX, right?
os = "Mac";
//all iOS browsers use a WebView that is similar to iOS Safari
browser = "Safari";
}
else//Assume some form of Linux, including Android
{
os = "Linux";
}
/**
* USLocale is the standard keyboard layout for US computers. All standard keys are included.
* Keys to note:
*
* * 'OS' represents both the Windows key and the 'command' key, although 'command'
* is also available when the client is running MacOS.
*
* * 'meta' represents 'ctrl' on Windows and Linux, and 'command' on OSX. Use this when creating
* keyboard shortcuts in web apps.
*
* @class USLocale
* @static
*/
var USLocale =
{
/**
* Cancel key
* @property {int} cancel
* @readOnly
*/
"cancel":3,
/**
* backspace key
* @property {int} backspace
* @readOnly
*/
"backspace":8,
/**
* tab key
* @property {int} tab
* @readOnly
*/
"tab":9,
/**
* enter key
* @property {int} enter
* @readOnly
*/
"enter":13,
/**
* shift key
* @property {int} shift
* @readOnly
*/
"shift":16,
/**
* ctrl key
* @property {int} ctrl
* @readOnly
*/
"ctrl":17,
/**
* alt key
* @property {int} alt
* @readOnly
*/
"alt":18,
/**
* Pause or break key
* @property {int} pause/break
* @readOnly
*/
"pause/break": os == "Mac" && browser != "Firefox" ? 126 : 19,
/**
* CAPS lock key
* @property {int} caps_lock
* @readOnly
*/
"caps_lock":20,
/**
* Escape key
* @property {int} esc
* @readOnly
*/
"esc":27,
/**
* Spacebar key
* @property {int} spacebar
* @readOnly
*/
"spacebar":32,
/**
* Page Up key
* @property {int} pageup
* @readOnly
*/
"pageup":33,
/**
* Page Down key
* @property {int} pagedown
* @readOnly
*/
"pagedown":34,
/**
* end key
* @property {int} end
* @readOnly
*/
"end":35,
/**
* home key
* @property {int} home
* @readOnly
*/
"home":36,
/**
* Toggle left key
* @property {int} arrow_left
* @readOnly
*/
"arrow_left":37,
/**
* Toggle up key
* @property {int} arrow_up
* @readOnly
*/
"arrow_up":38,
/**
* Toggle right key
* @property {int} arrow_right
* @readOnly
*/
"arrow_right":39,
/**
* Toggle down key
* @property {int} arrow_down
* @readOnly
*/
"arrow_down":40,
/**
* Print screen key
* @property {int} print_screen
* @readOnly
*/
//Note: on windows, only keyUp is fired for print_screen
"print_screen": os == "Linux" ? 42 : (os == "Mac" && browser != "Firefox" ? 124 : 44),
/**
* insert key
* @property {int} insert
* @readOnly
*/
"insert":45,
/**
* delete key
* @property {int} delete
* @readOnly
*/
"delete":46,
/**
* Scroll lock key
* @property {int} scroll_lock
* @readOnly
*/
"scroll_lock": os == "Mac" && browser != "Firefox" ? 125 : 145,
/**
* The OS button, either Windows or Apple Button
* @property {int} OS
* @readOnly
*/
//command/windows - may be different for left/right, depending on browser
//also might be 93, depending on OS
"OS": browser == "Firefox" ?
//Firefox uses the same keycode for left & right
(os == "Mac" ? 224 : 91) :
//other browsers use different codes for left/right, although webkit uses a different
//code on OSX than Windows/Linux
[
91,
os == "Mac" ? 93 : 92
],
/**
* on windows keyboard, located where the right 'windows' key might be
* not fired by Safari/Chrome on OSX (but is on FF?)
* @property {int} context_menu
* @readOnly
*/
"context_menu": os == "Mac" ? 0 : 93,
/**
* Semi-colon
* @property {int} ;
* @readOnly
*/
";":186,
/**
* Equals
* @property {int} =
* @readOnly
*/
"=":187,
/**
* Comma
* @property {int} ,
* @readOnly
*/
",":188,
/**
* Hyphen
* @property {int} -
* @readOnly
*/
"-":189,
/**
* Period
* @property {int} .
* @readOnly
*/
".":190,
/**
* Backslash
* @property {int} /
* @readOnly
*/
"/":191,
/**
* Tick mark
* @property {int} `
* @readOnly
*/
"`":192,
/**
* Forward slash
* @property {int} \
* @readOnly
*/
"\\":220,
/**
* Left bracket
* @property {int} [
* @readOnly
*/
"[":219,
/**
* Right bracket
* @property {int} ]
* @readOnly
*/
"]":221,
/**
* An apostrophe
* @property {int} '
* @readOnly
*/
"'":222,
//number pad keys
/**
* Number pad times
* @property {int} num_*
* @readOnly
*/
"num_*":106,
/**
* Number pad plus
* @property {int} num_+
* @readOnly
*/
"num_+":107,
/**
* Number pad enter
* @property {int} num_enter
* @readOnly
*/
"num_enter":108,
/**
* Number pad minus
* @property {int} num_-
* @readOnly
*/
"num_-":109,
/**
* Number pad decimal
* @property {int} num_.
* @readOnly
*/
"num_.":110,
/**
* Number pad divide
* @property {int} num_/
* @readOnly
*/
"num_/":111,
/**
* Number pad lock, 'num lock' is 'clear' on Mac keyboards
* @property {int} num_lock
* @readOnly
*/
"num_lock": os == "Mac" ? 12 : 144,
/**
* Number pad clear
* @property {int} clear
* @readOnly
*/
"clear": os == "Mac" ? 12 : 144
};
var i;
/**
* Alpha letter A
* @property {int} A
* @readOnly
*/
/**
* Alpha letter B
* @property {int} B
* @readOnly
*/
/**
* Alpha letter C
* @property {int} C
* @readOnly
*/
/**
* Alpha letter D
* @property {int} D
* @readOnly
*/
/**
* Alpha letter E
* @property {int} E
* @readOnly
*/
/**
* Alpha letter F
* @property {int} F
* @readOnly
*/
/**
* Alpha letter G
* @property {int} G
* @readOnly
*/
/**
* Alpha letter H
* @property {int} H
* @readOnly
*/
/**
* Alpha letter I
* @property {int} I
* @readOnly
*/
/**
* Alpha letter J
* @property {int} J
* @readOnly
*/
/**
* Alpha letter K
* @property {int} K
* @readOnly
*/
/**
* Alpha letter L
* @property {int} L
* @readOnly
*/
/**
* Alpha letter M
* @property {int} M
* @readOnly
*/
/**
* Alpha letter N
* @property {int} N
* @readOnly
*/
/**
* Alpha letter O
* @property {int} O
* @readOnly
*/
/**
* Alpha letter P
* @property {int} P
* @readOnly
*/
/**
* Alpha letter Q
* @property {int} Q
* @readOnly
*/
/**
* Alpha letter R
* @property {int} R
* @readOnly
*/
/**
* Alpha letter S
* @property {int} S
* @readOnly
*/
/**
* Alpha letter T
* @property {int} T
* @readOnly
*/
/**
* Alpha letter U
* @property {int} U
* @readOnly
*/
/**
* Alpha letter V
* @property {int} V
* @readOnly
*/
/**
* Alpha letter W
* @property {int} W
* @readOnly
*/
/**
* Alpha letter X
* @property {int} X
* @readOnly
*/
/**
* Alpha letter Y
* @property {int} Y
* @readOnly
*/
/**
* Alpha letter Z
* @property {int} Z
* @readOnly
*/
//A-Z
for(i = 65; i <= 90; ++i)
{
//use the capital letter as the value for the keyCode
USLocale[String.fromCharCode(i + 32)] = i;
}
//0-9
for(i = 48; i <= 57; ++i)
{
USLocale[String.fromCharCode(i)] = i;
}
//0-9, number pad: num_0-num_9
/**
* Number pad 1
* @property {int} num_1
* @readOnly
*/
/**
* Number pad 2
* @property {int} num_2
* @readOnly
*/
/**
* Number pad 3
* @property {int} num_3
* @readOnly
*/
/**
* Number pad 4
* @property {int} num_4
* @readOnly
*/
/**
* Number pad 5
* @property {int} num_5
* @readOnly
*/
/**
* Number pad 6
* @property {int} num_6
* @readOnly
*/
/**
* Number pad 7
* @property {int} num_7
* @readOnly
*/
/**
* Number pad 8
* @property {int} num_8
* @readOnly
*/
/**
* Number pad 9
* @property {int} num_9
* @readOnly
*/
/**
* Number pad 0
* @property {int} num_0
* @readOnly
*/
for(i = 96; i <= 105; ++i)
{
USLocale["num_" + (i-96)] = i;
}
/**
* Function key F1
* @property {int} F1
* @readOnly
*/
/**
* Function key F2
* @property {int} F2
* @readOnly
*/
/**
* Function key F3
* @property {int} F3
* @readOnly
*/
/**
* Function key F4
* @property {int} F4
* @readOnly
*/
/**
* Function key F5
* @property {int} F5
* @readOnly
*/
/**
* Function key F6
* @property {int} F6
* @readOnly
*/
/**
* Function key F7
* @property {int} F7
* @readOnly
*/
/**
* Function key F8
* @property {int} F8
* @readOnly
*/
/**
* Function key F9
* @property {int} F9
* @readOnly
*/
/**
* Function key F10
* @property {int} F10
* @readOnly
*/
/**
* Function key F11
* @property {int} F11
* @readOnly
*/
/**
* Function key F12
* @property {int} F12
* @readOnly
*/
for(i = 112; i <= 123; ++i)
{
USLocale["F" + (i - 111)] = i;
}
//OS specfic 'meta' key - pick ctrl or command
if(os == "Mac")
{
//also create 'command' for people that only want command
/**
* The command (Mac OSX) or ctrl (Windows) key
* @property {int} meta
* @readOnly
*/
USLocale.meta = USLocale.command = USLocale.OS;
}
else
{
USLocale.meta = USLocale.ctrl;
USLocale.command = 0;
}
// Assign to namespace
namespace('springroll.keyboard').USLocale = USLocale;
}());
/**
* @namespace springroll
*/
(function()
{
var Application = include('springroll.Application'),
Debug = include('springroll.Debug', false);
/**
* A class for easier keyboard controls, from simple key events to complex key combinations.
*
* @class Keyboard
* @constructor
* @param {DOMElement} target The DOM element to listen to key events on.
* @param {Object} locale The keyboard locale, like springroll.USLocale, which defines keys to
* keep track of.
*/
var Keyboard = function(target, locale)
{
//bind callbacks/listeners
this._onFocusLost = this._onFocusLost.bind(this);
this._onPaused = this._onPaused.bind(this);
this._onResumed = this._onResumed.bind(this);
this._update = this._update.bind(this);
this._keyDown = this._keyDown.bind(this);
this._keyUp = this._keyUp.bind(this);
/**
* The DOM element that the key event listeners are attached to.
* @property {DOMElement} target
* @private
* @readOnly
*/
this.target = target;
target.addEventListener('onblur', this._onFocusLost);
/**
* All keys that are listened to, arranged by key code.
* @property {Object} _keysByCode
* @private
*/
var _keysByCode = this._keysByCode = {};
/**
* All keys that are listened to, arranged by key name.
* @property {Object} _keysByName
* @private
*/
var _keysByName = this._keysByName = {};
/**
* All key combinations that have been registered
* @property {Array} _activeCombos
* @private
*/
this._activeCombos = [];
/**
* Keys that have been updated since the most recent frame update. This array gets wiped
* each _update call.
* @property {Array} _updatedKeys
* @private
*/
this._updatedKeys = [];
/**
* The callback used when key de