feat:Added piechart in Dashboard
This commit is contained in:
+243
@@ -0,0 +1,243 @@
|
||||
import Utils from './Utils'
|
||||
|
||||
/**
|
||||
* DateTime Class to manipulate datetime values.
|
||||
*
|
||||
* @module DateTime
|
||||
**/
|
||||
|
||||
class DateTime {
|
||||
constructor(ctx) {
|
||||
this.ctx = ctx
|
||||
this.w = ctx.w
|
||||
|
||||
this.months31 = [1, 3, 5, 7, 8, 10, 12]
|
||||
this.months30 = [2, 4, 6, 9, 11]
|
||||
|
||||
this.daysCntOfYear = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334]
|
||||
}
|
||||
|
||||
isValidDate(date) {
|
||||
if (typeof date === 'number') {
|
||||
return false // don't test for timestamps
|
||||
}
|
||||
return !isNaN(this.parseDate(date))
|
||||
}
|
||||
|
||||
getTimeStamp(dateStr) {
|
||||
if (!Date.parse(dateStr)) {
|
||||
return dateStr
|
||||
}
|
||||
const utc = this.w.config.xaxis.labels.datetimeUTC
|
||||
return !utc
|
||||
? new Date(dateStr).getTime()
|
||||
: new Date(new Date(dateStr).toISOString().substr(0, 25)).getTime()
|
||||
}
|
||||
|
||||
getDate(timestamp) {
|
||||
const utc = this.w.config.xaxis.labels.datetimeUTC
|
||||
|
||||
return utc
|
||||
? new Date(new Date(timestamp).toUTCString())
|
||||
: new Date(timestamp)
|
||||
}
|
||||
|
||||
parseDate(dateStr) {
|
||||
const parsed = Date.parse(dateStr)
|
||||
if (!isNaN(parsed)) {
|
||||
return this.getTimeStamp(dateStr)
|
||||
}
|
||||
|
||||
let output = Date.parse(dateStr.replace(/-/g, '/').replace(/[a-z]+/gi, ' '))
|
||||
output = this.getTimeStamp(output)
|
||||
return output
|
||||
}
|
||||
|
||||
// This fixes the difference of x-axis labels between chrome/safari
|
||||
// Fixes #1726, #1544, #1485, #1255
|
||||
parseDateWithTimezone(dateStr) {
|
||||
return Date.parse(dateStr.replace(/-/g, '/').replace(/[a-z]+/gi, ' '))
|
||||
}
|
||||
|
||||
// http://stackoverflow.com/questions/14638018/current-time-formatting-with-javascript#answer-14638191
|
||||
formatDate(date, format) {
|
||||
const locale = this.w.globals.locale
|
||||
|
||||
const utc = this.w.config.xaxis.labels.datetimeUTC
|
||||
|
||||
let MMMM = ['\x00', ...locale.months]
|
||||
let MMM = ['\x01', ...locale.shortMonths]
|
||||
let dddd = ['\x02', ...locale.days]
|
||||
let ddd = ['\x03', ...locale.shortDays]
|
||||
|
||||
function ii(i, len) {
|
||||
let s = i + ''
|
||||
len = len || 2
|
||||
while (s.length < len) s = '0' + s
|
||||
return s
|
||||
}
|
||||
|
||||
let y = utc ? date.getUTCFullYear() : date.getFullYear()
|
||||
format = format.replace(/(^|[^\\])yyyy+/g, '$1' + y)
|
||||
format = format.replace(/(^|[^\\])yy/g, '$1' + y.toString().substr(2, 2))
|
||||
format = format.replace(/(^|[^\\])y/g, '$1' + y)
|
||||
|
||||
let M = (utc ? date.getUTCMonth() : date.getMonth()) + 1
|
||||
format = format.replace(/(^|[^\\])MMMM+/g, '$1' + MMMM[0])
|
||||
format = format.replace(/(^|[^\\])MMM/g, '$1' + MMM[0])
|
||||
format = format.replace(/(^|[^\\])MM/g, '$1' + ii(M))
|
||||
format = format.replace(/(^|[^\\])M/g, '$1' + M)
|
||||
|
||||
let d = utc ? date.getUTCDate() : date.getDate()
|
||||
format = format.replace(/(^|[^\\])dddd+/g, '$1' + dddd[0])
|
||||
format = format.replace(/(^|[^\\])ddd/g, '$1' + ddd[0])
|
||||
format = format.replace(/(^|[^\\])dd/g, '$1' + ii(d))
|
||||
format = format.replace(/(^|[^\\])d/g, '$1' + d)
|
||||
|
||||
let H = utc ? date.getUTCHours() : date.getHours()
|
||||
format = format.replace(/(^|[^\\])HH+/g, '$1' + ii(H))
|
||||
format = format.replace(/(^|[^\\])H/g, '$1' + H)
|
||||
|
||||
let h = H > 12 ? H - 12 : H === 0 ? 12 : H
|
||||
format = format.replace(/(^|[^\\])hh+/g, '$1' + ii(h))
|
||||
format = format.replace(/(^|[^\\])h/g, '$1' + h)
|
||||
|
||||
let m = utc ? date.getUTCMinutes() : date.getMinutes()
|
||||
format = format.replace(/(^|[^\\])mm+/g, '$1' + ii(m))
|
||||
format = format.replace(/(^|[^\\])m/g, '$1' + m)
|
||||
|
||||
let s = utc ? date.getUTCSeconds() : date.getSeconds()
|
||||
format = format.replace(/(^|[^\\])ss+/g, '$1' + ii(s))
|
||||
format = format.replace(/(^|[^\\])s/g, '$1' + s)
|
||||
|
||||
let f = utc ? date.getUTCMilliseconds() : date.getMilliseconds()
|
||||
format = format.replace(/(^|[^\\])fff+/g, '$1' + ii(f, 3))
|
||||
f = Math.round(f / 10)
|
||||
format = format.replace(/(^|[^\\])ff/g, '$1' + ii(f))
|
||||
f = Math.round(f / 10)
|
||||
format = format.replace(/(^|[^\\])f/g, '$1' + f)
|
||||
|
||||
let T = H < 12 ? 'AM' : 'PM'
|
||||
format = format.replace(/(^|[^\\])TT+/g, '$1' + T)
|
||||
format = format.replace(/(^|[^\\])T/g, '$1' + T.charAt(0))
|
||||
|
||||
let t = T.toLowerCase()
|
||||
format = format.replace(/(^|[^\\])tt+/g, '$1' + t)
|
||||
format = format.replace(/(^|[^\\])t/g, '$1' + t.charAt(0))
|
||||
|
||||
let tz = -date.getTimezoneOffset()
|
||||
let K = utc || !tz ? 'Z' : tz > 0 ? '+' : '-'
|
||||
|
||||
if (!utc) {
|
||||
tz = Math.abs(tz)
|
||||
let tzHrs = Math.floor(tz / 60)
|
||||
let tzMin = tz % 60
|
||||
K += ii(tzHrs) + ':' + ii(tzMin)
|
||||
}
|
||||
|
||||
format = format.replace(/(^|[^\\])K/g, '$1' + K)
|
||||
|
||||
let day = (utc ? date.getUTCDay() : date.getDay()) + 1
|
||||
format = format.replace(new RegExp(dddd[0], 'g'), dddd[day])
|
||||
format = format.replace(new RegExp(ddd[0], 'g'), ddd[day])
|
||||
|
||||
format = format.replace(new RegExp(MMMM[0], 'g'), MMMM[M])
|
||||
format = format.replace(new RegExp(MMM[0], 'g'), MMM[M])
|
||||
|
||||
format = format.replace(/\\(.)/g, '$1')
|
||||
|
||||
return format
|
||||
}
|
||||
|
||||
getTimeUnitsfromTimestamp(minX, maxX, utc) {
|
||||
let w = this.w
|
||||
|
||||
if (w.config.xaxis.min !== undefined) {
|
||||
minX = w.config.xaxis.min
|
||||
}
|
||||
if (w.config.xaxis.max !== undefined) {
|
||||
maxX = w.config.xaxis.max
|
||||
}
|
||||
|
||||
const tsMin = this.getDate(minX)
|
||||
const tsMax = this.getDate(maxX)
|
||||
|
||||
const minD = this.formatDate(tsMin, 'yyyy MM dd HH mm ss fff').split(' ')
|
||||
const maxD = this.formatDate(tsMax, 'yyyy MM dd HH mm ss fff').split(' ')
|
||||
|
||||
return {
|
||||
minMillisecond: parseInt(minD[6], 10),
|
||||
maxMillisecond: parseInt(maxD[6], 10),
|
||||
minSecond: parseInt(minD[5], 10),
|
||||
maxSecond: parseInt(maxD[5], 10),
|
||||
minMinute: parseInt(minD[4], 10),
|
||||
maxMinute: parseInt(maxD[4], 10),
|
||||
minHour: parseInt(minD[3], 10),
|
||||
maxHour: parseInt(maxD[3], 10),
|
||||
minDate: parseInt(minD[2], 10),
|
||||
maxDate: parseInt(maxD[2], 10),
|
||||
minMonth: parseInt(minD[1], 10) - 1,
|
||||
maxMonth: parseInt(maxD[1], 10) - 1,
|
||||
minYear: parseInt(minD[0], 10),
|
||||
maxYear: parseInt(maxD[0], 10),
|
||||
}
|
||||
}
|
||||
|
||||
isLeapYear(year) {
|
||||
return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0
|
||||
}
|
||||
|
||||
calculcateLastDaysOfMonth(month, year, subtract) {
|
||||
const days = this.determineDaysOfMonths(month, year)
|
||||
|
||||
// whatever days we get, subtract the number of days asked
|
||||
return days - subtract
|
||||
}
|
||||
|
||||
determineDaysOfYear(year) {
|
||||
let days = 365
|
||||
|
||||
if (this.isLeapYear(year)) {
|
||||
days = 366
|
||||
}
|
||||
|
||||
return days
|
||||
}
|
||||
|
||||
determineRemainingDaysOfYear(year, month, date) {
|
||||
let dayOfYear = this.daysCntOfYear[month] + date
|
||||
if (month > 1 && this.isLeapYear()) dayOfYear++
|
||||
return dayOfYear
|
||||
}
|
||||
|
||||
determineDaysOfMonths(month, year) {
|
||||
let days = 30
|
||||
|
||||
month = Utils.monthMod(month)
|
||||
|
||||
switch (true) {
|
||||
case this.months30.indexOf(month) > -1:
|
||||
if (month === 2) {
|
||||
if (this.isLeapYear(year)) {
|
||||
days = 29
|
||||
} else {
|
||||
days = 28
|
||||
}
|
||||
}
|
||||
|
||||
break
|
||||
|
||||
case this.months31.indexOf(month) > -1:
|
||||
days = 31
|
||||
break
|
||||
|
||||
default:
|
||||
days = 31
|
||||
break
|
||||
}
|
||||
|
||||
return days
|
||||
}
|
||||
}
|
||||
|
||||
export default DateTime
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
// Helpers to react to element resizes, regardless of what caused them
|
||||
// TODO Currently this creates a new ResizeObserver every time we want to observe an element for resizes
|
||||
// Ideally, we should be able to use a single observer for all elements
|
||||
let ros = new WeakMap() // Map callbacks to ResizeObserver instances for easy removal
|
||||
|
||||
export function addResizeListener(el, fn) {
|
||||
let called = false
|
||||
|
||||
if (el.nodeType !== Node.DOCUMENT_FRAGMENT_NODE) {
|
||||
const elRect = el.getBoundingClientRect()
|
||||
if (el.style.display === 'none' || elRect.width === 0) {
|
||||
// if elRect.width=0, the chart is not rendered at all
|
||||
// (it has either display none or hidden in a different tab)
|
||||
// fixes https://github.com/apexcharts/apexcharts.js/issues/2825
|
||||
// fixes https://github.com/apexcharts/apexcharts.js/issues/2991
|
||||
// fixes https://github.com/apexcharts/apexcharts.js/issues/2992
|
||||
called = true
|
||||
}
|
||||
}
|
||||
|
||||
let ro = new ResizeObserver((r) => {
|
||||
// ROs fire immediately after being created,
|
||||
// per spec: https://drafts.csswg.org/resize-observer/#ref-for-element%E2%91%A3
|
||||
// we don't want that so we just discard the first run
|
||||
if (called) {
|
||||
fn.call(el, r)
|
||||
}
|
||||
called = true
|
||||
})
|
||||
|
||||
if (el.nodeType === Node.DOCUMENT_FRAGMENT_NODE) {
|
||||
// Document fragment, observe children instead (needed for Shadow DOM, see #1332)
|
||||
Array.from(el.children).forEach((c) => ro.observe(c))
|
||||
} else {
|
||||
ro.observe(el)
|
||||
}
|
||||
|
||||
ros.set(fn, ro)
|
||||
}
|
||||
|
||||
export function removeResizeListener(el, fn) {
|
||||
let ro = ros.get(fn)
|
||||
if (ro) {
|
||||
ro.disconnect()
|
||||
ros.delete(fn)
|
||||
}
|
||||
}
|
||||
+444
@@ -0,0 +1,444 @@
|
||||
/*
|
||||
** Generic functions which are not dependent on ApexCharts
|
||||
*/
|
||||
|
||||
class Utils {
|
||||
static bind(fn, me) {
|
||||
return function () {
|
||||
return fn.apply(me, arguments)
|
||||
}
|
||||
}
|
||||
|
||||
static isObject(item) {
|
||||
return (
|
||||
item && typeof item === 'object' && !Array.isArray(item) && item != null
|
||||
)
|
||||
}
|
||||
|
||||
// Type checking that works across different window objects
|
||||
static is(type, val) {
|
||||
return Object.prototype.toString.call(val) === '[object ' + type + ']'
|
||||
}
|
||||
|
||||
static listToArray(list) {
|
||||
let i,
|
||||
array = []
|
||||
for (i = 0; i < list.length; i++) {
|
||||
array[i] = list[i]
|
||||
}
|
||||
return array
|
||||
}
|
||||
|
||||
// to extend defaults with user options
|
||||
// credit: http://stackoverflow.com/questions/27936772/deep-object-merging-in-es6-es7#answer-34749873
|
||||
static extend(target, source) {
|
||||
if (typeof Object.assign !== 'function') {
|
||||
;(function () {
|
||||
Object.assign = function (target) {
|
||||
'use strict'
|
||||
// We must check against these specific cases.
|
||||
if (target === undefined || target === null) {
|
||||
throw new TypeError('Cannot convert undefined or null to object')
|
||||
}
|
||||
|
||||
let output = Object(target)
|
||||
for (let index = 1; index < arguments.length; index++) {
|
||||
let source = arguments[index]
|
||||
if (source !== undefined && source !== null) {
|
||||
for (let nextKey in source) {
|
||||
if (source.hasOwnProperty(nextKey)) {
|
||||
output[nextKey] = source[nextKey]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return output
|
||||
}
|
||||
})()
|
||||
}
|
||||
|
||||
let output = Object.assign({}, target)
|
||||
if (this.isObject(target) && this.isObject(source)) {
|
||||
Object.keys(source).forEach((key) => {
|
||||
if (this.isObject(source[key])) {
|
||||
if (!(key in target)) {
|
||||
Object.assign(output, {
|
||||
[key]: source[key],
|
||||
})
|
||||
} else {
|
||||
output[key] = this.extend(target[key], source[key])
|
||||
}
|
||||
} else {
|
||||
Object.assign(output, {
|
||||
[key]: source[key],
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
return output
|
||||
}
|
||||
|
||||
static extendArray(arrToExtend, resultArr) {
|
||||
let extendedArr = []
|
||||
arrToExtend.map((item) => {
|
||||
extendedArr.push(Utils.extend(resultArr, item))
|
||||
})
|
||||
arrToExtend = extendedArr
|
||||
return arrToExtend
|
||||
}
|
||||
|
||||
// If month counter exceeds 12, it starts again from 1
|
||||
static monthMod(month) {
|
||||
return month % 12
|
||||
}
|
||||
|
||||
static clone(source) {
|
||||
if (Utils.is('Array', source)) {
|
||||
let cloneResult = []
|
||||
for (let i = 0; i < source.length; i++) {
|
||||
cloneResult[i] = this.clone(source[i])
|
||||
}
|
||||
return cloneResult
|
||||
} else if (Utils.is('Null', source)) {
|
||||
// fixes an issue where null values were converted to {}
|
||||
return null
|
||||
} else if (Utils.is('Date', source)) {
|
||||
return source
|
||||
} else if (typeof source === 'object') {
|
||||
let cloneResult = {}
|
||||
for (let prop in source) {
|
||||
if (source.hasOwnProperty(prop)) {
|
||||
cloneResult[prop] = this.clone(source[prop])
|
||||
}
|
||||
}
|
||||
return cloneResult
|
||||
} else {
|
||||
return source
|
||||
}
|
||||
}
|
||||
|
||||
static log10(x) {
|
||||
return Math.log(x) / Math.LN10
|
||||
}
|
||||
|
||||
static roundToBase10(x) {
|
||||
return Math.pow(10, Math.floor(Math.log10(x)))
|
||||
}
|
||||
|
||||
static roundToBase(x, base) {
|
||||
return Math.pow(base, Math.floor(Math.log(x) / Math.log(base)))
|
||||
}
|
||||
|
||||
static parseNumber(val) {
|
||||
if (val === null) return val
|
||||
return parseFloat(val)
|
||||
}
|
||||
|
||||
static stripNumber(num, precision = 2) {
|
||||
return Number.isInteger(num) ? num : parseFloat(num.toPrecision(precision))
|
||||
}
|
||||
|
||||
static randomId() {
|
||||
return (Math.random() + 1).toString(36).substring(4)
|
||||
}
|
||||
|
||||
static noExponents(val) {
|
||||
let data = String(val).split(/[eE]/)
|
||||
if (data.length === 1) return data[0]
|
||||
|
||||
let z = '',
|
||||
sign = val < 0 ? '-' : '',
|
||||
str = data[0].replace('.', ''),
|
||||
mag = Number(data[1]) + 1
|
||||
|
||||
if (mag < 0) {
|
||||
z = sign + '0.'
|
||||
while (mag++) z += '0'
|
||||
return z + str.replace(/^-/, '')
|
||||
}
|
||||
mag -= str.length
|
||||
while (mag--) z += '0'
|
||||
return str + z
|
||||
}
|
||||
|
||||
static getDimensions(el) {
|
||||
const computedStyle = getComputedStyle(el, null)
|
||||
|
||||
let elementHeight = el.clientHeight
|
||||
let elementWidth = el.clientWidth
|
||||
elementHeight -=
|
||||
parseFloat(computedStyle.paddingTop) +
|
||||
parseFloat(computedStyle.paddingBottom)
|
||||
elementWidth -=
|
||||
parseFloat(computedStyle.paddingLeft) +
|
||||
parseFloat(computedStyle.paddingRight)
|
||||
|
||||
return [elementWidth, elementHeight]
|
||||
}
|
||||
|
||||
static getBoundingClientRect(element) {
|
||||
const rect = element.getBoundingClientRect()
|
||||
return {
|
||||
top: rect.top,
|
||||
right: rect.right,
|
||||
bottom: rect.bottom,
|
||||
left: rect.left,
|
||||
width: element.clientWidth,
|
||||
height: element.clientHeight,
|
||||
x: rect.left,
|
||||
y: rect.top,
|
||||
}
|
||||
}
|
||||
|
||||
static getLargestStringFromArr(arr) {
|
||||
return arr.reduce((a, b) => {
|
||||
if (Array.isArray(b)) {
|
||||
b = b.reduce((aa, bb) => (aa.length > bb.length ? aa : bb))
|
||||
}
|
||||
return a.length > b.length ? a : b
|
||||
}, 0)
|
||||
}
|
||||
|
||||
// http://stackoverflow.com/questions/5623838/rgb-to-hex-and-hex-to-rgb#answer-12342275
|
||||
static hexToRgba(hex = '#999999', opacity = 0.6) {
|
||||
if (hex.substring(0, 1) !== '#') {
|
||||
hex = '#999999'
|
||||
}
|
||||
|
||||
let h = hex.replace('#', '')
|
||||
h = h.match(new RegExp('(.{' + h.length / 3 + '})', 'g'))
|
||||
|
||||
for (let i = 0; i < h.length; i++) {
|
||||
h[i] = parseInt(h[i].length === 1 ? h[i] + h[i] : h[i], 16)
|
||||
}
|
||||
|
||||
if (typeof opacity !== 'undefined') h.push(opacity)
|
||||
|
||||
return 'rgba(' + h.join(',') + ')'
|
||||
}
|
||||
|
||||
static getOpacityFromRGBA(rgba) {
|
||||
return parseFloat(rgba.replace(/^.*,(.+)\)/, '$1'))
|
||||
}
|
||||
|
||||
static rgb2hex(rgb) {
|
||||
rgb = rgb.match(
|
||||
/^rgba?[\s+]?\([\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?/i
|
||||
)
|
||||
return rgb && rgb.length === 4
|
||||
? '#' +
|
||||
('0' + parseInt(rgb[1], 10).toString(16)).slice(-2) +
|
||||
('0' + parseInt(rgb[2], 10).toString(16)).slice(-2) +
|
||||
('0' + parseInt(rgb[3], 10).toString(16)).slice(-2)
|
||||
: ''
|
||||
}
|
||||
|
||||
shadeRGBColor(percent, color) {
|
||||
let f = color.split(','),
|
||||
t = percent < 0 ? 0 : 255,
|
||||
p = percent < 0 ? percent * -1 : percent,
|
||||
R = parseInt(f[0].slice(4), 10),
|
||||
G = parseInt(f[1], 10),
|
||||
B = parseInt(f[2], 10)
|
||||
return (
|
||||
'rgb(' +
|
||||
(Math.round((t - R) * p) + R) +
|
||||
',' +
|
||||
(Math.round((t - G) * p) + G) +
|
||||
',' +
|
||||
(Math.round((t - B) * p) + B) +
|
||||
')'
|
||||
)
|
||||
}
|
||||
|
||||
shadeHexColor(percent, color) {
|
||||
let f = parseInt(color.slice(1), 16),
|
||||
t = percent < 0 ? 0 : 255,
|
||||
p = percent < 0 ? percent * -1 : percent,
|
||||
R = f >> 16,
|
||||
G = (f >> 8) & 0x00ff,
|
||||
B = f & 0x0000ff
|
||||
return (
|
||||
'#' +
|
||||
(
|
||||
0x1000000 +
|
||||
(Math.round((t - R) * p) + R) * 0x10000 +
|
||||
(Math.round((t - G) * p) + G) * 0x100 +
|
||||
(Math.round((t - B) * p) + B)
|
||||
)
|
||||
.toString(16)
|
||||
.slice(1)
|
||||
)
|
||||
}
|
||||
|
||||
// beautiful color shading blending code
|
||||
// http://stackoverflow.com/questions/5560248/programmatically-lighten-or-darken-a-hex-color-or-rgb-and-blend-colors
|
||||
shadeColor(p, color) {
|
||||
if (Utils.isColorHex(color)) {
|
||||
return this.shadeHexColor(p, color)
|
||||
} else {
|
||||
return this.shadeRGBColor(p, color)
|
||||
}
|
||||
}
|
||||
|
||||
static isColorHex(color) {
|
||||
return /(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)|(^#[0-9A-F]{8}$)/i.test(color)
|
||||
}
|
||||
|
||||
static getPolygonPos(size, dataPointsLen) {
|
||||
let dotsArray = []
|
||||
let angle = (Math.PI * 2) / dataPointsLen
|
||||
for (let i = 0; i < dataPointsLen; i++) {
|
||||
let curPos = {}
|
||||
curPos.x = size * Math.sin(i * angle)
|
||||
curPos.y = -size * Math.cos(i * angle)
|
||||
dotsArray.push(curPos)
|
||||
}
|
||||
return dotsArray
|
||||
}
|
||||
|
||||
static polarToCartesian(centerX, centerY, radius, angleInDegrees) {
|
||||
let angleInRadians = ((angleInDegrees - 90) * Math.PI) / 180.0
|
||||
|
||||
return {
|
||||
x: centerX + radius * Math.cos(angleInRadians),
|
||||
y: centerY + radius * Math.sin(angleInRadians),
|
||||
}
|
||||
}
|
||||
|
||||
static escapeString(str, escapeWith = 'x') {
|
||||
let newStr = str.toString().slice()
|
||||
newStr = newStr.replace(
|
||||
/[` ~!@#$%^&*()|+\=?;:'",.<>{}[\]\\/]/gi,
|
||||
escapeWith
|
||||
)
|
||||
return newStr
|
||||
}
|
||||
|
||||
static negToZero(val) {
|
||||
return val < 0 ? 0 : val
|
||||
}
|
||||
|
||||
static moveIndexInArray(arr, old_index, new_index) {
|
||||
if (new_index >= arr.length) {
|
||||
let k = new_index - arr.length + 1
|
||||
while (k--) {
|
||||
arr.push(undefined)
|
||||
}
|
||||
}
|
||||
arr.splice(new_index, 0, arr.splice(old_index, 1)[0])
|
||||
return arr
|
||||
}
|
||||
|
||||
static extractNumber(s) {
|
||||
return parseFloat(s.replace(/[^\d.]*/g, ''))
|
||||
}
|
||||
|
||||
static findAncestor(el, cls) {
|
||||
while ((el = el.parentElement) && !el.classList.contains(cls));
|
||||
return el
|
||||
}
|
||||
|
||||
static setELstyles(el, styles) {
|
||||
for (let key in styles) {
|
||||
if (styles.hasOwnProperty(key)) {
|
||||
el.style.key = styles[key]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static isNumber(value) {
|
||||
return (
|
||||
!isNaN(value) &&
|
||||
parseFloat(Number(value)) === value &&
|
||||
!isNaN(parseInt(value, 10))
|
||||
)
|
||||
}
|
||||
|
||||
static isFloat(n) {
|
||||
return Number(n) === n && n % 1 !== 0
|
||||
}
|
||||
|
||||
static isSafari() {
|
||||
return /^((?!chrome|android).)*safari/i.test(navigator.userAgent)
|
||||
}
|
||||
|
||||
static isFirefox() {
|
||||
return navigator.userAgent.toLowerCase().indexOf('firefox') > -1
|
||||
}
|
||||
|
||||
static isIE11() {
|
||||
if (
|
||||
window.navigator.userAgent.indexOf('MSIE') !== -1 ||
|
||||
window.navigator.appVersion.indexOf('Trident/') > -1
|
||||
) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
static isIE() {
|
||||
let ua = window.navigator.userAgent
|
||||
|
||||
let msie = ua.indexOf('MSIE ')
|
||||
if (msie > 0) {
|
||||
// IE 10 or older => return version number
|
||||
return parseInt(ua.substring(msie + 5, ua.indexOf('.', msie)), 10)
|
||||
}
|
||||
|
||||
let trident = ua.indexOf('Trident/')
|
||||
if (trident > 0) {
|
||||
// IE 11 => return version number
|
||||
let rv = ua.indexOf('rv:')
|
||||
return parseInt(ua.substring(rv + 3, ua.indexOf('.', rv)), 10)
|
||||
}
|
||||
|
||||
let edge = ua.indexOf('Edge/')
|
||||
if (edge > 0) {
|
||||
// Edge (IE 12+) => return version number
|
||||
return parseInt(ua.substring(edge + 5, ua.indexOf('.', edge)), 10)
|
||||
}
|
||||
|
||||
// other browser
|
||||
return false
|
||||
}
|
||||
//
|
||||
// Find the Greatest Common Divisor of two numbers
|
||||
//
|
||||
static getGCD(a, b, p = 7) {
|
||||
let big = Math.pow(10, (p - Math.floor(Math.log10(Math.max(a, b)))))
|
||||
a = Math.round(Math.abs(a) * big)
|
||||
b = Math.round(Math.abs(b) * big)
|
||||
|
||||
while (b) {
|
||||
let t = b
|
||||
b = a % b
|
||||
a = t
|
||||
}
|
||||
return a / big
|
||||
}
|
||||
|
||||
static getPrimeFactors(n) {
|
||||
const factors = []
|
||||
let divisor = 2
|
||||
|
||||
while (n >= 2) {
|
||||
if (n % divisor == 0) {
|
||||
factors.push(divisor)
|
||||
n = n / divisor
|
||||
} else {
|
||||
divisor++
|
||||
}
|
||||
}
|
||||
return factors
|
||||
}
|
||||
|
||||
static mod(a, b, p = 7) {
|
||||
let big = Math.pow(10, (p - Math.floor(Math.log10(Math.max(a, b)))))
|
||||
a = Math.round(Math.abs(a) * big)
|
||||
b = Math.round(Math.abs(b) * big)
|
||||
|
||||
return (a % b) / big
|
||||
}
|
||||
}
|
||||
|
||||
export default Utils
|
||||
Reference in New Issue
Block a user