Created
May 2, 2020 21:39
-
-
Save WebMechanic/6f05fbc688d055c89bd1b0d0db32ff15 to your computer and use it in GitHub Desktop.
A simple browser feature sleuth that sets class names on html and body.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| * A simple browser feature sleuth that sets class names on html and body. | |
| * - Sleuth.sniff() | |
| * Tested with IE9-11, all evergreen Chrome, Firefox, EdgeHTML/Edgium, Opera. | |
| * | |
| * @version 1.3.3 02.05.2020 | |
| * @author WebMechanic.biz (c)2019 | |
| * @license DWTF | |
| */ | |
| const Sleuth = {agents:{}, features:{}, | |
| setFeature: function (key, elt) { | |
| elt.classList.add(key); | |
| }, | |
| sniff: function () { | |
| this.root = document.documentElement; | |
| let site = this, | |
| body = document.body, | |
| ua = (navigator.userAgent || 'Mozilla/5').replace(/\w+\/537.36/gi, 'FAKE/537.36'), | |
| ff = ('originalTarget' in Event.prototype) && ('CSS2Properties' in window), | |
| msie = ('runtimeStyle' in HTMLBodyElement.prototype), | |
| edge = !msie && ('msHyphenateLimitChars' in body.style) && ('maxTouchPoints' in navigator), | |
| edg = !edge, | |
| CSSOM = ('CSS' in window) && (CSSRule['SUPPORTS_RULE']); | |
| /* collection of booleans, undefined or nulls */ | |
| site.features = { | |
| touch: ('ontouchstart' in this.root), | |
| lazyloading: ('loading' in HTMLImageElement.prototype), | |
| mediaquery: ('matchMedia' in window), | |
| resize: ('ResizeObserver' in window), | |
| intersection: ('IntersectionObserver' in window), | |
| fontface: ('FontFace' in window) && !!document['fonts'], | |
| cssom: CSSOM, | |
| csstypes: !!(CSSOM && CSS.number), /* typed CSSOM that is; 'CSSUnitValue' in window */ | |
| houdini: CSSOM && ('paintWorklet' in CSS), | |
| flex: CSSOM && CSS.supports("display", "flex"), | |
| msflex: msie && ('msFlexLinePack' in body.style), | |
| grid: CSSOM && CSS.supports("display", "grid"), | |
| msgrid: msie && ('msGridColumnAlign' in body.style), | |
| backdropfilter: CSSOM && (CSS.supports('backdrop-filter', 'blur(1px)') || CSS.supports('-webkit-backdrop-filter', 'blur(1px)')), | |
| cssmin: CSSOM && CSS.supports("width", "min(1px,2px)"), | |
| cssmax: CSSOM && CSS.supports("width", "max(1px,2px)"), | |
| cssclamp: CSSOM && CSS.supports("width", "clamp(1px,2px,3px)") | |
| }; | |
| /* keep what's true */ | |
| Object.keys(site.features).forEach(function (key, index) { | |
| if (!site.features[key]) { | |
| delete site.features[key]; | |
| } else { | |
| site.setFeature(key, body); | |
| } | |
| }); | |
| (this.debug) && console.log('features',site.features); | |
| /* engines and user agents, collection of booleans, undefined or nulls */ | |
| site.agents = { | |
| msie : msie, | |
| trident: msie && !!(ua.match("Trident/(\\d+)", "g")), | |
| presto : ('supportsCSS' in window) && ('opera' in window && window.opera.version() <= 13), /* !!(ua.match("Presto/(\\d+)", "g")) */ | |
| edge : edge && CSSOM, /* 12:navigator.maxTouchPoints, 14:navigator.sendBeacon() */ | |
| edgium : edg = CSSOM && !!(ua.match("Edg/(\\d+)", "g")), | |
| gecko : ff && !!(ua.match("rv:(\\d+).*Firefox/\\1", "g")), | |
| servo : ff && CSSOM && (Error.prototype instanceof Object), /* Firefox 53+ Quantum CSS Engine */ | |
| chrome : (window.chrome) && ('CSSVariableReferenceValue' in window), /* CR66+,EG79,OP53 */ | |
| opera : !!(ua.match("OPR/(\\d+)", "g")) && ('opr' in window), | |
| blink : !edge && CSSOM && !!(ua.match("(?:Chrome|ChriOS)/(\\d+)", "g")), /* Chrome, OPera (OPR/15+), VIvaldi, Amazon Silk, Edg/79+, SamsungInternet, Android Webview */ | |
| webkit : false, /* SaFari */ | |
| }; | |
| (this.debug) && console.log('agents',site.agents); | |
| if (msie && site.agents.trident) { | |
| /* add stub entry for setClasses() ie9: Trident/5, ie10: Trident/6, ie11: Trident/7 */ | |
| site.agents['is-ie'] = | |
| site.agents['msie' + (document.documentMode||7)] = true; | |
| } else if (!site.agents.gecko) { | |
| site.agents.webkit = (!site.agents.edge && ('webkitAnimation' in body.style)); | |
| site.agents.chrome = (site.agents.blink && site.agents.webkit); | |
| /* Old Edge on iOS and Android uses different engines | |
| * @link https://blogs.windows.com/msedgedev/2017/10/05/microsoft-edge-ios-android-developer/ */ | |
| if (site.agents.webkit && (edg = ua.match("EdgiOS/(\\d+)", "g"))) { | |
| site.agents['edge-ios'] = true; | |
| } else if (site.agents.chrome && (edg = ua.match("EdgA/(\\d+)", "g"))) { | |
| site.agents['edge-and'] = true; | |
| } | |
| } | |
| /* keep what's true */ | |
| Object.keys(site.agents).forEach(function (key, index) { | |
| if (!site.agents[key]) { | |
| delete site.agents[key]; | |
| } else { | |
| site.setFeature(key, this.root); | |
| } | |
| }); | |
| }, | |
| debug: false, | |
| version: '1.3.3' | |
| }; | |
| (function() { | |
| Sleuth.debug = true; /* check console */ | |
| Sleuth.sniff(); | |
| })(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment