// *** src/dashboard.js/utils.js NETDATA.name2id = function (s) { return s .replace(/ /g, '_') .replace(/:/g, '_') .replace(/\(/g, '_') .replace(/\)/g, '_') .replace(/\./g, '_') .replace(/\//g, '_'); }; NETDATA.encodeURIComponent = function (s) { if (typeof(s) === 'string') { return encodeURIComponent(s); } return s; }; /// A heuristic for detecting slow devices. let isSlowDeviceResult = undefined; const isSlowDevice = function () { if (!isSlowDeviceResult) { return isSlowDeviceResult; } try { let ua = navigator.userAgent.toLowerCase(); let iOS = /ipad|iphone|ipod/.test(ua) && !window.MSStream; let android = /android/.test(ua) && !window.MSStream; isSlowDeviceResult = (iOS || android); } catch (e) { isSlowDeviceResult = false; } return isSlowDeviceResult; }; NETDATA.guid = function () { function s4() { return Math.floor((1 + Math.random()) * 0x10000) .toString(16) .substring(1); } return s4() + s4() + '-' + s4() + '-' + s4() + '-' + s4() + '-' + s4() + s4() + s4(); }; NETDATA.zeropad = function (x) { if (x > -10 && x < 10) { return '0' + x.toString(); } else { return x.toString(); } }; NETDATA.seconds4human = function (seconds, options) { let defaultOptions = { now: 'now', space: ' ', negative_suffix: 'ago', day: 'day', days: 'days', hour: 'hour', hours: 'hours', minute: 'min', minutes: 'mins', second: 'sec', seconds: 'secs', and: 'and' }; if (typeof options !== 'object') { options = defaultOptions; } else { for (const x in defaultOptions) { if (typeof options[x] !== 'string') { options[x] = defaultOptions[x]; } } } if (typeof seconds === 'string') { seconds = parseInt(seconds, 10); } if (seconds === 0) { return options.now; } let suffix = ''; if (seconds < 0) { seconds = -seconds; if (options.negative_suffix !== '') { suffix = options.space + options.negative_suffix; } } let days = Math.floor(seconds / 86400); seconds -= (days * 86400); let hours = Math.floor(seconds / 3600); seconds -= (hours * 3600); let minutes = Math.floor(seconds / 60); seconds -= (minutes * 60); let strings = []; if (days > 1) { strings.push(days.toString() + options.space + options.days); } else if (days === 1) { strings.push(days.toString() + options.space + options.day); } if (hours > 1) { strings.push(hours.toString() + options.space + options.hours); } else if (hours === 1) { strings.push(hours.toString() + options.space + options.hour); } if (minutes > 1) { strings.push(minutes.toString() + options.space + options.minutes); } else if (minutes === 1) { strings.push(minutes.toString() + options.space + options.minute); } if (seconds > 1) { strings.push(Math.floor(seconds).toString() + options.space + options.seconds); } else if (seconds === 1) { strings.push(Math.floor(seconds).toString() + options.space + options.second); } if (strings.length === 1) { return strings.pop() + suffix; } let last = strings.pop(); return strings.join(", ") + " " + options.and + " " + last + suffix; }; // ---------------------------------------------------------------------------------------------------------------- // element data attributes NETDATA.dataAttribute = function (element, attribute, def) { let key = 'data-' + attribute.toString(); if (element.hasAttribute(key)) { let data = element.getAttribute(key); if (data === 'true') { return true; } if (data === 'false') { return false; } if (data === 'null') { return null; } // Only convert to a number if it doesn't change the string if (data === +data + '') { return +data; } if (/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/.test(data)) { return JSON.parse(data); } return data; } else { return def; } }; NETDATA.dataAttributeBoolean = function (element, attribute, def) { let value = NETDATA.dataAttribute(element, attribute, def); if (value === true || value === false) // gmosx: Love this :) { return value; } if (typeof(value) === 'string') { if (value === 'yes' || value === 'on') { return true; } if (value === '' || value === 'no' || value === 'off' || value === 'null') { return false; } return def; } if (typeof(value) === 'number') { return value !== 0; } return def; }; // ---------------------------------------------------------------------------------------------------------------- // fast numbers formatting NETDATA.fastNumberFormat = { formattersFixed: [], formattersZeroBased: [], // this is the fastest and the preferred getIntlNumberFormat: function (min, max) { let key = max; if (min === max) { if (typeof this.formattersFixed[key] === 'undefined') { this.formattersFixed[key] = new Intl.NumberFormat(undefined, { // style: 'decimal', // minimumIntegerDigits: 1, // minimumSignificantDigits: 1, // maximumSignificantDigits: 1, useGrouping: true, minimumFractionDigits: min, maximumFractionDigits: max }); } return this.formattersFixed[key]; } else if (min === 0) { if (typeof this.formattersZeroBased[key] === 'undefined') { this.formattersZeroBased[key] = new Intl.NumberFormat(undefined, { // style: 'decimal', // minimumIntegerDigits: 1, // minimumSignificantDigits: 1, // maximumSignificantDigits: 1, useGrouping: true, minimumFractionDigits: min, maximumFractionDigits: max }); } return this.formattersZeroBased[key]; } else { // this is never used // it is added just for completeness return new Intl.NumberFormat(undefined, { // style: 'decimal', // minimumIntegerDigits: 1, // minimumSignificantDigits: 1, // maximumSignificantDigits: 1, useGrouping: true, minimumFractionDigits: min, maximumFractionDigits: max }); } }, // this respects locale getLocaleString: function (min, max) { let key = max; if (min === max) { if (typeof this.formattersFixed[key] === 'undefined') { this.formattersFixed[key] = { format: function (value) { return value.toLocaleString(undefined, { // style: 'decimal', // minimumIntegerDigits: 1, // minimumSignificantDigits: 1, // maximumSignificantDigits: 1, useGrouping: true, minimumFractionDigits: min, maximumFractionDigits: max }); } }; } return this.formattersFixed[key]; } else if (min === 0) { if (typeof this.formattersZeroBased[key] === 'undefined') { this.formattersZeroBased[key] = { format: function (value) { return value.toLocaleString(undefined, { // style: 'decimal', // minimumIntegerDigits: 1, // minimumSignificantDigits: 1, // maximumSignificantDigits: 1, useGrouping: true, minimumFractionDigits: min, maximumFractionDigits: max }); } }; } return this.formattersZeroBased[key]; } else { return { format: function (value) { return value.toLocaleString(undefined, { // style: 'decimal', // minimumIntegerDigits: 1, // minimumSignificantDigits: 1, // maximumSignificantDigits: 1, useGrouping: true, minimumFractionDigits: min, maximumFractionDigits: max }); } }; } }, // the fallback getFixed: function (min, max) { let key = max; if (min === max) { if (typeof this.formattersFixed[key] === 'undefined') { this.formattersFixed[key] = { format: function (value) { if (value === 0) { return "0"; } return value.toFixed(max); } }; } return this.formattersFixed[key]; } else if (min === 0) { if (typeof this.formattersZeroBased[key] === 'undefined') { this.formattersZeroBased[key] = { format: function (value) { if (value === 0) { return "0"; } return value.toFixed(max); } }; } return this.formattersZeroBased[key]; } else { return { format: function (value) { if (value === 0) { return "0"; } return value.toFixed(max); } }; } }, testIntlNumberFormat: function () { let value = 1.12345; let e1 = "1.12", e2 = "1,12"; let s = ""; try { let x = new Intl.NumberFormat(undefined, { useGrouping: true, minimumFractionDigits: 2, maximumFractionDigits: 2 }); s = x.format(value); } catch (e) { s = ""; } // console.log('NumberFormat: ', s); return (s === e1 || s === e2); }, testLocaleString: function () { let value = 1.12345; let e1 = "1.12", e2 = "1,12"; let s = ""; try { s = value.toLocaleString(undefined, { useGrouping: true, minimumFractionDigits: 2, maximumFractionDigits: 2 }); } catch (e) { s = ""; } // console.log('localeString: ', s); return (s === e1 || s === e2); }, // on first run we decide which formatter to use get: function (min, max) { if (this.testIntlNumberFormat()) { // console.log('numberformat'); this.get = this.getIntlNumberFormat; } else if (this.testLocaleString()) { // console.log('localestring'); this.get = this.getLocaleString; } else { // console.log('fixed'); this.get = this.getFixed; } return this.get(min, max); } }; // ---------------------------------------------------------------------------------------------------------------- // Detect the netdata server // http://stackoverflow.com/questions/984510/what-is-my-script-src-url // http://stackoverflow.com/questions/6941533/get-protocol-domain-and-port-from-url NETDATA._scriptSource = function () { let script = null; if (typeof document.currentScript !== 'undefined') { script = document.currentScript; } else { const all_scripts = document.getElementsByTagName('script'); script = all_scripts[all_scripts.length - 1]; } if (typeof script.getAttribute.length !== 'undefined') { script = script.src; } else { script = script.getAttribute('src', -1); } return script; };