mirror of
https://github.com/jellyfin/jellyfin-web.git
synced 2024-11-18 11:28:23 -07:00
289 lines
8.3 KiB
JavaScript
289 lines
8.3 KiB
JavaScript
define([], function () {
|
|
'use strict';
|
|
|
|
function isTv() {
|
|
|
|
// This is going to be really difficult to get right
|
|
var userAgent = navigator.userAgent.toLowerCase();
|
|
|
|
if (userAgent.indexOf('tv') !== -1) {
|
|
return true;
|
|
}
|
|
|
|
if (userAgent.indexOf('samsungbrowser') !== -1) {
|
|
return true;
|
|
}
|
|
|
|
if (userAgent.indexOf('nintendo') !== -1) {
|
|
return true;
|
|
}
|
|
|
|
if (userAgent.indexOf('viera') !== -1) {
|
|
return true;
|
|
}
|
|
|
|
if (userAgent.indexOf('webos') !== -1) {
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
function isMobile(userAgent) {
|
|
|
|
var terms = [
|
|
'mobi',
|
|
'ipad',
|
|
'iphone',
|
|
'ipod',
|
|
'silk',
|
|
'gt-p1000',
|
|
'nexus 7',
|
|
'kindle fire',
|
|
'opera mini'
|
|
];
|
|
|
|
var lower = userAgent.toLowerCase();
|
|
|
|
for (var i = 0, length = terms.length; i < length; i++) {
|
|
if (lower.indexOf(terms[i]) !== -1) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
function isStyleSupported(prop, value) {
|
|
|
|
if (typeof window === 'undefined') {
|
|
return false;
|
|
}
|
|
|
|
// If no value is supplied, use "inherit"
|
|
value = arguments.length === 2 ? value : 'inherit';
|
|
// Try the native standard method first
|
|
if ('CSS' in window && 'supports' in window.CSS) {
|
|
return window.CSS.supports(prop, value);
|
|
}
|
|
// Check Opera's native method
|
|
if ('supportsCSS' in window) {
|
|
return window.supportsCSS(prop, value);
|
|
}
|
|
|
|
// need try/catch because it's failing on tizen
|
|
|
|
try {
|
|
// Convert to camel-case for DOM interactions
|
|
var camel = prop.replace(/-([a-z]|[0-9])/ig, function (all, letter) {
|
|
return (letter + '').toUpperCase();
|
|
});
|
|
// Check if the property is supported
|
|
var support = (camel in el.style);
|
|
// Create test element
|
|
var el = document.createElement('div');
|
|
// Assign the property and value to invoke
|
|
// the CSS interpreter
|
|
el.style.cssText = prop + ':' + value;
|
|
// Ensure both the property and value are
|
|
// supported and return
|
|
return support && (el.style[camel] !== '');
|
|
} catch (err) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
function hasKeyboard(browser) {
|
|
|
|
if (browser.touch) {
|
|
return true;
|
|
}
|
|
|
|
if (browser.xboxOne) {
|
|
return true;
|
|
}
|
|
|
|
if (browser.ps4) {
|
|
return true;
|
|
}
|
|
|
|
if (browser.edgeUwp) {
|
|
// This is OK for now, but this won't always be true
|
|
// Should we use this?
|
|
// https://gist.github.com/wagonli/40d8a31bd0d6f0dd7a5d
|
|
return true;
|
|
}
|
|
|
|
if (browser.tv) {
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
var _supportsCssAnimation;
|
|
var _supportsCssAnimationWithPrefix;
|
|
function supportsCssAnimation(allowPrefix) {
|
|
|
|
if (allowPrefix) {
|
|
if (_supportsCssAnimationWithPrefix === true || _supportsCssAnimationWithPrefix === false) {
|
|
return _supportsCssAnimationWithPrefix;
|
|
}
|
|
} else {
|
|
if (_supportsCssAnimation === true || _supportsCssAnimation === false) {
|
|
return _supportsCssAnimation;
|
|
}
|
|
}
|
|
|
|
var animation = false,
|
|
animationstring = 'animation',
|
|
keyframeprefix = '',
|
|
domPrefixes = ['Webkit', 'O', 'Moz'],
|
|
pfx = '',
|
|
elm = document.createElement('div');
|
|
|
|
if (elm.style.animationName !== undefined) { animation = true; }
|
|
|
|
if (animation === false && allowPrefix) {
|
|
for (var i = 0; i < domPrefixes.length; i++) {
|
|
if (elm.style[domPrefixes[i] + 'AnimationName'] !== undefined) {
|
|
pfx = domPrefixes[i];
|
|
animationstring = pfx + 'Animation';
|
|
keyframeprefix = '-' + pfx.toLowerCase() + '-';
|
|
animation = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (allowPrefix) {
|
|
_supportsCssAnimationWithPrefix = animation;
|
|
return _supportsCssAnimationWithPrefix;
|
|
} else {
|
|
_supportsCssAnimation = animation;
|
|
return _supportsCssAnimation;
|
|
}
|
|
}
|
|
|
|
var uaMatch = function (ua) {
|
|
ua = ua.toLowerCase();
|
|
|
|
var match = /(edge)[ \/]([\w.]+)/.exec(ua) ||
|
|
/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) ||
|
|
/(opr)(?:.*version|)[ \/]([\w.]+)/.exec(ua) ||
|
|
/(chrome)[ \/]([\w.]+)/.exec(ua) ||
|
|
/(safari)[ \/]([\w.]+)/.exec(ua) ||
|
|
/(firefox)[ \/]([\w.]+)/.exec(ua) ||
|
|
/(msie) ([\w.]+)/.exec(ua) ||
|
|
ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) ||
|
|
[];
|
|
|
|
var versionMatch = /(version)[ \/]([\w.]+)/.exec(ua);
|
|
|
|
var platform_match = /(ipad)/.exec(ua) ||
|
|
/(iphone)/.exec(ua) ||
|
|
/(android)/.exec(ua) ||
|
|
[];
|
|
|
|
var browser = match[1] || "";
|
|
|
|
if (browser === "edge") {
|
|
platform_match = [""];
|
|
} else {
|
|
if (ua.indexOf("windows phone") !== -1 || ua.indexOf("iemobile") !== -1) {
|
|
|
|
// http://www.neowin.net/news/ie11-fakes-user-agent-to-fool-gmail-in-windows-phone-81-gdr1-update
|
|
browser = "msie";
|
|
}
|
|
else if (ua.indexOf("like gecko") !== -1 && ua.indexOf('webkit') === -1 && ua.indexOf('opera') === -1 && ua.indexOf('chrome') === -1 && ua.indexOf('safari') === -1) {
|
|
browser = "msie";
|
|
}
|
|
}
|
|
|
|
if (browser === 'opr') {
|
|
browser = 'opera';
|
|
}
|
|
|
|
var version;
|
|
if (versionMatch && versionMatch.length > 2) {
|
|
version = versionMatch[2];
|
|
}
|
|
|
|
version = version || match[2] || "0";
|
|
|
|
var versionMajor = parseInt(version.split('.')[0]);
|
|
|
|
if (isNaN(versionMajor)) {
|
|
versionMajor = 0;
|
|
}
|
|
|
|
return {
|
|
browser: browser,
|
|
version: version,
|
|
platform: platform_match[0] || "",
|
|
versionMajor: versionMajor
|
|
};
|
|
};
|
|
|
|
var userAgent = navigator.userAgent;
|
|
var matched = uaMatch(userAgent);
|
|
var browser = {};
|
|
|
|
if (matched.browser) {
|
|
browser[matched.browser] = true;
|
|
browser.version = matched.version;
|
|
browser.versionMajor = matched.versionMajor;
|
|
}
|
|
|
|
if (matched.platform) {
|
|
browser[matched.platform] = true;
|
|
}
|
|
|
|
if (!browser.chrome && !browser.msie && !browser.edge && !browser.opera && userAgent.toLowerCase().indexOf("webkit") !== -1) {
|
|
browser.safari = true;
|
|
}
|
|
|
|
if (userAgent.toLowerCase().indexOf("playstation 4") !== -1) {
|
|
browser.ps4 = true;
|
|
browser.tv = true;
|
|
}
|
|
|
|
if (isMobile(userAgent)) {
|
|
browser.mobile = true;
|
|
}
|
|
|
|
browser.xboxOne = userAgent.toLowerCase().indexOf('xbox') !== -1;
|
|
browser.animate = typeof document !== 'undefined' && document.documentElement.animate != null;
|
|
browser.tizen = userAgent.toLowerCase().indexOf('tizen') !== -1 || userAgent.toLowerCase().indexOf('smarthub') !== -1;
|
|
browser.web0s = userAgent.toLowerCase().indexOf('Web0S'.toLowerCase()) !== -1;
|
|
browser.edgeUwp = browser.edge && userAgent.toLowerCase().indexOf('msapphost') !== -1;
|
|
|
|
if (browser.edgeUwp) {
|
|
browser.edge = true;
|
|
}
|
|
|
|
browser.tv = isTv();
|
|
browser.operaTv = browser.tv && userAgent.toLowerCase().indexOf('opr/') !== -1;
|
|
|
|
if (!isStyleSupported('display', 'flex')) {
|
|
browser.noFlex = true;
|
|
}
|
|
|
|
if (browser.mobile || browser.tv) {
|
|
browser.slow = true;
|
|
}
|
|
|
|
if (typeof document !== 'undefined') {
|
|
if (('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch) {
|
|
browser.touch = true;
|
|
}
|
|
}
|
|
|
|
browser.keyboard = hasKeyboard(browser);
|
|
browser.supportsCssAnimation = supportsCssAnimation;
|
|
|
|
browser.osx = userAgent.toLowerCase().indexOf('os x') !== -1;
|
|
browser.iOS = browser.ipad || browser.iphone || browser.ipod;
|
|
|
|
return browser;
|
|
}); |