You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
303 lines
7.2 KiB
303 lines
7.2 KiB
// Device.js |
|
// (c) 2014 Matthew Hudson |
|
// Device.js is freely distributable under the MIT license. |
|
// For all details and documentation: |
|
// http://matthewhudson.me/projects/device.js/ |
|
|
|
(function() { |
|
|
|
var device, |
|
previousDevice, |
|
addClass, |
|
documentElement, |
|
find, |
|
handleOrientation, |
|
hasClass, |
|
orientationEvent, |
|
removeClass, |
|
userAgent; |
|
|
|
// Save the previous value of the device variable. |
|
previousDevice = window.device; |
|
|
|
device = {}; |
|
|
|
// Add device as a global object. |
|
window.device = device; |
|
|
|
// The <html> element. |
|
documentElement = window.document.documentElement; |
|
|
|
// The client user agent string. |
|
// Lowercase, so we can use the more efficient indexOf(), instead of Regex |
|
userAgent = window.navigator.userAgent.toLowerCase(); |
|
|
|
// Main functions |
|
// -------------- |
|
|
|
device.ios = function () { |
|
return device.iphone() || device.ipod() || device.ipad(); |
|
}; |
|
|
|
device.iphone = function () { |
|
return !device.windows() && find('iphone'); |
|
}; |
|
|
|
device.ipod = function () { |
|
return find('ipod'); |
|
}; |
|
|
|
device.ipad = function () { |
|
return find('ipad'); |
|
}; |
|
|
|
device.android = function () { |
|
return !device.windows() && find('android'); |
|
}; |
|
|
|
device.androidPhone = function () { |
|
return device.android() && find('mobile'); |
|
}; |
|
|
|
device.androidTablet = function () { |
|
return device.android() && !find('mobile'); |
|
}; |
|
|
|
device.blackberry = function () { |
|
return find('blackberry') || find('bb10') || find('rim'); |
|
}; |
|
|
|
device.blackberryPhone = function () { |
|
return device.blackberry() && !find('tablet'); |
|
}; |
|
|
|
device.blackberryTablet = function () { |
|
return device.blackberry() && find('tablet'); |
|
}; |
|
|
|
device.windows = function () { |
|
return find('windows'); |
|
}; |
|
|
|
device.windowsPhone = function () { |
|
return device.windows() && find('phone'); |
|
}; |
|
|
|
device.windowsTablet = function () { |
|
return device.windows() && (find('touch') && !device.windowsPhone()); |
|
}; |
|
|
|
device.fxos = function () { |
|
return (find('(mobile;') || find('(tablet;')) && find('; rv:'); |
|
}; |
|
|
|
device.fxosPhone = function () { |
|
return device.fxos() && find('mobile'); |
|
}; |
|
|
|
device.fxosTablet = function () { |
|
return device.fxos() && find('tablet'); |
|
}; |
|
|
|
device.meego = function () { |
|
return find('meego'); |
|
}; |
|
|
|
device.cordova = function () { |
|
return window.cordova && location.protocol === 'file:'; |
|
}; |
|
|
|
device.nodeWebkit = function () { |
|
return typeof window.process === 'object'; |
|
}; |
|
|
|
device.mobile = function () { |
|
return device.androidPhone() || device.iphone() || device.ipod() || device.windowsPhone() || device.blackberryPhone() || device.fxosPhone() || device.meego(); |
|
}; |
|
|
|
device.tablet = function () { |
|
return device.ipad() || device.androidTablet() || device.blackberryTablet() || device.windowsTablet() || device.fxosTablet(); |
|
}; |
|
|
|
device.desktop = function () { |
|
return !device.tablet() && !device.mobile(); |
|
}; |
|
|
|
device.television = function() { |
|
var i, tvString; |
|
|
|
television = [ |
|
"googletv", |
|
"viera", |
|
"smarttv", |
|
"internet.tv", |
|
"netcast", |
|
"nettv", |
|
"appletv", |
|
"boxee", |
|
"kylo", |
|
"roku", |
|
"dlnadoc", |
|
"roku", |
|
"pov_tv", |
|
"hbbtv", |
|
"ce-html" |
|
]; |
|
|
|
i = 0; |
|
while (i < television.length) { |
|
if (find(television[i])) { |
|
return true; |
|
} |
|
i++; |
|
} |
|
return false; |
|
}; |
|
|
|
device.portrait = function () { |
|
return (window.innerHeight / window.innerWidth) > 1; |
|
}; |
|
|
|
device.landscape = function () { |
|
return (window.innerHeight / window.innerWidth) < 1; |
|
}; |
|
|
|
// Public Utility Functions |
|
// ------------------------ |
|
|
|
// Run device.js in noConflict mode, |
|
// returning the device variable to its previous owner. |
|
device.noConflict = function () { |
|
window.device = previousDevice; |
|
return this; |
|
}; |
|
|
|
// Private Utility Functions |
|
// ------------------------- |
|
|
|
// Simple UA string search |
|
find = function (needle) { |
|
return userAgent.indexOf(needle) !== -1; |
|
}; |
|
|
|
// Check if documentElement already has a given class. |
|
hasClass = function (className) { |
|
var regex; |
|
regex = new RegExp(className, 'i'); |
|
return documentElement.className.match(regex); |
|
}; |
|
|
|
// Add one or more CSS classes to the <html> element. |
|
addClass = function (className) { |
|
var currentClassNames = null; |
|
if (!hasClass(className)) { |
|
currentClassNames = documentElement.className.replace(/^\s+|\s+$/g, ''); |
|
documentElement.className = currentClassNames + " " + className; |
|
} |
|
}; |
|
|
|
// Remove single CSS class from the <html> element. |
|
removeClass = function (className) { |
|
if (hasClass(className)) { |
|
documentElement.className = documentElement.className.replace(" " + className, ""); |
|
} |
|
}; |
|
|
|
// HTML Element Handling |
|
// --------------------- |
|
|
|
// Insert the appropriate CSS class based on the _user_agent. |
|
|
|
if (device.ios()) { |
|
if (device.ipad()) { |
|
addClass("ios ipad tablet"); |
|
} else if (device.iphone()) { |
|
addClass("ios iphone mobile"); |
|
} else if (device.ipod()) { |
|
addClass("ios ipod mobile"); |
|
} |
|
} else if (device.android()) { |
|
if (device.androidTablet()) { |
|
addClass("android tablet"); |
|
} else { |
|
addClass("android mobile"); |
|
} |
|
} else if (device.blackberry()) { |
|
if (device.blackberryTablet()) { |
|
addClass("blackberry tablet"); |
|
} else { |
|
addClass("blackberry mobile"); |
|
} |
|
} else if (device.windows()) { |
|
if (device.windowsTablet()) { |
|
addClass("windows tablet"); |
|
} else if (device.windowsPhone()) { |
|
addClass("windows mobile"); |
|
} else { |
|
addClass("desktop"); |
|
} |
|
} else if (device.fxos()) { |
|
if (device.fxosTablet()) { |
|
addClass("fxos tablet"); |
|
} else { |
|
addClass("fxos mobile"); |
|
} |
|
} else if (device.meego()) { |
|
addClass("meego mobile"); |
|
} else if (device.nodeWebkit()) { |
|
addClass("node-webkit"); |
|
} else if (device.television()) { |
|
addClass("television"); |
|
} else if (device.desktop()) { |
|
addClass("desktop"); |
|
} |
|
|
|
if (device.cordova()) { |
|
addClass("cordova"); |
|
} |
|
|
|
// Orientation Handling |
|
// -------------------- |
|
|
|
// Handle device orientation changes. |
|
handleOrientation = function () { |
|
if (device.landscape()) { |
|
removeClass("portrait"); |
|
addClass("landscape"); |
|
} else { |
|
removeClass("landscape"); |
|
addClass("portrait"); |
|
} |
|
return; |
|
}; |
|
|
|
// Detect whether device supports orientationchange event, |
|
// otherwise fall back to the resize event. |
|
if (Object.prototype.hasOwnProperty.call(window, "onorientationchange")) { |
|
orientationEvent = "orientationchange"; |
|
} else { |
|
orientationEvent = "resize"; |
|
} |
|
|
|
// Listen for changes in orientation. |
|
if (window.addEventListener) { |
|
window.addEventListener(orientationEvent, handleOrientation, false); |
|
} else if (window.attachEvent) { |
|
window.attachEvent(orientationEvent, handleOrientation); |
|
} else { |
|
window[orientationEvent] = handleOrientation; |
|
} |
|
|
|
handleOrientation(); |
|
|
|
if (typeof define === 'function' && typeof define.amd === 'object' && define.amd) { |
|
define(function() { |
|
return device; |
|
}); |
|
} else if (typeof module !== 'undefined' && module.exports) { |
|
module.exports = device; |
|
} else { |
|
window.device = device; |
|
} |
|
|
|
}).call(this);
|
|
|