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.

304 lines
7.2 KiB

7 years ago
// 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);