Minetrack 5 (#143)
* remove unused #getServer methods, inline #roundToPoint * replace #safeName regex with incremental ids * remove legacy #setInterval based #updateMojangServices handling * add Tooltip class, move faviconSize to css instead of js * move server id assignment to ServerRegistry * move printPort logic to formatMinecraftServerAddress, add MINECRAFT_DEFAULT_PORTS * simplify ping tracking * rework perc-bar tooltip to not use mousemove event * begin moving graphing logic to GraphDisplayManager * begin merge graph point tracking into graphDisplayManager * centralizing graphing logic into GraphDisplayManager * properly reset GraphDisplayManager when handling disconnects * move individual server graph data into ServerGraph class * constantly run sortServers loop to simplify logic * inline #updateMojangServices method * resize performance improvements * remove legacy bootTime refresh behavior, require manual user refresh * move class defs to core.js * remove unused #isGraphDataVisible arg * remove #toggleControlsDrawer * dont call #updatePercentageBar in #updateServerStatus calls * centralize caption handling * inline #msToTime * remove hackish seconds handling for timestamps * reduce #forEach calls with filter/map * safely fallback to errorMessage if errno/description does not match * Add /images/missing_favicon.png path instead of putting base64 in js * remove debug * cleanup mojang status handling * move historyPlot instance into GraphDisplayManager * cleanup checkbox html generation * cleanup #updateServerStatus * fix up tooltip styling * move jquery code out of core.js * fix add server race condition when initially pinging servers * send error.placeholder=true for pending pings so the frontend can discard later * filter placeholder pings sent by the backend * del assets/images/logo_2014.png * move graph code into graph.js * merge pingTracker into ServerRegistry+ServerGraph * remove todos * simplify getVisibleGraphData * fix potential sortServers race condition when adding * use #show instead of #fadeIn(0) * remove publicConfig.json, send over socket * update docs/CHANGELOG.md * getOrAssign -> getOrCreateId * dont delete graph controls when disconnected * early work cleaning up HTML+CSS structures * cleanup server css elements * cleanup graph control css elements * move base CSS color values into @media(prefers-color-scheme: light) * move CSS magic colors to vars * reduce duplicated CSS color rules * inline body text color CSS * WIP replacing jQuery calls with vanilla JS * WIP replacing jQuery calls with vanilla JS * replace getElementsByClass with querySelectorAll * typeMarker -> serverTypeHTML * use jQuery slim for remaining flot.js dependency * merge setAllGraphVisibility into GraphDisplayManager * break apart element update and redraw logic * add eslint + parcel bundler * auto lint assets/js when building * statically serve favicons/ for faviconOverrides outside of dist/ * only send favicons when changed * move faviconOverride behavior into entry in servers.json * add warning to backend server files * remove .server-favicon-missing class * add Minetrack 5 migration guide * add npm run build step to install.sh * adjust package.json version to 5.0.0 * remove js references from index.html * move logic and behavior out of site.js * cleanup ServerRegistry methods * prevent multiple history graph redraws * add comments * cleanup #addServer usage, move to App * move graph control bindings into GraphDisplayManager * site.js -> main.js, core.js -> servers.js * move Tooltip/Caption into util.js * spacing tweak * format index.html * ensure the frontend does not handling updateHistoryGraph events * prevent versions/record updates if the same value * avoid empty percbar updates, ensure versions are sorted * only include main.js ref in index.html * serve minified copy of font awesome directly * bundle icons.css into main.css, remove Open Sans 400 * add new SVG logo * update docs/CHANGELOG.md * new design, server version grouping * remove start.sh call from install.sh * move graph controls into header with new button * move #handleSettingsToggle back to graph * fix legacy code behavior of currentVersionIndex applying globally * fix header text color in light mode * fix mojang status text color in light mode * fix toggle settings and checkbox colors * tweak button hover color * tweak button hover color * add new status-overlay to avoid complicated DOM management during loading * fix initial graph rendering bug * add comments * update default graph tick sizes * prevent #tooltip from overflowing page * remove localhost spec * prevent minor connection errors from reshuffling layout * update CHANGELOG.md * add message/button for manually loading historical graph on mobile devices * send isGraphVisible to frontend to prevent alert if logToDatabase: false * send timestamp data with record * update docs/CHANGELOG.md * remove clock icon * remove 24h peak timestamp * Only check favicon if present * safely handle undefined/empty knownVersions in #formatMinecraftVersions * merge config.versions and minecraft.json into minecraft_versions.json, simplify index matching behavior * remove localhost url in socket.io config * stub methods/linkage for FocusManager * add #isObjectEqual hack, add event proxying to FocusManager * wip extended stats box * remove server-type badging * tweak mojang unstable color * serve socket.io-client using parcel * fix incorrect mojang status colors * remove legacy capitalization design * redesign focus boxes * update docs/CHANGELOG.md * remove localhost ref * color clock icon * use background-color for hover effect, remove unused var * improve stats focus box icons * change mojang sessions icon to globe * Add favorites system * remove focus boxes * update docs/CHANGELOG.md * remove focus icons from font * simplify graph related event binding * Add Sort By button * store current sortOption in localStorage * update docs/CHANGELOG.md * move magic 0 sortOption to SORT_OPTION_INDEX_DEFAULT * remove localhost ref * merge #settings-toggle, #sort-by and .mojang-status CSS * remove .focus-box CSS * use sortedServerIds for _lastSortedServers * tweak --color-blue * new missing_favicon design to match logo * edit footer CSS/text, remove github icon * replace player count diff counter with GROWTH sort option * italize non-default sort options * add Only Favorites button to auto sync favorites to the visible graph data * add icons to graph control buttons * update docs/CHANGELOG.md * use * to denote non-default sort option instead * remove localhost url in socket.io config * add value highlighting to make sort by easier to read * remove last remaining uppercase text * remove serverTypesVisible from config.json * simplify header CSS, fix spacing with logToDatabase=false * fix inverted text color on highlighted values * remove localhost url in socket.io config * break header into rows on mobile devices Co-authored-by: Hugo Manrique <contact@hugmanrique.me>
This commit is contained in:
@ -1,189 +1,160 @@
|
||||
var MISSING_FAVICON_BASE64 = "data:image/png;base64,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";
|
||||
export class Tooltip {
|
||||
constructor () {
|
||||
this._div = document.getElementById('tooltip')
|
||||
}
|
||||
|
||||
var tooltip = $('#tooltip');
|
||||
set (x, y, offsetX, offsetY, html) {
|
||||
this._div.innerHTML = html
|
||||
|
||||
var lastMojangServiceUpdate;
|
||||
var publicConfig;
|
||||
// Assign display: block so that the offsetWidth is valid
|
||||
this._div.style.display = 'block'
|
||||
|
||||
function showCaption(html) {
|
||||
var tagline = $('#tagline-text');
|
||||
tagline.stop(true, false);
|
||||
tagline.html(html);
|
||||
tagline.slideDown(100);
|
||||
}
|
||||
// Prevent the div from overflowing the page width
|
||||
const tooltipWidth = this._div.offsetWidth
|
||||
|
||||
function hideCaption() {
|
||||
var tagline = $('#tagline-text');
|
||||
tagline.stop(true, false);
|
||||
tagline.slideUp(100);
|
||||
}
|
||||
|
||||
function setPublicConfig(json) {
|
||||
publicConfig = json;
|
||||
$('#server-container-list').html('');
|
||||
}
|
||||
|
||||
function getServerByField(id, value) {
|
||||
for (var i = 0; i < publicConfig.servers.length; i++) {
|
||||
var entry = publicConfig.servers[i];
|
||||
|
||||
if (entry[id] === value) {
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getServerByIp(ip) {
|
||||
return getServerByField('ip', ip);
|
||||
}
|
||||
|
||||
function getServerByName(name) {
|
||||
return getServerByField('name', name);
|
||||
}
|
||||
|
||||
function getServerColor(name) {
|
||||
var server = getServerByName(name);
|
||||
|
||||
return server ? server.color : stringToColor(name);
|
||||
}
|
||||
|
||||
// Generate (and set) the HTML that displays Mojang status.
|
||||
// If nothing is passed, re-render the last update.
|
||||
// If something is passed, update and then re-render.
|
||||
function updateMojangServices(currentUpdate) {
|
||||
if (currentUpdate) {
|
||||
lastMojangServiceUpdate = currentUpdate;
|
||||
// 1.2 is a magic number used to pad the offset to ensure the tooltip
|
||||
// never gets close or surpasses the page's X width
|
||||
if (x + offsetX + (tooltipWidth * 1.2) > window.innerWidth) {
|
||||
x -= tooltipWidth
|
||||
offsetX *= -1
|
||||
}
|
||||
|
||||
if (!lastMojangServiceUpdate) {
|
||||
return;
|
||||
this._div.style.top = (y + offsetY) + 'px'
|
||||
this._div.style.left = (x + offsetX) + 'px'
|
||||
}
|
||||
|
||||
hide = () => {
|
||||
this._div.style.display = 'none'
|
||||
}
|
||||
}
|
||||
|
||||
export class Caption {
|
||||
constructor () {
|
||||
this._div = document.getElementById('status-text')
|
||||
}
|
||||
|
||||
set (text) {
|
||||
this._div.innerText = text
|
||||
this._div.style.display = 'block'
|
||||
}
|
||||
|
||||
hide () {
|
||||
this._div.style.display = 'none'
|
||||
}
|
||||
}
|
||||
|
||||
// Minecraft Java Edition default server port: 25565
|
||||
// Minecraft Bedrock Edition default server port: 19132
|
||||
const MINECRAFT_DEFAULT_PORTS = [25565, 19132]
|
||||
|
||||
export function formatMinecraftServerAddress (ip, port) {
|
||||
if (port && !MINECRAFT_DEFAULT_PORTS.includes(port)) {
|
||||
return ip + ':' + port
|
||||
}
|
||||
return ip
|
||||
}
|
||||
|
||||
// Detect gaps in versions by matching their indexes to knownVersions
|
||||
export function formatMinecraftVersions (versions, knownVersions) {
|
||||
if (!versions || !versions.length || !knownVersions || !knownVersions.length) {
|
||||
return
|
||||
}
|
||||
|
||||
let currentVersionGroup = []
|
||||
const versionGroups = []
|
||||
|
||||
for (let i = 0; i < versions.length; i++) {
|
||||
const versionIndex = versions[i]
|
||||
|
||||
// Look for value mismatch between the previous index
|
||||
// Require i > 0 since lastVersionIndex is undefined for i === 0
|
||||
if (i > 0 && versions[i] - 1 !== versionIndex - 1) {
|
||||
versionGroups.push(currentVersionGroup)
|
||||
currentVersionGroup = []
|
||||
}
|
||||
|
||||
var keys = Object.keys(lastMojangServiceUpdate);
|
||||
currentVersionGroup.push(versionIndex)
|
||||
}
|
||||
|
||||
for (var i = 0; i < keys.length; i++) {
|
||||
var key = keys[i];
|
||||
var status = lastMojangServiceUpdate[key];
|
||||
// Ensure the last versionGroup is always pushed
|
||||
if (currentVersionGroup.length > 0) {
|
||||
versionGroups.push(currentVersionGroup)
|
||||
}
|
||||
|
||||
// hack: ensure mojang-status is added for alignment, replace existing class to swap status color
|
||||
$('#mojang-status_' + status.name).attr('class', 'mojang-status mojang-status-' + status.title.toLowerCase());
|
||||
$('#mojang-status-text_' + status.name).text(status.title);
|
||||
if (versionGroups.length === 0) {
|
||||
return
|
||||
}
|
||||
|
||||
// Remap individual versionGroups values into named versions
|
||||
return versionGroups.map(versionGroup => {
|
||||
const startVersion = knownVersions[versionGroup[0]]
|
||||
|
||||
if (versionGroup.length === 1) {
|
||||
// A versionGroup may contain a single version, only return its name
|
||||
// This is a cosmetic catch to avoid version labels like 1.0-1.0
|
||||
return startVersion
|
||||
} else {
|
||||
const endVersion = knownVersions[versionGroup[versionGroup.length - 1]]
|
||||
|
||||
return startVersion + '-' + endVersion
|
||||
}
|
||||
}).join(', ')
|
||||
}
|
||||
|
||||
function findErrorMessage(error) {
|
||||
if (error.description) {
|
||||
return error.description;
|
||||
} else if (error.errno) {
|
||||
return error.errno;
|
||||
export function formatTimestamp (millis) {
|
||||
const date = new Date(0)
|
||||
date.setUTCSeconds(millis / 1000)
|
||||
return date.toLocaleTimeString()
|
||||
}
|
||||
|
||||
export function formatDate (millis) {
|
||||
const date = new Date(0)
|
||||
date.setUTCSeconds(millis / 1000)
|
||||
return date.toLocaleDateString()
|
||||
}
|
||||
|
||||
export function formatPercent (x, over) {
|
||||
const val = Math.round((x / over) * 100 * 10) / 10
|
||||
return val + '%'
|
||||
}
|
||||
|
||||
export function formatNumber (x) {
|
||||
return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',')
|
||||
}
|
||||
|
||||
export function isArrayEqual (a, b) {
|
||||
if (typeof a === 'undefined' || typeof a !== typeof b) {
|
||||
return false
|
||||
}
|
||||
if (a.length !== b.length) {
|
||||
return false
|
||||
}
|
||||
for (let i = 0; i < a.length; i++) {
|
||||
if (a[i] !== b[i]) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
function getTimestamp(ms, timeOnly) {
|
||||
var date = new Date(0);
|
||||
export function isObjectEqual (a, b, props) {
|
||||
if (typeof a === 'undefined' || typeof a !== typeof b) {
|
||||
return false
|
||||
}
|
||||
for (let i = 0; i < props.length; i++) {
|
||||
const prop = props[i]
|
||||
|
||||
date.setUTCSeconds(ms);
|
||||
|
||||
return date.toLocaleTimeString();
|
||||
}
|
||||
|
||||
function safeName(name) {
|
||||
return name.replace(/ /g, '');
|
||||
}
|
||||
|
||||
function renderTooltip(x, y, html) {
|
||||
tooltip.html(html).css({
|
||||
top: y,
|
||||
left: x
|
||||
}).fadeIn(0);
|
||||
}
|
||||
|
||||
function hideTooltip() {
|
||||
tooltip.hide();
|
||||
}
|
||||
|
||||
function formatNumber(x) {
|
||||
return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
|
||||
if (typeof a[prop] === 'undefined' || typeof a[prop] !== typeof b[prop] || a[prop] !== b[prop]) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// From http://detectmobilebrowsers.com/
|
||||
function isMobileBrowser() {
|
||||
export function isMobileBrowser () {
|
||||
var check = false;
|
||||
(function(a){if(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0,4)))check = true})(navigator.userAgent||navigator.vendor||window.opera);
|
||||
return check;
|
||||
}
|
||||
|
||||
function trimOldPings(data, graphDuration) {
|
||||
var keys = Object.keys(data);
|
||||
|
||||
var timeMs = new Date().getTime();
|
||||
|
||||
for (var x = 0; x < keys.length; x++) {
|
||||
var listing = data[keys[x]];
|
||||
|
||||
var toSplice = [];
|
||||
|
||||
for (var i = 0; i < listing.length; i++) {
|
||||
var entry = listing[i];
|
||||
|
||||
if (timeMs - entry[0] > graphDuration) {
|
||||
toSplice.push(i);
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = 0; i < toSplice.length; i++) {
|
||||
listing.splice(toSplice[i], 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function stringToColor(base) {
|
||||
var hash;
|
||||
|
||||
for (var i = base.length - 1, hash = 0; i >= 0; i--) {
|
||||
hash = base.charCodeAt(i) + ((hash << 5) - hash);
|
||||
}
|
||||
|
||||
color = Math.floor(Math.abs((Math.sin(hash) * 10000) % 1 * 16777216)).toString(16);
|
||||
|
||||
return '#' + Array(6 - color.length + 1).join('0') + color;
|
||||
}
|
||||
|
||||
function roundToPoint(val, scale) {
|
||||
return Math.round(val * scale) / scale;
|
||||
}
|
||||
|
||||
function msToTime(timer) {
|
||||
var milliseconds = timer % 1000;
|
||||
timer = (timer - milliseconds) / 1000;
|
||||
|
||||
var seconds = timer % 60;
|
||||
timer = (timer - seconds) / 60;
|
||||
|
||||
var minutes = timer % 60;
|
||||
var hours = (timer - minutes) / 60;
|
||||
|
||||
var days = Math.floor(hours / 24);
|
||||
hours -= days * 24;
|
||||
|
||||
var string = '';
|
||||
|
||||
// hack: only format days if >1, if === 1 it will format as "24h" instead
|
||||
if (days > 1) {
|
||||
string += days + 'd';
|
||||
} else if (days === 1) {
|
||||
hours += 24;
|
||||
}
|
||||
|
||||
if (hours > 0) {
|
||||
string += hours + 'h';
|
||||
}
|
||||
if (minutes > 0) {
|
||||
string += minutes + 'm';
|
||||
}
|
||||
if (seconds > 0) {
|
||||
string += seconds + 's';
|
||||
}
|
||||
|
||||
return string;
|
||||
// eslint-disable-next-line no-useless-escape
|
||||
(function (a) { if (/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(a) || /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0, 4)))check = true })(navigator.userAgent || navigator.vendor || window.opera)
|
||||
return check
|
||||
}
|
||||
|
Reference in New Issue
Block a user