diff options
Diffstat (limited to 'web/gui/src/dashboard.js/utils.js')
-rw-r--r-- | web/gui/src/dashboard.js/utils.js | 432 |
1 files changed, 432 insertions, 0 deletions
diff --git a/web/gui/src/dashboard.js/utils.js b/web/gui/src/dashboard.js/utils.js new file mode 100644 index 0000000..8014aaf --- /dev/null +++ b/web/gui/src/dashboard.js/utils.js @@ -0,0 +1,432 @@ +// *** 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 (var 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; +}; |