diff --git a/demos/index.html b/demos/index.html index b1d35fd2..3c63b017 100644 --- a/demos/index.html +++ b/demos/index.html @@ -84,7 +84,7 @@

μPlot Demos

Discrete & shifted series w/sync Maintains location of cursor/select/hoverPts during resize (test) - Russian month names on date/time axis + Override default localization (French Canada) Dynamically add or delete series Sync chart position when inside a scrollable container diff --git a/demos/months-ru.html b/demos/localize-fr-ca.html similarity index 55% rename from demos/months-ru.html rename to demos/localize-fr-ca.html index 621aab7e..22667d83 100644 --- a/demos/months-ru.html +++ b/demos/localize-fr-ca.html @@ -2,7 +2,7 @@ - Months (Russian) + Localize Time & Measure (French Canadian) @@ -23,26 +23,19 @@ }) }); - let vals = [0,1,2,3,4,5,6,7,8,9,10]; + let vals = [1000.1,1100.1,1200.2,1300.3,1400.4,1500.5,1600.6,1700.7,1800.8,1900.9,2000.10]; let data = [ ts, - ts.map((t, i) => i == 0 ? 5 : vals[Math.floor(Math.random() * vals.length)]), + ts.map((t, i) => i == 0 ? 1500 : vals[Math.floor(Math.random() * vals.length)]), ]; - const ruNames = { - MMMM: ["Январь","Февраль","Март","Апрель","Май","Июнь","Июль","Август","Сентябрь","Октябрь","Ноябрь","Декабрь"], - MMM: ["Янв","Февр","Март","Апр","Май","Июнь","Июль","Авг","Сент","Окт","Нояб","Дек"], - WWWW: ["Воскресенье","Понедельник","Вторник","Среда","Четверг","Пятница","Суббота"], - WWW: ["Вск","Пнд","Втр","Срд","Чтв","Птн","Сбт"], - }; - const opts = { width: 1920, height: 600, title: "Months", + locale: 'fr-CA', tzDate: ts => uPlot.tzDate(new Date(ts * 1e3), 'Etc/UTC'), - fmtDate: tpl => uPlot.fmtDate(tpl, ruNames), series: [ {}, { @@ -54,4 +47,4 @@ let u = new uPlot(opts, data, document.body); - \ No newline at end of file + diff --git a/dist/uPlot.cjs.js b/dist/uPlot.cjs.js index a5102e22..f5b04014 100644 --- a/dist/uPlot.cjs.js +++ b/dist/uPlot.cjs.js @@ -11,168 +11,7 @@ const FEAT_TIME = true; -const pre = "u-"; - -const UPLOT = "uplot"; -const ORI_HZ = pre + "hz"; -const ORI_VT = pre + "vt"; -const TITLE = pre + "title"; -const WRAP = pre + "wrap"; -const UNDER = pre + "under"; -const OVER = pre + "over"; -const AXIS = pre + "axis"; -const OFF = pre + "off"; -const SELECT = pre + "select"; -const CURSOR_X = pre + "cursor-x"; -const CURSOR_Y = pre + "cursor-y"; -const CURSOR_PT = pre + "cursor-pt"; -const LEGEND = pre + "legend"; -const LEGEND_LIVE = pre + "live"; -const LEGEND_INLINE = pre + "inline"; -const LEGEND_SERIES = pre + "series"; -const LEGEND_MARKER = pre + "marker"; -const LEGEND_LABEL = pre + "label"; -const LEGEND_VALUE = pre + "value"; - -const WIDTH = "width"; -const HEIGHT = "height"; -const TOP = "top"; -const BOTTOM = "bottom"; -const LEFT = "left"; -const RIGHT = "right"; -const hexBlack = "#000"; -const transparent = hexBlack + "0"; - -const mousemove = "mousemove"; -const mousedown = "mousedown"; -const mouseup = "mouseup"; -const mouseenter = "mouseenter"; -const mouseleave = "mouseleave"; -const dblclick = "dblclick"; -const resize = "resize"; -const scroll = "scroll"; - -const change = "change"; -const dppxchange = "dppxchange"; - -const LEGEND_DISP = "--"; - -const domEnv = typeof window != 'undefined'; - -const doc = domEnv ? document : null; -const win = domEnv ? window : null; -const nav = domEnv ? navigator : null; - -let pxRatio; - -//export const canHover = domEnv && !win.matchMedia('(hover: none)').matches; - -let query; - -function setPxRatio() { - let _pxRatio = devicePixelRatio; - - // during print preview, Chrome fires off these dppx queries even without changes - if (pxRatio != _pxRatio) { - pxRatio = _pxRatio; - - query && off(change, query, setPxRatio); - query = matchMedia(`(min-resolution: ${pxRatio - 0.001}dppx) and (max-resolution: ${pxRatio + 0.001}dppx)`); - on(change, query, setPxRatio); - - win.dispatchEvent(new CustomEvent(dppxchange)); - } -} - -function addClass(el, c) { - if (c != null) { - let cl = el.classList; - !cl.contains(c) && cl.add(c); - } -} - -function remClass(el, c) { - let cl = el.classList; - cl.contains(c) && cl.remove(c); -} - -function setStylePx(el, name, value) { - el.style[name] = value + "px"; -} - -function placeTag(tag, cls, targ, refEl) { - let el = doc.createElement(tag); - - if (cls != null) - addClass(el, cls); - - if (targ != null) - targ.insertBefore(el, refEl); - - return el; -} - -function placeDiv(cls, targ) { - return placeTag("div", cls, targ); -} - -const xformCache = new WeakMap(); - -function elTrans(el, xPos, yPos, xMax, yMax) { - let xform = "translate(" + xPos + "px," + yPos + "px)"; - let xformOld = xformCache.get(el); - - if (xform != xformOld) { - el.style.transform = xform; - xformCache.set(el, xform); - - if (xPos < 0 || yPos < 0 || xPos > xMax || yPos > yMax) - addClass(el, OFF); - else - remClass(el, OFF); - } -} - -const colorCache = new WeakMap(); - -function elColor(el, background, borderColor) { - let newColor = background + borderColor; - let oldColor = colorCache.get(el); - - if (newColor != oldColor) { - colorCache.set(el, newColor); - el.style.background = background; - el.style.borderColor = borderColor; - } -} - -const sizeCache = new WeakMap(); - -function elSize(el, newWid, newHgt, centered) { - let newSize = newWid + "" + newHgt; - let oldSize = sizeCache.get(el); - - if (newSize != oldSize) { - sizeCache.set(el, newSize); - el.style.height = newHgt + "px"; - el.style.width = newWid + "px"; - el.style.marginLeft = centered ? -newWid/2 + "px" : 0; - el.style.marginTop = centered ? -newHgt/2 + "px" : 0; - } -} - -const evOpts = {passive: true}; -const evOpts2 = {...evOpts, capture: true}; - -function on(ev, el, cb, capt) { - el.addEventListener(ev, cb, capt ? evOpts2 : evOpts); -} - -function off(ev, el, cb, capt) { - el.removeEventListener(ev, cb, evOpts); -} - -domEnv && setPxRatio(); +const browserLocale = new Intl.DateTimeFormat().resolvedOptions().locale; // binary search for index of closest value function closestIdx(num, arr, lo, hi) { @@ -431,10 +270,6 @@ function _rangeNum(_min, _max, cfg) { return [minLim, maxLim]; } -// alternative: https://stackoverflow.com/a/2254896 -const numFormatter = new Intl.NumberFormat(domEnv ? nav.language : 'en-US'); -const fmtNum = val => numFormatter.format(val); - const M = Math; const PI = M.PI; @@ -820,130 +655,168 @@ function isAsc(vals, samples = 100) { return true; } -const months = [ - "January", - "February", - "March", - "April", - "May", - "June", - "July", - "August", - "September", - "October", - "November", - "December", -]; - -const days = [ - "Sunday", - "Monday", - "Tuesday", - "Wednesday", - "Thursday", - "Friday", - "Saturday", -]; - -function slice3(str) { - return str.slice(0, 3); +const WIDTH = "width"; +const HEIGHT = "height"; +const TOP = "top"; +const BOTTOM = "bottom"; +const LEFT = "left"; +const RIGHT = "right"; +const hexBlack = "#000"; +const transparent = hexBlack + "0"; + +const mousemove = "mousemove"; +const mousedown = "mousedown"; +const mouseup = "mouseup"; +const mouseenter = "mouseenter"; +const mouseleave = "mouseleave"; +const dblclick = "dblclick"; +const resize = "resize"; +const scroll = "scroll"; + +const change = "change"; +const dppxchange = "dppxchange"; + +const LEGEND_DISP = "--"; + +const pre = "u-"; + +const UPLOT = "uplot"; +const ORI_HZ = pre + "hz"; +const ORI_VT = pre + "vt"; +const TITLE = pre + "title"; +const WRAP = pre + "wrap"; +const UNDER = pre + "under"; +const OVER = pre + "over"; +const AXIS = pre + "axis"; +const OFF = pre + "off"; +const SELECT = pre + "select"; +const CURSOR_X = pre + "cursor-x"; +const CURSOR_Y = pre + "cursor-y"; +const CURSOR_PT = pre + "cursor-pt"; +const LEGEND = pre + "legend"; +const LEGEND_LIVE = pre + "live"; +const LEGEND_INLINE = pre + "inline"; +const LEGEND_SERIES = pre + "series"; +const LEGEND_MARKER = pre + "marker"; +const LEGEND_LABEL = pre + "label"; +const LEGEND_VALUE = pre + "value"; + +const domEnv = typeof window != 'undefined'; + +const doc = domEnv ? document : null; +const win = domEnv ? window : null; + +let pxRatio; + +//export const canHover = domEnv && !win.matchMedia('(hover: none)').matches; + +let query; + +function setPxRatio() { + let _pxRatio = devicePixelRatio; + + // during print preview, Chrome fires off these dppx queries even without changes + if (pxRatio != _pxRatio) { + pxRatio = _pxRatio; + + query && off(change, query, setPxRatio); + query = matchMedia(`(min-resolution: ${pxRatio - 0.001}dppx) and (max-resolution: ${pxRatio + 0.001}dppx)`); + on(change, query, setPxRatio); + + win.dispatchEvent(new CustomEvent(dppxchange)); + } +} + +function addClass(el, c) { + if (c != null) { + let cl = el.classList; + !cl.contains(c) && cl.add(c); + } +} + +function remClass(el, c) { + let cl = el.classList; + cl.contains(c) && cl.remove(c); } -const days3 = days.map(slice3); +function setStylePx(el, name, value) { + el.style[name] = value + "px"; +} -const months3 = months.map(slice3); +function placeTag(tag, cls, targ, refEl) { + let el = doc.createElement(tag); -const engNames = { - MMMM: months, - MMM: months3, - WWWW: days, - WWW: days3, -}; + if (cls != null) + addClass(el, cls); + + if (targ != null) + targ.insertBefore(el, refEl); + + return el; +} + +function placeDiv(cls, targ) { + return placeTag("div", cls, targ); +} -function zeroPad2(int) { - return (int < 10 ? '0' : '') + int; +const xformCache = new WeakMap(); + +function elTrans(el, xPos, yPos, xMax, yMax) { + let xform = "translate(" + xPos + "px," + yPos + "px)"; + let xformOld = xformCache.get(el); + + if (xform != xformOld) { + el.style.transform = xform; + xformCache.set(el, xform); + + if (xPos < 0 || yPos < 0 || xPos > xMax || yPos > yMax) + addClass(el, OFF); + else + remClass(el, OFF); + } } -function zeroPad3(int) { - return (int < 10 ? '00' : int < 100 ? '0' : '') + int; -} +const colorCache = new WeakMap(); -/* -function suffix(int) { - let mod10 = int % 10; +function elColor(el, background, borderColor) { + let newColor = background + borderColor; + let oldColor = colorCache.get(el); - return int + ( - mod10 == 1 && int != 11 ? "st" : - mod10 == 2 && int != 12 ? "nd" : - mod10 == 3 && int != 13 ? "rd" : "th" - ); + if (newColor != oldColor) { + colorCache.set(el, newColor); + el.style.background = background; + el.style.borderColor = borderColor; + } } -*/ -const subs = { - // 2019 - YYYY: d => d.getFullYear(), - // 19 - YY: d => (d.getFullYear()+'').slice(2), - // July - MMMM: (d, names) => names.MMMM[d.getMonth()], - // Jul - MMM: (d, names) => names.MMM[d.getMonth()], - // 07 - MM: d => zeroPad2(d.getMonth()+1), - // 7 - M: d => d.getMonth()+1, - // 09 - DD: d => zeroPad2(d.getDate()), - // 9 - D: d => d.getDate(), - // Monday - WWWW: (d, names) => names.WWWW[d.getDay()], - // Mon - WWW: (d, names) => names.WWW[d.getDay()], - // 03 - HH: d => zeroPad2(d.getHours()), - // 3 - H: d => d.getHours(), - // 9 (12hr, unpadded) - h: d => {let h = d.getHours(); return h == 0 ? 12 : h > 12 ? h - 12 : h;}, - // AM - AA: d => d.getHours() >= 12 ? 'PM' : 'AM', - // am - aa: d => d.getHours() >= 12 ? 'pm' : 'am', - // a - a: d => d.getHours() >= 12 ? 'p' : 'a', - // 09 - mm: d => zeroPad2(d.getMinutes()), - // 9 - m: d => d.getMinutes(), - // 09 - ss: d => zeroPad2(d.getSeconds()), - // 9 - s: d => d.getSeconds(), - // 374 - fff: d => zeroPad3(d.getMilliseconds()), -}; - -function fmtDate(tpl, names) { - names = names || engNames; - let parts = []; +const sizeCache = new WeakMap(); - let R = /\{([a-z]+)\}|[^{]+/gi, m; +function elSize(el, newWid, newHgt, centered) { + let newSize = newWid + "" + newHgt; + let oldSize = sizeCache.get(el); - while (m = R.exec(tpl)) - parts.push(m[0][0] == '{' ? subs[m[1]] : m[0]); + if (newSize != oldSize) { + sizeCache.set(el, newSize); + el.style.height = newHgt + "px"; + el.style.width = newWid + "px"; + el.style.marginLeft = centered ? -newWid/2 + "px" : 0; + el.style.marginTop = centered ? -newHgt/2 + "px" : 0; + } +} - return d => { - let out = ''; +const evOpts = {passive: true}; +const evOpts2 = {...evOpts, capture: true}; - for (let i = 0; i < parts.length; i++) - out += typeof parts[i] == "string" ? parts[i] : parts[i](d, names); +function on(ev, el, cb, capt) { + el.addEventListener(ev, cb, capt ? evOpts2 : evOpts); +} - return out; - } +function off(ev, el, cb, capt) { + el.removeEventListener(ev, cb, evOpts); } +domEnv && setPxRatio(); + const localTz = new Intl.DateTimeFormat().resolvedOptions().timeZone; // https://stackoverflow.com/questions/15141762/how-to-initialize-a-javascript-date-to-a-particular-time-zone/53652131#53652131 @@ -984,17 +857,14 @@ const numIncrs = decIncrs.concat(oneIncrs); const NL = "\n"; -const yyyy = "{YYYY}"; -const NLyyyy = NL + yyyy; -const md = "{M}/{D}"; -const NLmd = NL + md; -const NLmdyy = NLmd + "/{YY}"; - -const aa = "{aa}"; -const hmm = "{h}:{mm}"; -const hmmaa = hmm + aa; -const NLhmmaa = NL + hmmaa; -const ss = ":{ss}"; +let YYYY = {year: 'numeric'}; +let MM = {month: 'numeric'}; +let MMM = {month: 'short'}; +let dd = {day: 'numeric'}; +let hh = {hour: 'numeric'}; +let mm = {minute: 'numeric'}; +let ss = {second: 'numeric'}; +let fff = { fractionalSecondDigits: 3}; const _ = null; @@ -1061,18 +931,18 @@ function genTimeStuffs(ms) { // [0]: minimum num secs in the tick incr // [1]: default tick format // [2-7]: rollover tick formats - // [8]: mode: 0: replace [1] -> [2-7], 1: concat [1] + [2-7] + // [8]: mode: 0: replace [1] -> [2-7], 1: merge [2-7] + \n + [1] const _timeAxisStamps = [ - // tick incr default year month day hour min sec mode - [y, yyyy, _, _, _, _, _, _, 1], - [d * 28, "{MMM}", NLyyyy, _, _, _, _, _, 1], - [d, md, NLyyyy, _, _, _, _, _, 1], - [h, "{h}" + aa, NLmdyy, _, NLmd, _, _, _, 1], - [m, hmmaa, NLmdyy, _, NLmd, _, _, _, 1], - [s, ss, NLmdyy + " " + hmmaa, _, NLmd + " " + hmmaa, _, NLhmmaa, _, 1], - [ms, ss + ".{fff}", NLmdyy + " " + hmmaa, _, NLmd + " " + hmmaa, _, NLhmmaa, _, 1], + // tick incr default year month day hour min sec mode + [y, { ...YYYY }, _, _, _, _, _, _, 1], + [d * 28, { ...MMM }, {...YYYY}, _, _, _, _, _, 1], + [d, { ...MM, ...dd }, {...YYYY}, _, _, _, _, _, 1], + [h, { ...hh }, { ...YYYY, ...MM, ...dd}, _, {...MM, ...dd}, _, _, _, 1], + [m, { ...hh, ...mm }, { ...YYYY, ...MM, ...dd}, _, {...MM, ...dd}, _, _, _, 1], + [s, { ...ss }, { ...YYYY, ...MM, ...dd, ...hh, ...mm}, _, {...MM, ...dd, ...hh, ...mm}, _, {...hh, ...mm}, _, 1], + [ms, { ...ss, ...fff }, { ...YYYY, ...MM, ...dd, ...hh, ...mm}, _, {...MM, ...dd, ...hh, ...mm}, _, {...hh, ...mm}, _, 1], ]; - + // the ensures that axis ticks, values & grid are aligned to logical temporal breakpoints and not an arbitrary timestamp // https://www.timeanddate.com/time/dst/ // https://www.timeanddate.com/time/dst/2019.html @@ -1185,8 +1055,18 @@ console.log({ */ function timeAxisStamps(stampCfg, fmtDate) { - return stampCfg.map(s => s.map((v, i) => - i == 0 || i == 8 || v == null ? v : fmtDate(i == 1 || s[8] == 0 ? v : s[1] + v) + return stampCfg.map(s => s.map((v, i) => { + if (i == 0 || i == 8 || v == null) { + return v + } + const line1 = fmtDate(v); + if (i == 1 || s[8] == 0) { + return line1 + } else { + const line2 = fmtDate(s[1]); + return (date) => line2(date)+NL+line1(date) + } + } )); } @@ -1236,12 +1116,6 @@ function timeAxisVals(tzDate, stamps) { } } -// for when axis.values is defined as a static fmtDate template string -function timeAxisVal(tzDate, dateTpl) { - let stamp = fmtDate(dateTpl); - return (self, splits, axisIdx, foundSpace, foundIncr) => splits.map(split => stamp(tzDate(split))); -} - function mkDate(y, m, d) { return new Date(y, m, d); } @@ -1249,7 +1123,7 @@ function mkDate(y, m, d) { function timeSeriesStamp(stampCfg, fmtDate) { return fmtDate(stampCfg); } -const _timeSeriesStamp = '{YYYY}-{MM}-{DD} {h}:{mm}{aa}'; +const _timeSeriesStamp = { ...YYYY, ...MM, ...dd, ...hh, ...mm }; function timeSeriesVal(tzDate, stamp) { return (self, val, seriesIdx, dataIdx) => dataIdx == null ? LEGEND_DISP : stamp(tzDate(val)); @@ -1460,7 +1334,7 @@ const xSeriesOpts = { idxs: [], }; -function numAxisVals(self, splits, axisIdx, foundSpace, foundIncr) { +function numAxisVals(self, splits, axisIdx, foundSpace, foundIncr, fmtNum) { return splits.map(v => v == null ? "" : fmtNum(v)); } @@ -1583,7 +1457,7 @@ function log2AxisValsFilt(self, splits, axisIdx, foundSpace, foundIncr) { return splits; } -function numSeriesVal(self, val, seriesIdx, dataIdx) { +function numSeriesVal(self, val, seriesIdx, dataIdx, fmtNum) { return dataIdx == null ? LEGEND_DISP : val == null ? "" : fmtNum(val); } @@ -2766,14 +2640,15 @@ function _monotoneCubic(xs, ys, moveTo, lineTo, bezierCurveTo, pxRound) { const cursorPlots = new Set(); function invalidateRects() { - for (let u of cursorPlots) - u.syncRect(true); + for (let u of cursorPlots) u.syncRect(true); } if (domEnv) { on(resize, win, invalidateRects); on(scroll, win, invalidateRects, true); - on(dppxchange, win, () => { uPlot.pxRatio = pxRatio; }); + on(dppxchange, win, () => { + uPlot.pxRatio = pxRatio; + }); } const linearPath = linear() ; @@ -2781,19 +2656,19 @@ const pointsPath = points() ; function setDefaults(d, xo, yo, initY) { let d2 = initY ? [d[0], d[1]].concat(d.slice(2)) : [d[0]].concat(d.slice(1)); - return d2.map((o, i) => setDefault(o, i, xo, yo)); + return d2.map((o, i) => setDefault(o, i, xo, yo)) } function setDefaults2(d, xyo) { - return d.map((o, i) => i == 0 ? {} : assign({}, xyo, o)); // todo: assign() will not merge facet arrays + return d.map((o, i) => (i == 0 ? {} : assign({}, xyo, o))) // todo: assign() will not merge facet arrays } function setDefault(o, i, xo, yo) { - return assign({}, (i == 0 ? xo : yo), o); + return assign({}, i == 0 ? xo : yo, o) } function snapNumX(self, dataMin, dataMax) { - return dataMin == null ? nullNullTuple : [dataMin, dataMax]; + return dataMin == null ? nullNullTuple : [dataMin, dataMax] } const snapTimeX = snapNumX; @@ -2801,17 +2676,23 @@ const snapTimeX = snapNumX; // this ensures that non-temporal/numeric y-axes get multiple-snapped padding added above/below // TODO: also account for incrs when snapping to ensure top of axis gets a tick & value function snapNumY(self, dataMin, dataMax) { - return dataMin == null ? nullNullTuple : rangeNum(dataMin, dataMax, rangePad, true); + return dataMin == null + ? nullNullTuple + : rangeNum(dataMin, dataMax, rangePad, true) } function snapLogY(self, dataMin, dataMax, scale) { - return dataMin == null ? nullNullTuple : rangeLog(dataMin, dataMax, self.scales[scale].log, false); + return dataMin == null + ? nullNullTuple + : rangeLog(dataMin, dataMax, self.scales[scale].log, false) } const snapLogX = snapLogY; function snapAsinhY(self, dataMin, dataMax, scale) { - return dataMin == null ? nullNullTuple : rangeAsinh(dataMin, dataMax, self.scales[scale].log, false); + return dataMin == null + ? nullNullTuple + : rangeAsinh(dataMin, dataMax, self.scales[scale].log, false) } const snapAsinhX = snapAsinhY; @@ -2826,24 +2707,30 @@ function findIncr(minVal, maxVal, incrs, dim, minSpace) { do { let foundIncr = incrs[incrIdx]; - let foundSpace = dim * foundIncr / delta; + let foundSpace = (dim * foundIncr) / delta; - if (foundSpace >= minSpace && intDigits + (foundIncr < 5 ? fixedDec.get(foundIncr) : 0) <= 17) - return [foundIncr, foundSpace]; - } while (++incrIdx < incrs.length); + if ( + foundSpace >= minSpace && + intDigits + (foundIncr < 5 ? fixedDec.get(foundIncr) : 0) <= 17 + ) + return [foundIncr, foundSpace] + } while (++incrIdx < incrs.length) - return [0, 0]; + return [0, 0] } function pxRatioFont(font) { let fontSize, fontSizeCss; - font = font.replace(/(\d+)px/, (m, p1) => (fontSize = round((fontSizeCss = +p1) * pxRatio)) + 'px'); - return [font, fontSize, fontSizeCss]; + font = font.replace( + /(\d+)px/, + (m, p1) => (fontSize = round((fontSizeCss = +p1) * pxRatio)) + 'px' + ); + return [font, fontSize, fontSizeCss] } function syncFontSize(axis) { if (axis.show) { - [axis.font, axis.labelFont].forEach(f => { +[axis.font, axis.labelFont].forEach((f) => { let size = roundDec(f[2] * pxRatio, 1); f[0] = f[0].replace(/[0-9.]+px/, size + 'px'); f[1] = size; @@ -2853,35 +2740,62 @@ function syncFontSize(axis) { function uPlot(opts, data, then) { const self = { - mode: ifNull(opts.mode, 1), + mode: ifNull(opts.mode, 1) }; const mode = self.mode; + const numFormatter = new Intl.NumberFormat(opts.locale || browserLocale); + const fmtNum = (val) => numFormatter.format(val); + self.fmtNum = fmtNum; + + const fmtDate = (tsOpts) => { + tsOpts.hourCycle = opts.hourCycle; + return new Intl.DateTimeFormat(opts.locale || browserLocale, tsOpts) + .format + }; + { + self.fmtDate = fmtDate; + } + // TODO: cache denoms & mins scale.cache = {r, min, } function getValPct(val, scale) { - let _val = ( - scale.distr == 3 ? log10(val > 0 ? val : scale.clamp(self, val, scale.min, scale.max, scale.key)) : - scale.distr == 4 ? asinh(val, scale.asinh) : - scale.distr == 100 ? scale.fwd(val) : - val - ); - - return (_val - scale._min) / (scale._max - scale._min); + let _val = + scale.distr == 3 + ? log10( + val > 0 + ? val + : scale.clamp( + self, + val, + scale.min, + scale.max, + scale.key + ) + ) + : scale.distr == 4 + ? asinh(val, scale.asinh) + : scale.distr == 100 + ? scale.fwd(val) + : val; + + return (_val - scale._min) / (scale._max - scale._min) } function getHPos(val, scale, dim, off) { let pct = getValPct(val, scale); - return off + dim * (scale.dir == -1 ? (1 - pct) : pct); + return off + dim * (scale.dir == -1 ? 1 - pct : pct) } function getVPos(val, scale, dim, off) { let pct = getValPct(val, scale); - return off + dim * (scale.dir == -1 ? pct : (1 - pct)); + return off + dim * (scale.dir == -1 ? pct : 1 - pct) } function getPos(val, scale, dim, off) { - return scale.ori == 0 ? getHPos(val, scale, dim, off) : getVPos(val, scale, dim, off); + return scale.ori == 0 + ? getHPos(val, scale, dim, off) + : getVPos(val, scale, dim, off) } self.valToPosH = getHPos; @@ -2890,10 +2804,9 @@ function uPlot(opts, data, then) { let ready = false; self.status = 0; - const root = self.root = placeDiv(UPLOT); + const root = (self.root = placeDiv(UPLOT)); - if (opts.id != null) - root.id = opts.id; + if (opts.id != null) root.id = opts.id; addClass(root, opts.class); @@ -2902,43 +2815,53 @@ function uPlot(opts, data, then) { title.textContent = opts.title; } - const can = placeTag("canvas"); - const ctx = self.ctx = can.getContext("2d"); + const can = placeTag('canvas'); + const ctx = (self.ctx = can.getContext('2d')); const wrap = placeDiv(WRAP, root); - on("click", wrap, e => { - if (e.target === over) { - let didDrag = mouseLeft1 != mouseLeft0 || mouseTop1 != mouseTop0; - didDrag && drag.click(self, e); - } - }, true); + on( + 'click', + wrap, + (e) => { + if (e.target === over) { + let didDrag = mouseLeft1 != mouseLeft0 || mouseTop1 != mouseTop0; + didDrag && drag.click(self, e); + } + }, + true + ); - const under = self.under = placeDiv(UNDER, wrap); + const under = (self.under = placeDiv(UNDER, wrap)); wrap.appendChild(can); - const over = self.over = placeDiv(OVER, wrap); + const over = (self.over = placeDiv(OVER, wrap)); opts = copy(opts); const pxAlign = +ifNull(opts.pxAlign, 1); - const pxRound = pxRoundGen(pxAlign); + const pxRound = pxRoundGen(pxAlign) - (opts.plugins || []).forEach(p => { - if (p.opts) - opts = p.opts(self, opts) || opts; + ;(opts.plugins || []).forEach((p) => { + if (p.opts) opts = p.opts(self, opts) || opts; }); const ms = opts.ms || 1e-3; - const series = self.series = mode == 1 ? - setDefaults(opts.series || [], xSeriesOpts, ySeriesOpts, false) : - setDefaults2(opts.series || [null], xySeriesOpts); - const axes = self.axes = setDefaults(opts.axes || [], xAxisOpts, yAxisOpts, true); - const scales = self.scales = {}; - const bands = self.bands = opts.bands || []; + const series = (self.series = + mode == 1 + ? setDefaults(opts.series || [], xSeriesOpts, ySeriesOpts, false) + : setDefaults2(opts.series || [null], xySeriesOpts)); + const axes = (self.axes = setDefaults( + opts.axes || [], + xAxisOpts, + yAxisOpts, + true + )); + const scales = (self.scales = {}); + const bands = (self.bands = opts.bands || []); - bands.forEach(b => { + bands.forEach((b) => { b.fill = fnOrSelf(b.fill || null); b.dir = ifNull(b.dir, -1); }); @@ -2947,10 +2870,12 @@ function uPlot(opts, data, then) { const drawOrderMap = { axes: drawAxesGrid, - series: drawSeries, + series: drawSeries }; - const drawOrder = (opts.drawOrder || ["axes", "series"]).map(key => drawOrderMap[key]); + const drawOrder = (opts.drawOrder || ['axes', 'series']).map( + (key) => drawOrderMap[key] + ); function initScale(scaleKey) { let sc = scales[scaleKey]; @@ -2962,10 +2887,18 @@ function uPlot(opts, data, then) { // ensure parent is initialized initScale(scaleOpts.from); // dependent scales inherit - scales[scaleKey] = assign({}, scales[scaleOpts.from], scaleOpts, {key: scaleKey}); - } - else { - sc = scales[scaleKey] = assign({}, (scaleKey == xScaleKey ? xScaleOpts : yScaleOpts), scaleOpts); + scales[scaleKey] = assign( + {}, + scales[scaleOpts.from], + scaleOpts, + { key: scaleKey } + ); + } else { + sc = scales[scaleKey] = assign( + {}, + scaleKey == xScaleKey ? xScaleOpts : yScaleOpts, + scaleOpts + ); sc.key = scaleKey; @@ -2979,16 +2912,22 @@ function uPlot(opts, data, then) { // if range array has null limits, it should be auto if (rangeIsArr && (rn[0] == null || rn[1] == null)) { rn = { - min: rn[0] == null ? autoRangePart : { - mode: 1, - hard: rn[0], - soft: rn[0], - }, - max: rn[1] == null ? autoRangePart : { - mode: 1, - hard: rn[1], - soft: rn[1], - }, + min: + rn[0] == null + ? autoRangePart + : { + mode: 1, + hard: rn[0], + soft: rn[0] + }, + max: + rn[1] == null + ? autoRangePart + : { + mode: 1, + hard: rn[1], + soft: rn[1] + } }; rangeIsArr = false; } @@ -2996,14 +2935,29 @@ function uPlot(opts, data, then) { if (!rangeIsArr && isObj(rn)) { let cfg = rn; // this is similar to snapNumY - rn = (self, dataMin, dataMax) => dataMin == null ? nullNullTuple : rangeNum(dataMin, dataMax, cfg); + rn = (self, dataMin, dataMax) => + dataMin == null + ? nullNullTuple + : rangeNum(dataMin, dataMax, cfg); } } - sc.range = fnOrSelf(rn || (isTime ? snapTimeX : scaleKey == xScaleKey ? - (sc.distr == 3 ? snapLogX : sc.distr == 4 ? snapAsinhX : snapNumX) : - (sc.distr == 3 ? snapLogY : sc.distr == 4 ? snapAsinhY : snapNumY) - )); + sc.range = fnOrSelf( + rn || + (isTime + ? snapTimeX + : scaleKey == xScaleKey + ? sc.distr == 3 + ? snapLogX + : sc.distr == 4 + ? snapAsinhX + : snapNumX + : sc.distr == 3 + ? snapLogY + : sc.distr == 4 + ? snapAsinhY + : snapNumY) + ); sc.auto = fnOrSelf(rangeIsArr ? false : sc.auto); @@ -3015,28 +2969,28 @@ function uPlot(opts, data, then) { } } - initScale("x"); - initScale("y"); + initScale('x'); + initScale('y'); // TODO: init scales from facets in mode: 2 if (mode == 1) { - series.forEach(s => { + series.forEach((s) => { initScale(s.scale); }); } - axes.forEach(a => { + axes.forEach((a) => { initScale(a.scale); }); - for (let k in opts.scales) - initScale(k); + for (let k in opts.scales) initScale(k); const scaleX = scales[xScaleKey]; const xScaleDistr = scaleX.distr; - let valToPosX, valToPosY; + let valToPosX, + valToPosY; if (scaleX.ori == 0) { addClass(root, ORI_HZ); @@ -3055,8 +3009,7 @@ function uPlot(opts, data, then) { yOffCss = plotTopCss; }; */ - } - else { + } else { addClass(root, ORI_VT); valToPosX = getVPos; valToPosY = getHPos; @@ -3082,32 +3035,43 @@ function uPlot(opts, data, then) { let sc = scales[k]; if (sc.min != null || sc.max != null) { - pendScales[k] = {min: sc.min, max: sc.max}; + pendScales[k] = { min: sc.min, max: sc.max }; sc.min = sc.max = null; } } -// self.tz = opts.tz || Intl.DateTimeFormat().resolvedOptions().timeZone; - const _tzDate = (opts.tzDate || (ts => new Date(round(ts / ms)))); + // self.tz = opts.tz || Intl.DateTimeFormat().resolvedOptions().timeZone; + const _tzDate = + (opts.tzDate || ((ts) => new Date(round(ts / ms)))); const _fmtDate = (opts.fmtDate || fmtDate); - const _timeAxisSplits = (ms == 1 ? timeAxisSplitsMs(_tzDate) : timeAxisSplitsS(_tzDate)); - const _timeAxisVals = timeAxisVals(_tzDate, timeAxisStamps((ms == 1 ? _timeAxisStampsMs : _timeAxisStampsS), _fmtDate)); - const _timeSeriesVal = timeSeriesVal(_tzDate, timeSeriesStamp(_timeSeriesStamp, _fmtDate)); + const _timeAxisSplits = + (ms == 1 ? timeAxisSplitsMs(_tzDate) : timeAxisSplitsS(_tzDate)); + const _timeAxisVals = + timeAxisVals( + _tzDate, + timeAxisStamps( + ms == 1 ? _timeAxisStampsMs : _timeAxisStampsS, + _fmtDate + ) + ); + const _timeSeriesVal = + timeSeriesVal(_tzDate, timeSeriesStamp(_timeSeriesStamp, _fmtDate)); const activeIdxs = []; - const legend = (self.legend = assign({}, legendOpts, opts.legend)); + const legend = + (self.legend = assign({}, legendOpts, opts.legend)); const showLegend = legend.show; - const markers = legend.markers; + const markers = legend.markers; { legend.idxs = activeIdxs; - markers.width = fnOrSelf(markers.width); - markers.dash = fnOrSelf(markers.dash); + markers.width = fnOrSelf(markers.width); + markers.dash = fnOrSelf(markers.dash); markers.stroke = fnOrSelf(markers.stroke); - markers.fill = fnOrSelf(markers.fill); + markers.fill = fnOrSelf(markers.fill); } let legendTable; @@ -3122,60 +3086,67 @@ function uPlot(opts, data, then) { if (legend.live) { const getMultiVals = series[1] ? series[1].values : null; multiValLegend = getMultiVals != null; - legendCols = multiValLegend ? getMultiVals(self, 1, 0) : {_: 0}; + legendCols = multiValLegend ? getMultiVals(self, 1, 0) : { _: 0 }; - for (let k in legendCols) - NULL_LEGEND_VALUES[k] = LEGEND_DISP; + for (let k in legendCols) NULL_LEGEND_VALUES[k] = LEGEND_DISP; } if (showLegend) { - legendTable = placeTag("table", LEGEND, root); - legendBody = placeTag("tbody", null, legendTable); + legendTable = placeTag('table', LEGEND, root); + legendBody = placeTag('tbody', null, legendTable); // allows legend to be moved out of root legend.mount(self, legendTable); if (multiValLegend) { - legendHead = placeTag("thead", null, legendTable, legendBody); + legendHead = placeTag('thead', null, legendTable, legendBody); - let head = placeTag("tr", null, legendHead); - placeTag("th", null, head); + let head = placeTag('tr', null, legendHead); + placeTag('th', null, head); for (var key in legendCols) - placeTag("th", LEGEND_LABEL, head).textContent = key; - } - else { + placeTag('th', LEGEND_LABEL, head).textContent = key; + } else { addClass(legendTable, LEGEND_INLINE); legend.live && addClass(legendTable, LEGEND_LIVE); } } - const son = {show: true}; - const soff = {show: false}; + const son = { show: true }; + const soff = { show: false }; function initLegendRow(s, i) { if (i == 0 && (multiValLegend || !legend.live || mode == 2)) - return nullNullTuple; + return nullNullTuple let cells = []; - let row = placeTag("tr", LEGEND_SERIES, legendBody, legendBody.childNodes[i]); + let row = placeTag( + 'tr', + LEGEND_SERIES, + legendBody, + legendBody.childNodes[i] + ); addClass(row, s.class); - if (!s.show) - addClass(row, OFF); + if (!s.show) addClass(row, OFF); - let label = placeTag("th", null, row); + let label = placeTag('th', null, row); if (markers.show) { let indic = placeDiv(LEGEND_MARKER, label); if (i > 0) { - let width = markers.width(self, i); + let width = markers.width(self, i); if (width) - indic.style.border = width + "px " + markers.dash(self, i) + " " + markers.stroke(self, i); + indic.style.border = + width + + 'px ' + + markers.dash(self, i) + + ' ' + + markers.stroke(self, i); indic.style.background = markers.fill(self, i); } @@ -3186,47 +3157,79 @@ function uPlot(opts, data, then) { if (i > 0) { if (!markers.show) - text.style.color = s.width > 0 ? markers.stroke(self, i) : markers.fill(self, i); + text.style.color = + s.width > 0 + ? markers.stroke(self, i) + : markers.fill(self, i); - onMouse("click", label, e => { - if (cursor._lock) - return; + onMouse( + 'click', + label, + (e) => { + if (cursor._lock) return - setCursorEvent(e); + setCursorEvent(e); - let seriesIdx = series.indexOf(s); + let seriesIdx = series.indexOf(s); - if ((e.ctrlKey || e.metaKey) != legend.isolate) { - // if any other series is shown, isolate this one. else show all - let isolate = series.some((s, i) => i > 0 && i != seriesIdx && s.show); + if ((e.ctrlKey || e.metaKey) != legend.isolate) { + // if any other series is shown, isolate this one. else show all + let isolate = series.some( + (s, i) => i > 0 && i != seriesIdx && s.show + ); - series.forEach((s, i) => { - i > 0 && setSeries(i, isolate ? (i == seriesIdx ? son : soff) : son, true, syncOpts.setSeries); - }); - } - else - setSeries(seriesIdx, {show: !s.show}, true, syncOpts.setSeries); - }, false); + series.forEach((s, i) => { + i > 0 && + setSeries( + i, + isolate + ? i == seriesIdx + ? son + : soff + : son, + true, + syncOpts.setSeries + ); + }); + } else + setSeries( + seriesIdx, + { show: !s.show }, + true, + syncOpts.setSeries + ); + }, + false + ); if (cursorFocus) { - onMouse(mouseenter, label, e => { - if (cursor._lock) - return; - - setCursorEvent(e); - - setSeries(series.indexOf(s), FOCUS_TRUE, true, syncOpts.setSeries); - }, false); + onMouse( + mouseenter, + label, + (e) => { + if (cursor._lock) return + + setCursorEvent(e); + + setSeries( + series.indexOf(s), + FOCUS_TRUE, + true, + syncOpts.setSeries + ); + }, + false + ); } } for (var key in legendCols) { - let v = placeTag("td", LEGEND_VALUE, row); - v.textContent = "--"; + let v = placeTag('td', LEGEND_VALUE, row); + v.textContent = '--'; cells.push(v); } - return [row, cells]; + return [row, cells] } const mouseListeners = new Map(); @@ -3236,7 +3239,7 @@ function uPlot(opts, data, then) { const listener = cursor.bind[ev](self, targ, fn, onlyTarg); if (listener) { - on(ev, targ, targListeners[ev] = listener); + on(ev, targ, (targListeners[ev] = listener)); mouseListeners.set(targ, targListeners); } } @@ -3251,8 +3254,7 @@ function uPlot(opts, data, then) { } } - if (ev == null) - mouseListeners.delete(targ); + if (ev == null) mouseListeners.delete(targ); } let fullWidCss = 0; @@ -3271,7 +3273,6 @@ function uPlot(opts, data, then) { let _plotWidCss = plotWidCss; let _plotHgtCss = plotHgtCss; - let plotLft = 0; let plotTop = 0; let plotWid = 0; @@ -3287,7 +3288,7 @@ function uPlot(opts, data, then) { let shouldSetLegend = false; function _setSize(width, height, force) { - if (force || (width != self.width || height != self.height)) + if (force || width != self.width || height != self.height) calcSize(width, height); resetYSeries(false); @@ -3299,23 +3300,23 @@ function uPlot(opts, data, then) { } function calcSize(width, height) { - // log("calcSize()", arguments); + // log("calcSize()", arguments); - self.width = fullWidCss = plotWidCss = width; + self.width = fullWidCss = plotWidCss = width; self.height = fullHgtCss = plotHgtCss = height; - plotLftCss = plotTopCss = 0; + plotLftCss = plotTopCss = 0; calcPlotRect(); calcAxesRects(); let bb = self.bbox; - plotLft = bb.left = incrRound(plotLftCss * pxRatio, 0.5); - plotTop = bb.top = incrRound(plotTopCss * pxRatio, 0.5); - plotWid = bb.width = incrRound(plotWidCss * pxRatio, 0.5); + plotLft = bb.left = incrRound(plotLftCss * pxRatio, 0.5); + plotTop = bb.top = incrRound(plotTopCss * pxRatio, 0.5); + plotWid = bb.width = incrRound(plotWidCss * pxRatio, 0.5); plotHgt = bb.height = incrRound(plotHgtCss * pxRatio, 0.5); - // updOriDims(); + // updOriDims(); } // ensures size calc convergence @@ -3332,7 +3333,8 @@ function uPlot(opts, data, then) { let axesConverged = axesCalc(cycleNum); let paddingConverged = paddingCalc(cycleNum); - converged = cycleNum == CYCLE_LIMIT || (axesConverged && paddingConverged); + converged = + cycleNum == CYCLE_LIMIT || (axesConverged && paddingConverged); if (!converged) { calcSize(self.width, self.height); @@ -3341,7 +3343,7 @@ function uPlot(opts, data, then) { } } - function setSize({width, height}) { + function setSize({ width, height }) { _setSize(width, height); } @@ -3357,7 +3359,7 @@ function uPlot(opts, data, then) { axes.forEach((axis, i) => { if (axis.show && axis._show) { - let {side, _size} = axis; + let { side, _size } = axis; let isVt = side % 2; let labelSize = axis.label != null ? axis.labelSize : 0; @@ -3370,19 +3372,14 @@ function uPlot(opts, data, then) { if (side == 3) { plotLftCss += fullSize; hasLftAxis = true; - } - else - hasRgtAxis = true; - } - else { + } else hasRgtAxis = true; + } else { plotHgtCss -= fullSize; if (side == 0) { plotTopCss += fullSize; hasTopAxis = true; - } - else - hasBtmAxis = true; + } else hasBtmAxis = true; } } } @@ -3412,10 +3409,18 @@ function uPlot(opts, data, then) { function incrOffset(side, size) { switch (side) { - case 1: off1 += size; return off1 - size; - case 2: off2 += size; return off2 - size; - case 3: off3 -= size; return off3 + size; - case 0: off0 -= size; return off0 + size; + case 1: + off1 += size; + return off1 - size + case 2: + off2 += size; + return off2 - size + case 3: + off3 -= size; + return off3 + size + case 0: + off0 -= size; + return off0 + size } } @@ -3431,20 +3436,24 @@ function uPlot(opts, data, then) { }); } - const cursor = self.cursor = assign({}, cursorOpts, {drag: {y: mode == 2}}, opts.cursor); + const cursor = (self.cursor = assign( + {}, + cursorOpts, + { drag: { y: mode == 2 } }, + opts.cursor + )); if (cursor.dataIdx == null) { let hov = cursor.hover; - let skip = hov.skip = new Set(hov.skip ?? []); + let skip = (hov.skip = new Set(hov.skip ?? [])); skip.add(void 0); // alignment artifacts - let prox = hov.prox = fnOrSelf(hov.prox); - let bias = hov.bias ??= 0; + let prox = (hov.prox = fnOrSelf(hov.prox)); + let bias = (hov.bias ??= 0); // TODO: only scan between in-view idxs (i0, i1) cursor.dataIdx = (self, seriesIdx, cursorIdx, valAtPosX) => { - if (seriesIdx == 0) - return cursorIdx; + if (seriesIdx == 0) return cursorIdx let idx2 = cursorIdx; @@ -3466,55 +3475,73 @@ function uPlot(opts, data, then) { if (bias == 0 || bias == -1) { j = cursorIdx; while (nonNullLft == null && j-- > 0) { - if (!skip.has(yValues[j])) - nonNullLft = j; + if (!skip.has(yValues[j])) nonNullLft = j; } } if (bias == 0 || bias == 1) { j = cursorIdx; while (nonNullRgt == null && j++ < yValues.length) { - if (!skip.has(yValues[j])) - nonNullRgt = j; + if (!skip.has(yValues[j])) nonNullRgt = j; } } if (nonNullLft != null || nonNullRgt != null) { if (withProx) { - let lftPos = nonNullLft == null ? -Infinity : valToPosX(xValues[nonNullLft], scaleX, xDim, 0); - let rgtPos = nonNullRgt == null ? Infinity : valToPosX(xValues[nonNullRgt], scaleX, xDim, 0); + let lftPos = + nonNullLft == null + ? -Infinity + : valToPosX( + xValues[nonNullLft], + scaleX, + xDim, + 0 + ); + let rgtPos = + nonNullRgt == null + ? Infinity + : valToPosX( + xValues[nonNullRgt], + scaleX, + xDim, + 0 + ); let lftDelta = cursorLft - lftPos; let rgtDelta = rgtPos - cursorLft; if (lftDelta <= rgtDelta) { - if (lftDelta <= _prox) - idx2 = nonNullLft; + if (lftDelta <= _prox) idx2 = nonNullLft; } else { - if (rgtDelta <= _prox) - idx2 = nonNullRgt; + if (rgtDelta <= _prox) idx2 = nonNullRgt; } - } - else { + } else { idx2 = - nonNullRgt == null ? nonNullLft : - nonNullLft == null ? nonNullRgt : - cursorIdx - nonNullLft <= nonNullRgt - cursorIdx ? nonNullLft : nonNullRgt; + nonNullRgt == null + ? nonNullLft + : nonNullLft == null + ? nonNullRgt + : cursorIdx - nonNullLft <= + nonNullRgt - cursorIdx + ? nonNullLft + : nonNullRgt; } } - } - else if (withProx) { - let dist = abs(cursorLft - valToPosX(xValues[cursorIdx], scaleX, xDim, 0)); + } else if (withProx) { + let dist = abs( + cursorLft - valToPosX(xValues[cursorIdx], scaleX, xDim, 0) + ); - if (dist > _prox) - idx2 = null; + if (dist > _prox) idx2 = null; } - return idx2; + return idx2 }; } - const setCursorEvent = e => { cursor.event = e; }; + const setCursorEvent = (e) => { + cursor.event = e; + }; cursor.idxs = activeIdxs; @@ -3522,13 +3549,17 @@ function uPlot(opts, data, then) { let points = cursor.points; - points.show = fnOrSelf(points.show); - points.size = fnOrSelf(points.size); + points.show = fnOrSelf(points.show); + points.size = fnOrSelf(points.size); points.stroke = fnOrSelf(points.stroke); - points.width = fnOrSelf(points.width); - points.fill = fnOrSelf(points.fill); + points.width = fnOrSelf(points.width); + points.fill = fnOrSelf(points.fill); - const focus = self.focus = assign({}, opts.focus || {alpha: 0.3}, cursor.focus); + const focus = (self.focus = assign( + {}, + opts.focus || { alpha: 0.3 }, + cursor.focus + )); const cursorFocus = focus.prox >= 0; const cursorOnePt = cursorFocus && points.one; @@ -3548,7 +3579,7 @@ function uPlot(opts, data, then) { elTrans(pt, -10, -10, plotWidCss, plotHgtCss); over.insertBefore(pt, cursorPts[si]); - return pt; + return pt } } @@ -3557,36 +3588,44 @@ function uPlot(opts, data, then) { let isTime = mode == 1 && scales[s.scale].time; let sv = s.value; - s.value = isTime ? (isStr(sv) ? timeSeriesVal(_tzDate, timeSeriesStamp(sv, _fmtDate)) : sv || _timeSeriesVal) : sv || numSeriesVal; + s.value = isTime + ? isStr(sv) + ? timeSeriesVal(_tzDate, timeSeriesStamp(sv, _fmtDate)) + : sv || _timeSeriesVal + : sv || numSeriesVal; s.label = s.label || (isTime ? timeSeriesLabel : numSeriesLabel); } if (cursorOnePt || i > 0) { - s.width = s.width == null ? 1 : s.width; - s.paths = s.paths || linearPath || retNull; + s.width = s.width == null ? 1 : s.width; + s.paths = s.paths || linearPath || retNull; s.fillTo = fnOrSelf(s.fillTo || seriesFillTo); s.pxAlign = +ifNull(s.pxAlign, pxAlign); s.pxRound = pxRoundGen(s.pxAlign); s.stroke = fnOrSelf(s.stroke || null); - s.fill = fnOrSelf(s.fill || null); + s.fill = fnOrSelf(s.fill || null); s._stroke = s._fill = s._paths = s._focus = null; let _ptDia = ptDia(max(1, s.width), 1); - let points = s.points = assign({}, { - size: _ptDia, - width: max(1, _ptDia * .2), - stroke: s.stroke, - space: _ptDia * 2, - paths: pointsPath, - _stroke: null, - _fill: null, - }, s.points); - points.show = fnOrSelf(points.show); + let points = (s.points = assign( + {}, + { + size: _ptDia, + width: max(1, _ptDia * 0.2), + stroke: s.stroke, + space: _ptDia * 2, + paths: pointsPath, + _stroke: null, + _fill: null + }, + s.points + )); + points.show = fnOrSelf(points.show); points.filter = fnOrSelf(points.filter); - points.fill = fnOrSelf(points.fill); + points.fill = fnOrSelf(points.fill); points.stroke = fnOrSelf(points.stroke); - points.paths = fnOrSelf(points.paths); + points.paths = fnOrSelf(points.paths); points.pxAlign = s.pxAlign; } @@ -3594,7 +3633,7 @@ function uPlot(opts, data, then) { let rowCells = initLegendRow(s, i); legendRows.splice(i, 0, rowCells[0]); legendCells.splice(i, 0, rowCells[1]); - legend.values.push(null); // NULL_LEGEND_VALS not yet avil here :( + legend.values.push(null); // NULL_LEGEND_VALS not yet avil here :( } if (cursor.show) { @@ -3603,24 +3642,24 @@ function uPlot(opts, data, then) { let pt = null; if (cursorOnePt) { - if (i == 0) - pt = initCursorPt(s, i); - } - else if (i > 0) - pt = initCursorPt(s, i); + if (i == 0) pt = initCursorPt(s, i); + } else if (i > 0) pt = initCursorPt(s, i); cursorPts.splice(i, 0, pt); cursorPtsLft.splice(i, 0, 0); cursorPtsTop.splice(i, 0, 0); } - fire("addSeries", i); + fire('addSeries', i); } function addSeries(opts, si) { si = si == null ? series.length : si; - opts = mode == 1 ? setDefault(opts, si, xSeriesOpts, ySeriesOpts) : setDefault(opts, si, {}, xySeriesOpts); + opts = + mode == 1 + ? setDefault(opts, si, xSeriesOpts, ySeriesOpts) + : setDefault(opts, si, {}, xySeriesOpts); series.splice(si, 0, opts); initSeries(series[si], si); @@ -3649,7 +3688,7 @@ function uPlot(opts, data, then) { // TODO: de-init no-longer-needed scales? - fire("delSeries", i); + fire('delSeries', i); } self.delSeries = delSeries; @@ -3673,54 +3712,80 @@ function uPlot(opts, data, then) { // also set defaults for incrs & values based on axis distr let isTime = sc.time; - axis.size = fnOrSelf(axis.size); - axis.space = fnOrSelf(axis.space); + axis.size = fnOrSelf(axis.size); + axis.space = fnOrSelf(axis.space); axis.rotate = fnOrSelf(axis.rotate); if (isArr(axis.incrs)) { - axis.incrs.forEach(incr => { + axis.incrs.forEach((incr) => { !fixedDec.has(incr) && fixedDec.set(incr, guessDec(incr)); }); } - axis.incrs = fnOrSelf(axis.incrs || ( sc.distr == 2 ? wholeIncrs : (isTime ? (ms == 1 ? timeIncrsMs : timeIncrsS) : numIncrs))); - axis.splits = fnOrSelf(axis.splits || (isTime && sc.distr == 1 ? _timeAxisSplits : sc.distr == 3 ? logAxisSplits : sc.distr == 4 ? asinhAxisSplits : numAxisSplits)); + axis.incrs = fnOrSelf( + axis.incrs || + (sc.distr == 2 + ? wholeIncrs + : isTime + ? ms == 1 + ? timeIncrsMs + : timeIncrsS + : numIncrs) + ); + axis.splits = fnOrSelf( + axis.splits || + (isTime && sc.distr == 1 + ? _timeAxisSplits + : sc.distr == 3 + ? logAxisSplits + : sc.distr == 4 + ? asinhAxisSplits + : numAxisSplits) + ); - axis.stroke = fnOrSelf(axis.stroke); - axis.grid.stroke = fnOrSelf(axis.grid.stroke); - axis.ticks.stroke = fnOrSelf(axis.ticks.stroke); + axis.stroke = fnOrSelf(axis.stroke); + axis.grid.stroke = fnOrSelf(axis.grid.stroke); + axis.ticks.stroke = fnOrSelf(axis.ticks.stroke); axis.border.stroke = fnOrSelf(axis.border.stroke); let av = axis.values; - axis.values = ( + axis.values = // static array of tick values - isArr(av) && !isArr(av[0]) ? fnOrSelf(av) : - // temporal - isTime ? ( - // config array of fmtDate string tpls - isArr(av) ? - timeAxisVals(_tzDate, timeAxisStamps(av, _fmtDate)) : - // fmtDate string tpl - isStr(av) ? - timeAxisVal(_tzDate, av) : - av || _timeAxisVals - ) : av || numAxisVals + isArr(av) && !isArr(av[0]) + ? fnOrSelf(av) + : // temporal + isTime + ? // config array of fmtDate string tpls + isArr(av) + ? timeAxisVals(_tzDate, timeAxisStamps(av, _fmtDate)) + : // fmtDate string tpl + //isStr(av) ? + // timeAxisVal(_tzDate, av) : + av || _timeAxisVals + : av || numAxisVals; + + axis.filter = fnOrSelf( + axis.filter || + (sc.distr >= 3 && sc.log == 10 + ? log10AxisValsFilt + : sc.distr == 3 && sc.log == 2 + ? log2AxisValsFilt + : retArg1) ); - axis.filter = fnOrSelf(axis.filter || ( sc.distr >= 3 && sc.log == 10 ? log10AxisValsFilt : sc.distr == 3 && sc.log == 2 ? log2AxisValsFilt : retArg1)); - - axis.font = pxRatioFont(axis.font); + axis.font = pxRatioFont(axis.font); axis.labelFont = pxRatioFont(axis.labelFont); - axis._size = axis.size(self, null, i, 0); + axis._size = axis.size(self, null, i, 0); - axis._space = - axis._rotate = - axis._incrs = - axis._found = // foundIncrSpace - axis._splits = - axis._values = null; + axis._space = + axis._rotate = + axis._incrs = + axis._found = // foundIncrSpace + axis._splits = + axis._values = + null; if (axis._size > 0) { sidesWithAxes[i] = true; @@ -3728,7 +3793,7 @@ function uPlot(opts, data, then) { } // debug - // axis._el.style.background = "#" + Math.floor(Math.random()*16777215).toString(16) + '80'; + // axis._el.style.background = "#" + Math.floor(Math.random()*16777215).toString(16) + '80'; } } @@ -3739,15 +3804,25 @@ function uPlot(opts, data, then) { let size = 0; if (ori == 0 && (hasLftAxis || hasRgtAxis)) - size = (side == 0 && !hasTopAxis || side == 2 && !hasBtmAxis ? round(xAxisOpts.size / 3) : 0); + size = + (side == 0 && !hasTopAxis) || (side == 2 && !hasBtmAxis) + ? round(xAxisOpts.size / 3) + : 0; if (ori == 1 && (hasTopAxis || hasBtmAxis)) - size = (side == 1 && !hasRgtAxis || side == 3 && !hasLftAxis ? round(yAxisOpts.size / 2) : 0); + size = + (side == 1 && !hasRgtAxis) || (side == 3 && !hasLftAxis) + ? round(yAxisOpts.size / 2) + : 0; - return size; + return size } - const padding = self.padding = (opts.padding || [autoPadSide,autoPadSide,autoPadSide,autoPadSide]).map(p => fnOrSelf(ifNull(p, autoPadSide))); - const _padding = self._padding = padding.map((p, i) => p(self, i, sidesWithAxes, 0)); + const padding = (self.padding = ( + opts.padding || [autoPadSide, autoPadSide, autoPadSide, autoPadSide] + ).map((p) => fnOrSelf(ifNull(p, autoPadSide)))); + const _padding = (self._padding = padding.map((p, i) => + p(self, i, sidesWithAxes, 0) + )); let dataLen; @@ -3767,12 +3842,9 @@ function uPlot(opts, data, then) { if (mode == 2) { dataLen = 0; - for (let i = 1; i < series.length; i++) - dataLen += data[i][0].length; - } - else { - if (data.length == 0) - self.data = self._data = data = [[]]; + for (let i = 1; i < series.length; i++) dataLen += data[i][0].length; + } else { + if (data.length == 0) self.data = self._data = data = [[]]; data0 = data[0]; dataLen = data0.length; @@ -3782,9 +3854,8 @@ function uPlot(opts, data, then) { if (xScaleDistr == 2) { scaleData = data.slice(); - let _data0 = scaleData[0] = Array(dataLen); - for (let i = 0; i < dataLen; i++) - _data0[i] = i; + let _data0 = (scaleData[0] = Array(dataLen)); + for (let i = 0; i < dataLen; i++) _data0[i] = i; } self._data = data = scaleData; @@ -3792,7 +3863,7 @@ function uPlot(opts, data, then) { resetYSeries(true); - fire("setData"); + fire('setData'); // forces x axis tick values to re-generate when neither x scale nor y scale changes // in ordinal mode, scale range is by index, so will not change if new data has same length, but tick values are from data @@ -3815,10 +3886,8 @@ function uPlot(opts, data, then) { if (_resetScales !== false) { let xsc = scaleX; - if (xsc.auto(self, viaAutoScaleX)) - autoScaleX(); - else - _setScale(xScaleKey, xsc.min, xsc.max); + if (xsc.auto(self, viaAutoScaleX)) autoScaleX(); + else _setScale(xScaleKey, xsc.min, xsc.max); shouldSetCursor = shouldSetCursor || cursor.left >= 0; shouldSetLegend = true; @@ -3844,19 +3913,15 @@ function uPlot(opts, data, then) { if (xScaleDistr == 2) { _min = i0; _max = i1; - } - else if (_min == _max) { + } else if (_min == _max) { if (xScaleDistr == 3) [_min, _max] = rangeLog(_min, _min, scaleX.log, false); else if (xScaleDistr == 4) [_min, _max] = rangeAsinh(_min, _min, scaleX.log, false); - else if (scaleX.time) - _max = _min + round(86400 / ms); - else - [_min, _max] = rangeNum(_min, _max, rangePad, true); + else if (scaleX.time) _max = _min + round(86400 / ms); + else [_min, _max] = rangeNum(_min, _max, rangePad, true); } - } - else { + } else { i0 = idxs[0] = _min = null; i1 = idxs[1] = _max = null; } @@ -3865,71 +3930,78 @@ function uPlot(opts, data, then) { _setScale(xScaleKey, _min, _max); } - let ctxStroke, ctxFill, ctxWidth, ctxDash, ctxJoin, ctxCap, ctxFont, ctxAlign, ctxBaseline; + let ctxStroke, + ctxFill, + ctxWidth, + ctxDash, + ctxJoin, + ctxCap, + ctxFont, + ctxAlign, + ctxBaseline; let ctxAlpha; function setCtxStyle(stroke, width, dash, cap, fill, join) { stroke ??= transparent; - dash ??= EMPTY_ARR; - cap ??= "butt"; // (‿|‿) - fill ??= transparent; - join ??= "round"; - - if (stroke != ctxStroke) - ctx.strokeStyle = ctxStroke = stroke; - if (fill != ctxFill) - ctx.fillStyle = ctxFill = fill; - if (width != ctxWidth) - ctx.lineWidth = ctxWidth = width; - if (join != ctxJoin) - ctx.lineJoin = ctxJoin = join; - if (cap != ctxCap) - ctx.lineCap = ctxCap = cap; - if (dash != ctxDash) - ctx.setLineDash(ctxDash = dash); + dash ??= EMPTY_ARR; + cap ??= 'butt'; // (‿|‿) + fill ??= transparent; + join ??= 'round'; + + if (stroke != ctxStroke) ctx.strokeStyle = ctxStroke = stroke; + if (fill != ctxFill) ctx.fillStyle = ctxFill = fill; + if (width != ctxWidth) ctx.lineWidth = ctxWidth = width; + if (join != ctxJoin) ctx.lineJoin = ctxJoin = join; + if (cap != ctxCap) ctx.lineCap = ctxCap = cap; + if (dash != ctxDash) ctx.setLineDash((ctxDash = dash)); } function setFontStyle(font, fill, align, baseline) { - if (fill != ctxFill) - ctx.fillStyle = ctxFill = fill; - if (font != ctxFont) - ctx.font = ctxFont = font; - if (align != ctxAlign) - ctx.textAlign = ctxAlign = align; - if (baseline != ctxBaseline) - ctx.textBaseline = ctxBaseline = baseline; + if (fill != ctxFill) ctx.fillStyle = ctxFill = fill; + if (font != ctxFont) ctx.font = ctxFont = font; + if (align != ctxAlign) ctx.textAlign = ctxAlign = align; + if (baseline != ctxBaseline) ctx.textBaseline = ctxBaseline = baseline; } function accScale(wsc, psc, facet, data, sorted = 0) { - if (data.length > 0 && wsc.auto(self, viaAutoScaleX) && (psc == null || psc.min == null)) { + if ( + data.length > 0 && + wsc.auto(self, viaAutoScaleX) && + (psc == null || psc.min == null) + ) { let _i0 = ifNull(i0, 0); let _i1 = ifNull(i1, data.length - 1); // only run getMinMax() for invalidated series data, else reuse - let minMax = facet.min == null ? (wsc.distr == 3 ? getMinMaxLog(data, _i0, _i1) : getMinMax(data, _i0, _i1, sorted)) : [facet.min, facet.max]; + let minMax = + facet.min == null + ? wsc.distr == 3 + ? getMinMaxLog(data, _i0, _i1) + : getMinMax(data, _i0, _i1, sorted) + : [facet.min, facet.max]; // initial min/max - wsc.min = min(wsc.min, facet.min = minMax[0]); - wsc.max = max(wsc.max, facet.max = minMax[1]); + wsc.min = min(wsc.min, (facet.min = minMax[0])); + wsc.max = max(wsc.max, (facet.max = minMax[1])); } } - const AUTOSCALE = {min: null, max: null}; + const AUTOSCALE = { min: null, max: null }; function setScales() { - // log("setScales()", arguments); + // log("setScales()", arguments); // implicitly add auto scales, and unranged scales for (let k in scales) { let sc = scales[k]; - if (pendScales[k] == null && - ( - // scales that have never been set (on init) - sc.min == null || + if ( + pendScales[k] == null && + // scales that have never been set (on init) + (sc.min == null || // or auto scales when the x scale was explicitly set - pendScales[xScaleKey] != null && sc.auto(self, viaAutoScaleX) - ) + (pendScales[xScaleKey] != null && + sc.auto(self, viaAutoScaleX))) ) { pendScales[k] = AUTOSCALE; } @@ -3939,13 +4011,16 @@ function uPlot(opts, data, then) { for (let k in scales) { let sc = scales[k]; - if (pendScales[k] == null && sc.from != null && pendScales[sc.from] != null) + if ( + pendScales[k] == null && + sc.from != null && + pendScales[sc.from] != null + ) pendScales[k] = AUTOSCALE; } // explicitly setting the x-scale invalidates everything (acts as redraw) - if (pendScales[xScaleKey] != null) - resetYSeries(true); // TODO: only reset series on auto scales? + if (pendScales[xScaleKey] != null) resetYSeries(true); // TODO: only reset series on auto scales? let wipScales = {}; @@ -3953,17 +4028,15 @@ function uPlot(opts, data, then) { let psc = pendScales[k]; if (psc != null) { - let wsc = wipScales[k] = copy(scales[k], fastIsObj); + let wsc = (wipScales[k] = copy(scales[k], fastIsObj)); - if (psc.min != null) - assign(wsc, psc); + if (psc.min != null) assign(wsc, psc); else if (k != xScaleKey || mode == 2) { if (dataLen == 0 && wsc.from == null) { let minMax = wsc.range(self, null, null, k); wsc.min = minMax[0]; wsc.max = minMax[1]; - } - else { + } else { wsc.min = inf; wsc.max = -inf; } @@ -3978,8 +4051,7 @@ function uPlot(opts, data, then) { let k = s.scale; let psc = pendScales[k]; - if (psc == null) - return; + if (psc == null) return let wsc = wipScales[k]; @@ -3995,36 +4067,46 @@ function uPlot(opts, data, then) { // don't try to contract same or adjacent idxs if (i1 - i0 > 1) { // closest indices can be outside of view - if (data[0][i0] < wsc.min) - i0++; - if (data[0][i1] > wsc.max) - i1--; + if (data[0][i0] < wsc.min) i0++; + if (data[0][i1] > wsc.max) i1--; } s.min = data0[i0]; s.max = data0[i1]; - } - else if (s.show && s.auto) + } else if (s.show && s.auto) accScale(wsc, psc, s, data[i], s.sorted); s.idxs[0] = i0; s.idxs[1] = i1; - } - else { + } else { if (i > 0) { if (s.show && s.auto) { // TODO: only handles, assumes and requires facets[0] / 'x' scale, and facets[1] / 'y' scale - let [ xFacet, yFacet ] = s.facets; + let [xFacet, yFacet] = s.facets; let xScaleKey = xFacet.scale; let yScaleKey = yFacet.scale; - let [ xData, yData ] = data[i]; + let [xData, yData] = data[i]; let wscx = wipScales[xScaleKey]; let wscy = wipScales[yScaleKey]; // null can happen when only x is zoomed, but y has static range and doesnt get auto-added to pending - wscx != null && accScale(wscx, pendScales[xScaleKey], xFacet, xData, xFacet.sorted); - wscy != null && accScale(wscy, pendScales[yScaleKey], yFacet, yData, yFacet.sorted); + wscx != null && + accScale( + wscx, + pendScales[xScaleKey], + xFacet, + xData, + xFacet.sorted + ); + wscy != null && + accScale( + wscy, + pendScales[yScaleKey], + yFacet, + yData, + yFacet.sorted + ); // temp s.min = yFacet.min; @@ -4042,7 +4124,7 @@ function uPlot(opts, data, then) { if (wsc.from == null && (psc == null || psc.min == null)) { let minMax = wsc.range( self, - wsc.min == inf ? null : wsc.min, + wsc.min == inf ? null : wsc.min, wsc.max == -inf ? null : wsc.max, k ); @@ -4059,8 +4141,7 @@ function uPlot(opts, data, then) { if (wsc.from != null) { let base = wipScales[wsc.from]; - if (base.min == null) - wsc.min = wsc.max = null; + if (base.min == null) wsc.min = wsc.max = null; else { let minMax = wsc.range(self, base.min, base.max, k); wsc.min = minMax[0]; @@ -4082,8 +4163,22 @@ function uPlot(opts, data, then) { let distr = sc.distr; - sc._min = distr == 3 ? log10(sc.min) : distr == 4 ? asinh(sc.min, sc.asinh) : distr == 100 ? sc.fwd(sc.min) : sc.min; - sc._max = distr == 3 ? log10(sc.max) : distr == 4 ? asinh(sc.max, sc.asinh) : distr == 100 ? sc.fwd(sc.max) : sc.max; + sc._min = + distr == 3 + ? log10(sc.min) + : distr == 4 + ? asinh(sc.min, sc.asinh) + : distr == 100 + ? sc.fwd(sc.min) + : sc.min; + sc._max = + distr == 3 + ? log10(sc.max) + : distr == 4 + ? asinh(sc.max, sc.asinh) + : distr == 100 + ? sc.fwd(sc.max) + : sc.max; changed[k] = anyChanged = true; } @@ -4093,26 +4188,22 @@ function uPlot(opts, data, then) { // invalidate paths of all series on changed scales series.forEach((s, i) => { if (mode == 2) { - if (i > 0 && changed.y) - s._paths = null; - } - else { - if (changed[s.scale]) - s._paths = null; + if (i > 0 && changed.y) s._paths = null; + } else { + if (changed[s.scale]) s._paths = null; } }); for (let k in changed) { shouldConvergeSize = true; - fire("setScale", k); + fire('setScale', k); } if (cursor.show && cursor.left >= 0) shouldSetCursor = shouldSetLegend = true; } - for (let k in pendScales) - pendScales[k] = null; + for (let k in pendScales) pendScales[k] = null; } // grabs the nearest indices with y data outside of x-scale limits @@ -4120,13 +4211,11 @@ function uPlot(opts, data, then) { let _i0 = clamp(i0 - 1, 0, dataLen - 1); let _i1 = clamp(i1 + 1, 0, dataLen - 1); - while (ydata[_i0] == null && _i0 > 0) - _i0--; + while (ydata[_i0] == null && _i0 > 0) _i0--; - while (ydata[_i1] == null && _i1 < dataLen - 1) - _i1++; + while (ydata[_i1] == null && _i1 < dataLen - 1) _i1++; - return [_i0, _i1]; + return [_i0, _i1] } function drawSeries() { @@ -4140,11 +4229,13 @@ function uPlot(opts, data, then) { if (ctxAlpha != s.alpha) ctx.globalAlpha = ctxAlpha = s.alpha; - let _idxs = mode == 2 ? [0, data[i][0].length - 1] : getOuterIdxs(data[i]); + let _idxs = + mode == 2 + ? [0, data[i][0].length - 1] + : getOuterIdxs(data[i]); s._paths = s.paths(self, i, _idxs[0], _idxs[1]); - if (ctxAlpha != 1) - ctx.globalAlpha = ctxAlpha = 1; + if (ctxAlpha != 1) ctx.globalAlpha = ctxAlpha = 1; } } }); @@ -4163,15 +4254,20 @@ function uPlot(opts, data, then) { let idxs = s.points.filter(self, i, show, _gaps); if (show || idxs) { - s.points._paths = s.points.paths(self, i, i0, i1, idxs); + s.points._paths = s.points.paths( + self, + i, + i0, + i1, + idxs + ); drawPath(i, true); } } - if (ctxAlpha != 1) - ctx.globalAlpha = ctxAlpha = 1; + if (ctxAlpha != 1) ctx.globalAlpha = ctxAlpha = 1; - fire("drawSeries", i); + fire('drawSeries', i); } }); } @@ -4181,7 +4277,7 @@ function uPlot(opts, data, then) { let s = _points ? series[si].points : series[si]; s._stroke = s.stroke(self, si); - s._fill = s.fill(self, si); + s._fill = s.fill(self, si); } function drawPath(si, _points) { @@ -4194,8 +4290,8 @@ function uPlot(opts, data, then) { flags, _stroke: strokeStyle = s._stroke, - _fill: fillStyle = s._fill, - _width: width = s.width, + _fill: fillStyle = s._fill, + _width: width = s.width } = s._paths; width = roundDec(width * pxRatio, 3); @@ -4204,7 +4300,7 @@ function uPlot(opts, data, then) { let offset = (width % 2) / 2; if (_points && fillStyle == null) - fillStyle = width > 0 ? "#fff" : strokeStyle; + fillStyle = width > 0 ? '#fff' : strokeStyle; let _pxAlign = s.pxAlign == 1 && offset > 0; @@ -4222,54 +4318,128 @@ function uPlot(opts, data, then) { // the points pathbuilder's gapsClip is its boundsClip, since points dont need gaps clipping, and bounds depend on point size if (_points) - strokeFill(strokeStyle, width, s.dash, s.cap, fillStyle, stroke, fill, flags, gapsClip); + strokeFill( + strokeStyle, + width, + s.dash, + s.cap, + fillStyle, + stroke, + fill, + flags, + gapsClip + ); else - fillStroke(si, strokeStyle, width, s.dash, s.cap, fillStyle, stroke, fill, flags, boundsClip, gapsClip); + fillStroke( + si, + strokeStyle, + width, + s.dash, + s.cap, + fillStyle, + stroke, + fill, + flags, + boundsClip, + gapsClip + ); _pxAlign && ctx.translate(-offset, -offset); } - function fillStroke(si, strokeStyle, lineWidth, lineDash, lineCap, fillStyle, strokePath, fillPath, flags, boundsClip, gapsClip) { + function fillStroke( + si, + strokeStyle, + lineWidth, + lineDash, + lineCap, + fillStyle, + strokePath, + fillPath, + flags, + boundsClip, + gapsClip + ) { let didStrokeFill = false; // for all bands where this series is the top edge, create upwards clips using the bottom edges // and apply clips + fill with band fill or dfltFill - flags != 0 && bands.forEach((b, bi) => { - // isUpperEdge? - if (b.series[0] == si) { - let lowerEdge = series[b.series[1]]; - let lowerData = data[b.series[1]]; - - let bandClip = (lowerEdge._paths || EMPTY_OBJ).band; - - if (isArr(bandClip)) - bandClip = b.dir == 1 ? bandClip[0] : bandClip[1]; - - let gapsClip2; - - let _fillStyle = null; + flags != 0 && + bands.forEach((b, bi) => { + // isUpperEdge? + if (b.series[0] == si) { + let lowerEdge = series[b.series[1]]; + let lowerData = data[b.series[1]]; + + let bandClip = (lowerEdge._paths || EMPTY_OBJ).band; + + if (isArr(bandClip)) + bandClip = b.dir == 1 ? bandClip[0] : bandClip[1]; + + let gapsClip2; + + let _fillStyle = null; + + // hasLowerEdge? + if ( + lowerEdge.show && + bandClip && + hasData(lowerData, i0, i1) + ) { + _fillStyle = b.fill(self, bi) || fillStyle; + gapsClip2 = lowerEdge._paths.clip; + } else bandClip = null; + + strokeFill( + strokeStyle, + lineWidth, + lineDash, + lineCap, + _fillStyle, + strokePath, + fillPath, + flags, + boundsClip, + gapsClip, + gapsClip2, + bandClip + ); - // hasLowerEdge? - if (lowerEdge.show && bandClip && hasData(lowerData, i0, i1)) { - _fillStyle = b.fill(self, bi) || fillStyle; - gapsClip2 = lowerEdge._paths.clip; + didStrokeFill = true; } - else - bandClip = null; - - strokeFill(strokeStyle, lineWidth, lineDash, lineCap, _fillStyle, strokePath, fillPath, flags, boundsClip, gapsClip, gapsClip2, bandClip); - - didStrokeFill = true; - } - }); + }); if (!didStrokeFill) - strokeFill(strokeStyle, lineWidth, lineDash, lineCap, fillStyle, strokePath, fillPath, flags, boundsClip, gapsClip); + strokeFill( + strokeStyle, + lineWidth, + lineDash, + lineCap, + fillStyle, + strokePath, + fillPath, + flags, + boundsClip, + gapsClip + ); } const CLIP_FILL_STROKE = BAND_CLIP_FILL | BAND_CLIP_STROKE; - function strokeFill(strokeStyle, lineWidth, lineDash, lineCap, fillStyle, strokePath, fillPath, flags, boundsClip, gapsClip, gapsClip2, bandClip) { + function strokeFill( + strokeStyle, + lineWidth, + lineDash, + lineCap, + fillStyle, + strokePath, + fillPath, + flags, + boundsClip, + gapsClip, + gapsClip2, + bandClip + ) { setCtxStyle(strokeStyle, lineWidth, lineDash, lineCap, fillStyle); if (boundsClip || gapsClip || bandClip) { @@ -4284,13 +4454,11 @@ function uPlot(opts, data, then) { gapsClip2 && ctx.clip(gapsClip2); doFill(fillStyle, fillPath); doStroke(strokeStyle, strokePath, lineWidth); - } - else if (flags & BAND_CLIP_STROKE) { + } else if (flags & BAND_CLIP_STROKE) { doFill(fillStyle, fillPath); ctx.clip(bandClip); doStroke(strokeStyle, strokePath, lineWidth); - } - else if (flags & BAND_CLIP_FILL) { + } else if (flags & BAND_CLIP_FILL) { ctx.save(); ctx.clip(bandClip); gapsClip2 && ctx.clip(gapsClip2); @@ -4298,14 +4466,12 @@ function uPlot(opts, data, then) { ctx.restore(); doStroke(strokeStyle, strokePath, lineWidth); } - } - else { + } else { doFill(fillStyle, fillPath); doStroke(strokeStyle, strokePath, lineWidth); } - if (boundsClip || gapsClip || bandClip) - ctx.restore(); + if (boundsClip || gapsClip || bandClip) ctx.restore(); } function doStroke(strokeStyle, strokePath, lineWidth) { @@ -4315,9 +4481,7 @@ function uPlot(opts, data, then) { ctx.strokeStyle = ctxStroke = strokeStyle; ctx.stroke(strokePath); }); - } - else - strokePath != null && strokeStyle && ctx.stroke(strokePath); + } else strokePath != null && strokeStyle && ctx.stroke(strokePath); } } @@ -4327,9 +4491,7 @@ function uPlot(opts, data, then) { ctx.fillStyle = ctxFill = fillStyle; ctx.fill(fillPath); }); - } - else - fillPath != null && fillStyle && ctx.fill(fillPath); + } else fillPath != null && fillStyle && ctx.fill(fillPath); } function getIncrSpace(axisIdx, min, max, fullDim) { @@ -4337,18 +4499,41 @@ function uPlot(opts, data, then) { let incrSpace; - if (fullDim <= 0) - incrSpace = [0, 0]; + if (fullDim <= 0) incrSpace = [0, 0]; else { - let minSpace = axis._space = axis.space(self, axisIdx, min, max, fullDim); - let incrs = axis._incrs = axis.incrs(self, axisIdx, min, max, fullDim, minSpace); - incrSpace = findIncr(min, max, incrs, fullDim, minSpace); + let minSpace = (axis._space = axis.space( + self, + axisIdx, + min, + max, + fullDim + )); + let incrs = (axis._incrs = axis.incrs( + self, + axisIdx, + min, + max, + fullDim, + minSpace + )); + incrSpace = findIncr(min, max, incrs, fullDim, minSpace); } - return (axis._found = incrSpace); - } - - function drawOrthoLines(offs, filts, ori, side, pos0, len, width, stroke, dash, cap) { + return (axis._found = incrSpace) + } + + function drawOrthoLines( + offs, + filts, + ori, + side, + pos0, + len, + width, + stroke, + dash, + cap + ) { let offset = (width % 2) / 2; pxAlign == 1 && ctx.translate(offset, offset); @@ -4357,23 +4542,24 @@ function uPlot(opts, data, then) { ctx.beginPath(); - let x0, y0, x1, y1, pos1 = pos0 + (side == 0 || side == 3 ? -len : len); + let x0, + y0, + x1, + y1, + pos1 = pos0 + (side == 0 || side == 3 ? -len : len); if (ori == 0) { y0 = pos0; y1 = pos1; - } - else { + } else { x0 = pos0; x1 = pos1; } for (let i = 0; i < offs.length; i++) { if (filts[i] != null) { - if (ori == 0) - x0 = x1 = offs[i]; - else - y0 = y1 = offs[i]; + if (ori == 0) x0 = x1 = offs[i]; + else y0 = y1 = offs[i]; ctx.moveTo(x0, y0); ctx.lineTo(x1, y1); @@ -4386,13 +4572,12 @@ function uPlot(opts, data, then) { } function axesCalc(cycleNum) { - // log("axesCalc()", arguments); + // log("axesCalc()", arguments); let converged = true; axes.forEach((axis, i) => { - if (!axis.show) - return; + if (!axis.show) return let scale = scales[axis.scale]; @@ -4402,9 +4587,8 @@ function uPlot(opts, data, then) { axis._show = false; resetYSeries(false); } - return; - } - else { + return + } else { if (!axis._show) { converged = false; axis._show = true; @@ -4415,24 +4599,45 @@ function uPlot(opts, data, then) { let side = axis.side; let ori = side % 2; - let {min, max} = scale; // // should this toggle them ._show = false + let { min, max } = scale; // // should this toggle them ._show = false - let [_incr, _space] = getIncrSpace(i, min, max, ori == 0 ? plotWidCss : plotHgtCss); + let [_incr, _space] = getIncrSpace( + i, + min, + max, + ori == 0 ? plotWidCss : plotHgtCss + ); - if (_space == 0) - return; + if (_space == 0) return // if we're using index positions, force first tick to match passed index let forceMin = scale.distr == 2; - let _splits = axis._splits = axis.splits(self, i, min, max, _incr, _space, forceMin); + let _splits = (axis._splits = axis.splits( + self, + i, + min, + max, + _incr, + _space, + forceMin + )); // tick labels // BOO this assumes a specific data/series - let splits = scale.distr == 2 ? _splits.map(i => data0[i]) : _splits; - let incr = scale.distr == 2 ? data0[_splits[1]] - data0[_splits[0]] : _incr; - - let values = axis._values = axis.values(self, axis.filter(self, splits, i, _space, incr), i, _space, incr); + let splits = + scale.distr == 2 ? _splits.map((i) => data0[i]) : _splits; + let incr = + scale.distr == 2 ? data0[_splits[1]] - data0[_splits[0]] : _incr; + + let values = (axis._values = axis.values( + self, + axis.filter(self, splits, i, _space, incr), + i, + _space, + incr, + fmtNum + )); // rotating of labels only supported on bottom x axis axis._rotate = side == 2 ? axis.rotate(self, values, i, _space) : 0; @@ -4441,11 +4646,12 @@ function uPlot(opts, data, then) { axis._size = ceil(axis.size(self, values, i, cycleNum)); - if (oldSize != null && axis._size != oldSize) // ready && ? + if (oldSize != null && axis._size != oldSize) + // ready && ? converged = false; }); - return converged; + return converged } function paddingCalc(cycleNum) { @@ -4454,21 +4660,19 @@ function uPlot(opts, data, then) { padding.forEach((p, i) => { let _p = p(self, i, sidesWithAxes, cycleNum); - if (_p != _padding[i]) - converged = false; + if (_p != _padding[i]) converged = false; _padding[i] = _p; }); - return converged; + return converged } function drawAxesGrid() { for (let i = 0; i < axes.length; i++) { let axis = axes[i]; - if (!axis.show || !axis._show) - continue; + if (!axis.show || !axis._show) continue let side = axis.side; let ori = side % 2; @@ -4484,21 +4688,21 @@ function uPlot(opts, data, then) { let shiftAmt = axis.labelGap * shiftDir; let baseLpos = round((axis._lpos + shiftAmt) * pxRatio); - setFontStyle(axis.labelFont[0], fillStyle, "center", side == 2 ? TOP : BOTTOM); + setFontStyle( + axis.labelFont[0], + fillStyle, + 'center', + side == 2 ? TOP : BOTTOM + ); ctx.save(); if (ori == 1) { x = y = 0; - ctx.translate( - baseLpos, - round(plotTop + plotHgt / 2), - ); + ctx.translate(baseLpos, round(plotTop + plotHgt / 2)); ctx.rotate((side == 3 ? -PI : PI) / 2); - - } - else { + } else { x = round(plotLft + plotWid / 2); y = baseLpos; } @@ -4510,8 +4714,7 @@ function uPlot(opts, data, then) { let [_incr, _space] = axis._found; - if (_space == 0) - continue; + if (_space == 0) continue let scale = scales[axis.scale]; @@ -4524,36 +4727,49 @@ function uPlot(opts, data, then) { // tick labels // BOO this assumes a specific data/series - let splits = scale.distr == 2 ? _splits.map(i => data0[i]) : _splits; - let incr = scale.distr == 2 ? data0[_splits[1]] - data0[_splits[0]] : _incr; + let splits = + scale.distr == 2 ? _splits.map((i) => data0[i]) : _splits; + let incr = + scale.distr == 2 ? data0[_splits[1]] - data0[_splits[0]] : _incr; let ticks = axis.ticks; let border = axis.border; let tickSize = ticks.show ? round(ticks.size * pxRatio) : 0; // rotating of labels only supported on bottom x axis - let angle = axis._rotate * -PI/180; + let angle = (axis._rotate * -PI) / 180; - let basePos = pxRound(axis._pos * pxRatio); + let basePos = pxRound(axis._pos * pxRatio); let shiftAmt = (tickSize + axisGap) * shiftDir; let finalPos = basePos + shiftAmt; - y = ori == 0 ? finalPos : 0; - x = ori == 1 ? finalPos : 0; - - let font = axis.font[0]; - let textAlign = axis.align == 1 ? LEFT : - axis.align == 2 ? RIGHT : - angle > 0 ? LEFT : - angle < 0 ? RIGHT : - ori == 0 ? "center" : side == 3 ? RIGHT : LEFT; - let textBaseline = angle || - ori == 1 ? "middle" : side == 2 ? TOP : BOTTOM; + y = ori == 0 ? finalPos : 0; + x = ori == 1 ? finalPos : 0; + + let font = axis.font[0]; + let textAlign = + axis.align == 1 + ? LEFT + : axis.align == 2 + ? RIGHT + : angle > 0 + ? LEFT + : angle < 0 + ? RIGHT + : ori == 0 + ? 'center' + : side == 3 + ? RIGHT + : LEFT; + let textBaseline = + angle || ori == 1 ? 'middle' : side == 2 ? TOP : BOTTOM; setFontStyle(font, fillStyle, textAlign, textBaseline); let lineHeight = axis.font[1] * axis.lineGap; - let canOffs = _splits.map(val => pxRound(getPos(val, scale, plotDim, plotOff))); + let canOffs = _splits.map((val) => + pxRound(getPos(val, scale, plotDim, plotOff)) + ); let _values = axis._values; @@ -4561,14 +4777,13 @@ function uPlot(opts, data, then) { let val = _values[i]; if (val != null) { - if (ori == 0) - x = canOffs[i]; - else - y = canOffs[i]; + if (ori == 0) x = canOffs[i]; + else y = canOffs[i]; - val = "" + val; + val = '' + val; - let _parts = val.indexOf("\n") == -1 ? [val] : val.split(/\n/gm); + let _parts = + val.indexOf('\n') == -1 ? [val] : val.split(/\n/gm); for (let j = 0; j < _parts.length; j++) { let text = _parts[j]; @@ -4579,9 +4794,7 @@ function uPlot(opts, data, then) { ctx.rotate(angle); // can this be done once? ctx.fillText(text, 0, 0); ctx.restore(); - } - else - ctx.fillText(text, x, y + j * lineHeight); + } else ctx.fillText(text, x, y + j * lineHeight); } } } @@ -4598,7 +4811,7 @@ function uPlot(opts, data, then) { roundDec(ticks.width * pxRatio, 3), ticks.stroke(self, i), ticks.dash, - ticks.cap, + ticks.cap ); } @@ -4616,7 +4829,7 @@ function uPlot(opts, data, then) { roundDec(grid.width * pxRatio, 3), grid.stroke(self, i), grid.dash, - grid.cap, + grid.cap ); } @@ -4631,16 +4844,16 @@ function uPlot(opts, data, then) { roundDec(border.width * pxRatio, 3), border.stroke(self, i), border.dash, - border.cap, + border.cap ); } } - fire("drawAxes"); + fire('drawAxes'); } function resetYSeries(minMax) { - // log("resetYSeries()", arguments); + // log("resetYSeries()", arguments); series.forEach((s, i) => { if (i > 0) { @@ -4650,9 +4863,8 @@ function uPlot(opts, data, then) { if (mode == 1) { s.min = null; s.max = null; - } - else { - s.facets.forEach(f => { + } else { + s.facets.forEach((f) => { f.min = null; f.max = null; }); @@ -4669,8 +4881,7 @@ function uPlot(opts, data, then) { function flushHooks() { deferHooks = false; - for (let i = 0; i < hooksQueue.length; i++) - fire(...hooksQueue[i]); + for (let i = 0; i < hooksQueue.length; i++) fire(...hooksQueue[i]); hooksQueue.length = 0; } @@ -4690,14 +4901,13 @@ function uPlot(opts, data, then) { fn(self); _commit(); - if (_deferHooks && hooksQueue.length > 0) - queueMicrotask(flushHooks); + if (_deferHooks && hooksQueue.length > 0) queueMicrotask(flushHooks); } self.batch = batch; function _commit() { - // log("_commit()", arguments); + // log("_commit()", arguments); if (shouldSetScales) { setScales(); @@ -4710,44 +4920,59 @@ function uPlot(opts, data, then) { } if (shouldSetSize) { - setStylePx(under, LEFT, plotLftCss); - setStylePx(under, TOP, plotTopCss); - setStylePx(under, WIDTH, plotWidCss); + setStylePx(under, LEFT, plotLftCss); + setStylePx(under, TOP, plotTopCss); + setStylePx(under, WIDTH, plotWidCss); setStylePx(under, HEIGHT, plotHgtCss); - setStylePx(over, LEFT, plotLftCss); - setStylePx(over, TOP, plotTopCss); - setStylePx(over, WIDTH, plotWidCss); - setStylePx(over, HEIGHT, plotHgtCss); + setStylePx(over, LEFT, plotLftCss); + setStylePx(over, TOP, plotTopCss); + setStylePx(over, WIDTH, plotWidCss); + setStylePx(over, HEIGHT, plotHgtCss); - setStylePx(wrap, WIDTH, fullWidCss); - setStylePx(wrap, HEIGHT, fullHgtCss); + setStylePx(wrap, WIDTH, fullWidCss); + setStylePx(wrap, HEIGHT, fullHgtCss); // NOTE: mutating this during print preview in Chrome forces transparent // canvas pixels to white, even when followed up with clearRect() below - can.width = round(fullWidCss * pxRatio); + can.width = round(fullWidCss * pxRatio); can.height = round(fullHgtCss * pxRatio); axes.forEach(({ _el, _show, _size, _pos, side }) => { if (_el != null) { if (_show) { - let posOffset = (side === 3 || side === 0 ? _size : 0); + let posOffset = side === 3 || side === 0 ? _size : 0; let isVt = side % 2 == 1; - setStylePx(_el, isVt ? "left" : "top", _pos - posOffset); - setStylePx(_el, isVt ? "width" : "height", _size); - setStylePx(_el, isVt ? "top" : "left", isVt ? plotTopCss : plotLftCss); - setStylePx(_el, isVt ? "height" : "width", isVt ? plotHgtCss : plotWidCss); + setStylePx(_el, isVt ? 'left' : 'top', _pos - posOffset); + setStylePx(_el, isVt ? 'width' : 'height', _size); + setStylePx( + _el, + isVt ? 'top' : 'left', + isVt ? plotTopCss : plotLftCss + ); + setStylePx( + _el, + isVt ? 'height' : 'width', + isVt ? plotHgtCss : plotWidCss + ); remClass(_el, OFF); - } - else - addClass(_el, OFF); + } else addClass(_el, OFF); } }); // invalidate ctx style cache - ctxStroke = ctxFill = ctxWidth = ctxJoin = ctxCap = ctxFont = ctxAlign = ctxBaseline = ctxDash = null; + ctxStroke = + ctxFill = + ctxWidth = + ctxJoin = + ctxCap = + ctxFont = + ctxAlign = + ctxBaseline = + ctxDash = + null; ctxAlpha = 1; syncRect(true); @@ -4765,10 +4990,24 @@ function uPlot(opts, data, then) { if (cursor.show && !shouldSetCursor && cursor.left >= 0) { cursor.left *= pctWid; - cursor.top *= pctHgt; - - vCursor && elTrans(vCursor, round(cursor.left), 0, plotWidCss, plotHgtCss); - hCursor && elTrans(hCursor, 0, round(cursor.top), plotWidCss, plotHgtCss); + cursor.top *= pctHgt; + + vCursor && + elTrans( + vCursor, + round(cursor.left), + 0, + plotWidCss, + plotHgtCss + ); + hCursor && + elTrans( + hCursor, + 0, + round(cursor.top), + plotWidCss, + plotHgtCss + ); for (let i = 0; i < cursorPts.length; i++) { let pt = cursorPts[i]; @@ -4776,15 +5015,26 @@ function uPlot(opts, data, then) { if (pt != null) { cursorPtsLft[i] *= pctWid; cursorPtsTop[i] *= pctHgt; - elTrans(pt, ceil(cursorPtsLft[i]), ceil(cursorPtsTop[i]), plotWidCss, plotHgtCss); + elTrans( + pt, + ceil(cursorPtsLft[i]), + ceil(cursorPtsTop[i]), + plotWidCss, + plotHgtCss + ); } } } - if (select.show && !shouldSetSelect && select.left >= 0 && select.width > 0) { - select.left *= pctWid; - select.width *= pctWid; - select.top *= pctHgt; + if ( + select.show && + !shouldSetSelect && + select.left >= 0 && + select.width > 0 + ) { + select.left *= pctWid; + select.width *= pctWid; + select.top *= pctHgt; select.height *= pctHgt; for (let prop in _hideProps) @@ -4797,16 +5047,16 @@ function uPlot(opts, data, then) { _plotHgtCss = plotHgtCss; } - fire("setSize"); + fire('setSize'); shouldSetSize = false; } if (fullWidCss > 0 && fullHgtCss > 0) { ctx.clearRect(0, 0, can.width, can.height); - fire("drawClear"); - drawOrder.forEach(fn => fn()); - fire("draw"); + fire('drawClear'); + drawOrder.forEach((fn) => fn()); + fire('draw'); } if (select.show && shouldSetSelect) { @@ -4828,7 +5078,7 @@ function uPlot(opts, data, then) { ready = true; self.status = 1; - fire("ready"); + fire('ready'); } viaAutoScaleX = false; @@ -4839,10 +5089,8 @@ function uPlot(opts, data, then) { self.redraw = (rebuildPaths, recalcAxes) => { shouldConvergeSize = recalcAxes || false; - if (rebuildPaths !== false) - _setScale(xScaleKey, scaleX.min, scaleX.max); - else - commit(); + if (rebuildPaths !== false) _setScale(xScaleKey, scaleX.min, scaleX.max); + else commit(); }; // redraw() => setScale('x', scales.x.min, scales.x.max); @@ -4864,20 +5112,24 @@ function uPlot(opts, data, then) { opts.max = _min; } - if (dataLen > 1 && opts.min != null && opts.max != null && opts.max - opts.min < 1e-16) - return; + if ( + dataLen > 1 && + opts.min != null && + opts.max != null && + opts.max - opts.min < 1e-16 + ) + return if (key == xScaleKey) { if (sc.distr == 2 && dataLen > 0) { opts.min = closestIdx(opts.min, data[0]); opts.max = closestIdx(opts.max, data[0]); - if (opts.min == opts.max) - opts.max++; + if (opts.min == opts.max) opts.max++; } } - // log("setScale()", arguments); + // log("setScale()", arguments); pendScales[key] = opts; @@ -4888,7 +5140,7 @@ function uPlot(opts, data, then) { self.setScale = setScale; -// INTERACTION + // INTERACTION let xCursor; let yCursor; @@ -4919,16 +5171,13 @@ function uPlot(opts, data, then) { let dragY = drag.y; if (cursor.show) { - if (cursor.x) - xCursor = placeDiv(CURSOR_X, over); - if (cursor.y) - yCursor = placeDiv(CURSOR_Y, over); + if (cursor.x) xCursor = placeDiv(CURSOR_X, over); + if (cursor.y) yCursor = placeDiv(CURSOR_Y, over); if (scaleX.ori == 0) { vCursor = xCursor; hCursor = yCursor; - } - else { + } else { vCursor = yCursor; hCursor = xCursor; } @@ -4937,27 +5186,31 @@ function uPlot(opts, data, then) { mouseTop1 = cursor.top; } - const select = self.select = assign({ - show: true, - over: true, - left: 0, - width: 0, - top: 0, - height: 0, - }, opts.select); + const select = (self.select = assign( + { + show: true, + over: true, + left: 0, + width: 0, + top: 0, + height: 0 + }, + opts.select + )); - const selectDiv = select.show ? placeDiv(SELECT, select.over ? over : under) : null; + const selectDiv = select.show + ? placeDiv(SELECT, select.over ? over : under) + : null; function setSelect(opts, _fire) { if (select.show) { for (let prop in opts) { select[prop] = opts[prop]; - if (prop in _hideProps) - setStylePx(selectDiv, prop, opts[prop]); + if (prop in _hideProps) setStylePx(selectDiv, prop, opts[prop]); } - _fire !== false && fire("setSelect"); + _fire !== false && fire('setSelect'); } } @@ -4967,8 +5220,7 @@ function uPlot(opts, data, then) { let s = series[i]; let label = showLegend ? legendRows[i] : null; - if (s.show) - label && remClass(label, OFF); + if (s.show) label && remClass(label, OFF); else { label && addClass(label, OFF); let pt = cursorOnePt ? cursorPts[0] : cursorPts[i]; @@ -4977,14 +5229,13 @@ function uPlot(opts, data, then) { } function _setScale(key, min, max) { - setScale(key, {min, max}); + setScale(key, { min, max }); } function setSeries(i, opts, _fire, _pub) { - // log("setSeries()", arguments); + // log("setSeries()", arguments); - if (opts.focus != null) - setFocus(i); + if (opts.focus != null) setFocus(i); if (opts.show != null) { series.forEach((s, si) => { @@ -4995,18 +5246,16 @@ function uPlot(opts, data, then) { if (mode == 2) { _setScale(s.facets[0].scale, null, null); _setScale(s.facets[1].scale, null, null); - } - else - _setScale(s.scale, null, null); + } else _setScale(s.scale, null, null); commit(); } }); } - _fire !== false && fire("setSeries", i, opts); + _fire !== false && fire('setSeries', i, opts); - _pub && pubSync("setSeries", self, i, opts); + _pub && pubSync('setSeries', self, i, opts); } self.setSeries = setSeries; @@ -5023,10 +5272,8 @@ function uPlot(opts, data, then) { } function delBand(bi) { - if (bi == null) - bands.length = 0; - else - bands.splice(bi, 1); + if (bi == null) bands.length = 0; + else bands.splice(bi, 1); } self.addBand = addBand; @@ -5036,8 +5283,7 @@ function uPlot(opts, data, then) { function setAlpha(i, value) { series[i].alpha = value; - if (cursor.show && cursorPts[i]) - cursorPts[i].style.opacity = value; + if (cursor.show && cursorPts[i]) cursorPts[i].style.opacity = value; if (showLegend && legendRows[i]) legendRows[i].style.opacity = value; @@ -5047,11 +5293,11 @@ function uPlot(opts, data, then) { let closestDist; let closestSeries; let focusedSeries; - const FOCUS_TRUE = {focus: true}; + const FOCUS_TRUE = { focus: true }; function setFocus(i) { if (i != focusedSeries) { - // log("setFocus()", arguments); + // log("setFocus()", arguments); let allFocused = i == null; @@ -5071,9 +5317,8 @@ function uPlot(opts, data, then) { } if (showLegend && cursorFocus) { - onMouse(mouseleave, legendTable, e => { - if (cursor._lock) - return; + onMouse(mouseleave, legendTable, (e) => { + if (cursor._lock) return setCursorEvent(e); @@ -5085,8 +5330,7 @@ function uPlot(opts, data, then) { function posToVal(pos, scale, can) { let sc = scales[scale]; - if (can) - pos = pos / pxRatio - (sc.ori == 1 ? plotTopCss : plotLftCss); + if (can) pos = pos / pxRatio - (sc.ori == 1 ? plotTopCss : plotLftCss); let dim = plotWidCss; @@ -5095,8 +5339,7 @@ function uPlot(opts, data, then) { pos = dim - pos; } - if (sc.dir == -1) - pos = dim - pos; + if (sc.dir == -1) pos = dim - pos; let _min = sc._min, _max = sc._max, @@ -5106,49 +5349,53 @@ function uPlot(opts, data, then) { let distr = sc.distr; - return ( - distr == 3 ? pow(10, sv) : - distr == 4 ? sinh(sv, sc.asinh) : - distr == 100 ? sc.bwd(sv) : - sv - ); + return distr == 3 + ? pow(10, sv) + : distr == 4 + ? sinh(sv, sc.asinh) + : distr == 100 + ? sc.bwd(sv) + : sv } function closestIdxFromXpos(pos, can) { let v = posToVal(pos, xScaleKey, can); - return closestIdx(v, data[0], i0, i1); + return closestIdx(v, data[0], i0, i1) } - self.valToIdx = val => closestIdx(val, data[0]); + self.valToIdx = (val) => closestIdx(val, data[0]); self.posToIdx = closestIdxFromXpos; self.posToVal = posToVal; - self.valToPos = (val, scale, can) => ( - scales[scale].ori == 0 ? - getHPos(val, scales[scale], - can ? plotWid : plotWidCss, - can ? plotLft : 0, - ) : - getVPos(val, scales[scale], - can ? plotHgt : plotHgtCss, - can ? plotTop : 0, - ) - ); + self.valToPos = (val, scale, can) => + scales[scale].ori == 0 + ? getHPos( + val, + scales[scale], + can ? plotWid : plotWidCss, + can ? plotLft : 0 + ) + : getVPos( + val, + scales[scale], + can ? plotHgt : plotHgtCss, + can ? plotTop : 0 + ); self.setCursor = (opts, _fire, _pub) => { mouseLeft1 = opts.left; mouseTop1 = opts.top; - // assign(cursor, opts); + // assign(cursor, opts); updateCursor(null, _fire, _pub); }; function setSelH(off, dim) { - setStylePx(selectDiv, LEFT, select.left = off); - setStylePx(selectDiv, WIDTH, select.width = dim); + setStylePx(selectDiv, LEFT, (select.left = off)); + setStylePx(selectDiv, WIDTH, (select.width = dim)); } function setSelV(off, dim) { - setStylePx(selectDiv, TOP, select.top = off); - setStylePx(selectDiv, HEIGHT, select.height = dim); + setStylePx(selectDiv, TOP, (select.top = off)); + setStylePx(selectDiv, HEIGHT, (select.height = dim)); } let setSelX = scaleX.ori == 0 ? setSelH : setSelV; @@ -5157,8 +5404,7 @@ function uPlot(opts, data, then) { function syncLegend() { if (showLegend && legend.live) { for (let i = mode == 2 ? 1 : 0; i < series.length; i++) { - if (i == 0 && multiValLegend) - continue; + if (i == 0 && multiValLegend) continue let vals = legend.values[i]; @@ -5176,16 +5422,14 @@ function uPlot(opts, data, then) { opts.idxs.forEach((didx, sidx) => { activeIdxs[sidx] = didx; }); - } - else if (!isUndef(opts.idx)) - activeIdxs.fill(opts.idx); + } else if (!isUndef(opts.idx)) activeIdxs.fill(opts.idx); legend.idx = activeIdxs[0]; } if (showLegend && legend.live) { for (let sidx = 0; sidx < series.length; sidx++) { - if (sidx > 0 || mode == 1 && !multiValLegend) + if (sidx > 0 || (mode == 1 && !multiValLegend)) setLegendValues(sidx, activeIdxs[sidx]); } @@ -5194,7 +5438,7 @@ function uPlot(opts, data, then) { shouldSetLegend = false; - _fire !== false && fire("setLegend"); + _fire !== false && fire('setLegend'); } self.setLegend = setLegend; @@ -5207,27 +5451,35 @@ function uPlot(opts, data, then) { if (multiValLegend) val = s.values(self, sidx, idx) ?? NULL_LEGEND_VALUES; else { - val = s.value(self, idx == null ? null : src[idx], sidx, idx); - val = val == null ? NULL_LEGEND_VALUES : {_: val}; + val = s.value( + self, + idx == null ? null : src[idx], + sidx, + idx, + fmtNum + ); + val = val == null ? NULL_LEGEND_VALUES : { _: val }; } legend.values[sidx] = val; } function updateCursor(src, _fire, _pub) { - // ts == null && log("updateCursor()", arguments); + // ts == null && log("updateCursor()", arguments); rawMouseLeft1 = mouseLeft1; - rawMouseTop1 = mouseTop1; + rawMouseTop1 = mouseTop1 - [mouseLeft1, mouseTop1] = cursor.move(self, mouseLeft1, mouseTop1); + ;[mouseLeft1, mouseTop1] = cursor.move(self, mouseLeft1, mouseTop1); cursor.left = mouseLeft1; cursor.top = mouseTop1; if (cursor.show) { - vCursor && elTrans(vCursor, round(mouseLeft1), 0, plotWidCss, plotHgtCss); - hCursor && elTrans(hCursor, 0, round(mouseTop1), plotWidCss, plotHgtCss); + vCursor && + elTrans(vCursor, round(mouseLeft1), 0, plotWidCss, plotHgtCss); + hCursor && + elTrans(hCursor, 0, round(mouseTop1), plotWidCss, plotHgtCss); } let idx; @@ -5253,15 +5505,19 @@ function uPlot(opts, data, then) { } if (cursorFocus) - setSeries(null, FOCUS_TRUE, true, src == null && syncOpts.setSeries); + setSeries( + null, + FOCUS_TRUE, + true, + src == null && syncOpts.setSeries + ); if (legend.live) { activeIdxs.fill(idx); shouldSetLegend = true; } - } - else { - // let pctY = 1 - (y / rect.height); + } else { + // let pctY = 1 - (y / rect.height); let mouseXPos, valAtPosX, xPos; @@ -5284,25 +5540,56 @@ function uPlot(opts, data, then) { for (let i = mode == 2 ? 1 : 0; i < series.length; i++) { let s = series[i]; - let idx1 = activeIdxs[i]; - let yVal1 = idx1 == null ? null : (mode == 1 ? data[i][idx1] : data[i][1][idx1]); - - let idx2 = cursor.dataIdx(self, i, idx, valAtPosX); - let yVal2 = idx2 == null ? null : (mode == 1 ? data[i][idx2] : data[i][1][idx2]); - - shouldSetLegend = shouldSetLegend || yVal2 != yVal1 || idx2 != idx1; + let idx1 = activeIdxs[i]; + let yVal1 = + idx1 == null + ? null + : mode == 1 + ? data[i][idx1] + : data[i][1][idx1]; + + let idx2 = cursor.dataIdx(self, i, idx, valAtPosX); + let yVal2 = + idx2 == null + ? null + : mode == 1 + ? data[i][idx2] + : data[i][1][idx2]; + + shouldSetLegend = + shouldSetLegend || yVal2 != yVal1 || idx2 != idx1; activeIdxs[i] = idx2; - let xPos2 = idx2 == idx ? xPos : valToPosX(mode == 1 ? data[0][idx2] : data[i][0][idx2], scaleX, xDim, 0); + let xPos2 = + idx2 == idx + ? xPos + : valToPosX( + mode == 1 ? data[0][idx2] : data[i][0][idx2], + scaleX, + xDim, + 0 + ); if (i > 0 && s.show) { // this doesnt really work for state timeline, heatmap, status history (where the value maps to color, not y coords) - let yPos = yVal2 == null ? -10 : valToPosY(yVal2, mode == 1 ? scales[s.scale] : scales[s.facets[1].scale], yDim, 0); + let yPos = + yVal2 == null + ? -10 + : valToPosY( + yVal2, + mode == 1 + ? scales[s.scale] + : scales[s.facets[1].scale], + yDim, + 0 + ); if (cursorFocus && yVal2 != null) { let mouseYPos = scaleX.ori == 1 ? mouseLeft1 : mouseTop1; - let dist = abs(focus.dist(self, i, idx2, yPos, mouseYPos)); + let dist = abs( + focus.dist(self, i, idx2, yPos, mouseYPos) + ); if (dist < closestDist) { let bias = focus.bias; @@ -5310,21 +5597,25 @@ function uPlot(opts, data, then) { if (bias != 0) { let mouseYVal = posToVal(mouseYPos, s.scale); - let seriesYValSign = yVal2 >= 0 ? 1 : -1; - let mouseYValSign = mouseYVal >= 0 ? 1 : -1; + let seriesYValSign = yVal2 >= 0 ? 1 : -1; + let mouseYValSign = mouseYVal >= 0 ? 1 : -1; // with a focus bias, we will never cross zero when prox testing // it's either closest towards zero, or closest away from zero - if (mouseYValSign == seriesYValSign && ( - mouseYValSign == 1 ? - (bias == 1 ? yVal2 >= mouseYVal : yVal2 <= mouseYVal) : // >= 0 - (bias == 1 ? yVal2 <= mouseYVal : yVal2 >= mouseYVal) // < 0 - )) { + if ( + mouseYValSign == seriesYValSign && + (mouseYValSign == 1 + ? bias == 1 + ? yVal2 >= mouseYVal + : yVal2 <= mouseYVal // >= 0 + : bias == 1 + ? yVal2 <= mouseYVal + : yVal2 >= mouseYVal) // < 0 + ) { closestDist = dist; closestSeries = i; } - } - else { + } else { closestDist = dist; closestSeries = i; } @@ -5337,14 +5628,17 @@ function uPlot(opts, data, then) { if (scaleX.ori == 0) { hPos = xPos2; vPos = yPos; - } - else { + } else { hPos = yPos; vPos = xPos2; } - let ptWid, ptHgt, ptLft, ptTop, - ptStroke, ptFill, + let ptWid, + ptHgt, + ptLft, + ptTop, + ptStroke, + ptFill, centered = true, getBBox = points.bbox; @@ -5357,8 +5651,7 @@ function uPlot(opts, data, then) { ptTop = bbox.top; ptWid = bbox.width; ptHgt = bbox.height; - } - else { + } else { ptLft = hPos; ptTop = vPos; ptWid = ptHgt = points.size(self, i); @@ -5368,7 +5661,10 @@ function uPlot(opts, data, then) { ptStroke = points.stroke(self, i); if (cursorOnePt) { - if (i == closestSeries && closestDist <= focus.prox) { + if ( + i == closestSeries && + closestDist <= focus.prox + ) { _ptLft = ptLft; _ptTop = ptTop; _ptWid = ptWid; @@ -5377,8 +5673,7 @@ function uPlot(opts, data, then) { _ptFill = ptFill; _ptStroke = ptStroke; } - } - else { + } else { let pt = cursorPts[i]; if (pt != null) { @@ -5387,7 +5682,13 @@ function uPlot(opts, data, then) { elSize(pt, ptWid, ptHgt, centered); elColor(pt, ptFill, ptStroke); - elTrans(pt, ceil(ptLft), ceil(ptTop), plotWidCss, plotHgtCss); + elTrans( + pt, + ceil(ptLft), + ceil(ptTop), + plotWidCss, + plotHgtCss + ); } } } @@ -5401,7 +5702,10 @@ function uPlot(opts, data, then) { let p = focus.prox; - let focusChanged = focusedSeries == null ? closestDist <= p : (closestDist > p || closestSeries != focusedSeries); + let focusChanged = + focusedSeries == null + ? closestDist <= p + : closestDist > p || closestSeries != focusedSeries; if (shouldSetLegend || focusChanged) { let pt = cursorPts[0]; @@ -5411,7 +5715,13 @@ function uPlot(opts, data, then) { elSize(pt, _ptWid, _ptHgt, _centered); elColor(pt, _ptFill, _ptStroke); - elTrans(pt, ceil(_ptLft), ceil(_ptTop), plotWidCss, plotHgtCss); + elTrans( + pt, + ceil(_ptLft), + ceil(_ptTop), + plotWidCss, + plotHgtCss + ); } } } @@ -5443,46 +5753,47 @@ function uPlot(opts, data, then) { if (sori == 0) { sOff = left; sDim = width; - } - else { + } else { sOff = top; sDim = height; } sc = scales[xKey]; - a = valToPosX(sPosToVal(sOff, xKeySrc), sc, xDim, 0); - b = valToPosX(sPosToVal(sOff + sDim, xKeySrc), sc, xDim, 0); + a = valToPosX(sPosToVal(sOff, xKeySrc), sc, xDim, 0); + b = valToPosX( + sPosToVal(sOff + sDim, xKeySrc), + sc, + xDim, + 0 + ); - setSelX(min(a,b), abs(b-a)); - } - else - setSelX(0, xDim); + setSelX(min(a, b), abs(b - a)); + } else setSelX(0, xDim); if (matchingY && dragY) { if (sori == 1) { sOff = left; sDim = width; - } - else { + } else { sOff = top; sDim = height; } sc = scales[yKey]; - a = valToPosY(sPosToVal(sOff, yKeySrc), sc, yDim, 0); - b = valToPosY(sPosToVal(sOff + sDim, yKeySrc), sc, yDim, 0); + a = valToPosY(sPosToVal(sOff, yKeySrc), sc, yDim, 0); + b = valToPosY( + sPosToVal(sOff + sDim, yKeySrc), + sc, + yDim, + 0 + ); - setSelY(min(a,b), abs(b-a)); - } - else - setSelY(0, yDim); - } - else - hideSelect(); - } - else { + setSelY(min(a, b), abs(b - a)); + } else setSelY(0, yDim); + } else hideSelect(); + } else { let rawDX = abs(rawMouseLeft1 - rawMouseLeft0); let rawDY = abs(rawMouseTop1 - rawMouseTop0); @@ -5505,14 +5816,11 @@ function uPlot(opts, data, then) { // force unidirectionality when both are under uni limit if (!dragX && !dragY) { - if (rawDY > rawDX) - dragY = true; - else - dragX = true; + if (rawDY > rawDX) dragY = true; + else dragX = true; } } - } - else if (drag.x && drag.y && (dragX || dragY)) + } else if (drag.x && drag.y && (dragX || dragY)) // if omni with no uni then both dragX / dragY should be true if either is true dragX = dragY = true; @@ -5522,32 +5830,28 @@ function uPlot(opts, data, then) { if (scaleX.ori == 0) { p0 = mouseLeft0; p1 = mouseLeft1; - } - else { + } else { p0 = mouseTop0; p1 = mouseTop1; } setSelX(min(p0, p1), abs(p1 - p0)); - if (!dragY) - setSelY(0, yDim); + if (!dragY) setSelY(0, yDim); } if (dragY) { if (scaleX.ori == 1) { p0 = mouseLeft0; p1 = mouseLeft1; - } - else { + } else { p0 = mouseTop0; p1 = mouseTop1; } setSelY(min(p0, p1), abs(p1 - p0)); - if (!dragX) - setSelX(0, xDim); + if (!dragX) setSelX(0, xDim); } // the drag didn't pass the dist requirement @@ -5566,11 +5870,31 @@ function uPlot(opts, data, then) { if (syncKey != null) { let [xSyncKey, ySyncKey] = syncOpts.scales; - syncOpts.values[0] = xSyncKey != null ? posToVal(scaleX.ori == 0 ? mouseLeft1 : mouseTop1, xSyncKey) : null; - syncOpts.values[1] = ySyncKey != null ? posToVal(scaleX.ori == 1 ? mouseLeft1 : mouseTop1, ySyncKey) : null; + syncOpts.values[0] = + xSyncKey != null + ? posToVal( + scaleX.ori == 0 ? mouseLeft1 : mouseTop1, + xSyncKey + ) + : null; + syncOpts.values[1] = + ySyncKey != null + ? posToVal( + scaleX.ori == 1 ? mouseLeft1 : mouseTop1, + ySyncKey + ) + : null; } - pubSync(mousemove, self, mouseLeft1, mouseTop1, plotWidCss, plotHgtCss, idx); + pubSync( + mousemove, + self, + mouseLeft1, + mouseTop1, + plotWidCss, + plotHgtCss, + idx + ); } if (cursorFocus) { @@ -5580,8 +5904,7 @@ function uPlot(opts, data, then) { if (focusedSeries == null) { if (closestDist <= p) setSeries(closestSeries, FOCUS_TRUE, true, shouldPub); - } - else { + } else { if (closestDist > p) setSeries(null, FOCUS_TRUE, true, shouldPub); else if (closestSeries != focusedSeries) @@ -5595,32 +5918,29 @@ function uPlot(opts, data, then) { setLegend(); } - _fire !== false && fire("setCursor"); + _fire !== false && fire('setCursor'); } let rect = null; Object.defineProperty(self, 'rect', { get() { - if (rect == null) - syncRect(false); + if (rect == null) syncRect(false); - return rect; - }, + return rect + } }); function syncRect(defer = false) { - if (defer) - rect = null; + if (defer) rect = null; else { rect = over.getBoundingClientRect(); - fire("syncRect", rect); + fire('syncRect', rect); } } function mouseMove(e, src, _l, _t, _w, _h, _i) { - if (cursor._lock) - return; + if (cursor._lock) return // Chrome on Windows has a bug which triggers a stray mousemove event after an initial mousedown event // when clicking into a plot as part of re-focusing the browser window. @@ -5628,31 +5948,27 @@ function uPlot(opts, data, then) { // However, on touch-only devices Chrome-based browsers trigger a 0-distance mousemove before mousedown // so we don't ignore it when mousedown has set the dragging flag if (dragging && e != null && e.movementX == 0 && e.movementY == 0) - return; + return cacheMouse(e, src, _l, _t, _w, _h, _i, false, e != null); - if (e != null) - updateCursor(null, true, true); - else - updateCursor(src, true, false); + if (e != null) updateCursor(null, true, true); + else updateCursor(src, true, false); } function cacheMouse(e, src, _l, _t, _w, _h, _i, initial, snap) { - if (rect == null) - syncRect(false); + if (rect == null) syncRect(false); setCursorEvent(e); if (e != null) { _l = e.clientX - rect.left; _t = e.clientY - rect.top; - } - else { + } else { if (_l < 0 || _t < 0) { mouseLeft1 = -10; mouseTop1 = -10; - return; + return } let [xKey, yKey] = syncOpts.scales; @@ -5672,14 +5988,16 @@ function uPlot(opts, data, then) { _yPos = rotSrc ? _l : _t; if (xKeySrc != null) - _l = matchXKeys(xKey, xKeySrc) ? getPos(xValSrc, scales[xKey], xDim, 0) : -10; - else - _l = xDim * (_xPos/_xDim); + _l = matchXKeys(xKey, xKeySrc) + ? getPos(xValSrc, scales[xKey], xDim, 0) + : -10; + else _l = xDim * (_xPos / _xDim); if (yKeySrc != null) - _t = matchYKeys(yKey, yKeySrc) ? getPos(yValSrc, scales[yKey], yDim, 0) : -10; - else - _t = yDim * (_yPos/_yDim); + _t = matchYKeys(yKey, yKeySrc) + ? getPos(yValSrc, scales[yKey], yDim, 0) + : -10; + else _t = yDim * (_yPos / _yDim); if (scaleX.ori == 1) { let __l = _l; @@ -5689,20 +6007,17 @@ function uPlot(opts, data, then) { } if (snap) { - if (_l <= 1 || _l >= plotWidCss - 1) - _l = incrRound(_l, plotWidCss); + if (_l <= 1 || _l >= plotWidCss - 1) _l = incrRound(_l, plotWidCss); - if (_t <= 1 || _t >= plotHgtCss - 1) - _t = incrRound(_t, plotHgtCss); + if (_t <= 1 || _t >= plotHgtCss - 1) _t = incrRound(_t, plotHgtCss); } if (initial) { rawMouseLeft0 = _l; - rawMouseTop0 = _t; + rawMouseTop0 = _t - [mouseLeft0, mouseTop0] = cursor.move(self, _l, _t); - } - else { + ;[mouseLeft0, mouseTop0] = cursor.move(self, _l, _t); + } else { mouseLeft1 = _l; mouseTop1 = _t; } @@ -5712,7 +6027,7 @@ function uPlot(opts, data, then) { width: 0, height: 0, left: 0, - top: 0, + top: 0 }; function hideSelect() { @@ -5732,14 +6047,22 @@ function uPlot(opts, data, then) { if (e != null) { onMouse(mouseup, doc, mouseUp, false); - pubSync(mousedown, self, mouseLeft0, mouseTop0, plotWidCss, plotHgtCss, null); + pubSync( + mousedown, + self, + mouseLeft0, + mouseTop0, + plotWidCss, + plotHgtCss, + null + ); } let { left, top, width, height } = select; - downSelectLeft = left; - downSelectTop = top; - downSelectWidth = width; + downSelectLeft = left; + downSelectTop = top; + downSelectWidth = width; downSelectHeight = height; hideSelect(); @@ -5753,20 +6076,19 @@ function uPlot(opts, data, then) { let { left, top, width, height } = select; let hasSelect = width > 0 || height > 0; - let chgSelect = ( - downSelectLeft != left || - downSelectTop != top || - downSelectWidth != width || - downSelectHeight != height - ); + let chgSelect = + downSelectLeft != left || + downSelectTop != top || + downSelectWidth != width || + downSelectHeight != height; hasSelect && chgSelect && setSelect(select); if (drag.setScale && hasSelect && chgSelect) { - // if (syncKey != null) { - // dragX = drag.x; - // dragY = drag.y; - // } + // if (syncKey != null) { + // dragX = drag.x; + // dragY = drag.y; + // } let xOff = left, xDim = width, @@ -5774,14 +6096,12 @@ function uPlot(opts, data, then) { yDim = height; if (scaleX.ori == 1) { - xOff = top, - xDim = height, - yOff = left, - yDim = width; +(xOff = top), (xDim = height), (yOff = left), (yDim = width); } if (dragX) { - _setScale(xScaleKey, + _setScale( + xScaleKey, posToVal(xOff, xScaleKey), posToVal(xOff + xDim, xScaleKey) ); @@ -5792,7 +6112,8 @@ function uPlot(opts, data, then) { let sc = scales[k]; if (k != xScaleKey && sc.from == null && sc.min != inf) { - _setScale(k, + _setScale( + k, posToVal(yOff + yDim, k), posToVal(yOff, k) ); @@ -5801,21 +6122,27 @@ function uPlot(opts, data, then) { } hideSelect(); - } - else if (cursor.lock) { + } else if (cursor.lock) { cursor._lock = !cursor._lock; updateCursor(null, true, false); } if (e != null) { offMouse(mouseup, doc); - pubSync(mouseup, self, mouseLeft1, mouseTop1, plotWidCss, plotHgtCss, null); + pubSync( + mouseup, + self, + mouseLeft1, + mouseTop1, + plotWidCss, + plotHgtCss, + null + ); } } function mouseLeave(e, src, _l, _t, _w, _h, _i) { - if (cursor._lock) - return; + if (cursor._lock) return setCursorEvent(e); @@ -5832,16 +6159,18 @@ function uPlot(opts, data, then) { if (scaleX.ori == 0) { dragH = dragX; dragV = dragY; - } - else { + } else { dragH = dragY; dragV = dragX; } if (dragH && dragV) { // maybe omni corner snap - snapH = mouseLeft1 <= snapProx || mouseLeft1 >= plotWidCss - snapProx; - snapV = mouseTop1 <= snapProx || mouseTop1 >= plotHgtCss - snapProx; + snapH = + mouseLeft1 <= snapProx || + mouseLeft1 >= plotWidCss - snapProx; + snapV = + mouseTop1 <= snapProx || mouseTop1 >= plotHgtCss - snapProx; } if (dragH && snapH) @@ -5861,13 +6190,11 @@ function uPlot(opts, data, then) { // passing a non-null timestamp to force sync/mousemove event updateCursor(null, true, true); - if (_dragging) - dragging = _dragging; + if (_dragging) dragging = _dragging; } function dblClick(e, src, _l, _t, _w, _h, _i) { - if (cursor._lock) - return; + if (cursor._lock) return setCursorEvent(e); @@ -5876,7 +6203,15 @@ function uPlot(opts, data, then) { hideSelect(); if (e != null) - pubSync(dblclick, self, mouseLeft1, mouseTop1, plotWidCss, plotHgtCss, null); + pubSync( + dblclick, + self, + mouseLeft1, + mouseTop1, + plotWidCss, + plotHgtCss, + null + ); } function syncPxRatio() { @@ -5893,16 +6228,16 @@ function uPlot(opts, data, then) { events.mousemove = mouseMove; events.mouseup = mouseUp; events.dblclick = dblClick; - events["setSeries"] = (e, src, idx, opts) => { + events['setSeries'] = (e, src, idx, opts) => { let seriesIdxMatcher = syncOpts.match[2]; idx = seriesIdxMatcher(self, src, idx); idx != -1 && setSeries(idx, opts, true, false); }; if (cursor.show) { - onMouse(mousedown, over, mouseDown); - onMouse(mousemove, over, mouseMove); - onMouse(mouseenter, over, e => { + onMouse(mousedown, over, mouseDown); + onMouse(mousemove, over, mouseMove); + onMouse(mouseenter, over, (e) => { setCursorEvent(e); syncRect(false); }); @@ -5916,41 +6251,41 @@ function uPlot(opts, data, then) { } // external on/off - const hooks = self.hooks = opts.hooks || {}; + const hooks = (self.hooks = opts.hooks || {}); function fire(evName, a1, a2) { - if (deferHooks) - hooksQueue.push([evName, a1, a2]); + if (deferHooks) hooksQueue.push([evName, a1, a2]); else { if (evName in hooks) { - hooks[evName].forEach(fn => { + hooks[evName].forEach((fn) => { fn.call(null, self, a1, a2); }); } } } - - (opts.plugins || []).forEach(p => { +(opts.plugins || []).forEach((p) => { for (let evName in p.hooks) hooks[evName] = (hooks[evName] || []).concat(p.hooks[evName]); }); const seriesIdxMatcher = (self, src, srcSeriesIdx) => srcSeriesIdx; - const syncOpts = assign({ - key: null, - setSeries: false, - filters: { - pub: retTrue, - sub: retTrue, + const syncOpts = assign( + { + key: null, + setSeries: false, + filters: { + pub: retTrue, + sub: retTrue + }, + scales: [xScaleKey, series[1] ? series[1].scale : null], + match: [retEq, retEq, seriesIdxMatcher], + values: [null, null] }, - scales: [xScaleKey, series[1] ? series[1].scale : null], - match: [retEq, retEq, seriesIdxMatcher], - values: [null, null], - }, cursor.sync); + cursor.sync + ); - if (syncOpts.match.length == 2) - syncOpts.match.push(seriesIdxMatcher); + if (syncOpts.match.length == 2) syncOpts.match.push(seriesIdxMatcher); cursor.sync = syncOpts; @@ -5979,20 +6314,18 @@ function uPlot(opts, data, then) { off(dppxchange, win, syncPxRatio); root.remove(); legendTable?.remove(); // in case mounted outside of root - fire("destroy"); + fire('destroy'); } self.destroy = destroy; function _init() { - fire("init", opts, data); + fire('init', opts, data); setData(data || opts.data, false); - if (pendScales[xScaleKey]) - setScale(xScaleKey, pendScales[xScaleKey]); - else - autoScaleX(); + if (pendScales[xScaleKey]) setScale(xScaleKey, pendScales[xScaleKey]); + else autoScaleX(); shouldSetSelect = select.show && (select.width > 0 || select.height > 0); shouldSetCursor = shouldSetLegend = true; @@ -6008,22 +6341,17 @@ function uPlot(opts, data, then) { if (then instanceof HTMLElement) { then.appendChild(root); _init(); - } - else - then(self, _init); - } - else - _init(); + } else then(self, _init); + } else _init(); - return self; + return self } uPlot.assign = assign; -uPlot.fmtNum = fmtNum; uPlot.rangeNum = rangeNum; uPlot.rangeLog = rangeLog; uPlot.rangeAsinh = rangeAsinh; -uPlot.orient = orient; +uPlot.orient = orient; uPlot.pxRatio = pxRatio; { @@ -6031,8 +6359,7 @@ uPlot.pxRatio = pxRatio; } { - uPlot.fmtDate = fmtDate; - uPlot.tzDate = tzDate; + uPlot.tzDate = tzDate; } uPlot.sync = _sync; @@ -6041,14 +6368,14 @@ uPlot.sync = _sync; uPlot.addGap = addGap; uPlot.clipGaps = clipGaps; - let paths = uPlot.paths = { - points, - }; + let paths = (uPlot.paths = { + points + }); - (paths.linear = linear); + (paths.linear = linear); (paths.stepped = stepped); - (paths.bars = bars); - (paths.spline = monotoneCubic); + (paths.bars = bars); + (paths.spline = monotoneCubic); } module.exports = uPlot; diff --git a/dist/uPlot.d.ts b/dist/uPlot.d.ts index 75e73e8d..86207b55 100644 --- a/dist/uPlot.d.ts +++ b/dist/uPlot.d.ts @@ -60,6 +60,9 @@ declare class uPlot { /** .u-under dom element */ readonly under: HTMLDivElement; + + /* + readonly locale: string; /** clears and redraws the canvas. if rebuildPaths = false, uses cached series' Path2D objects */ redraw(rebuildPaths?: boolean, recalcAxes?: boolean): void; @@ -138,11 +141,11 @@ declare class uPlot { /** re-ranges a given min/max outwards to nearest 10% of given min/max's magnitudes, unless fullMags = true */ static rangeAsinh(min: number, max: number, base: uPlot.Scale.LogBase, fullMags: boolean): uPlot.Range.MinMax; - /** default numeric formatter using browser's locale: new Intl.NumberFormat(navigator.language).format */ + /** default numeric formatter using browser's locale: new Intl.NumberFormat(defaultLocale).format */ static fmtNum(val: number): string; - /** creates an efficient formatter for Date objects from a template string, e.g. {YYYY}-{MM}-{DD} */ - static fmtDate(tpl: string, names?: uPlot.DateNames): (date: Date) => string; + /** default DateTime formatter using browser's locale: new Intl.DateTimeFormat(defaultLocale, opts).format */ + static fmtDate(opts: string, locale?: string): (date: Date) => string; /** converts a Date into new Date that's time-adjusted for the given IANA Time Zone Name */ static tzDate(date: Date, tzName: string): Date; @@ -222,19 +225,6 @@ declare namespace uPlot { ...yValues: ((number | null | undefined)[] | TypedArray)[], ] - export interface DateNames { - /** long month names */ - MMMM: string[]; - - /** short month names */ - MMM: string[]; - - /** long weekday names (0: Sunday) */ - WWWW: string[]; - - /** short weekday names (0: Sun) */ - WWW: string[]; - } export namespace Range { export type MinMax = [min: number | null, max: number | null]; diff --git a/dist/uPlot.esm.js b/dist/uPlot.esm.js index f3072f89..36708db8 100644 --- a/dist/uPlot.esm.js +++ b/dist/uPlot.esm.js @@ -9,168 +9,7 @@ const FEAT_TIME = true; -const pre = "u-"; - -const UPLOT = "uplot"; -const ORI_HZ = pre + "hz"; -const ORI_VT = pre + "vt"; -const TITLE = pre + "title"; -const WRAP = pre + "wrap"; -const UNDER = pre + "under"; -const OVER = pre + "over"; -const AXIS = pre + "axis"; -const OFF = pre + "off"; -const SELECT = pre + "select"; -const CURSOR_X = pre + "cursor-x"; -const CURSOR_Y = pre + "cursor-y"; -const CURSOR_PT = pre + "cursor-pt"; -const LEGEND = pre + "legend"; -const LEGEND_LIVE = pre + "live"; -const LEGEND_INLINE = pre + "inline"; -const LEGEND_SERIES = pre + "series"; -const LEGEND_MARKER = pre + "marker"; -const LEGEND_LABEL = pre + "label"; -const LEGEND_VALUE = pre + "value"; - -const WIDTH = "width"; -const HEIGHT = "height"; -const TOP = "top"; -const BOTTOM = "bottom"; -const LEFT = "left"; -const RIGHT = "right"; -const hexBlack = "#000"; -const transparent = hexBlack + "0"; - -const mousemove = "mousemove"; -const mousedown = "mousedown"; -const mouseup = "mouseup"; -const mouseenter = "mouseenter"; -const mouseleave = "mouseleave"; -const dblclick = "dblclick"; -const resize = "resize"; -const scroll = "scroll"; - -const change = "change"; -const dppxchange = "dppxchange"; - -const LEGEND_DISP = "--"; - -const domEnv = typeof window != 'undefined'; - -const doc = domEnv ? document : null; -const win = domEnv ? window : null; -const nav = domEnv ? navigator : null; - -let pxRatio; - -//export const canHover = domEnv && !win.matchMedia('(hover: none)').matches; - -let query; - -function setPxRatio() { - let _pxRatio = devicePixelRatio; - - // during print preview, Chrome fires off these dppx queries even without changes - if (pxRatio != _pxRatio) { - pxRatio = _pxRatio; - - query && off(change, query, setPxRatio); - query = matchMedia(`(min-resolution: ${pxRatio - 0.001}dppx) and (max-resolution: ${pxRatio + 0.001}dppx)`); - on(change, query, setPxRatio); - - win.dispatchEvent(new CustomEvent(dppxchange)); - } -} - -function addClass(el, c) { - if (c != null) { - let cl = el.classList; - !cl.contains(c) && cl.add(c); - } -} - -function remClass(el, c) { - let cl = el.classList; - cl.contains(c) && cl.remove(c); -} - -function setStylePx(el, name, value) { - el.style[name] = value + "px"; -} - -function placeTag(tag, cls, targ, refEl) { - let el = doc.createElement(tag); - - if (cls != null) - addClass(el, cls); - - if (targ != null) - targ.insertBefore(el, refEl); - - return el; -} - -function placeDiv(cls, targ) { - return placeTag("div", cls, targ); -} - -const xformCache = new WeakMap(); - -function elTrans(el, xPos, yPos, xMax, yMax) { - let xform = "translate(" + xPos + "px," + yPos + "px)"; - let xformOld = xformCache.get(el); - - if (xform != xformOld) { - el.style.transform = xform; - xformCache.set(el, xform); - - if (xPos < 0 || yPos < 0 || xPos > xMax || yPos > yMax) - addClass(el, OFF); - else - remClass(el, OFF); - } -} - -const colorCache = new WeakMap(); - -function elColor(el, background, borderColor) { - let newColor = background + borderColor; - let oldColor = colorCache.get(el); - - if (newColor != oldColor) { - colorCache.set(el, newColor); - el.style.background = background; - el.style.borderColor = borderColor; - } -} - -const sizeCache = new WeakMap(); - -function elSize(el, newWid, newHgt, centered) { - let newSize = newWid + "" + newHgt; - let oldSize = sizeCache.get(el); - - if (newSize != oldSize) { - sizeCache.set(el, newSize); - el.style.height = newHgt + "px"; - el.style.width = newWid + "px"; - el.style.marginLeft = centered ? -newWid/2 + "px" : 0; - el.style.marginTop = centered ? -newHgt/2 + "px" : 0; - } -} - -const evOpts = {passive: true}; -const evOpts2 = {...evOpts, capture: true}; - -function on(ev, el, cb, capt) { - el.addEventListener(ev, cb, capt ? evOpts2 : evOpts); -} - -function off(ev, el, cb, capt) { - el.removeEventListener(ev, cb, evOpts); -} - -domEnv && setPxRatio(); +const browserLocale = new Intl.DateTimeFormat().resolvedOptions().locale; // binary search for index of closest value function closestIdx(num, arr, lo, hi) { @@ -429,10 +268,6 @@ function _rangeNum(_min, _max, cfg) { return [minLim, maxLim]; } -// alternative: https://stackoverflow.com/a/2254896 -const numFormatter = new Intl.NumberFormat(domEnv ? nav.language : 'en-US'); -const fmtNum = val => numFormatter.format(val); - const M = Math; const PI = M.PI; @@ -818,130 +653,168 @@ function isAsc(vals, samples = 100) { return true; } -const months = [ - "January", - "February", - "March", - "April", - "May", - "June", - "July", - "August", - "September", - "October", - "November", - "December", -]; - -const days = [ - "Sunday", - "Monday", - "Tuesday", - "Wednesday", - "Thursday", - "Friday", - "Saturday", -]; - -function slice3(str) { - return str.slice(0, 3); +const WIDTH = "width"; +const HEIGHT = "height"; +const TOP = "top"; +const BOTTOM = "bottom"; +const LEFT = "left"; +const RIGHT = "right"; +const hexBlack = "#000"; +const transparent = hexBlack + "0"; + +const mousemove = "mousemove"; +const mousedown = "mousedown"; +const mouseup = "mouseup"; +const mouseenter = "mouseenter"; +const mouseleave = "mouseleave"; +const dblclick = "dblclick"; +const resize = "resize"; +const scroll = "scroll"; + +const change = "change"; +const dppxchange = "dppxchange"; + +const LEGEND_DISP = "--"; + +const pre = "u-"; + +const UPLOT = "uplot"; +const ORI_HZ = pre + "hz"; +const ORI_VT = pre + "vt"; +const TITLE = pre + "title"; +const WRAP = pre + "wrap"; +const UNDER = pre + "under"; +const OVER = pre + "over"; +const AXIS = pre + "axis"; +const OFF = pre + "off"; +const SELECT = pre + "select"; +const CURSOR_X = pre + "cursor-x"; +const CURSOR_Y = pre + "cursor-y"; +const CURSOR_PT = pre + "cursor-pt"; +const LEGEND = pre + "legend"; +const LEGEND_LIVE = pre + "live"; +const LEGEND_INLINE = pre + "inline"; +const LEGEND_SERIES = pre + "series"; +const LEGEND_MARKER = pre + "marker"; +const LEGEND_LABEL = pre + "label"; +const LEGEND_VALUE = pre + "value"; + +const domEnv = typeof window != 'undefined'; + +const doc = domEnv ? document : null; +const win = domEnv ? window : null; + +let pxRatio; + +//export const canHover = domEnv && !win.matchMedia('(hover: none)').matches; + +let query; + +function setPxRatio() { + let _pxRatio = devicePixelRatio; + + // during print preview, Chrome fires off these dppx queries even without changes + if (pxRatio != _pxRatio) { + pxRatio = _pxRatio; + + query && off(change, query, setPxRatio); + query = matchMedia(`(min-resolution: ${pxRatio - 0.001}dppx) and (max-resolution: ${pxRatio + 0.001}dppx)`); + on(change, query, setPxRatio); + + win.dispatchEvent(new CustomEvent(dppxchange)); + } +} + +function addClass(el, c) { + if (c != null) { + let cl = el.classList; + !cl.contains(c) && cl.add(c); + } +} + +function remClass(el, c) { + let cl = el.classList; + cl.contains(c) && cl.remove(c); } -const days3 = days.map(slice3); +function setStylePx(el, name, value) { + el.style[name] = value + "px"; +} -const months3 = months.map(slice3); +function placeTag(tag, cls, targ, refEl) { + let el = doc.createElement(tag); -const engNames = { - MMMM: months, - MMM: months3, - WWWW: days, - WWW: days3, -}; + if (cls != null) + addClass(el, cls); + + if (targ != null) + targ.insertBefore(el, refEl); + + return el; +} + +function placeDiv(cls, targ) { + return placeTag("div", cls, targ); +} -function zeroPad2(int) { - return (int < 10 ? '0' : '') + int; +const xformCache = new WeakMap(); + +function elTrans(el, xPos, yPos, xMax, yMax) { + let xform = "translate(" + xPos + "px," + yPos + "px)"; + let xformOld = xformCache.get(el); + + if (xform != xformOld) { + el.style.transform = xform; + xformCache.set(el, xform); + + if (xPos < 0 || yPos < 0 || xPos > xMax || yPos > yMax) + addClass(el, OFF); + else + remClass(el, OFF); + } } -function zeroPad3(int) { - return (int < 10 ? '00' : int < 100 ? '0' : '') + int; -} +const colorCache = new WeakMap(); -/* -function suffix(int) { - let mod10 = int % 10; +function elColor(el, background, borderColor) { + let newColor = background + borderColor; + let oldColor = colorCache.get(el); - return int + ( - mod10 == 1 && int != 11 ? "st" : - mod10 == 2 && int != 12 ? "nd" : - mod10 == 3 && int != 13 ? "rd" : "th" - ); + if (newColor != oldColor) { + colorCache.set(el, newColor); + el.style.background = background; + el.style.borderColor = borderColor; + } } -*/ -const subs = { - // 2019 - YYYY: d => d.getFullYear(), - // 19 - YY: d => (d.getFullYear()+'').slice(2), - // July - MMMM: (d, names) => names.MMMM[d.getMonth()], - // Jul - MMM: (d, names) => names.MMM[d.getMonth()], - // 07 - MM: d => zeroPad2(d.getMonth()+1), - // 7 - M: d => d.getMonth()+1, - // 09 - DD: d => zeroPad2(d.getDate()), - // 9 - D: d => d.getDate(), - // Monday - WWWW: (d, names) => names.WWWW[d.getDay()], - // Mon - WWW: (d, names) => names.WWW[d.getDay()], - // 03 - HH: d => zeroPad2(d.getHours()), - // 3 - H: d => d.getHours(), - // 9 (12hr, unpadded) - h: d => {let h = d.getHours(); return h == 0 ? 12 : h > 12 ? h - 12 : h;}, - // AM - AA: d => d.getHours() >= 12 ? 'PM' : 'AM', - // am - aa: d => d.getHours() >= 12 ? 'pm' : 'am', - // a - a: d => d.getHours() >= 12 ? 'p' : 'a', - // 09 - mm: d => zeroPad2(d.getMinutes()), - // 9 - m: d => d.getMinutes(), - // 09 - ss: d => zeroPad2(d.getSeconds()), - // 9 - s: d => d.getSeconds(), - // 374 - fff: d => zeroPad3(d.getMilliseconds()), -}; - -function fmtDate(tpl, names) { - names = names || engNames; - let parts = []; +const sizeCache = new WeakMap(); - let R = /\{([a-z]+)\}|[^{]+/gi, m; +function elSize(el, newWid, newHgt, centered) { + let newSize = newWid + "" + newHgt; + let oldSize = sizeCache.get(el); - while (m = R.exec(tpl)) - parts.push(m[0][0] == '{' ? subs[m[1]] : m[0]); + if (newSize != oldSize) { + sizeCache.set(el, newSize); + el.style.height = newHgt + "px"; + el.style.width = newWid + "px"; + el.style.marginLeft = centered ? -newWid/2 + "px" : 0; + el.style.marginTop = centered ? -newHgt/2 + "px" : 0; + } +} - return d => { - let out = ''; +const evOpts = {passive: true}; +const evOpts2 = {...evOpts, capture: true}; - for (let i = 0; i < parts.length; i++) - out += typeof parts[i] == "string" ? parts[i] : parts[i](d, names); +function on(ev, el, cb, capt) { + el.addEventListener(ev, cb, capt ? evOpts2 : evOpts); +} - return out; - } +function off(ev, el, cb, capt) { + el.removeEventListener(ev, cb, evOpts); } +domEnv && setPxRatio(); + const localTz = new Intl.DateTimeFormat().resolvedOptions().timeZone; // https://stackoverflow.com/questions/15141762/how-to-initialize-a-javascript-date-to-a-particular-time-zone/53652131#53652131 @@ -982,17 +855,14 @@ const numIncrs = decIncrs.concat(oneIncrs); const NL = "\n"; -const yyyy = "{YYYY}"; -const NLyyyy = NL + yyyy; -const md = "{M}/{D}"; -const NLmd = NL + md; -const NLmdyy = NLmd + "/{YY}"; - -const aa = "{aa}"; -const hmm = "{h}:{mm}"; -const hmmaa = hmm + aa; -const NLhmmaa = NL + hmmaa; -const ss = ":{ss}"; +let YYYY = {year: 'numeric'}; +let MM = {month: 'numeric'}; +let MMM = {month: 'short'}; +let dd = {day: 'numeric'}; +let hh = {hour: 'numeric'}; +let mm = {minute: 'numeric'}; +let ss = {second: 'numeric'}; +let fff = { fractionalSecondDigits: 3}; const _ = null; @@ -1059,18 +929,18 @@ function genTimeStuffs(ms) { // [0]: minimum num secs in the tick incr // [1]: default tick format // [2-7]: rollover tick formats - // [8]: mode: 0: replace [1] -> [2-7], 1: concat [1] + [2-7] + // [8]: mode: 0: replace [1] -> [2-7], 1: merge [2-7] + \n + [1] const _timeAxisStamps = [ - // tick incr default year month day hour min sec mode - [y, yyyy, _, _, _, _, _, _, 1], - [d * 28, "{MMM}", NLyyyy, _, _, _, _, _, 1], - [d, md, NLyyyy, _, _, _, _, _, 1], - [h, "{h}" + aa, NLmdyy, _, NLmd, _, _, _, 1], - [m, hmmaa, NLmdyy, _, NLmd, _, _, _, 1], - [s, ss, NLmdyy + " " + hmmaa, _, NLmd + " " + hmmaa, _, NLhmmaa, _, 1], - [ms, ss + ".{fff}", NLmdyy + " " + hmmaa, _, NLmd + " " + hmmaa, _, NLhmmaa, _, 1], + // tick incr default year month day hour min sec mode + [y, { ...YYYY }, _, _, _, _, _, _, 1], + [d * 28, { ...MMM }, {...YYYY}, _, _, _, _, _, 1], + [d, { ...MM, ...dd }, {...YYYY}, _, _, _, _, _, 1], + [h, { ...hh }, { ...YYYY, ...MM, ...dd}, _, {...MM, ...dd}, _, _, _, 1], + [m, { ...hh, ...mm }, { ...YYYY, ...MM, ...dd}, _, {...MM, ...dd}, _, _, _, 1], + [s, { ...ss }, { ...YYYY, ...MM, ...dd, ...hh, ...mm}, _, {...MM, ...dd, ...hh, ...mm}, _, {...hh, ...mm}, _, 1], + [ms, { ...ss, ...fff }, { ...YYYY, ...MM, ...dd, ...hh, ...mm}, _, {...MM, ...dd, ...hh, ...mm}, _, {...hh, ...mm}, _, 1], ]; - + // the ensures that axis ticks, values & grid are aligned to logical temporal breakpoints and not an arbitrary timestamp // https://www.timeanddate.com/time/dst/ // https://www.timeanddate.com/time/dst/2019.html @@ -1183,8 +1053,18 @@ console.log({ */ function timeAxisStamps(stampCfg, fmtDate) { - return stampCfg.map(s => s.map((v, i) => - i == 0 || i == 8 || v == null ? v : fmtDate(i == 1 || s[8] == 0 ? v : s[1] + v) + return stampCfg.map(s => s.map((v, i) => { + if (i == 0 || i == 8 || v == null) { + return v + } + const line1 = fmtDate(v); + if (i == 1 || s[8] == 0) { + return line1 + } else { + const line2 = fmtDate(s[1]); + return (date) => line2(date)+NL+line1(date) + } + } )); } @@ -1234,12 +1114,6 @@ function timeAxisVals(tzDate, stamps) { } } -// for when axis.values is defined as a static fmtDate template string -function timeAxisVal(tzDate, dateTpl) { - let stamp = fmtDate(dateTpl); - return (self, splits, axisIdx, foundSpace, foundIncr) => splits.map(split => stamp(tzDate(split))); -} - function mkDate(y, m, d) { return new Date(y, m, d); } @@ -1247,7 +1121,7 @@ function mkDate(y, m, d) { function timeSeriesStamp(stampCfg, fmtDate) { return fmtDate(stampCfg); } -const _timeSeriesStamp = '{YYYY}-{MM}-{DD} {h}:{mm}{aa}'; +const _timeSeriesStamp = { ...YYYY, ...MM, ...dd, ...hh, ...mm }; function timeSeriesVal(tzDate, stamp) { return (self, val, seriesIdx, dataIdx) => dataIdx == null ? LEGEND_DISP : stamp(tzDate(val)); @@ -1458,7 +1332,7 @@ const xSeriesOpts = { idxs: [], }; -function numAxisVals(self, splits, axisIdx, foundSpace, foundIncr) { +function numAxisVals(self, splits, axisIdx, foundSpace, foundIncr, fmtNum) { return splits.map(v => v == null ? "" : fmtNum(v)); } @@ -1581,7 +1455,7 @@ function log2AxisValsFilt(self, splits, axisIdx, foundSpace, foundIncr) { return splits; } -function numSeriesVal(self, val, seriesIdx, dataIdx) { +function numSeriesVal(self, val, seriesIdx, dataIdx, fmtNum) { return dataIdx == null ? LEGEND_DISP : val == null ? "" : fmtNum(val); } @@ -2764,14 +2638,15 @@ function _monotoneCubic(xs, ys, moveTo, lineTo, bezierCurveTo, pxRound) { const cursorPlots = new Set(); function invalidateRects() { - for (let u of cursorPlots) - u.syncRect(true); + for (let u of cursorPlots) u.syncRect(true); } if (domEnv) { on(resize, win, invalidateRects); on(scroll, win, invalidateRects, true); - on(dppxchange, win, () => { uPlot.pxRatio = pxRatio; }); + on(dppxchange, win, () => { + uPlot.pxRatio = pxRatio; + }); } const linearPath = linear() ; @@ -2779,19 +2654,19 @@ const pointsPath = points() ; function setDefaults(d, xo, yo, initY) { let d2 = initY ? [d[0], d[1]].concat(d.slice(2)) : [d[0]].concat(d.slice(1)); - return d2.map((o, i) => setDefault(o, i, xo, yo)); + return d2.map((o, i) => setDefault(o, i, xo, yo)) } function setDefaults2(d, xyo) { - return d.map((o, i) => i == 0 ? {} : assign({}, xyo, o)); // todo: assign() will not merge facet arrays + return d.map((o, i) => (i == 0 ? {} : assign({}, xyo, o))) // todo: assign() will not merge facet arrays } function setDefault(o, i, xo, yo) { - return assign({}, (i == 0 ? xo : yo), o); + return assign({}, i == 0 ? xo : yo, o) } function snapNumX(self, dataMin, dataMax) { - return dataMin == null ? nullNullTuple : [dataMin, dataMax]; + return dataMin == null ? nullNullTuple : [dataMin, dataMax] } const snapTimeX = snapNumX; @@ -2799,17 +2674,23 @@ const snapTimeX = snapNumX; // this ensures that non-temporal/numeric y-axes get multiple-snapped padding added above/below // TODO: also account for incrs when snapping to ensure top of axis gets a tick & value function snapNumY(self, dataMin, dataMax) { - return dataMin == null ? nullNullTuple : rangeNum(dataMin, dataMax, rangePad, true); + return dataMin == null + ? nullNullTuple + : rangeNum(dataMin, dataMax, rangePad, true) } function snapLogY(self, dataMin, dataMax, scale) { - return dataMin == null ? nullNullTuple : rangeLog(dataMin, dataMax, self.scales[scale].log, false); + return dataMin == null + ? nullNullTuple + : rangeLog(dataMin, dataMax, self.scales[scale].log, false) } const snapLogX = snapLogY; function snapAsinhY(self, dataMin, dataMax, scale) { - return dataMin == null ? nullNullTuple : rangeAsinh(dataMin, dataMax, self.scales[scale].log, false); + return dataMin == null + ? nullNullTuple + : rangeAsinh(dataMin, dataMax, self.scales[scale].log, false) } const snapAsinhX = snapAsinhY; @@ -2824,24 +2705,30 @@ function findIncr(minVal, maxVal, incrs, dim, minSpace) { do { let foundIncr = incrs[incrIdx]; - let foundSpace = dim * foundIncr / delta; + let foundSpace = (dim * foundIncr) / delta; - if (foundSpace >= minSpace && intDigits + (foundIncr < 5 ? fixedDec.get(foundIncr) : 0) <= 17) - return [foundIncr, foundSpace]; - } while (++incrIdx < incrs.length); + if ( + foundSpace >= minSpace && + intDigits + (foundIncr < 5 ? fixedDec.get(foundIncr) : 0) <= 17 + ) + return [foundIncr, foundSpace] + } while (++incrIdx < incrs.length) - return [0, 0]; + return [0, 0] } function pxRatioFont(font) { let fontSize, fontSizeCss; - font = font.replace(/(\d+)px/, (m, p1) => (fontSize = round((fontSizeCss = +p1) * pxRatio)) + 'px'); - return [font, fontSize, fontSizeCss]; + font = font.replace( + /(\d+)px/, + (m, p1) => (fontSize = round((fontSizeCss = +p1) * pxRatio)) + 'px' + ); + return [font, fontSize, fontSizeCss] } function syncFontSize(axis) { if (axis.show) { - [axis.font, axis.labelFont].forEach(f => { +[axis.font, axis.labelFont].forEach((f) => { let size = roundDec(f[2] * pxRatio, 1); f[0] = f[0].replace(/[0-9.]+px/, size + 'px'); f[1] = size; @@ -2851,35 +2738,62 @@ function syncFontSize(axis) { function uPlot(opts, data, then) { const self = { - mode: ifNull(opts.mode, 1), + mode: ifNull(opts.mode, 1) }; const mode = self.mode; + const numFormatter = new Intl.NumberFormat(opts.locale || browserLocale); + const fmtNum = (val) => numFormatter.format(val); + self.fmtNum = fmtNum; + + const fmtDate = (tsOpts) => { + tsOpts.hourCycle = opts.hourCycle; + return new Intl.DateTimeFormat(opts.locale || browserLocale, tsOpts) + .format + }; + { + self.fmtDate = fmtDate; + } + // TODO: cache denoms & mins scale.cache = {r, min, } function getValPct(val, scale) { - let _val = ( - scale.distr == 3 ? log10(val > 0 ? val : scale.clamp(self, val, scale.min, scale.max, scale.key)) : - scale.distr == 4 ? asinh(val, scale.asinh) : - scale.distr == 100 ? scale.fwd(val) : - val - ); - - return (_val - scale._min) / (scale._max - scale._min); + let _val = + scale.distr == 3 + ? log10( + val > 0 + ? val + : scale.clamp( + self, + val, + scale.min, + scale.max, + scale.key + ) + ) + : scale.distr == 4 + ? asinh(val, scale.asinh) + : scale.distr == 100 + ? scale.fwd(val) + : val; + + return (_val - scale._min) / (scale._max - scale._min) } function getHPos(val, scale, dim, off) { let pct = getValPct(val, scale); - return off + dim * (scale.dir == -1 ? (1 - pct) : pct); + return off + dim * (scale.dir == -1 ? 1 - pct : pct) } function getVPos(val, scale, dim, off) { let pct = getValPct(val, scale); - return off + dim * (scale.dir == -1 ? pct : (1 - pct)); + return off + dim * (scale.dir == -1 ? pct : 1 - pct) } function getPos(val, scale, dim, off) { - return scale.ori == 0 ? getHPos(val, scale, dim, off) : getVPos(val, scale, dim, off); + return scale.ori == 0 + ? getHPos(val, scale, dim, off) + : getVPos(val, scale, dim, off) } self.valToPosH = getHPos; @@ -2888,10 +2802,9 @@ function uPlot(opts, data, then) { let ready = false; self.status = 0; - const root = self.root = placeDiv(UPLOT); + const root = (self.root = placeDiv(UPLOT)); - if (opts.id != null) - root.id = opts.id; + if (opts.id != null) root.id = opts.id; addClass(root, opts.class); @@ -2900,43 +2813,53 @@ function uPlot(opts, data, then) { title.textContent = opts.title; } - const can = placeTag("canvas"); - const ctx = self.ctx = can.getContext("2d"); + const can = placeTag('canvas'); + const ctx = (self.ctx = can.getContext('2d')); const wrap = placeDiv(WRAP, root); - on("click", wrap, e => { - if (e.target === over) { - let didDrag = mouseLeft1 != mouseLeft0 || mouseTop1 != mouseTop0; - didDrag && drag.click(self, e); - } - }, true); + on( + 'click', + wrap, + (e) => { + if (e.target === over) { + let didDrag = mouseLeft1 != mouseLeft0 || mouseTop1 != mouseTop0; + didDrag && drag.click(self, e); + } + }, + true + ); - const under = self.under = placeDiv(UNDER, wrap); + const under = (self.under = placeDiv(UNDER, wrap)); wrap.appendChild(can); - const over = self.over = placeDiv(OVER, wrap); + const over = (self.over = placeDiv(OVER, wrap)); opts = copy(opts); const pxAlign = +ifNull(opts.pxAlign, 1); - const pxRound = pxRoundGen(pxAlign); + const pxRound = pxRoundGen(pxAlign) - (opts.plugins || []).forEach(p => { - if (p.opts) - opts = p.opts(self, opts) || opts; + ;(opts.plugins || []).forEach((p) => { + if (p.opts) opts = p.opts(self, opts) || opts; }); const ms = opts.ms || 1e-3; - const series = self.series = mode == 1 ? - setDefaults(opts.series || [], xSeriesOpts, ySeriesOpts, false) : - setDefaults2(opts.series || [null], xySeriesOpts); - const axes = self.axes = setDefaults(opts.axes || [], xAxisOpts, yAxisOpts, true); - const scales = self.scales = {}; - const bands = self.bands = opts.bands || []; + const series = (self.series = + mode == 1 + ? setDefaults(opts.series || [], xSeriesOpts, ySeriesOpts, false) + : setDefaults2(opts.series || [null], xySeriesOpts)); + const axes = (self.axes = setDefaults( + opts.axes || [], + xAxisOpts, + yAxisOpts, + true + )); + const scales = (self.scales = {}); + const bands = (self.bands = opts.bands || []); - bands.forEach(b => { + bands.forEach((b) => { b.fill = fnOrSelf(b.fill || null); b.dir = ifNull(b.dir, -1); }); @@ -2945,10 +2868,12 @@ function uPlot(opts, data, then) { const drawOrderMap = { axes: drawAxesGrid, - series: drawSeries, + series: drawSeries }; - const drawOrder = (opts.drawOrder || ["axes", "series"]).map(key => drawOrderMap[key]); + const drawOrder = (opts.drawOrder || ['axes', 'series']).map( + (key) => drawOrderMap[key] + ); function initScale(scaleKey) { let sc = scales[scaleKey]; @@ -2960,10 +2885,18 @@ function uPlot(opts, data, then) { // ensure parent is initialized initScale(scaleOpts.from); // dependent scales inherit - scales[scaleKey] = assign({}, scales[scaleOpts.from], scaleOpts, {key: scaleKey}); - } - else { - sc = scales[scaleKey] = assign({}, (scaleKey == xScaleKey ? xScaleOpts : yScaleOpts), scaleOpts); + scales[scaleKey] = assign( + {}, + scales[scaleOpts.from], + scaleOpts, + { key: scaleKey } + ); + } else { + sc = scales[scaleKey] = assign( + {}, + scaleKey == xScaleKey ? xScaleOpts : yScaleOpts, + scaleOpts + ); sc.key = scaleKey; @@ -2977,16 +2910,22 @@ function uPlot(opts, data, then) { // if range array has null limits, it should be auto if (rangeIsArr && (rn[0] == null || rn[1] == null)) { rn = { - min: rn[0] == null ? autoRangePart : { - mode: 1, - hard: rn[0], - soft: rn[0], - }, - max: rn[1] == null ? autoRangePart : { - mode: 1, - hard: rn[1], - soft: rn[1], - }, + min: + rn[0] == null + ? autoRangePart + : { + mode: 1, + hard: rn[0], + soft: rn[0] + }, + max: + rn[1] == null + ? autoRangePart + : { + mode: 1, + hard: rn[1], + soft: rn[1] + } }; rangeIsArr = false; } @@ -2994,14 +2933,29 @@ function uPlot(opts, data, then) { if (!rangeIsArr && isObj(rn)) { let cfg = rn; // this is similar to snapNumY - rn = (self, dataMin, dataMax) => dataMin == null ? nullNullTuple : rangeNum(dataMin, dataMax, cfg); + rn = (self, dataMin, dataMax) => + dataMin == null + ? nullNullTuple + : rangeNum(dataMin, dataMax, cfg); } } - sc.range = fnOrSelf(rn || (isTime ? snapTimeX : scaleKey == xScaleKey ? - (sc.distr == 3 ? snapLogX : sc.distr == 4 ? snapAsinhX : snapNumX) : - (sc.distr == 3 ? snapLogY : sc.distr == 4 ? snapAsinhY : snapNumY) - )); + sc.range = fnOrSelf( + rn || + (isTime + ? snapTimeX + : scaleKey == xScaleKey + ? sc.distr == 3 + ? snapLogX + : sc.distr == 4 + ? snapAsinhX + : snapNumX + : sc.distr == 3 + ? snapLogY + : sc.distr == 4 + ? snapAsinhY + : snapNumY) + ); sc.auto = fnOrSelf(rangeIsArr ? false : sc.auto); @@ -3013,28 +2967,28 @@ function uPlot(opts, data, then) { } } - initScale("x"); - initScale("y"); + initScale('x'); + initScale('y'); // TODO: init scales from facets in mode: 2 if (mode == 1) { - series.forEach(s => { + series.forEach((s) => { initScale(s.scale); }); } - axes.forEach(a => { + axes.forEach((a) => { initScale(a.scale); }); - for (let k in opts.scales) - initScale(k); + for (let k in opts.scales) initScale(k); const scaleX = scales[xScaleKey]; const xScaleDistr = scaleX.distr; - let valToPosX, valToPosY; + let valToPosX, + valToPosY; if (scaleX.ori == 0) { addClass(root, ORI_HZ); @@ -3053,8 +3007,7 @@ function uPlot(opts, data, then) { yOffCss = plotTopCss; }; */ - } - else { + } else { addClass(root, ORI_VT); valToPosX = getVPos; valToPosY = getHPos; @@ -3080,32 +3033,43 @@ function uPlot(opts, data, then) { let sc = scales[k]; if (sc.min != null || sc.max != null) { - pendScales[k] = {min: sc.min, max: sc.max}; + pendScales[k] = { min: sc.min, max: sc.max }; sc.min = sc.max = null; } } -// self.tz = opts.tz || Intl.DateTimeFormat().resolvedOptions().timeZone; - const _tzDate = (opts.tzDate || (ts => new Date(round(ts / ms)))); + // self.tz = opts.tz || Intl.DateTimeFormat().resolvedOptions().timeZone; + const _tzDate = + (opts.tzDate || ((ts) => new Date(round(ts / ms)))); const _fmtDate = (opts.fmtDate || fmtDate); - const _timeAxisSplits = (ms == 1 ? timeAxisSplitsMs(_tzDate) : timeAxisSplitsS(_tzDate)); - const _timeAxisVals = timeAxisVals(_tzDate, timeAxisStamps((ms == 1 ? _timeAxisStampsMs : _timeAxisStampsS), _fmtDate)); - const _timeSeriesVal = timeSeriesVal(_tzDate, timeSeriesStamp(_timeSeriesStamp, _fmtDate)); + const _timeAxisSplits = + (ms == 1 ? timeAxisSplitsMs(_tzDate) : timeAxisSplitsS(_tzDate)); + const _timeAxisVals = + timeAxisVals( + _tzDate, + timeAxisStamps( + ms == 1 ? _timeAxisStampsMs : _timeAxisStampsS, + _fmtDate + ) + ); + const _timeSeriesVal = + timeSeriesVal(_tzDate, timeSeriesStamp(_timeSeriesStamp, _fmtDate)); const activeIdxs = []; - const legend = (self.legend = assign({}, legendOpts, opts.legend)); + const legend = + (self.legend = assign({}, legendOpts, opts.legend)); const showLegend = legend.show; - const markers = legend.markers; + const markers = legend.markers; { legend.idxs = activeIdxs; - markers.width = fnOrSelf(markers.width); - markers.dash = fnOrSelf(markers.dash); + markers.width = fnOrSelf(markers.width); + markers.dash = fnOrSelf(markers.dash); markers.stroke = fnOrSelf(markers.stroke); - markers.fill = fnOrSelf(markers.fill); + markers.fill = fnOrSelf(markers.fill); } let legendTable; @@ -3120,60 +3084,67 @@ function uPlot(opts, data, then) { if (legend.live) { const getMultiVals = series[1] ? series[1].values : null; multiValLegend = getMultiVals != null; - legendCols = multiValLegend ? getMultiVals(self, 1, 0) : {_: 0}; + legendCols = multiValLegend ? getMultiVals(self, 1, 0) : { _: 0 }; - for (let k in legendCols) - NULL_LEGEND_VALUES[k] = LEGEND_DISP; + for (let k in legendCols) NULL_LEGEND_VALUES[k] = LEGEND_DISP; } if (showLegend) { - legendTable = placeTag("table", LEGEND, root); - legendBody = placeTag("tbody", null, legendTable); + legendTable = placeTag('table', LEGEND, root); + legendBody = placeTag('tbody', null, legendTable); // allows legend to be moved out of root legend.mount(self, legendTable); if (multiValLegend) { - legendHead = placeTag("thead", null, legendTable, legendBody); + legendHead = placeTag('thead', null, legendTable, legendBody); - let head = placeTag("tr", null, legendHead); - placeTag("th", null, head); + let head = placeTag('tr', null, legendHead); + placeTag('th', null, head); for (var key in legendCols) - placeTag("th", LEGEND_LABEL, head).textContent = key; - } - else { + placeTag('th', LEGEND_LABEL, head).textContent = key; + } else { addClass(legendTable, LEGEND_INLINE); legend.live && addClass(legendTable, LEGEND_LIVE); } } - const son = {show: true}; - const soff = {show: false}; + const son = { show: true }; + const soff = { show: false }; function initLegendRow(s, i) { if (i == 0 && (multiValLegend || !legend.live || mode == 2)) - return nullNullTuple; + return nullNullTuple let cells = []; - let row = placeTag("tr", LEGEND_SERIES, legendBody, legendBody.childNodes[i]); + let row = placeTag( + 'tr', + LEGEND_SERIES, + legendBody, + legendBody.childNodes[i] + ); addClass(row, s.class); - if (!s.show) - addClass(row, OFF); + if (!s.show) addClass(row, OFF); - let label = placeTag("th", null, row); + let label = placeTag('th', null, row); if (markers.show) { let indic = placeDiv(LEGEND_MARKER, label); if (i > 0) { - let width = markers.width(self, i); + let width = markers.width(self, i); if (width) - indic.style.border = width + "px " + markers.dash(self, i) + " " + markers.stroke(self, i); + indic.style.border = + width + + 'px ' + + markers.dash(self, i) + + ' ' + + markers.stroke(self, i); indic.style.background = markers.fill(self, i); } @@ -3184,47 +3155,79 @@ function uPlot(opts, data, then) { if (i > 0) { if (!markers.show) - text.style.color = s.width > 0 ? markers.stroke(self, i) : markers.fill(self, i); + text.style.color = + s.width > 0 + ? markers.stroke(self, i) + : markers.fill(self, i); - onMouse("click", label, e => { - if (cursor._lock) - return; + onMouse( + 'click', + label, + (e) => { + if (cursor._lock) return - setCursorEvent(e); + setCursorEvent(e); - let seriesIdx = series.indexOf(s); + let seriesIdx = series.indexOf(s); - if ((e.ctrlKey || e.metaKey) != legend.isolate) { - // if any other series is shown, isolate this one. else show all - let isolate = series.some((s, i) => i > 0 && i != seriesIdx && s.show); + if ((e.ctrlKey || e.metaKey) != legend.isolate) { + // if any other series is shown, isolate this one. else show all + let isolate = series.some( + (s, i) => i > 0 && i != seriesIdx && s.show + ); - series.forEach((s, i) => { - i > 0 && setSeries(i, isolate ? (i == seriesIdx ? son : soff) : son, true, syncOpts.setSeries); - }); - } - else - setSeries(seriesIdx, {show: !s.show}, true, syncOpts.setSeries); - }, false); + series.forEach((s, i) => { + i > 0 && + setSeries( + i, + isolate + ? i == seriesIdx + ? son + : soff + : son, + true, + syncOpts.setSeries + ); + }); + } else + setSeries( + seriesIdx, + { show: !s.show }, + true, + syncOpts.setSeries + ); + }, + false + ); if (cursorFocus) { - onMouse(mouseenter, label, e => { - if (cursor._lock) - return; - - setCursorEvent(e); - - setSeries(series.indexOf(s), FOCUS_TRUE, true, syncOpts.setSeries); - }, false); + onMouse( + mouseenter, + label, + (e) => { + if (cursor._lock) return + + setCursorEvent(e); + + setSeries( + series.indexOf(s), + FOCUS_TRUE, + true, + syncOpts.setSeries + ); + }, + false + ); } } for (var key in legendCols) { - let v = placeTag("td", LEGEND_VALUE, row); - v.textContent = "--"; + let v = placeTag('td', LEGEND_VALUE, row); + v.textContent = '--'; cells.push(v); } - return [row, cells]; + return [row, cells] } const mouseListeners = new Map(); @@ -3234,7 +3237,7 @@ function uPlot(opts, data, then) { const listener = cursor.bind[ev](self, targ, fn, onlyTarg); if (listener) { - on(ev, targ, targListeners[ev] = listener); + on(ev, targ, (targListeners[ev] = listener)); mouseListeners.set(targ, targListeners); } } @@ -3249,8 +3252,7 @@ function uPlot(opts, data, then) { } } - if (ev == null) - mouseListeners.delete(targ); + if (ev == null) mouseListeners.delete(targ); } let fullWidCss = 0; @@ -3269,7 +3271,6 @@ function uPlot(opts, data, then) { let _plotWidCss = plotWidCss; let _plotHgtCss = plotHgtCss; - let plotLft = 0; let plotTop = 0; let plotWid = 0; @@ -3285,7 +3286,7 @@ function uPlot(opts, data, then) { let shouldSetLegend = false; function _setSize(width, height, force) { - if (force || (width != self.width || height != self.height)) + if (force || width != self.width || height != self.height) calcSize(width, height); resetYSeries(false); @@ -3297,23 +3298,23 @@ function uPlot(opts, data, then) { } function calcSize(width, height) { - // log("calcSize()", arguments); + // log("calcSize()", arguments); - self.width = fullWidCss = plotWidCss = width; + self.width = fullWidCss = plotWidCss = width; self.height = fullHgtCss = plotHgtCss = height; - plotLftCss = plotTopCss = 0; + plotLftCss = plotTopCss = 0; calcPlotRect(); calcAxesRects(); let bb = self.bbox; - plotLft = bb.left = incrRound(plotLftCss * pxRatio, 0.5); - plotTop = bb.top = incrRound(plotTopCss * pxRatio, 0.5); - plotWid = bb.width = incrRound(plotWidCss * pxRatio, 0.5); + plotLft = bb.left = incrRound(plotLftCss * pxRatio, 0.5); + plotTop = bb.top = incrRound(plotTopCss * pxRatio, 0.5); + plotWid = bb.width = incrRound(plotWidCss * pxRatio, 0.5); plotHgt = bb.height = incrRound(plotHgtCss * pxRatio, 0.5); - // updOriDims(); + // updOriDims(); } // ensures size calc convergence @@ -3330,7 +3331,8 @@ function uPlot(opts, data, then) { let axesConverged = axesCalc(cycleNum); let paddingConverged = paddingCalc(cycleNum); - converged = cycleNum == CYCLE_LIMIT || (axesConverged && paddingConverged); + converged = + cycleNum == CYCLE_LIMIT || (axesConverged && paddingConverged); if (!converged) { calcSize(self.width, self.height); @@ -3339,7 +3341,7 @@ function uPlot(opts, data, then) { } } - function setSize({width, height}) { + function setSize({ width, height }) { _setSize(width, height); } @@ -3355,7 +3357,7 @@ function uPlot(opts, data, then) { axes.forEach((axis, i) => { if (axis.show && axis._show) { - let {side, _size} = axis; + let { side, _size } = axis; let isVt = side % 2; let labelSize = axis.label != null ? axis.labelSize : 0; @@ -3368,19 +3370,14 @@ function uPlot(opts, data, then) { if (side == 3) { plotLftCss += fullSize; hasLftAxis = true; - } - else - hasRgtAxis = true; - } - else { + } else hasRgtAxis = true; + } else { plotHgtCss -= fullSize; if (side == 0) { plotTopCss += fullSize; hasTopAxis = true; - } - else - hasBtmAxis = true; + } else hasBtmAxis = true; } } } @@ -3410,10 +3407,18 @@ function uPlot(opts, data, then) { function incrOffset(side, size) { switch (side) { - case 1: off1 += size; return off1 - size; - case 2: off2 += size; return off2 - size; - case 3: off3 -= size; return off3 + size; - case 0: off0 -= size; return off0 + size; + case 1: + off1 += size; + return off1 - size + case 2: + off2 += size; + return off2 - size + case 3: + off3 -= size; + return off3 + size + case 0: + off0 -= size; + return off0 + size } } @@ -3429,20 +3434,24 @@ function uPlot(opts, data, then) { }); } - const cursor = self.cursor = assign({}, cursorOpts, {drag: {y: mode == 2}}, opts.cursor); + const cursor = (self.cursor = assign( + {}, + cursorOpts, + { drag: { y: mode == 2 } }, + opts.cursor + )); if (cursor.dataIdx == null) { let hov = cursor.hover; - let skip = hov.skip = new Set(hov.skip ?? []); + let skip = (hov.skip = new Set(hov.skip ?? [])); skip.add(void 0); // alignment artifacts - let prox = hov.prox = fnOrSelf(hov.prox); - let bias = hov.bias ??= 0; + let prox = (hov.prox = fnOrSelf(hov.prox)); + let bias = (hov.bias ??= 0); // TODO: only scan between in-view idxs (i0, i1) cursor.dataIdx = (self, seriesIdx, cursorIdx, valAtPosX) => { - if (seriesIdx == 0) - return cursorIdx; + if (seriesIdx == 0) return cursorIdx let idx2 = cursorIdx; @@ -3464,55 +3473,73 @@ function uPlot(opts, data, then) { if (bias == 0 || bias == -1) { j = cursorIdx; while (nonNullLft == null && j-- > 0) { - if (!skip.has(yValues[j])) - nonNullLft = j; + if (!skip.has(yValues[j])) nonNullLft = j; } } if (bias == 0 || bias == 1) { j = cursorIdx; while (nonNullRgt == null && j++ < yValues.length) { - if (!skip.has(yValues[j])) - nonNullRgt = j; + if (!skip.has(yValues[j])) nonNullRgt = j; } } if (nonNullLft != null || nonNullRgt != null) { if (withProx) { - let lftPos = nonNullLft == null ? -Infinity : valToPosX(xValues[nonNullLft], scaleX, xDim, 0); - let rgtPos = nonNullRgt == null ? Infinity : valToPosX(xValues[nonNullRgt], scaleX, xDim, 0); + let lftPos = + nonNullLft == null + ? -Infinity + : valToPosX( + xValues[nonNullLft], + scaleX, + xDim, + 0 + ); + let rgtPos = + nonNullRgt == null + ? Infinity + : valToPosX( + xValues[nonNullRgt], + scaleX, + xDim, + 0 + ); let lftDelta = cursorLft - lftPos; let rgtDelta = rgtPos - cursorLft; if (lftDelta <= rgtDelta) { - if (lftDelta <= _prox) - idx2 = nonNullLft; + if (lftDelta <= _prox) idx2 = nonNullLft; } else { - if (rgtDelta <= _prox) - idx2 = nonNullRgt; + if (rgtDelta <= _prox) idx2 = nonNullRgt; } - } - else { + } else { idx2 = - nonNullRgt == null ? nonNullLft : - nonNullLft == null ? nonNullRgt : - cursorIdx - nonNullLft <= nonNullRgt - cursorIdx ? nonNullLft : nonNullRgt; + nonNullRgt == null + ? nonNullLft + : nonNullLft == null + ? nonNullRgt + : cursorIdx - nonNullLft <= + nonNullRgt - cursorIdx + ? nonNullLft + : nonNullRgt; } } - } - else if (withProx) { - let dist = abs(cursorLft - valToPosX(xValues[cursorIdx], scaleX, xDim, 0)); + } else if (withProx) { + let dist = abs( + cursorLft - valToPosX(xValues[cursorIdx], scaleX, xDim, 0) + ); - if (dist > _prox) - idx2 = null; + if (dist > _prox) idx2 = null; } - return idx2; + return idx2 }; } - const setCursorEvent = e => { cursor.event = e; }; + const setCursorEvent = (e) => { + cursor.event = e; + }; cursor.idxs = activeIdxs; @@ -3520,13 +3547,17 @@ function uPlot(opts, data, then) { let points = cursor.points; - points.show = fnOrSelf(points.show); - points.size = fnOrSelf(points.size); + points.show = fnOrSelf(points.show); + points.size = fnOrSelf(points.size); points.stroke = fnOrSelf(points.stroke); - points.width = fnOrSelf(points.width); - points.fill = fnOrSelf(points.fill); + points.width = fnOrSelf(points.width); + points.fill = fnOrSelf(points.fill); - const focus = self.focus = assign({}, opts.focus || {alpha: 0.3}, cursor.focus); + const focus = (self.focus = assign( + {}, + opts.focus || { alpha: 0.3 }, + cursor.focus + )); const cursorFocus = focus.prox >= 0; const cursorOnePt = cursorFocus && points.one; @@ -3546,7 +3577,7 @@ function uPlot(opts, data, then) { elTrans(pt, -10, -10, plotWidCss, plotHgtCss); over.insertBefore(pt, cursorPts[si]); - return pt; + return pt } } @@ -3555,36 +3586,44 @@ function uPlot(opts, data, then) { let isTime = mode == 1 && scales[s.scale].time; let sv = s.value; - s.value = isTime ? (isStr(sv) ? timeSeriesVal(_tzDate, timeSeriesStamp(sv, _fmtDate)) : sv || _timeSeriesVal) : sv || numSeriesVal; + s.value = isTime + ? isStr(sv) + ? timeSeriesVal(_tzDate, timeSeriesStamp(sv, _fmtDate)) + : sv || _timeSeriesVal + : sv || numSeriesVal; s.label = s.label || (isTime ? timeSeriesLabel : numSeriesLabel); } if (cursorOnePt || i > 0) { - s.width = s.width == null ? 1 : s.width; - s.paths = s.paths || linearPath || retNull; + s.width = s.width == null ? 1 : s.width; + s.paths = s.paths || linearPath || retNull; s.fillTo = fnOrSelf(s.fillTo || seriesFillTo); s.pxAlign = +ifNull(s.pxAlign, pxAlign); s.pxRound = pxRoundGen(s.pxAlign); s.stroke = fnOrSelf(s.stroke || null); - s.fill = fnOrSelf(s.fill || null); + s.fill = fnOrSelf(s.fill || null); s._stroke = s._fill = s._paths = s._focus = null; let _ptDia = ptDia(max(1, s.width), 1); - let points = s.points = assign({}, { - size: _ptDia, - width: max(1, _ptDia * .2), - stroke: s.stroke, - space: _ptDia * 2, - paths: pointsPath, - _stroke: null, - _fill: null, - }, s.points); - points.show = fnOrSelf(points.show); + let points = (s.points = assign( + {}, + { + size: _ptDia, + width: max(1, _ptDia * 0.2), + stroke: s.stroke, + space: _ptDia * 2, + paths: pointsPath, + _stroke: null, + _fill: null + }, + s.points + )); + points.show = fnOrSelf(points.show); points.filter = fnOrSelf(points.filter); - points.fill = fnOrSelf(points.fill); + points.fill = fnOrSelf(points.fill); points.stroke = fnOrSelf(points.stroke); - points.paths = fnOrSelf(points.paths); + points.paths = fnOrSelf(points.paths); points.pxAlign = s.pxAlign; } @@ -3592,7 +3631,7 @@ function uPlot(opts, data, then) { let rowCells = initLegendRow(s, i); legendRows.splice(i, 0, rowCells[0]); legendCells.splice(i, 0, rowCells[1]); - legend.values.push(null); // NULL_LEGEND_VALS not yet avil here :( + legend.values.push(null); // NULL_LEGEND_VALS not yet avil here :( } if (cursor.show) { @@ -3601,24 +3640,24 @@ function uPlot(opts, data, then) { let pt = null; if (cursorOnePt) { - if (i == 0) - pt = initCursorPt(s, i); - } - else if (i > 0) - pt = initCursorPt(s, i); + if (i == 0) pt = initCursorPt(s, i); + } else if (i > 0) pt = initCursorPt(s, i); cursorPts.splice(i, 0, pt); cursorPtsLft.splice(i, 0, 0); cursorPtsTop.splice(i, 0, 0); } - fire("addSeries", i); + fire('addSeries', i); } function addSeries(opts, si) { si = si == null ? series.length : si; - opts = mode == 1 ? setDefault(opts, si, xSeriesOpts, ySeriesOpts) : setDefault(opts, si, {}, xySeriesOpts); + opts = + mode == 1 + ? setDefault(opts, si, xSeriesOpts, ySeriesOpts) + : setDefault(opts, si, {}, xySeriesOpts); series.splice(si, 0, opts); initSeries(series[si], si); @@ -3647,7 +3686,7 @@ function uPlot(opts, data, then) { // TODO: de-init no-longer-needed scales? - fire("delSeries", i); + fire('delSeries', i); } self.delSeries = delSeries; @@ -3671,54 +3710,80 @@ function uPlot(opts, data, then) { // also set defaults for incrs & values based on axis distr let isTime = sc.time; - axis.size = fnOrSelf(axis.size); - axis.space = fnOrSelf(axis.space); + axis.size = fnOrSelf(axis.size); + axis.space = fnOrSelf(axis.space); axis.rotate = fnOrSelf(axis.rotate); if (isArr(axis.incrs)) { - axis.incrs.forEach(incr => { + axis.incrs.forEach((incr) => { !fixedDec.has(incr) && fixedDec.set(incr, guessDec(incr)); }); } - axis.incrs = fnOrSelf(axis.incrs || ( sc.distr == 2 ? wholeIncrs : (isTime ? (ms == 1 ? timeIncrsMs : timeIncrsS) : numIncrs))); - axis.splits = fnOrSelf(axis.splits || (isTime && sc.distr == 1 ? _timeAxisSplits : sc.distr == 3 ? logAxisSplits : sc.distr == 4 ? asinhAxisSplits : numAxisSplits)); + axis.incrs = fnOrSelf( + axis.incrs || + (sc.distr == 2 + ? wholeIncrs + : isTime + ? ms == 1 + ? timeIncrsMs + : timeIncrsS + : numIncrs) + ); + axis.splits = fnOrSelf( + axis.splits || + (isTime && sc.distr == 1 + ? _timeAxisSplits + : sc.distr == 3 + ? logAxisSplits + : sc.distr == 4 + ? asinhAxisSplits + : numAxisSplits) + ); - axis.stroke = fnOrSelf(axis.stroke); - axis.grid.stroke = fnOrSelf(axis.grid.stroke); - axis.ticks.stroke = fnOrSelf(axis.ticks.stroke); + axis.stroke = fnOrSelf(axis.stroke); + axis.grid.stroke = fnOrSelf(axis.grid.stroke); + axis.ticks.stroke = fnOrSelf(axis.ticks.stroke); axis.border.stroke = fnOrSelf(axis.border.stroke); let av = axis.values; - axis.values = ( + axis.values = // static array of tick values - isArr(av) && !isArr(av[0]) ? fnOrSelf(av) : - // temporal - isTime ? ( - // config array of fmtDate string tpls - isArr(av) ? - timeAxisVals(_tzDate, timeAxisStamps(av, _fmtDate)) : - // fmtDate string tpl - isStr(av) ? - timeAxisVal(_tzDate, av) : - av || _timeAxisVals - ) : av || numAxisVals + isArr(av) && !isArr(av[0]) + ? fnOrSelf(av) + : // temporal + isTime + ? // config array of fmtDate string tpls + isArr(av) + ? timeAxisVals(_tzDate, timeAxisStamps(av, _fmtDate)) + : // fmtDate string tpl + //isStr(av) ? + // timeAxisVal(_tzDate, av) : + av || _timeAxisVals + : av || numAxisVals; + + axis.filter = fnOrSelf( + axis.filter || + (sc.distr >= 3 && sc.log == 10 + ? log10AxisValsFilt + : sc.distr == 3 && sc.log == 2 + ? log2AxisValsFilt + : retArg1) ); - axis.filter = fnOrSelf(axis.filter || ( sc.distr >= 3 && sc.log == 10 ? log10AxisValsFilt : sc.distr == 3 && sc.log == 2 ? log2AxisValsFilt : retArg1)); - - axis.font = pxRatioFont(axis.font); + axis.font = pxRatioFont(axis.font); axis.labelFont = pxRatioFont(axis.labelFont); - axis._size = axis.size(self, null, i, 0); + axis._size = axis.size(self, null, i, 0); - axis._space = - axis._rotate = - axis._incrs = - axis._found = // foundIncrSpace - axis._splits = - axis._values = null; + axis._space = + axis._rotate = + axis._incrs = + axis._found = // foundIncrSpace + axis._splits = + axis._values = + null; if (axis._size > 0) { sidesWithAxes[i] = true; @@ -3726,7 +3791,7 @@ function uPlot(opts, data, then) { } // debug - // axis._el.style.background = "#" + Math.floor(Math.random()*16777215).toString(16) + '80'; + // axis._el.style.background = "#" + Math.floor(Math.random()*16777215).toString(16) + '80'; } } @@ -3737,15 +3802,25 @@ function uPlot(opts, data, then) { let size = 0; if (ori == 0 && (hasLftAxis || hasRgtAxis)) - size = (side == 0 && !hasTopAxis || side == 2 && !hasBtmAxis ? round(xAxisOpts.size / 3) : 0); + size = + (side == 0 && !hasTopAxis) || (side == 2 && !hasBtmAxis) + ? round(xAxisOpts.size / 3) + : 0; if (ori == 1 && (hasTopAxis || hasBtmAxis)) - size = (side == 1 && !hasRgtAxis || side == 3 && !hasLftAxis ? round(yAxisOpts.size / 2) : 0); + size = + (side == 1 && !hasRgtAxis) || (side == 3 && !hasLftAxis) + ? round(yAxisOpts.size / 2) + : 0; - return size; + return size } - const padding = self.padding = (opts.padding || [autoPadSide,autoPadSide,autoPadSide,autoPadSide]).map(p => fnOrSelf(ifNull(p, autoPadSide))); - const _padding = self._padding = padding.map((p, i) => p(self, i, sidesWithAxes, 0)); + const padding = (self.padding = ( + opts.padding || [autoPadSide, autoPadSide, autoPadSide, autoPadSide] + ).map((p) => fnOrSelf(ifNull(p, autoPadSide)))); + const _padding = (self._padding = padding.map((p, i) => + p(self, i, sidesWithAxes, 0) + )); let dataLen; @@ -3765,12 +3840,9 @@ function uPlot(opts, data, then) { if (mode == 2) { dataLen = 0; - for (let i = 1; i < series.length; i++) - dataLen += data[i][0].length; - } - else { - if (data.length == 0) - self.data = self._data = data = [[]]; + for (let i = 1; i < series.length; i++) dataLen += data[i][0].length; + } else { + if (data.length == 0) self.data = self._data = data = [[]]; data0 = data[0]; dataLen = data0.length; @@ -3780,9 +3852,8 @@ function uPlot(opts, data, then) { if (xScaleDistr == 2) { scaleData = data.slice(); - let _data0 = scaleData[0] = Array(dataLen); - for (let i = 0; i < dataLen; i++) - _data0[i] = i; + let _data0 = (scaleData[0] = Array(dataLen)); + for (let i = 0; i < dataLen; i++) _data0[i] = i; } self._data = data = scaleData; @@ -3790,7 +3861,7 @@ function uPlot(opts, data, then) { resetYSeries(true); - fire("setData"); + fire('setData'); // forces x axis tick values to re-generate when neither x scale nor y scale changes // in ordinal mode, scale range is by index, so will not change if new data has same length, but tick values are from data @@ -3813,10 +3884,8 @@ function uPlot(opts, data, then) { if (_resetScales !== false) { let xsc = scaleX; - if (xsc.auto(self, viaAutoScaleX)) - autoScaleX(); - else - _setScale(xScaleKey, xsc.min, xsc.max); + if (xsc.auto(self, viaAutoScaleX)) autoScaleX(); + else _setScale(xScaleKey, xsc.min, xsc.max); shouldSetCursor = shouldSetCursor || cursor.left >= 0; shouldSetLegend = true; @@ -3842,19 +3911,15 @@ function uPlot(opts, data, then) { if (xScaleDistr == 2) { _min = i0; _max = i1; - } - else if (_min == _max) { + } else if (_min == _max) { if (xScaleDistr == 3) [_min, _max] = rangeLog(_min, _min, scaleX.log, false); else if (xScaleDistr == 4) [_min, _max] = rangeAsinh(_min, _min, scaleX.log, false); - else if (scaleX.time) - _max = _min + round(86400 / ms); - else - [_min, _max] = rangeNum(_min, _max, rangePad, true); + else if (scaleX.time) _max = _min + round(86400 / ms); + else [_min, _max] = rangeNum(_min, _max, rangePad, true); } - } - else { + } else { i0 = idxs[0] = _min = null; i1 = idxs[1] = _max = null; } @@ -3863,71 +3928,78 @@ function uPlot(opts, data, then) { _setScale(xScaleKey, _min, _max); } - let ctxStroke, ctxFill, ctxWidth, ctxDash, ctxJoin, ctxCap, ctxFont, ctxAlign, ctxBaseline; + let ctxStroke, + ctxFill, + ctxWidth, + ctxDash, + ctxJoin, + ctxCap, + ctxFont, + ctxAlign, + ctxBaseline; let ctxAlpha; function setCtxStyle(stroke, width, dash, cap, fill, join) { stroke ??= transparent; - dash ??= EMPTY_ARR; - cap ??= "butt"; // (‿|‿) - fill ??= transparent; - join ??= "round"; - - if (stroke != ctxStroke) - ctx.strokeStyle = ctxStroke = stroke; - if (fill != ctxFill) - ctx.fillStyle = ctxFill = fill; - if (width != ctxWidth) - ctx.lineWidth = ctxWidth = width; - if (join != ctxJoin) - ctx.lineJoin = ctxJoin = join; - if (cap != ctxCap) - ctx.lineCap = ctxCap = cap; - if (dash != ctxDash) - ctx.setLineDash(ctxDash = dash); + dash ??= EMPTY_ARR; + cap ??= 'butt'; // (‿|‿) + fill ??= transparent; + join ??= 'round'; + + if (stroke != ctxStroke) ctx.strokeStyle = ctxStroke = stroke; + if (fill != ctxFill) ctx.fillStyle = ctxFill = fill; + if (width != ctxWidth) ctx.lineWidth = ctxWidth = width; + if (join != ctxJoin) ctx.lineJoin = ctxJoin = join; + if (cap != ctxCap) ctx.lineCap = ctxCap = cap; + if (dash != ctxDash) ctx.setLineDash((ctxDash = dash)); } function setFontStyle(font, fill, align, baseline) { - if (fill != ctxFill) - ctx.fillStyle = ctxFill = fill; - if (font != ctxFont) - ctx.font = ctxFont = font; - if (align != ctxAlign) - ctx.textAlign = ctxAlign = align; - if (baseline != ctxBaseline) - ctx.textBaseline = ctxBaseline = baseline; + if (fill != ctxFill) ctx.fillStyle = ctxFill = fill; + if (font != ctxFont) ctx.font = ctxFont = font; + if (align != ctxAlign) ctx.textAlign = ctxAlign = align; + if (baseline != ctxBaseline) ctx.textBaseline = ctxBaseline = baseline; } function accScale(wsc, psc, facet, data, sorted = 0) { - if (data.length > 0 && wsc.auto(self, viaAutoScaleX) && (psc == null || psc.min == null)) { + if ( + data.length > 0 && + wsc.auto(self, viaAutoScaleX) && + (psc == null || psc.min == null) + ) { let _i0 = ifNull(i0, 0); let _i1 = ifNull(i1, data.length - 1); // only run getMinMax() for invalidated series data, else reuse - let minMax = facet.min == null ? (wsc.distr == 3 ? getMinMaxLog(data, _i0, _i1) : getMinMax(data, _i0, _i1, sorted)) : [facet.min, facet.max]; + let minMax = + facet.min == null + ? wsc.distr == 3 + ? getMinMaxLog(data, _i0, _i1) + : getMinMax(data, _i0, _i1, sorted) + : [facet.min, facet.max]; // initial min/max - wsc.min = min(wsc.min, facet.min = minMax[0]); - wsc.max = max(wsc.max, facet.max = minMax[1]); + wsc.min = min(wsc.min, (facet.min = minMax[0])); + wsc.max = max(wsc.max, (facet.max = minMax[1])); } } - const AUTOSCALE = {min: null, max: null}; + const AUTOSCALE = { min: null, max: null }; function setScales() { - // log("setScales()", arguments); + // log("setScales()", arguments); // implicitly add auto scales, and unranged scales for (let k in scales) { let sc = scales[k]; - if (pendScales[k] == null && - ( - // scales that have never been set (on init) - sc.min == null || + if ( + pendScales[k] == null && + // scales that have never been set (on init) + (sc.min == null || // or auto scales when the x scale was explicitly set - pendScales[xScaleKey] != null && sc.auto(self, viaAutoScaleX) - ) + (pendScales[xScaleKey] != null && + sc.auto(self, viaAutoScaleX))) ) { pendScales[k] = AUTOSCALE; } @@ -3937,13 +4009,16 @@ function uPlot(opts, data, then) { for (let k in scales) { let sc = scales[k]; - if (pendScales[k] == null && sc.from != null && pendScales[sc.from] != null) + if ( + pendScales[k] == null && + sc.from != null && + pendScales[sc.from] != null + ) pendScales[k] = AUTOSCALE; } // explicitly setting the x-scale invalidates everything (acts as redraw) - if (pendScales[xScaleKey] != null) - resetYSeries(true); // TODO: only reset series on auto scales? + if (pendScales[xScaleKey] != null) resetYSeries(true); // TODO: only reset series on auto scales? let wipScales = {}; @@ -3951,17 +4026,15 @@ function uPlot(opts, data, then) { let psc = pendScales[k]; if (psc != null) { - let wsc = wipScales[k] = copy(scales[k], fastIsObj); + let wsc = (wipScales[k] = copy(scales[k], fastIsObj)); - if (psc.min != null) - assign(wsc, psc); + if (psc.min != null) assign(wsc, psc); else if (k != xScaleKey || mode == 2) { if (dataLen == 0 && wsc.from == null) { let minMax = wsc.range(self, null, null, k); wsc.min = minMax[0]; wsc.max = minMax[1]; - } - else { + } else { wsc.min = inf; wsc.max = -inf; } @@ -3976,8 +4049,7 @@ function uPlot(opts, data, then) { let k = s.scale; let psc = pendScales[k]; - if (psc == null) - return; + if (psc == null) return let wsc = wipScales[k]; @@ -3993,36 +4065,46 @@ function uPlot(opts, data, then) { // don't try to contract same or adjacent idxs if (i1 - i0 > 1) { // closest indices can be outside of view - if (data[0][i0] < wsc.min) - i0++; - if (data[0][i1] > wsc.max) - i1--; + if (data[0][i0] < wsc.min) i0++; + if (data[0][i1] > wsc.max) i1--; } s.min = data0[i0]; s.max = data0[i1]; - } - else if (s.show && s.auto) + } else if (s.show && s.auto) accScale(wsc, psc, s, data[i], s.sorted); s.idxs[0] = i0; s.idxs[1] = i1; - } - else { + } else { if (i > 0) { if (s.show && s.auto) { // TODO: only handles, assumes and requires facets[0] / 'x' scale, and facets[1] / 'y' scale - let [ xFacet, yFacet ] = s.facets; + let [xFacet, yFacet] = s.facets; let xScaleKey = xFacet.scale; let yScaleKey = yFacet.scale; - let [ xData, yData ] = data[i]; + let [xData, yData] = data[i]; let wscx = wipScales[xScaleKey]; let wscy = wipScales[yScaleKey]; // null can happen when only x is zoomed, but y has static range and doesnt get auto-added to pending - wscx != null && accScale(wscx, pendScales[xScaleKey], xFacet, xData, xFacet.sorted); - wscy != null && accScale(wscy, pendScales[yScaleKey], yFacet, yData, yFacet.sorted); + wscx != null && + accScale( + wscx, + pendScales[xScaleKey], + xFacet, + xData, + xFacet.sorted + ); + wscy != null && + accScale( + wscy, + pendScales[yScaleKey], + yFacet, + yData, + yFacet.sorted + ); // temp s.min = yFacet.min; @@ -4040,7 +4122,7 @@ function uPlot(opts, data, then) { if (wsc.from == null && (psc == null || psc.min == null)) { let minMax = wsc.range( self, - wsc.min == inf ? null : wsc.min, + wsc.min == inf ? null : wsc.min, wsc.max == -inf ? null : wsc.max, k ); @@ -4057,8 +4139,7 @@ function uPlot(opts, data, then) { if (wsc.from != null) { let base = wipScales[wsc.from]; - if (base.min == null) - wsc.min = wsc.max = null; + if (base.min == null) wsc.min = wsc.max = null; else { let minMax = wsc.range(self, base.min, base.max, k); wsc.min = minMax[0]; @@ -4080,8 +4161,22 @@ function uPlot(opts, data, then) { let distr = sc.distr; - sc._min = distr == 3 ? log10(sc.min) : distr == 4 ? asinh(sc.min, sc.asinh) : distr == 100 ? sc.fwd(sc.min) : sc.min; - sc._max = distr == 3 ? log10(sc.max) : distr == 4 ? asinh(sc.max, sc.asinh) : distr == 100 ? sc.fwd(sc.max) : sc.max; + sc._min = + distr == 3 + ? log10(sc.min) + : distr == 4 + ? asinh(sc.min, sc.asinh) + : distr == 100 + ? sc.fwd(sc.min) + : sc.min; + sc._max = + distr == 3 + ? log10(sc.max) + : distr == 4 + ? asinh(sc.max, sc.asinh) + : distr == 100 + ? sc.fwd(sc.max) + : sc.max; changed[k] = anyChanged = true; } @@ -4091,26 +4186,22 @@ function uPlot(opts, data, then) { // invalidate paths of all series on changed scales series.forEach((s, i) => { if (mode == 2) { - if (i > 0 && changed.y) - s._paths = null; - } - else { - if (changed[s.scale]) - s._paths = null; + if (i > 0 && changed.y) s._paths = null; + } else { + if (changed[s.scale]) s._paths = null; } }); for (let k in changed) { shouldConvergeSize = true; - fire("setScale", k); + fire('setScale', k); } if (cursor.show && cursor.left >= 0) shouldSetCursor = shouldSetLegend = true; } - for (let k in pendScales) - pendScales[k] = null; + for (let k in pendScales) pendScales[k] = null; } // grabs the nearest indices with y data outside of x-scale limits @@ -4118,13 +4209,11 @@ function uPlot(opts, data, then) { let _i0 = clamp(i0 - 1, 0, dataLen - 1); let _i1 = clamp(i1 + 1, 0, dataLen - 1); - while (ydata[_i0] == null && _i0 > 0) - _i0--; + while (ydata[_i0] == null && _i0 > 0) _i0--; - while (ydata[_i1] == null && _i1 < dataLen - 1) - _i1++; + while (ydata[_i1] == null && _i1 < dataLen - 1) _i1++; - return [_i0, _i1]; + return [_i0, _i1] } function drawSeries() { @@ -4138,11 +4227,13 @@ function uPlot(opts, data, then) { if (ctxAlpha != s.alpha) ctx.globalAlpha = ctxAlpha = s.alpha; - let _idxs = mode == 2 ? [0, data[i][0].length - 1] : getOuterIdxs(data[i]); + let _idxs = + mode == 2 + ? [0, data[i][0].length - 1] + : getOuterIdxs(data[i]); s._paths = s.paths(self, i, _idxs[0], _idxs[1]); - if (ctxAlpha != 1) - ctx.globalAlpha = ctxAlpha = 1; + if (ctxAlpha != 1) ctx.globalAlpha = ctxAlpha = 1; } } }); @@ -4161,15 +4252,20 @@ function uPlot(opts, data, then) { let idxs = s.points.filter(self, i, show, _gaps); if (show || idxs) { - s.points._paths = s.points.paths(self, i, i0, i1, idxs); + s.points._paths = s.points.paths( + self, + i, + i0, + i1, + idxs + ); drawPath(i, true); } } - if (ctxAlpha != 1) - ctx.globalAlpha = ctxAlpha = 1; + if (ctxAlpha != 1) ctx.globalAlpha = ctxAlpha = 1; - fire("drawSeries", i); + fire('drawSeries', i); } }); } @@ -4179,7 +4275,7 @@ function uPlot(opts, data, then) { let s = _points ? series[si].points : series[si]; s._stroke = s.stroke(self, si); - s._fill = s.fill(self, si); + s._fill = s.fill(self, si); } function drawPath(si, _points) { @@ -4192,8 +4288,8 @@ function uPlot(opts, data, then) { flags, _stroke: strokeStyle = s._stroke, - _fill: fillStyle = s._fill, - _width: width = s.width, + _fill: fillStyle = s._fill, + _width: width = s.width } = s._paths; width = roundDec(width * pxRatio, 3); @@ -4202,7 +4298,7 @@ function uPlot(opts, data, then) { let offset = (width % 2) / 2; if (_points && fillStyle == null) - fillStyle = width > 0 ? "#fff" : strokeStyle; + fillStyle = width > 0 ? '#fff' : strokeStyle; let _pxAlign = s.pxAlign == 1 && offset > 0; @@ -4220,54 +4316,128 @@ function uPlot(opts, data, then) { // the points pathbuilder's gapsClip is its boundsClip, since points dont need gaps clipping, and bounds depend on point size if (_points) - strokeFill(strokeStyle, width, s.dash, s.cap, fillStyle, stroke, fill, flags, gapsClip); + strokeFill( + strokeStyle, + width, + s.dash, + s.cap, + fillStyle, + stroke, + fill, + flags, + gapsClip + ); else - fillStroke(si, strokeStyle, width, s.dash, s.cap, fillStyle, stroke, fill, flags, boundsClip, gapsClip); + fillStroke( + si, + strokeStyle, + width, + s.dash, + s.cap, + fillStyle, + stroke, + fill, + flags, + boundsClip, + gapsClip + ); _pxAlign && ctx.translate(-offset, -offset); } - function fillStroke(si, strokeStyle, lineWidth, lineDash, lineCap, fillStyle, strokePath, fillPath, flags, boundsClip, gapsClip) { + function fillStroke( + si, + strokeStyle, + lineWidth, + lineDash, + lineCap, + fillStyle, + strokePath, + fillPath, + flags, + boundsClip, + gapsClip + ) { let didStrokeFill = false; // for all bands where this series is the top edge, create upwards clips using the bottom edges // and apply clips + fill with band fill or dfltFill - flags != 0 && bands.forEach((b, bi) => { - // isUpperEdge? - if (b.series[0] == si) { - let lowerEdge = series[b.series[1]]; - let lowerData = data[b.series[1]]; - - let bandClip = (lowerEdge._paths || EMPTY_OBJ).band; - - if (isArr(bandClip)) - bandClip = b.dir == 1 ? bandClip[0] : bandClip[1]; - - let gapsClip2; - - let _fillStyle = null; + flags != 0 && + bands.forEach((b, bi) => { + // isUpperEdge? + if (b.series[0] == si) { + let lowerEdge = series[b.series[1]]; + let lowerData = data[b.series[1]]; + + let bandClip = (lowerEdge._paths || EMPTY_OBJ).band; + + if (isArr(bandClip)) + bandClip = b.dir == 1 ? bandClip[0] : bandClip[1]; + + let gapsClip2; + + let _fillStyle = null; + + // hasLowerEdge? + if ( + lowerEdge.show && + bandClip && + hasData(lowerData, i0, i1) + ) { + _fillStyle = b.fill(self, bi) || fillStyle; + gapsClip2 = lowerEdge._paths.clip; + } else bandClip = null; + + strokeFill( + strokeStyle, + lineWidth, + lineDash, + lineCap, + _fillStyle, + strokePath, + fillPath, + flags, + boundsClip, + gapsClip, + gapsClip2, + bandClip + ); - // hasLowerEdge? - if (lowerEdge.show && bandClip && hasData(lowerData, i0, i1)) { - _fillStyle = b.fill(self, bi) || fillStyle; - gapsClip2 = lowerEdge._paths.clip; + didStrokeFill = true; } - else - bandClip = null; - - strokeFill(strokeStyle, lineWidth, lineDash, lineCap, _fillStyle, strokePath, fillPath, flags, boundsClip, gapsClip, gapsClip2, bandClip); - - didStrokeFill = true; - } - }); + }); if (!didStrokeFill) - strokeFill(strokeStyle, lineWidth, lineDash, lineCap, fillStyle, strokePath, fillPath, flags, boundsClip, gapsClip); + strokeFill( + strokeStyle, + lineWidth, + lineDash, + lineCap, + fillStyle, + strokePath, + fillPath, + flags, + boundsClip, + gapsClip + ); } const CLIP_FILL_STROKE = BAND_CLIP_FILL | BAND_CLIP_STROKE; - function strokeFill(strokeStyle, lineWidth, lineDash, lineCap, fillStyle, strokePath, fillPath, flags, boundsClip, gapsClip, gapsClip2, bandClip) { + function strokeFill( + strokeStyle, + lineWidth, + lineDash, + lineCap, + fillStyle, + strokePath, + fillPath, + flags, + boundsClip, + gapsClip, + gapsClip2, + bandClip + ) { setCtxStyle(strokeStyle, lineWidth, lineDash, lineCap, fillStyle); if (boundsClip || gapsClip || bandClip) { @@ -4282,13 +4452,11 @@ function uPlot(opts, data, then) { gapsClip2 && ctx.clip(gapsClip2); doFill(fillStyle, fillPath); doStroke(strokeStyle, strokePath, lineWidth); - } - else if (flags & BAND_CLIP_STROKE) { + } else if (flags & BAND_CLIP_STROKE) { doFill(fillStyle, fillPath); ctx.clip(bandClip); doStroke(strokeStyle, strokePath, lineWidth); - } - else if (flags & BAND_CLIP_FILL) { + } else if (flags & BAND_CLIP_FILL) { ctx.save(); ctx.clip(bandClip); gapsClip2 && ctx.clip(gapsClip2); @@ -4296,14 +4464,12 @@ function uPlot(opts, data, then) { ctx.restore(); doStroke(strokeStyle, strokePath, lineWidth); } - } - else { + } else { doFill(fillStyle, fillPath); doStroke(strokeStyle, strokePath, lineWidth); } - if (boundsClip || gapsClip || bandClip) - ctx.restore(); + if (boundsClip || gapsClip || bandClip) ctx.restore(); } function doStroke(strokeStyle, strokePath, lineWidth) { @@ -4313,9 +4479,7 @@ function uPlot(opts, data, then) { ctx.strokeStyle = ctxStroke = strokeStyle; ctx.stroke(strokePath); }); - } - else - strokePath != null && strokeStyle && ctx.stroke(strokePath); + } else strokePath != null && strokeStyle && ctx.stroke(strokePath); } } @@ -4325,9 +4489,7 @@ function uPlot(opts, data, then) { ctx.fillStyle = ctxFill = fillStyle; ctx.fill(fillPath); }); - } - else - fillPath != null && fillStyle && ctx.fill(fillPath); + } else fillPath != null && fillStyle && ctx.fill(fillPath); } function getIncrSpace(axisIdx, min, max, fullDim) { @@ -4335,18 +4497,41 @@ function uPlot(opts, data, then) { let incrSpace; - if (fullDim <= 0) - incrSpace = [0, 0]; + if (fullDim <= 0) incrSpace = [0, 0]; else { - let minSpace = axis._space = axis.space(self, axisIdx, min, max, fullDim); - let incrs = axis._incrs = axis.incrs(self, axisIdx, min, max, fullDim, minSpace); - incrSpace = findIncr(min, max, incrs, fullDim, minSpace); + let minSpace = (axis._space = axis.space( + self, + axisIdx, + min, + max, + fullDim + )); + let incrs = (axis._incrs = axis.incrs( + self, + axisIdx, + min, + max, + fullDim, + minSpace + )); + incrSpace = findIncr(min, max, incrs, fullDim, minSpace); } - return (axis._found = incrSpace); - } - - function drawOrthoLines(offs, filts, ori, side, pos0, len, width, stroke, dash, cap) { + return (axis._found = incrSpace) + } + + function drawOrthoLines( + offs, + filts, + ori, + side, + pos0, + len, + width, + stroke, + dash, + cap + ) { let offset = (width % 2) / 2; pxAlign == 1 && ctx.translate(offset, offset); @@ -4355,23 +4540,24 @@ function uPlot(opts, data, then) { ctx.beginPath(); - let x0, y0, x1, y1, pos1 = pos0 + (side == 0 || side == 3 ? -len : len); + let x0, + y0, + x1, + y1, + pos1 = pos0 + (side == 0 || side == 3 ? -len : len); if (ori == 0) { y0 = pos0; y1 = pos1; - } - else { + } else { x0 = pos0; x1 = pos1; } for (let i = 0; i < offs.length; i++) { if (filts[i] != null) { - if (ori == 0) - x0 = x1 = offs[i]; - else - y0 = y1 = offs[i]; + if (ori == 0) x0 = x1 = offs[i]; + else y0 = y1 = offs[i]; ctx.moveTo(x0, y0); ctx.lineTo(x1, y1); @@ -4384,13 +4570,12 @@ function uPlot(opts, data, then) { } function axesCalc(cycleNum) { - // log("axesCalc()", arguments); + // log("axesCalc()", arguments); let converged = true; axes.forEach((axis, i) => { - if (!axis.show) - return; + if (!axis.show) return let scale = scales[axis.scale]; @@ -4400,9 +4585,8 @@ function uPlot(opts, data, then) { axis._show = false; resetYSeries(false); } - return; - } - else { + return + } else { if (!axis._show) { converged = false; axis._show = true; @@ -4413,24 +4597,45 @@ function uPlot(opts, data, then) { let side = axis.side; let ori = side % 2; - let {min, max} = scale; // // should this toggle them ._show = false + let { min, max } = scale; // // should this toggle them ._show = false - let [_incr, _space] = getIncrSpace(i, min, max, ori == 0 ? plotWidCss : plotHgtCss); + let [_incr, _space] = getIncrSpace( + i, + min, + max, + ori == 0 ? plotWidCss : plotHgtCss + ); - if (_space == 0) - return; + if (_space == 0) return // if we're using index positions, force first tick to match passed index let forceMin = scale.distr == 2; - let _splits = axis._splits = axis.splits(self, i, min, max, _incr, _space, forceMin); + let _splits = (axis._splits = axis.splits( + self, + i, + min, + max, + _incr, + _space, + forceMin + )); // tick labels // BOO this assumes a specific data/series - let splits = scale.distr == 2 ? _splits.map(i => data0[i]) : _splits; - let incr = scale.distr == 2 ? data0[_splits[1]] - data0[_splits[0]] : _incr; - - let values = axis._values = axis.values(self, axis.filter(self, splits, i, _space, incr), i, _space, incr); + let splits = + scale.distr == 2 ? _splits.map((i) => data0[i]) : _splits; + let incr = + scale.distr == 2 ? data0[_splits[1]] - data0[_splits[0]] : _incr; + + let values = (axis._values = axis.values( + self, + axis.filter(self, splits, i, _space, incr), + i, + _space, + incr, + fmtNum + )); // rotating of labels only supported on bottom x axis axis._rotate = side == 2 ? axis.rotate(self, values, i, _space) : 0; @@ -4439,11 +4644,12 @@ function uPlot(opts, data, then) { axis._size = ceil(axis.size(self, values, i, cycleNum)); - if (oldSize != null && axis._size != oldSize) // ready && ? + if (oldSize != null && axis._size != oldSize) + // ready && ? converged = false; }); - return converged; + return converged } function paddingCalc(cycleNum) { @@ -4452,21 +4658,19 @@ function uPlot(opts, data, then) { padding.forEach((p, i) => { let _p = p(self, i, sidesWithAxes, cycleNum); - if (_p != _padding[i]) - converged = false; + if (_p != _padding[i]) converged = false; _padding[i] = _p; }); - return converged; + return converged } function drawAxesGrid() { for (let i = 0; i < axes.length; i++) { let axis = axes[i]; - if (!axis.show || !axis._show) - continue; + if (!axis.show || !axis._show) continue let side = axis.side; let ori = side % 2; @@ -4482,21 +4686,21 @@ function uPlot(opts, data, then) { let shiftAmt = axis.labelGap * shiftDir; let baseLpos = round((axis._lpos + shiftAmt) * pxRatio); - setFontStyle(axis.labelFont[0], fillStyle, "center", side == 2 ? TOP : BOTTOM); + setFontStyle( + axis.labelFont[0], + fillStyle, + 'center', + side == 2 ? TOP : BOTTOM + ); ctx.save(); if (ori == 1) { x = y = 0; - ctx.translate( - baseLpos, - round(plotTop + plotHgt / 2), - ); + ctx.translate(baseLpos, round(plotTop + plotHgt / 2)); ctx.rotate((side == 3 ? -PI : PI) / 2); - - } - else { + } else { x = round(plotLft + plotWid / 2); y = baseLpos; } @@ -4508,8 +4712,7 @@ function uPlot(opts, data, then) { let [_incr, _space] = axis._found; - if (_space == 0) - continue; + if (_space == 0) continue let scale = scales[axis.scale]; @@ -4522,36 +4725,49 @@ function uPlot(opts, data, then) { // tick labels // BOO this assumes a specific data/series - let splits = scale.distr == 2 ? _splits.map(i => data0[i]) : _splits; - let incr = scale.distr == 2 ? data0[_splits[1]] - data0[_splits[0]] : _incr; + let splits = + scale.distr == 2 ? _splits.map((i) => data0[i]) : _splits; + let incr = + scale.distr == 2 ? data0[_splits[1]] - data0[_splits[0]] : _incr; let ticks = axis.ticks; let border = axis.border; let tickSize = ticks.show ? round(ticks.size * pxRatio) : 0; // rotating of labels only supported on bottom x axis - let angle = axis._rotate * -PI/180; + let angle = (axis._rotate * -PI) / 180; - let basePos = pxRound(axis._pos * pxRatio); + let basePos = pxRound(axis._pos * pxRatio); let shiftAmt = (tickSize + axisGap) * shiftDir; let finalPos = basePos + shiftAmt; - y = ori == 0 ? finalPos : 0; - x = ori == 1 ? finalPos : 0; - - let font = axis.font[0]; - let textAlign = axis.align == 1 ? LEFT : - axis.align == 2 ? RIGHT : - angle > 0 ? LEFT : - angle < 0 ? RIGHT : - ori == 0 ? "center" : side == 3 ? RIGHT : LEFT; - let textBaseline = angle || - ori == 1 ? "middle" : side == 2 ? TOP : BOTTOM; + y = ori == 0 ? finalPos : 0; + x = ori == 1 ? finalPos : 0; + + let font = axis.font[0]; + let textAlign = + axis.align == 1 + ? LEFT + : axis.align == 2 + ? RIGHT + : angle > 0 + ? LEFT + : angle < 0 + ? RIGHT + : ori == 0 + ? 'center' + : side == 3 + ? RIGHT + : LEFT; + let textBaseline = + angle || ori == 1 ? 'middle' : side == 2 ? TOP : BOTTOM; setFontStyle(font, fillStyle, textAlign, textBaseline); let lineHeight = axis.font[1] * axis.lineGap; - let canOffs = _splits.map(val => pxRound(getPos(val, scale, plotDim, plotOff))); + let canOffs = _splits.map((val) => + pxRound(getPos(val, scale, plotDim, plotOff)) + ); let _values = axis._values; @@ -4559,14 +4775,13 @@ function uPlot(opts, data, then) { let val = _values[i]; if (val != null) { - if (ori == 0) - x = canOffs[i]; - else - y = canOffs[i]; + if (ori == 0) x = canOffs[i]; + else y = canOffs[i]; - val = "" + val; + val = '' + val; - let _parts = val.indexOf("\n") == -1 ? [val] : val.split(/\n/gm); + let _parts = + val.indexOf('\n') == -1 ? [val] : val.split(/\n/gm); for (let j = 0; j < _parts.length; j++) { let text = _parts[j]; @@ -4577,9 +4792,7 @@ function uPlot(opts, data, then) { ctx.rotate(angle); // can this be done once? ctx.fillText(text, 0, 0); ctx.restore(); - } - else - ctx.fillText(text, x, y + j * lineHeight); + } else ctx.fillText(text, x, y + j * lineHeight); } } } @@ -4596,7 +4809,7 @@ function uPlot(opts, data, then) { roundDec(ticks.width * pxRatio, 3), ticks.stroke(self, i), ticks.dash, - ticks.cap, + ticks.cap ); } @@ -4614,7 +4827,7 @@ function uPlot(opts, data, then) { roundDec(grid.width * pxRatio, 3), grid.stroke(self, i), grid.dash, - grid.cap, + grid.cap ); } @@ -4629,16 +4842,16 @@ function uPlot(opts, data, then) { roundDec(border.width * pxRatio, 3), border.stroke(self, i), border.dash, - border.cap, + border.cap ); } } - fire("drawAxes"); + fire('drawAxes'); } function resetYSeries(minMax) { - // log("resetYSeries()", arguments); + // log("resetYSeries()", arguments); series.forEach((s, i) => { if (i > 0) { @@ -4648,9 +4861,8 @@ function uPlot(opts, data, then) { if (mode == 1) { s.min = null; s.max = null; - } - else { - s.facets.forEach(f => { + } else { + s.facets.forEach((f) => { f.min = null; f.max = null; }); @@ -4667,8 +4879,7 @@ function uPlot(opts, data, then) { function flushHooks() { deferHooks = false; - for (let i = 0; i < hooksQueue.length; i++) - fire(...hooksQueue[i]); + for (let i = 0; i < hooksQueue.length; i++) fire(...hooksQueue[i]); hooksQueue.length = 0; } @@ -4688,14 +4899,13 @@ function uPlot(opts, data, then) { fn(self); _commit(); - if (_deferHooks && hooksQueue.length > 0) - queueMicrotask(flushHooks); + if (_deferHooks && hooksQueue.length > 0) queueMicrotask(flushHooks); } self.batch = batch; function _commit() { - // log("_commit()", arguments); + // log("_commit()", arguments); if (shouldSetScales) { setScales(); @@ -4708,44 +4918,59 @@ function uPlot(opts, data, then) { } if (shouldSetSize) { - setStylePx(under, LEFT, plotLftCss); - setStylePx(under, TOP, plotTopCss); - setStylePx(under, WIDTH, plotWidCss); + setStylePx(under, LEFT, plotLftCss); + setStylePx(under, TOP, plotTopCss); + setStylePx(under, WIDTH, plotWidCss); setStylePx(under, HEIGHT, plotHgtCss); - setStylePx(over, LEFT, plotLftCss); - setStylePx(over, TOP, plotTopCss); - setStylePx(over, WIDTH, plotWidCss); - setStylePx(over, HEIGHT, plotHgtCss); + setStylePx(over, LEFT, plotLftCss); + setStylePx(over, TOP, plotTopCss); + setStylePx(over, WIDTH, plotWidCss); + setStylePx(over, HEIGHT, plotHgtCss); - setStylePx(wrap, WIDTH, fullWidCss); - setStylePx(wrap, HEIGHT, fullHgtCss); + setStylePx(wrap, WIDTH, fullWidCss); + setStylePx(wrap, HEIGHT, fullHgtCss); // NOTE: mutating this during print preview in Chrome forces transparent // canvas pixels to white, even when followed up with clearRect() below - can.width = round(fullWidCss * pxRatio); + can.width = round(fullWidCss * pxRatio); can.height = round(fullHgtCss * pxRatio); axes.forEach(({ _el, _show, _size, _pos, side }) => { if (_el != null) { if (_show) { - let posOffset = (side === 3 || side === 0 ? _size : 0); + let posOffset = side === 3 || side === 0 ? _size : 0; let isVt = side % 2 == 1; - setStylePx(_el, isVt ? "left" : "top", _pos - posOffset); - setStylePx(_el, isVt ? "width" : "height", _size); - setStylePx(_el, isVt ? "top" : "left", isVt ? plotTopCss : plotLftCss); - setStylePx(_el, isVt ? "height" : "width", isVt ? plotHgtCss : plotWidCss); + setStylePx(_el, isVt ? 'left' : 'top', _pos - posOffset); + setStylePx(_el, isVt ? 'width' : 'height', _size); + setStylePx( + _el, + isVt ? 'top' : 'left', + isVt ? plotTopCss : plotLftCss + ); + setStylePx( + _el, + isVt ? 'height' : 'width', + isVt ? plotHgtCss : plotWidCss + ); remClass(_el, OFF); - } - else - addClass(_el, OFF); + } else addClass(_el, OFF); } }); // invalidate ctx style cache - ctxStroke = ctxFill = ctxWidth = ctxJoin = ctxCap = ctxFont = ctxAlign = ctxBaseline = ctxDash = null; + ctxStroke = + ctxFill = + ctxWidth = + ctxJoin = + ctxCap = + ctxFont = + ctxAlign = + ctxBaseline = + ctxDash = + null; ctxAlpha = 1; syncRect(true); @@ -4763,10 +4988,24 @@ function uPlot(opts, data, then) { if (cursor.show && !shouldSetCursor && cursor.left >= 0) { cursor.left *= pctWid; - cursor.top *= pctHgt; - - vCursor && elTrans(vCursor, round(cursor.left), 0, plotWidCss, plotHgtCss); - hCursor && elTrans(hCursor, 0, round(cursor.top), plotWidCss, plotHgtCss); + cursor.top *= pctHgt; + + vCursor && + elTrans( + vCursor, + round(cursor.left), + 0, + plotWidCss, + plotHgtCss + ); + hCursor && + elTrans( + hCursor, + 0, + round(cursor.top), + plotWidCss, + plotHgtCss + ); for (let i = 0; i < cursorPts.length; i++) { let pt = cursorPts[i]; @@ -4774,15 +5013,26 @@ function uPlot(opts, data, then) { if (pt != null) { cursorPtsLft[i] *= pctWid; cursorPtsTop[i] *= pctHgt; - elTrans(pt, ceil(cursorPtsLft[i]), ceil(cursorPtsTop[i]), plotWidCss, plotHgtCss); + elTrans( + pt, + ceil(cursorPtsLft[i]), + ceil(cursorPtsTop[i]), + plotWidCss, + plotHgtCss + ); } } } - if (select.show && !shouldSetSelect && select.left >= 0 && select.width > 0) { - select.left *= pctWid; - select.width *= pctWid; - select.top *= pctHgt; + if ( + select.show && + !shouldSetSelect && + select.left >= 0 && + select.width > 0 + ) { + select.left *= pctWid; + select.width *= pctWid; + select.top *= pctHgt; select.height *= pctHgt; for (let prop in _hideProps) @@ -4795,16 +5045,16 @@ function uPlot(opts, data, then) { _plotHgtCss = plotHgtCss; } - fire("setSize"); + fire('setSize'); shouldSetSize = false; } if (fullWidCss > 0 && fullHgtCss > 0) { ctx.clearRect(0, 0, can.width, can.height); - fire("drawClear"); - drawOrder.forEach(fn => fn()); - fire("draw"); + fire('drawClear'); + drawOrder.forEach((fn) => fn()); + fire('draw'); } if (select.show && shouldSetSelect) { @@ -4826,7 +5076,7 @@ function uPlot(opts, data, then) { ready = true; self.status = 1; - fire("ready"); + fire('ready'); } viaAutoScaleX = false; @@ -4837,10 +5087,8 @@ function uPlot(opts, data, then) { self.redraw = (rebuildPaths, recalcAxes) => { shouldConvergeSize = recalcAxes || false; - if (rebuildPaths !== false) - _setScale(xScaleKey, scaleX.min, scaleX.max); - else - commit(); + if (rebuildPaths !== false) _setScale(xScaleKey, scaleX.min, scaleX.max); + else commit(); }; // redraw() => setScale('x', scales.x.min, scales.x.max); @@ -4862,20 +5110,24 @@ function uPlot(opts, data, then) { opts.max = _min; } - if (dataLen > 1 && opts.min != null && opts.max != null && opts.max - opts.min < 1e-16) - return; + if ( + dataLen > 1 && + opts.min != null && + opts.max != null && + opts.max - opts.min < 1e-16 + ) + return if (key == xScaleKey) { if (sc.distr == 2 && dataLen > 0) { opts.min = closestIdx(opts.min, data[0]); opts.max = closestIdx(opts.max, data[0]); - if (opts.min == opts.max) - opts.max++; + if (opts.min == opts.max) opts.max++; } } - // log("setScale()", arguments); + // log("setScale()", arguments); pendScales[key] = opts; @@ -4886,7 +5138,7 @@ function uPlot(opts, data, then) { self.setScale = setScale; -// INTERACTION + // INTERACTION let xCursor; let yCursor; @@ -4917,16 +5169,13 @@ function uPlot(opts, data, then) { let dragY = drag.y; if (cursor.show) { - if (cursor.x) - xCursor = placeDiv(CURSOR_X, over); - if (cursor.y) - yCursor = placeDiv(CURSOR_Y, over); + if (cursor.x) xCursor = placeDiv(CURSOR_X, over); + if (cursor.y) yCursor = placeDiv(CURSOR_Y, over); if (scaleX.ori == 0) { vCursor = xCursor; hCursor = yCursor; - } - else { + } else { vCursor = yCursor; hCursor = xCursor; } @@ -4935,27 +5184,31 @@ function uPlot(opts, data, then) { mouseTop1 = cursor.top; } - const select = self.select = assign({ - show: true, - over: true, - left: 0, - width: 0, - top: 0, - height: 0, - }, opts.select); + const select = (self.select = assign( + { + show: true, + over: true, + left: 0, + width: 0, + top: 0, + height: 0 + }, + opts.select + )); - const selectDiv = select.show ? placeDiv(SELECT, select.over ? over : under) : null; + const selectDiv = select.show + ? placeDiv(SELECT, select.over ? over : under) + : null; function setSelect(opts, _fire) { if (select.show) { for (let prop in opts) { select[prop] = opts[prop]; - if (prop in _hideProps) - setStylePx(selectDiv, prop, opts[prop]); + if (prop in _hideProps) setStylePx(selectDiv, prop, opts[prop]); } - _fire !== false && fire("setSelect"); + _fire !== false && fire('setSelect'); } } @@ -4965,8 +5218,7 @@ function uPlot(opts, data, then) { let s = series[i]; let label = showLegend ? legendRows[i] : null; - if (s.show) - label && remClass(label, OFF); + if (s.show) label && remClass(label, OFF); else { label && addClass(label, OFF); let pt = cursorOnePt ? cursorPts[0] : cursorPts[i]; @@ -4975,14 +5227,13 @@ function uPlot(opts, data, then) { } function _setScale(key, min, max) { - setScale(key, {min, max}); + setScale(key, { min, max }); } function setSeries(i, opts, _fire, _pub) { - // log("setSeries()", arguments); + // log("setSeries()", arguments); - if (opts.focus != null) - setFocus(i); + if (opts.focus != null) setFocus(i); if (opts.show != null) { series.forEach((s, si) => { @@ -4993,18 +5244,16 @@ function uPlot(opts, data, then) { if (mode == 2) { _setScale(s.facets[0].scale, null, null); _setScale(s.facets[1].scale, null, null); - } - else - _setScale(s.scale, null, null); + } else _setScale(s.scale, null, null); commit(); } }); } - _fire !== false && fire("setSeries", i, opts); + _fire !== false && fire('setSeries', i, opts); - _pub && pubSync("setSeries", self, i, opts); + _pub && pubSync('setSeries', self, i, opts); } self.setSeries = setSeries; @@ -5021,10 +5270,8 @@ function uPlot(opts, data, then) { } function delBand(bi) { - if (bi == null) - bands.length = 0; - else - bands.splice(bi, 1); + if (bi == null) bands.length = 0; + else bands.splice(bi, 1); } self.addBand = addBand; @@ -5034,8 +5281,7 @@ function uPlot(opts, data, then) { function setAlpha(i, value) { series[i].alpha = value; - if (cursor.show && cursorPts[i]) - cursorPts[i].style.opacity = value; + if (cursor.show && cursorPts[i]) cursorPts[i].style.opacity = value; if (showLegend && legendRows[i]) legendRows[i].style.opacity = value; @@ -5045,11 +5291,11 @@ function uPlot(opts, data, then) { let closestDist; let closestSeries; let focusedSeries; - const FOCUS_TRUE = {focus: true}; + const FOCUS_TRUE = { focus: true }; function setFocus(i) { if (i != focusedSeries) { - // log("setFocus()", arguments); + // log("setFocus()", arguments); let allFocused = i == null; @@ -5069,9 +5315,8 @@ function uPlot(opts, data, then) { } if (showLegend && cursorFocus) { - onMouse(mouseleave, legendTable, e => { - if (cursor._lock) - return; + onMouse(mouseleave, legendTable, (e) => { + if (cursor._lock) return setCursorEvent(e); @@ -5083,8 +5328,7 @@ function uPlot(opts, data, then) { function posToVal(pos, scale, can) { let sc = scales[scale]; - if (can) - pos = pos / pxRatio - (sc.ori == 1 ? plotTopCss : plotLftCss); + if (can) pos = pos / pxRatio - (sc.ori == 1 ? plotTopCss : plotLftCss); let dim = plotWidCss; @@ -5093,8 +5337,7 @@ function uPlot(opts, data, then) { pos = dim - pos; } - if (sc.dir == -1) - pos = dim - pos; + if (sc.dir == -1) pos = dim - pos; let _min = sc._min, _max = sc._max, @@ -5104,49 +5347,53 @@ function uPlot(opts, data, then) { let distr = sc.distr; - return ( - distr == 3 ? pow(10, sv) : - distr == 4 ? sinh(sv, sc.asinh) : - distr == 100 ? sc.bwd(sv) : - sv - ); + return distr == 3 + ? pow(10, sv) + : distr == 4 + ? sinh(sv, sc.asinh) + : distr == 100 + ? sc.bwd(sv) + : sv } function closestIdxFromXpos(pos, can) { let v = posToVal(pos, xScaleKey, can); - return closestIdx(v, data[0], i0, i1); + return closestIdx(v, data[0], i0, i1) } - self.valToIdx = val => closestIdx(val, data[0]); + self.valToIdx = (val) => closestIdx(val, data[0]); self.posToIdx = closestIdxFromXpos; self.posToVal = posToVal; - self.valToPos = (val, scale, can) => ( - scales[scale].ori == 0 ? - getHPos(val, scales[scale], - can ? plotWid : plotWidCss, - can ? plotLft : 0, - ) : - getVPos(val, scales[scale], - can ? plotHgt : plotHgtCss, - can ? plotTop : 0, - ) - ); + self.valToPos = (val, scale, can) => + scales[scale].ori == 0 + ? getHPos( + val, + scales[scale], + can ? plotWid : plotWidCss, + can ? plotLft : 0 + ) + : getVPos( + val, + scales[scale], + can ? plotHgt : plotHgtCss, + can ? plotTop : 0 + ); self.setCursor = (opts, _fire, _pub) => { mouseLeft1 = opts.left; mouseTop1 = opts.top; - // assign(cursor, opts); + // assign(cursor, opts); updateCursor(null, _fire, _pub); }; function setSelH(off, dim) { - setStylePx(selectDiv, LEFT, select.left = off); - setStylePx(selectDiv, WIDTH, select.width = dim); + setStylePx(selectDiv, LEFT, (select.left = off)); + setStylePx(selectDiv, WIDTH, (select.width = dim)); } function setSelV(off, dim) { - setStylePx(selectDiv, TOP, select.top = off); - setStylePx(selectDiv, HEIGHT, select.height = dim); + setStylePx(selectDiv, TOP, (select.top = off)); + setStylePx(selectDiv, HEIGHT, (select.height = dim)); } let setSelX = scaleX.ori == 0 ? setSelH : setSelV; @@ -5155,8 +5402,7 @@ function uPlot(opts, data, then) { function syncLegend() { if (showLegend && legend.live) { for (let i = mode == 2 ? 1 : 0; i < series.length; i++) { - if (i == 0 && multiValLegend) - continue; + if (i == 0 && multiValLegend) continue let vals = legend.values[i]; @@ -5174,16 +5420,14 @@ function uPlot(opts, data, then) { opts.idxs.forEach((didx, sidx) => { activeIdxs[sidx] = didx; }); - } - else if (!isUndef(opts.idx)) - activeIdxs.fill(opts.idx); + } else if (!isUndef(opts.idx)) activeIdxs.fill(opts.idx); legend.idx = activeIdxs[0]; } if (showLegend && legend.live) { for (let sidx = 0; sidx < series.length; sidx++) { - if (sidx > 0 || mode == 1 && !multiValLegend) + if (sidx > 0 || (mode == 1 && !multiValLegend)) setLegendValues(sidx, activeIdxs[sidx]); } @@ -5192,7 +5436,7 @@ function uPlot(opts, data, then) { shouldSetLegend = false; - _fire !== false && fire("setLegend"); + _fire !== false && fire('setLegend'); } self.setLegend = setLegend; @@ -5205,27 +5449,35 @@ function uPlot(opts, data, then) { if (multiValLegend) val = s.values(self, sidx, idx) ?? NULL_LEGEND_VALUES; else { - val = s.value(self, idx == null ? null : src[idx], sidx, idx); - val = val == null ? NULL_LEGEND_VALUES : {_: val}; + val = s.value( + self, + idx == null ? null : src[idx], + sidx, + idx, + fmtNum + ); + val = val == null ? NULL_LEGEND_VALUES : { _: val }; } legend.values[sidx] = val; } function updateCursor(src, _fire, _pub) { - // ts == null && log("updateCursor()", arguments); + // ts == null && log("updateCursor()", arguments); rawMouseLeft1 = mouseLeft1; - rawMouseTop1 = mouseTop1; + rawMouseTop1 = mouseTop1 - [mouseLeft1, mouseTop1] = cursor.move(self, mouseLeft1, mouseTop1); + ;[mouseLeft1, mouseTop1] = cursor.move(self, mouseLeft1, mouseTop1); cursor.left = mouseLeft1; cursor.top = mouseTop1; if (cursor.show) { - vCursor && elTrans(vCursor, round(mouseLeft1), 0, plotWidCss, plotHgtCss); - hCursor && elTrans(hCursor, 0, round(mouseTop1), plotWidCss, plotHgtCss); + vCursor && + elTrans(vCursor, round(mouseLeft1), 0, plotWidCss, plotHgtCss); + hCursor && + elTrans(hCursor, 0, round(mouseTop1), plotWidCss, plotHgtCss); } let idx; @@ -5251,15 +5503,19 @@ function uPlot(opts, data, then) { } if (cursorFocus) - setSeries(null, FOCUS_TRUE, true, src == null && syncOpts.setSeries); + setSeries( + null, + FOCUS_TRUE, + true, + src == null && syncOpts.setSeries + ); if (legend.live) { activeIdxs.fill(idx); shouldSetLegend = true; } - } - else { - // let pctY = 1 - (y / rect.height); + } else { + // let pctY = 1 - (y / rect.height); let mouseXPos, valAtPosX, xPos; @@ -5282,25 +5538,56 @@ function uPlot(opts, data, then) { for (let i = mode == 2 ? 1 : 0; i < series.length; i++) { let s = series[i]; - let idx1 = activeIdxs[i]; - let yVal1 = idx1 == null ? null : (mode == 1 ? data[i][idx1] : data[i][1][idx1]); - - let idx2 = cursor.dataIdx(self, i, idx, valAtPosX); - let yVal2 = idx2 == null ? null : (mode == 1 ? data[i][idx2] : data[i][1][idx2]); - - shouldSetLegend = shouldSetLegend || yVal2 != yVal1 || idx2 != idx1; + let idx1 = activeIdxs[i]; + let yVal1 = + idx1 == null + ? null + : mode == 1 + ? data[i][idx1] + : data[i][1][idx1]; + + let idx2 = cursor.dataIdx(self, i, idx, valAtPosX); + let yVal2 = + idx2 == null + ? null + : mode == 1 + ? data[i][idx2] + : data[i][1][idx2]; + + shouldSetLegend = + shouldSetLegend || yVal2 != yVal1 || idx2 != idx1; activeIdxs[i] = idx2; - let xPos2 = idx2 == idx ? xPos : valToPosX(mode == 1 ? data[0][idx2] : data[i][0][idx2], scaleX, xDim, 0); + let xPos2 = + idx2 == idx + ? xPos + : valToPosX( + mode == 1 ? data[0][idx2] : data[i][0][idx2], + scaleX, + xDim, + 0 + ); if (i > 0 && s.show) { // this doesnt really work for state timeline, heatmap, status history (where the value maps to color, not y coords) - let yPos = yVal2 == null ? -10 : valToPosY(yVal2, mode == 1 ? scales[s.scale] : scales[s.facets[1].scale], yDim, 0); + let yPos = + yVal2 == null + ? -10 + : valToPosY( + yVal2, + mode == 1 + ? scales[s.scale] + : scales[s.facets[1].scale], + yDim, + 0 + ); if (cursorFocus && yVal2 != null) { let mouseYPos = scaleX.ori == 1 ? mouseLeft1 : mouseTop1; - let dist = abs(focus.dist(self, i, idx2, yPos, mouseYPos)); + let dist = abs( + focus.dist(self, i, idx2, yPos, mouseYPos) + ); if (dist < closestDist) { let bias = focus.bias; @@ -5308,21 +5595,25 @@ function uPlot(opts, data, then) { if (bias != 0) { let mouseYVal = posToVal(mouseYPos, s.scale); - let seriesYValSign = yVal2 >= 0 ? 1 : -1; - let mouseYValSign = mouseYVal >= 0 ? 1 : -1; + let seriesYValSign = yVal2 >= 0 ? 1 : -1; + let mouseYValSign = mouseYVal >= 0 ? 1 : -1; // with a focus bias, we will never cross zero when prox testing // it's either closest towards zero, or closest away from zero - if (mouseYValSign == seriesYValSign && ( - mouseYValSign == 1 ? - (bias == 1 ? yVal2 >= mouseYVal : yVal2 <= mouseYVal) : // >= 0 - (bias == 1 ? yVal2 <= mouseYVal : yVal2 >= mouseYVal) // < 0 - )) { + if ( + mouseYValSign == seriesYValSign && + (mouseYValSign == 1 + ? bias == 1 + ? yVal2 >= mouseYVal + : yVal2 <= mouseYVal // >= 0 + : bias == 1 + ? yVal2 <= mouseYVal + : yVal2 >= mouseYVal) // < 0 + ) { closestDist = dist; closestSeries = i; } - } - else { + } else { closestDist = dist; closestSeries = i; } @@ -5335,14 +5626,17 @@ function uPlot(opts, data, then) { if (scaleX.ori == 0) { hPos = xPos2; vPos = yPos; - } - else { + } else { hPos = yPos; vPos = xPos2; } - let ptWid, ptHgt, ptLft, ptTop, - ptStroke, ptFill, + let ptWid, + ptHgt, + ptLft, + ptTop, + ptStroke, + ptFill, centered = true, getBBox = points.bbox; @@ -5355,8 +5649,7 @@ function uPlot(opts, data, then) { ptTop = bbox.top; ptWid = bbox.width; ptHgt = bbox.height; - } - else { + } else { ptLft = hPos; ptTop = vPos; ptWid = ptHgt = points.size(self, i); @@ -5366,7 +5659,10 @@ function uPlot(opts, data, then) { ptStroke = points.stroke(self, i); if (cursorOnePt) { - if (i == closestSeries && closestDist <= focus.prox) { + if ( + i == closestSeries && + closestDist <= focus.prox + ) { _ptLft = ptLft; _ptTop = ptTop; _ptWid = ptWid; @@ -5375,8 +5671,7 @@ function uPlot(opts, data, then) { _ptFill = ptFill; _ptStroke = ptStroke; } - } - else { + } else { let pt = cursorPts[i]; if (pt != null) { @@ -5385,7 +5680,13 @@ function uPlot(opts, data, then) { elSize(pt, ptWid, ptHgt, centered); elColor(pt, ptFill, ptStroke); - elTrans(pt, ceil(ptLft), ceil(ptTop), plotWidCss, plotHgtCss); + elTrans( + pt, + ceil(ptLft), + ceil(ptTop), + plotWidCss, + plotHgtCss + ); } } } @@ -5399,7 +5700,10 @@ function uPlot(opts, data, then) { let p = focus.prox; - let focusChanged = focusedSeries == null ? closestDist <= p : (closestDist > p || closestSeries != focusedSeries); + let focusChanged = + focusedSeries == null + ? closestDist <= p + : closestDist > p || closestSeries != focusedSeries; if (shouldSetLegend || focusChanged) { let pt = cursorPts[0]; @@ -5409,7 +5713,13 @@ function uPlot(opts, data, then) { elSize(pt, _ptWid, _ptHgt, _centered); elColor(pt, _ptFill, _ptStroke); - elTrans(pt, ceil(_ptLft), ceil(_ptTop), plotWidCss, plotHgtCss); + elTrans( + pt, + ceil(_ptLft), + ceil(_ptTop), + plotWidCss, + plotHgtCss + ); } } } @@ -5441,46 +5751,47 @@ function uPlot(opts, data, then) { if (sori == 0) { sOff = left; sDim = width; - } - else { + } else { sOff = top; sDim = height; } sc = scales[xKey]; - a = valToPosX(sPosToVal(sOff, xKeySrc), sc, xDim, 0); - b = valToPosX(sPosToVal(sOff + sDim, xKeySrc), sc, xDim, 0); + a = valToPosX(sPosToVal(sOff, xKeySrc), sc, xDim, 0); + b = valToPosX( + sPosToVal(sOff + sDim, xKeySrc), + sc, + xDim, + 0 + ); - setSelX(min(a,b), abs(b-a)); - } - else - setSelX(0, xDim); + setSelX(min(a, b), abs(b - a)); + } else setSelX(0, xDim); if (matchingY && dragY) { if (sori == 1) { sOff = left; sDim = width; - } - else { + } else { sOff = top; sDim = height; } sc = scales[yKey]; - a = valToPosY(sPosToVal(sOff, yKeySrc), sc, yDim, 0); - b = valToPosY(sPosToVal(sOff + sDim, yKeySrc), sc, yDim, 0); + a = valToPosY(sPosToVal(sOff, yKeySrc), sc, yDim, 0); + b = valToPosY( + sPosToVal(sOff + sDim, yKeySrc), + sc, + yDim, + 0 + ); - setSelY(min(a,b), abs(b-a)); - } - else - setSelY(0, yDim); - } - else - hideSelect(); - } - else { + setSelY(min(a, b), abs(b - a)); + } else setSelY(0, yDim); + } else hideSelect(); + } else { let rawDX = abs(rawMouseLeft1 - rawMouseLeft0); let rawDY = abs(rawMouseTop1 - rawMouseTop0); @@ -5503,14 +5814,11 @@ function uPlot(opts, data, then) { // force unidirectionality when both are under uni limit if (!dragX && !dragY) { - if (rawDY > rawDX) - dragY = true; - else - dragX = true; + if (rawDY > rawDX) dragY = true; + else dragX = true; } } - } - else if (drag.x && drag.y && (dragX || dragY)) + } else if (drag.x && drag.y && (dragX || dragY)) // if omni with no uni then both dragX / dragY should be true if either is true dragX = dragY = true; @@ -5520,32 +5828,28 @@ function uPlot(opts, data, then) { if (scaleX.ori == 0) { p0 = mouseLeft0; p1 = mouseLeft1; - } - else { + } else { p0 = mouseTop0; p1 = mouseTop1; } setSelX(min(p0, p1), abs(p1 - p0)); - if (!dragY) - setSelY(0, yDim); + if (!dragY) setSelY(0, yDim); } if (dragY) { if (scaleX.ori == 1) { p0 = mouseLeft0; p1 = mouseLeft1; - } - else { + } else { p0 = mouseTop0; p1 = mouseTop1; } setSelY(min(p0, p1), abs(p1 - p0)); - if (!dragX) - setSelX(0, xDim); + if (!dragX) setSelX(0, xDim); } // the drag didn't pass the dist requirement @@ -5564,11 +5868,31 @@ function uPlot(opts, data, then) { if (syncKey != null) { let [xSyncKey, ySyncKey] = syncOpts.scales; - syncOpts.values[0] = xSyncKey != null ? posToVal(scaleX.ori == 0 ? mouseLeft1 : mouseTop1, xSyncKey) : null; - syncOpts.values[1] = ySyncKey != null ? posToVal(scaleX.ori == 1 ? mouseLeft1 : mouseTop1, ySyncKey) : null; + syncOpts.values[0] = + xSyncKey != null + ? posToVal( + scaleX.ori == 0 ? mouseLeft1 : mouseTop1, + xSyncKey + ) + : null; + syncOpts.values[1] = + ySyncKey != null + ? posToVal( + scaleX.ori == 1 ? mouseLeft1 : mouseTop1, + ySyncKey + ) + : null; } - pubSync(mousemove, self, mouseLeft1, mouseTop1, plotWidCss, plotHgtCss, idx); + pubSync( + mousemove, + self, + mouseLeft1, + mouseTop1, + plotWidCss, + plotHgtCss, + idx + ); } if (cursorFocus) { @@ -5578,8 +5902,7 @@ function uPlot(opts, data, then) { if (focusedSeries == null) { if (closestDist <= p) setSeries(closestSeries, FOCUS_TRUE, true, shouldPub); - } - else { + } else { if (closestDist > p) setSeries(null, FOCUS_TRUE, true, shouldPub); else if (closestSeries != focusedSeries) @@ -5593,32 +5916,29 @@ function uPlot(opts, data, then) { setLegend(); } - _fire !== false && fire("setCursor"); + _fire !== false && fire('setCursor'); } let rect = null; Object.defineProperty(self, 'rect', { get() { - if (rect == null) - syncRect(false); + if (rect == null) syncRect(false); - return rect; - }, + return rect + } }); function syncRect(defer = false) { - if (defer) - rect = null; + if (defer) rect = null; else { rect = over.getBoundingClientRect(); - fire("syncRect", rect); + fire('syncRect', rect); } } function mouseMove(e, src, _l, _t, _w, _h, _i) { - if (cursor._lock) - return; + if (cursor._lock) return // Chrome on Windows has a bug which triggers a stray mousemove event after an initial mousedown event // when clicking into a plot as part of re-focusing the browser window. @@ -5626,31 +5946,27 @@ function uPlot(opts, data, then) { // However, on touch-only devices Chrome-based browsers trigger a 0-distance mousemove before mousedown // so we don't ignore it when mousedown has set the dragging flag if (dragging && e != null && e.movementX == 0 && e.movementY == 0) - return; + return cacheMouse(e, src, _l, _t, _w, _h, _i, false, e != null); - if (e != null) - updateCursor(null, true, true); - else - updateCursor(src, true, false); + if (e != null) updateCursor(null, true, true); + else updateCursor(src, true, false); } function cacheMouse(e, src, _l, _t, _w, _h, _i, initial, snap) { - if (rect == null) - syncRect(false); + if (rect == null) syncRect(false); setCursorEvent(e); if (e != null) { _l = e.clientX - rect.left; _t = e.clientY - rect.top; - } - else { + } else { if (_l < 0 || _t < 0) { mouseLeft1 = -10; mouseTop1 = -10; - return; + return } let [xKey, yKey] = syncOpts.scales; @@ -5670,14 +5986,16 @@ function uPlot(opts, data, then) { _yPos = rotSrc ? _l : _t; if (xKeySrc != null) - _l = matchXKeys(xKey, xKeySrc) ? getPos(xValSrc, scales[xKey], xDim, 0) : -10; - else - _l = xDim * (_xPos/_xDim); + _l = matchXKeys(xKey, xKeySrc) + ? getPos(xValSrc, scales[xKey], xDim, 0) + : -10; + else _l = xDim * (_xPos / _xDim); if (yKeySrc != null) - _t = matchYKeys(yKey, yKeySrc) ? getPos(yValSrc, scales[yKey], yDim, 0) : -10; - else - _t = yDim * (_yPos/_yDim); + _t = matchYKeys(yKey, yKeySrc) + ? getPos(yValSrc, scales[yKey], yDim, 0) + : -10; + else _t = yDim * (_yPos / _yDim); if (scaleX.ori == 1) { let __l = _l; @@ -5687,20 +6005,17 @@ function uPlot(opts, data, then) { } if (snap) { - if (_l <= 1 || _l >= plotWidCss - 1) - _l = incrRound(_l, plotWidCss); + if (_l <= 1 || _l >= plotWidCss - 1) _l = incrRound(_l, plotWidCss); - if (_t <= 1 || _t >= plotHgtCss - 1) - _t = incrRound(_t, plotHgtCss); + if (_t <= 1 || _t >= plotHgtCss - 1) _t = incrRound(_t, plotHgtCss); } if (initial) { rawMouseLeft0 = _l; - rawMouseTop0 = _t; + rawMouseTop0 = _t - [mouseLeft0, mouseTop0] = cursor.move(self, _l, _t); - } - else { + ;[mouseLeft0, mouseTop0] = cursor.move(self, _l, _t); + } else { mouseLeft1 = _l; mouseTop1 = _t; } @@ -5710,7 +6025,7 @@ function uPlot(opts, data, then) { width: 0, height: 0, left: 0, - top: 0, + top: 0 }; function hideSelect() { @@ -5730,14 +6045,22 @@ function uPlot(opts, data, then) { if (e != null) { onMouse(mouseup, doc, mouseUp, false); - pubSync(mousedown, self, mouseLeft0, mouseTop0, plotWidCss, plotHgtCss, null); + pubSync( + mousedown, + self, + mouseLeft0, + mouseTop0, + plotWidCss, + plotHgtCss, + null + ); } let { left, top, width, height } = select; - downSelectLeft = left; - downSelectTop = top; - downSelectWidth = width; + downSelectLeft = left; + downSelectTop = top; + downSelectWidth = width; downSelectHeight = height; hideSelect(); @@ -5751,20 +6074,19 @@ function uPlot(opts, data, then) { let { left, top, width, height } = select; let hasSelect = width > 0 || height > 0; - let chgSelect = ( - downSelectLeft != left || - downSelectTop != top || - downSelectWidth != width || - downSelectHeight != height - ); + let chgSelect = + downSelectLeft != left || + downSelectTop != top || + downSelectWidth != width || + downSelectHeight != height; hasSelect && chgSelect && setSelect(select); if (drag.setScale && hasSelect && chgSelect) { - // if (syncKey != null) { - // dragX = drag.x; - // dragY = drag.y; - // } + // if (syncKey != null) { + // dragX = drag.x; + // dragY = drag.y; + // } let xOff = left, xDim = width, @@ -5772,14 +6094,12 @@ function uPlot(opts, data, then) { yDim = height; if (scaleX.ori == 1) { - xOff = top, - xDim = height, - yOff = left, - yDim = width; +(xOff = top), (xDim = height), (yOff = left), (yDim = width); } if (dragX) { - _setScale(xScaleKey, + _setScale( + xScaleKey, posToVal(xOff, xScaleKey), posToVal(xOff + xDim, xScaleKey) ); @@ -5790,7 +6110,8 @@ function uPlot(opts, data, then) { let sc = scales[k]; if (k != xScaleKey && sc.from == null && sc.min != inf) { - _setScale(k, + _setScale( + k, posToVal(yOff + yDim, k), posToVal(yOff, k) ); @@ -5799,21 +6120,27 @@ function uPlot(opts, data, then) { } hideSelect(); - } - else if (cursor.lock) { + } else if (cursor.lock) { cursor._lock = !cursor._lock; updateCursor(null, true, false); } if (e != null) { offMouse(mouseup, doc); - pubSync(mouseup, self, mouseLeft1, mouseTop1, plotWidCss, plotHgtCss, null); + pubSync( + mouseup, + self, + mouseLeft1, + mouseTop1, + plotWidCss, + plotHgtCss, + null + ); } } function mouseLeave(e, src, _l, _t, _w, _h, _i) { - if (cursor._lock) - return; + if (cursor._lock) return setCursorEvent(e); @@ -5830,16 +6157,18 @@ function uPlot(opts, data, then) { if (scaleX.ori == 0) { dragH = dragX; dragV = dragY; - } - else { + } else { dragH = dragY; dragV = dragX; } if (dragH && dragV) { // maybe omni corner snap - snapH = mouseLeft1 <= snapProx || mouseLeft1 >= plotWidCss - snapProx; - snapV = mouseTop1 <= snapProx || mouseTop1 >= plotHgtCss - snapProx; + snapH = + mouseLeft1 <= snapProx || + mouseLeft1 >= plotWidCss - snapProx; + snapV = + mouseTop1 <= snapProx || mouseTop1 >= plotHgtCss - snapProx; } if (dragH && snapH) @@ -5859,13 +6188,11 @@ function uPlot(opts, data, then) { // passing a non-null timestamp to force sync/mousemove event updateCursor(null, true, true); - if (_dragging) - dragging = _dragging; + if (_dragging) dragging = _dragging; } function dblClick(e, src, _l, _t, _w, _h, _i) { - if (cursor._lock) - return; + if (cursor._lock) return setCursorEvent(e); @@ -5874,7 +6201,15 @@ function uPlot(opts, data, then) { hideSelect(); if (e != null) - pubSync(dblclick, self, mouseLeft1, mouseTop1, plotWidCss, plotHgtCss, null); + pubSync( + dblclick, + self, + mouseLeft1, + mouseTop1, + plotWidCss, + plotHgtCss, + null + ); } function syncPxRatio() { @@ -5891,16 +6226,16 @@ function uPlot(opts, data, then) { events.mousemove = mouseMove; events.mouseup = mouseUp; events.dblclick = dblClick; - events["setSeries"] = (e, src, idx, opts) => { + events['setSeries'] = (e, src, idx, opts) => { let seriesIdxMatcher = syncOpts.match[2]; idx = seriesIdxMatcher(self, src, idx); idx != -1 && setSeries(idx, opts, true, false); }; if (cursor.show) { - onMouse(mousedown, over, mouseDown); - onMouse(mousemove, over, mouseMove); - onMouse(mouseenter, over, e => { + onMouse(mousedown, over, mouseDown); + onMouse(mousemove, over, mouseMove); + onMouse(mouseenter, over, (e) => { setCursorEvent(e); syncRect(false); }); @@ -5914,41 +6249,41 @@ function uPlot(opts, data, then) { } // external on/off - const hooks = self.hooks = opts.hooks || {}; + const hooks = (self.hooks = opts.hooks || {}); function fire(evName, a1, a2) { - if (deferHooks) - hooksQueue.push([evName, a1, a2]); + if (deferHooks) hooksQueue.push([evName, a1, a2]); else { if (evName in hooks) { - hooks[evName].forEach(fn => { + hooks[evName].forEach((fn) => { fn.call(null, self, a1, a2); }); } } } - - (opts.plugins || []).forEach(p => { +(opts.plugins || []).forEach((p) => { for (let evName in p.hooks) hooks[evName] = (hooks[evName] || []).concat(p.hooks[evName]); }); const seriesIdxMatcher = (self, src, srcSeriesIdx) => srcSeriesIdx; - const syncOpts = assign({ - key: null, - setSeries: false, - filters: { - pub: retTrue, - sub: retTrue, + const syncOpts = assign( + { + key: null, + setSeries: false, + filters: { + pub: retTrue, + sub: retTrue + }, + scales: [xScaleKey, series[1] ? series[1].scale : null], + match: [retEq, retEq, seriesIdxMatcher], + values: [null, null] }, - scales: [xScaleKey, series[1] ? series[1].scale : null], - match: [retEq, retEq, seriesIdxMatcher], - values: [null, null], - }, cursor.sync); + cursor.sync + ); - if (syncOpts.match.length == 2) - syncOpts.match.push(seriesIdxMatcher); + if (syncOpts.match.length == 2) syncOpts.match.push(seriesIdxMatcher); cursor.sync = syncOpts; @@ -5977,20 +6312,18 @@ function uPlot(opts, data, then) { off(dppxchange, win, syncPxRatio); root.remove(); legendTable?.remove(); // in case mounted outside of root - fire("destroy"); + fire('destroy'); } self.destroy = destroy; function _init() { - fire("init", opts, data); + fire('init', opts, data); setData(data || opts.data, false); - if (pendScales[xScaleKey]) - setScale(xScaleKey, pendScales[xScaleKey]); - else - autoScaleX(); + if (pendScales[xScaleKey]) setScale(xScaleKey, pendScales[xScaleKey]); + else autoScaleX(); shouldSetSelect = select.show && (select.width > 0 || select.height > 0); shouldSetCursor = shouldSetLegend = true; @@ -6006,22 +6339,17 @@ function uPlot(opts, data, then) { if (then instanceof HTMLElement) { then.appendChild(root); _init(); - } - else - then(self, _init); - } - else - _init(); + } else then(self, _init); + } else _init(); - return self; + return self } uPlot.assign = assign; -uPlot.fmtNum = fmtNum; uPlot.rangeNum = rangeNum; uPlot.rangeLog = rangeLog; uPlot.rangeAsinh = rangeAsinh; -uPlot.orient = orient; +uPlot.orient = orient; uPlot.pxRatio = pxRatio; { @@ -6029,8 +6357,7 @@ uPlot.pxRatio = pxRatio; } { - uPlot.fmtDate = fmtDate; - uPlot.tzDate = tzDate; + uPlot.tzDate = tzDate; } uPlot.sync = _sync; @@ -6039,14 +6366,14 @@ uPlot.sync = _sync; uPlot.addGap = addGap; uPlot.clipGaps = clipGaps; - let paths = uPlot.paths = { - points, - }; + let paths = (uPlot.paths = { + points + }); - (paths.linear = linear); + (paths.linear = linear); (paths.stepped = stepped); - (paths.bars = bars); - (paths.spline = monotoneCubic); + (paths.bars = bars); + (paths.spline = monotoneCubic); } export { uPlot as default }; diff --git a/dist/uPlot.iife.js b/dist/uPlot.iife.js index 03830cc9..29f917ac 100644 --- a/dist/uPlot.iife.js +++ b/dist/uPlot.iife.js @@ -12,168 +12,7 @@ var uPlot = (function () { const FEAT_TIME = true; - const pre = "u-"; - - const UPLOT = "uplot"; - const ORI_HZ = pre + "hz"; - const ORI_VT = pre + "vt"; - const TITLE = pre + "title"; - const WRAP = pre + "wrap"; - const UNDER = pre + "under"; - const OVER = pre + "over"; - const AXIS = pre + "axis"; - const OFF = pre + "off"; - const SELECT = pre + "select"; - const CURSOR_X = pre + "cursor-x"; - const CURSOR_Y = pre + "cursor-y"; - const CURSOR_PT = pre + "cursor-pt"; - const LEGEND = pre + "legend"; - const LEGEND_LIVE = pre + "live"; - const LEGEND_INLINE = pre + "inline"; - const LEGEND_SERIES = pre + "series"; - const LEGEND_MARKER = pre + "marker"; - const LEGEND_LABEL = pre + "label"; - const LEGEND_VALUE = pre + "value"; - - const WIDTH = "width"; - const HEIGHT = "height"; - const TOP = "top"; - const BOTTOM = "bottom"; - const LEFT = "left"; - const RIGHT = "right"; - const hexBlack = "#000"; - const transparent = hexBlack + "0"; - - const mousemove = "mousemove"; - const mousedown = "mousedown"; - const mouseup = "mouseup"; - const mouseenter = "mouseenter"; - const mouseleave = "mouseleave"; - const dblclick = "dblclick"; - const resize = "resize"; - const scroll = "scroll"; - - const change = "change"; - const dppxchange = "dppxchange"; - - const LEGEND_DISP = "--"; - - const domEnv = typeof window != 'undefined'; - - const doc = domEnv ? document : null; - const win = domEnv ? window : null; - const nav = domEnv ? navigator : null; - - let pxRatio; - - //export const canHover = domEnv && !win.matchMedia('(hover: none)').matches; - - let query; - - function setPxRatio() { - let _pxRatio = devicePixelRatio; - - // during print preview, Chrome fires off these dppx queries even without changes - if (pxRatio != _pxRatio) { - pxRatio = _pxRatio; - - query && off(change, query, setPxRatio); - query = matchMedia(`(min-resolution: ${pxRatio - 0.001}dppx) and (max-resolution: ${pxRatio + 0.001}dppx)`); - on(change, query, setPxRatio); - - win.dispatchEvent(new CustomEvent(dppxchange)); - } - } - - function addClass(el, c) { - if (c != null) { - let cl = el.classList; - !cl.contains(c) && cl.add(c); - } - } - - function remClass(el, c) { - let cl = el.classList; - cl.contains(c) && cl.remove(c); - } - - function setStylePx(el, name, value) { - el.style[name] = value + "px"; - } - - function placeTag(tag, cls, targ, refEl) { - let el = doc.createElement(tag); - - if (cls != null) - addClass(el, cls); - - if (targ != null) - targ.insertBefore(el, refEl); - - return el; - } - - function placeDiv(cls, targ) { - return placeTag("div", cls, targ); - } - - const xformCache = new WeakMap(); - - function elTrans(el, xPos, yPos, xMax, yMax) { - let xform = "translate(" + xPos + "px," + yPos + "px)"; - let xformOld = xformCache.get(el); - - if (xform != xformOld) { - el.style.transform = xform; - xformCache.set(el, xform); - - if (xPos < 0 || yPos < 0 || xPos > xMax || yPos > yMax) - addClass(el, OFF); - else - remClass(el, OFF); - } - } - - const colorCache = new WeakMap(); - - function elColor(el, background, borderColor) { - let newColor = background + borderColor; - let oldColor = colorCache.get(el); - - if (newColor != oldColor) { - colorCache.set(el, newColor); - el.style.background = background; - el.style.borderColor = borderColor; - } - } - - const sizeCache = new WeakMap(); - - function elSize(el, newWid, newHgt, centered) { - let newSize = newWid + "" + newHgt; - let oldSize = sizeCache.get(el); - - if (newSize != oldSize) { - sizeCache.set(el, newSize); - el.style.height = newHgt + "px"; - el.style.width = newWid + "px"; - el.style.marginLeft = centered ? -newWid/2 + "px" : 0; - el.style.marginTop = centered ? -newHgt/2 + "px" : 0; - } - } - - const evOpts = {passive: true}; - const evOpts2 = {...evOpts, capture: true}; - - function on(ev, el, cb, capt) { - el.addEventListener(ev, cb, capt ? evOpts2 : evOpts); - } - - function off(ev, el, cb, capt) { - el.removeEventListener(ev, cb, evOpts); - } - - domEnv && setPxRatio(); + const browserLocale = new Intl.DateTimeFormat().resolvedOptions().locale; // binary search for index of closest value function closestIdx(num, arr, lo, hi) { @@ -432,10 +271,6 @@ var uPlot = (function () { return [minLim, maxLim]; } - // alternative: https://stackoverflow.com/a/2254896 - const numFormatter = new Intl.NumberFormat(domEnv ? nav.language : 'en-US'); - const fmtNum = val => numFormatter.format(val); - const M = Math; const PI = M.PI; @@ -821,130 +656,168 @@ var uPlot = (function () { return true; } - const months = [ - "January", - "February", - "March", - "April", - "May", - "June", - "July", - "August", - "September", - "October", - "November", - "December", - ]; - - const days = [ - "Sunday", - "Monday", - "Tuesday", - "Wednesday", - "Thursday", - "Friday", - "Saturday", - ]; - - function slice3(str) { - return str.slice(0, 3); + const WIDTH = "width"; + const HEIGHT = "height"; + const TOP = "top"; + const BOTTOM = "bottom"; + const LEFT = "left"; + const RIGHT = "right"; + const hexBlack = "#000"; + const transparent = hexBlack + "0"; + + const mousemove = "mousemove"; + const mousedown = "mousedown"; + const mouseup = "mouseup"; + const mouseenter = "mouseenter"; + const mouseleave = "mouseleave"; + const dblclick = "dblclick"; + const resize = "resize"; + const scroll = "scroll"; + + const change = "change"; + const dppxchange = "dppxchange"; + + const LEGEND_DISP = "--"; + + const pre = "u-"; + + const UPLOT = "uplot"; + const ORI_HZ = pre + "hz"; + const ORI_VT = pre + "vt"; + const TITLE = pre + "title"; + const WRAP = pre + "wrap"; + const UNDER = pre + "under"; + const OVER = pre + "over"; + const AXIS = pre + "axis"; + const OFF = pre + "off"; + const SELECT = pre + "select"; + const CURSOR_X = pre + "cursor-x"; + const CURSOR_Y = pre + "cursor-y"; + const CURSOR_PT = pre + "cursor-pt"; + const LEGEND = pre + "legend"; + const LEGEND_LIVE = pre + "live"; + const LEGEND_INLINE = pre + "inline"; + const LEGEND_SERIES = pre + "series"; + const LEGEND_MARKER = pre + "marker"; + const LEGEND_LABEL = pre + "label"; + const LEGEND_VALUE = pre + "value"; + + const domEnv = typeof window != 'undefined'; + + const doc = domEnv ? document : null; + const win = domEnv ? window : null; + + let pxRatio; + + //export const canHover = domEnv && !win.matchMedia('(hover: none)').matches; + + let query; + + function setPxRatio() { + let _pxRatio = devicePixelRatio; + + // during print preview, Chrome fires off these dppx queries even without changes + if (pxRatio != _pxRatio) { + pxRatio = _pxRatio; + + query && off(change, query, setPxRatio); + query = matchMedia(`(min-resolution: ${pxRatio - 0.001}dppx) and (max-resolution: ${pxRatio + 0.001}dppx)`); + on(change, query, setPxRatio); + + win.dispatchEvent(new CustomEvent(dppxchange)); + } + } + + function addClass(el, c) { + if (c != null) { + let cl = el.classList; + !cl.contains(c) && cl.add(c); + } + } + + function remClass(el, c) { + let cl = el.classList; + cl.contains(c) && cl.remove(c); } - const days3 = days.map(slice3); + function setStylePx(el, name, value) { + el.style[name] = value + "px"; + } - const months3 = months.map(slice3); + function placeTag(tag, cls, targ, refEl) { + let el = doc.createElement(tag); - const engNames = { - MMMM: months, - MMM: months3, - WWWW: days, - WWW: days3, - }; + if (cls != null) + addClass(el, cls); + + if (targ != null) + targ.insertBefore(el, refEl); + + return el; + } + + function placeDiv(cls, targ) { + return placeTag("div", cls, targ); + } - function zeroPad2(int) { - return (int < 10 ? '0' : '') + int; + const xformCache = new WeakMap(); + + function elTrans(el, xPos, yPos, xMax, yMax) { + let xform = "translate(" + xPos + "px," + yPos + "px)"; + let xformOld = xformCache.get(el); + + if (xform != xformOld) { + el.style.transform = xform; + xformCache.set(el, xform); + + if (xPos < 0 || yPos < 0 || xPos > xMax || yPos > yMax) + addClass(el, OFF); + else + remClass(el, OFF); + } } - function zeroPad3(int) { - return (int < 10 ? '00' : int < 100 ? '0' : '') + int; - } + const colorCache = new WeakMap(); - /* - function suffix(int) { - let mod10 = int % 10; + function elColor(el, background, borderColor) { + let newColor = background + borderColor; + let oldColor = colorCache.get(el); - return int + ( - mod10 == 1 && int != 11 ? "st" : - mod10 == 2 && int != 12 ? "nd" : - mod10 == 3 && int != 13 ? "rd" : "th" - ); + if (newColor != oldColor) { + colorCache.set(el, newColor); + el.style.background = background; + el.style.borderColor = borderColor; + } } - */ - const subs = { - // 2019 - YYYY: d => d.getFullYear(), - // 19 - YY: d => (d.getFullYear()+'').slice(2), - // July - MMMM: (d, names) => names.MMMM[d.getMonth()], - // Jul - MMM: (d, names) => names.MMM[d.getMonth()], - // 07 - MM: d => zeroPad2(d.getMonth()+1), - // 7 - M: d => d.getMonth()+1, - // 09 - DD: d => zeroPad2(d.getDate()), - // 9 - D: d => d.getDate(), - // Monday - WWWW: (d, names) => names.WWWW[d.getDay()], - // Mon - WWW: (d, names) => names.WWW[d.getDay()], - // 03 - HH: d => zeroPad2(d.getHours()), - // 3 - H: d => d.getHours(), - // 9 (12hr, unpadded) - h: d => {let h = d.getHours(); return h == 0 ? 12 : h > 12 ? h - 12 : h;}, - // AM - AA: d => d.getHours() >= 12 ? 'PM' : 'AM', - // am - aa: d => d.getHours() >= 12 ? 'pm' : 'am', - // a - a: d => d.getHours() >= 12 ? 'p' : 'a', - // 09 - mm: d => zeroPad2(d.getMinutes()), - // 9 - m: d => d.getMinutes(), - // 09 - ss: d => zeroPad2(d.getSeconds()), - // 9 - s: d => d.getSeconds(), - // 374 - fff: d => zeroPad3(d.getMilliseconds()), - }; - - function fmtDate(tpl, names) { - names = names || engNames; - let parts = []; + const sizeCache = new WeakMap(); - let R = /\{([a-z]+)\}|[^{]+/gi, m; + function elSize(el, newWid, newHgt, centered) { + let newSize = newWid + "" + newHgt; + let oldSize = sizeCache.get(el); - while (m = R.exec(tpl)) - parts.push(m[0][0] == '{' ? subs[m[1]] : m[0]); + if (newSize != oldSize) { + sizeCache.set(el, newSize); + el.style.height = newHgt + "px"; + el.style.width = newWid + "px"; + el.style.marginLeft = centered ? -newWid/2 + "px" : 0; + el.style.marginTop = centered ? -newHgt/2 + "px" : 0; + } + } - return d => { - let out = ''; + const evOpts = {passive: true}; + const evOpts2 = {...evOpts, capture: true}; - for (let i = 0; i < parts.length; i++) - out += typeof parts[i] == "string" ? parts[i] : parts[i](d, names); + function on(ev, el, cb, capt) { + el.addEventListener(ev, cb, capt ? evOpts2 : evOpts); + } - return out; - } + function off(ev, el, cb, capt) { + el.removeEventListener(ev, cb, evOpts); } + domEnv && setPxRatio(); + const localTz = new Intl.DateTimeFormat().resolvedOptions().timeZone; // https://stackoverflow.com/questions/15141762/how-to-initialize-a-javascript-date-to-a-particular-time-zone/53652131#53652131 @@ -985,17 +858,14 @@ var uPlot = (function () { const NL = "\n"; - const yyyy = "{YYYY}"; - const NLyyyy = NL + yyyy; - const md = "{M}/{D}"; - const NLmd = NL + md; - const NLmdyy = NLmd + "/{YY}"; - - const aa = "{aa}"; - const hmm = "{h}:{mm}"; - const hmmaa = hmm + aa; - const NLhmmaa = NL + hmmaa; - const ss = ":{ss}"; + let YYYY = {year: 'numeric'}; + let MM = {month: 'numeric'}; + let MMM = {month: 'short'}; + let dd = {day: 'numeric'}; + let hh = {hour: 'numeric'}; + let mm = {minute: 'numeric'}; + let ss = {second: 'numeric'}; + let fff = { fractionalSecondDigits: 3}; const _ = null; @@ -1062,18 +932,18 @@ var uPlot = (function () { // [0]: minimum num secs in the tick incr // [1]: default tick format // [2-7]: rollover tick formats - // [8]: mode: 0: replace [1] -> [2-7], 1: concat [1] + [2-7] + // [8]: mode: 0: replace [1] -> [2-7], 1: merge [2-7] + \n + [1] const _timeAxisStamps = [ - // tick incr default year month day hour min sec mode - [y, yyyy, _, _, _, _, _, _, 1], - [d * 28, "{MMM}", NLyyyy, _, _, _, _, _, 1], - [d, md, NLyyyy, _, _, _, _, _, 1], - [h, "{h}" + aa, NLmdyy, _, NLmd, _, _, _, 1], - [m, hmmaa, NLmdyy, _, NLmd, _, _, _, 1], - [s, ss, NLmdyy + " " + hmmaa, _, NLmd + " " + hmmaa, _, NLhmmaa, _, 1], - [ms, ss + ".{fff}", NLmdyy + " " + hmmaa, _, NLmd + " " + hmmaa, _, NLhmmaa, _, 1], + // tick incr default year month day hour min sec mode + [y, { ...YYYY }, _, _, _, _, _, _, 1], + [d * 28, { ...MMM }, {...YYYY}, _, _, _, _, _, 1], + [d, { ...MM, ...dd }, {...YYYY}, _, _, _, _, _, 1], + [h, { ...hh }, { ...YYYY, ...MM, ...dd}, _, {...MM, ...dd}, _, _, _, 1], + [m, { ...hh, ...mm }, { ...YYYY, ...MM, ...dd}, _, {...MM, ...dd}, _, _, _, 1], + [s, { ...ss }, { ...YYYY, ...MM, ...dd, ...hh, ...mm}, _, {...MM, ...dd, ...hh, ...mm}, _, {...hh, ...mm}, _, 1], + [ms, { ...ss, ...fff }, { ...YYYY, ...MM, ...dd, ...hh, ...mm}, _, {...MM, ...dd, ...hh, ...mm}, _, {...hh, ...mm}, _, 1], ]; - + // the ensures that axis ticks, values & grid are aligned to logical temporal breakpoints and not an arbitrary timestamp // https://www.timeanddate.com/time/dst/ // https://www.timeanddate.com/time/dst/2019.html @@ -1186,8 +1056,18 @@ var uPlot = (function () { */ function timeAxisStamps(stampCfg, fmtDate) { - return stampCfg.map(s => s.map((v, i) => - i == 0 || i == 8 || v == null ? v : fmtDate(i == 1 || s[8] == 0 ? v : s[1] + v) + return stampCfg.map(s => s.map((v, i) => { + if (i == 0 || i == 8 || v == null) { + return v + } + const line1 = fmtDate(v); + if (i == 1 || s[8] == 0) { + return line1 + } else { + const line2 = fmtDate(s[1]); + return (date) => line2(date)+NL+line1(date) + } + } )); } @@ -1237,12 +1117,6 @@ var uPlot = (function () { } } - // for when axis.values is defined as a static fmtDate template string - function timeAxisVal(tzDate, dateTpl) { - let stamp = fmtDate(dateTpl); - return (self, splits, axisIdx, foundSpace, foundIncr) => splits.map(split => stamp(tzDate(split))); - } - function mkDate(y, m, d) { return new Date(y, m, d); } @@ -1250,7 +1124,7 @@ var uPlot = (function () { function timeSeriesStamp(stampCfg, fmtDate) { return fmtDate(stampCfg); } - const _timeSeriesStamp = '{YYYY}-{MM}-{DD} {h}:{mm}{aa}'; + const _timeSeriesStamp = { ...YYYY, ...MM, ...dd, ...hh, ...mm }; function timeSeriesVal(tzDate, stamp) { return (self, val, seriesIdx, dataIdx) => dataIdx == null ? LEGEND_DISP : stamp(tzDate(val)); @@ -1461,7 +1335,7 @@ var uPlot = (function () { idxs: [], }; - function numAxisVals(self, splits, axisIdx, foundSpace, foundIncr) { + function numAxisVals(self, splits, axisIdx, foundSpace, foundIncr, fmtNum) { return splits.map(v => v == null ? "" : fmtNum(v)); } @@ -1584,7 +1458,7 @@ var uPlot = (function () { return splits; } - function numSeriesVal(self, val, seriesIdx, dataIdx) { + function numSeriesVal(self, val, seriesIdx, dataIdx, fmtNum) { return dataIdx == null ? LEGEND_DISP : val == null ? "" : fmtNum(val); } @@ -2767,14 +2641,15 @@ var uPlot = (function () { const cursorPlots = new Set(); function invalidateRects() { - for (let u of cursorPlots) - u.syncRect(true); + for (let u of cursorPlots) u.syncRect(true); } if (domEnv) { on(resize, win, invalidateRects); on(scroll, win, invalidateRects, true); - on(dppxchange, win, () => { uPlot.pxRatio = pxRatio; }); + on(dppxchange, win, () => { + uPlot.pxRatio = pxRatio; + }); } const linearPath = linear() ; @@ -2782,19 +2657,19 @@ var uPlot = (function () { function setDefaults(d, xo, yo, initY) { let d2 = initY ? [d[0], d[1]].concat(d.slice(2)) : [d[0]].concat(d.slice(1)); - return d2.map((o, i) => setDefault(o, i, xo, yo)); + return d2.map((o, i) => setDefault(o, i, xo, yo)) } function setDefaults2(d, xyo) { - return d.map((o, i) => i == 0 ? {} : assign({}, xyo, o)); // todo: assign() will not merge facet arrays + return d.map((o, i) => (i == 0 ? {} : assign({}, xyo, o))) // todo: assign() will not merge facet arrays } function setDefault(o, i, xo, yo) { - return assign({}, (i == 0 ? xo : yo), o); + return assign({}, i == 0 ? xo : yo, o) } function snapNumX(self, dataMin, dataMax) { - return dataMin == null ? nullNullTuple : [dataMin, dataMax]; + return dataMin == null ? nullNullTuple : [dataMin, dataMax] } const snapTimeX = snapNumX; @@ -2802,17 +2677,23 @@ var uPlot = (function () { // this ensures that non-temporal/numeric y-axes get multiple-snapped padding added above/below // TODO: also account for incrs when snapping to ensure top of axis gets a tick & value function snapNumY(self, dataMin, dataMax) { - return dataMin == null ? nullNullTuple : rangeNum(dataMin, dataMax, rangePad, true); + return dataMin == null + ? nullNullTuple + : rangeNum(dataMin, dataMax, rangePad, true) } function snapLogY(self, dataMin, dataMax, scale) { - return dataMin == null ? nullNullTuple : rangeLog(dataMin, dataMax, self.scales[scale].log, false); + return dataMin == null + ? nullNullTuple + : rangeLog(dataMin, dataMax, self.scales[scale].log, false) } const snapLogX = snapLogY; function snapAsinhY(self, dataMin, dataMax, scale) { - return dataMin == null ? nullNullTuple : rangeAsinh(dataMin, dataMax, self.scales[scale].log, false); + return dataMin == null + ? nullNullTuple + : rangeAsinh(dataMin, dataMax, self.scales[scale].log, false) } const snapAsinhX = snapAsinhY; @@ -2827,24 +2708,30 @@ var uPlot = (function () { do { let foundIncr = incrs[incrIdx]; - let foundSpace = dim * foundIncr / delta; + let foundSpace = (dim * foundIncr) / delta; - if (foundSpace >= minSpace && intDigits + (foundIncr < 5 ? fixedDec.get(foundIncr) : 0) <= 17) - return [foundIncr, foundSpace]; - } while (++incrIdx < incrs.length); + if ( + foundSpace >= minSpace && + intDigits + (foundIncr < 5 ? fixedDec.get(foundIncr) : 0) <= 17 + ) + return [foundIncr, foundSpace] + } while (++incrIdx < incrs.length) - return [0, 0]; + return [0, 0] } function pxRatioFont(font) { let fontSize, fontSizeCss; - font = font.replace(/(\d+)px/, (m, p1) => (fontSize = round((fontSizeCss = +p1) * pxRatio)) + 'px'); - return [font, fontSize, fontSizeCss]; + font = font.replace( + /(\d+)px/, + (m, p1) => (fontSize = round((fontSizeCss = +p1) * pxRatio)) + 'px' + ); + return [font, fontSize, fontSizeCss] } function syncFontSize(axis) { if (axis.show) { - [axis.font, axis.labelFont].forEach(f => { + [axis.font, axis.labelFont].forEach((f) => { let size = roundDec(f[2] * pxRatio, 1); f[0] = f[0].replace(/[0-9.]+px/, size + 'px'); f[1] = size; @@ -2854,35 +2741,62 @@ var uPlot = (function () { function uPlot(opts, data, then) { const self = { - mode: ifNull(opts.mode, 1), + mode: ifNull(opts.mode, 1) }; const mode = self.mode; + const numFormatter = new Intl.NumberFormat(opts.locale || browserLocale); + const fmtNum = (val) => numFormatter.format(val); + self.fmtNum = fmtNum; + + const fmtDate = (tsOpts) => { + tsOpts.hourCycle = opts.hourCycle; + return new Intl.DateTimeFormat(opts.locale || browserLocale, tsOpts) + .format + }; + { + self.fmtDate = fmtDate; + } + // TODO: cache denoms & mins scale.cache = {r, min, } function getValPct(val, scale) { - let _val = ( - scale.distr == 3 ? log10(val > 0 ? val : scale.clamp(self, val, scale.min, scale.max, scale.key)) : - scale.distr == 4 ? asinh(val, scale.asinh) : - scale.distr == 100 ? scale.fwd(val) : - val - ); - - return (_val - scale._min) / (scale._max - scale._min); + let _val = + scale.distr == 3 + ? log10( + val > 0 + ? val + : scale.clamp( + self, + val, + scale.min, + scale.max, + scale.key + ) + ) + : scale.distr == 4 + ? asinh(val, scale.asinh) + : scale.distr == 100 + ? scale.fwd(val) + : val; + + return (_val - scale._min) / (scale._max - scale._min) } function getHPos(val, scale, dim, off) { let pct = getValPct(val, scale); - return off + dim * (scale.dir == -1 ? (1 - pct) : pct); + return off + dim * (scale.dir == -1 ? 1 - pct : pct) } function getVPos(val, scale, dim, off) { let pct = getValPct(val, scale); - return off + dim * (scale.dir == -1 ? pct : (1 - pct)); + return off + dim * (scale.dir == -1 ? pct : 1 - pct) } function getPos(val, scale, dim, off) { - return scale.ori == 0 ? getHPos(val, scale, dim, off) : getVPos(val, scale, dim, off); + return scale.ori == 0 + ? getHPos(val, scale, dim, off) + : getVPos(val, scale, dim, off) } self.valToPosH = getHPos; @@ -2891,10 +2805,9 @@ var uPlot = (function () { let ready = false; self.status = 0; - const root = self.root = placeDiv(UPLOT); + const root = (self.root = placeDiv(UPLOT)); - if (opts.id != null) - root.id = opts.id; + if (opts.id != null) root.id = opts.id; addClass(root, opts.class); @@ -2903,43 +2816,53 @@ var uPlot = (function () { title.textContent = opts.title; } - const can = placeTag("canvas"); - const ctx = self.ctx = can.getContext("2d"); + const can = placeTag('canvas'); + const ctx = (self.ctx = can.getContext('2d')); const wrap = placeDiv(WRAP, root); - on("click", wrap, e => { - if (e.target === over) { - let didDrag = mouseLeft1 != mouseLeft0 || mouseTop1 != mouseTop0; - didDrag && drag.click(self, e); - } - }, true); + on( + 'click', + wrap, + (e) => { + if (e.target === over) { + let didDrag = mouseLeft1 != mouseLeft0 || mouseTop1 != mouseTop0; + didDrag && drag.click(self, e); + } + }, + true + ); - const under = self.under = placeDiv(UNDER, wrap); + const under = (self.under = placeDiv(UNDER, wrap)); wrap.appendChild(can); - const over = self.over = placeDiv(OVER, wrap); + const over = (self.over = placeDiv(OVER, wrap)); opts = copy(opts); const pxAlign = +ifNull(opts.pxAlign, 1); - const pxRound = pxRoundGen(pxAlign); + const pxRound = pxRoundGen(pxAlign) - (opts.plugins || []).forEach(p => { - if (p.opts) - opts = p.opts(self, opts) || opts; + ;(opts.plugins || []).forEach((p) => { + if (p.opts) opts = p.opts(self, opts) || opts; }); const ms = opts.ms || 1e-3; - const series = self.series = mode == 1 ? - setDefaults(opts.series || [], xSeriesOpts, ySeriesOpts, false) : - setDefaults2(opts.series || [null], xySeriesOpts); - const axes = self.axes = setDefaults(opts.axes || [], xAxisOpts, yAxisOpts, true); - const scales = self.scales = {}; - const bands = self.bands = opts.bands || []; + const series = (self.series = + mode == 1 + ? setDefaults(opts.series || [], xSeriesOpts, ySeriesOpts, false) + : setDefaults2(opts.series || [null], xySeriesOpts)); + const axes = (self.axes = setDefaults( + opts.axes || [], + xAxisOpts, + yAxisOpts, + true + )); + const scales = (self.scales = {}); + const bands = (self.bands = opts.bands || []); - bands.forEach(b => { + bands.forEach((b) => { b.fill = fnOrSelf(b.fill || null); b.dir = ifNull(b.dir, -1); }); @@ -2948,10 +2871,12 @@ var uPlot = (function () { const drawOrderMap = { axes: drawAxesGrid, - series: drawSeries, + series: drawSeries }; - const drawOrder = (opts.drawOrder || ["axes", "series"]).map(key => drawOrderMap[key]); + const drawOrder = (opts.drawOrder || ['axes', 'series']).map( + (key) => drawOrderMap[key] + ); function initScale(scaleKey) { let sc = scales[scaleKey]; @@ -2963,10 +2888,18 @@ var uPlot = (function () { // ensure parent is initialized initScale(scaleOpts.from); // dependent scales inherit - scales[scaleKey] = assign({}, scales[scaleOpts.from], scaleOpts, {key: scaleKey}); - } - else { - sc = scales[scaleKey] = assign({}, (scaleKey == xScaleKey ? xScaleOpts : yScaleOpts), scaleOpts); + scales[scaleKey] = assign( + {}, + scales[scaleOpts.from], + scaleOpts, + { key: scaleKey } + ); + } else { + sc = scales[scaleKey] = assign( + {}, + scaleKey == xScaleKey ? xScaleOpts : yScaleOpts, + scaleOpts + ); sc.key = scaleKey; @@ -2980,16 +2913,22 @@ var uPlot = (function () { // if range array has null limits, it should be auto if (rangeIsArr && (rn[0] == null || rn[1] == null)) { rn = { - min: rn[0] == null ? autoRangePart : { - mode: 1, - hard: rn[0], - soft: rn[0], - }, - max: rn[1] == null ? autoRangePart : { - mode: 1, - hard: rn[1], - soft: rn[1], - }, + min: + rn[0] == null + ? autoRangePart + : { + mode: 1, + hard: rn[0], + soft: rn[0] + }, + max: + rn[1] == null + ? autoRangePart + : { + mode: 1, + hard: rn[1], + soft: rn[1] + } }; rangeIsArr = false; } @@ -2997,14 +2936,29 @@ var uPlot = (function () { if (!rangeIsArr && isObj(rn)) { let cfg = rn; // this is similar to snapNumY - rn = (self, dataMin, dataMax) => dataMin == null ? nullNullTuple : rangeNum(dataMin, dataMax, cfg); + rn = (self, dataMin, dataMax) => + dataMin == null + ? nullNullTuple + : rangeNum(dataMin, dataMax, cfg); } } - sc.range = fnOrSelf(rn || (isTime ? snapTimeX : scaleKey == xScaleKey ? - (sc.distr == 3 ? snapLogX : sc.distr == 4 ? snapAsinhX : snapNumX) : - (sc.distr == 3 ? snapLogY : sc.distr == 4 ? snapAsinhY : snapNumY) - )); + sc.range = fnOrSelf( + rn || + (isTime + ? snapTimeX + : scaleKey == xScaleKey + ? sc.distr == 3 + ? snapLogX + : sc.distr == 4 + ? snapAsinhX + : snapNumX + : sc.distr == 3 + ? snapLogY + : sc.distr == 4 + ? snapAsinhY + : snapNumY) + ); sc.auto = fnOrSelf(rangeIsArr ? false : sc.auto); @@ -3016,28 +2970,28 @@ var uPlot = (function () { } } - initScale("x"); - initScale("y"); + initScale('x'); + initScale('y'); // TODO: init scales from facets in mode: 2 if (mode == 1) { - series.forEach(s => { + series.forEach((s) => { initScale(s.scale); }); } - axes.forEach(a => { + axes.forEach((a) => { initScale(a.scale); }); - for (let k in opts.scales) - initScale(k); + for (let k in opts.scales) initScale(k); const scaleX = scales[xScaleKey]; const xScaleDistr = scaleX.distr; - let valToPosX, valToPosY; + let valToPosX, + valToPosY; if (scaleX.ori == 0) { addClass(root, ORI_HZ); @@ -3056,8 +3010,7 @@ var uPlot = (function () { yOffCss = plotTopCss; }; */ - } - else { + } else { addClass(root, ORI_VT); valToPosX = getVPos; valToPosY = getHPos; @@ -3083,32 +3036,43 @@ var uPlot = (function () { let sc = scales[k]; if (sc.min != null || sc.max != null) { - pendScales[k] = {min: sc.min, max: sc.max}; + pendScales[k] = { min: sc.min, max: sc.max }; sc.min = sc.max = null; } } - // self.tz = opts.tz || Intl.DateTimeFormat().resolvedOptions().timeZone; - const _tzDate = (opts.tzDate || (ts => new Date(round(ts / ms)))); + // self.tz = opts.tz || Intl.DateTimeFormat().resolvedOptions().timeZone; + const _tzDate = + (opts.tzDate || ((ts) => new Date(round(ts / ms)))); const _fmtDate = (opts.fmtDate || fmtDate); - const _timeAxisSplits = (ms == 1 ? timeAxisSplitsMs(_tzDate) : timeAxisSplitsS(_tzDate)); - const _timeAxisVals = timeAxisVals(_tzDate, timeAxisStamps((ms == 1 ? _timeAxisStampsMs : _timeAxisStampsS), _fmtDate)); - const _timeSeriesVal = timeSeriesVal(_tzDate, timeSeriesStamp(_timeSeriesStamp, _fmtDate)); + const _timeAxisSplits = + (ms == 1 ? timeAxisSplitsMs(_tzDate) : timeAxisSplitsS(_tzDate)); + const _timeAxisVals = + timeAxisVals( + _tzDate, + timeAxisStamps( + ms == 1 ? _timeAxisStampsMs : _timeAxisStampsS, + _fmtDate + ) + ); + const _timeSeriesVal = + timeSeriesVal(_tzDate, timeSeriesStamp(_timeSeriesStamp, _fmtDate)); const activeIdxs = []; - const legend = (self.legend = assign({}, legendOpts, opts.legend)); + const legend = + (self.legend = assign({}, legendOpts, opts.legend)); const showLegend = legend.show; - const markers = legend.markers; + const markers = legend.markers; { legend.idxs = activeIdxs; - markers.width = fnOrSelf(markers.width); - markers.dash = fnOrSelf(markers.dash); + markers.width = fnOrSelf(markers.width); + markers.dash = fnOrSelf(markers.dash); markers.stroke = fnOrSelf(markers.stroke); - markers.fill = fnOrSelf(markers.fill); + markers.fill = fnOrSelf(markers.fill); } let legendTable; @@ -3123,60 +3087,67 @@ var uPlot = (function () { if (legend.live) { const getMultiVals = series[1] ? series[1].values : null; multiValLegend = getMultiVals != null; - legendCols = multiValLegend ? getMultiVals(self, 1, 0) : {_: 0}; + legendCols = multiValLegend ? getMultiVals(self, 1, 0) : { _: 0 }; - for (let k in legendCols) - NULL_LEGEND_VALUES[k] = LEGEND_DISP; + for (let k in legendCols) NULL_LEGEND_VALUES[k] = LEGEND_DISP; } if (showLegend) { - legendTable = placeTag("table", LEGEND, root); - legendBody = placeTag("tbody", null, legendTable); + legendTable = placeTag('table', LEGEND, root); + legendBody = placeTag('tbody', null, legendTable); // allows legend to be moved out of root legend.mount(self, legendTable); if (multiValLegend) { - legendHead = placeTag("thead", null, legendTable, legendBody); + legendHead = placeTag('thead', null, legendTable, legendBody); - let head = placeTag("tr", null, legendHead); - placeTag("th", null, head); + let head = placeTag('tr', null, legendHead); + placeTag('th', null, head); for (var key in legendCols) - placeTag("th", LEGEND_LABEL, head).textContent = key; - } - else { + placeTag('th', LEGEND_LABEL, head).textContent = key; + } else { addClass(legendTable, LEGEND_INLINE); legend.live && addClass(legendTable, LEGEND_LIVE); } } - const son = {show: true}; - const soff = {show: false}; + const son = { show: true }; + const soff = { show: false }; function initLegendRow(s, i) { if (i == 0 && (multiValLegend || !legend.live || mode == 2)) - return nullNullTuple; + return nullNullTuple let cells = []; - let row = placeTag("tr", LEGEND_SERIES, legendBody, legendBody.childNodes[i]); + let row = placeTag( + 'tr', + LEGEND_SERIES, + legendBody, + legendBody.childNodes[i] + ); addClass(row, s.class); - if (!s.show) - addClass(row, OFF); + if (!s.show) addClass(row, OFF); - let label = placeTag("th", null, row); + let label = placeTag('th', null, row); if (markers.show) { let indic = placeDiv(LEGEND_MARKER, label); if (i > 0) { - let width = markers.width(self, i); + let width = markers.width(self, i); if (width) - indic.style.border = width + "px " + markers.dash(self, i) + " " + markers.stroke(self, i); + indic.style.border = + width + + 'px ' + + markers.dash(self, i) + + ' ' + + markers.stroke(self, i); indic.style.background = markers.fill(self, i); } @@ -3187,47 +3158,79 @@ var uPlot = (function () { if (i > 0) { if (!markers.show) - text.style.color = s.width > 0 ? markers.stroke(self, i) : markers.fill(self, i); + text.style.color = + s.width > 0 + ? markers.stroke(self, i) + : markers.fill(self, i); - onMouse("click", label, e => { - if (cursor._lock) - return; + onMouse( + 'click', + label, + (e) => { + if (cursor._lock) return - setCursorEvent(e); + setCursorEvent(e); - let seriesIdx = series.indexOf(s); + let seriesIdx = series.indexOf(s); - if ((e.ctrlKey || e.metaKey) != legend.isolate) { - // if any other series is shown, isolate this one. else show all - let isolate = series.some((s, i) => i > 0 && i != seriesIdx && s.show); + if ((e.ctrlKey || e.metaKey) != legend.isolate) { + // if any other series is shown, isolate this one. else show all + let isolate = series.some( + (s, i) => i > 0 && i != seriesIdx && s.show + ); - series.forEach((s, i) => { - i > 0 && setSeries(i, isolate ? (i == seriesIdx ? son : soff) : son, true, syncOpts.setSeries); - }); - } - else - setSeries(seriesIdx, {show: !s.show}, true, syncOpts.setSeries); - }, false); + series.forEach((s, i) => { + i > 0 && + setSeries( + i, + isolate + ? i == seriesIdx + ? son + : soff + : son, + true, + syncOpts.setSeries + ); + }); + } else + setSeries( + seriesIdx, + { show: !s.show }, + true, + syncOpts.setSeries + ); + }, + false + ); if (cursorFocus) { - onMouse(mouseenter, label, e => { - if (cursor._lock) - return; - - setCursorEvent(e); - - setSeries(series.indexOf(s), FOCUS_TRUE, true, syncOpts.setSeries); - }, false); + onMouse( + mouseenter, + label, + (e) => { + if (cursor._lock) return + + setCursorEvent(e); + + setSeries( + series.indexOf(s), + FOCUS_TRUE, + true, + syncOpts.setSeries + ); + }, + false + ); } } for (var key in legendCols) { - let v = placeTag("td", LEGEND_VALUE, row); - v.textContent = "--"; + let v = placeTag('td', LEGEND_VALUE, row); + v.textContent = '--'; cells.push(v); } - return [row, cells]; + return [row, cells] } const mouseListeners = new Map(); @@ -3237,7 +3240,7 @@ var uPlot = (function () { const listener = cursor.bind[ev](self, targ, fn, onlyTarg); if (listener) { - on(ev, targ, targListeners[ev] = listener); + on(ev, targ, (targListeners[ev] = listener)); mouseListeners.set(targ, targListeners); } } @@ -3252,8 +3255,7 @@ var uPlot = (function () { } } - if (ev == null) - mouseListeners.delete(targ); + if (ev == null) mouseListeners.delete(targ); } let fullWidCss = 0; @@ -3272,7 +3274,6 @@ var uPlot = (function () { let _plotWidCss = plotWidCss; let _plotHgtCss = plotHgtCss; - let plotLft = 0; let plotTop = 0; let plotWid = 0; @@ -3288,7 +3289,7 @@ var uPlot = (function () { let shouldSetLegend = false; function _setSize(width, height, force) { - if (force || (width != self.width || height != self.height)) + if (force || width != self.width || height != self.height) calcSize(width, height); resetYSeries(false); @@ -3300,23 +3301,23 @@ var uPlot = (function () { } function calcSize(width, height) { - // log("calcSize()", arguments); + // log("calcSize()", arguments); - self.width = fullWidCss = plotWidCss = width; + self.width = fullWidCss = plotWidCss = width; self.height = fullHgtCss = plotHgtCss = height; - plotLftCss = plotTopCss = 0; + plotLftCss = plotTopCss = 0; calcPlotRect(); calcAxesRects(); let bb = self.bbox; - plotLft = bb.left = incrRound(plotLftCss * pxRatio, 0.5); - plotTop = bb.top = incrRound(plotTopCss * pxRatio, 0.5); - plotWid = bb.width = incrRound(plotWidCss * pxRatio, 0.5); + plotLft = bb.left = incrRound(plotLftCss * pxRatio, 0.5); + plotTop = bb.top = incrRound(plotTopCss * pxRatio, 0.5); + plotWid = bb.width = incrRound(plotWidCss * pxRatio, 0.5); plotHgt = bb.height = incrRound(plotHgtCss * pxRatio, 0.5); - // updOriDims(); + // updOriDims(); } // ensures size calc convergence @@ -3333,7 +3334,8 @@ var uPlot = (function () { let axesConverged = axesCalc(cycleNum); let paddingConverged = paddingCalc(cycleNum); - converged = cycleNum == CYCLE_LIMIT || (axesConverged && paddingConverged); + converged = + cycleNum == CYCLE_LIMIT || (axesConverged && paddingConverged); if (!converged) { calcSize(self.width, self.height); @@ -3342,7 +3344,7 @@ var uPlot = (function () { } } - function setSize({width, height}) { + function setSize({ width, height }) { _setSize(width, height); } @@ -3358,7 +3360,7 @@ var uPlot = (function () { axes.forEach((axis, i) => { if (axis.show && axis._show) { - let {side, _size} = axis; + let { side, _size } = axis; let isVt = side % 2; let labelSize = axis.label != null ? axis.labelSize : 0; @@ -3371,19 +3373,14 @@ var uPlot = (function () { if (side == 3) { plotLftCss += fullSize; hasLftAxis = true; - } - else - hasRgtAxis = true; - } - else { + } else hasRgtAxis = true; + } else { plotHgtCss -= fullSize; if (side == 0) { plotTopCss += fullSize; hasTopAxis = true; - } - else - hasBtmAxis = true; + } else hasBtmAxis = true; } } } @@ -3413,10 +3410,18 @@ var uPlot = (function () { function incrOffset(side, size) { switch (side) { - case 1: off1 += size; return off1 - size; - case 2: off2 += size; return off2 - size; - case 3: off3 -= size; return off3 + size; - case 0: off0 -= size; return off0 + size; + case 1: + off1 += size; + return off1 - size + case 2: + off2 += size; + return off2 - size + case 3: + off3 -= size; + return off3 + size + case 0: + off0 -= size; + return off0 + size } } @@ -3432,20 +3437,24 @@ var uPlot = (function () { }); } - const cursor = self.cursor = assign({}, cursorOpts, {drag: {y: mode == 2}}, opts.cursor); + const cursor = (self.cursor = assign( + {}, + cursorOpts, + { drag: { y: mode == 2 } }, + opts.cursor + )); if (cursor.dataIdx == null) { let hov = cursor.hover; - let skip = hov.skip = new Set(hov.skip ?? []); + let skip = (hov.skip = new Set(hov.skip ?? [])); skip.add(void 0); // alignment artifacts - let prox = hov.prox = fnOrSelf(hov.prox); - let bias = hov.bias ??= 0; + let prox = (hov.prox = fnOrSelf(hov.prox)); + let bias = (hov.bias ??= 0); // TODO: only scan between in-view idxs (i0, i1) cursor.dataIdx = (self, seriesIdx, cursorIdx, valAtPosX) => { - if (seriesIdx == 0) - return cursorIdx; + if (seriesIdx == 0) return cursorIdx let idx2 = cursorIdx; @@ -3467,55 +3476,73 @@ var uPlot = (function () { if (bias == 0 || bias == -1) { j = cursorIdx; while (nonNullLft == null && j-- > 0) { - if (!skip.has(yValues[j])) - nonNullLft = j; + if (!skip.has(yValues[j])) nonNullLft = j; } } if (bias == 0 || bias == 1) { j = cursorIdx; while (nonNullRgt == null && j++ < yValues.length) { - if (!skip.has(yValues[j])) - nonNullRgt = j; + if (!skip.has(yValues[j])) nonNullRgt = j; } } if (nonNullLft != null || nonNullRgt != null) { if (withProx) { - let lftPos = nonNullLft == null ? -Infinity : valToPosX(xValues[nonNullLft], scaleX, xDim, 0); - let rgtPos = nonNullRgt == null ? Infinity : valToPosX(xValues[nonNullRgt], scaleX, xDim, 0); + let lftPos = + nonNullLft == null + ? -Infinity + : valToPosX( + xValues[nonNullLft], + scaleX, + xDim, + 0 + ); + let rgtPos = + nonNullRgt == null + ? Infinity + : valToPosX( + xValues[nonNullRgt], + scaleX, + xDim, + 0 + ); let lftDelta = cursorLft - lftPos; let rgtDelta = rgtPos - cursorLft; if (lftDelta <= rgtDelta) { - if (lftDelta <= _prox) - idx2 = nonNullLft; + if (lftDelta <= _prox) idx2 = nonNullLft; } else { - if (rgtDelta <= _prox) - idx2 = nonNullRgt; + if (rgtDelta <= _prox) idx2 = nonNullRgt; } - } - else { + } else { idx2 = - nonNullRgt == null ? nonNullLft : - nonNullLft == null ? nonNullRgt : - cursorIdx - nonNullLft <= nonNullRgt - cursorIdx ? nonNullLft : nonNullRgt; + nonNullRgt == null + ? nonNullLft + : nonNullLft == null + ? nonNullRgt + : cursorIdx - nonNullLft <= + nonNullRgt - cursorIdx + ? nonNullLft + : nonNullRgt; } } - } - else if (withProx) { - let dist = abs(cursorLft - valToPosX(xValues[cursorIdx], scaleX, xDim, 0)); + } else if (withProx) { + let dist = abs( + cursorLft - valToPosX(xValues[cursorIdx], scaleX, xDim, 0) + ); - if (dist > _prox) - idx2 = null; + if (dist > _prox) idx2 = null; } - return idx2; + return idx2 }; } - const setCursorEvent = e => { cursor.event = e; }; + const setCursorEvent = (e) => { + cursor.event = e; + }; cursor.idxs = activeIdxs; @@ -3523,13 +3550,17 @@ var uPlot = (function () { let points = cursor.points; - points.show = fnOrSelf(points.show); - points.size = fnOrSelf(points.size); + points.show = fnOrSelf(points.show); + points.size = fnOrSelf(points.size); points.stroke = fnOrSelf(points.stroke); - points.width = fnOrSelf(points.width); - points.fill = fnOrSelf(points.fill); + points.width = fnOrSelf(points.width); + points.fill = fnOrSelf(points.fill); - const focus = self.focus = assign({}, opts.focus || {alpha: 0.3}, cursor.focus); + const focus = (self.focus = assign( + {}, + opts.focus || { alpha: 0.3 }, + cursor.focus + )); const cursorFocus = focus.prox >= 0; const cursorOnePt = cursorFocus && points.one; @@ -3549,7 +3580,7 @@ var uPlot = (function () { elTrans(pt, -10, -10, plotWidCss, plotHgtCss); over.insertBefore(pt, cursorPts[si]); - return pt; + return pt } } @@ -3558,36 +3589,44 @@ var uPlot = (function () { let isTime = mode == 1 && scales[s.scale].time; let sv = s.value; - s.value = isTime ? (isStr(sv) ? timeSeriesVal(_tzDate, timeSeriesStamp(sv, _fmtDate)) : sv || _timeSeriesVal) : sv || numSeriesVal; + s.value = isTime + ? isStr(sv) + ? timeSeriesVal(_tzDate, timeSeriesStamp(sv, _fmtDate)) + : sv || _timeSeriesVal + : sv || numSeriesVal; s.label = s.label || (isTime ? timeSeriesLabel : numSeriesLabel); } if (cursorOnePt || i > 0) { - s.width = s.width == null ? 1 : s.width; - s.paths = s.paths || linearPath || retNull; + s.width = s.width == null ? 1 : s.width; + s.paths = s.paths || linearPath || retNull; s.fillTo = fnOrSelf(s.fillTo || seriesFillTo); s.pxAlign = +ifNull(s.pxAlign, pxAlign); s.pxRound = pxRoundGen(s.pxAlign); s.stroke = fnOrSelf(s.stroke || null); - s.fill = fnOrSelf(s.fill || null); + s.fill = fnOrSelf(s.fill || null); s._stroke = s._fill = s._paths = s._focus = null; let _ptDia = ptDia(max(1, s.width), 1); - let points = s.points = assign({}, { - size: _ptDia, - width: max(1, _ptDia * .2), - stroke: s.stroke, - space: _ptDia * 2, - paths: pointsPath, - _stroke: null, - _fill: null, - }, s.points); - points.show = fnOrSelf(points.show); + let points = (s.points = assign( + {}, + { + size: _ptDia, + width: max(1, _ptDia * 0.2), + stroke: s.stroke, + space: _ptDia * 2, + paths: pointsPath, + _stroke: null, + _fill: null + }, + s.points + )); + points.show = fnOrSelf(points.show); points.filter = fnOrSelf(points.filter); - points.fill = fnOrSelf(points.fill); + points.fill = fnOrSelf(points.fill); points.stroke = fnOrSelf(points.stroke); - points.paths = fnOrSelf(points.paths); + points.paths = fnOrSelf(points.paths); points.pxAlign = s.pxAlign; } @@ -3595,7 +3634,7 @@ var uPlot = (function () { let rowCells = initLegendRow(s, i); legendRows.splice(i, 0, rowCells[0]); legendCells.splice(i, 0, rowCells[1]); - legend.values.push(null); // NULL_LEGEND_VALS not yet avil here :( + legend.values.push(null); // NULL_LEGEND_VALS not yet avil here :( } if (cursor.show) { @@ -3604,24 +3643,24 @@ var uPlot = (function () { let pt = null; if (cursorOnePt) { - if (i == 0) - pt = initCursorPt(s, i); - } - else if (i > 0) - pt = initCursorPt(s, i); + if (i == 0) pt = initCursorPt(s, i); + } else if (i > 0) pt = initCursorPt(s, i); cursorPts.splice(i, 0, pt); cursorPtsLft.splice(i, 0, 0); cursorPtsTop.splice(i, 0, 0); } - fire("addSeries", i); + fire('addSeries', i); } function addSeries(opts, si) { si = si == null ? series.length : si; - opts = mode == 1 ? setDefault(opts, si, xSeriesOpts, ySeriesOpts) : setDefault(opts, si, {}, xySeriesOpts); + opts = + mode == 1 + ? setDefault(opts, si, xSeriesOpts, ySeriesOpts) + : setDefault(opts, si, {}, xySeriesOpts); series.splice(si, 0, opts); initSeries(series[si], si); @@ -3650,7 +3689,7 @@ var uPlot = (function () { // TODO: de-init no-longer-needed scales? - fire("delSeries", i); + fire('delSeries', i); } self.delSeries = delSeries; @@ -3674,54 +3713,80 @@ var uPlot = (function () { // also set defaults for incrs & values based on axis distr let isTime = sc.time; - axis.size = fnOrSelf(axis.size); - axis.space = fnOrSelf(axis.space); + axis.size = fnOrSelf(axis.size); + axis.space = fnOrSelf(axis.space); axis.rotate = fnOrSelf(axis.rotate); if (isArr(axis.incrs)) { - axis.incrs.forEach(incr => { + axis.incrs.forEach((incr) => { !fixedDec.has(incr) && fixedDec.set(incr, guessDec(incr)); }); } - axis.incrs = fnOrSelf(axis.incrs || ( sc.distr == 2 ? wholeIncrs : (isTime ? (ms == 1 ? timeIncrsMs : timeIncrsS) : numIncrs))); - axis.splits = fnOrSelf(axis.splits || (isTime && sc.distr == 1 ? _timeAxisSplits : sc.distr == 3 ? logAxisSplits : sc.distr == 4 ? asinhAxisSplits : numAxisSplits)); + axis.incrs = fnOrSelf( + axis.incrs || + (sc.distr == 2 + ? wholeIncrs + : isTime + ? ms == 1 + ? timeIncrsMs + : timeIncrsS + : numIncrs) + ); + axis.splits = fnOrSelf( + axis.splits || + (isTime && sc.distr == 1 + ? _timeAxisSplits + : sc.distr == 3 + ? logAxisSplits + : sc.distr == 4 + ? asinhAxisSplits + : numAxisSplits) + ); - axis.stroke = fnOrSelf(axis.stroke); - axis.grid.stroke = fnOrSelf(axis.grid.stroke); - axis.ticks.stroke = fnOrSelf(axis.ticks.stroke); + axis.stroke = fnOrSelf(axis.stroke); + axis.grid.stroke = fnOrSelf(axis.grid.stroke); + axis.ticks.stroke = fnOrSelf(axis.ticks.stroke); axis.border.stroke = fnOrSelf(axis.border.stroke); let av = axis.values; - axis.values = ( + axis.values = // static array of tick values - isArr(av) && !isArr(av[0]) ? fnOrSelf(av) : - // temporal - isTime ? ( - // config array of fmtDate string tpls - isArr(av) ? - timeAxisVals(_tzDate, timeAxisStamps(av, _fmtDate)) : - // fmtDate string tpl - isStr(av) ? - timeAxisVal(_tzDate, av) : - av || _timeAxisVals - ) : av || numAxisVals + isArr(av) && !isArr(av[0]) + ? fnOrSelf(av) + : // temporal + isTime + ? // config array of fmtDate string tpls + isArr(av) + ? timeAxisVals(_tzDate, timeAxisStamps(av, _fmtDate)) + : // fmtDate string tpl + //isStr(av) ? + // timeAxisVal(_tzDate, av) : + av || _timeAxisVals + : av || numAxisVals; + + axis.filter = fnOrSelf( + axis.filter || + (sc.distr >= 3 && sc.log == 10 + ? log10AxisValsFilt + : sc.distr == 3 && sc.log == 2 + ? log2AxisValsFilt + : retArg1) ); - axis.filter = fnOrSelf(axis.filter || ( sc.distr >= 3 && sc.log == 10 ? log10AxisValsFilt : sc.distr == 3 && sc.log == 2 ? log2AxisValsFilt : retArg1)); - - axis.font = pxRatioFont(axis.font); + axis.font = pxRatioFont(axis.font); axis.labelFont = pxRatioFont(axis.labelFont); - axis._size = axis.size(self, null, i, 0); + axis._size = axis.size(self, null, i, 0); - axis._space = - axis._rotate = - axis._incrs = - axis._found = // foundIncrSpace - axis._splits = - axis._values = null; + axis._space = + axis._rotate = + axis._incrs = + axis._found = // foundIncrSpace + axis._splits = + axis._values = + null; if (axis._size > 0) { sidesWithAxes[i] = true; @@ -3729,7 +3794,7 @@ var uPlot = (function () { } // debug - // axis._el.style.background = "#" + Math.floor(Math.random()*16777215).toString(16) + '80'; + // axis._el.style.background = "#" + Math.floor(Math.random()*16777215).toString(16) + '80'; } } @@ -3740,15 +3805,25 @@ var uPlot = (function () { let size = 0; if (ori == 0 && (hasLftAxis || hasRgtAxis)) - size = (side == 0 && !hasTopAxis || side == 2 && !hasBtmAxis ? round(xAxisOpts.size / 3) : 0); + size = + (side == 0 && !hasTopAxis) || (side == 2 && !hasBtmAxis) + ? round(xAxisOpts.size / 3) + : 0; if (ori == 1 && (hasTopAxis || hasBtmAxis)) - size = (side == 1 && !hasRgtAxis || side == 3 && !hasLftAxis ? round(yAxisOpts.size / 2) : 0); + size = + (side == 1 && !hasRgtAxis) || (side == 3 && !hasLftAxis) + ? round(yAxisOpts.size / 2) + : 0; - return size; + return size } - const padding = self.padding = (opts.padding || [autoPadSide,autoPadSide,autoPadSide,autoPadSide]).map(p => fnOrSelf(ifNull(p, autoPadSide))); - const _padding = self._padding = padding.map((p, i) => p(self, i, sidesWithAxes, 0)); + const padding = (self.padding = ( + opts.padding || [autoPadSide, autoPadSide, autoPadSide, autoPadSide] + ).map((p) => fnOrSelf(ifNull(p, autoPadSide)))); + const _padding = (self._padding = padding.map((p, i) => + p(self, i, sidesWithAxes, 0) + )); let dataLen; @@ -3768,12 +3843,9 @@ var uPlot = (function () { if (mode == 2) { dataLen = 0; - for (let i = 1; i < series.length; i++) - dataLen += data[i][0].length; - } - else { - if (data.length == 0) - self.data = self._data = data = [[]]; + for (let i = 1; i < series.length; i++) dataLen += data[i][0].length; + } else { + if (data.length == 0) self.data = self._data = data = [[]]; data0 = data[0]; dataLen = data0.length; @@ -3783,9 +3855,8 @@ var uPlot = (function () { if (xScaleDistr == 2) { scaleData = data.slice(); - let _data0 = scaleData[0] = Array(dataLen); - for (let i = 0; i < dataLen; i++) - _data0[i] = i; + let _data0 = (scaleData[0] = Array(dataLen)); + for (let i = 0; i < dataLen; i++) _data0[i] = i; } self._data = data = scaleData; @@ -3793,7 +3864,7 @@ var uPlot = (function () { resetYSeries(true); - fire("setData"); + fire('setData'); // forces x axis tick values to re-generate when neither x scale nor y scale changes // in ordinal mode, scale range is by index, so will not change if new data has same length, but tick values are from data @@ -3816,10 +3887,8 @@ var uPlot = (function () { if (_resetScales !== false) { let xsc = scaleX; - if (xsc.auto(self, viaAutoScaleX)) - autoScaleX(); - else - _setScale(xScaleKey, xsc.min, xsc.max); + if (xsc.auto(self, viaAutoScaleX)) autoScaleX(); + else _setScale(xScaleKey, xsc.min, xsc.max); shouldSetCursor = shouldSetCursor || cursor.left >= 0; shouldSetLegend = true; @@ -3845,19 +3914,15 @@ var uPlot = (function () { if (xScaleDistr == 2) { _min = i0; _max = i1; - } - else if (_min == _max) { + } else if (_min == _max) { if (xScaleDistr == 3) [_min, _max] = rangeLog(_min, _min, scaleX.log, false); else if (xScaleDistr == 4) [_min, _max] = rangeAsinh(_min, _min, scaleX.log, false); - else if (scaleX.time) - _max = _min + round(86400 / ms); - else - [_min, _max] = rangeNum(_min, _max, rangePad, true); + else if (scaleX.time) _max = _min + round(86400 / ms); + else [_min, _max] = rangeNum(_min, _max, rangePad, true); } - } - else { + } else { i0 = idxs[0] = _min = null; i1 = idxs[1] = _max = null; } @@ -3866,71 +3931,78 @@ var uPlot = (function () { _setScale(xScaleKey, _min, _max); } - let ctxStroke, ctxFill, ctxWidth, ctxDash, ctxJoin, ctxCap, ctxFont, ctxAlign, ctxBaseline; + let ctxStroke, + ctxFill, + ctxWidth, + ctxDash, + ctxJoin, + ctxCap, + ctxFont, + ctxAlign, + ctxBaseline; let ctxAlpha; function setCtxStyle(stroke, width, dash, cap, fill, join) { stroke ??= transparent; - dash ??= EMPTY_ARR; - cap ??= "butt"; // (‿|‿) - fill ??= transparent; - join ??= "round"; - - if (stroke != ctxStroke) - ctx.strokeStyle = ctxStroke = stroke; - if (fill != ctxFill) - ctx.fillStyle = ctxFill = fill; - if (width != ctxWidth) - ctx.lineWidth = ctxWidth = width; - if (join != ctxJoin) - ctx.lineJoin = ctxJoin = join; - if (cap != ctxCap) - ctx.lineCap = ctxCap = cap; - if (dash != ctxDash) - ctx.setLineDash(ctxDash = dash); + dash ??= EMPTY_ARR; + cap ??= 'butt'; // (‿|‿) + fill ??= transparent; + join ??= 'round'; + + if (stroke != ctxStroke) ctx.strokeStyle = ctxStroke = stroke; + if (fill != ctxFill) ctx.fillStyle = ctxFill = fill; + if (width != ctxWidth) ctx.lineWidth = ctxWidth = width; + if (join != ctxJoin) ctx.lineJoin = ctxJoin = join; + if (cap != ctxCap) ctx.lineCap = ctxCap = cap; + if (dash != ctxDash) ctx.setLineDash((ctxDash = dash)); } function setFontStyle(font, fill, align, baseline) { - if (fill != ctxFill) - ctx.fillStyle = ctxFill = fill; - if (font != ctxFont) - ctx.font = ctxFont = font; - if (align != ctxAlign) - ctx.textAlign = ctxAlign = align; - if (baseline != ctxBaseline) - ctx.textBaseline = ctxBaseline = baseline; + if (fill != ctxFill) ctx.fillStyle = ctxFill = fill; + if (font != ctxFont) ctx.font = ctxFont = font; + if (align != ctxAlign) ctx.textAlign = ctxAlign = align; + if (baseline != ctxBaseline) ctx.textBaseline = ctxBaseline = baseline; } function accScale(wsc, psc, facet, data, sorted = 0) { - if (data.length > 0 && wsc.auto(self, viaAutoScaleX) && (psc == null || psc.min == null)) { + if ( + data.length > 0 && + wsc.auto(self, viaAutoScaleX) && + (psc == null || psc.min == null) + ) { let _i0 = ifNull(i0, 0); let _i1 = ifNull(i1, data.length - 1); // only run getMinMax() for invalidated series data, else reuse - let minMax = facet.min == null ? (wsc.distr == 3 ? getMinMaxLog(data, _i0, _i1) : getMinMax(data, _i0, _i1, sorted)) : [facet.min, facet.max]; + let minMax = + facet.min == null + ? wsc.distr == 3 + ? getMinMaxLog(data, _i0, _i1) + : getMinMax(data, _i0, _i1, sorted) + : [facet.min, facet.max]; // initial min/max - wsc.min = min(wsc.min, facet.min = minMax[0]); - wsc.max = max(wsc.max, facet.max = minMax[1]); + wsc.min = min(wsc.min, (facet.min = minMax[0])); + wsc.max = max(wsc.max, (facet.max = minMax[1])); } } - const AUTOSCALE = {min: null, max: null}; + const AUTOSCALE = { min: null, max: null }; function setScales() { - // log("setScales()", arguments); + // log("setScales()", arguments); // implicitly add auto scales, and unranged scales for (let k in scales) { let sc = scales[k]; - if (pendScales[k] == null && - ( - // scales that have never been set (on init) - sc.min == null || + if ( + pendScales[k] == null && + // scales that have never been set (on init) + (sc.min == null || // or auto scales when the x scale was explicitly set - pendScales[xScaleKey] != null && sc.auto(self, viaAutoScaleX) - ) + (pendScales[xScaleKey] != null && + sc.auto(self, viaAutoScaleX))) ) { pendScales[k] = AUTOSCALE; } @@ -3940,13 +4012,16 @@ var uPlot = (function () { for (let k in scales) { let sc = scales[k]; - if (pendScales[k] == null && sc.from != null && pendScales[sc.from] != null) + if ( + pendScales[k] == null && + sc.from != null && + pendScales[sc.from] != null + ) pendScales[k] = AUTOSCALE; } // explicitly setting the x-scale invalidates everything (acts as redraw) - if (pendScales[xScaleKey] != null) - resetYSeries(true); // TODO: only reset series on auto scales? + if (pendScales[xScaleKey] != null) resetYSeries(true); // TODO: only reset series on auto scales? let wipScales = {}; @@ -3954,17 +4029,15 @@ var uPlot = (function () { let psc = pendScales[k]; if (psc != null) { - let wsc = wipScales[k] = copy(scales[k], fastIsObj); + let wsc = (wipScales[k] = copy(scales[k], fastIsObj)); - if (psc.min != null) - assign(wsc, psc); + if (psc.min != null) assign(wsc, psc); else if (k != xScaleKey || mode == 2) { if (dataLen == 0 && wsc.from == null) { let minMax = wsc.range(self, null, null, k); wsc.min = minMax[0]; wsc.max = minMax[1]; - } - else { + } else { wsc.min = inf; wsc.max = -inf; } @@ -3979,8 +4052,7 @@ var uPlot = (function () { let k = s.scale; let psc = pendScales[k]; - if (psc == null) - return; + if (psc == null) return let wsc = wipScales[k]; @@ -3996,36 +4068,46 @@ var uPlot = (function () { // don't try to contract same or adjacent idxs if (i1 - i0 > 1) { // closest indices can be outside of view - if (data[0][i0] < wsc.min) - i0++; - if (data[0][i1] > wsc.max) - i1--; + if (data[0][i0] < wsc.min) i0++; + if (data[0][i1] > wsc.max) i1--; } s.min = data0[i0]; s.max = data0[i1]; - } - else if (s.show && s.auto) + } else if (s.show && s.auto) accScale(wsc, psc, s, data[i], s.sorted); s.idxs[0] = i0; s.idxs[1] = i1; - } - else { + } else { if (i > 0) { if (s.show && s.auto) { // TODO: only handles, assumes and requires facets[0] / 'x' scale, and facets[1] / 'y' scale - let [ xFacet, yFacet ] = s.facets; + let [xFacet, yFacet] = s.facets; let xScaleKey = xFacet.scale; let yScaleKey = yFacet.scale; - let [ xData, yData ] = data[i]; + let [xData, yData] = data[i]; let wscx = wipScales[xScaleKey]; let wscy = wipScales[yScaleKey]; // null can happen when only x is zoomed, but y has static range and doesnt get auto-added to pending - wscx != null && accScale(wscx, pendScales[xScaleKey], xFacet, xData, xFacet.sorted); - wscy != null && accScale(wscy, pendScales[yScaleKey], yFacet, yData, yFacet.sorted); + wscx != null && + accScale( + wscx, + pendScales[xScaleKey], + xFacet, + xData, + xFacet.sorted + ); + wscy != null && + accScale( + wscy, + pendScales[yScaleKey], + yFacet, + yData, + yFacet.sorted + ); // temp s.min = yFacet.min; @@ -4043,7 +4125,7 @@ var uPlot = (function () { if (wsc.from == null && (psc == null || psc.min == null)) { let minMax = wsc.range( self, - wsc.min == inf ? null : wsc.min, + wsc.min == inf ? null : wsc.min, wsc.max == -inf ? null : wsc.max, k ); @@ -4060,8 +4142,7 @@ var uPlot = (function () { if (wsc.from != null) { let base = wipScales[wsc.from]; - if (base.min == null) - wsc.min = wsc.max = null; + if (base.min == null) wsc.min = wsc.max = null; else { let minMax = wsc.range(self, base.min, base.max, k); wsc.min = minMax[0]; @@ -4083,8 +4164,22 @@ var uPlot = (function () { let distr = sc.distr; - sc._min = distr == 3 ? log10(sc.min) : distr == 4 ? asinh(sc.min, sc.asinh) : distr == 100 ? sc.fwd(sc.min) : sc.min; - sc._max = distr == 3 ? log10(sc.max) : distr == 4 ? asinh(sc.max, sc.asinh) : distr == 100 ? sc.fwd(sc.max) : sc.max; + sc._min = + distr == 3 + ? log10(sc.min) + : distr == 4 + ? asinh(sc.min, sc.asinh) + : distr == 100 + ? sc.fwd(sc.min) + : sc.min; + sc._max = + distr == 3 + ? log10(sc.max) + : distr == 4 + ? asinh(sc.max, sc.asinh) + : distr == 100 + ? sc.fwd(sc.max) + : sc.max; changed[k] = anyChanged = true; } @@ -4094,26 +4189,22 @@ var uPlot = (function () { // invalidate paths of all series on changed scales series.forEach((s, i) => { if (mode == 2) { - if (i > 0 && changed.y) - s._paths = null; - } - else { - if (changed[s.scale]) - s._paths = null; + if (i > 0 && changed.y) s._paths = null; + } else { + if (changed[s.scale]) s._paths = null; } }); for (let k in changed) { shouldConvergeSize = true; - fire("setScale", k); + fire('setScale', k); } if (cursor.show && cursor.left >= 0) shouldSetCursor = shouldSetLegend = true; } - for (let k in pendScales) - pendScales[k] = null; + for (let k in pendScales) pendScales[k] = null; } // grabs the nearest indices with y data outside of x-scale limits @@ -4121,13 +4212,11 @@ var uPlot = (function () { let _i0 = clamp(i0 - 1, 0, dataLen - 1); let _i1 = clamp(i1 + 1, 0, dataLen - 1); - while (ydata[_i0] == null && _i0 > 0) - _i0--; + while (ydata[_i0] == null && _i0 > 0) _i0--; - while (ydata[_i1] == null && _i1 < dataLen - 1) - _i1++; + while (ydata[_i1] == null && _i1 < dataLen - 1) _i1++; - return [_i0, _i1]; + return [_i0, _i1] } function drawSeries() { @@ -4141,11 +4230,13 @@ var uPlot = (function () { if (ctxAlpha != s.alpha) ctx.globalAlpha = ctxAlpha = s.alpha; - let _idxs = mode == 2 ? [0, data[i][0].length - 1] : getOuterIdxs(data[i]); + let _idxs = + mode == 2 + ? [0, data[i][0].length - 1] + : getOuterIdxs(data[i]); s._paths = s.paths(self, i, _idxs[0], _idxs[1]); - if (ctxAlpha != 1) - ctx.globalAlpha = ctxAlpha = 1; + if (ctxAlpha != 1) ctx.globalAlpha = ctxAlpha = 1; } } }); @@ -4164,15 +4255,20 @@ var uPlot = (function () { let idxs = s.points.filter(self, i, show, _gaps); if (show || idxs) { - s.points._paths = s.points.paths(self, i, i0, i1, idxs); + s.points._paths = s.points.paths( + self, + i, + i0, + i1, + idxs + ); drawPath(i, true); } } - if (ctxAlpha != 1) - ctx.globalAlpha = ctxAlpha = 1; + if (ctxAlpha != 1) ctx.globalAlpha = ctxAlpha = 1; - fire("drawSeries", i); + fire('drawSeries', i); } }); } @@ -4182,7 +4278,7 @@ var uPlot = (function () { let s = _points ? series[si].points : series[si]; s._stroke = s.stroke(self, si); - s._fill = s.fill(self, si); + s._fill = s.fill(self, si); } function drawPath(si, _points) { @@ -4195,8 +4291,8 @@ var uPlot = (function () { flags, _stroke: strokeStyle = s._stroke, - _fill: fillStyle = s._fill, - _width: width = s.width, + _fill: fillStyle = s._fill, + _width: width = s.width } = s._paths; width = roundDec(width * pxRatio, 3); @@ -4205,7 +4301,7 @@ var uPlot = (function () { let offset = (width % 2) / 2; if (_points && fillStyle == null) - fillStyle = width > 0 ? "#fff" : strokeStyle; + fillStyle = width > 0 ? '#fff' : strokeStyle; let _pxAlign = s.pxAlign == 1 && offset > 0; @@ -4223,54 +4319,128 @@ var uPlot = (function () { // the points pathbuilder's gapsClip is its boundsClip, since points dont need gaps clipping, and bounds depend on point size if (_points) - strokeFill(strokeStyle, width, s.dash, s.cap, fillStyle, stroke, fill, flags, gapsClip); + strokeFill( + strokeStyle, + width, + s.dash, + s.cap, + fillStyle, + stroke, + fill, + flags, + gapsClip + ); else - fillStroke(si, strokeStyle, width, s.dash, s.cap, fillStyle, stroke, fill, flags, boundsClip, gapsClip); + fillStroke( + si, + strokeStyle, + width, + s.dash, + s.cap, + fillStyle, + stroke, + fill, + flags, + boundsClip, + gapsClip + ); _pxAlign && ctx.translate(-offset, -offset); } - function fillStroke(si, strokeStyle, lineWidth, lineDash, lineCap, fillStyle, strokePath, fillPath, flags, boundsClip, gapsClip) { + function fillStroke( + si, + strokeStyle, + lineWidth, + lineDash, + lineCap, + fillStyle, + strokePath, + fillPath, + flags, + boundsClip, + gapsClip + ) { let didStrokeFill = false; // for all bands where this series is the top edge, create upwards clips using the bottom edges // and apply clips + fill with band fill or dfltFill - flags != 0 && bands.forEach((b, bi) => { - // isUpperEdge? - if (b.series[0] == si) { - let lowerEdge = series[b.series[1]]; - let lowerData = data[b.series[1]]; - - let bandClip = (lowerEdge._paths || EMPTY_OBJ).band; - - if (isArr(bandClip)) - bandClip = b.dir == 1 ? bandClip[0] : bandClip[1]; - - let gapsClip2; - - let _fillStyle = null; + flags != 0 && + bands.forEach((b, bi) => { + // isUpperEdge? + if (b.series[0] == si) { + let lowerEdge = series[b.series[1]]; + let lowerData = data[b.series[1]]; + + let bandClip = (lowerEdge._paths || EMPTY_OBJ).band; + + if (isArr(bandClip)) + bandClip = b.dir == 1 ? bandClip[0] : bandClip[1]; + + let gapsClip2; + + let _fillStyle = null; + + // hasLowerEdge? + if ( + lowerEdge.show && + bandClip && + hasData(lowerData, i0, i1) + ) { + _fillStyle = b.fill(self, bi) || fillStyle; + gapsClip2 = lowerEdge._paths.clip; + } else bandClip = null; + + strokeFill( + strokeStyle, + lineWidth, + lineDash, + lineCap, + _fillStyle, + strokePath, + fillPath, + flags, + boundsClip, + gapsClip, + gapsClip2, + bandClip + ); - // hasLowerEdge? - if (lowerEdge.show && bandClip && hasData(lowerData, i0, i1)) { - _fillStyle = b.fill(self, bi) || fillStyle; - gapsClip2 = lowerEdge._paths.clip; + didStrokeFill = true; } - else - bandClip = null; - - strokeFill(strokeStyle, lineWidth, lineDash, lineCap, _fillStyle, strokePath, fillPath, flags, boundsClip, gapsClip, gapsClip2, bandClip); - - didStrokeFill = true; - } - }); + }); if (!didStrokeFill) - strokeFill(strokeStyle, lineWidth, lineDash, lineCap, fillStyle, strokePath, fillPath, flags, boundsClip, gapsClip); + strokeFill( + strokeStyle, + lineWidth, + lineDash, + lineCap, + fillStyle, + strokePath, + fillPath, + flags, + boundsClip, + gapsClip + ); } const CLIP_FILL_STROKE = BAND_CLIP_FILL | BAND_CLIP_STROKE; - function strokeFill(strokeStyle, lineWidth, lineDash, lineCap, fillStyle, strokePath, fillPath, flags, boundsClip, gapsClip, gapsClip2, bandClip) { + function strokeFill( + strokeStyle, + lineWidth, + lineDash, + lineCap, + fillStyle, + strokePath, + fillPath, + flags, + boundsClip, + gapsClip, + gapsClip2, + bandClip + ) { setCtxStyle(strokeStyle, lineWidth, lineDash, lineCap, fillStyle); if (boundsClip || gapsClip || bandClip) { @@ -4285,13 +4455,11 @@ var uPlot = (function () { gapsClip2 && ctx.clip(gapsClip2); doFill(fillStyle, fillPath); doStroke(strokeStyle, strokePath, lineWidth); - } - else if (flags & BAND_CLIP_STROKE) { + } else if (flags & BAND_CLIP_STROKE) { doFill(fillStyle, fillPath); ctx.clip(bandClip); doStroke(strokeStyle, strokePath, lineWidth); - } - else if (flags & BAND_CLIP_FILL) { + } else if (flags & BAND_CLIP_FILL) { ctx.save(); ctx.clip(bandClip); gapsClip2 && ctx.clip(gapsClip2); @@ -4299,14 +4467,12 @@ var uPlot = (function () { ctx.restore(); doStroke(strokeStyle, strokePath, lineWidth); } - } - else { + } else { doFill(fillStyle, fillPath); doStroke(strokeStyle, strokePath, lineWidth); } - if (boundsClip || gapsClip || bandClip) - ctx.restore(); + if (boundsClip || gapsClip || bandClip) ctx.restore(); } function doStroke(strokeStyle, strokePath, lineWidth) { @@ -4316,9 +4482,7 @@ var uPlot = (function () { ctx.strokeStyle = ctxStroke = strokeStyle; ctx.stroke(strokePath); }); - } - else - strokePath != null && strokeStyle && ctx.stroke(strokePath); + } else strokePath != null && strokeStyle && ctx.stroke(strokePath); } } @@ -4328,9 +4492,7 @@ var uPlot = (function () { ctx.fillStyle = ctxFill = fillStyle; ctx.fill(fillPath); }); - } - else - fillPath != null && fillStyle && ctx.fill(fillPath); + } else fillPath != null && fillStyle && ctx.fill(fillPath); } function getIncrSpace(axisIdx, min, max, fullDim) { @@ -4338,18 +4500,41 @@ var uPlot = (function () { let incrSpace; - if (fullDim <= 0) - incrSpace = [0, 0]; + if (fullDim <= 0) incrSpace = [0, 0]; else { - let minSpace = axis._space = axis.space(self, axisIdx, min, max, fullDim); - let incrs = axis._incrs = axis.incrs(self, axisIdx, min, max, fullDim, minSpace); - incrSpace = findIncr(min, max, incrs, fullDim, minSpace); + let minSpace = (axis._space = axis.space( + self, + axisIdx, + min, + max, + fullDim + )); + let incrs = (axis._incrs = axis.incrs( + self, + axisIdx, + min, + max, + fullDim, + minSpace + )); + incrSpace = findIncr(min, max, incrs, fullDim, minSpace); } - return (axis._found = incrSpace); - } - - function drawOrthoLines(offs, filts, ori, side, pos0, len, width, stroke, dash, cap) { + return (axis._found = incrSpace) + } + + function drawOrthoLines( + offs, + filts, + ori, + side, + pos0, + len, + width, + stroke, + dash, + cap + ) { let offset = (width % 2) / 2; pxAlign == 1 && ctx.translate(offset, offset); @@ -4358,23 +4543,24 @@ var uPlot = (function () { ctx.beginPath(); - let x0, y0, x1, y1, pos1 = pos0 + (side == 0 || side == 3 ? -len : len); + let x0, + y0, + x1, + y1, + pos1 = pos0 + (side == 0 || side == 3 ? -len : len); if (ori == 0) { y0 = pos0; y1 = pos1; - } - else { + } else { x0 = pos0; x1 = pos1; } for (let i = 0; i < offs.length; i++) { if (filts[i] != null) { - if (ori == 0) - x0 = x1 = offs[i]; - else - y0 = y1 = offs[i]; + if (ori == 0) x0 = x1 = offs[i]; + else y0 = y1 = offs[i]; ctx.moveTo(x0, y0); ctx.lineTo(x1, y1); @@ -4387,13 +4573,12 @@ var uPlot = (function () { } function axesCalc(cycleNum) { - // log("axesCalc()", arguments); + // log("axesCalc()", arguments); let converged = true; axes.forEach((axis, i) => { - if (!axis.show) - return; + if (!axis.show) return let scale = scales[axis.scale]; @@ -4403,9 +4588,8 @@ var uPlot = (function () { axis._show = false; resetYSeries(false); } - return; - } - else { + return + } else { if (!axis._show) { converged = false; axis._show = true; @@ -4416,24 +4600,45 @@ var uPlot = (function () { let side = axis.side; let ori = side % 2; - let {min, max} = scale; // // should this toggle them ._show = false + let { min, max } = scale; // // should this toggle them ._show = false - let [_incr, _space] = getIncrSpace(i, min, max, ori == 0 ? plotWidCss : plotHgtCss); + let [_incr, _space] = getIncrSpace( + i, + min, + max, + ori == 0 ? plotWidCss : plotHgtCss + ); - if (_space == 0) - return; + if (_space == 0) return // if we're using index positions, force first tick to match passed index let forceMin = scale.distr == 2; - let _splits = axis._splits = axis.splits(self, i, min, max, _incr, _space, forceMin); + let _splits = (axis._splits = axis.splits( + self, + i, + min, + max, + _incr, + _space, + forceMin + )); // tick labels // BOO this assumes a specific data/series - let splits = scale.distr == 2 ? _splits.map(i => data0[i]) : _splits; - let incr = scale.distr == 2 ? data0[_splits[1]] - data0[_splits[0]] : _incr; - - let values = axis._values = axis.values(self, axis.filter(self, splits, i, _space, incr), i, _space, incr); + let splits = + scale.distr == 2 ? _splits.map((i) => data0[i]) : _splits; + let incr = + scale.distr == 2 ? data0[_splits[1]] - data0[_splits[0]] : _incr; + + let values = (axis._values = axis.values( + self, + axis.filter(self, splits, i, _space, incr), + i, + _space, + incr, + fmtNum + )); // rotating of labels only supported on bottom x axis axis._rotate = side == 2 ? axis.rotate(self, values, i, _space) : 0; @@ -4442,11 +4647,12 @@ var uPlot = (function () { axis._size = ceil(axis.size(self, values, i, cycleNum)); - if (oldSize != null && axis._size != oldSize) // ready && ? + if (oldSize != null && axis._size != oldSize) + // ready && ? converged = false; }); - return converged; + return converged } function paddingCalc(cycleNum) { @@ -4455,21 +4661,19 @@ var uPlot = (function () { padding.forEach((p, i) => { let _p = p(self, i, sidesWithAxes, cycleNum); - if (_p != _padding[i]) - converged = false; + if (_p != _padding[i]) converged = false; _padding[i] = _p; }); - return converged; + return converged } function drawAxesGrid() { for (let i = 0; i < axes.length; i++) { let axis = axes[i]; - if (!axis.show || !axis._show) - continue; + if (!axis.show || !axis._show) continue let side = axis.side; let ori = side % 2; @@ -4485,21 +4689,21 @@ var uPlot = (function () { let shiftAmt = axis.labelGap * shiftDir; let baseLpos = round((axis._lpos + shiftAmt) * pxRatio); - setFontStyle(axis.labelFont[0], fillStyle, "center", side == 2 ? TOP : BOTTOM); + setFontStyle( + axis.labelFont[0], + fillStyle, + 'center', + side == 2 ? TOP : BOTTOM + ); ctx.save(); if (ori == 1) { x = y = 0; - ctx.translate( - baseLpos, - round(plotTop + plotHgt / 2), - ); + ctx.translate(baseLpos, round(plotTop + plotHgt / 2)); ctx.rotate((side == 3 ? -PI : PI) / 2); - - } - else { + } else { x = round(plotLft + plotWid / 2); y = baseLpos; } @@ -4511,8 +4715,7 @@ var uPlot = (function () { let [_incr, _space] = axis._found; - if (_space == 0) - continue; + if (_space == 0) continue let scale = scales[axis.scale]; @@ -4525,36 +4728,49 @@ var uPlot = (function () { // tick labels // BOO this assumes a specific data/series - let splits = scale.distr == 2 ? _splits.map(i => data0[i]) : _splits; - let incr = scale.distr == 2 ? data0[_splits[1]] - data0[_splits[0]] : _incr; + let splits = + scale.distr == 2 ? _splits.map((i) => data0[i]) : _splits; + let incr = + scale.distr == 2 ? data0[_splits[1]] - data0[_splits[0]] : _incr; let ticks = axis.ticks; let border = axis.border; let tickSize = ticks.show ? round(ticks.size * pxRatio) : 0; // rotating of labels only supported on bottom x axis - let angle = axis._rotate * -PI/180; + let angle = (axis._rotate * -PI) / 180; - let basePos = pxRound(axis._pos * pxRatio); + let basePos = pxRound(axis._pos * pxRatio); let shiftAmt = (tickSize + axisGap) * shiftDir; let finalPos = basePos + shiftAmt; - y = ori == 0 ? finalPos : 0; - x = ori == 1 ? finalPos : 0; - - let font = axis.font[0]; - let textAlign = axis.align == 1 ? LEFT : - axis.align == 2 ? RIGHT : - angle > 0 ? LEFT : - angle < 0 ? RIGHT : - ori == 0 ? "center" : side == 3 ? RIGHT : LEFT; - let textBaseline = angle || - ori == 1 ? "middle" : side == 2 ? TOP : BOTTOM; + y = ori == 0 ? finalPos : 0; + x = ori == 1 ? finalPos : 0; + + let font = axis.font[0]; + let textAlign = + axis.align == 1 + ? LEFT + : axis.align == 2 + ? RIGHT + : angle > 0 + ? LEFT + : angle < 0 + ? RIGHT + : ori == 0 + ? 'center' + : side == 3 + ? RIGHT + : LEFT; + let textBaseline = + angle || ori == 1 ? 'middle' : side == 2 ? TOP : BOTTOM; setFontStyle(font, fillStyle, textAlign, textBaseline); let lineHeight = axis.font[1] * axis.lineGap; - let canOffs = _splits.map(val => pxRound(getPos(val, scale, plotDim, plotOff))); + let canOffs = _splits.map((val) => + pxRound(getPos(val, scale, plotDim, plotOff)) + ); let _values = axis._values; @@ -4562,14 +4778,13 @@ var uPlot = (function () { let val = _values[i]; if (val != null) { - if (ori == 0) - x = canOffs[i]; - else - y = canOffs[i]; + if (ori == 0) x = canOffs[i]; + else y = canOffs[i]; - val = "" + val; + val = '' + val; - let _parts = val.indexOf("\n") == -1 ? [val] : val.split(/\n/gm); + let _parts = + val.indexOf('\n') == -1 ? [val] : val.split(/\n/gm); for (let j = 0; j < _parts.length; j++) { let text = _parts[j]; @@ -4580,9 +4795,7 @@ var uPlot = (function () { ctx.rotate(angle); // can this be done once? ctx.fillText(text, 0, 0); ctx.restore(); - } - else - ctx.fillText(text, x, y + j * lineHeight); + } else ctx.fillText(text, x, y + j * lineHeight); } } } @@ -4599,7 +4812,7 @@ var uPlot = (function () { roundDec(ticks.width * pxRatio, 3), ticks.stroke(self, i), ticks.dash, - ticks.cap, + ticks.cap ); } @@ -4617,7 +4830,7 @@ var uPlot = (function () { roundDec(grid.width * pxRatio, 3), grid.stroke(self, i), grid.dash, - grid.cap, + grid.cap ); } @@ -4632,16 +4845,16 @@ var uPlot = (function () { roundDec(border.width * pxRatio, 3), border.stroke(self, i), border.dash, - border.cap, + border.cap ); } } - fire("drawAxes"); + fire('drawAxes'); } function resetYSeries(minMax) { - // log("resetYSeries()", arguments); + // log("resetYSeries()", arguments); series.forEach((s, i) => { if (i > 0) { @@ -4651,9 +4864,8 @@ var uPlot = (function () { if (mode == 1) { s.min = null; s.max = null; - } - else { - s.facets.forEach(f => { + } else { + s.facets.forEach((f) => { f.min = null; f.max = null; }); @@ -4670,8 +4882,7 @@ var uPlot = (function () { function flushHooks() { deferHooks = false; - for (let i = 0; i < hooksQueue.length; i++) - fire(...hooksQueue[i]); + for (let i = 0; i < hooksQueue.length; i++) fire(...hooksQueue[i]); hooksQueue.length = 0; } @@ -4691,14 +4902,13 @@ var uPlot = (function () { fn(self); _commit(); - if (_deferHooks && hooksQueue.length > 0) - queueMicrotask(flushHooks); + if (_deferHooks && hooksQueue.length > 0) queueMicrotask(flushHooks); } self.batch = batch; function _commit() { - // log("_commit()", arguments); + // log("_commit()", arguments); if (shouldSetScales) { setScales(); @@ -4711,44 +4921,59 @@ var uPlot = (function () { } if (shouldSetSize) { - setStylePx(under, LEFT, plotLftCss); - setStylePx(under, TOP, plotTopCss); - setStylePx(under, WIDTH, plotWidCss); + setStylePx(under, LEFT, plotLftCss); + setStylePx(under, TOP, plotTopCss); + setStylePx(under, WIDTH, plotWidCss); setStylePx(under, HEIGHT, plotHgtCss); - setStylePx(over, LEFT, plotLftCss); - setStylePx(over, TOP, plotTopCss); - setStylePx(over, WIDTH, plotWidCss); - setStylePx(over, HEIGHT, plotHgtCss); + setStylePx(over, LEFT, plotLftCss); + setStylePx(over, TOP, plotTopCss); + setStylePx(over, WIDTH, plotWidCss); + setStylePx(over, HEIGHT, plotHgtCss); - setStylePx(wrap, WIDTH, fullWidCss); - setStylePx(wrap, HEIGHT, fullHgtCss); + setStylePx(wrap, WIDTH, fullWidCss); + setStylePx(wrap, HEIGHT, fullHgtCss); // NOTE: mutating this during print preview in Chrome forces transparent // canvas pixels to white, even when followed up with clearRect() below - can.width = round(fullWidCss * pxRatio); + can.width = round(fullWidCss * pxRatio); can.height = round(fullHgtCss * pxRatio); axes.forEach(({ _el, _show, _size, _pos, side }) => { if (_el != null) { if (_show) { - let posOffset = (side === 3 || side === 0 ? _size : 0); + let posOffset = side === 3 || side === 0 ? _size : 0; let isVt = side % 2 == 1; - setStylePx(_el, isVt ? "left" : "top", _pos - posOffset); - setStylePx(_el, isVt ? "width" : "height", _size); - setStylePx(_el, isVt ? "top" : "left", isVt ? plotTopCss : plotLftCss); - setStylePx(_el, isVt ? "height" : "width", isVt ? plotHgtCss : plotWidCss); + setStylePx(_el, isVt ? 'left' : 'top', _pos - posOffset); + setStylePx(_el, isVt ? 'width' : 'height', _size); + setStylePx( + _el, + isVt ? 'top' : 'left', + isVt ? plotTopCss : plotLftCss + ); + setStylePx( + _el, + isVt ? 'height' : 'width', + isVt ? plotHgtCss : plotWidCss + ); remClass(_el, OFF); - } - else - addClass(_el, OFF); + } else addClass(_el, OFF); } }); // invalidate ctx style cache - ctxStroke = ctxFill = ctxWidth = ctxJoin = ctxCap = ctxFont = ctxAlign = ctxBaseline = ctxDash = null; + ctxStroke = + ctxFill = + ctxWidth = + ctxJoin = + ctxCap = + ctxFont = + ctxAlign = + ctxBaseline = + ctxDash = + null; ctxAlpha = 1; syncRect(true); @@ -4766,10 +4991,24 @@ var uPlot = (function () { if (cursor.show && !shouldSetCursor && cursor.left >= 0) { cursor.left *= pctWid; - cursor.top *= pctHgt; - - vCursor && elTrans(vCursor, round(cursor.left), 0, plotWidCss, plotHgtCss); - hCursor && elTrans(hCursor, 0, round(cursor.top), plotWidCss, plotHgtCss); + cursor.top *= pctHgt; + + vCursor && + elTrans( + vCursor, + round(cursor.left), + 0, + plotWidCss, + plotHgtCss + ); + hCursor && + elTrans( + hCursor, + 0, + round(cursor.top), + plotWidCss, + plotHgtCss + ); for (let i = 0; i < cursorPts.length; i++) { let pt = cursorPts[i]; @@ -4777,15 +5016,26 @@ var uPlot = (function () { if (pt != null) { cursorPtsLft[i] *= pctWid; cursorPtsTop[i] *= pctHgt; - elTrans(pt, ceil(cursorPtsLft[i]), ceil(cursorPtsTop[i]), plotWidCss, plotHgtCss); + elTrans( + pt, + ceil(cursorPtsLft[i]), + ceil(cursorPtsTop[i]), + plotWidCss, + plotHgtCss + ); } } } - if (select.show && !shouldSetSelect && select.left >= 0 && select.width > 0) { - select.left *= pctWid; - select.width *= pctWid; - select.top *= pctHgt; + if ( + select.show && + !shouldSetSelect && + select.left >= 0 && + select.width > 0 + ) { + select.left *= pctWid; + select.width *= pctWid; + select.top *= pctHgt; select.height *= pctHgt; for (let prop in _hideProps) @@ -4798,16 +5048,16 @@ var uPlot = (function () { _plotHgtCss = plotHgtCss; } - fire("setSize"); + fire('setSize'); shouldSetSize = false; } if (fullWidCss > 0 && fullHgtCss > 0) { ctx.clearRect(0, 0, can.width, can.height); - fire("drawClear"); - drawOrder.forEach(fn => fn()); - fire("draw"); + fire('drawClear'); + drawOrder.forEach((fn) => fn()); + fire('draw'); } if (select.show && shouldSetSelect) { @@ -4829,7 +5079,7 @@ var uPlot = (function () { ready = true; self.status = 1; - fire("ready"); + fire('ready'); } viaAutoScaleX = false; @@ -4840,10 +5090,8 @@ var uPlot = (function () { self.redraw = (rebuildPaths, recalcAxes) => { shouldConvergeSize = recalcAxes || false; - if (rebuildPaths !== false) - _setScale(xScaleKey, scaleX.min, scaleX.max); - else - commit(); + if (rebuildPaths !== false) _setScale(xScaleKey, scaleX.min, scaleX.max); + else commit(); }; // redraw() => setScale('x', scales.x.min, scales.x.max); @@ -4865,20 +5113,24 @@ var uPlot = (function () { opts.max = _min; } - if (dataLen > 1 && opts.min != null && opts.max != null && opts.max - opts.min < 1e-16) - return; + if ( + dataLen > 1 && + opts.min != null && + opts.max != null && + opts.max - opts.min < 1e-16 + ) + return if (key == xScaleKey) { if (sc.distr == 2 && dataLen > 0) { opts.min = closestIdx(opts.min, data[0]); opts.max = closestIdx(opts.max, data[0]); - if (opts.min == opts.max) - opts.max++; + if (opts.min == opts.max) opts.max++; } } - // log("setScale()", arguments); + // log("setScale()", arguments); pendScales[key] = opts; @@ -4889,7 +5141,7 @@ var uPlot = (function () { self.setScale = setScale; - // INTERACTION + // INTERACTION let xCursor; let yCursor; @@ -4920,16 +5172,13 @@ var uPlot = (function () { let dragY = drag.y; if (cursor.show) { - if (cursor.x) - xCursor = placeDiv(CURSOR_X, over); - if (cursor.y) - yCursor = placeDiv(CURSOR_Y, over); + if (cursor.x) xCursor = placeDiv(CURSOR_X, over); + if (cursor.y) yCursor = placeDiv(CURSOR_Y, over); if (scaleX.ori == 0) { vCursor = xCursor; hCursor = yCursor; - } - else { + } else { vCursor = yCursor; hCursor = xCursor; } @@ -4938,27 +5187,31 @@ var uPlot = (function () { mouseTop1 = cursor.top; } - const select = self.select = assign({ - show: true, - over: true, - left: 0, - width: 0, - top: 0, - height: 0, - }, opts.select); + const select = (self.select = assign( + { + show: true, + over: true, + left: 0, + width: 0, + top: 0, + height: 0 + }, + opts.select + )); - const selectDiv = select.show ? placeDiv(SELECT, select.over ? over : under) : null; + const selectDiv = select.show + ? placeDiv(SELECT, select.over ? over : under) + : null; function setSelect(opts, _fire) { if (select.show) { for (let prop in opts) { select[prop] = opts[prop]; - if (prop in _hideProps) - setStylePx(selectDiv, prop, opts[prop]); + if (prop in _hideProps) setStylePx(selectDiv, prop, opts[prop]); } - _fire !== false && fire("setSelect"); + _fire !== false && fire('setSelect'); } } @@ -4968,8 +5221,7 @@ var uPlot = (function () { let s = series[i]; let label = showLegend ? legendRows[i] : null; - if (s.show) - label && remClass(label, OFF); + if (s.show) label && remClass(label, OFF); else { label && addClass(label, OFF); let pt = cursorOnePt ? cursorPts[0] : cursorPts[i]; @@ -4978,14 +5230,13 @@ var uPlot = (function () { } function _setScale(key, min, max) { - setScale(key, {min, max}); + setScale(key, { min, max }); } function setSeries(i, opts, _fire, _pub) { - // log("setSeries()", arguments); + // log("setSeries()", arguments); - if (opts.focus != null) - setFocus(i); + if (opts.focus != null) setFocus(i); if (opts.show != null) { series.forEach((s, si) => { @@ -4996,18 +5247,16 @@ var uPlot = (function () { if (mode == 2) { _setScale(s.facets[0].scale, null, null); _setScale(s.facets[1].scale, null, null); - } - else - _setScale(s.scale, null, null); + } else _setScale(s.scale, null, null); commit(); } }); } - _fire !== false && fire("setSeries", i, opts); + _fire !== false && fire('setSeries', i, opts); - _pub && pubSync("setSeries", self, i, opts); + _pub && pubSync('setSeries', self, i, opts); } self.setSeries = setSeries; @@ -5024,10 +5273,8 @@ var uPlot = (function () { } function delBand(bi) { - if (bi == null) - bands.length = 0; - else - bands.splice(bi, 1); + if (bi == null) bands.length = 0; + else bands.splice(bi, 1); } self.addBand = addBand; @@ -5037,8 +5284,7 @@ var uPlot = (function () { function setAlpha(i, value) { series[i].alpha = value; - if (cursor.show && cursorPts[i]) - cursorPts[i].style.opacity = value; + if (cursor.show && cursorPts[i]) cursorPts[i].style.opacity = value; if (showLegend && legendRows[i]) legendRows[i].style.opacity = value; @@ -5048,11 +5294,11 @@ var uPlot = (function () { let closestDist; let closestSeries; let focusedSeries; - const FOCUS_TRUE = {focus: true}; + const FOCUS_TRUE = { focus: true }; function setFocus(i) { if (i != focusedSeries) { - // log("setFocus()", arguments); + // log("setFocus()", arguments); let allFocused = i == null; @@ -5072,9 +5318,8 @@ var uPlot = (function () { } if (showLegend && cursorFocus) { - onMouse(mouseleave, legendTable, e => { - if (cursor._lock) - return; + onMouse(mouseleave, legendTable, (e) => { + if (cursor._lock) return setCursorEvent(e); @@ -5086,8 +5331,7 @@ var uPlot = (function () { function posToVal(pos, scale, can) { let sc = scales[scale]; - if (can) - pos = pos / pxRatio - (sc.ori == 1 ? plotTopCss : plotLftCss); + if (can) pos = pos / pxRatio - (sc.ori == 1 ? plotTopCss : plotLftCss); let dim = plotWidCss; @@ -5096,8 +5340,7 @@ var uPlot = (function () { pos = dim - pos; } - if (sc.dir == -1) - pos = dim - pos; + if (sc.dir == -1) pos = dim - pos; let _min = sc._min, _max = sc._max, @@ -5107,49 +5350,53 @@ var uPlot = (function () { let distr = sc.distr; - return ( - distr == 3 ? pow(10, sv) : - distr == 4 ? sinh(sv, sc.asinh) : - distr == 100 ? sc.bwd(sv) : - sv - ); + return distr == 3 + ? pow(10, sv) + : distr == 4 + ? sinh(sv, sc.asinh) + : distr == 100 + ? sc.bwd(sv) + : sv } function closestIdxFromXpos(pos, can) { let v = posToVal(pos, xScaleKey, can); - return closestIdx(v, data[0], i0, i1); + return closestIdx(v, data[0], i0, i1) } - self.valToIdx = val => closestIdx(val, data[0]); + self.valToIdx = (val) => closestIdx(val, data[0]); self.posToIdx = closestIdxFromXpos; self.posToVal = posToVal; - self.valToPos = (val, scale, can) => ( - scales[scale].ori == 0 ? - getHPos(val, scales[scale], - can ? plotWid : plotWidCss, - can ? plotLft : 0, - ) : - getVPos(val, scales[scale], - can ? plotHgt : plotHgtCss, - can ? plotTop : 0, - ) - ); + self.valToPos = (val, scale, can) => + scales[scale].ori == 0 + ? getHPos( + val, + scales[scale], + can ? plotWid : plotWidCss, + can ? plotLft : 0 + ) + : getVPos( + val, + scales[scale], + can ? plotHgt : plotHgtCss, + can ? plotTop : 0 + ); self.setCursor = (opts, _fire, _pub) => { mouseLeft1 = opts.left; mouseTop1 = opts.top; - // assign(cursor, opts); + // assign(cursor, opts); updateCursor(null, _fire, _pub); }; function setSelH(off, dim) { - setStylePx(selectDiv, LEFT, select.left = off); - setStylePx(selectDiv, WIDTH, select.width = dim); + setStylePx(selectDiv, LEFT, (select.left = off)); + setStylePx(selectDiv, WIDTH, (select.width = dim)); } function setSelV(off, dim) { - setStylePx(selectDiv, TOP, select.top = off); - setStylePx(selectDiv, HEIGHT, select.height = dim); + setStylePx(selectDiv, TOP, (select.top = off)); + setStylePx(selectDiv, HEIGHT, (select.height = dim)); } let setSelX = scaleX.ori == 0 ? setSelH : setSelV; @@ -5158,8 +5405,7 @@ var uPlot = (function () { function syncLegend() { if (showLegend && legend.live) { for (let i = mode == 2 ? 1 : 0; i < series.length; i++) { - if (i == 0 && multiValLegend) - continue; + if (i == 0 && multiValLegend) continue let vals = legend.values[i]; @@ -5177,16 +5423,14 @@ var uPlot = (function () { opts.idxs.forEach((didx, sidx) => { activeIdxs[sidx] = didx; }); - } - else if (!isUndef(opts.idx)) - activeIdxs.fill(opts.idx); + } else if (!isUndef(opts.idx)) activeIdxs.fill(opts.idx); legend.idx = activeIdxs[0]; } if (showLegend && legend.live) { for (let sidx = 0; sidx < series.length; sidx++) { - if (sidx > 0 || mode == 1 && !multiValLegend) + if (sidx > 0 || (mode == 1 && !multiValLegend)) setLegendValues(sidx, activeIdxs[sidx]); } @@ -5195,7 +5439,7 @@ var uPlot = (function () { shouldSetLegend = false; - _fire !== false && fire("setLegend"); + _fire !== false && fire('setLegend'); } self.setLegend = setLegend; @@ -5208,27 +5452,35 @@ var uPlot = (function () { if (multiValLegend) val = s.values(self, sidx, idx) ?? NULL_LEGEND_VALUES; else { - val = s.value(self, idx == null ? null : src[idx], sidx, idx); - val = val == null ? NULL_LEGEND_VALUES : {_: val}; + val = s.value( + self, + idx == null ? null : src[idx], + sidx, + idx, + fmtNum + ); + val = val == null ? NULL_LEGEND_VALUES : { _: val }; } legend.values[sidx] = val; } function updateCursor(src, _fire, _pub) { - // ts == null && log("updateCursor()", arguments); + // ts == null && log("updateCursor()", arguments); rawMouseLeft1 = mouseLeft1; - rawMouseTop1 = mouseTop1; + rawMouseTop1 = mouseTop1 - [mouseLeft1, mouseTop1] = cursor.move(self, mouseLeft1, mouseTop1); + ;[mouseLeft1, mouseTop1] = cursor.move(self, mouseLeft1, mouseTop1); cursor.left = mouseLeft1; cursor.top = mouseTop1; if (cursor.show) { - vCursor && elTrans(vCursor, round(mouseLeft1), 0, plotWidCss, plotHgtCss); - hCursor && elTrans(hCursor, 0, round(mouseTop1), plotWidCss, plotHgtCss); + vCursor && + elTrans(vCursor, round(mouseLeft1), 0, plotWidCss, plotHgtCss); + hCursor && + elTrans(hCursor, 0, round(mouseTop1), plotWidCss, plotHgtCss); } let idx; @@ -5254,15 +5506,19 @@ var uPlot = (function () { } if (cursorFocus) - setSeries(null, FOCUS_TRUE, true, src == null && syncOpts.setSeries); + setSeries( + null, + FOCUS_TRUE, + true, + src == null && syncOpts.setSeries + ); if (legend.live) { activeIdxs.fill(idx); shouldSetLegend = true; } - } - else { - // let pctY = 1 - (y / rect.height); + } else { + // let pctY = 1 - (y / rect.height); let mouseXPos, valAtPosX, xPos; @@ -5285,25 +5541,56 @@ var uPlot = (function () { for (let i = mode == 2 ? 1 : 0; i < series.length; i++) { let s = series[i]; - let idx1 = activeIdxs[i]; - let yVal1 = idx1 == null ? null : (mode == 1 ? data[i][idx1] : data[i][1][idx1]); - - let idx2 = cursor.dataIdx(self, i, idx, valAtPosX); - let yVal2 = idx2 == null ? null : (mode == 1 ? data[i][idx2] : data[i][1][idx2]); - - shouldSetLegend = shouldSetLegend || yVal2 != yVal1 || idx2 != idx1; + let idx1 = activeIdxs[i]; + let yVal1 = + idx1 == null + ? null + : mode == 1 + ? data[i][idx1] + : data[i][1][idx1]; + + let idx2 = cursor.dataIdx(self, i, idx, valAtPosX); + let yVal2 = + idx2 == null + ? null + : mode == 1 + ? data[i][idx2] + : data[i][1][idx2]; + + shouldSetLegend = + shouldSetLegend || yVal2 != yVal1 || idx2 != idx1; activeIdxs[i] = idx2; - let xPos2 = idx2 == idx ? xPos : valToPosX(mode == 1 ? data[0][idx2] : data[i][0][idx2], scaleX, xDim, 0); + let xPos2 = + idx2 == idx + ? xPos + : valToPosX( + mode == 1 ? data[0][idx2] : data[i][0][idx2], + scaleX, + xDim, + 0 + ); if (i > 0 && s.show) { // this doesnt really work for state timeline, heatmap, status history (where the value maps to color, not y coords) - let yPos = yVal2 == null ? -10 : valToPosY(yVal2, mode == 1 ? scales[s.scale] : scales[s.facets[1].scale], yDim, 0); + let yPos = + yVal2 == null + ? -10 + : valToPosY( + yVal2, + mode == 1 + ? scales[s.scale] + : scales[s.facets[1].scale], + yDim, + 0 + ); if (cursorFocus && yVal2 != null) { let mouseYPos = scaleX.ori == 1 ? mouseLeft1 : mouseTop1; - let dist = abs(focus.dist(self, i, idx2, yPos, mouseYPos)); + let dist = abs( + focus.dist(self, i, idx2, yPos, mouseYPos) + ); if (dist < closestDist) { let bias = focus.bias; @@ -5311,21 +5598,25 @@ var uPlot = (function () { if (bias != 0) { let mouseYVal = posToVal(mouseYPos, s.scale); - let seriesYValSign = yVal2 >= 0 ? 1 : -1; - let mouseYValSign = mouseYVal >= 0 ? 1 : -1; + let seriesYValSign = yVal2 >= 0 ? 1 : -1; + let mouseYValSign = mouseYVal >= 0 ? 1 : -1; // with a focus bias, we will never cross zero when prox testing // it's either closest towards zero, or closest away from zero - if (mouseYValSign == seriesYValSign && ( - mouseYValSign == 1 ? - (bias == 1 ? yVal2 >= mouseYVal : yVal2 <= mouseYVal) : // >= 0 - (bias == 1 ? yVal2 <= mouseYVal : yVal2 >= mouseYVal) // < 0 - )) { + if ( + mouseYValSign == seriesYValSign && + (mouseYValSign == 1 + ? bias == 1 + ? yVal2 >= mouseYVal + : yVal2 <= mouseYVal // >= 0 + : bias == 1 + ? yVal2 <= mouseYVal + : yVal2 >= mouseYVal) // < 0 + ) { closestDist = dist; closestSeries = i; } - } - else { + } else { closestDist = dist; closestSeries = i; } @@ -5338,14 +5629,17 @@ var uPlot = (function () { if (scaleX.ori == 0) { hPos = xPos2; vPos = yPos; - } - else { + } else { hPos = yPos; vPos = xPos2; } - let ptWid, ptHgt, ptLft, ptTop, - ptStroke, ptFill, + let ptWid, + ptHgt, + ptLft, + ptTop, + ptStroke, + ptFill, centered = true, getBBox = points.bbox; @@ -5358,8 +5652,7 @@ var uPlot = (function () { ptTop = bbox.top; ptWid = bbox.width; ptHgt = bbox.height; - } - else { + } else { ptLft = hPos; ptTop = vPos; ptWid = ptHgt = points.size(self, i); @@ -5369,7 +5662,10 @@ var uPlot = (function () { ptStroke = points.stroke(self, i); if (cursorOnePt) { - if (i == closestSeries && closestDist <= focus.prox) { + if ( + i == closestSeries && + closestDist <= focus.prox + ) { _ptLft = ptLft; _ptTop = ptTop; _ptWid = ptWid; @@ -5378,8 +5674,7 @@ var uPlot = (function () { _ptFill = ptFill; _ptStroke = ptStroke; } - } - else { + } else { let pt = cursorPts[i]; if (pt != null) { @@ -5388,7 +5683,13 @@ var uPlot = (function () { elSize(pt, ptWid, ptHgt, centered); elColor(pt, ptFill, ptStroke); - elTrans(pt, ceil(ptLft), ceil(ptTop), plotWidCss, plotHgtCss); + elTrans( + pt, + ceil(ptLft), + ceil(ptTop), + plotWidCss, + plotHgtCss + ); } } } @@ -5402,7 +5703,10 @@ var uPlot = (function () { let p = focus.prox; - let focusChanged = focusedSeries == null ? closestDist <= p : (closestDist > p || closestSeries != focusedSeries); + let focusChanged = + focusedSeries == null + ? closestDist <= p + : closestDist > p || closestSeries != focusedSeries; if (shouldSetLegend || focusChanged) { let pt = cursorPts[0]; @@ -5412,7 +5716,13 @@ var uPlot = (function () { elSize(pt, _ptWid, _ptHgt, _centered); elColor(pt, _ptFill, _ptStroke); - elTrans(pt, ceil(_ptLft), ceil(_ptTop), plotWidCss, plotHgtCss); + elTrans( + pt, + ceil(_ptLft), + ceil(_ptTop), + plotWidCss, + plotHgtCss + ); } } } @@ -5444,46 +5754,47 @@ var uPlot = (function () { if (sori == 0) { sOff = left; sDim = width; - } - else { + } else { sOff = top; sDim = height; } sc = scales[xKey]; - a = valToPosX(sPosToVal(sOff, xKeySrc), sc, xDim, 0); - b = valToPosX(sPosToVal(sOff + sDim, xKeySrc), sc, xDim, 0); + a = valToPosX(sPosToVal(sOff, xKeySrc), sc, xDim, 0); + b = valToPosX( + sPosToVal(sOff + sDim, xKeySrc), + sc, + xDim, + 0 + ); - setSelX(min(a,b), abs(b-a)); - } - else - setSelX(0, xDim); + setSelX(min(a, b), abs(b - a)); + } else setSelX(0, xDim); if (matchingY && dragY) { if (sori == 1) { sOff = left; sDim = width; - } - else { + } else { sOff = top; sDim = height; } sc = scales[yKey]; - a = valToPosY(sPosToVal(sOff, yKeySrc), sc, yDim, 0); - b = valToPosY(sPosToVal(sOff + sDim, yKeySrc), sc, yDim, 0); + a = valToPosY(sPosToVal(sOff, yKeySrc), sc, yDim, 0); + b = valToPosY( + sPosToVal(sOff + sDim, yKeySrc), + sc, + yDim, + 0 + ); - setSelY(min(a,b), abs(b-a)); - } - else - setSelY(0, yDim); - } - else - hideSelect(); - } - else { + setSelY(min(a, b), abs(b - a)); + } else setSelY(0, yDim); + } else hideSelect(); + } else { let rawDX = abs(rawMouseLeft1 - rawMouseLeft0); let rawDY = abs(rawMouseTop1 - rawMouseTop0); @@ -5506,14 +5817,11 @@ var uPlot = (function () { // force unidirectionality when both are under uni limit if (!dragX && !dragY) { - if (rawDY > rawDX) - dragY = true; - else - dragX = true; + if (rawDY > rawDX) dragY = true; + else dragX = true; } } - } - else if (drag.x && drag.y && (dragX || dragY)) + } else if (drag.x && drag.y && (dragX || dragY)) // if omni with no uni then both dragX / dragY should be true if either is true dragX = dragY = true; @@ -5523,32 +5831,28 @@ var uPlot = (function () { if (scaleX.ori == 0) { p0 = mouseLeft0; p1 = mouseLeft1; - } - else { + } else { p0 = mouseTop0; p1 = mouseTop1; } setSelX(min(p0, p1), abs(p1 - p0)); - if (!dragY) - setSelY(0, yDim); + if (!dragY) setSelY(0, yDim); } if (dragY) { if (scaleX.ori == 1) { p0 = mouseLeft0; p1 = mouseLeft1; - } - else { + } else { p0 = mouseTop0; p1 = mouseTop1; } setSelY(min(p0, p1), abs(p1 - p0)); - if (!dragX) - setSelX(0, xDim); + if (!dragX) setSelX(0, xDim); } // the drag didn't pass the dist requirement @@ -5567,11 +5871,31 @@ var uPlot = (function () { if (syncKey != null) { let [xSyncKey, ySyncKey] = syncOpts.scales; - syncOpts.values[0] = xSyncKey != null ? posToVal(scaleX.ori == 0 ? mouseLeft1 : mouseTop1, xSyncKey) : null; - syncOpts.values[1] = ySyncKey != null ? posToVal(scaleX.ori == 1 ? mouseLeft1 : mouseTop1, ySyncKey) : null; + syncOpts.values[0] = + xSyncKey != null + ? posToVal( + scaleX.ori == 0 ? mouseLeft1 : mouseTop1, + xSyncKey + ) + : null; + syncOpts.values[1] = + ySyncKey != null + ? posToVal( + scaleX.ori == 1 ? mouseLeft1 : mouseTop1, + ySyncKey + ) + : null; } - pubSync(mousemove, self, mouseLeft1, mouseTop1, plotWidCss, plotHgtCss, idx); + pubSync( + mousemove, + self, + mouseLeft1, + mouseTop1, + plotWidCss, + plotHgtCss, + idx + ); } if (cursorFocus) { @@ -5581,8 +5905,7 @@ var uPlot = (function () { if (focusedSeries == null) { if (closestDist <= p) setSeries(closestSeries, FOCUS_TRUE, true, shouldPub); - } - else { + } else { if (closestDist > p) setSeries(null, FOCUS_TRUE, true, shouldPub); else if (closestSeries != focusedSeries) @@ -5596,32 +5919,29 @@ var uPlot = (function () { setLegend(); } - _fire !== false && fire("setCursor"); + _fire !== false && fire('setCursor'); } let rect = null; Object.defineProperty(self, 'rect', { get() { - if (rect == null) - syncRect(false); + if (rect == null) syncRect(false); - return rect; - }, + return rect + } }); function syncRect(defer = false) { - if (defer) - rect = null; + if (defer) rect = null; else { rect = over.getBoundingClientRect(); - fire("syncRect", rect); + fire('syncRect', rect); } } function mouseMove(e, src, _l, _t, _w, _h, _i) { - if (cursor._lock) - return; + if (cursor._lock) return // Chrome on Windows has a bug which triggers a stray mousemove event after an initial mousedown event // when clicking into a plot as part of re-focusing the browser window. @@ -5629,31 +5949,27 @@ var uPlot = (function () { // However, on touch-only devices Chrome-based browsers trigger a 0-distance mousemove before mousedown // so we don't ignore it when mousedown has set the dragging flag if (dragging && e != null && e.movementX == 0 && e.movementY == 0) - return; + return cacheMouse(e, src, _l, _t, _w, _h, _i, false, e != null); - if (e != null) - updateCursor(null, true, true); - else - updateCursor(src, true, false); + if (e != null) updateCursor(null, true, true); + else updateCursor(src, true, false); } function cacheMouse(e, src, _l, _t, _w, _h, _i, initial, snap) { - if (rect == null) - syncRect(false); + if (rect == null) syncRect(false); setCursorEvent(e); if (e != null) { _l = e.clientX - rect.left; _t = e.clientY - rect.top; - } - else { + } else { if (_l < 0 || _t < 0) { mouseLeft1 = -10; mouseTop1 = -10; - return; + return } let [xKey, yKey] = syncOpts.scales; @@ -5673,14 +5989,16 @@ var uPlot = (function () { _yPos = rotSrc ? _l : _t; if (xKeySrc != null) - _l = matchXKeys(xKey, xKeySrc) ? getPos(xValSrc, scales[xKey], xDim, 0) : -10; - else - _l = xDim * (_xPos/_xDim); + _l = matchXKeys(xKey, xKeySrc) + ? getPos(xValSrc, scales[xKey], xDim, 0) + : -10; + else _l = xDim * (_xPos / _xDim); if (yKeySrc != null) - _t = matchYKeys(yKey, yKeySrc) ? getPos(yValSrc, scales[yKey], yDim, 0) : -10; - else - _t = yDim * (_yPos/_yDim); + _t = matchYKeys(yKey, yKeySrc) + ? getPos(yValSrc, scales[yKey], yDim, 0) + : -10; + else _t = yDim * (_yPos / _yDim); if (scaleX.ori == 1) { let __l = _l; @@ -5690,20 +6008,17 @@ var uPlot = (function () { } if (snap) { - if (_l <= 1 || _l >= plotWidCss - 1) - _l = incrRound(_l, plotWidCss); + if (_l <= 1 || _l >= plotWidCss - 1) _l = incrRound(_l, plotWidCss); - if (_t <= 1 || _t >= plotHgtCss - 1) - _t = incrRound(_t, plotHgtCss); + if (_t <= 1 || _t >= plotHgtCss - 1) _t = incrRound(_t, plotHgtCss); } if (initial) { rawMouseLeft0 = _l; - rawMouseTop0 = _t; + rawMouseTop0 = _t - [mouseLeft0, mouseTop0] = cursor.move(self, _l, _t); - } - else { + ;[mouseLeft0, mouseTop0] = cursor.move(self, _l, _t); + } else { mouseLeft1 = _l; mouseTop1 = _t; } @@ -5713,7 +6028,7 @@ var uPlot = (function () { width: 0, height: 0, left: 0, - top: 0, + top: 0 }; function hideSelect() { @@ -5733,14 +6048,22 @@ var uPlot = (function () { if (e != null) { onMouse(mouseup, doc, mouseUp, false); - pubSync(mousedown, self, mouseLeft0, mouseTop0, plotWidCss, plotHgtCss, null); + pubSync( + mousedown, + self, + mouseLeft0, + mouseTop0, + plotWidCss, + plotHgtCss, + null + ); } let { left, top, width, height } = select; - downSelectLeft = left; - downSelectTop = top; - downSelectWidth = width; + downSelectLeft = left; + downSelectTop = top; + downSelectWidth = width; downSelectHeight = height; hideSelect(); @@ -5754,20 +6077,19 @@ var uPlot = (function () { let { left, top, width, height } = select; let hasSelect = width > 0 || height > 0; - let chgSelect = ( - downSelectLeft != left || - downSelectTop != top || - downSelectWidth != width || - downSelectHeight != height - ); + let chgSelect = + downSelectLeft != left || + downSelectTop != top || + downSelectWidth != width || + downSelectHeight != height; hasSelect && chgSelect && setSelect(select); if (drag.setScale && hasSelect && chgSelect) { - // if (syncKey != null) { - // dragX = drag.x; - // dragY = drag.y; - // } + // if (syncKey != null) { + // dragX = drag.x; + // dragY = drag.y; + // } let xOff = left, xDim = width, @@ -5775,14 +6097,12 @@ var uPlot = (function () { yDim = height; if (scaleX.ori == 1) { - xOff = top, - xDim = height, - yOff = left, - yDim = width; + (xOff = top), (xDim = height), (yOff = left), (yDim = width); } if (dragX) { - _setScale(xScaleKey, + _setScale( + xScaleKey, posToVal(xOff, xScaleKey), posToVal(xOff + xDim, xScaleKey) ); @@ -5793,7 +6113,8 @@ var uPlot = (function () { let sc = scales[k]; if (k != xScaleKey && sc.from == null && sc.min != inf) { - _setScale(k, + _setScale( + k, posToVal(yOff + yDim, k), posToVal(yOff, k) ); @@ -5802,21 +6123,27 @@ var uPlot = (function () { } hideSelect(); - } - else if (cursor.lock) { + } else if (cursor.lock) { cursor._lock = !cursor._lock; updateCursor(null, true, false); } if (e != null) { offMouse(mouseup, doc); - pubSync(mouseup, self, mouseLeft1, mouseTop1, plotWidCss, plotHgtCss, null); + pubSync( + mouseup, + self, + mouseLeft1, + mouseTop1, + plotWidCss, + plotHgtCss, + null + ); } } function mouseLeave(e, src, _l, _t, _w, _h, _i) { - if (cursor._lock) - return; + if (cursor._lock) return setCursorEvent(e); @@ -5833,16 +6160,18 @@ var uPlot = (function () { if (scaleX.ori == 0) { dragH = dragX; dragV = dragY; - } - else { + } else { dragH = dragY; dragV = dragX; } if (dragH && dragV) { // maybe omni corner snap - snapH = mouseLeft1 <= snapProx || mouseLeft1 >= plotWidCss - snapProx; - snapV = mouseTop1 <= snapProx || mouseTop1 >= plotHgtCss - snapProx; + snapH = + mouseLeft1 <= snapProx || + mouseLeft1 >= plotWidCss - snapProx; + snapV = + mouseTop1 <= snapProx || mouseTop1 >= plotHgtCss - snapProx; } if (dragH && snapH) @@ -5862,13 +6191,11 @@ var uPlot = (function () { // passing a non-null timestamp to force sync/mousemove event updateCursor(null, true, true); - if (_dragging) - dragging = _dragging; + if (_dragging) dragging = _dragging; } function dblClick(e, src, _l, _t, _w, _h, _i) { - if (cursor._lock) - return; + if (cursor._lock) return setCursorEvent(e); @@ -5877,7 +6204,15 @@ var uPlot = (function () { hideSelect(); if (e != null) - pubSync(dblclick, self, mouseLeft1, mouseTop1, plotWidCss, plotHgtCss, null); + pubSync( + dblclick, + self, + mouseLeft1, + mouseTop1, + plotWidCss, + plotHgtCss, + null + ); } function syncPxRatio() { @@ -5894,16 +6229,16 @@ var uPlot = (function () { events.mousemove = mouseMove; events.mouseup = mouseUp; events.dblclick = dblClick; - events["setSeries"] = (e, src, idx, opts) => { + events['setSeries'] = (e, src, idx, opts) => { let seriesIdxMatcher = syncOpts.match[2]; idx = seriesIdxMatcher(self, src, idx); idx != -1 && setSeries(idx, opts, true, false); }; if (cursor.show) { - onMouse(mousedown, over, mouseDown); - onMouse(mousemove, over, mouseMove); - onMouse(mouseenter, over, e => { + onMouse(mousedown, over, mouseDown); + onMouse(mousemove, over, mouseMove); + onMouse(mouseenter, over, (e) => { setCursorEvent(e); syncRect(false); }); @@ -5917,41 +6252,41 @@ var uPlot = (function () { } // external on/off - const hooks = self.hooks = opts.hooks || {}; + const hooks = (self.hooks = opts.hooks || {}); function fire(evName, a1, a2) { - if (deferHooks) - hooksQueue.push([evName, a1, a2]); + if (deferHooks) hooksQueue.push([evName, a1, a2]); else { if (evName in hooks) { - hooks[evName].forEach(fn => { + hooks[evName].forEach((fn) => { fn.call(null, self, a1, a2); }); } } } - - (opts.plugins || []).forEach(p => { + (opts.plugins || []).forEach((p) => { for (let evName in p.hooks) hooks[evName] = (hooks[evName] || []).concat(p.hooks[evName]); }); const seriesIdxMatcher = (self, src, srcSeriesIdx) => srcSeriesIdx; - const syncOpts = assign({ - key: null, - setSeries: false, - filters: { - pub: retTrue, - sub: retTrue, + const syncOpts = assign( + { + key: null, + setSeries: false, + filters: { + pub: retTrue, + sub: retTrue + }, + scales: [xScaleKey, series[1] ? series[1].scale : null], + match: [retEq, retEq, seriesIdxMatcher], + values: [null, null] }, - scales: [xScaleKey, series[1] ? series[1].scale : null], - match: [retEq, retEq, seriesIdxMatcher], - values: [null, null], - }, cursor.sync); + cursor.sync + ); - if (syncOpts.match.length == 2) - syncOpts.match.push(seriesIdxMatcher); + if (syncOpts.match.length == 2) syncOpts.match.push(seriesIdxMatcher); cursor.sync = syncOpts; @@ -5980,20 +6315,18 @@ var uPlot = (function () { off(dppxchange, win, syncPxRatio); root.remove(); legendTable?.remove(); // in case mounted outside of root - fire("destroy"); + fire('destroy'); } self.destroy = destroy; function _init() { - fire("init", opts, data); + fire('init', opts, data); setData(data || opts.data, false); - if (pendScales[xScaleKey]) - setScale(xScaleKey, pendScales[xScaleKey]); - else - autoScaleX(); + if (pendScales[xScaleKey]) setScale(xScaleKey, pendScales[xScaleKey]); + else autoScaleX(); shouldSetSelect = select.show && (select.width > 0 || select.height > 0); shouldSetCursor = shouldSetLegend = true; @@ -6009,22 +6342,17 @@ var uPlot = (function () { if (then instanceof HTMLElement) { then.appendChild(root); _init(); - } - else - then(self, _init); - } - else - _init(); + } else then(self, _init); + } else _init(); - return self; + return self } uPlot.assign = assign; - uPlot.fmtNum = fmtNum; uPlot.rangeNum = rangeNum; uPlot.rangeLog = rangeLog; uPlot.rangeAsinh = rangeAsinh; - uPlot.orient = orient; + uPlot.orient = orient; uPlot.pxRatio = pxRatio; { @@ -6032,8 +6360,7 @@ var uPlot = (function () { } { - uPlot.fmtDate = fmtDate; - uPlot.tzDate = tzDate; + uPlot.tzDate = tzDate; } uPlot.sync = _sync; @@ -6042,14 +6369,14 @@ var uPlot = (function () { uPlot.addGap = addGap; uPlot.clipGaps = clipGaps; - let paths = uPlot.paths = { - points, - }; + let paths = (uPlot.paths = { + points + }); - (paths.linear = linear); + (paths.linear = linear); (paths.stepped = stepped); - (paths.bars = bars); - (paths.spline = monotoneCubic); + (paths.bars = bars); + (paths.spline = monotoneCubic); } return uPlot; diff --git a/dist/uPlot.iife.min.js b/dist/uPlot.iife.min.js index be69d139..2dd6061d 100644 --- a/dist/uPlot.iife.min.js +++ b/dist/uPlot.iife.min.js @@ -1,2 +1,2 @@ /*! https://github.com/leeoniya/uPlot (v1.6.31) */ -var uPlot=function(){"use strict";const e="u-off",l="u-label",t="width",n="height",i="top",o="bottom",s="left",r="right",u="#000",a=u+"0",f="mousemove",c="mousedown",h="mouseup",d="mouseenter",p="mouseleave",m="dblclick",g="change",x="dppxchange",w="--",_="undefined"!=typeof window,b=_?document:null,v=_?window:null,k=_?navigator:null;let y,M;function S(e,l){if(null!=l){let t=e.classList;!t.contains(l)&&t.add(l)}}function E(e,l){let t=e.classList;t.contains(l)&&t.remove(l)}function T(e,l,t){e.style[l]=t+"px"}function z(e,l,t,n){let i=b.createElement(e);return null!=l&&S(i,l),null!=t&&t.insertBefore(i,n),i}function D(e,l){return z("div",e,l)}const P=new WeakMap;function A(l,t,n,i,o){let s="translate("+t+"px,"+n+"px)";s!=P.get(l)&&(l.style.transform=s,P.set(l,s),0>t||0>n||t>i||n>o?S(l,e):E(l,e))}const W=new WeakMap;function Y(e,l,t){let n=l+t;n!=W.get(e)&&(W.set(e,n),e.style.background=l,e.style.borderColor=t)}const C=new WeakMap;function F(e,l,t,n){let i=l+""+t;i!=C.get(e)&&(C.set(e,i),e.style.height=t+"px",e.style.width=l+"px",e.style.marginLeft=n?-l/2+"px":0,e.style.marginTop=n?-t/2+"px":0)}const H={passive:!0},R={...H,capture:!0};function G(e,l,t,n){l.addEventListener(e,t,n?R:H)}function I(e,l,t){l.removeEventListener(e,t,H)}function O(e,l,t,n){let i;t=t||0;let o=2147483647>=(n=n||l.length-1);for(;n-t>1;)i=o?t+n>>1:te((t+n)/2),e>l[i]?t=i:n=i;return e-l[t]>l[n]-e?n:t}function L(e,l,t,n){for(let i=1==n?l:t;i>=l&&t>=i;i+=n)if(null!=e[i])return i;return-1}function N(e,l,t,n){let i=ue(e),o=ue(l);e==l&&(-1==i?(e*=t,l/=t):(e/=t,l*=t));let s=10==t?ae:fe,r=1==o?ie:te,u=(1==i?te:ie)(s(le(e))),a=r(s(le(l))),f=re(t,u),c=re(t,a);return 10==t&&(0>u&&(f=Ee(f,-u)),0>a&&(c=Ee(c,-a))),n||2==t?(e=f*i,l=c*o):(e=Se(e,f),l=Me(l,c)),[e,l]}function j(e,l,t,n){let i=N(e,l,t,n);return 0==e&&(i[0]=0),0==l&&(i[1]=0),i}_&&function e(){let l=devicePixelRatio;y!=l&&(y=l,M&&I(g,M,e),M=matchMedia(`(min-resolution: ${y-.001}dppx) and (max-resolution: ${y+.001}dppx)`),G(g,M,e),v.dispatchEvent(new CustomEvent(x)))}();const U=.1,B={mode:3,pad:U},V={pad:0,soft:null,mode:0},$={min:V,max:V};function J(e,l,t,n){return He(t)?K(e,l,t):(V.pad=t,V.soft=n?0:null,V.mode=n?3:0,K(e,l,$))}function q(e,l){return null==e?l:e}function K(e,l,t){let n=t.min,i=t.max,o=q(n.pad,0),s=q(i.pad,0),r=q(n.hard,-he),u=q(i.hard,he),a=q(n.soft,he),f=q(i.soft,-he),c=q(n.mode,0),h=q(i.mode,0),d=l-e,p=ae(d),m=se(le(e),le(l)),g=ae(m),x=le(g-p);(1e-24>d||x>10)&&(d=0,0!=e&&0!=l||(d=1e-24,2==c&&a!=he&&(o=0),2==h&&f!=-he&&(s=0)));let w=d||m||1e3,_=ae(w),b=re(10,te(_)),v=Ee(Se(e-w*(0==d?0==e?.1:1:o),b/10),24),k=a>e||1!=c&&(3!=c||v>a)&&(2!=c||a>v)?he:a,y=se(r,k>v&&e>=k?k:oe(k,v)),M=Ee(Me(l+w*(0==d?0==l?.1:1:s),b/10),24),S=l>f||1!=h&&(3!=h||f>M)&&(2!=h||M>f)?-he:f,E=oe(u,M>S&&S>=l?S:se(S,M));return y==E&&0==y&&(E=100),[y,E]}const X=new Intl.NumberFormat(_?k.language:"en-US"),Z=e=>X.format(e),Q=Math,ee=Q.PI,le=Q.abs,te=Q.floor,ne=Q.round,ie=Q.ceil,oe=Q.min,se=Q.max,re=Q.pow,ue=Q.sign,ae=Q.log10,fe=Q.log2,ce=(e,l=1)=>Q.asinh(e/l),he=1/0;function de(e){return 1+(0|ae((e^e>>31)-(e>>31)))}function pe(e,l,t){return oe(se(e,l),t)}function me(e){return"function"==typeof e?e:()=>e}const ge=e=>e,xe=(e,l)=>l,we=()=>null,_e=()=>!0,be=(e,l)=>e==l,ve=/\.\d*?(?=9{6,}|0{6,})/gm,ke=e=>{if(Ce(e)||Te.has(e))return e;const l=""+e,t=l.match(ve);if(null==t)return e;let n=t[0].length-1;if(-1!=l.indexOf("e-")){let[e,t]=l.split("e");return+`${ke(e)}e${t}`}return Ee(e,n)};function ye(e,l){return ke(Ee(ke(e/l))*l)}function Me(e,l){return ke(ie(ke(e/l))*l)}function Se(e,l){return ke(te(ke(e/l))*l)}function Ee(e,l=0){if(Ce(e))return e;let t=10**l;return ne(e*t*(1+Number.EPSILON))/t}const Te=new Map;function ze(e){return((""+e).split(".")[1]||"").length}function De(e,l,t,n){let i=[],o=n.map(ze);for(let s=l;t>s;s++){let l=le(s),t=Ee(re(e,s),l);for(let r=0;n.length>r;r++){let u=10==e?+`${n[r]}e${s}`:n[r]*t,a=(0>s?l:0)+(o[r]>s?o[r]:0),f=10==e?u:Ee(u,a);i.push(f),Te.set(f,a)}}return i}const Pe={},Ae=[],We=[null,null],Ye=Array.isArray,Ce=Number.isInteger;function Fe(e){return"string"==typeof e}function He(e){let l=!1;if(null!=e){let t=e.constructor;l=null==t||t==Object}return l}function Re(e){return null!=e&&"object"==typeof e}const Ge=Object.getPrototypeOf(Uint8Array),Ie="__proto__";function Oe(e,l=He){let t;if(Ye(e)){let n=e.find((e=>null!=e));if(Ye(n)||l(n)){t=Array(e.length);for(let n=0;e.length>n;n++)t[n]=Oe(e[n],l)}else t=e.slice()}else if(e instanceof Ge)t=e.slice();else if(l(e)){t={};for(let n in e)n!=Ie&&(t[n]=Oe(e[n],l))}else t=e;return t}function Le(e){let l=arguments;for(let t=1;l.length>t;t++){let n=l[t];for(let l in n)l!=Ie&&(He(e[l])?Le(e[l],Oe(n[l])):e[l]=Oe(n[l]))}return e}function Ne(e,l,t){for(let n,i=0,o=-1;l.length>i;i++){let s=l[i];if(s>o){for(n=s-1;n>=0&&null==e[n];)e[n--]=null;for(n=s+1;t>n&&null==e[n];)e[o=n++]=null}}}const je="undefined"==typeof queueMicrotask?e=>Promise.resolve().then(e):queueMicrotask,Ue=["January","February","March","April","May","June","July","August","September","October","November","December"],Be=["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"];function Ve(e){return e.slice(0,3)}const $e=Be.map(Ve),Je=Ue.map(Ve),qe={MMMM:Ue,MMM:Je,WWWW:Be,WWW:$e};function Ke(e){return(10>e?"0":"")+e}const Xe={YYYY:e=>e.getFullYear(),YY:e=>(e.getFullYear()+"").slice(2),MMMM:(e,l)=>l.MMMM[e.getMonth()],MMM:(e,l)=>l.MMM[e.getMonth()],MM:e=>Ke(e.getMonth()+1),M:e=>e.getMonth()+1,DD:e=>Ke(e.getDate()),D:e=>e.getDate(),WWWW:(e,l)=>l.WWWW[e.getDay()],WWW:(e,l)=>l.WWW[e.getDay()],HH:e=>Ke(e.getHours()),H:e=>e.getHours(),h:e=>{let l=e.getHours();return 0==l?12:l>12?l-12:l},AA:e=>12>e.getHours()?"AM":"PM",aa:e=>12>e.getHours()?"am":"pm",a:e=>12>e.getHours()?"a":"p",mm:e=>Ke(e.getMinutes()),m:e=>e.getMinutes(),ss:e=>Ke(e.getSeconds()),s:e=>e.getSeconds(),fff:e=>function(e){return(10>e?"00":100>e?"0":"")+e}(e.getMilliseconds())};function Ze(e,l){l=l||qe;let t,n=[],i=/\{([a-z]+)\}|[^{]+/gi;for(;t=i.exec(e);)n.push("{"==t[0][0]?Xe[t[1]]:t[0]);return e=>{let t="";for(let i=0;n.length>i;i++)t+="string"==typeof n[i]?n[i]:n[i](e,l);return t}}const Qe=(new Intl.DateTimeFormat).resolvedOptions().timeZone,el=e=>e%1==0,ll=[1,2,2.5,5],tl=De(10,-32,0,ll),nl=De(10,0,32,ll),il=nl.filter(el),ol=tl.concat(nl),sl="{YYYY}",rl="\n"+sl,ul="{M}/{D}",al="\n"+ul,fl=al+"/{YY}",cl="{aa}",hl="{h}:{mm}"+cl,dl="\n"+hl,pl=":{ss}",ml=null;function gl(e){let l=1e3*e,t=60*l,n=60*t,i=24*n,o=30*i,s=365*i;return[(1==e?De(10,0,3,ll).filter(el):De(10,-3,0,ll)).concat([l,5*l,10*l,15*l,30*l,t,5*t,10*t,15*t,30*t,n,2*n,3*n,4*n,6*n,8*n,12*n,i,2*i,3*i,4*i,5*i,6*i,7*i,8*i,9*i,10*i,15*i,o,2*o,3*o,4*o,6*o,s,2*s,5*s,10*s,25*s,50*s,100*s]),[[s,sl,ml,ml,ml,ml,ml,ml,1],[28*i,"{MMM}",rl,ml,ml,ml,ml,ml,1],[i,ul,rl,ml,ml,ml,ml,ml,1],[n,"{h}"+cl,fl,ml,al,ml,ml,ml,1],[t,hl,fl,ml,al,ml,ml,ml,1],[l,pl,fl+" "+hl,ml,al+" "+hl,ml,dl,ml,1],[e,pl+".{fff}",fl+" "+hl,ml,al+" "+hl,ml,dl,ml,1]],function(l){return(r,u,a,f,c,h)=>{let d=[],p=c>=s,m=c>=o&&s>c,g=l(a),x=Ee(g*e,3),w=Sl(g.getFullYear(),p?0:g.getMonth(),m||p?1:g.getDate()),_=Ee(w*e,3);if(m||p){let t=m?c/o:0,n=p?c/s:0,i=x==_?x:Ee(Sl(w.getFullYear()+n,w.getMonth()+t,1)*e,3),r=new Date(ne(i/e)),u=r.getFullYear(),a=r.getMonth();for(let o=0;f>=i;o++){let s=Sl(u+n*o,a+t*o,1),r=s-l(Ee(s*e,3));i=Ee((+s+r)*e,3),i>f||d.push(i)}}else{let o=i>c?c:i,s=_+(te(a)-te(x))+Me(x-_,o);d.push(s);let p=l(s),m=p.getHours()+p.getMinutes()/t+p.getSeconds()/n,g=c/n,w=h/r.axes[u]._space;for(;s=Ee(s+c,1==e?0:3),f>=s;)if(g>1){let e=te(Ee(m+g,6))%24,t=l(s).getHours()-e;t>1&&(t=-1),s-=t*n,m=(m+g)%24,.7>Ee((s-d[d.length-1])/c,3)*w||d.push(s)}else d.push(s)}return d}}]}const[xl,wl,_l]=gl(1),[bl,vl,kl]=gl(.001);function yl(e,l){return e.map((e=>e.map(((t,n)=>0==n||8==n||null==t?t:l(1==n||0==e[8]?t:e[1]+t)))))}function Ml(e,l){return(t,n,i,o,s)=>{let r,u,a,f,c,h,d=l.find((e=>s>=e[0]))||l[l.length-1];return n.map((l=>{let t=e(l),n=t.getFullYear(),i=t.getMonth(),o=t.getDate(),s=t.getHours(),p=t.getMinutes(),m=t.getSeconds(),g=n!=r&&d[2]||i!=u&&d[3]||o!=a&&d[4]||s!=f&&d[5]||p!=c&&d[6]||m!=h&&d[7]||d[1];return r=n,u=i,a=o,f=s,c=p,h=m,g(t)}))}}function Sl(e,l,t){return new Date(e,l,t)}function El(e,l){return l(e)}function Tl(e,l){return(t,n,i,o)=>null==o?w:l(e(n))}De(2,-53,53,[1]);const zl={show:!0,live:!0,isolate:!1,mount:()=>{},markers:{show:!0,width:2,stroke:function(e,l){let t=e.series[l];return t.width?t.stroke(e,l):t.points.width?t.points.stroke(e,l):null},fill:function(e,l){return e.series[l].fill(e,l)},dash:"solid"},idx:null,idxs:null,values:[]},Dl=[0,0];function Pl(e,l,t,n=!0){return e=>{0==e.button&&(!n||e.target==l)&&t(e)}}function Al(e,l,t,n=!0){return e=>{(!n||e.target==l)&&t(e)}}const Wl={show:!0,x:!0,y:!0,lock:!1,move:function(e,l,t){return Dl[0]=l,Dl[1]=t,Dl},points:{one:!1,show:function(e,l){let i=e.cursor.points,o=D(),s=i.size(e,l);T(o,t,s),T(o,n,s);let r=s/-2;T(o,"marginLeft",r),T(o,"marginTop",r);let u=i.width(e,l,s);return u&&T(o,"borderWidth",u),o},size:function(e,l){return e.series[l].points.size},width:0,stroke:function(e,l){let t=e.series[l].points;return t._stroke||t._fill},fill:function(e,l){let t=e.series[l].points;return t._fill||t._stroke}},bind:{mousedown:Pl,mouseup:Pl,click:Pl,dblclick:Pl,mousemove:Al,mouseleave:Al,mouseenter:Al},drag:{setScale:!0,x:!0,y:!1,dist:0,uni:null,click:(e,l)=>{l.stopPropagation(),l.stopImmediatePropagation()},_x:!1,_y:!1},focus:{dist:(e,l,t,n,i)=>n-i,prox:-1,bias:0},hover:{skip:[void 0],prox:null,bias:0},left:-10,top:-10,idx:null,dataIdx:null,idxs:null,event:null},Yl={show:!0,stroke:"rgba(0,0,0,0.07)",width:2},Cl=Le({},Yl,{filter:xe}),Fl=Le({},Cl,{size:10}),Hl=Le({},Yl,{show:!1}),Rl='12px system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"',Gl="bold "+Rl,Il={show:!0,scale:"x",stroke:u,space:50,gap:5,size:50,labelGap:0,labelSize:30,labelFont:Gl,side:2,grid:Cl,ticks:Fl,border:Hl,font:Rl,lineGap:1.5,rotate:0},Ol={show:!0,scale:"x",auto:!1,sorted:1,min:he,max:-he,idxs:[]};function Ll(e,l){return l.map((e=>null==e?"":Z(e)))}function Nl(e,l,t,n,i,o,s){let r=[],u=Te.get(i)||0;for(let e=t=s?t:Ee(Me(t,i),u);n>=e;e=Ee(e+i,u))r.push(Object.is(e,-0)?0:e);return r}function jl(e,l,t,n,i){const o=[],s=e.scales[e.axes[l].scale].log,r=te((10==s?ae:fe)(t));i=re(s,r),10==s&&(i=ol[O(i,ol)]);let u=t,a=i*s;10==s&&(a=ol[O(a,ol)]);do{o.push(u),u+=i,10!=s||Te.has(u)||(u=Ee(u,Te.get(i))),a>u||(a=(i=u)*s,10==s&&(a=ol[O(a,ol)]))}while(n>=u);return o}function Ul(e,l,t,n,i){let o=e.scales[e.axes[l].scale].asinh,s=n>o?jl(e,l,se(o,t),n,i):[o],r=0>n||t>0?[]:[0];return(-o>t?jl(e,l,se(o,-n),-t,i):[o]).reverse().map((e=>-e)).concat(r,s)}const Bl=/./,Vl=/[12357]/,$l=/[125]/,Jl=/1/,ql=(e,l,t,n)=>e.map(((e,i)=>4==l&&0==e||i%n==0&&t.test(e.toExponential()[0>e?1:0])?e:null));function Kl(e,l,t){let n=e.axes[t],i=n.scale,o=e.scales[i],s=e.valToPos,r=n._space,u=s(10,i),a=s(9,i)-ue)return ql(l.slice().reverse(),o.distr,a,ie(r/e)).reverse()}return ql(l,o.distr,a,1)}function Xl(e,l,t){let n=e.axes[t],i=n.scale,o=n._space,s=e.valToPos,r=le(s(1,i)-s(2,i));return o>r?ql(l.slice().reverse(),3,Bl,ie(o/r)).reverse():l}function Zl(e,l,t,n){return null==n?w:null==l?"":Z(l)}const Ql={show:!0,scale:"y",stroke:u,space:30,gap:5,size:50,labelGap:0,labelSize:30,labelFont:Gl,side:3,grid:Cl,ticks:Fl,border:Hl,font:Rl,lineGap:1.5,rotate:0},et={scale:null,auto:!0,sorted:0,min:he,max:-he},lt=(e,l,t,n,i)=>i,tt={show:!0,auto:!0,sorted:0,gaps:lt,alpha:1,facets:[Le({},et,{scale:"x"}),Le({},et,{scale:"y"})]},nt={scale:"y",auto:!0,sorted:0,show:!0,spanGaps:!1,gaps:lt,alpha:1,points:{show:function(e,l){let{scale:t,idxs:n}=e.series[0],i=e._data[0],o=e.valToPos(i[n[0]],t,!0),s=e.valToPos(i[n[1]],t,!0);return le(s-o)/(e.series[l].points.space*y)>=n[1]-n[0]},filter:null},values:null,min:he,max:-he,idxs:[],path:null,clip:null};function it(e,l,t){return t/10}const ot={time:!0,auto:!0,distr:1,log:10,asinh:1,min:null,max:null,dir:1,ori:0},st=Le({},ot,{time:!1,ori:1}),rt={};function ut(e){let l=rt[e];return l||(l={key:e,plots:[],sub(e){l.plots.push(e)},unsub(e){l.plots=l.plots.filter((l=>l!=e))},pub(e,t,n,i,o,s,r){for(let u=0;l.plots.length>u;u++)l.plots[u]!=t&&l.plots[u].pub(e,t,n,i,o,s,r)}},null!=e&&(rt[e]=l)),l}function at(e,l,t){const n=e.mode,i=e.series[l],o=2==n?e._data[l]:e._data,s=e.scales,r=e.bbox;let u=o[0],a=2==n?o[1]:o[l],f=2==n?s[i.facets[0].scale]:s[e.series[0].scale],c=2==n?s[i.facets[1].scale]:s[i.scale],h=r.left,d=r.top,p=r.width,m=r.height,g=e.valToPosH,x=e.valToPosV;return 0==f.ori?t(i,u,a,f,c,g,x,h,d,p,m,xt,_t,vt,yt,St):t(i,u,a,f,c,x,g,d,h,m,p,wt,bt,kt,Mt,Et)}function ft(e,l){let t=0,n=0,i=q(e.bands,Ae);for(let e=0;i.length>e;e++){let o=i[e];o.series[0]==l?t=o.dir:o.series[1]==l&&(n|=1==o.dir?1:2)}return[t,1==n?-1:2==n?1:3==n?2:0]}function ct(e,l,t,n,i){let o=e.series[l],s=e.scales[2==e.mode?o.facets[1].scale:o.scale];return-1==i?s.min:1==i?s.max:3==s.distr?1==s.dir?s.min:s.max:0}function ht(e,l,t,n,i,o){return at(e,l,((e,l,s,r,u,a,f,c,h,d,p)=>{let m=e.pxRound;const g=0==r.ori?_t:bt;let x,w;1==r.dir*(0==r.ori?1:-1)?(x=t,w=n):(x=n,w=t);let _=m(a(l[x],r,d,c)),b=m(f(s[x],u,p,h)),v=m(a(l[w],r,d,c)),k=m(f(1==o?u.max:u.min,u,p,h)),y=new Path2D(i);return g(y,v,k),g(y,_,k),g(y,_,b),y}))}function dt(e,l,t,n,i,o){let s=null;if(e.length>0){s=new Path2D;const r=0==l?vt:kt;let u=t;for(let l=0;e.length>l;l++){let t=e[l];if(t[1]>t[0]){let e=t[0]-u;e>0&&r(s,u,n,e,n+o),u=t[1]}}let a=t+i-u,f=10;a>0&&r(s,u,n-f/2,a,n+o+f)}return s}function pt(e,l,t,n,i,o,s){let r=[],u=e.length;for(let a=1==i?t:n;a>=t&&n>=a;a+=i)if(null===l[a]){let f=a,c=a;if(1==i)for(;++a<=n&&null===l[a];)c=a;else for(;--a>=t&&null===l[a];)c=a;let h=o(e[f]),d=c==f?h:o(e[c]),p=f-i;h=s>0||0>p||p>=u?h:o(e[p]);let m=c+i;d=0>s||0>m||m>=u?d:o(e[m]),h>d||r.push([h,d])}return r}function mt(e){return 0==e?ge:1==e?ne:l=>ye(l,e)}function gt(e){let l=0==e?xt:wt,t=0==e?(e,l,t,n,i,o)=>{e.arcTo(l,t,n,i,o)}:(e,l,t,n,i,o)=>{e.arcTo(t,l,i,n,o)},n=0==e?(e,l,t,n,i)=>{e.rect(l,t,n,i)}:(e,l,t,n,i)=>{e.rect(t,l,i,n)};return(e,i,o,s,r,u=0,a=0)=>{0==u&&0==a?n(e,i,o,s,r):(u=oe(u,s/2,r/2),a=oe(a,s/2,r/2),l(e,i+u,o),t(e,i+s,o,i+s,o+r,u),t(e,i+s,o+r,i,o+r,a),t(e,i,o+r,i,o,a),t(e,i,o,i+s,o,u),e.closePath())}}const xt=(e,l,t)=>{e.moveTo(l,t)},wt=(e,l,t)=>{e.moveTo(t,l)},_t=(e,l,t)=>{e.lineTo(l,t)},bt=(e,l,t)=>{e.lineTo(t,l)},vt=gt(0),kt=gt(1),yt=(e,l,t,n,i,o)=>{e.arc(l,t,n,i,o)},Mt=(e,l,t,n,i,o)=>{e.arc(t,l,n,i,o)},St=(e,l,t,n,i,o,s)=>{e.bezierCurveTo(l,t,n,i,o,s)},Et=(e,l,t,n,i,o,s)=>{e.bezierCurveTo(t,l,i,n,s,o)};function Tt(){return(e,l,t,n,i)=>at(e,l,((l,o,s,r,u,a,f,c,h,d,p)=>{let m,g,{pxRound:x,points:w}=l;0==r.ori?(m=xt,g=yt):(m=wt,g=Mt);const _=Ee(w.width*y,3);let b=(w.size-w.width)/2*y,v=Ee(2*b,3),k=new Path2D,M=new Path2D,{left:S,top:E,width:T,height:z}=e.bbox;vt(M,S-v,E-v,T+2*v,z+2*v);const D=e=>{if(null!=s[e]){let l=x(a(o[e],r,d,c)),t=x(f(s[e],u,p,h));m(k,l+b,t),g(k,l,t,b,0,2*ee)}};if(i)i.forEach(D);else for(let e=t;n>=e;e++)D(e);return{stroke:_>0?k:null,fill:k,clip:M,flags:3}}))}function zt(e){return(l,t,n,i,o,s)=>{n!=i&&(o!=n&&s!=n&&e(l,t,n),o!=i&&s!=i&&e(l,t,i),e(l,t,s))}}const Dt=zt(_t),Pt=zt(bt);function At(e){const l=q(e?.alignGaps,0);return(e,t,n,i)=>at(e,t,((o,s,r,u,a,f,c,h,d,p,m)=>{let g,x,w=o.pxRound,_=e=>w(f(e,u,p,h)),b=e=>w(c(e,a,m,d));0==u.ori?(g=_t,x=Dt):(g=bt,x=Pt);const v=u.dir*(0==u.ori?1:-1),k={stroke:new Path2D,fill:null,clip:null,band:null,gaps:null,flags:1},y=k.stroke;let M,S,E,T=he,z=-he,D=_(s[1==v?n:i]),P=L(r,n,i,1*v),A=L(r,n,i,-1*v),W=_(s[P]),Y=_(s[A]),C=!1;for(let e=1==v?n:i;e>=n&&i>=e;e+=v){let l=_(s[e]),t=r[e];l==D?null!=t?(S=b(t),T==he&&(g(y,l,S),M=S),T=oe(S,T),z=se(S,z)):null===t&&(C=!0):(T!=he&&(x(y,D,T,z,M,S),E=D),null!=t?(S=b(t),g(y,l,S),T=z=M=S):(T=he,z=-he,null===t&&(C=!0)),D=l)}T!=he&&T!=z&&E!=D&&x(y,D,T,z,M,S);let[F,H]=ft(e,t);if(null!=o.fill||0!=F){let l=k.fill=new Path2D(y),n=b(o.fillTo(e,t,o.min,o.max,F));g(l,Y,n),g(l,W,n)}if(!o.spanGaps){let a=[];C&&a.push(...pt(s,r,n,i,v,_,l)),k.gaps=a=o.gaps(e,t,n,i,a),k.clip=dt(a,u.ori,h,d,p,m)}return 0!=H&&(k.band=2==H?[ht(e,t,n,i,y,-1),ht(e,t,n,i,y,1)]:ht(e,t,n,i,y,H)),k}))}function Wt(e,l,t,n,i,o,s=he){if(e.length>1){let r=null;for(let u=0,a=1/0;e.length>u;u++)if(void 0!==l[u]){if(null!=r){let l=le(e[u]-e[r]);a>l&&(a=l,s=le(t(e[u],n,i,o)-t(e[r],n,i,o)))}r=u}}return s}function Yt(e,l,t,n,i){const o=e.length;if(2>o)return null;const s=new Path2D;if(t(s,e[0],l[0]),2==o)n(s,e[1],l[1]);else{let t=Array(o),n=Array(o-1),r=Array(o-1),u=Array(o-1);for(let t=0;o-1>t;t++)r[t]=l[t+1]-l[t],u[t]=e[t+1]-e[t],n[t]=r[t]/u[t];t[0]=n[0];for(let e=1;o-1>e;e++)0===n[e]||0===n[e-1]||n[e-1]>0!=n[e]>0?t[e]=0:(t[e]=3*(u[e-1]+u[e])/((2*u[e]+u[e-1])/n[e-1]+(u[e]+2*u[e-1])/n[e]),isFinite(t[e])||(t[e]=0));t[o-1]=n[o-2];for(let n=0;o-1>n;n++)i(s,e[n]+u[n]/3,l[n]+t[n]*u[n]/3,e[n+1]-u[n]/3,l[n+1]-t[n+1]*u[n]/3,e[n+1],l[n+1])}return s}const Ct=new Set;function Ft(){for(let e of Ct)e.syncRect(!0)}_&&(G("resize",v,Ft),G("scroll",v,Ft,!0),G(x,v,(()=>{Kt.pxRatio=y})));const Ht=At(),Rt=Tt();function Gt(e,l,t,n){return(n?[e[0],e[1]].concat(e.slice(2)):[e[0]].concat(e.slice(1))).map(((e,n)=>It(e,n,l,t)))}function It(e,l,t,n){return Le({},0==l?t:n,e)}function Ot(e,l,t){return null==l?We:[l,t]}const Lt=Ot;function Nt(e,l,t){return null==l?We:J(l,t,U,!0)}function jt(e,l,t,n){return null==l?We:N(l,t,e.scales[n].log,!1)}const Ut=jt;function Bt(e,l,t,n){return null==l?We:j(l,t,e.scales[n].log,!1)}const Vt=Bt;function $t(e,l,t,n,i){let o=se(de(e),de(l)),s=l-e,r=O(i/n*s,t);do{let e=t[r],l=n*e/s;if(l>=i&&17>=o+(5>e?Te.get(e):0))return[e,l]}while(++r(l=ne((t=+n)*y))+"px")),l,t]}function qt(e){e.show&&[e.font,e.labelFont].forEach((e=>{let l=Ee(e[2]*y,1);e[0]=e[0].replace(/[0-9.]+px/,l+"px"),e[1]=l}))}function Kt(u,g,_){const k={mode:q(u.mode,1)},M=k.mode;function P(e,l){return((3==l.distr?ae(e>0?e:l.clamp(k,e,l.min,l.max,l.key)):4==l.distr?ce(e,l.asinh):100==l.distr?l.fwd(e):e)-l._min)/(l._max-l._min)}function W(e,l,t,n){let i=P(e,l);return n+t*(-1==l.dir?1-i:i)}function C(e,l,t,n){let i=P(e,l);return n+t*(-1==l.dir?i:1-i)}function H(e,l,t,n){return 0==l.ori?W(e,l,t,n):C(e,l,t,n)}k.valToPosH=W,k.valToPosV=C;let R=!1;k.status=0;const L=k.root=D("uplot");null!=u.id&&(L.id=u.id),S(L,u.class),u.title&&(D("u-title",L).textContent=u.title);const V=z("canvas"),$=k.ctx=V.getContext("2d"),K=D("u-wrap",L);G("click",K,(e=>{e.target===Z&&(Hn!=Wn||Rn!=Yn)&&Vn.click(k,e)}),!0);const X=k.under=D("u-under",K);K.appendChild(V);const Z=k.over=D("u-over",K),te=+q((u=Oe(u)).pxAlign,1),ue=mt(te);(u.plugins||[]).forEach((e=>{e.opts&&(u=e.opts(k,u)||u)}));const fe=u.ms||.001,de=k.series=1==M?Gt(u.series||[],Ol,nt,!1):function(e,l){return e.map(((e,t)=>0==t?{}:Le({},l,e)))}(u.series||[null],tt),ge=k.axes=Gt(u.axes||[],Il,Ql,!0),ve=k.scales={},ke=k.bands=u.bands||[];ke.forEach((e=>{e.fill=me(e.fill||null),e.dir=q(e.dir,-1)}));const Me=2==M?de[1].facets[0].scale:de[0].scale,Se={axes:function(){for(let e=0;ge.length>e;e++){let l=ge[e];if(!l.show||!l._show)continue;let t,n,u=l.side,a=u%2,f=l.stroke(k,e),c=0==u||3==u?-1:1;if(l.label){let e=ne((l._lpos+l.labelGap*c)*y);dn(l.labelFont[0],f,"center",2==u?i:o),$.save(),1==a?(t=n=0,$.translate(e,ne($l+ql/2)),$.rotate((3==u?-ee:ee)/2)):(t=ne(Vl+Jl/2),n=e),$.fillText(l.label,t,n),$.restore()}let[h,d]=l._found;if(0==d)continue;let p=ve[l.scale],m=0==a?Jl:ql,g=0==a?Vl:$l,x=ne(l.gap*y),w=l._splits,_=2==p.distr?w.map((e=>un[e])):w,b=2==p.distr?un[w[1]]-un[w[0]]:h,v=l.ticks,M=l.border,S=v.show?ne(v.size*y):0,E=l._rotate*-ee/180,T=ue(l._pos*y),z=T+(S+x)*c;n=0==a?z:0,t=1==a?z:0,dn(l.font[0],f,1==l.align?s:2==l.align?r:E>0?s:0>E?r:0==a?"center":3==u?r:s,E||1==a?"middle":2==u?i:o);let D=l.font[1]*l.lineGap,P=w.map((e=>ue(H(e,p,m,g)))),A=l._values;for(let e=0;A.length>e;e++){let l=A[e];if(null!=l){0==a?t=P[e]:n=P[e],l=""+l;let i=-1==l.indexOf("\n")?[l]:l.split(/\n/gm);for(let e=0;i.length>e;e++){let l=i[e];E?($.save(),$.translate(t,n+e*D),$.rotate(E),$.fillText(l,0,0),$.restore()):$.fillText(l,t,n+e*D)}}}v.show&&kn(P,v.filter(k,_,e,d,b),a,u,T,S,Ee(v.width*y,3),v.stroke(k,e),v.dash,v.cap);let W=l.grid;W.show&&kn(P,W.filter(k,_,e,d,b),a,0==a?2:1,0==a?$l:Vl,0==a?ql:Jl,Ee(W.width*y,3),W.stroke(k,e),W.dash,W.cap),M.show&&kn([T],[1],0==a?1:0,0==a?1:2,1==a?$l:Vl,1==a?ql:Jl,Ee(M.width*y,3),M.stroke(k,e),M.dash,M.cap)}zi("drawAxes")},series:function(){Wt>0&&(de.forEach(((e,l)=>{if(l>0&&e.show&&(gn(l,!1),gn(l,!0),null==e._paths)){rn!=e.alpha&&($.globalAlpha=rn=e.alpha);let t=2==M?[0,g[l][0].length-1]:function(e){let l=pe(Yt-1,0,Wt-1),t=pe(Ft+1,0,Wt-1);for(;null==e[l]&&l>0;)l--;for(;null==e[t]&&Wt-1>t;)t++;return[l,t]}(g[l]);e._paths=e.paths(k,l,t[0],t[1]),1!=rn&&($.globalAlpha=rn=1)}})),de.forEach(((e,l)=>{if(l>0&&e.show){rn!=e.alpha&&($.globalAlpha=rn=e.alpha),null!=e._paths&&xn(l,!1);{let t=null!=e._paths?e._paths.gaps:null,n=e.points.show(k,l,Yt,Ft,t),i=e.points.filter(k,l,n,t);(n||i)&&(e.points._paths=e.points.paths(k,l,Yt,Ft,i),xn(l,!0))}1!=rn&&($.globalAlpha=rn=1),zi("drawSeries",l)}})))}},De=(u.drawOrder||["axes","series"]).map((e=>Se[e]));function Ce(e){let l=ve[e];if(null==l){let t=(u.scales||Pe)[e]||Pe;if(null!=t.from)Ce(t.from),ve[e]=Le({},ve[t.from],t,{key:e});else{l=ve[e]=Le({},e==Me?ot:st,t),l.key=e;let n=l.time,i=l.range,o=Ye(i);if((e!=Me||2==M&&!n)&&(!o||null!=i[0]&&null!=i[1]||(i={min:null==i[0]?B:{mode:1,hard:i[0],soft:i[0]},max:null==i[1]?B:{mode:1,hard:i[1],soft:i[1]}},o=!1),!o&&He(i))){let e=i;i=(l,t,n)=>null==t?We:J(t,n,e)}l.range=me(i||(n?Lt:e==Me?3==l.distr?Ut:4==l.distr?Vt:Ot:3==l.distr?jt:4==l.distr?Bt:Nt)),l.auto=me(!o&&l.auto),l.clamp=me(l.clamp||it),l._min=l._max=null}}}Ce("x"),Ce("y"),1==M&&de.forEach((e=>{Ce(e.scale)})),ge.forEach((e=>{Ce(e.scale)}));for(let e in u.scales)Ce(e);const Ge=ve[Me],Ie=Ge.distr;let Ne,Ue;0==Ge.ori?(S(L,"u-hz"),Ne=W,Ue=C):(S(L,"u-vt"),Ne=C,Ue=W);const Be={};for(let e in ve){let l=ve[e];null==l.min&&null==l.max||(Be[e]={min:l.min,max:l.max},l.min=l.max=null)}const Ve=u.tzDate||(e=>new Date(ne(e/fe))),$e=u.fmtDate||Ze,Je=1==fe?_l(Ve):kl(Ve),qe=Ml(Ve,yl(1==fe?wl:vl,$e)),Ke=Tl(Ve,El("{YYYY}-{MM}-{DD} {h}:{mm}{aa}",$e)),Xe=[],Qe=k.legend=Le({},zl,u.legend),el=Qe.show,ll=Qe.markers;let tl,nl,sl;Qe.idxs=Xe,ll.width=me(ll.width),ll.dash=me(ll.dash),ll.stroke=me(ll.stroke),ll.fill=me(ll.fill);let rl,ul=[],al=[],fl=!1,cl={};if(Qe.live){const e=de[1]?de[1].values:null;fl=null!=e,rl=fl?e(k,1,0):{_:0};for(let e in rl)cl[e]=w}if(el)if(tl=z("table","u-legend",L),sl=z("tbody",null,tl),Qe.mount(k,tl),fl){nl=z("thead",null,tl,sl);let e=z("tr",null,nl);for(var hl in z("th",null,e),rl)z("th",l,e).textContent=hl}else S(tl,"u-inline"),Qe.live&&S(tl,"u-live");const dl={show:!0},pl={show:!1},ml=new Map;function gl(e,l,t,n=!0){const i=ml.get(l)||{},o=xt.bind[e](k,l,t,n);o&&(G(e,l,i[e]=o),ml.set(l,i))}function Sl(e,l){const t=ml.get(l)||{};for(let n in t)null!=e&&n!=e||(I(n,l,t[n]),delete t[n]);null==e&&ml.delete(l)}let Dl=0,Pl=0,Al=0,Yl=0,Cl=0,Fl=0,Hl=Cl,Rl=Fl,Gl=Al,Bl=Yl,Vl=0,$l=0,Jl=0,ql=0;k.bbox={};let et=!1,lt=!1,rt=!1,at=!1,ft=!1,ht=!1;function dt(e,l,t){(t||e!=k.width||l!=k.height)&&pt(e,l),Sn(!1),rt=!0,lt=!0,Nn()}function pt(e,l){k.width=Dl=Al=e,k.height=Pl=Yl=l,Cl=Fl=0,function(){let e=!1,l=!1,t=!1,n=!1;ge.forEach((i=>{if(i.show&&i._show){let{side:o,_size:s}=i,r=s+(null!=i.label?i.labelSize:0);r>0&&(o%2?(Al-=r,3==o?(Cl+=r,n=!0):t=!0):(Yl-=r,0==o?(Fl+=r,e=!0):l=!0))}})),zt[0]=e,zt[1]=t,zt[2]=l,zt[3]=n,Al-=At[1]+At[3],Cl+=At[3],Yl-=At[2]+At[0],Fl+=At[0]}(),function(){let e=Cl+Al,l=Fl+Yl,t=Cl,n=Fl;function i(i,o){switch(i){case 1:return e+=o,e-o;case 2:return l+=o,l-o;case 3:return t-=o,t+o;case 0:return n-=o,n+o}}ge.forEach((e=>{if(e.show&&e._show){let l=e.side;e._pos=i(l,e._size),null!=e.label&&(e._lpos=i(l,e.labelSize))}}))}();let t=k.bbox;Vl=t.left=ye(Cl*y,.5),$l=t.top=ye(Fl*y,.5),Jl=t.width=ye(Al*y,.5),ql=t.height=ye(Yl*y,.5)}const gt=3;k.setSize=function({width:e,height:l}){dt(e,l)};const xt=k.cursor=Le({},Wl,{drag:{y:2==M}},u.cursor);if(null==xt.dataIdx){let e=xt.hover,l=e.skip=new Set(e.skip??[]);l.add(void 0);let t=e.prox=me(e.prox),n=e.bias??=0;xt.dataIdx=(e,i,o,s)=>{if(0==i)return o;let r=o,u=t(e,i,o,s)??he,a=u>=0&&he>u,f=0==Ge.ori?Al:Yl,c=xt.left,h=g[0],d=g[i];if(l.has(d[o])){r=null;let e,t=null,i=null;if(0==n||-1==n)for(e=o;null==t&&e-- >0;)l.has(d[e])||(t=e);if(0==n||1==n)for(e=o;null==i&&e++l?l>u||(r=i):e>u||(r=t)}else r=null==i?t:null==t||o-t>i-o?i:t}else a&&le(c-Ne(h[o],Ge,f,0))>u&&(r=null);return r}}const wt=e=>{xt.event=e};xt.idxs=Xe,xt._lock=!1;let _t=xt.points;_t.show=me(_t.show),_t.size=me(_t.size),_t.stroke=me(_t.stroke),_t.width=me(_t.width),_t.fill=me(_t.fill);const bt=k.focus=Le({},u.focus||{alpha:.3},xt.focus),vt=bt.prox>=0,kt=vt&&_t.one;let yt=[],Mt=[],St=[];function Et(e,l){let t=_t.show(k,l);if(t)return S(t,"u-cursor-pt"),S(t,e.class),A(t,-10,-10,Al,Yl),Z.insertBefore(t,yt[l]),t}function Tt(t,n){if(1==M||n>0){let e=1==M&&ve[t.scale].time,l=t.value;t.value=e?Fe(l)?Tl(Ve,El(l,$e)):l||Ke:l||Zl,t.label=t.label||(e?"Time":"Value")}if(kt||n>0){t.width=null==t.width?1:t.width,t.paths=t.paths||Ht||we,t.fillTo=me(t.fillTo||ct),t.pxAlign=+q(t.pxAlign,te),t.pxRound=mt(t.pxAlign),t.stroke=me(t.stroke||null),t.fill=me(t.fill||null),t._stroke=t._fill=t._paths=t._focus=null;let e=function(e){return Ee(1*(3+2*(e||1)),3)}(se(1,t.width)),l=t.points=Le({},{size:e,width:se(1,.2*e),stroke:t.stroke,space:2*e,paths:Rt,_stroke:null,_fill:null},t.points);l.show=me(l.show),l.filter=me(l.filter),l.fill=me(l.fill),l.stroke=me(l.stroke),l.paths=me(l.paths),l.pxAlign=t.pxAlign}if(el){let i=function(t,n){if(0==n&&(fl||!Qe.live||2==M))return We;let i=[],o=z("tr","u-series",sl,sl.childNodes[n]);S(o,t.class),t.show||S(o,e);let s=z("th",null,o);if(ll.show){let e=D("u-marker",s);if(n>0){let l=ll.width(k,n);l&&(e.style.border=l+"px "+ll.dash(k,n)+" "+ll.stroke(k,n)),e.style.background=ll.fill(k,n)}}let r=D(l,s);for(var u in r.textContent=t.label,n>0&&(ll.show||(r.style.color=t.width>0?ll.stroke(k,n):ll.fill(k,n)),gl("click",s,(e=>{if(xt._lock)return;wt(e);let l=de.indexOf(t);if((e.ctrlKey||e.metaKey)!=Qe.isolate){let e=de.some(((e,t)=>t>0&&t!=l&&e.show));de.forEach(((t,n)=>{n>0&&Qn(n,e?n==l?dl:pl:dl,!0,Pi.setSeries)}))}else Qn(l,{show:!t.show},!0,Pi.setSeries)}),!1),vt&&gl(d,s,(e=>{xt._lock||(wt(e),Qn(de.indexOf(t),ni,!0,Pi.setSeries))}),!1)),rl){let e=z("td","u-value",o);e.textContent="--",i.push(e)}return[o,i]}(t,n);ul.splice(n,0,i[0]),al.splice(n,0,i[1]),Qe.values.push(null)}if(xt.show){Xe.splice(n,0,null);let e=null;kt?0==n&&(e=Et(t,n)):n>0&&(e=Et(t,n)),yt.splice(n,0,e),Mt.splice(n,0,0),St.splice(n,0,0)}zi("addSeries",n)}k.addSeries=function(e,l){l=null==l?de.length:l,e=1==M?It(e,l,Ol,nt):It(e,l,{},tt),de.splice(l,0,e),Tt(de[l],l)},k.delSeries=function(e){if(de.splice(e,1),el){Qe.values.splice(e,1),al.splice(e,1);let l=ul.splice(e,1)[0];Sl(null,l.firstChild),l.remove()}xt.show&&(Xe.splice(e,1),yt.splice(e,1)[0].remove(),Mt.splice(e,1),St.splice(e,1)),zi("delSeries",e)};const zt=[!1,!1,!1,!1];function Dt(e,l,t){let[n,i,o,s]=t,r=l%2,u=0;return 0==r&&(s||i)&&(u=0==l&&!n||2==l&&!o?ne(Il.size/3):0),1==r&&(n||o)&&(u=1==l&&!i||3==l&&!s?ne(Ql.size/2):0),u}const Pt=k.padding=(u.padding||[Dt,Dt,Dt,Dt]).map((e=>me(q(e,Dt)))),At=k._padding=Pt.map(((e,l)=>e(k,l,zt,0)));let Wt,Yt=null,Ft=null;const Kt=1==M?de[0].idxs:null;let Xt,Zt,Qt,en,ln,tn,nn,on,sn,rn,un=null,an=!1;function fn(e,l){if(k.data=k._data=g=null==e?[]:e,2==M){Wt=0;for(let e=1;de.length>e;e++)Wt+=g[e][0].length}else{0==g.length&&(k.data=k._data=g=[[]]),un=g[0],Wt=un.length;let e=g;if(2==Ie){e=g.slice();let l=e[0]=Array(Wt);for(let e=0;Wt>e;e++)l[e]=e}k._data=g=e}if(Sn(!0),zi("setData"),2==Ie&&(rt=!0),!1!==l){let e=Ge;e.auto(k,an)?cn():Zn(Me,e.min,e.max),at=at||xt.left>=0,ht=!0,Nn()}}function cn(){let e,l;an=!0,1==M&&(Wt>0?(Yt=Kt[0]=0,Ft=Kt[1]=Wt-1,e=g[0][Yt],l=g[0][Ft],2==Ie?(e=Yt,l=Ft):e==l&&(3==Ie?[e,l]=N(e,e,Ge.log,!1):4==Ie?[e,l]=j(e,e,Ge.log,!1):Ge.time?l=e+ne(86400/fe):[e,l]=J(e,l,U,!0))):(Yt=Kt[0]=e=null,Ft=Kt[1]=l=null)),Zn(Me,e,l)}function hn(e,l,t,n,i,o){e??=a,t??=Ae,n??="butt",i??=a,o??="round",e!=Xt&&($.strokeStyle=Xt=e),i!=Zt&&($.fillStyle=Zt=i),l!=Qt&&($.lineWidth=Qt=l),o!=ln&&($.lineJoin=ln=o),n!=tn&&($.lineCap=tn=n),t!=en&&$.setLineDash(en=t)}function dn(e,l,t,n){l!=Zt&&($.fillStyle=Zt=l),e!=nn&&($.font=nn=e),t!=on&&($.textAlign=on=t),n!=sn&&($.textBaseline=sn=n)}function pn(e,l,t,n,i=0){if(n.length>0&&e.auto(k,an)&&(null==l||null==l.min)){let l=q(Yt,0),o=q(Ft,n.length-1),s=null==t.min?3==e.distr?function(e,l,t){let n=he,i=-he;for(let o=l;t>=o;o++){let l=e[o];null!=l&&l>0&&(n>l&&(n=l),l>i&&(i=l))}return[n,i]}(n,l,o):function(e,l,t,n){let i=he,o=-he;if(1==n)i=e[l],o=e[t];else if(-1==n)i=e[t],o=e[l];else for(let n=l;t>=n;n++){let l=e[n];null!=l&&(i>l&&(i=l),l>o&&(o=l))}return[i,o]}(n,l,o,i):[t.min,t.max];e.min=oe(e.min,t.min=s[0]),e.max=se(e.max,t.max=s[1])}}k.setData=fn;const mn={min:null,max:null};function gn(e,l){let t=l?de[e].points:de[e];t._stroke=t.stroke(k,e),t._fill=t.fill(k,e)}function xn(e,l){let t=l?de[e].points:de[e],{stroke:n,fill:i,clip:o,flags:s,_stroke:r=t._stroke,_fill:u=t._fill,_width:a=t.width}=t._paths;a=Ee(a*y,3);let f=null,c=a%2/2;l&&null==u&&(u=a>0?"#fff":r);let h=1==t.pxAlign&&c>0;if(h&&$.translate(c,c),!l){let e=Vl-a/2,l=$l-a/2,t=Jl+a,n=ql+a;f=new Path2D,f.rect(e,l,t,n)}l?_n(r,a,t.dash,t.cap,u,n,i,s,o):function(e,l,t,n,i,o,s,r,u,a,f){let c=!1;0!=u&&ke.forEach(((h,d)=>{if(h.series[0]==e){let e,p=de[h.series[1]],m=g[h.series[1]],x=(p._paths||Pe).band;Ye(x)&&(x=1==h.dir?x[0]:x[1]);let w=null;p.show&&x&&function(e,l,t){for(l=q(l,0),t=q(t,e.length-1);t>=l;){if(null!=e[l])return!0;l++}return!1}(m,Yt,Ft)?(w=h.fill(k,d)||o,e=p._paths.clip):x=null,_n(l,t,n,i,w,s,r,u,a,f,e,x),c=!0}})),c||_n(l,t,n,i,o,s,r,u,a,f)}(e,r,a,t.dash,t.cap,u,n,i,s,f,o),h&&$.translate(-c,-c)}const wn=3;function _n(e,l,t,n,i,o,s,r,u,a,f,c){hn(e,l,t,n,i),(u||a||c)&&($.save(),u&&$.clip(u),a&&$.clip(a)),c?(r&wn)==wn?($.clip(c),f&&$.clip(f),vn(i,s),bn(e,o,l)):2&r?(vn(i,s),$.clip(c),bn(e,o,l)):1&r&&($.save(),$.clip(c),f&&$.clip(f),vn(i,s),$.restore(),bn(e,o,l)):(vn(i,s),bn(e,o,l)),(u||a||c)&&$.restore()}function bn(e,l,t){t>0&&(l instanceof Map?l.forEach(((e,l)=>{$.strokeStyle=Xt=l,$.stroke(e)})):null!=l&&e&&$.stroke(l))}function vn(e,l){l instanceof Map?l.forEach(((e,l)=>{$.fillStyle=Zt=l,$.fill(e)})):null!=l&&e&&$.fill(l)}function kn(e,l,t,n,i,o,s,r,u,a){let f=s%2/2;1==te&&$.translate(f,f),hn(r,s,u,a,r),$.beginPath();let c,h,d,p,m=i+(0==n||3==n?-o:o);0==t?(h=i,p=m):(c=i,d=m);for(let n=0;e.length>n;n++)null!=l[n]&&(0==t?c=d=e[n]:h=p=e[n],$.moveTo(c,h),$.lineTo(d,p));$.stroke(),1==te&&$.translate(-f,-f)}function yn(e){let l=!0;return ge.forEach(((t,n)=>{if(!t.show)return;let i=ve[t.scale];if(null==i.min)return void(t._show&&(l=!1,t._show=!1,Sn(!1)));t._show||(l=!1,t._show=!0,Sn(!1));let o=t.side,s=o%2,{min:r,max:u}=i,[a,f]=function(e,l,t,n){let i,o=ge[e];if(n>0){let s=o._space=o.space(k,e,l,t,n);i=$t(l,t,o._incrs=o.incrs(k,e,l,t,n,s),n,s)}else i=[0,0];return o._found=i}(n,r,u,0==s?Al:Yl);if(0==f)return;let c=t._splits=t.splits(k,n,r,u,a,f,2==i.distr),h=2==i.distr?c.map((e=>un[e])):c,d=2==i.distr?un[c[1]]-un[c[0]]:a,p=t._values=t.values(k,t.filter(k,h,n,f,d),n,f,d);t._rotate=2==o?t.rotate(k,p,n,f):0;let m=t._size;t._size=ie(t.size(k,p,n,e)),null!=m&&t._size!=m&&(l=!1)})),l}function Mn(e){let l=!0;return Pt.forEach(((t,n)=>{let i=t(k,n,zt,e);i!=At[n]&&(l=!1),At[n]=i})),l}function Sn(e){de.forEach(((l,t)=>{t>0&&(l._paths=null,e&&(1==M?(l.min=null,l.max=null):l.facets.forEach((e=>{e.min=null,e.max=null}))))}))}let En,Tn,zn,Dn,Pn,An,Wn,Yn,Cn,Fn,Hn,Rn,Gn=!1,In=!1,On=[];function Ln(){In=!1;for(let e=0;On.length>e;e++)zi(...On[e]);On.length=0}function Nn(){Gn||(je(jn),Gn=!0)}function jn(){if(et&&(function(){for(let e in ve){let l=ve[e];null==Be[e]&&(null==l.min||null!=Be[Me]&&l.auto(k,an))&&(Be[e]=mn)}for(let e in ve){let l=ve[e];null==Be[e]&&null!=l.from&&null!=Be[l.from]&&(Be[e]=mn)}null!=Be[Me]&&Sn(!0);let e={};for(let l in Be){let t=Be[l];if(null!=t){let n=e[l]=Oe(ve[l],Re);if(null!=t.min)Le(n,t);else if(l!=Me||2==M)if(0==Wt&&null==n.from){let e=n.range(k,null,null,l);n.min=e[0],n.max=e[1]}else n.min=he,n.max=-he}}if(Wt>0){de.forEach(((l,t)=>{if(1==M){let n=l.scale,i=Be[n];if(null==i)return;let o=e[n];if(0==t){let e=o.range(k,o.min,o.max,n);o.min=e[0],o.max=e[1],Yt=O(o.min,g[0]),Ft=O(o.max,g[0]),Ft-Yt>1&&(o.min>g[0][Yt]&&Yt++,g[0][Ft]>o.max&&Ft--),l.min=un[Yt],l.max=un[Ft]}else l.show&&l.auto&&pn(o,i,l,g[t],l.sorted);l.idxs[0]=Yt,l.idxs[1]=Ft}else if(t>0&&l.show&&l.auto){let[n,i]=l.facets,o=n.scale,s=i.scale,[r,u]=g[t],a=e[o],f=e[s];null!=a&&pn(a,Be[o],n,r,n.sorted),null!=f&&pn(f,Be[s],i,u,i.sorted),l.min=i.min,l.max=i.max}}));for(let l in e){let t=e[l],n=Be[l];if(null==t.from&&(null==n||null==n.min)){let e=t.range(k,t.min==he?null:t.min,t.max==-he?null:t.max,l);t.min=e[0],t.max=e[1]}}}for(let l in e){let t=e[l];if(null!=t.from){let n=e[t.from];if(null==n.min)t.min=t.max=null;else{let e=t.range(k,n.min,n.max,l);t.min=e[0],t.max=e[1]}}}let l={},t=!1;for(let n in e){let i=e[n],o=ve[n];if(o.min!=i.min||o.max!=i.max){o.min=i.min,o.max=i.max;let e=o.distr;o._min=3==e?ae(o.min):4==e?ce(o.min,o.asinh):100==e?o.fwd(o.min):o.min,o._max=3==e?ae(o.max):4==e?ce(o.max,o.asinh):100==e?o.fwd(o.max):o.max,l[n]=t=!0}}if(t){de.forEach(((e,t)=>{2==M?t>0&&l.y&&(e._paths=null):l[e.scale]&&(e._paths=null)}));for(let e in l)rt=!0,zi("setScale",e);xt.show&&xt.left>=0&&(at=ht=!0)}for(let e in Be)Be[e]=null}(),et=!1),rt&&(function(){let e=!1,l=0;for(;!e;){l++;let t=yn(l),n=Mn(l);e=l==gt||t&&n,e||(pt(k.width,k.height),lt=!0)}}(),rt=!1),lt){if(T(X,s,Cl),T(X,i,Fl),T(X,t,Al),T(X,n,Yl),T(Z,s,Cl),T(Z,i,Fl),T(Z,t,Al),T(Z,n,Yl),T(K,t,Dl),T(K,n,Pl),V.width=ne(Dl*y),V.height=ne(Pl*y),ge.forEach((({_el:l,_show:t,_size:n,_pos:i,side:o})=>{if(null!=l)if(t){let t=o%2==1;T(l,t?"left":"top",i-(3===o||0===o?n:0)),T(l,t?"width":"height",n),T(l,t?"top":"left",t?Fl:Cl),T(l,t?"height":"width",t?Yl:Al),E(l,e)}else S(l,e)})),Xt=Zt=Qt=ln=tn=nn=on=sn=en=null,rn=1,di(!0),Cl!=Hl||Fl!=Rl||Al!=Gl||Yl!=Bl){Sn(!1);let e=Al/Gl,l=Yl/Bl;if(xt.show&&!at&&xt.left>=0){xt.left*=e,xt.top*=l,zn&&A(zn,ne(xt.left),0,Al,Yl),Dn&&A(Dn,0,ne(xt.top),Al,Yl);for(let t=0;yt.length>t;t++){let n=yt[t];null!=n&&(Mt[t]*=e,St[t]*=l,A(n,ie(Mt[t]),ie(St[t]),Al,Yl))}}if(qn.show&&!ft&&qn.left>=0&&qn.width>0){qn.left*=e,qn.width*=e,qn.top*=l,qn.height*=l;for(let e in gi)T(Kn,e,qn[e])}Hl=Cl,Rl=Fl,Gl=Al,Bl=Yl}zi("setSize"),lt=!1}Dl>0&&Pl>0&&($.clearRect(0,0,V.width,V.height),zi("drawClear"),De.forEach((e=>e())),zi("draw")),qn.show&&ft&&(Xn(qn),ft=!1),xt.show&&at&&(ci(null,!0,!1),at=!1),Qe.show&&Qe.live&&ht&&(ai(),ht=!1),R||(R=!0,k.status=1,zi("ready")),an=!1,Gn=!1}function Un(e,l){let t=ve[e];if(null==t.from){if(0==Wt){let n=t.range(k,l.min,l.max,e);l.min=n[0],l.max=n[1]}if(l.min>l.max){let e=l.min;l.min=l.max,l.max=e}if(Wt>1&&null!=l.min&&null!=l.max&&1e-16>l.max-l.min)return;e==Me&&2==t.distr&&Wt>0&&(l.min=O(l.min,g[0]),l.max=O(l.max,g[0]),l.min==l.max&&l.max++),Be[e]=l,et=!0,Nn()}}k.batch=function(e,l=!1){Gn=!0,In=l,e(k),jn(),l&&On.length>0&&queueMicrotask(Ln)},k.redraw=(e,l)=>{rt=l||!1,!1!==e?Zn(Me,Ge.min,Ge.max):Nn()},k.setScale=Un;let Bn=!1;const Vn=xt.drag;let $n=Vn.x,Jn=Vn.y;xt.show&&(xt.x&&(En=D("u-cursor-x",Z)),xt.y&&(Tn=D("u-cursor-y",Z)),0==Ge.ori?(zn=En,Dn=Tn):(zn=Tn,Dn=En),Hn=xt.left,Rn=xt.top);const qn=k.select=Le({show:!0,over:!0,left:0,width:0,top:0,height:0},u.select),Kn=qn.show?D("u-select",qn.over?Z:X):null;function Xn(e,l){if(qn.show){for(let l in e)qn[l]=e[l],l in gi&&T(Kn,l,e[l]);!1!==l&&zi("setSelect")}}function Zn(e,l,t){Un(e,{min:l,max:t})}function Qn(l,t,n,i){null!=t.focus&&function(e){if(e!=ti){let l=null==e,t=1!=bt.alpha;de.forEach(((n,i)=>{if(1==M||i>0){let o=l||0==i||i==e;n._focus=l?null:o,t&&function(e,l){de[e].alpha=l,xt.show&&yt[e]&&(yt[e].style.opacity=l),el&&ul[e]&&(ul[e].style.opacity=l)}(i,o?1:bt.alpha)}})),ti=e,t&&Nn()}}(l),null!=t.show&&de.forEach(((n,i)=>{0>=i||l!=i&&null!=l||(n.show=t.show,function(l){let t=el?ul[l]:null;de[l].show?t&&E(t,e):(t&&S(t,e),A(kt?yt[0]:yt[l],-10,-10,Al,Yl))}(i),2==M?(Zn(n.facets[0].scale,null,null),Zn(n.facets[1].scale,null,null)):Zn(n.scale,null,null),Nn())})),!1!==n&&zi("setSeries",l,t),i&&Yi("setSeries",k,l,t)}let ei,li,ti;k.setSelect=Xn,k.setSeries=Qn,k.addBand=function(e,l){e.fill=me(e.fill||null),e.dir=q(e.dir,-1),ke.splice(l=null==l?ke.length:l,0,e)},k.setBand=function(e,l){Le(ke[e],l)},k.delBand=function(e){null==e?ke.length=0:ke.splice(e,1)};const ni={focus:!0};function ii(e,l,t){let n=ve[l];t&&(e=e/y-(1==n.ori?Fl:Cl));let i=Al;1==n.ori&&(i=Yl,e=i-e),-1==n.dir&&(e=i-e);let o=n._min,s=o+e/i*(n._max-o),r=n.distr;return 3==r?re(10,s):4==r?((e,l=1)=>Q.sinh(e)*l)(s,n.asinh):100==r?n.bwd(s):s}function oi(e,l){T(Kn,s,qn.left=e),T(Kn,t,qn.width=l)}function si(e,l){T(Kn,i,qn.top=e),T(Kn,n,qn.height=l)}el&&vt&&gl(p,tl,(e=>{xt._lock||(wt(e),null!=ti&&Qn(null,ni,!0,Pi.setSeries))})),k.valToIdx=e=>O(e,g[0]),k.posToIdx=function(e,l){return O(ii(e,Me,l),g[0],Yt,Ft)},k.posToVal=ii,k.valToPos=(e,l,t)=>0==ve[l].ori?W(e,ve[l],t?Jl:Al,t?Vl:0):C(e,ve[l],t?ql:Yl,t?$l:0),k.setCursor=(e,l,t)=>{Hn=e.left,Rn=e.top,ci(null,l,t)};let ri=0==Ge.ori?oi:si,ui=1==Ge.ori?oi:si;function ai(e,l){if(null!=e&&(e.idxs?e.idxs.forEach(((e,l)=>{Xe[l]=e})):(e=>void 0===e)(e.idx)||Xe.fill(e.idx),Qe.idx=Xe[0]),el&&Qe.live){for(let e=0;de.length>e;e++)(e>0||1==M&&!fl)&&fi(e,Xe[e]);!function(){if(el&&Qe.live)for(let e=2==M?1:0;de.length>e;e++){if(0==e&&fl)continue;let l=Qe.values[e],t=0;for(let n in l)al[e][t++].firstChild.nodeValue=l[n]}}()}ht=!1,!1!==l&&zi("setLegend")}function fi(e,l){let t,n=de[e],i=0==e&&2==Ie?un:g[e];fl?t=n.values(k,e,l)??cl:(t=n.value(k,null==l?null:i[l],e,l),t=null==t?cl:{_:t}),Qe.values[e]=t}function ci(e,l,t){let n;Cn=Hn,Fn=Rn,[Hn,Rn]=xt.move(k,Hn,Rn),xt.left=Hn,xt.top=Rn,xt.show&&(zn&&A(zn,ne(Hn),0,Al,Yl),Dn&&A(Dn,0,ne(Rn),Al,Yl)),ei=he,li=null;let i=0==Ge.ori?Al:Yl,o=1==Ge.ori?Al:Yl;if(0>Hn||0==Wt||Yt>Ft){n=xt.idx=null;for(let e=0;de.length>e;e++){let l=yt[e];null!=l&&A(l,-10,-10,Al,Yl)}vt&&Qn(null,ni,!0,null==e&&Pi.setSeries),Qe.live&&(Xe.fill(n),ht=!0)}else{let e,l,t;1==M&&(e=0==Ge.ori?Hn:Rn,l=ii(e,Me),n=xt.idx=O(l,g[0],Yt,Ft),t=Ne(g[0][n],Ge,i,0));let s=-10,r=-10,u=0,a=0,f=!0,c="",h="";for(let e=2==M?1:0;de.length>e;e++){let d=de[e],p=Xe[e],m=null==p?null:1==M?g[e][p]:g[e][1][p],x=xt.dataIdx(k,e,n,l),w=null==x?null:1==M?g[e][x]:g[e][1][x];ht=ht||w!=m||x!=p,Xe[e]=x;let _=x==n?t:Ne(1==M?g[0][x]:g[e][0][x],Ge,i,0);if(e>0&&d.show){let l=null==w?-10:Ue(w,1==M?ve[d.scale]:ve[d.facets[1].scale],o,0);if(vt&&null!=w){let t=1==Ge.ori?Hn:Rn,n=le(bt.dist(k,e,x,l,t));if(ei>n){let l=bt.bias;if(0!=l){let i=ii(t,d.scale),o=0>i?-1:1;o!=(0>w?-1:1)||(1==o?1==l?i>w:w>i:1==l?w>i:i>w)||(ei=n,li=e)}else ei=n,li=e}}if(ht||kt){let t,n;0==Ge.ori?(t=_,n=l):(t=l,n=_);let i,o,d,p,m,g,x=!0,w=_t.bbox;if(null!=w){x=!1;let l=w(k,e);d=l.left,p=l.top,i=l.width,o=l.height}else d=t,p=n,i=o=_t.size(k,e);if(g=_t.fill(k,e),m=_t.stroke(k,e),kt)e!=li||ei>bt.prox||(s=d,r=p,u=i,a=o,f=x,c=g,h=m);else{let l=yt[e];null!=l&&(Mt[e]=d,St[e]=p,F(l,i,o,x),Y(l,g,m),A(l,ie(d),ie(p),Al,Yl))}}}}if(kt){let e=bt.prox;if(ht||(null==ti?e>=ei:ei>e||li!=ti)){let e=yt[0];Mt[0]=s,St[0]=r,F(e,u,a,f),Y(e,c,h),A(e,ie(s),ie(r),Al,Yl)}}}if(qn.show&&Bn)if(null!=e){let[l,t]=Pi.scales,[n,s]=Pi.match,[r,u]=e.cursor.sync.scales,a=e.cursor.drag;if($n=a._x,Jn=a._y,$n||Jn){let a,f,c,h,d,{left:p,top:m,width:g,height:x}=e.select,w=e.scales[r].ori,_=e.posToVal,b=null!=l&&n(l,r),v=null!=t&&s(t,u);b&&$n?(0==w?(a=p,f=g):(a=m,f=x),c=ve[l],h=Ne(_(a,r),c,i,0),d=Ne(_(a+f,r),c,i,0),ri(oe(h,d),le(d-h))):ri(0,i),v&&Jn?(1==w?(a=p,f=g):(a=m,f=x),c=ve[t],h=Ue(_(a,u),c,o,0),d=Ue(_(a+f,u),c,o,0),ui(oe(h,d),le(d-h))):ui(0,o)}else xi()}else{let e=le(Cn-Pn),l=le(Fn-An);if(1==Ge.ori){let t=e;e=l,l=t}$n=Vn.x&&e>=Vn.dist,Jn=Vn.y&&l>=Vn.dist;let t,n,s=Vn.uni;null!=s?$n&&Jn&&($n=e>=s,Jn=l>=s,$n||Jn||(l>e?Jn=!0:$n=!0)):Vn.x&&Vn.y&&($n||Jn)&&($n=Jn=!0),$n&&(0==Ge.ori?(t=Wn,n=Hn):(t=Yn,n=Rn),ri(oe(t,n),le(n-t)),Jn||ui(0,o)),Jn&&(1==Ge.ori?(t=Wn,n=Hn):(t=Yn,n=Rn),ui(oe(t,n),le(n-t)),$n||ri(0,i)),$n||Jn||(ri(0,0),ui(0,0))}if(Vn._x=$n,Vn._y=Jn,null==e){if(t){if(null!=Ai){let[e,l]=Pi.scales;Pi.values[0]=null!=e?ii(0==Ge.ori?Hn:Rn,e):null,Pi.values[1]=null!=l?ii(1==Ge.ori?Hn:Rn,l):null}Yi(f,k,Hn,Rn,Al,Yl,n)}if(vt){let e=t&&Pi.setSeries,l=bt.prox;null==ti?ei>l||Qn(li,ni,!0,e):ei>l?Qn(null,ni,!0,e):li!=ti&&Qn(li,ni,!0,e)}}ht&&(Qe.idx=n,ai()),!1!==l&&zi("setCursor")}k.setLegend=ai;let hi=null;function di(e=!1){e?hi=null:(hi=Z.getBoundingClientRect(),zi("syncRect",hi))}function pi(e,l,t,n,i,o){xt._lock||Bn&&null!=e&&0==e.movementX&&0==e.movementY||(mi(e,l,t,n,i,o,0,!1,null!=e),null!=e?ci(null,!0,!0):ci(l,!0,!1))}function mi(e,l,t,n,i,o,s,r,u){if(null==hi&&di(!1),wt(e),null!=e)t=e.clientX-hi.left,n=e.clientY-hi.top;else{if(0>t||0>n)return Hn=-10,void(Rn=-10);let[e,s]=Pi.scales,r=l.cursor.sync,[u,a]=r.values,[f,c]=r.scales,[h,d]=Pi.match,p=l.axes[0].side%2==1,m=0==Ge.ori?Al:Yl,g=1==Ge.ori?Al:Yl,x=p?o:i,w=p?i:o,_=p?n:t,b=p?t:n;if(t=null!=f?h(e,f)?H(u,ve[e],m,0):-10:m*(_/x),n=null!=c?d(s,c)?H(a,ve[s],g,0):-10:g*(b/w),1==Ge.ori){let e=t;t=n,n=e}}u&&(t>1&&Al-1>t||(t=ye(t,Al)),n>1&&Yl-1>n||(n=ye(n,Yl))),r?(Pn=t,An=n,[Wn,Yn]=xt.move(k,t,n)):(Hn=t,Rn=n)}Object.defineProperty(k,"rect",{get:()=>(null==hi&&di(!1),hi)});const gi={width:0,height:0,left:0,top:0};function xi(){Xn(gi,!1)}let wi,_i,bi,vi;function ki(e,l,t,n,i,o){Bn=!0,$n=Jn=Vn._x=Vn._y=!1,mi(e,l,t,n,i,o,0,!0,!1),null!=e&&(gl(h,b,yi,!1),Yi(c,k,Wn,Yn,Al,Yl,null));let{left:s,top:r,width:u,height:a}=qn;wi=s,_i=r,bi=u,vi=a,xi()}function yi(e,l,t,n,i,o){Bn=Vn._x=Vn._y=!1,mi(e,l,t,n,i,o,0,!1,!0);let{left:s,top:r,width:u,height:a}=qn,f=u>0||a>0,c=wi!=s||_i!=r||bi!=u||vi!=a;if(f&&c&&Xn(qn),Vn.setScale&&f&&c){let e=s,l=u,t=r,n=a;if(1==Ge.ori&&(e=r,l=a,t=s,n=u),$n&&Zn(Me,ii(e,Me),ii(e+l,Me)),Jn)for(let e in ve){let l=ve[e];e!=Me&&null==l.from&&l.min!=he&&Zn(e,ii(t+n,e),ii(t,e))}xi()}else xt.lock&&(xt._lock=!xt._lock,ci(null,!0,!1));null!=e&&(Sl(h,b),Yi(h,k,Hn,Rn,Al,Yl,null))}function Mi(e){xt._lock||(wt(e),cn(),xi(),null!=e&&Yi(m,k,Hn,Rn,Al,Yl,null))}function Si(){ge.forEach(qt),dt(k.width,k.height,!0)}G(x,v,Si);const Ei={};Ei.mousedown=ki,Ei.mousemove=pi,Ei.mouseup=yi,Ei.dblclick=Mi,Ei.setSeries=(e,l,t,n)=>{-1!=(t=(0,Pi.match[2])(k,l,t))&&Qn(t,n,!0,!1)},xt.show&&(gl(c,Z,ki),gl(f,Z,pi),gl(d,Z,(e=>{wt(e),di(!1)})),gl(p,Z,(function(e){if(xt._lock)return;wt(e);let l=Bn;if(Bn){let e,l,t=!0,n=!0,i=10;0==Ge.ori?(e=$n,l=Jn):(e=Jn,l=$n),e&&l&&(t=i>=Hn||Hn>=Al-i,n=i>=Rn||Rn>=Yl-i),e&&t&&(Hn=Wn>Hn?0:Al),l&&n&&(Rn=Yn>Rn?0:Yl),ci(null,!0,!0),Bn=!1}Hn=-10,Rn=-10,ci(null,!0,!0),l&&(Bn=l)})),gl(m,Z,Mi),Ct.add(k),k.syncRect=di);const Ti=k.hooks=u.hooks||{};function zi(e,l,t){In?On.push([e,l,t]):e in Ti&&Ti[e].forEach((e=>{e.call(null,k,l,t)}))}(u.plugins||[]).forEach((e=>{for(let l in e.hooks)Ti[l]=(Ti[l]||[]).concat(e.hooks[l])}));const Di=(e,l,t)=>t,Pi=Le({key:null,setSeries:!1,filters:{pub:_e,sub:_e},scales:[Me,de[1]?de[1].scale:null],match:[be,be,Di],values:[null,null]},xt.sync);2==Pi.match.length&&Pi.match.push(Di),xt.sync=Pi;const Ai=Pi.key,Wi=ut(Ai);function Yi(e,l,t,n,i,o,s){Pi.filters.pub(e,l,t,n,i,o,s)&&Wi.pub(e,l,t,n,i,o,s)}function Ci(){zi("init",u,g),fn(g||u.data,!1),Be[Me]?Un(Me,Be[Me]):cn(),ft=qn.show&&(qn.width>0||qn.height>0),at=ht=!0,dt(u.width,u.height)}return Wi.sub(k),k.pub=function(e,l,t,n,i,o,s){Pi.filters.sub(e,l,t,n,i,o,s)&&Ei[e](null,l,t,n,i,o,s)},k.destroy=function(){Wi.unsub(k),Ct.delete(k),ml.clear(),I(x,v,Si),L.remove(),tl?.remove(),zi("destroy")},de.forEach(Tt),ge.forEach((function(e,l){if(e._show=e.show,e.show){let t=ve[e.scale];null==t&&(e.scale=e.side%2?de[1].scale:Me,t=ve[e.scale]);let n=t.time;e.size=me(e.size),e.space=me(e.space),e.rotate=me(e.rotate),Ye(e.incrs)&&e.incrs.forEach((e=>{!Te.has(e)&&Te.set(e,ze(e))})),e.incrs=me(e.incrs||(2==t.distr?il:n?1==fe?xl:bl:ol)),e.splits=me(e.splits||(n&&1==t.distr?Je:3==t.distr?jl:4==t.distr?Ul:Nl)),e.stroke=me(e.stroke),e.grid.stroke=me(e.grid.stroke),e.ticks.stroke=me(e.ticks.stroke),e.border.stroke=me(e.border.stroke);let i=e.values;e.values=Ye(i)&&!Ye(i[0])?me(i):n?Ye(i)?Ml(Ve,yl(i,$e)):Fe(i)?function(e,l){let t=Ze(l);return(l,n)=>n.map((l=>t(e(l))))}(Ve,i):i||qe:i||Ll,e.filter=me(e.filter||(3>t.distr||10!=t.log?3==t.distr&&2==t.log?Xl:xe:Kl)),e.font=Jt(e.font),e.labelFont=Jt(e.labelFont),e._size=e.size(k,null,l,0),e._space=e._rotate=e._incrs=e._found=e._splits=e._values=null,e._size>0&&(zt[l]=!0,e._el=D("u-axis",K))}})),_?_ instanceof HTMLElement?(_.appendChild(L),Ci()):_(k,Ci):Ci(),k}Kt.assign=Le,Kt.fmtNum=Z,Kt.rangeNum=J,Kt.rangeLog=N,Kt.rangeAsinh=j,Kt.orient=at,Kt.pxRatio=y,Kt.join=function(e,l){if(function(e){let l=e[0][0],t=l.length;for(let n=1;e.length>n;n++){let i=e[n][0];if(i.length!=t)return!1;if(i!=l)for(let e=0;t>e;e++)if(i[e]!=l[e])return!1}return!0}(e)){let l=e[0].slice();for(let t=1;e.length>t;t++)l.push(...e[t].slice(1));return function(e,l=100){const t=e.length;if(1>=t)return!0;let n=0,i=t-1;for(;i>=n&&null==e[n];)n++;for(;i>=n&&null==e[i];)i--;if(n>=i)return!0;const o=se(1,te((i-n+1)/l));for(let l=e[n],t=n+o;i>=t;t+=o){const n=e[t];if(null!=n){if(l>=n)return!1;l=n}}return!0}(l[0])||(l=function(e){let l=e[0],t=l.length,n=Array(t);for(let e=0;n.length>e;e++)n[e]=e;n.sort(((e,t)=>l[e]-l[t]));let i=[];for(let l=0;e.length>l;l++){let o=e[l],s=Array(t);for(let e=0;t>e;e++)s[e]=o[n[e]];i.push(s)}return i}(l)),l}let t=new Set;for(let l=0;e.length>l;l++){let n=e[l][0],i=n.length;for(let e=0;i>e;e++)t.add(n[e])}let n=[Array.from(t).sort(((e,l)=>e-l))],i=n[0].length,o=new Map;for(let e=0;i>e;e++)o.set(n[0][e],e);for(let t=0;e.length>t;t++){let s=e[t],r=s[0];for(let e=1;s.length>e;e++){let u=s[e],a=Array(i).fill(void 0),f=l?l[t][e]:1,c=[];for(let e=0;u.length>e;e++){let l=u[e],t=o.get(r[e]);null===l?0!=f&&(a[t]=l,2==f&&c.push(t)):a[t]=l}Ne(a,c,i),n.push(a)}}return n},Kt.fmtDate=Ze,Kt.tzDate=function(e,l){let t;return"UTC"==l||"Etc/UTC"==l?t=new Date(+e+6e4*e.getTimezoneOffset()):l==Qe?t=e:(t=new Date(e.toLocaleString("en-US",{timeZone:l})),t.setMilliseconds(e.getMilliseconds())),t},Kt.sync=ut;{Kt.addGap=function(e,l,t){let n=e[e.length-1];n&&n[0]==l?n[1]=t:e.push([l,t])},Kt.clipGaps=dt;let e=Kt.paths={points:Tt};e.linear=At,e.stepped=function(e){const l=q(e.align,1),t=q(e.ascDesc,!1),n=q(e.alignGaps,0),i=q(e.extend,!1);return(e,o,s,r)=>at(e,o,((u,a,f,c,h,d,p,m,g,x,w)=>{let _=u.pxRound,{left:b,width:v}=e.bbox,k=e=>_(d(e,c,x,m)),M=e=>_(p(e,h,w,g)),S=0==c.ori?_t:bt;const E={stroke:new Path2D,fill:null,clip:null,band:null,gaps:null,flags:1},T=E.stroke,z=c.dir*(0==c.ori?1:-1);s=L(f,s,r,1),r=L(f,s,r,-1);let D=M(f[1==z?s:r]),P=k(a[1==z?s:r]),A=P,W=P;i&&-1==l&&(W=b,S(T,W,D)),S(T,P,D);for(let e=1==z?s:r;e>=s&&r>=e;e+=z){let t=f[e];if(null==t)continue;let n=k(a[e]),i=M(t);1==l?S(T,n,D):S(T,A,i),S(T,n,i),D=i,A=n}let Y=A;i&&1==l&&(Y=b+v,S(T,Y,D));let[C,F]=ft(e,o);if(null!=u.fill||0!=C){let l=E.fill=new Path2D(T),t=M(u.fillTo(e,o,u.min,u.max,C));S(l,Y,t),S(l,W,t)}if(!u.spanGaps){let i=[];i.push(...pt(a,f,s,r,z,k,n));let h=u.width*y/2,d=t||1==l?h:-h,p=t||-1==l?-h:h;i.forEach((e=>{e[0]+=d,e[1]+=p})),E.gaps=i=u.gaps(e,o,s,r,i),E.clip=dt(i,c.ori,m,g,x,w)}return 0!=F&&(E.band=2==F?[ht(e,o,s,r,T,-1),ht(e,o,s,r,T,1)]:ht(e,o,s,r,T,F)),E}))},e.bars=function(e){const l=q((e=e||Pe).size,[.6,he,1]),t=e.align||0,n=e.gap||0;let i=e.radius;i=null==i?[0,0]:"number"==typeof i?[i,0]:i;const o=me(i),s=1-l[0],r=q(l[1],he),u=q(l[2],1),a=q(e.disp,Pe),f=q(e.each,(()=>{})),{fill:c,stroke:h}=a;return(e,l,i,d)=>at(e,l,((p,m,g,x,w,_,b,v,k,M,S)=>{let E,T,z=p.pxRound,D=t,P=n*y,A=r*y,W=u*y;0==x.ori?[E,T]=o(e,l):[T,E]=o(e,l);const Y=x.dir*(0==x.ori?1:-1);let C,F,H,R=0==x.ori?vt:kt,G=0==x.ori?f:(e,l,t,n,i,o,s)=>{f(e,l,t,i,n,s,o)},I=q(e.bands,Ae).find((e=>e.series[0]==l)),O=p.fillTo(e,l,p.min,p.max,null!=I?I.dir:0),L=z(b(O,w,S,k)),N=M,j=z(p.width*y),U=!1,B=null,V=null,$=null,J=null;null==c||0!=j&&null==h||(U=!0,B=c.values(e,l,i,d),V=new Map,new Set(B).forEach((e=>{null!=e&&V.set(e,new Path2D)})),j>0&&($=h.values(e,l,i,d),J=new Map,new Set($).forEach((e=>{null!=e&&J.set(e,new Path2D)}))));let{x0:K,size:X}=a;if(null!=K&&null!=X){D=1,m=K.values(e,l,i,d),2==K.unit&&(m=m.map((l=>e.posToVal(v+l*M,x.key,!0))));let t=X.values(e,l,i,d);F=2==X.unit?t[0]*M:_(t[0],x,M,v)-_(0,x,M,v),N=Wt(m,g,_,x,M,v,N),H=N-F+P}else N=Wt(m,g,_,x,M,v,N),H=N*s+P,F=N-H;1>H&&(H=0),F/2>j||(j=0),5>H&&(z=ge);let Z=H>0;F=z(pe(N-H-(Z?j:0),W,A)),C=(0==D?F/2:D==Y?0:F)-D*Y*((0==D?P/2:0)+(Z?j/2:0));const Q={stroke:null,fill:null,clip:null,band:null,gaps:null,flags:0},ee=U?null:new Path2D;let le=null;if(null!=I)le=e.data[I.series[1]];else{let{y0:t,y1:n}=a;null!=t&&null!=n&&(g=n.values(e,l,i,d),le=t.values(e,l,i,d))}let ne=E*F,ie=T*F;for(let t=1==Y?i:d;t>=i&&d>=t;t+=Y){let n=g[t];if(null==n)continue;if(null!=le){let e=le[t]??0;if(n-e==0)continue;L=b(e,w,S,k)}let i=_(2!=x.distr||null!=a?m[t]:t,x,M,v),o=b(q(n,O),w,S,k),s=z(i-C),r=z(se(o,L)),u=z(oe(o,L)),f=r-u;if(null!=n){let i=0>n?ie:ne,o=0>n?ne:ie;U?(j>0&&null!=$[t]&&R(J.get($[t]),s,u+te(j/2),F,se(0,f-j),i,o),null!=B[t]&&R(V.get(B[t]),s,u+te(j/2),F,se(0,f-j),i,o)):R(ee,s,u+te(j/2),F,se(0,f-j),i,o),G(e,l,t,s-j/2,u,F+j,f)}}return j>0?Q.stroke=U?J:ee:U||(Q._fill=0==p.width?p._fill:p._stroke??p._fill,Q.width=0),Q.fill=U?V:ee,Q}))},e.spline=function(e){return function(e,l){const t=q(l?.alignGaps,0);return(l,n,i,o)=>at(l,n,((s,r,u,a,f,c,h,d,p,m,g)=>{let x,w,_,b=s.pxRound,v=e=>b(c(e,a,m,d)),k=e=>b(h(e,f,g,p));0==a.ori?(x=xt,_=_t,w=St):(x=wt,_=bt,w=Et);const y=a.dir*(0==a.ori?1:-1);i=L(u,i,o,1),o=L(u,i,o,-1);let M=v(r[1==y?i:o]),S=M,E=[],T=[];for(let e=1==y?i:o;e>=i&&o>=e;e+=y)if(null!=u[e]){let l=v(r[e]);E.push(S=l),T.push(k(u[e]))}const z={stroke:e(E,T,x,_,w,b),fill:null,clip:null,band:null,gaps:null,flags:1},D=z.stroke;let[P,A]=ft(l,n);if(null!=s.fill||0!=P){let e=z.fill=new Path2D(D),t=k(s.fillTo(l,n,s.min,s.max,P));_(e,S,t),_(e,M,t)}if(!s.spanGaps){let e=[];e.push(...pt(r,u,i,o,y,v,t)),z.gaps=e=s.gaps(l,n,i,o,e),z.clip=dt(e,a.ori,d,p,m,g)}return 0!=A&&(z.band=2==A?[ht(l,n,i,o,D,-1),ht(l,n,i,o,D,1)]:ht(l,n,i,o,D,A)),z}))}(Yt,e)}}return Kt}(); +var uPlot=function(){"use strict";const l=(new Intl.DateTimeFormat).resolvedOptions().locale;function e(l,e,t,n){let i;t=t||0;let o=2147483647>=(n=n||e.length-1);for(;n-t>1;)i=o?t+n>>1:m((t+n)/2),l>e[i]?t=i:n=i;return l-e[t]>e[n]-l?n:t}function t(l,e,t,n){for(let i=1==n?e:t;i>=e&&t>=i;i+=n)if(null!=l[i])return i;return-1}function n(l,e,t,n){let i=k(l),o=k(e);l==e&&(-1==i?(l*=t,e/=t):(l/=t,e*=t));let s=10==t?b:y,r=1==o?x:m,u=(1==i?m:x)(s(p(l))),a=r(s(p(e))),f=v(t,u),c=v(t,a);return 10==t&&(0>u&&(f=N(f,-u)),0>a&&(c=N(c,-a))),n||2==t?(l=f*i,e=c*o):(l=L(l,f),e=O(e,c)),[l,e]}function i(l,e,t,i){let o=n(l,e,t,i);return 0==l&&(o[0]=0),0==e&&(o[1]=0),o}const o=.1,s={mode:3,pad:o},r={pad:0,soft:null,mode:0},u={min:r,max:r};function a(l,e,t,n){return q(t)?c(l,e,t):(r.pad=t,r.soft=n?0:null,r.mode=n?3:0,c(l,e,u))}function f(l,e){return null==l?e:l}function c(l,e,t){let n=t.min,i=t.max,o=f(n.pad,0),s=f(i.pad,0),r=f(n.hard,-E),u=f(i.hard,E),a=f(n.soft,E),c=f(i.soft,-E),h=f(n.mode,0),d=f(i.mode,0),g=e-l,x=b(g),k=_(p(l),p(e)),y=b(k),S=p(y-x);(1e-24>g||S>10)&&(g=0,0!=l&&0!=e||(g=1e-24,2==h&&a!=E&&(o=0),2==d&&c!=-E&&(s=0)));let T=g||k||1e3,z=b(T),P=v(10,m(z)),D=N(L(l-T*(0==g?0==l?.1:1:o),P/10),24),A=a>l||1!=h&&(3!=h||D>a)&&(2!=h||a>D)?E:a,C=_(r,A>D&&l>=A?A:w(A,D)),M=N(O(e+T*(0==g?0==e?.1:1:s),P/10),24),I=e>c||1!=d&&(3!=d||c>M)&&(2!=d||M>c)?-E:c,R=w(u,M>I&&I>=e?I:_(I,M));return C==R&&0==C&&(R=100),[C,R]}const h=Math,d=h.PI,p=h.abs,m=h.floor,g=h.round,x=h.ceil,w=h.min,_=h.max,v=h.pow,k=h.sign,b=h.log10,y=h.log2,S=(l,e=1)=>h.asinh(l/e),E=1/0;function T(l){return 1+(0|b((l^l>>31)-(l>>31)))}function z(l,e,t){return w(_(l,e),t)}function P(l){return"function"==typeof l?l:()=>l}const D=l=>l,A=(l,e)=>e,C=()=>null,M=()=>!0,I=(l,e)=>l==e,R=/\.\d*?(?=9{6,}|0{6,})/gm,F=l=>{if(W(l)||j.has(l))return l;const e=""+l,t=e.match(R);if(null==t)return l;let n=t[0].length-1;if(-1!=e.indexOf("e-")){let[l,t]=e.split("e");return+`${F(l)}e${t}`}return N(l,n)};function G(l,e){return F(N(F(l/e))*e)}function O(l,e){return F(x(F(l/e))*e)}function L(l,e){return F(m(F(l/e))*e)}function N(l,e=0){if(W(l))return l;let t=10**e;return g(l*t*(1+Number.EPSILON))/t}const j=new Map;function B(l){return((""+l).split(".")[1]||"").length}function H(l,e,t,n){let i=[],o=n.map(B);for(let s=e;t>s;s++){let e=p(s),t=N(v(l,s),e);for(let r=0;n.length>r;r++){let u=10==l?+`${n[r]}e${s}`:n[r]*t,a=(0>s?e:0)+(o[r]>s?o[r]:0),f=10==l?u:N(u,a);i.push(f),j.set(f,a)}}return i}const U={},V=[],Y=[null,null],$=Array.isArray,W=Number.isInteger;function q(l){let e=!1;if(null!=l){let t=l.constructor;e=null==t||t==Object}return e}function K(l){return null!=l&&"object"==typeof l}const X=Object.getPrototypeOf(Uint8Array),Z="__proto__";function J(l,e=q){let t;if($(l)){let n=l.find((l=>null!=l));if($(n)||e(n)){t=Array(l.length);for(let n=0;l.length>n;n++)t[n]=J(l[n],e)}else t=l.slice()}else if(l instanceof X)t=l.slice();else if(e(l)){t={};for(let n in l)n!=Z&&(t[n]=J(l[n],e))}else t=l;return t}function Q(l){let e=arguments;for(let t=1;e.length>t;t++){let n=e[t];for(let e in n)e!=Z&&(q(l[e])?Q(l[e],J(n[e])):l[e]=J(n[e]))}return l}function ll(l,e,t){for(let n,i=0,o=-1;e.length>i;i++){let s=e[i];if(s>o){for(n=s-1;n>=0&&null==l[n];)l[n--]=null;for(n=s+1;t>n&&null==l[n];)l[o=n++]=null}}}const el="undefined"==typeof queueMicrotask?l=>Promise.resolve().then(l):queueMicrotask,tl="width",nl="height",il="top",ol="bottom",sl="left",rl="right",ul="#000",al=ul+"0",fl="mousemove",cl="mousedown",hl="mouseup",dl="mouseenter",pl="mouseleave",ml="dblclick",gl="change",xl="dppxchange",wl="--",_l="u-off",vl="u-label",kl="undefined"!=typeof window,bl=kl?document:null,yl=kl?window:null;let Sl,El;function Tl(l,e){if(null!=e){let t=l.classList;!t.contains(e)&&t.add(e)}}function zl(l,e){let t=l.classList;t.contains(e)&&t.remove(e)}function Pl(l,e,t){l.style[e]=t+"px"}function Dl(l,e,t,n){let i=bl.createElement(l);return null!=e&&Tl(i,e),null!=t&&t.insertBefore(i,n),i}function Al(l,e){return Dl("div",l,e)}const Cl=new WeakMap;function Ml(l,e,t,n,i){let o="translate("+e+"px,"+t+"px)";o!=Cl.get(l)&&(l.style.transform=o,Cl.set(l,o),0>e||0>t||e>n||t>i?Tl(l,_l):zl(l,_l))}const Il=new WeakMap;function Rl(l,e,t){let n=e+t;n!=Il.get(l)&&(Il.set(l,n),l.style.background=e,l.style.borderColor=t)}const Fl=new WeakMap;function Gl(l,e,t,n){let i=e+""+t;i!=Fl.get(l)&&(Fl.set(l,i),l.style.height=t+"px",l.style.width=e+"px",l.style.marginLeft=n?-e/2+"px":0,l.style.marginTop=n?-t/2+"px":0)}const Ol={passive:!0},Ll={...Ol,capture:!0};function Nl(l,e,t,n){e.addEventListener(l,t,n?Ll:Ol)}function jl(l,e,t){e.removeEventListener(l,t,Ol)}kl&&function l(){let e=devicePixelRatio;Sl!=e&&(Sl=e,El&&jl(gl,El,l),El=matchMedia(`(min-resolution: ${Sl-.001}dppx) and (max-resolution: ${Sl+.001}dppx)`),Nl(gl,El,l),yl.dispatchEvent(new CustomEvent(xl)))}();const Bl=(new Intl.DateTimeFormat).resolvedOptions().timeZone,Hl=l=>l%1==0,Ul=[1,2,2.5,5],Vl=H(10,-32,0,Ul),Yl=H(10,0,32,Ul),$l=Yl.filter(Hl),Wl=Vl.concat(Yl),ql="\n";let Kl={year:"numeric"},Xl={month:"numeric"},Zl={month:"short"},Jl={day:"numeric"},Ql={hour:"numeric"},le={minute:"numeric"},ee={second:"numeric"},te={fractionalSecondDigits:3};const ne=null;function ie(l){let e=1e3*l,t=60*e,n=60*t,i=24*n,o=30*i,s=365*i;return[(1==l?H(10,0,3,Ul).filter(Hl):H(10,-3,0,Ul)).concat([e,5*e,10*e,15*e,30*e,t,5*t,10*t,15*t,30*t,n,2*n,3*n,4*n,6*n,8*n,12*n,i,2*i,3*i,4*i,5*i,6*i,7*i,8*i,9*i,10*i,15*i,o,2*o,3*o,4*o,6*o,s,2*s,5*s,10*s,25*s,50*s,100*s]),[[s,{...Kl},ne,ne,ne,ne,ne,ne,1],[28*i,{...Zl},{...Kl},ne,ne,ne,ne,ne,1],[i,{...Xl,...Jl},{...Kl},ne,ne,ne,ne,ne,1],[n,{...Ql},{...Kl,...Xl,...Jl},ne,{...Xl,...Jl},ne,ne,ne,1],[t,{...Ql,...le},{...Kl,...Xl,...Jl},ne,{...Xl,...Jl},ne,ne,ne,1],[e,{...ee},{...Kl,...Xl,...Jl,...Ql,...le},ne,{...Xl,...Jl,...Ql,...le},ne,{...Ql,...le},ne,1],[l,{...ee,...te},{...Kl,...Xl,...Jl,...Ql,...le},ne,{...Xl,...Jl,...Ql,...le},ne,{...Ql,...le},ne,1]],function(e){return(r,u,a,f,c,h)=>{let d=[],p=c>=s,x=c>=o&&s>c,w=e(a),_=N(w*l,3),v=de(w.getFullYear(),p?0:w.getMonth(),x||p?1:w.getDate()),k=N(v*l,3);if(x||p){let t=x?c/o:0,n=p?c/s:0,i=_==k?_:N(de(v.getFullYear()+n,v.getMonth()+t,1)*l,3),r=new Date(g(i/l)),u=r.getFullYear(),a=r.getMonth();for(let o=0;f>=i;o++){let s=de(u+n*o,a+t*o,1),r=s-e(N(s*l,3));i=N((+s+r)*l,3),i>f||d.push(i)}}else{let o=i>c?c:i,s=k+(m(a)-m(_))+O(_-k,o);d.push(s);let p=e(s),g=p.getHours()+p.getMinutes()/t+p.getSeconds()/n,x=c/n,w=h/r.axes[u]._space;for(;s=N(s+c,1==l?0:3),f>=s;)if(x>1){let l=m(N(g+x,6))%24,t=e(s).getHours()-l;t>1&&(t=-1),s-=t*n,g=(g+x)%24,.7>N((s-d[d.length-1])/c,3)*w||d.push(s)}else d.push(s)}return d}}]}const[oe,se,re]=ie(1),[ue,ae,fe]=ie(.001);function ce(l,e){return l.map((l=>l.map(((t,n)=>{if(0==n||8==n||null==t)return t;const i=e(t);if(1==n||0==l[8])return i;{const t=e(l[1]);return l=>t(l)+ql+i(l)}}))))}function he(l,e){return(t,n,i,o,s)=>{let r,u,a,f,c,h,d=e.find((l=>s>=l[0]))||e[e.length-1];return n.map((e=>{let t=l(e),n=t.getFullYear(),i=t.getMonth(),o=t.getDate(),s=t.getHours(),p=t.getMinutes(),m=t.getSeconds(),g=n!=r&&d[2]||i!=u&&d[3]||o!=a&&d[4]||s!=f&&d[5]||p!=c&&d[6]||m!=h&&d[7]||d[1];return r=n,u=i,a=o,f=s,c=p,h=m,g(t)}))}}function de(l,e,t){return new Date(l,e,t)}function pe(l,e){return e(l)}H(2,-53,53,[1]);const me={...Kl,...Xl,...Jl,...Ql,...le};function ge(l,e){return(t,n,i,o)=>null==o?wl:e(l(n))}const xe={show:!0,live:!0,isolate:!1,mount:()=>{},markers:{show:!0,width:2,stroke:function(l,e){let t=l.series[e];return t.width?t.stroke(l,e):t.points.width?t.points.stroke(l,e):null},fill:function(l,e){return l.series[e].fill(l,e)},dash:"solid"},idx:null,idxs:null,values:[]},we=[0,0];function _e(l,e,t,n=!0){return l=>{0==l.button&&(!n||l.target==e)&&t(l)}}function ve(l,e,t,n=!0){return l=>{(!n||l.target==e)&&t(l)}}const ke={show:!0,x:!0,y:!0,lock:!1,move:function(l,e,t){return we[0]=e,we[1]=t,we},points:{one:!1,show:function(l,e){let t=l.cursor.points,n=Al(),i=t.size(l,e);Pl(n,tl,i),Pl(n,nl,i);let o=i/-2;Pl(n,"marginLeft",o),Pl(n,"marginTop",o);let s=t.width(l,e,i);return s&&Pl(n,"borderWidth",s),n},size:function(l,e){return l.series[e].points.size},width:0,stroke:function(l,e){let t=l.series[e].points;return t._stroke||t._fill},fill:function(l,e){let t=l.series[e].points;return t._fill||t._stroke}},bind:{mousedown:_e,mouseup:_e,click:_e,dblclick:_e,mousemove:ve,mouseleave:ve,mouseenter:ve},drag:{setScale:!0,x:!0,y:!1,dist:0,uni:null,click:(l,e)=>{e.stopPropagation(),e.stopImmediatePropagation()},_x:!1,_y:!1},focus:{dist:(l,e,t,n,i)=>n-i,prox:-1,bias:0},hover:{skip:[void 0],prox:null,bias:0},left:-10,top:-10,idx:null,dataIdx:null,idxs:null,event:null},be={show:!0,stroke:"rgba(0,0,0,0.07)",width:2},ye=Q({},be,{filter:A}),Se=Q({},ye,{size:10}),Ee=Q({},be,{show:!1}),Te='12px system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"',ze="bold "+Te,Pe={show:!0,scale:"x",stroke:ul,space:50,gap:5,size:50,labelGap:0,labelSize:30,labelFont:ze,side:2,grid:ye,ticks:Se,border:Ee,font:Te,lineGap:1.5,rotate:0},De={show:!0,scale:"x",auto:!1,sorted:1,min:E,max:-E,idxs:[]};function Ae(l,e,t,n,i,o){return e.map((l=>null==l?"":o(l)))}function Ce(l,e,t,n,i,o,s){let r=[],u=j.get(i)||0;for(let l=t=s?t:N(O(t,i),u);n>=l;l=N(l+i,u))r.push(Object.is(l,-0)?0:l);return r}function Me(l,t,n,i,o){const s=[],r=l.scales[l.axes[t].scale].log,u=m((10==r?b:y)(n));o=v(r,u),10==r&&(o=Wl[e(o,Wl)]);let a=n,f=o*r;10==r&&(f=Wl[e(f,Wl)]);do{s.push(a),a+=o,10!=r||j.has(a)||(a=N(a,j.get(o))),f>a||(f=(o=a)*r,10==r&&(f=Wl[e(f,Wl)]))}while(i>=a);return s}function Ie(l,e,t,n,i){let o=l.scales[l.axes[e].scale].asinh,s=n>o?Me(l,e,_(o,t),n,i):[o],r=0>n||t>0?[]:[0];return(-o>t?Me(l,e,_(o,-n),-t,i):[o]).reverse().map((l=>-l)).concat(r,s)}const Re=/./,Fe=/[12357]/,Ge=/[125]/,Oe=/1/,Le=(l,e,t,n)=>l.map(((l,i)=>4==e&&0==l||i%n==0&&t.test(l.toExponential()[0>l?1:0])?l:null));function Ne(l,e,t){let n=l.axes[t],i=n.scale,o=l.scales[i],s=l.valToPos,r=n._space,u=s(10,i),a=s(9,i)-ul)return Le(e.slice().reverse(),o.distr,a,x(r/l)).reverse()}return Le(e,o.distr,a,1)}function je(l,e,t){let n=l.axes[t],i=n.scale,o=n._space,s=l.valToPos,r=p(s(1,i)-s(2,i));return o>r?Le(e.slice().reverse(),3,Re,x(o/r)).reverse():e}function Be(l,e,t,n,i){return null==n?wl:null==e?"":i(e)}const He={show:!0,scale:"y",stroke:ul,space:30,gap:5,size:50,labelGap:0,labelSize:30,labelFont:ze,side:3,grid:ye,ticks:Se,border:Ee,font:Te,lineGap:1.5,rotate:0},Ue={scale:null,auto:!0,sorted:0,min:E,max:-E},Ve=(l,e,t,n,i)=>i,Ye={show:!0,auto:!0,sorted:0,gaps:Ve,alpha:1,facets:[Q({},Ue,{scale:"x"}),Q({},Ue,{scale:"y"})]},$e={scale:"y",auto:!0,sorted:0,show:!0,spanGaps:!1,gaps:Ve,alpha:1,points:{show:function(l,e){let{scale:t,idxs:n}=l.series[0],i=l._data[0],o=l.valToPos(i[n[0]],t,!0),s=l.valToPos(i[n[1]],t,!0);return p(s-o)/(l.series[e].points.space*Sl)>=n[1]-n[0]},filter:null},values:null,min:E,max:-E,idxs:[],path:null,clip:null};function We(l,e,t){return t/10}const qe={time:!0,auto:!0,distr:1,log:10,asinh:1,min:null,max:null,dir:1,ori:0},Ke=Q({},qe,{time:!1,ori:1}),Xe={};function Ze(l){let e=Xe[l];return e||(e={key:l,plots:[],sub(l){e.plots.push(l)},unsub(l){e.plots=e.plots.filter((e=>e!=l))},pub(l,t,n,i,o,s,r){for(let u=0;e.plots.length>u;u++)e.plots[u]!=t&&e.plots[u].pub(l,t,n,i,o,s,r)}},null!=l&&(Xe[l]=e)),e}function Je(l,e,t){const n=l.mode,i=l.series[e],o=2==n?l._data[e]:l._data,s=l.scales,r=l.bbox;let u=o[0],a=2==n?o[1]:o[e],f=2==n?s[i.facets[0].scale]:s[l.series[0].scale],c=2==n?s[i.facets[1].scale]:s[i.scale],h=r.left,d=r.top,p=r.width,m=r.height,g=l.valToPosH,x=l.valToPosV;return 0==f.ori?t(i,u,a,f,c,g,x,h,d,p,m,st,ut,ft,ht,pt):t(i,u,a,f,c,x,g,d,h,m,p,rt,at,ct,dt,mt)}function Qe(l,e){let t=0,n=0,i=f(l.bands,V);for(let l=0;i.length>l;l++){let o=i[l];o.series[0]==e?t=o.dir:o.series[1]==e&&(n|=1==o.dir?1:2)}return[t,1==n?-1:2==n?1:3==n?2:0]}function lt(l,e,t,n,i){let o=l.series[e],s=l.scales[2==l.mode?o.facets[1].scale:o.scale];return-1==i?s.min:1==i?s.max:3==s.distr?1==s.dir?s.min:s.max:0}function et(l,e,t,n,i,o){return Je(l,e,((l,e,s,r,u,a,f,c,h,d,p)=>{let m=l.pxRound;const g=0==r.ori?ut:at;let x,w;1==r.dir*(0==r.ori?1:-1)?(x=t,w=n):(x=n,w=t);let _=m(a(e[x],r,d,c)),v=m(f(s[x],u,p,h)),k=m(a(e[w],r,d,c)),b=m(f(1==o?u.max:u.min,u,p,h)),y=new Path2D(i);return g(y,k,b),g(y,_,b),g(y,_,v),y}))}function tt(l,e,t,n,i,o){let s=null;if(l.length>0){s=new Path2D;const r=0==e?ft:ct;let u=t;for(let e=0;l.length>e;e++){let t=l[e];if(t[1]>t[0]){let l=t[0]-u;l>0&&r(s,u,n,l,n+o),u=t[1]}}let a=t+i-u,f=10;a>0&&r(s,u,n-f/2,a,n+o+f)}return s}function nt(l,e,t,n,i,o,s){let r=[],u=l.length;for(let a=1==i?t:n;a>=t&&n>=a;a+=i)if(null===e[a]){let f=a,c=a;if(1==i)for(;++a<=n&&null===e[a];)c=a;else for(;--a>=t&&null===e[a];)c=a;let h=o(l[f]),d=c==f?h:o(l[c]),p=f-i;h=s>0||0>p||p>=u?h:o(l[p]);let m=c+i;d=0>s||0>m||m>=u?d:o(l[m]),h>d||r.push([h,d])}return r}function it(l){return 0==l?D:1==l?g:e=>G(e,l)}function ot(l){let e=0==l?st:rt,t=0==l?(l,e,t,n,i,o)=>{l.arcTo(e,t,n,i,o)}:(l,e,t,n,i,o)=>{l.arcTo(t,e,i,n,o)},n=0==l?(l,e,t,n,i)=>{l.rect(e,t,n,i)}:(l,e,t,n,i)=>{l.rect(t,e,i,n)};return(l,i,o,s,r,u=0,a=0)=>{0==u&&0==a?n(l,i,o,s,r):(u=w(u,s/2,r/2),a=w(a,s/2,r/2),e(l,i+u,o),t(l,i+s,o,i+s,o+r,u),t(l,i+s,o+r,i,o+r,a),t(l,i,o+r,i,o,a),t(l,i,o,i+s,o,u),l.closePath())}}const st=(l,e,t)=>{l.moveTo(e,t)},rt=(l,e,t)=>{l.moveTo(t,e)},ut=(l,e,t)=>{l.lineTo(e,t)},at=(l,e,t)=>{l.lineTo(t,e)},ft=ot(0),ct=ot(1),ht=(l,e,t,n,i,o)=>{l.arc(e,t,n,i,o)},dt=(l,e,t,n,i,o)=>{l.arc(t,e,n,i,o)},pt=(l,e,t,n,i,o,s)=>{l.bezierCurveTo(e,t,n,i,o,s)},mt=(l,e,t,n,i,o,s)=>{l.bezierCurveTo(t,e,i,n,s,o)};function gt(){return(l,e,t,n,i)=>Je(l,e,((e,o,s,r,u,a,f,c,h,p,m)=>{let g,x,{pxRound:w,points:_}=e;0==r.ori?(g=st,x=ht):(g=rt,x=dt);const v=N(_.width*Sl,3);let k=(_.size-_.width)/2*Sl,b=N(2*k,3),y=new Path2D,S=new Path2D,{left:E,top:T,width:z,height:P}=l.bbox;ft(S,E-b,T-b,z+2*b,P+2*b);const D=l=>{if(null!=s[l]){let e=w(a(o[l],r,p,c)),t=w(f(s[l],u,m,h));g(y,e+k,t),x(y,e,t,k,0,2*d)}};if(i)i.forEach(D);else for(let l=t;n>=l;l++)D(l);return{stroke:v>0?y:null,fill:y,clip:S,flags:3}}))}function xt(l){return(e,t,n,i,o,s)=>{n!=i&&(o!=n&&s!=n&&l(e,t,n),o!=i&&s!=i&&l(e,t,i),l(e,t,s))}}const wt=xt(ut),_t=xt(at);function vt(l){const e=f(l?.alignGaps,0);return(l,n,i,o)=>Je(l,n,((s,r,u,a,f,c,h,d,p,m,g)=>{let x,v,k=s.pxRound,b=l=>k(c(l,a,m,d)),y=l=>k(h(l,f,g,p));0==a.ori?(x=ut,v=wt):(x=at,v=_t);const S=a.dir*(0==a.ori?1:-1),T={stroke:new Path2D,fill:null,clip:null,band:null,gaps:null,flags:1},z=T.stroke;let P,D,A,C=E,M=-E,I=b(r[1==S?i:o]),R=t(u,i,o,1*S),F=t(u,i,o,-1*S),G=b(r[R]),O=b(r[F]),L=!1;for(let l=1==S?i:o;l>=i&&o>=l;l+=S){let e=b(r[l]),t=u[l];e==I?null!=t?(D=y(t),C==E&&(x(z,e,D),P=D),C=w(D,C),M=_(D,M)):null===t&&(L=!0):(C!=E&&(v(z,I,C,M,P,D),A=I),null!=t?(D=y(t),x(z,e,D),C=M=P=D):(C=E,M=-E,null===t&&(L=!0)),I=e)}C!=E&&C!=M&&A!=I&&v(z,I,C,M,P,D);let[N,j]=Qe(l,n);if(null!=s.fill||0!=N){let e=T.fill=new Path2D(z),t=y(s.fillTo(l,n,s.min,s.max,N));x(e,O,t),x(e,G,t)}if(!s.spanGaps){let t=[];L&&t.push(...nt(r,u,i,o,S,b,e)),T.gaps=t=s.gaps(l,n,i,o,t),T.clip=tt(t,a.ori,d,p,m,g)}return 0!=j&&(T.band=2==j?[et(l,n,i,o,z,-1),et(l,n,i,o,z,1)]:et(l,n,i,o,z,j)),T}))}function kt(l,e,t,n,i,o,s=E){if(l.length>1){let r=null;for(let u=0,a=1/0;l.length>u;u++)if(void 0!==e[u]){if(null!=r){let e=p(l[u]-l[r]);a>e&&(a=e,s=p(t(l[u],n,i,o)-t(l[r],n,i,o)))}r=u}}return s}function bt(l,e,t,n,i){const o=l.length;if(2>o)return null;const s=new Path2D;if(t(s,l[0],e[0]),2==o)n(s,l[1],e[1]);else{let t=Array(o),n=Array(o-1),r=Array(o-1),u=Array(o-1);for(let t=0;o-1>t;t++)r[t]=e[t+1]-e[t],u[t]=l[t+1]-l[t],n[t]=r[t]/u[t];t[0]=n[0];for(let l=1;o-1>l;l++)0===n[l]||0===n[l-1]||n[l-1]>0!=n[l]>0?t[l]=0:(t[l]=3*(u[l-1]+u[l])/((2*u[l]+u[l-1])/n[l-1]+(u[l]+2*u[l-1])/n[l]),isFinite(t[l])||(t[l]=0));t[o-1]=n[o-2];for(let n=0;o-1>n;n++)i(s,l[n]+u[n]/3,e[n]+t[n]*u[n]/3,l[n+1]-u[n]/3,e[n+1]-t[n+1]*u[n]/3,l[n+1],e[n+1])}return s}const yt=new Set;function St(){for(let l of yt)l.syncRect(!0)}kl&&(Nl("resize",yl,St),Nl("scroll",yl,St,!0),Nl(xl,yl,(()=>{Nt.pxRatio=Sl})));const Et=vt(),Tt=gt();function zt(l,e,t,n){return(n?[l[0],l[1]].concat(l.slice(2)):[l[0]].concat(l.slice(1))).map(((l,n)=>Pt(l,n,e,t)))}function Pt(l,e,t,n){return Q({},0==e?t:n,l)}function Dt(l,e,t){return null==e?Y:[e,t]}const At=Dt;function Ct(l,e,t){return null==e?Y:a(e,t,o,!0)}function Mt(l,e,t,i){return null==e?Y:n(e,t,l.scales[i].log,!1)}const It=Mt;function Rt(l,e,t,n){return null==e?Y:i(e,t,l.scales[n].log,!1)}const Ft=Rt;function Gt(l,t,n,i,o){let s=_(T(l),T(t)),r=t-l,u=e(o/i*r,n);do{let l=n[u],e=i*l/r;if(e>=o&&17>=s+(5>l?j.get(l):0))return[l,e]}while(++u(e=g((t=+n)*Sl))+"px")),e,t]}function Lt(l){l.show&&[l.font,l.labelFont].forEach((l=>{let e=N(l[2]*Sl,1);l[0]=l[0].replace(/[0-9.]+px/,e+"px"),l[1]=e}))}function Nt(t,r,u){const c={mode:f(t.mode,1)},m=c.mode,k=new Intl.NumberFormat(t.locale||l),y=l=>k.format(l);c.fmtNum=y;const T=e=>(e.hourCycle=t.hourCycle,new Intl.DateTimeFormat(t.locale||l,e).format);function D(l,e){return((3==e.distr?b(l>0?l:e.clamp(c,l,e.min,e.max,e.key)):4==e.distr?S(l,e.asinh):100==e.distr?e.fwd(l):l)-e._min)/(e._max-e._min)}function R(l,e,t,n){let i=D(l,e);return n+t*(-1==e.dir?1-i:i)}function F(l,e,t,n){let i=D(l,e);return n+t*(-1==e.dir?i:1-i)}function O(l,e,t,n){return 0==e.ori?R(l,e,t,n):F(l,e,t,n)}c.fmtDate=T,c.valToPosH=R,c.valToPosV=F;let L=!1;c.status=0;const H=c.root=Al("uplot");null!=t.id&&(H.id=t.id),Tl(H,t.class),t.title&&(Al("u-title",H).textContent=t.title);const W=Dl("canvas"),X=c.ctx=W.getContext("2d"),Z=Al("u-wrap",H);Nl("click",Z,(l=>{l.target===ul&&(Nn!=Fn||jn!=Gn)&&Kn.click(c,l)}),!0);const ll=c.under=Al("u-under",Z);Z.appendChild(W);const ul=c.over=Al("u-over",Z),gl=+f((t=J(t)).pxAlign,1),kl=it(gl);(t.plugins||[]).forEach((l=>{l.opts&&(t=l.opts(c,t)||t)}));const El=t.ms||.001,Cl=c.series=1==m?zt(t.series||[],De,$e,!1):function(l,e){return l.map(((l,t)=>0==t?{}:Q({},e,l)))}(t.series||[null],Ye),Il=c.axes=zt(t.axes||[],Pe,He,!0),Fl=c.scales={},Ol=c.bands=t.bands||[];Ol.forEach((l=>{l.fill=P(l.fill||null),l.dir=f(l.dir,-1)}));const Ll=2==m?Cl[1].facets[0].scale:Cl[0].scale,Bl={axes:function(){for(let l=0;Il.length>l;l++){let e=Il[l];if(!e.show||!e._show)continue;let t,n,i=e.side,o=i%2,s=e.stroke(c,l),r=0==i||3==i?-1:1;if(e.label){let l=g((e._lpos+e.labelGap*r)*Sl);gn(e.labelFont[0],s,"center",2==i?il:ol),X.save(),1==o?(t=n=0,X.translate(l,g(ut+ft/2)),X.rotate((3==i?-d:d)/2)):(t=g(rt+at/2),n=l),X.fillText(e.label,t,n),X.restore()}let[u,a]=e._found;if(0==a)continue;let f=Fl[e.scale],h=0==o?at:ft,p=0==o?rt:ut,m=g(e.gap*Sl),x=e._splits,w=2==f.distr?x.map((l=>cn[l])):x,_=2==f.distr?cn[x[1]]-cn[x[0]]:u,v=e.ticks,k=e.border,b=v.show?g(v.size*Sl):0,y=e._rotate*-d/180,S=kl(e._pos*Sl),E=S+(b+m)*r;n=0==o?E:0,t=1==o?E:0,gn(e.font[0],s,1==e.align?sl:2==e.align?rl:y>0?sl:0>y?rl:0==o?"center":3==i?rl:sl,y||1==o?"middle":2==i?il:ol);let T=e.font[1]*e.lineGap,z=x.map((l=>kl(O(l,f,h,p)))),P=e._values;for(let l=0;P.length>l;l++){let e=P[l];if(null!=e){0==o?t=z[l]:n=z[l],e=""+e;let i=-1==e.indexOf("\n")?[e]:e.split(/\n/gm);for(let l=0;i.length>l;l++){let e=i[l];y?(X.save(),X.translate(t,n+l*T),X.rotate(y),X.fillText(e,0,0),X.restore()):X.fillText(e,t,n+l*T)}}}v.show&&En(z,v.filter(c,w,l,a,_),o,i,S,b,N(v.width*Sl,3),v.stroke(c,l),v.dash,v.cap);let D=e.grid;D.show&&En(z,D.filter(c,w,l,a,_),o,0==o?2:1,0==o?ut:rt,0==o?ft:at,N(D.width*Sl,3),D.stroke(c,l),D.dash,D.cap),k.show&&En([S],[1],0==o?1:0,0==o?1:2,1==o?ut:rt,1==o?ft:at,N(k.width*Sl,3),k.stroke(c,l),k.dash,k.cap)}Ci("drawAxes")},series:function(){Xt>0&&(Cl.forEach(((l,e)=>{if(e>0&&l.show&&(_n(e,!1),_n(e,!0),null==l._paths)){fn!=l.alpha&&(X.globalAlpha=fn=l.alpha);let t=2==m?[0,r[e][0].length-1]:function(l){let e=z(Zt-1,0,Xt-1),t=z(Jt+1,0,Xt-1);for(;null==l[e]&&e>0;)e--;for(;null==l[t]&&Xt-1>t;)t++;return[e,t]}(r[e]);l._paths=l.paths(c,e,t[0],t[1]),1!=fn&&(X.globalAlpha=fn=1)}})),Cl.forEach(((l,e)=>{if(e>0&&l.show){fn!=l.alpha&&(X.globalAlpha=fn=l.alpha),null!=l._paths&&vn(e,!1);{let t=null!=l._paths?l._paths.gaps:null,n=l.points.show(c,e,Zt,Jt,t),i=l.points.filter(c,e,n,t);(n||i)&&(l.points._paths=l.points.paths(c,e,Zt,Jt,i),vn(e,!0))}1!=fn&&(X.globalAlpha=fn=1),Ci("drawSeries",e)}})))}},Hl=(t.drawOrder||["axes","series"]).map((l=>Bl[l]));function Ul(l){let e=Fl[l];if(null==e){let n=(t.scales||U)[l]||U;if(null!=n.from)Ul(n.from),Fl[l]=Q({},Fl[n.from],n,{key:l});else{e=Fl[l]=Q({},l==Ll?qe:Ke,n),e.key=l;let t=e.time,i=e.range,o=$(i);if((l!=Ll||2==m&&!t)&&(!o||null!=i[0]&&null!=i[1]||(i={min:null==i[0]?s:{mode:1,hard:i[0],soft:i[0]},max:null==i[1]?s:{mode:1,hard:i[1],soft:i[1]}},o=!1),!o&&q(i))){let l=i;i=(e,t,n)=>null==t?Y:a(t,n,l)}e.range=P(i||(t?At:l==Ll?3==e.distr?It:4==e.distr?Ft:Dt:3==e.distr?Mt:4==e.distr?Rt:Ct)),e.auto=P(!o&&e.auto),e.clamp=P(e.clamp||We),e._min=e._max=null}}}Ul("x"),Ul("y"),1==m&&Cl.forEach((l=>{Ul(l.scale)})),Il.forEach((l=>{Ul(l.scale)}));for(let l in t.scales)Ul(l);const Vl=Fl[Ll],Yl=Vl.distr;let ql,Kl;0==Vl.ori?(Tl(H,"u-hz"),ql=R,Kl=F):(Tl(H,"u-vt"),ql=F,Kl=R);const Xl={};for(let l in Fl){let e=Fl[l];null==e.min&&null==e.max||(Xl[l]={min:e.min,max:e.max},e.min=e.max=null)}const Zl=t.tzDate||(l=>new Date(g(l/El))),Jl=t.fmtDate||T,Ql=1==El?re(Zl):fe(Zl),le=he(Zl,ce(1==El?se:ae,Jl)),ee=ge(Zl,pe(me,Jl)),te=[],ne=c.legend=Q({},xe,t.legend),ie=ne.show,de=ne.markers;let we,_e,ve;ne.idxs=te,de.width=P(de.width),de.dash=P(de.dash),de.stroke=P(de.stroke),de.fill=P(de.fill);let be,ye=[],Se=[],Ee=!1,Te={};if(ne.live){const l=Cl[1]?Cl[1].values:null;Ee=null!=l,be=Ee?l(c,1,0):{_:0};for(let l in be)Te[l]=wl}if(ie)if(we=Dl("table","u-legend",H),ve=Dl("tbody",null,we),ne.mount(c,we),Ee){_e=Dl("thead",null,we,ve);let l=Dl("tr",null,_e);for(var ze in Dl("th",null,l),be)Dl("th",vl,l).textContent=ze}else Tl(we,"u-inline"),ne.live&&Tl(we,"u-live");const Re={show:!0},Fe={show:!1},Ge=new Map;function Oe(l,e,t,n=!0){const i=Ge.get(e)||{},o=vt.bind[l](c,e,t,n);o&&(Nl(l,e,i[l]=o),Ge.set(e,i))}function Le(l,e){const t=Ge.get(e)||{};for(let n in t)null!=l&&n!=l||(jl(n,e,t[n]),delete t[n]);null==l&&Ge.delete(e)}let Ue=0,Ve=0,Xe=0,Je=0,Qe=0,et=0,tt=Qe,nt=et,ot=Xe,st=Je,rt=0,ut=0,at=0,ft=0;c.bbox={};let ct=!1,ht=!1,dt=!1,pt=!1,mt=!1,gt=!1;function xt(l,e,t){(t||l!=c.width||e!=c.height)&&wt(l,e),Pn(!1),dt=!0,ht=!0,Yn()}function wt(l,e){c.width=Ue=Xe=l,c.height=Ve=Je=e,Qe=et=0,function(){let l=!1,e=!1,t=!1,n=!1;Il.forEach((i=>{if(i.show&&i._show){let{side:o,_size:s}=i,r=s+(null!=i.label?i.labelSize:0);r>0&&(o%2?(Xe-=r,3==o?(Qe+=r,n=!0):t=!0):(Je-=r,0==o?(et+=r,l=!0):e=!0))}})),$t[0]=l,$t[1]=t,$t[2]=e,$t[3]=n,Xe-=Kt[1]+Kt[3],Qe+=Kt[3],Je-=Kt[2]+Kt[0],et+=Kt[0]}(),function(){let l=Qe+Xe,e=et+Je,t=Qe,n=et;function i(i,o){switch(i){case 1:return l+=o,l-o;case 2:return e+=o,e-o;case 3:return t-=o,t+o;case 0:return n-=o,n+o}}Il.forEach((l=>{if(l.show&&l._show){let e=l.side;l._pos=i(e,l._size),null!=l.label&&(l._lpos=i(e,l.labelSize))}}))}();let t=c.bbox;rt=t.left=G(Qe*Sl,.5),ut=t.top=G(et*Sl,.5),at=t.width=G(Xe*Sl,.5),ft=t.height=G(Je*Sl,.5)}const _t=3;c.setSize=function({width:l,height:e}){xt(l,e)};const vt=c.cursor=Q({},ke,{drag:{y:2==m}},t.cursor);if(null==vt.dataIdx){let l=vt.hover,e=l.skip=new Set(l.skip??[]);e.add(void 0);let t=l.prox=P(l.prox),n=l.bias??=0;vt.dataIdx=(l,i,o,s)=>{if(0==i)return o;let u=o,a=t(l,i,o,s)??E,f=a>=0&&E>a,c=0==Vl.ori?Xe:Je,h=vt.left,d=r[0],m=r[i];if(e.has(m[o])){u=null;let l,t=null,i=null;if(0==n||-1==n)for(l=o;null==t&&l-- >0;)e.has(m[l])||(t=l);if(0==n||1==n)for(l=o;null==i&&l++e?e>a||(u=i):l>a||(u=t)}else u=null==i?t:null==t||o-t>i-o?i:t}else f&&p(h-ql(d[o],Vl,c,0))>a&&(u=null);return u}}const kt=l=>{vt.event=l};vt.idxs=te,vt._lock=!1;let bt=vt.points;bt.show=P(bt.show),bt.size=P(bt.size),bt.stroke=P(bt.stroke),bt.width=P(bt.width),bt.fill=P(bt.fill);const St=c.focus=Q({},t.focus||{alpha:.3},vt.focus),Nt=St.prox>=0,jt=Nt&&bt.one;let Bt=[],Ht=[],Ut=[];function Vt(l,e){let t=bt.show(c,e);if(t)return Tl(t,"u-cursor-pt"),Tl(t,l.class),Ml(t,-10,-10,Xe,Je),ul.insertBefore(t,Bt[e]),t}function Yt(l,e){if(1==m||e>0){let e=1==m&&Fl[l.scale].time,t=l.value;l.value=e?function(l){return"string"==typeof l}(t)?ge(Zl,pe(t,Jl)):t||ee:t||Be,l.label=l.label||(e?"Time":"Value")}if(jt||e>0){l.width=null==l.width?1:l.width,l.paths=l.paths||Et||C,l.fillTo=P(l.fillTo||lt),l.pxAlign=+f(l.pxAlign,gl),l.pxRound=it(l.pxAlign),l.stroke=P(l.stroke||null),l.fill=P(l.fill||null),l._stroke=l._fill=l._paths=l._focus=null;let e=function(l){return N(1*(3+2*(l||1)),3)}(_(1,l.width)),t=l.points=Q({},{size:e,width:_(1,.2*e),stroke:l.stroke,space:2*e,paths:Tt,_stroke:null,_fill:null},l.points);t.show=P(t.show),t.filter=P(t.filter),t.fill=P(t.fill),t.stroke=P(t.stroke),t.paths=P(t.paths),t.pxAlign=l.pxAlign}if(ie){let t=function(l,e){if(0==e&&(Ee||!ne.live||2==m))return Y;let t=[],n=Dl("tr","u-series",ve,ve.childNodes[e]);Tl(n,l.class),l.show||Tl(n,_l);let i=Dl("th",null,n);if(de.show){let l=Al("u-marker",i);if(e>0){let t=de.width(c,e);t&&(l.style.border=t+"px "+de.dash(c,e)+" "+de.stroke(c,e)),l.style.background=de.fill(c,e)}}let o=Al(vl,i);for(var s in o.textContent=l.label,e>0&&(de.show||(o.style.color=l.width>0?de.stroke(c,e):de.fill(c,e)),Oe("click",i,(e=>{if(vt._lock)return;kt(e);let t=Cl.indexOf(l);if((e.ctrlKey||e.metaKey)!=ne.isolate){let l=Cl.some(((l,e)=>e>0&&e!=t&&l.show));Cl.forEach(((e,n)=>{n>0&&ti(n,l?n==t?Re:Fe:Re,!0,Ii.setSeries)}))}else ti(t,{show:!l.show},!0,Ii.setSeries)}),!1),Nt&&Oe(dl,i,(e=>{vt._lock||(kt(e),ti(Cl.indexOf(l),si,!0,Ii.setSeries))}),!1)),be){let l=Dl("td","u-value",n);l.textContent="--",t.push(l)}return[n,t]}(l,e);ye.splice(e,0,t[0]),Se.splice(e,0,t[1]),ne.values.push(null)}if(vt.show){te.splice(e,0,null);let t=null;jt?0==e&&(t=Vt(l,e)):e>0&&(t=Vt(l,e)),Bt.splice(e,0,t),Ht.splice(e,0,0),Ut.splice(e,0,0)}Ci("addSeries",e)}c.addSeries=function(l,e){e=null==e?Cl.length:e,l=1==m?Pt(l,e,De,$e):Pt(l,e,{},Ye),Cl.splice(e,0,l),Yt(Cl[e],e)},c.delSeries=function(l){if(Cl.splice(l,1),ie){ne.values.splice(l,1),Se.splice(l,1);let e=ye.splice(l,1)[0];Le(null,e.firstChild),e.remove()}vt.show&&(te.splice(l,1),Bt.splice(l,1)[0].remove(),Ht.splice(l,1),Ut.splice(l,1)),Ci("delSeries",l)};const $t=[!1,!1,!1,!1];function Wt(l,e,t){let[n,i,o,s]=t,r=e%2,u=0;return 0==r&&(s||i)&&(u=0==e&&!n||2==e&&!o?g(Pe.size/3):0),1==r&&(n||o)&&(u=1==e&&!i||3==e&&!s?g(He.size/2):0),u}const qt=c.padding=(t.padding||[Wt,Wt,Wt,Wt]).map((l=>P(f(l,Wt)))),Kt=c._padding=qt.map(((l,e)=>l(c,e,$t,0)));let Xt,Zt=null,Jt=null;const Qt=1==m?Cl[0].idxs:null;let ln,en,tn,nn,on,sn,rn,un,an,fn,cn=null,hn=!1;function dn(l,e){if(c.data=c._data=r=null==l?[]:l,2==m){Xt=0;for(let l=1;Cl.length>l;l++)Xt+=r[l][0].length}else{0==r.length&&(c.data=c._data=r=[[]]),cn=r[0],Xt=cn.length;let l=r;if(2==Yl){l=r.slice();let e=l[0]=Array(Xt);for(let l=0;Xt>l;l++)e[l]=l}c._data=r=l}if(Pn(!0),Ci("setData"),2==Yl&&(dt=!0),!1!==e){let l=Vl;l.auto(c,hn)?pn():ei(Ll,l.min,l.max),pt=pt||vt.left>=0,gt=!0,Yn()}}function pn(){let l,e;hn=!0,1==m&&(Xt>0?(Zt=Qt[0]=0,Jt=Qt[1]=Xt-1,l=r[0][Zt],e=r[0][Jt],2==Yl?(l=Zt,e=Jt):l==e&&(3==Yl?[l,e]=n(l,l,Vl.log,!1):4==Yl?[l,e]=i(l,l,Vl.log,!1):Vl.time?e=l+g(86400/El):[l,e]=a(l,e,o,!0))):(Zt=Qt[0]=l=null,Jt=Qt[1]=e=null)),ei(Ll,l,e)}function mn(l,e,t,n,i,o){l??=al,t??=V,n??="butt",i??=al,o??="round",l!=ln&&(X.strokeStyle=ln=l),i!=en&&(X.fillStyle=en=i),e!=tn&&(X.lineWidth=tn=e),o!=on&&(X.lineJoin=on=o),n!=sn&&(X.lineCap=sn=n),t!=nn&&X.setLineDash(nn=t)}function gn(l,e,t,n){e!=en&&(X.fillStyle=en=e),l!=rn&&(X.font=rn=l),t!=un&&(X.textAlign=un=t),n!=an&&(X.textBaseline=an=n)}function xn(l,e,t,n,i=0){if(n.length>0&&l.auto(c,hn)&&(null==e||null==e.min)){let e=f(Zt,0),o=f(Jt,n.length-1),s=null==t.min?3==l.distr?function(l,e,t){let n=E,i=-E;for(let o=e;t>=o;o++){let e=l[o];null!=e&&e>0&&(n>e&&(n=e),e>i&&(i=e))}return[n,i]}(n,e,o):function(l,e,t,n){let i=E,o=-E;if(1==n)i=l[e],o=l[t];else if(-1==n)i=l[t],o=l[e];else for(let n=e;t>=n;n++){let e=l[n];null!=e&&(i>e&&(i=e),e>o&&(o=e))}return[i,o]}(n,e,o,i):[t.min,t.max];l.min=w(l.min,t.min=s[0]),l.max=_(l.max,t.max=s[1])}}c.setData=dn;const wn={min:null,max:null};function _n(l,e){let t=e?Cl[l].points:Cl[l];t._stroke=t.stroke(c,l),t._fill=t.fill(c,l)}function vn(l,e){let t=e?Cl[l].points:Cl[l],{stroke:n,fill:i,clip:o,flags:s,_stroke:u=t._stroke,_fill:a=t._fill,_width:h=t.width}=t._paths;h=N(h*Sl,3);let d=null,p=h%2/2;e&&null==a&&(a=h>0?"#fff":u);let m=1==t.pxAlign&&p>0;if(m&&X.translate(p,p),!e){let l=rt-h/2,e=ut-h/2,t=at+h,n=ft+h;d=new Path2D,d.rect(l,e,t,n)}e?bn(u,h,t.dash,t.cap,a,n,i,s,o):function(l,e,t,n,i,o,s,u,a,h,d){let p=!1;0!=a&&Ol.forEach(((m,g)=>{if(m.series[0]==l){let l,x=Cl[m.series[1]],w=r[m.series[1]],_=(x._paths||U).band;$(_)&&(_=1==m.dir?_[0]:_[1]);let v=null;x.show&&_&&function(l,e,t){for(e=f(e,0),t=f(t,l.length-1);t>=e;){if(null!=l[e])return!0;e++}return!1}(w,Zt,Jt)?(v=m.fill(c,g)||o,l=x._paths.clip):_=null,bn(e,t,n,i,v,s,u,a,h,d,l,_),p=!0}})),p||bn(e,t,n,i,o,s,u,a,h,d)}(l,u,h,t.dash,t.cap,a,n,i,s,d,o),m&&X.translate(-p,-p)}const kn=3;function bn(l,e,t,n,i,o,s,r,u,a,f,c){mn(l,e,t,n,i),(u||a||c)&&(X.save(),u&&X.clip(u),a&&X.clip(a)),c?(r&kn)==kn?(X.clip(c),f&&X.clip(f),Sn(i,s),yn(l,o,e)):2&r?(Sn(i,s),X.clip(c),yn(l,o,e)):1&r&&(X.save(),X.clip(c),f&&X.clip(f),Sn(i,s),X.restore(),yn(l,o,e)):(Sn(i,s),yn(l,o,e)),(u||a||c)&&X.restore()}function yn(l,e,t){t>0&&(e instanceof Map?e.forEach(((l,e)=>{X.strokeStyle=ln=e,X.stroke(l)})):null!=e&&l&&X.stroke(e))}function Sn(l,e){e instanceof Map?e.forEach(((l,e)=>{X.fillStyle=en=e,X.fill(l)})):null!=e&&l&&X.fill(e)}function En(l,e,t,n,i,o,s,r,u,a){let f=s%2/2;1==gl&&X.translate(f,f),mn(r,s,u,a,r),X.beginPath();let c,h,d,p,m=i+(0==n||3==n?-o:o);0==t?(h=i,p=m):(c=i,d=m);for(let n=0;l.length>n;n++)null!=e[n]&&(0==t?c=d=l[n]:h=p=l[n],X.moveTo(c,h),X.lineTo(d,p));X.stroke(),1==gl&&X.translate(-f,-f)}function Tn(l){let e=!0;return Il.forEach(((t,n)=>{if(!t.show)return;let i=Fl[t.scale];if(null==i.min)return void(t._show&&(e=!1,t._show=!1,Pn(!1)));t._show||(e=!1,t._show=!0,Pn(!1));let o=t.side,s=o%2,{min:r,max:u}=i,[a,f]=function(l,e,t,n){let i,o=Il[l];if(n>0){let s=o._space=o.space(c,l,e,t,n);i=Gt(e,t,o._incrs=o.incrs(c,l,e,t,n,s),n,s)}else i=[0,0];return o._found=i}(n,r,u,0==s?Xe:Je);if(0==f)return;let h=t._splits=t.splits(c,n,r,u,a,f,2==i.distr),d=2==i.distr?h.map((l=>cn[l])):h,p=2==i.distr?cn[h[1]]-cn[h[0]]:a,m=t._values=t.values(c,t.filter(c,d,n,f,p),n,f,p,y);t._rotate=2==o?t.rotate(c,m,n,f):0;let g=t._size;t._size=x(t.size(c,m,n,l)),null!=g&&t._size!=g&&(e=!1)})),e}function zn(l){let e=!0;return qt.forEach(((t,n)=>{let i=t(c,n,$t,l);i!=Kt[n]&&(e=!1),Kt[n]=i})),e}function Pn(l){Cl.forEach(((e,t)=>{t>0&&(e._paths=null,l&&(1==m?(e.min=null,e.max=null):e.facets.forEach((l=>{l.min=null,l.max=null}))))}))}let Dn,An,Cn,Mn,In,Rn,Fn,Gn,On,Ln,Nn,jn,Bn=!1,Hn=!1,Un=[];function Vn(){Hn=!1;for(let l=0;Un.length>l;l++)Ci(...Un[l]);Un.length=0}function Yn(){Bn||(el($n),Bn=!0)}function $n(){if(ct&&(function(){for(let l in Fl){let e=Fl[l];null==Xl[l]&&(null==e.min||null!=Xl[Ll]&&e.auto(c,hn))&&(Xl[l]=wn)}for(let l in Fl){let e=Fl[l];null==Xl[l]&&null!=e.from&&null!=Xl[e.from]&&(Xl[l]=wn)}null!=Xl[Ll]&&Pn(!0);let l={};for(let e in Xl){let t=Xl[e];if(null!=t){let n=l[e]=J(Fl[e],K);if(null!=t.min)Q(n,t);else if(e!=Ll||2==m)if(0==Xt&&null==n.from){let l=n.range(c,null,null,e);n.min=l[0],n.max=l[1]}else n.min=E,n.max=-E}}if(Xt>0){Cl.forEach(((t,n)=>{if(1==m){let i=t.scale,o=Xl[i];if(null==o)return;let s=l[i];if(0==n){let l=s.range(c,s.min,s.max,i);s.min=l[0],s.max=l[1],Zt=e(s.min,r[0]),Jt=e(s.max,r[0]),Jt-Zt>1&&(s.min>r[0][Zt]&&Zt++,r[0][Jt]>s.max&&Jt--),t.min=cn[Zt],t.max=cn[Jt]}else t.show&&t.auto&&xn(s,o,t,r[n],t.sorted);t.idxs[0]=Zt,t.idxs[1]=Jt}else if(n>0&&t.show&&t.auto){let[e,i]=t.facets,o=e.scale,s=i.scale,[u,a]=r[n],f=l[o],c=l[s];null!=f&&xn(f,Xl[o],e,u,e.sorted),null!=c&&xn(c,Xl[s],i,a,i.sorted),t.min=i.min,t.max=i.max}}));for(let e in l){let t=l[e],n=Xl[e];if(null==t.from&&(null==n||null==n.min)){let l=t.range(c,t.min==E?null:t.min,t.max==-E?null:t.max,e);t.min=l[0],t.max=l[1]}}}for(let e in l){let t=l[e];if(null!=t.from){let n=l[t.from];if(null==n.min)t.min=t.max=null;else{let l=t.range(c,n.min,n.max,e);t.min=l[0],t.max=l[1]}}}let t={},n=!1;for(let e in l){let i=l[e],o=Fl[e];if(o.min!=i.min||o.max!=i.max){o.min=i.min,o.max=i.max;let l=o.distr;o._min=3==l?b(o.min):4==l?S(o.min,o.asinh):100==l?o.fwd(o.min):o.min,o._max=3==l?b(o.max):4==l?S(o.max,o.asinh):100==l?o.fwd(o.max):o.max,t[e]=n=!0}}if(n){Cl.forEach(((l,e)=>{2==m?e>0&&t.y&&(l._paths=null):t[l.scale]&&(l._paths=null)}));for(let l in t)dt=!0,Ci("setScale",l);vt.show&&vt.left>=0&&(pt=gt=!0)}for(let l in Xl)Xl[l]=null}(),ct=!1),dt&&(function(){let l=!1,e=0;for(;!l;){e++;let t=Tn(e),n=zn(e);l=e==_t||t&&n,l||(wt(c.width,c.height),ht=!0)}}(),dt=!1),ht){if(Pl(ll,sl,Qe),Pl(ll,il,et),Pl(ll,tl,Xe),Pl(ll,nl,Je),Pl(ul,sl,Qe),Pl(ul,il,et),Pl(ul,tl,Xe),Pl(ul,nl,Je),Pl(Z,tl,Ue),Pl(Z,nl,Ve),W.width=g(Ue*Sl),W.height=g(Ve*Sl),Il.forEach((({_el:l,_show:e,_size:t,_pos:n,side:i})=>{if(null!=l)if(e){let e=i%2==1;Pl(l,e?"left":"top",n-(3===i||0===i?t:0)),Pl(l,e?"width":"height",t),Pl(l,e?"top":"left",e?et:Qe),Pl(l,e?"height":"width",e?Je:Xe),zl(l,_l)}else Tl(l,_l)})),ln=en=tn=on=sn=rn=un=an=nn=null,fn=1,gi(!0),Qe!=tt||et!=nt||Xe!=ot||Je!=st){Pn(!1);let l=Xe/ot,e=Je/st;if(vt.show&&!pt&&vt.left>=0){vt.left*=l,vt.top*=e,Cn&&Ml(Cn,g(vt.left),0,Xe,Je),Mn&&Ml(Mn,0,g(vt.top),Xe,Je);for(let t=0;Bt.length>t;t++){let n=Bt[t];null!=n&&(Ht[t]*=l,Ut[t]*=e,Ml(n,x(Ht[t]),x(Ut[t]),Xe,Je))}}if(Jn.show&&!mt&&Jn.left>=0&&Jn.width>0){Jn.left*=l,Jn.width*=l,Jn.top*=e,Jn.height*=e;for(let l in _i)Pl(Qn,l,Jn[l])}tt=Qe,nt=et,ot=Xe,st=Je}Ci("setSize"),ht=!1}Ue>0&&Ve>0&&(X.clearRect(0,0,W.width,W.height),Ci("drawClear"),Hl.forEach((l=>l())),Ci("draw")),Jn.show&&mt&&(li(Jn),mt=!1),vt.show&&pt&&(pi(null,!0,!1),pt=!1),ne.show&&ne.live&>&&(hi(),gt=!1),L||(L=!0,c.status=1,Ci("ready")),hn=!1,Bn=!1}function Wn(l,t){let n=Fl[l];if(null==n.from){if(0==Xt){let e=n.range(c,t.min,t.max,l);t.min=e[0],t.max=e[1]}if(t.min>t.max){let l=t.min;t.min=t.max,t.max=l}if(Xt>1&&null!=t.min&&null!=t.max&&1e-16>t.max-t.min)return;l==Ll&&2==n.distr&&Xt>0&&(t.min=e(t.min,r[0]),t.max=e(t.max,r[0]),t.min==t.max&&t.max++),Xl[l]=t,ct=!0,Yn()}}c.batch=function(l,e=!1){Bn=!0,Hn=e,l(c),$n(),e&&Un.length>0&&queueMicrotask(Vn)},c.redraw=(l,e)=>{dt=e||!1,!1!==l?ei(Ll,Vl.min,Vl.max):Yn()},c.setScale=Wn;let qn=!1;const Kn=vt.drag;let Xn=Kn.x,Zn=Kn.y;vt.show&&(vt.x&&(Dn=Al("u-cursor-x",ul)),vt.y&&(An=Al("u-cursor-y",ul)),0==Vl.ori?(Cn=Dn,Mn=An):(Cn=An,Mn=Dn),Nn=vt.left,jn=vt.top);const Jn=c.select=Q({show:!0,over:!0,left:0,width:0,top:0,height:0},t.select),Qn=Jn.show?Al("u-select",Jn.over?ul:ll):null;function li(l,e){if(Jn.show){for(let e in l)Jn[e]=l[e],e in _i&&Pl(Qn,e,l[e]);!1!==e&&Ci("setSelect")}}function ei(l,e,t){Wn(l,{min:e,max:t})}function ti(l,e,t,n){null!=e.focus&&function(l){if(l!=oi){let e=null==l,t=1!=St.alpha;Cl.forEach(((n,i)=>{if(1==m||i>0){let o=e||0==i||i==l;n._focus=e?null:o,t&&function(l,e){Cl[l].alpha=e,vt.show&&Bt[l]&&(Bt[l].style.opacity=e),ie&&ye[l]&&(ye[l].style.opacity=e)}(i,o?1:St.alpha)}})),oi=l,t&&Yn()}}(l),null!=e.show&&Cl.forEach(((t,n)=>{0>=n||l!=n&&null!=l||(t.show=e.show,function(l){let e=ie?ye[l]:null;Cl[l].show?e&&zl(e,_l):(e&&Tl(e,_l),Ml(jt?Bt[0]:Bt[l],-10,-10,Xe,Je))}(n),2==m?(ei(t.facets[0].scale,null,null),ei(t.facets[1].scale,null,null)):ei(t.scale,null,null),Yn())})),!1!==t&&Ci("setSeries",l,e),n&&Gi("setSeries",c,l,e)}let ni,ii,oi;c.setSelect=li,c.setSeries=ti,c.addBand=function(l,e){l.fill=P(l.fill||null),l.dir=f(l.dir,-1),Ol.splice(e=null==e?Ol.length:e,0,l)},c.setBand=function(l,e){Q(Ol[l],e)},c.delBand=function(l){null==l?Ol.length=0:Ol.splice(l,1)};const si={focus:!0};function ri(l,e,t){let n=Fl[e];t&&(l=l/Sl-(1==n.ori?et:Qe));let i=Xe;1==n.ori&&(i=Je,l=i-l),-1==n.dir&&(l=i-l);let o=n._min,s=o+l/i*(n._max-o),r=n.distr;return 3==r?v(10,s):4==r?((l,e=1)=>h.sinh(l)*e)(s,n.asinh):100==r?n.bwd(s):s}function ui(l,e){Pl(Qn,sl,Jn.left=l),Pl(Qn,tl,Jn.width=e)}function ai(l,e){Pl(Qn,il,Jn.top=l),Pl(Qn,nl,Jn.height=e)}ie&&Nt&&Oe(pl,we,(l=>{vt._lock||(kt(l),null!=oi&&ti(null,si,!0,Ii.setSeries))})),c.valToIdx=l=>e(l,r[0]),c.posToIdx=function(l,t){return e(ri(l,Ll,t),r[0],Zt,Jt)},c.posToVal=ri,c.valToPos=(l,e,t)=>0==Fl[e].ori?R(l,Fl[e],t?at:Xe,t?rt:0):F(l,Fl[e],t?ft:Je,t?ut:0),c.setCursor=(l,e,t)=>{Nn=l.left,jn=l.top,pi(null,e,t)};let fi=0==Vl.ori?ui:ai,ci=1==Vl.ori?ui:ai;function hi(l,e){if(null!=l&&(l.idxs?l.idxs.forEach(((l,e)=>{te[e]=l})):(l=>void 0===l)(l.idx)||te.fill(l.idx),ne.idx=te[0]),ie&&ne.live){for(let l=0;Cl.length>l;l++)(l>0||1==m&&!Ee)&&di(l,te[l]);!function(){if(ie&&ne.live)for(let l=2==m?1:0;Cl.length>l;l++){if(0==l&&Ee)continue;let e=ne.values[l],t=0;for(let n in e)Se[l][t++].firstChild.nodeValue=e[n]}}()}gt=!1,!1!==e&&Ci("setLegend")}function di(l,e){let t,n=Cl[l],i=0==l&&2==Yl?cn:r[l];Ee?t=n.values(c,l,e)??Te:(t=n.value(c,null==e?null:i[e],l,e,y),t=null==t?Te:{_:t}),ne.values[l]=t}function pi(l,t,n){let i;On=Nn,Ln=jn,[Nn,jn]=vt.move(c,Nn,jn),vt.left=Nn,vt.top=jn,vt.show&&(Cn&&Ml(Cn,g(Nn),0,Xe,Je),Mn&&Ml(Mn,0,g(jn),Xe,Je)),ni=E,ii=null;let o=0==Vl.ori?Xe:Je,s=1==Vl.ori?Xe:Je;if(0>Nn||0==Xt||Zt>Jt){i=vt.idx=null;for(let l=0;Cl.length>l;l++){let e=Bt[l];null!=e&&Ml(e,-10,-10,Xe,Je)}Nt&&ti(null,si,!0,null==l&&Ii.setSeries),ne.live&&(te.fill(i),gt=!0)}else{let l,t,n;1==m&&(l=0==Vl.ori?Nn:jn,t=ri(l,Ll),i=vt.idx=e(t,r[0],Zt,Jt),n=ql(r[0][i],Vl,o,0));let u=-10,a=-10,f=0,h=0,d=!0,g="",w="";for(let l=2==m?1:0;Cl.length>l;l++){let e=Cl[l],_=te[l],v=null==_?null:1==m?r[l][_]:r[l][1][_],k=vt.dataIdx(c,l,i,t),b=null==k?null:1==m?r[l][k]:r[l][1][k];gt=gt||b!=v||k!=_,te[l]=k;let y=k==i?n:ql(1==m?r[0][k]:r[l][0][k],Vl,o,0);if(l>0&&e.show){let t=null==b?-10:Kl(b,1==m?Fl[e.scale]:Fl[e.facets[1].scale],s,0);if(Nt&&null!=b){let n=1==Vl.ori?Nn:jn,i=p(St.dist(c,l,k,t,n));if(ni>i){let t=St.bias;if(0!=t){let o=ri(n,e.scale),s=0>o?-1:1;s!=(0>b?-1:1)||(1==s?1==t?o>b:b>o:1==t?b>o:o>b)||(ni=i,ii=l)}else ni=i,ii=l}}if(gt||jt){let e,n;0==Vl.ori?(e=y,n=t):(e=t,n=y);let i,o,s,r,p,m,_=!0,v=bt.bbox;if(null!=v){_=!1;let e=v(c,l);s=e.left,r=e.top,i=e.width,o=e.height}else s=e,r=n,i=o=bt.size(c,l);if(m=bt.fill(c,l),p=bt.stroke(c,l),jt)l!=ii||ni>St.prox||(u=s,a=r,f=i,h=o,d=_,g=m,w=p);else{let e=Bt[l];null!=e&&(Ht[l]=s,Ut[l]=r,Gl(e,i,o,_),Rl(e,m,p),Ml(e,x(s),x(r),Xe,Je))}}}}if(jt){let l=St.prox;if(gt||(null==oi?l>=ni:ni>l||ii!=oi)){let l=Bt[0];Ht[0]=u,Ut[0]=a,Gl(l,f,h,d),Rl(l,g,w),Ml(l,x(u),x(a),Xe,Je)}}}if(Jn.show&&qn)if(null!=l){let[e,t]=Ii.scales,[n,i]=Ii.match,[r,u]=l.cursor.sync.scales,a=l.cursor.drag;if(Xn=a._x,Zn=a._y,Xn||Zn){let a,f,c,h,d,{left:m,top:g,width:x,height:_}=l.select,v=l.scales[r].ori,k=l.posToVal,b=null!=e&&n(e,r),y=null!=t&&i(t,u);b&&Xn?(0==v?(a=m,f=x):(a=g,f=_),c=Fl[e],h=ql(k(a,r),c,o,0),d=ql(k(a+f,r),c,o,0),fi(w(h,d),p(d-h))):fi(0,o),y&&Zn?(1==v?(a=m,f=x):(a=g,f=_),c=Fl[t],h=Kl(k(a,u),c,s,0),d=Kl(k(a+f,u),c,s,0),ci(w(h,d),p(d-h))):ci(0,s)}else vi()}else{let l=p(On-In),e=p(Ln-Rn);if(1==Vl.ori){let t=l;l=e,e=t}Xn=Kn.x&&l>=Kn.dist,Zn=Kn.y&&e>=Kn.dist;let t,n,i=Kn.uni;null!=i?Xn&&Zn&&(Xn=l>=i,Zn=e>=i,Xn||Zn||(e>l?Zn=!0:Xn=!0)):Kn.x&&Kn.y&&(Xn||Zn)&&(Xn=Zn=!0),Xn&&(0==Vl.ori?(t=Fn,n=Nn):(t=Gn,n=jn),fi(w(t,n),p(n-t)),Zn||ci(0,s)),Zn&&(1==Vl.ori?(t=Fn,n=Nn):(t=Gn,n=jn),ci(w(t,n),p(n-t)),Xn||fi(0,o)),Xn||Zn||(fi(0,0),ci(0,0))}if(Kn._x=Xn,Kn._y=Zn,null==l){if(n){if(null!=Ri){let[l,e]=Ii.scales;Ii.values[0]=null!=l?ri(0==Vl.ori?Nn:jn,l):null,Ii.values[1]=null!=e?ri(1==Vl.ori?Nn:jn,e):null}Gi(fl,c,Nn,jn,Xe,Je,i)}if(Nt){let l=n&&Ii.setSeries,e=St.prox;null==oi?ni>e||ti(ii,si,!0,l):ni>e?ti(null,si,!0,l):ii!=oi&&ti(ii,si,!0,l)}}gt&&(ne.idx=i,hi()),!1!==t&&Ci("setCursor")}c.setLegend=hi;let mi=null;function gi(l=!1){l?mi=null:(mi=ul.getBoundingClientRect(),Ci("syncRect",mi))}function xi(l,e,t,n,i,o){vt._lock||qn&&null!=l&&0==l.movementX&&0==l.movementY||(wi(l,e,t,n,i,o,0,!1,null!=l),null!=l?pi(null,!0,!0):pi(e,!0,!1))}function wi(l,e,t,n,i,o,s,r,u){if(null==mi&&gi(!1),kt(l),null!=l)t=l.clientX-mi.left,n=l.clientY-mi.top;else{if(0>t||0>n)return Nn=-10,void(jn=-10);let[l,s]=Ii.scales,r=e.cursor.sync,[u,a]=r.values,[f,c]=r.scales,[h,d]=Ii.match,p=e.axes[0].side%2==1,m=0==Vl.ori?Xe:Je,g=1==Vl.ori?Xe:Je,x=p?o:i,w=p?i:o,_=p?n:t,v=p?t:n;if(t=null!=f?h(l,f)?O(u,Fl[l],m,0):-10:m*(_/x),n=null!=c?d(s,c)?O(a,Fl[s],g,0):-10:g*(v/w),1==Vl.ori){let l=t;t=n,n=l}}u&&(t>1&&Xe-1>t||(t=G(t,Xe)),n>1&&Je-1>n||(n=G(n,Je))),r?(In=t,Rn=n,[Fn,Gn]=vt.move(c,t,n)):(Nn=t,jn=n)}Object.defineProperty(c,"rect",{get:()=>(null==mi&&gi(!1),mi)});const _i={width:0,height:0,left:0,top:0};function vi(){li(_i,!1)}let ki,bi,yi,Si;function Ei(l,e,t,n,i,o){qn=!0,Xn=Zn=Kn._x=Kn._y=!1,wi(l,e,t,n,i,o,0,!0,!1),null!=l&&(Oe(hl,bl,Ti,!1),Gi(cl,c,Fn,Gn,Xe,Je,null));let{left:s,top:r,width:u,height:a}=Jn;ki=s,bi=r,yi=u,Si=a,vi()}function Ti(l,e,t,n,i,o){qn=Kn._x=Kn._y=!1,wi(l,e,t,n,i,o,0,!1,!0);let{left:s,top:r,width:u,height:a}=Jn,f=u>0||a>0,h=ki!=s||bi!=r||yi!=u||Si!=a;if(f&&h&&li(Jn),Kn.setScale&&f&&h){let l=s,e=u,t=r,n=a;if(1==Vl.ori&&(l=r,e=a,t=s,n=u),Xn&&ei(Ll,ri(l,Ll),ri(l+e,Ll)),Zn)for(let l in Fl){let e=Fl[l];l!=Ll&&null==e.from&&e.min!=E&&ei(l,ri(t+n,l),ri(t,l))}vi()}else vt.lock&&(vt._lock=!vt._lock,pi(null,!0,!1));null!=l&&(Le(hl,bl),Gi(hl,c,Nn,jn,Xe,Je,null))}function zi(l){vt._lock||(kt(l),pn(),vi(),null!=l&&Gi(ml,c,Nn,jn,Xe,Je,null))}function Pi(){Il.forEach(Lt),xt(c.width,c.height,!0)}Nl(xl,yl,Pi);const Di={};Di.mousedown=Ei,Di.mousemove=xi,Di.mouseup=Ti,Di.dblclick=zi,Di.setSeries=(l,e,t,n)=>{-1!=(t=(0,Ii.match[2])(c,e,t))&&ti(t,n,!0,!1)},vt.show&&(Oe(cl,ul,Ei),Oe(fl,ul,xi),Oe(dl,ul,(l=>{kt(l),gi(!1)})),Oe(pl,ul,(function(l){if(vt._lock)return;kt(l);let e=qn;if(qn){let l,e,t=!0,n=!0,i=10;0==Vl.ori?(l=Xn,e=Zn):(l=Zn,e=Xn),l&&e&&(t=i>=Nn||Nn>=Xe-i,n=i>=jn||jn>=Je-i),l&&t&&(Nn=Fn>Nn?0:Xe),e&&n&&(jn=Gn>jn?0:Je),pi(null,!0,!0),qn=!1}Nn=-10,jn=-10,pi(null,!0,!0),e&&(qn=e)})),Oe(ml,ul,zi),yt.add(c),c.syncRect=gi);const Ai=c.hooks=t.hooks||{};function Ci(l,e,t){Hn?Un.push([l,e,t]):l in Ai&&Ai[l].forEach((l=>{l.call(null,c,e,t)}))}(t.plugins||[]).forEach((l=>{for(let e in l.hooks)Ai[e]=(Ai[e]||[]).concat(l.hooks[e])}));const Mi=(l,e,t)=>t,Ii=Q({key:null,setSeries:!1,filters:{pub:M,sub:M},scales:[Ll,Cl[1]?Cl[1].scale:null],match:[I,I,Mi],values:[null,null]},vt.sync);2==Ii.match.length&&Ii.match.push(Mi),vt.sync=Ii;const Ri=Ii.key,Fi=Ze(Ri);function Gi(l,e,t,n,i,o,s){Ii.filters.pub(l,e,t,n,i,o,s)&&Fi.pub(l,e,t,n,i,o,s)}function Oi(){Ci("init",t,r),dn(r||t.data,!1),Xl[Ll]?Wn(Ll,Xl[Ll]):pn(),mt=Jn.show&&(Jn.width>0||Jn.height>0),pt=gt=!0,xt(t.width,t.height)}return Fi.sub(c),c.pub=function(l,e,t,n,i,o,s){Ii.filters.sub(l,e,t,n,i,o,s)&&Di[l](null,e,t,n,i,o,s)},c.destroy=function(){Fi.unsub(c),yt.delete(c),Ge.clear(),jl(xl,yl,Pi),H.remove(),we?.remove(),Ci("destroy")},Cl.forEach(Yt),Il.forEach((function(l,e){if(l._show=l.show,l.show){let t=Fl[l.scale];null==t&&(l.scale=l.side%2?Cl[1].scale:Ll,t=Fl[l.scale]);let n=t.time;l.size=P(l.size),l.space=P(l.space),l.rotate=P(l.rotate),$(l.incrs)&&l.incrs.forEach((l=>{!j.has(l)&&j.set(l,B(l))})),l.incrs=P(l.incrs||(2==t.distr?$l:n?1==El?oe:ue:Wl)),l.splits=P(l.splits||(n&&1==t.distr?Ql:3==t.distr?Me:4==t.distr?Ie:Ce)),l.stroke=P(l.stroke),l.grid.stroke=P(l.grid.stroke),l.ticks.stroke=P(l.ticks.stroke),l.border.stroke=P(l.border.stroke);let i=l.values;l.values=$(i)&&!$(i[0])?P(i):n?$(i)?he(Zl,ce(i,Jl)):i||le:i||Ae,l.filter=P(l.filter||(3>t.distr||10!=t.log?3==t.distr&&2==t.log?je:A:Ne)),l.font=Ot(l.font),l.labelFont=Ot(l.labelFont),l._size=l.size(c,null,e,0),l._space=l._rotate=l._incrs=l._found=l._splits=l._values=null,l._size>0&&($t[e]=!0,l._el=Al("u-axis",Z))}})),u?u instanceof HTMLElement?(u.appendChild(H),Oi()):u(c,Oi):Oi(),c}Nt.assign=Q,Nt.rangeNum=a,Nt.rangeLog=n,Nt.rangeAsinh=i,Nt.orient=Je,Nt.pxRatio=Sl,Nt.join=function(l,e){if(function(l){let e=l[0][0],t=e.length;for(let n=1;l.length>n;n++){let i=l[n][0];if(i.length!=t)return!1;if(i!=e)for(let l=0;t>l;l++)if(i[l]!=e[l])return!1}return!0}(l)){let e=l[0].slice();for(let t=1;l.length>t;t++)e.push(...l[t].slice(1));return function(l,e=100){const t=l.length;if(1>=t)return!0;let n=0,i=t-1;for(;i>=n&&null==l[n];)n++;for(;i>=n&&null==l[i];)i--;if(n>=i)return!0;const o=_(1,m((i-n+1)/e));for(let e=l[n],t=n+o;i>=t;t+=o){const n=l[t];if(null!=n){if(e>=n)return!1;e=n}}return!0}(e[0])||(e=function(l){let e=l[0],t=e.length,n=Array(t);for(let l=0;n.length>l;l++)n[l]=l;n.sort(((l,t)=>e[l]-e[t]));let i=[];for(let e=0;l.length>e;e++){let o=l[e],s=Array(t);for(let l=0;t>l;l++)s[l]=o[n[l]];i.push(s)}return i}(e)),e}let t=new Set;for(let e=0;l.length>e;e++){let n=l[e][0],i=n.length;for(let l=0;i>l;l++)t.add(n[l])}let n=[Array.from(t).sort(((l,e)=>l-e))],i=n[0].length,o=new Map;for(let l=0;i>l;l++)o.set(n[0][l],l);for(let t=0;l.length>t;t++){let s=l[t],r=s[0];for(let l=1;s.length>l;l++){let u=s[l],a=Array(i).fill(void 0),f=e?e[t][l]:1,c=[];for(let l=0;u.length>l;l++){let e=u[l],t=o.get(r[l]);null===e?0!=f&&(a[t]=e,2==f&&c.push(t)):a[t]=e}ll(a,c,i),n.push(a)}}return n},Nt.tzDate=function(l,e){let t;return"UTC"==e||"Etc/UTC"==e?t=new Date(+l+6e4*l.getTimezoneOffset()):e==Bl?t=l:(t=new Date(l.toLocaleString("en-US",{timeZone:e})),t.setMilliseconds(l.getMilliseconds())),t},Nt.sync=Ze;{Nt.addGap=function(l,e,t){let n=l[l.length-1];n&&n[0]==e?n[1]=t:l.push([e,t])},Nt.clipGaps=tt;let l=Nt.paths={points:gt};l.linear=vt,l.stepped=function(l){const e=f(l.align,1),n=f(l.ascDesc,!1),i=f(l.alignGaps,0),o=f(l.extend,!1);return(l,s,r,u)=>Je(l,s,((a,f,c,h,d,p,m,g,x,w,_)=>{let v=a.pxRound,{left:k,width:b}=l.bbox,y=l=>v(p(l,h,w,g)),S=l=>v(m(l,d,_,x)),E=0==h.ori?ut:at;const T={stroke:new Path2D,fill:null,clip:null,band:null,gaps:null,flags:1},z=T.stroke,P=h.dir*(0==h.ori?1:-1);r=t(c,r,u,1),u=t(c,r,u,-1);let D=S(c[1==P?r:u]),A=y(f[1==P?r:u]),C=A,M=A;o&&-1==e&&(M=k,E(z,M,D)),E(z,A,D);for(let l=1==P?r:u;l>=r&&u>=l;l+=P){let t=c[l];if(null==t)continue;let n=y(f[l]),i=S(t);1==e?E(z,n,D):E(z,C,i),E(z,n,i),D=i,C=n}let I=C;o&&1==e&&(I=k+b,E(z,I,D));let[R,F]=Qe(l,s);if(null!=a.fill||0!=R){let e=T.fill=new Path2D(z),t=S(a.fillTo(l,s,a.min,a.max,R));E(e,I,t),E(e,M,t)}if(!a.spanGaps){let t=[];t.push(...nt(f,c,r,u,P,y,i));let o=a.width*Sl/2,d=n||1==e?o:-o,p=n||-1==e?-o:o;t.forEach((l=>{l[0]+=d,l[1]+=p})),T.gaps=t=a.gaps(l,s,r,u,t),T.clip=tt(t,h.ori,g,x,w,_)}return 0!=F&&(T.band=2==F?[et(l,s,r,u,z,-1),et(l,s,r,u,z,1)]:et(l,s,r,u,z,F)),T}))},l.bars=function(l){const e=f((l=l||U).size,[.6,E,1]),t=l.align||0,n=l.gap||0;let i=l.radius;i=null==i?[0,0]:"number"==typeof i?[i,0]:i;const o=P(i),s=1-e[0],r=f(e[1],E),u=f(e[2],1),a=f(l.disp,U),c=f(l.each,(()=>{})),{fill:h,stroke:d}=a;return(l,e,i,p)=>Je(l,e,((g,x,v,k,b,y,S,E,T,P,A)=>{let C,M,I=g.pxRound,R=t,F=n*Sl,G=r*Sl,O=u*Sl;0==k.ori?[C,M]=o(l,e):[M,C]=o(l,e);const L=k.dir*(0==k.ori?1:-1);let N,j,B,H=0==k.ori?ft:ct,U=0==k.ori?c:(l,e,t,n,i,o,s)=>{c(l,e,t,i,n,s,o)},Y=f(l.bands,V).find((l=>l.series[0]==e)),$=g.fillTo(l,e,g.min,g.max,null!=Y?Y.dir:0),W=I(S($,b,A,T)),q=P,K=I(g.width*Sl),X=!1,Z=null,J=null,Q=null,ll=null;null==h||0!=K&&null==d||(X=!0,Z=h.values(l,e,i,p),J=new Map,new Set(Z).forEach((l=>{null!=l&&J.set(l,new Path2D)})),K>0&&(Q=d.values(l,e,i,p),ll=new Map,new Set(Q).forEach((l=>{null!=l&&ll.set(l,new Path2D)}))));let{x0:el,size:tl}=a;if(null!=el&&null!=tl){R=1,x=el.values(l,e,i,p),2==el.unit&&(x=x.map((e=>l.posToVal(E+e*P,k.key,!0))));let t=tl.values(l,e,i,p);j=2==tl.unit?t[0]*P:y(t[0],k,P,E)-y(0,k,P,E),q=kt(x,v,y,k,P,E,q),B=q-j+F}else q=kt(x,v,y,k,P,E,q),B=q*s+F,j=q-B;1>B&&(B=0),j/2>K||(K=0),5>B&&(I=D);let nl=B>0;j=I(z(q-B-(nl?K:0),O,G)),N=(0==R?j/2:R==L?0:j)-R*L*((0==R?F/2:0)+(nl?K/2:0));const il={stroke:null,fill:null,clip:null,band:null,gaps:null,flags:0},ol=X?null:new Path2D;let sl=null;if(null!=Y)sl=l.data[Y.series[1]];else{let{y0:t,y1:n}=a;null!=t&&null!=n&&(v=n.values(l,e,i,p),sl=t.values(l,e,i,p))}let rl=C*j,ul=M*j;for(let t=1==L?i:p;t>=i&&p>=t;t+=L){let n=v[t];if(null==n)continue;if(null!=sl){let l=sl[t]??0;if(n-l==0)continue;W=S(l,b,A,T)}let i=y(2!=k.distr||null!=a?x[t]:t,k,P,E),o=S(f(n,$),b,A,T),s=I(i-N),r=I(_(o,W)),u=I(w(o,W)),c=r-u;if(null!=n){let i=0>n?ul:rl,o=0>n?rl:ul;X?(K>0&&null!=Q[t]&&H(ll.get(Q[t]),s,u+m(K/2),j,_(0,c-K),i,o),null!=Z[t]&&H(J.get(Z[t]),s,u+m(K/2),j,_(0,c-K),i,o)):H(ol,s,u+m(K/2),j,_(0,c-K),i,o),U(l,e,t,s-K/2,u,j+K,c)}}return K>0?il.stroke=X?ll:ol:X||(il._fill=0==g.width?g._fill:g._stroke??g._fill,il.width=0),il.fill=X?J:ol,il}))},l.spline=function(l){return function(l,e){const n=f(e?.alignGaps,0);return(e,i,o,s)=>Je(e,i,((r,u,a,f,c,h,d,p,m,g,x)=>{let w,_,v,k=r.pxRound,b=l=>k(h(l,f,g,p)),y=l=>k(d(l,c,x,m));0==f.ori?(w=st,v=ut,_=pt):(w=rt,v=at,_=mt);const S=f.dir*(0==f.ori?1:-1);o=t(a,o,s,1),s=t(a,o,s,-1);let E=b(u[1==S?o:s]),T=E,z=[],P=[];for(let l=1==S?o:s;l>=o&&s>=l;l+=S)if(null!=a[l]){let e=b(u[l]);z.push(T=e),P.push(y(a[l]))}const D={stroke:l(z,P,w,v,_,k),fill:null,clip:null,band:null,gaps:null,flags:1},A=D.stroke;let[C,M]=Qe(e,i);if(null!=r.fill||0!=C){let l=D.fill=new Path2D(A),t=y(r.fillTo(e,i,r.min,r.max,C));v(l,T,t),v(l,E,t)}if(!r.spanGaps){let l=[];l.push(...nt(u,a,o,s,S,b,n)),D.gaps=l=r.gaps(e,i,o,s,l),D.clip=tt(l,f.ori,p,m,g,x)}return 0!=M&&(D.band=2==M?[et(e,i,o,s,A,-1),et(e,i,o,s,A,1)]:et(e,i,o,s,A,M)),D}))}(bt,l)}}return Nt}(); diff --git a/src/fmtDate.js b/src/fmtDate.js deleted file mode 100644 index 2bc31af0..00000000 --- a/src/fmtDate.js +++ /dev/null @@ -1,146 +0,0 @@ -import { - FEAT_TIME, -} from './feats'; - -const months = [ - "January", - "February", - "March", - "April", - "May", - "June", - "July", - "August", - "September", - "October", - "November", - "December", -]; - -const days = [ - "Sunday", - "Monday", - "Tuesday", - "Wednesday", - "Thursday", - "Friday", - "Saturday", -]; - -function slice3(str) { - return str.slice(0, 3); -} - -const days3 = FEAT_TIME && days.map(slice3); - -const months3 = FEAT_TIME && months.map(slice3); - -const engNames = { - MMMM: months, - MMM: months3, - WWWW: days, - WWW: days3, -}; - -function zeroPad2(int) { - return (int < 10 ? '0' : '') + int; -} - -function zeroPad3(int) { - return (int < 10 ? '00' : int < 100 ? '0' : '') + int; -} - -/* -function suffix(int) { - let mod10 = int % 10; - - return int + ( - mod10 == 1 && int != 11 ? "st" : - mod10 == 2 && int != 12 ? "nd" : - mod10 == 3 && int != 13 ? "rd" : "th" - ); -} -*/ - -const subs = { - // 2019 - YYYY: d => d.getFullYear(), - // 19 - YY: d => (d.getFullYear()+'').slice(2), - // July - MMMM: (d, names) => names.MMMM[d.getMonth()], - // Jul - MMM: (d, names) => names.MMM[d.getMonth()], - // 07 - MM: d => zeroPad2(d.getMonth()+1), - // 7 - M: d => d.getMonth()+1, - // 09 - DD: d => zeroPad2(d.getDate()), - // 9 - D: d => d.getDate(), - // Monday - WWWW: (d, names) => names.WWWW[d.getDay()], - // Mon - WWW: (d, names) => names.WWW[d.getDay()], - // 03 - HH: d => zeroPad2(d.getHours()), - // 3 - H: d => d.getHours(), - // 9 (12hr, unpadded) - h: d => {let h = d.getHours(); return h == 0 ? 12 : h > 12 ? h - 12 : h;}, - // AM - AA: d => d.getHours() >= 12 ? 'PM' : 'AM', - // am - aa: d => d.getHours() >= 12 ? 'pm' : 'am', - // a - a: d => d.getHours() >= 12 ? 'p' : 'a', - // 09 - mm: d => zeroPad2(d.getMinutes()), - // 9 - m: d => d.getMinutes(), - // 09 - ss: d => zeroPad2(d.getSeconds()), - // 9 - s: d => d.getSeconds(), - // 374 - fff: d => zeroPad3(d.getMilliseconds()), -}; - -export function fmtDate(tpl, names) { - names = names || engNames; - let parts = []; - - let R = /\{([a-z]+)\}|[^{]+/gi, m; - - while (m = R.exec(tpl)) - parts.push(m[0][0] == '{' ? subs[m[1]] : m[0]); - - return d => { - let out = ''; - - for (let i = 0; i < parts.length; i++) - out += typeof parts[i] == "string" ? parts[i] : parts[i](d, names); - - return out; - } -} - -const localTz = new Intl.DateTimeFormat().resolvedOptions().timeZone; - -// https://stackoverflow.com/questions/15141762/how-to-initialize-a-javascript-date-to-a-particular-time-zone/53652131#53652131 -export function tzDate(date, tz) { - let date2; - - // perf optimization - if (tz == 'UTC' || tz == 'Etc/UTC') - date2 = new Date(+date + date.getTimezoneOffset() * 6e4); - else if (tz == localTz) - date2 = date; - else { - date2 = new Date(date.toLocaleString('en-US', {timeZone: tz})); - date2.setMilliseconds(date.getMilliseconds()); - } - - return date2; -} \ No newline at end of file diff --git a/src/opts.js b/src/opts.js index f93e40ae..5d5084b8 100644 --- a/src/opts.js +++ b/src/opts.js @@ -18,7 +18,6 @@ import { incrRoundUp, roundDec, floor, - fmtNum, fixedDec, retArg1, @@ -40,8 +39,6 @@ import { setStylePx, } from './dom'; -import { fmtDate } from './fmtDate'; - //export const series = []; // default formatters: @@ -63,17 +60,14 @@ export const numIncrs = decIncrs.concat(oneIncrs); const NL = "\n"; -const yyyy = "{YYYY}"; -const NLyyyy = NL + yyyy; -const md = "{M}/{D}"; -const NLmd = NL + md; -const NLmdyy = NLmd + "/{YY}"; - -const aa = "{aa}"; -const hmm = "{h}:{mm}"; -const hmmaa = hmm + aa; -const NLhmmaa = NL + hmmaa; -const ss = ":{ss}"; +let YYYY = {year: 'numeric'}; +let MM = {month: 'numeric'}; +let MMM = {month: 'short'}; +let dd = {day: 'numeric'}; +let hh = {hour: 'numeric'}; +let mm = {minute: 'numeric'}; +let ss = {second: 'numeric'}; +let fff = { fractionalSecondDigits: 3}; const _ = null; @@ -140,18 +134,18 @@ function genTimeStuffs(ms) { // [0]: minimum num secs in the tick incr // [1]: default tick format // [2-7]: rollover tick formats - // [8]: mode: 0: replace [1] -> [2-7], 1: concat [1] + [2-7] + // [8]: mode: 0: replace [1] -> [2-7], 1: merge [2-7] + \n + [1] const _timeAxisStamps = [ - // tick incr default year month day hour min sec mode - [y, yyyy, _, _, _, _, _, _, 1], - [d * 28, "{MMM}", NLyyyy, _, _, _, _, _, 1], - [d, md, NLyyyy, _, _, _, _, _, 1], - [h, "{h}" + aa, NLmdyy, _, NLmd, _, _, _, 1], - [m, hmmaa, NLmdyy, _, NLmd, _, _, _, 1], - [s, ss, NLmdyy + " " + hmmaa, _, NLmd + " " + hmmaa, _, NLhmmaa, _, 1], - [ms, ss + ".{fff}", NLmdyy + " " + hmmaa, _, NLmd + " " + hmmaa, _, NLhmmaa, _, 1], + // tick incr default year month day hour min sec mode + [y, { ...YYYY }, _, _, _, _, _, _, 1], + [d * 28, { ...MMM }, {...YYYY}, _, _, _, _, _, 1], + [d, { ...MM, ...dd }, {...YYYY}, _, _, _, _, _, 1], + [h, { ...hh }, { ...YYYY, ...MM, ...dd}, _, {...MM, ...dd}, _, _, _, 1], + [m, { ...hh, ...mm }, { ...YYYY, ...MM, ...dd}, _, {...MM, ...dd}, _, _, _, 1], + [s, { ...ss }, { ...YYYY, ...MM, ...dd, ...hh, ...mm}, _, {...MM, ...dd, ...hh, ...mm}, _, {...hh, ...mm}, _, 1], + [ms, { ...ss, ...fff }, { ...YYYY, ...MM, ...dd, ...hh, ...mm}, _, {...MM, ...dd, ...hh, ...mm}, _, {...hh, ...mm}, _, 1], ]; - + // the ensures that axis ticks, values & grid are aligned to logical temporal breakpoints and not an arbitrary timestamp // https://www.timeanddate.com/time/dst/ // https://www.timeanddate.com/time/dst/2019.html @@ -264,8 +258,18 @@ console.log({ */ export function timeAxisStamps(stampCfg, fmtDate) { - return stampCfg.map(s => s.map((v, i) => - i == 0 || i == 8 || v == null ? v : fmtDate(i == 1 || s[8] == 0 ? v : s[1] + v) + return stampCfg.map(s => s.map((v, i) => { + if (i == 0 || i == 8 || v == null) { + return v + } + const line1 = fmtDate(v) + if (i == 1 || s[8] == 0) { + return line1 + } else { + const line2 = fmtDate(s[1]) + return (date) => line2(date)+NL+line1(date) + } + } )); } @@ -329,7 +333,7 @@ export function timeSeriesStamp(stampCfg, fmtDate) { return fmtDate(stampCfg); }; -export const _timeSeriesStamp = '{YYYY}-{MM}-{DD} {h}:{mm}{aa}'; +export const _timeSeriesStamp = { ...YYYY, ...MM, ...dd, ...hh, ...mm }; export function timeSeriesVal(tzDate, stamp) { return (self, val, seriesIdx, dataIdx) => dataIdx == null ? LEGEND_DISP : stamp(tzDate(val)); @@ -540,7 +544,7 @@ export const xSeriesOpts = { idxs: [], }; -export function numAxisVals(self, splits, axisIdx, foundSpace, foundIncr) { +export function numAxisVals(self, splits, axisIdx, foundSpace, foundIncr, fmtNum) { return splits.map(v => v == null ? "" : fmtNum(v)); } @@ -663,7 +667,7 @@ export function log2AxisValsFilt(self, splits, axisIdx, foundSpace, foundIncr) { return splits; } -export function numSeriesVal(self, val, seriesIdx, dataIdx) { +export function numSeriesVal(self, val, seriesIdx, dataIdx, fmtNum) { return dataIdx == null ? LEGEND_DISP : val == null ? "" : fmtNum(val); } @@ -790,4 +794,4 @@ export const xScaleOpts = { export const yScaleOpts = assign({}, xScaleOpts, { time: false, ori: 1, -}); \ No newline at end of file +}); diff --git a/src/tzDate.js b/src/tzDate.js new file mode 100644 index 00000000..10658704 --- /dev/null +++ b/src/tzDate.js @@ -0,0 +1,19 @@ + +const localTz = new Intl.DateTimeFormat().resolvedOptions().timeZone; + +// https://stackoverflow.com/questions/15141762/how-to-initialize-a-javascript-date-to-a-particular-time-zone/53652131#53652131 +export function tzDate(date, tz) { + let date2; + + // perf optimization + if (tz == 'UTC' || tz == 'Etc/UTC') + date2 = new Date(+date + date.getTimezoneOffset() * 6e4); + else if (tz == localTz) + date2 = date; + else { + date2 = new Date(date.toLocaleString('en-US', {timeZone: tz})); + date2.setMilliseconds(date.getMilliseconds()); + } + + return date2; +} diff --git a/src/uPlot.js b/src/uPlot.js index 3421ba68..7fb193df 100644 --- a/src/uPlot.js +++ b/src/uPlot.js @@ -1,22 +1,20 @@ import { FEAT_TIME, FEAT_LEGEND, - FEAT_POINTS, - FEAT_PATHS, FEAT_PATHS_LINEAR, FEAT_PATHS_SPLINE, FEAT_PATHS_SPLINE2, FEAT_PATHS_STEPPED, FEAT_PATHS_BARS, - - FEAT_JOIN, -} from './feats'; + FEAT_JOIN +} from './feats' import { copy, assign, + browserLocale, PI, inf, abs, @@ -44,7 +42,6 @@ import { fastIsObj, isStr, fnOrSelf, - fmtNum, fixedDec, ifNull, join, @@ -63,8 +60,8 @@ import { numIntDigits, isUndef, guessDec, - cmpObj, -} from './utils'; + cmpObj +} from './utils' import { WIDTH, @@ -74,7 +71,6 @@ import { LEFT, RIGHT, transparent, - mousemove, mousedown, mouseup, @@ -83,10 +79,9 @@ import { dblclick, resize, scroll, - dppxchange, LEGEND_DISP -} from './strings'; +} from './strings' import { UPLOT, @@ -108,15 +103,14 @@ import { LEGEND_SERIES, LEGEND_MARKER, LEGEND_LABEL, - LEGEND_VALUE, -} from './domClasses'; + LEGEND_VALUE +} from './domClasses' import { domEnv, doc, win, pxRatio, - addClass, remClass, setStylePx, @@ -126,361 +120,447 @@ import { elColor, elSize, on, - off, -} from './dom'; + off +} from './dom' -import { - fmtDate, - tzDate, -} from './fmtDate'; +import { tzDate } from './tzDate' import { ptDia, cursorOpts, - xAxisOpts, yAxisOpts, xSeriesOpts, ySeriesOpts, xScaleOpts, yScaleOpts, - xySeriesOpts, - clampScale, - timeIncrsMs, timeIncrsS, - wholeIncrs, numIncrs, timeAxisVal, timeAxisVals, numAxisVals, - log2AxisValsFilt, log10AxisValsFilt, - timeSeriesVal, numSeriesVal, - timeSeriesLabel, numSeriesLabel, - timeAxisSplitsMs, timeAxisSplitsS, - numAxisSplits, logAxisSplits, asinhAxisSplits, - timeAxisStamps, - _timeAxisStampsMs, _timeAxisStampsS, - timeSeriesStamp, _timeSeriesStamp, + legendOpts +} from './opts' - legendOpts, -} from './opts'; - -import { _sync } from './sync'; +import { _sync } from './sync' -import { points } from './paths/points'; -import { linear } from './paths/linear'; -import { stepped } from './paths/stepped'; -import { bars } from './paths/bars'; -import { monotoneCubic as spline } from './paths/monotoneCubic'; -import { catmullRomCentrip as spline2 } from './paths/catmullRomCentrip'; +import { points } from './paths/points' +import { linear } from './paths/linear' +import { stepped } from './paths/stepped' +import { bars } from './paths/bars' +import { monotoneCubic as spline } from './paths/monotoneCubic' +import { catmullRomCentrip as spline2 } from './paths/catmullRomCentrip' -import { addGap, clipGaps, moveToH, moveToV, arcH, arcV, orient, pxRoundGen, seriesFillTo, BAND_CLIP_FILL, BAND_CLIP_STROKE } from './paths/utils'; +import { + addGap, + clipGaps, + moveToH, + moveToV, + arcH, + arcV, + orient, + pxRoundGen, + seriesFillTo, + BAND_CLIP_FILL, + BAND_CLIP_STROKE +} from './paths/utils' function log(name, args) { - console.log.apply(console, [name].concat(Array.prototype.slice.call(args))); + console.log.apply(console, [name].concat(Array.prototype.slice.call(args))) } -const cursorPlots = new Set(); +const cursorPlots = new Set() function invalidateRects() { - for (let u of cursorPlots) - u.syncRect(true); + for (let u of cursorPlots) u.syncRect(true) } if (domEnv) { - on(resize, win, invalidateRects); - on(scroll, win, invalidateRects, true); - on(dppxchange, win, () => { uPlot.pxRatio = pxRatio; }); + on(resize, win, invalidateRects) + on(scroll, win, invalidateRects, true) + on(dppxchange, win, () => { + uPlot.pxRatio = pxRatio + }) } -const linearPath = FEAT_PATHS && FEAT_PATHS_LINEAR ? linear() : null; -const pointsPath = FEAT_POINTS ? points() : null; +const linearPath = FEAT_PATHS && FEAT_PATHS_LINEAR ? linear() : null +const pointsPath = FEAT_POINTS ? points() : null function setDefaults(d, xo, yo, initY) { - let d2 = initY ? [d[0], d[1]].concat(d.slice(2)) : [d[0]].concat(d.slice(1)); - return d2.map((o, i) => setDefault(o, i, xo, yo)); + let d2 = initY ? [d[0], d[1]].concat(d.slice(2)) : [d[0]].concat(d.slice(1)) + return d2.map((o, i) => setDefault(o, i, xo, yo)) } function setDefaults2(d, xyo) { - return d.map((o, i) => i == 0 ? {} : assign({}, xyo, o)); // todo: assign() will not merge facet arrays + return d.map((o, i) => (i == 0 ? {} : assign({}, xyo, o))) // todo: assign() will not merge facet arrays } function setDefault(o, i, xo, yo) { - return assign({}, (i == 0 ? xo : yo), o); + return assign({}, i == 0 ? xo : yo, o) } function snapNumX(self, dataMin, dataMax) { - return dataMin == null ? nullNullTuple : [dataMin, dataMax]; + return dataMin == null ? nullNullTuple : [dataMin, dataMax] } -const snapTimeX = snapNumX; +const snapTimeX = snapNumX // this ensures that non-temporal/numeric y-axes get multiple-snapped padding added above/below // TODO: also account for incrs when snapping to ensure top of axis gets a tick & value function snapNumY(self, dataMin, dataMax) { - return dataMin == null ? nullNullTuple : rangeNum(dataMin, dataMax, rangePad, true); + return dataMin == null + ? nullNullTuple + : rangeNum(dataMin, dataMax, rangePad, true) } function snapLogY(self, dataMin, dataMax, scale) { - return dataMin == null ? nullNullTuple : rangeLog(dataMin, dataMax, self.scales[scale].log, false); + return dataMin == null + ? nullNullTuple + : rangeLog(dataMin, dataMax, self.scales[scale].log, false) } -const snapLogX = snapLogY; +const snapLogX = snapLogY function snapAsinhY(self, dataMin, dataMax, scale) { - return dataMin == null ? nullNullTuple : rangeAsinh(dataMin, dataMax, self.scales[scale].log, false); + return dataMin == null + ? nullNullTuple + : rangeAsinh(dataMin, dataMax, self.scales[scale].log, false) } -const snapAsinhX = snapAsinhY; +const snapAsinhX = snapAsinhY // dim is logical (getClientBoundingRect) pixels, not canvas pixels function findIncr(minVal, maxVal, incrs, dim, minSpace) { - let intDigits = max(numIntDigits(minVal), numIntDigits(maxVal)); + let intDigits = max(numIntDigits(minVal), numIntDigits(maxVal)) - let delta = maxVal - minVal; + let delta = maxVal - minVal - let incrIdx = closestIdx((minSpace / dim) * delta, incrs); + let incrIdx = closestIdx((minSpace / dim) * delta, incrs) do { - let foundIncr = incrs[incrIdx]; - let foundSpace = dim * foundIncr / delta; + let foundIncr = incrs[incrIdx] + let foundSpace = (dim * foundIncr) / delta - if (foundSpace >= minSpace && intDigits + (foundIncr < 5 ? fixedDec.get(foundIncr) : 0) <= 17) - return [foundIncr, foundSpace]; - } while (++incrIdx < incrs.length); + if ( + foundSpace >= minSpace && + intDigits + (foundIncr < 5 ? fixedDec.get(foundIncr) : 0) <= 17 + ) + return [foundIncr, foundSpace] + } while (++incrIdx < incrs.length) - return [0, 0]; + return [0, 0] } function pxRatioFont(font) { - let fontSize, fontSizeCss; - font = font.replace(/(\d+)px/, (m, p1) => (fontSize = round((fontSizeCss = +p1) * pxRatio)) + 'px'); - return [font, fontSize, fontSizeCss]; + let fontSize, fontSizeCss + font = font.replace( + /(\d+)px/, + (m, p1) => (fontSize = round((fontSizeCss = +p1) * pxRatio)) + 'px' + ) + return [font, fontSize, fontSizeCss] } function syncFontSize(axis) { if (axis.show) { - [axis.font, axis.labelFont].forEach(f => { - let size = roundDec(f[2] * pxRatio, 1); - f[0] = f[0].replace(/[0-9.]+px/, size + 'px'); - f[1] = size; - }); + ;[axis.font, axis.labelFont].forEach((f) => { + let size = roundDec(f[2] * pxRatio, 1) + f[0] = f[0].replace(/[0-9.]+px/, size + 'px') + f[1] = size + }) } } export default function uPlot(opts, data, then) { const self = { - mode: ifNull(opts.mode, 1), - }; + mode: ifNull(opts.mode, 1) + } - const mode = self.mode; + const mode = self.mode + + const numFormatter = new Intl.NumberFormat(opts.locale || browserLocale) + const fmtNum = (val) => numFormatter.format(val) + self.fmtNum = fmtNum + + const fmtDate = (tsOpts) => { + tsOpts.hourCycle = opts.hourCycle + return new Intl.DateTimeFormat(opts.locale || browserLocale, tsOpts) + .format + } + if (FEAT_TIME) { + self.fmtDate = fmtDate + } // TODO: cache denoms & mins scale.cache = {r, min, } function getValPct(val, scale) { - let _val = ( - scale.distr == 3 ? log10(val > 0 ? val : scale.clamp(self, val, scale.min, scale.max, scale.key)) : - scale.distr == 4 ? asinh(val, scale.asinh) : - scale.distr == 100 ? scale.fwd(val) : - val - ); - - return (_val - scale._min) / (scale._max - scale._min); + let _val = + scale.distr == 3 + ? log10( + val > 0 + ? val + : scale.clamp( + self, + val, + scale.min, + scale.max, + scale.key + ) + ) + : scale.distr == 4 + ? asinh(val, scale.asinh) + : scale.distr == 100 + ? scale.fwd(val) + : val + + return (_val - scale._min) / (scale._max - scale._min) } function getHPos(val, scale, dim, off) { - let pct = getValPct(val, scale); - return off + dim * (scale.dir == -1 ? (1 - pct) : pct); + let pct = getValPct(val, scale) + return off + dim * (scale.dir == -1 ? 1 - pct : pct) } function getVPos(val, scale, dim, off) { - let pct = getValPct(val, scale); - return off + dim * (scale.dir == -1 ? pct : (1 - pct)); + let pct = getValPct(val, scale) + return off + dim * (scale.dir == -1 ? pct : 1 - pct) } function getPos(val, scale, dim, off) { - return scale.ori == 0 ? getHPos(val, scale, dim, off) : getVPos(val, scale, dim, off); + return scale.ori == 0 + ? getHPos(val, scale, dim, off) + : getVPos(val, scale, dim, off) } - self.valToPosH = getHPos; + self.valToPosH = getHPos self.valToPosV = getVPos - let ready = false; - self.status = 0; + let ready = false + self.status = 0 - const root = self.root = placeDiv(UPLOT); + const root = (self.root = placeDiv(UPLOT)) - if (opts.id != null) - root.id = opts.id; + if (opts.id != null) root.id = opts.id - addClass(root, opts.class); + addClass(root, opts.class) if (opts.title) { - let title = placeDiv(TITLE, root); - title.textContent = opts.title; + let title = placeDiv(TITLE, root) + title.textContent = opts.title } - const can = placeTag("canvas"); - const ctx = self.ctx = can.getContext("2d"); + const can = placeTag('canvas') + const ctx = (self.ctx = can.getContext('2d')) - const wrap = placeDiv(WRAP, root); + const wrap = placeDiv(WRAP, root) - on("click", wrap, e => { - if (e.target === over) { - let didDrag = mouseLeft1 != mouseLeft0 || mouseTop1 != mouseTop0; - didDrag && drag.click(self, e); - } - }, true); + on( + 'click', + wrap, + (e) => { + if (e.target === over) { + let didDrag = mouseLeft1 != mouseLeft0 || mouseTop1 != mouseTop0 + didDrag && drag.click(self, e) + } + }, + true + ) - const under = self.under = placeDiv(UNDER, wrap); - wrap.appendChild(can); - const over = self.over = placeDiv(OVER, wrap); + const under = (self.under = placeDiv(UNDER, wrap)) + wrap.appendChild(can) + const over = (self.over = placeDiv(OVER, wrap)) - opts = copy(opts); + opts = copy(opts) - const pxAlign = +ifNull(opts.pxAlign, 1); + const pxAlign = +ifNull(opts.pxAlign, 1) - const pxRound = pxRoundGen(pxAlign); + const pxRound = pxRoundGen(pxAlign) - (opts.plugins || []).forEach(p => { - if (p.opts) - opts = p.opts(self, opts) || opts; - }); + ;(opts.plugins || []).forEach((p) => { + if (p.opts) opts = p.opts(self, opts) || opts + }) - const ms = opts.ms || 1e-3; + const ms = opts.ms || 1e-3 - const series = self.series = mode == 1 ? - setDefaults(opts.series || [], xSeriesOpts, ySeriesOpts, false) : - setDefaults2(opts.series || [null], xySeriesOpts); - const axes = self.axes = setDefaults(opts.axes || [], xAxisOpts, yAxisOpts, true); - const scales = self.scales = {}; - const bands = self.bands = opts.bands || []; + const series = (self.series = + mode == 1 + ? setDefaults(opts.series || [], xSeriesOpts, ySeriesOpts, false) + : setDefaults2(opts.series || [null], xySeriesOpts)) + const axes = (self.axes = setDefaults( + opts.axes || [], + xAxisOpts, + yAxisOpts, + true + )) + const scales = (self.scales = {}) + const bands = (self.bands = opts.bands || []) - bands.forEach(b => { - b.fill = fnOrSelf(b.fill || null); - b.dir = ifNull(b.dir, -1); - }); + bands.forEach((b) => { + b.fill = fnOrSelf(b.fill || null) + b.dir = ifNull(b.dir, -1) + }) - const xScaleKey = mode == 2 ? series[1].facets[0].scale : series[0].scale; + const xScaleKey = mode == 2 ? series[1].facets[0].scale : series[0].scale const drawOrderMap = { axes: drawAxesGrid, - series: drawSeries, - }; + series: drawSeries + } - const drawOrder = (opts.drawOrder || ["axes", "series"]).map(key => drawOrderMap[key]); + const drawOrder = (opts.drawOrder || ['axes', 'series']).map( + (key) => drawOrderMap[key] + ) function initScale(scaleKey) { - let sc = scales[scaleKey]; + let sc = scales[scaleKey] if (sc == null) { - let scaleOpts = (opts.scales || EMPTY_OBJ)[scaleKey] || EMPTY_OBJ; + let scaleOpts = (opts.scales || EMPTY_OBJ)[scaleKey] || EMPTY_OBJ if (scaleOpts.from != null) { // ensure parent is initialized - initScale(scaleOpts.from); + initScale(scaleOpts.from) // dependent scales inherit - scales[scaleKey] = assign({}, scales[scaleOpts.from], scaleOpts, {key: scaleKey}); - } - else { - sc = scales[scaleKey] = assign({}, (scaleKey == xScaleKey ? xScaleOpts : yScaleOpts), scaleOpts); + scales[scaleKey] = assign( + {}, + scales[scaleOpts.from], + scaleOpts, + { key: scaleKey } + ) + } else { + sc = scales[scaleKey] = assign( + {}, + scaleKey == xScaleKey ? xScaleOpts : yScaleOpts, + scaleOpts + ) - sc.key = scaleKey; + sc.key = scaleKey - let isTime = FEAT_TIME && sc.time; + let isTime = FEAT_TIME && sc.time - let rn = sc.range; + let rn = sc.range - let rangeIsArr = isArr(rn); + let rangeIsArr = isArr(rn) if (scaleKey != xScaleKey || (mode == 2 && !isTime)) { // if range array has null limits, it should be auto if (rangeIsArr && (rn[0] == null || rn[1] == null)) { rn = { - min: rn[0] == null ? autoRangePart : { - mode: 1, - hard: rn[0], - soft: rn[0], - }, - max: rn[1] == null ? autoRangePart : { - mode: 1, - hard: rn[1], - soft: rn[1], - }, - }; - rangeIsArr = false; + min: + rn[0] == null + ? autoRangePart + : { + mode: 1, + hard: rn[0], + soft: rn[0] + }, + max: + rn[1] == null + ? autoRangePart + : { + mode: 1, + hard: rn[1], + soft: rn[1] + } + } + rangeIsArr = false } if (!rangeIsArr && isObj(rn)) { - let cfg = rn; + let cfg = rn // this is similar to snapNumY - rn = (self, dataMin, dataMax) => dataMin == null ? nullNullTuple : rangeNum(dataMin, dataMax, cfg); + rn = (self, dataMin, dataMax) => + dataMin == null + ? nullNullTuple + : rangeNum(dataMin, dataMax, cfg) } } - sc.range = fnOrSelf(rn || (isTime ? snapTimeX : scaleKey == xScaleKey ? - (sc.distr == 3 ? snapLogX : sc.distr == 4 ? snapAsinhX : snapNumX) : - (sc.distr == 3 ? snapLogY : sc.distr == 4 ? snapAsinhY : snapNumY) - )); + sc.range = fnOrSelf( + rn || + (isTime + ? snapTimeX + : scaleKey == xScaleKey + ? sc.distr == 3 + ? snapLogX + : sc.distr == 4 + ? snapAsinhX + : snapNumX + : sc.distr == 3 + ? snapLogY + : sc.distr == 4 + ? snapAsinhY + : snapNumY) + ) - sc.auto = fnOrSelf(rangeIsArr ? false : sc.auto); + sc.auto = fnOrSelf(rangeIsArr ? false : sc.auto) - sc.clamp = fnOrSelf(sc.clamp || clampScale); + sc.clamp = fnOrSelf(sc.clamp || clampScale) // caches for expensive ops like asinh() & log() - sc._min = sc._max = null; + sc._min = sc._max = null } } } - initScale("x"); - initScale("y"); + initScale('x') + initScale('y') // TODO: init scales from facets in mode: 2 if (mode == 1) { - series.forEach(s => { - initScale(s.scale); - }); + series.forEach((s) => { + initScale(s.scale) + }) } - axes.forEach(a => { - initScale(a.scale); - }); + axes.forEach((a) => { + initScale(a.scale) + }) - for (let k in opts.scales) - initScale(k); + for (let k in opts.scales) initScale(k) - const scaleX = scales[xScaleKey]; + const scaleX = scales[xScaleKey] - const xScaleDistr = scaleX.distr; + const xScaleDistr = scaleX.distr - let valToPosX, valToPosY, moveTo, arc, xDimCan, xOffCan, yDimCan, yOffCan, xDimCss, xOffCss, yDimCss, yOffCss, updOriDims; + let valToPosX, + valToPosY, + moveTo, + arc, + xDimCan, + xOffCan, + yDimCan, + yOffCan, + xDimCss, + xOffCss, + yDimCss, + yOffCss, + updOriDims if (scaleX.ori == 0) { - addClass(root, ORI_HZ); - valToPosX = getHPos; - valToPosY = getVPos; - moveTo = moveToH; - arc = arcH; + addClass(root, ORI_HZ) + valToPosX = getHPos + valToPosY = getVPos + moveTo = moveToH + arc = arcH /* updOriDims = () => { xDimCan = plotWid; @@ -494,13 +574,12 @@ export default function uPlot(opts, data, then) { yOffCss = plotTopCss; }; */ - } - else { - addClass(root, ORI_VT); - valToPosX = getVPos; - valToPosY = getHPos; - moveTo = moveToV; - arc = arcV; + } else { + addClass(root, ORI_VT) + valToPosX = getVPos + valToPosY = getHPos + moveTo = moveToV + arc = arcV /* updOriDims = () => { xDimCan = plotHgt; @@ -516,729 +595,850 @@ export default function uPlot(opts, data, then) { */ } - const pendScales = {}; + const pendScales = {} // explicitly-set initial scales for (let k in scales) { - let sc = scales[k]; + let sc = scales[k] if (sc.min != null || sc.max != null) { - pendScales[k] = {min: sc.min, max: sc.max}; - sc.min = sc.max = null; - } - } - -// self.tz = opts.tz || Intl.DateTimeFormat().resolvedOptions().timeZone; - const _tzDate = FEAT_TIME && (opts.tzDate || (ts => new Date(round(ts / ms)))); - const _fmtDate = FEAT_TIME && (opts.fmtDate || fmtDate); - - const _timeAxisSplits = FEAT_TIME && (ms == 1 ? timeAxisSplitsMs(_tzDate) : timeAxisSplitsS(_tzDate)); - const _timeAxisVals = FEAT_TIME && timeAxisVals(_tzDate, timeAxisStamps((ms == 1 ? _timeAxisStampsMs : _timeAxisStampsS), _fmtDate)); - const _timeSeriesVal = FEAT_TIME && timeSeriesVal(_tzDate, timeSeriesStamp(_timeSeriesStamp, _fmtDate)); + pendScales[k] = { min: sc.min, max: sc.max } + sc.min = sc.max = null + } + } + + // self.tz = opts.tz || Intl.DateTimeFormat().resolvedOptions().timeZone; + const _tzDate = + FEAT_TIME && (opts.tzDate || ((ts) => new Date(round(ts / ms)))) + const _fmtDate = FEAT_TIME && (opts.fmtDate || fmtDate) + + const _timeAxisSplits = + FEAT_TIME && + (ms == 1 ? timeAxisSplitsMs(_tzDate) : timeAxisSplitsS(_tzDate)) + const _timeAxisVals = + FEAT_TIME && + timeAxisVals( + _tzDate, + timeAxisStamps( + ms == 1 ? _timeAxisStampsMs : _timeAxisStampsS, + _fmtDate + ) + ) + const _timeSeriesVal = + FEAT_TIME && + timeSeriesVal(_tzDate, timeSeriesStamp(_timeSeriesStamp, _fmtDate)) - const activeIdxs = []; + const activeIdxs = [] - const legend = FEAT_LEGEND && (self.legend = assign({}, legendOpts, opts.legend)); - const showLegend = FEAT_LEGEND && legend.show; - const markers = FEAT_LEGEND && legend.markers; + const legend = + FEAT_LEGEND && (self.legend = assign({}, legendOpts, opts.legend)) + const showLegend = FEAT_LEGEND && legend.show + const markers = FEAT_LEGEND && legend.markers if (FEAT_LEGEND) { - legend.idxs = activeIdxs; + legend.idxs = activeIdxs - markers.width = fnOrSelf(markers.width); - markers.dash = fnOrSelf(markers.dash); - markers.stroke = fnOrSelf(markers.stroke); - markers.fill = fnOrSelf(markers.fill); + markers.width = fnOrSelf(markers.width) + markers.dash = fnOrSelf(markers.dash) + markers.stroke = fnOrSelf(markers.stroke) + markers.fill = fnOrSelf(markers.fill) } - let legendTable; - let legendHead; - let legendBody; - let legendRows = []; - let legendCells = []; - let legendCols; - let multiValLegend = false; - let NULL_LEGEND_VALUES = {}; + let legendTable + let legendHead + let legendBody + let legendRows = [] + let legendCells = [] + let legendCols + let multiValLegend = false + let NULL_LEGEND_VALUES = {} if (FEAT_LEGEND && legend.live) { - const getMultiVals = series[1] ? series[1].values : null; - multiValLegend = getMultiVals != null; - legendCols = multiValLegend ? getMultiVals(self, 1, 0) : {_: 0}; + const getMultiVals = series[1] ? series[1].values : null + multiValLegend = getMultiVals != null + legendCols = multiValLegend ? getMultiVals(self, 1, 0) : { _: 0 } - for (let k in legendCols) - NULL_LEGEND_VALUES[k] = LEGEND_DISP; + for (let k in legendCols) NULL_LEGEND_VALUES[k] = LEGEND_DISP } if (showLegend) { - legendTable = placeTag("table", LEGEND, root); - legendBody = placeTag("tbody", null, legendTable); + legendTable = placeTag('table', LEGEND, root) + legendBody = placeTag('tbody', null, legendTable) // allows legend to be moved out of root - legend.mount(self, legendTable); + legend.mount(self, legendTable) if (multiValLegend) { - legendHead = placeTag("thead", null, legendTable, legendBody); + legendHead = placeTag('thead', null, legendTable, legendBody) - let head = placeTag("tr", null, legendHead); - placeTag("th", null, head); + let head = placeTag('tr', null, legendHead) + placeTag('th', null, head) for (var key in legendCols) - placeTag("th", LEGEND_LABEL, head).textContent = key; - } - else { - addClass(legendTable, LEGEND_INLINE); - legend.live && addClass(legendTable, LEGEND_LIVE); + placeTag('th', LEGEND_LABEL, head).textContent = key + } else { + addClass(legendTable, LEGEND_INLINE) + legend.live && addClass(legendTable, LEGEND_LIVE) } } - const son = {show: true}; - const soff = {show: false}; + const son = { show: true } + const soff = { show: false } function initLegendRow(s, i) { if (i == 0 && (multiValLegend || !legend.live || mode == 2)) - return nullNullTuple; + return nullNullTuple - let cells = []; + let cells = [] - let row = placeTag("tr", LEGEND_SERIES, legendBody, legendBody.childNodes[i]); + let row = placeTag( + 'tr', + LEGEND_SERIES, + legendBody, + legendBody.childNodes[i] + ) - addClass(row, s.class); + addClass(row, s.class) - if (!s.show) - addClass(row, OFF); + if (!s.show) addClass(row, OFF) - let label = placeTag("th", null, row); + let label = placeTag('th', null, row) if (markers.show) { - let indic = placeDiv(LEGEND_MARKER, label); + let indic = placeDiv(LEGEND_MARKER, label) if (i > 0) { - let width = markers.width(self, i); + let width = markers.width(self, i) if (width) - indic.style.border = width + "px " + markers.dash(self, i) + " " + markers.stroke(self, i); + indic.style.border = + width + + 'px ' + + markers.dash(self, i) + + ' ' + + markers.stroke(self, i) - indic.style.background = markers.fill(self, i); + indic.style.background = markers.fill(self, i) } } - let text = placeDiv(LEGEND_LABEL, label); - text.textContent = s.label; + let text = placeDiv(LEGEND_LABEL, label) + text.textContent = s.label if (i > 0) { if (!markers.show) - text.style.color = s.width > 0 ? markers.stroke(self, i) : markers.fill(self, i); - - onMouse("click", label, e => { - if (cursor._lock) - return; - - setCursorEvent(e); - - let seriesIdx = series.indexOf(s); - - if ((e.ctrlKey || e.metaKey) != legend.isolate) { - // if any other series is shown, isolate this one. else show all - let isolate = series.some((s, i) => i > 0 && i != seriesIdx && s.show); - - series.forEach((s, i) => { - i > 0 && setSeries(i, isolate ? (i == seriesIdx ? son : soff) : son, true, syncOpts.setSeries); - }); - } - else - setSeries(seriesIdx, {show: !s.show}, true, syncOpts.setSeries); - }, false); + text.style.color = + s.width > 0 + ? markers.stroke(self, i) + : markers.fill(self, i) + + onMouse( + 'click', + label, + (e) => { + if (cursor._lock) return + + setCursorEvent(e) + + let seriesIdx = series.indexOf(s) + + if ((e.ctrlKey || e.metaKey) != legend.isolate) { + // if any other series is shown, isolate this one. else show all + let isolate = series.some( + (s, i) => i > 0 && i != seriesIdx && s.show + ) + + series.forEach((s, i) => { + i > 0 && + setSeries( + i, + isolate + ? i == seriesIdx + ? son + : soff + : son, + true, + syncOpts.setSeries + ) + }) + } else + setSeries( + seriesIdx, + { show: !s.show }, + true, + syncOpts.setSeries + ) + }, + false + ) if (cursorFocus) { - onMouse(mouseenter, label, e => { - if (cursor._lock) - return; - - setCursorEvent(e); - - setSeries(series.indexOf(s), FOCUS_TRUE, true, syncOpts.setSeries); - }, false); + onMouse( + mouseenter, + label, + (e) => { + if (cursor._lock) return + + setCursorEvent(e) + + setSeries( + series.indexOf(s), + FOCUS_TRUE, + true, + syncOpts.setSeries + ) + }, + false + ) } } for (var key in legendCols) { - let v = placeTag("td", LEGEND_VALUE, row); - v.textContent = "--"; - cells.push(v); + let v = placeTag('td', LEGEND_VALUE, row) + v.textContent = '--' + cells.push(v) } - return [row, cells]; + return [row, cells] } - const mouseListeners = new Map(); + const mouseListeners = new Map() function onMouse(ev, targ, fn, onlyTarg = true) { - const targListeners = mouseListeners.get(targ) || {}; - const listener = cursor.bind[ev](self, targ, fn, onlyTarg); + const targListeners = mouseListeners.get(targ) || {} + const listener = cursor.bind[ev](self, targ, fn, onlyTarg) if (listener) { - on(ev, targ, targListeners[ev] = listener); - mouseListeners.set(targ, targListeners); + on(ev, targ, (targListeners[ev] = listener)) + mouseListeners.set(targ, targListeners) } } function offMouse(ev, targ, fn) { - const targListeners = mouseListeners.get(targ) || {}; + const targListeners = mouseListeners.get(targ) || {} for (let k in targListeners) { if (ev == null || k == ev) { - off(k, targ, targListeners[k]); - delete targListeners[k]; + off(k, targ, targListeners[k]) + delete targListeners[k] } } - if (ev == null) - mouseListeners.delete(targ); + if (ev == null) mouseListeners.delete(targ) } - let fullWidCss = 0; - let fullHgtCss = 0; + let fullWidCss = 0 + let fullHgtCss = 0 - let plotWidCss = 0; - let plotHgtCss = 0; + let plotWidCss = 0 + let plotHgtCss = 0 // plot margins to account for axes - let plotLftCss = 0; - let plotTopCss = 0; + let plotLftCss = 0 + let plotTopCss = 0 // previous values for diffing - let _plotLftCss = plotLftCss; - let _plotTopCss = plotTopCss; - let _plotWidCss = plotWidCss; - let _plotHgtCss = plotHgtCss; - + let _plotLftCss = plotLftCss + let _plotTopCss = plotTopCss + let _plotWidCss = plotWidCss + let _plotHgtCss = plotHgtCss - let plotLft = 0; - let plotTop = 0; - let plotWid = 0; - let plotHgt = 0; + let plotLft = 0 + let plotTop = 0 + let plotWid = 0 + let plotHgt = 0 - self.bbox = {}; + self.bbox = {} - let shouldSetScales = false; - let shouldSetSize = false; - let shouldConvergeSize = false; - let shouldSetCursor = false; - let shouldSetSelect = false; - let shouldSetLegend = false; + let shouldSetScales = false + let shouldSetSize = false + let shouldConvergeSize = false + let shouldSetCursor = false + let shouldSetSelect = false + let shouldSetLegend = false function _setSize(width, height, force) { - if (force || (width != self.width || height != self.height)) - calcSize(width, height); + if (force || width != self.width || height != self.height) + calcSize(width, height) - resetYSeries(false); + resetYSeries(false) - shouldConvergeSize = true; - shouldSetSize = true; + shouldConvergeSize = true + shouldSetSize = true - commit(); + commit() } function calcSize(width, height) { - // log("calcSize()", arguments); + // log("calcSize()", arguments); - self.width = fullWidCss = plotWidCss = width; - self.height = fullHgtCss = plotHgtCss = height; - plotLftCss = plotTopCss = 0; + self.width = fullWidCss = plotWidCss = width + self.height = fullHgtCss = plotHgtCss = height + plotLftCss = plotTopCss = 0 - calcPlotRect(); - calcAxesRects(); + calcPlotRect() + calcAxesRects() - let bb = self.bbox; + let bb = self.bbox - plotLft = bb.left = incrRound(plotLftCss * pxRatio, 0.5); - plotTop = bb.top = incrRound(plotTopCss * pxRatio, 0.5); - plotWid = bb.width = incrRound(plotWidCss * pxRatio, 0.5); - plotHgt = bb.height = incrRound(plotHgtCss * pxRatio, 0.5); + plotLft = bb.left = incrRound(plotLftCss * pxRatio, 0.5) + plotTop = bb.top = incrRound(plotTopCss * pxRatio, 0.5) + plotWid = bb.width = incrRound(plotWidCss * pxRatio, 0.5) + plotHgt = bb.height = incrRound(plotHgtCss * pxRatio, 0.5) - // updOriDims(); + // updOriDims(); } // ensures size calc convergence - const CYCLE_LIMIT = 3; + const CYCLE_LIMIT = 3 function convergeSize() { - let converged = false; + let converged = false - let cycleNum = 0; + let cycleNum = 0 while (!converged) { - cycleNum++; + cycleNum++ - let axesConverged = axesCalc(cycleNum); - let paddingConverged = paddingCalc(cycleNum); + let axesConverged = axesCalc(cycleNum) + let paddingConverged = paddingCalc(cycleNum) - converged = cycleNum == CYCLE_LIMIT || (axesConverged && paddingConverged); + converged = + cycleNum == CYCLE_LIMIT || (axesConverged && paddingConverged) if (!converged) { - calcSize(self.width, self.height); - shouldSetSize = true; + calcSize(self.width, self.height) + shouldSetSize = true } } } - function setSize({width, height}) { - _setSize(width, height); + function setSize({ width, height }) { + _setSize(width, height) } - self.setSize = setSize; + self.setSize = setSize // accumulate axis offsets, reduce canvas width function calcPlotRect() { // easements for edge labels - let hasTopAxis = false; - let hasBtmAxis = false; - let hasRgtAxis = false; - let hasLftAxis = false; + let hasTopAxis = false + let hasBtmAxis = false + let hasRgtAxis = false + let hasLftAxis = false axes.forEach((axis, i) => { if (axis.show && axis._show) { - let {side, _size} = axis; - let isVt = side % 2; - let labelSize = axis.label != null ? axis.labelSize : 0; + let { side, _size } = axis + let isVt = side % 2 + let labelSize = axis.label != null ? axis.labelSize : 0 - let fullSize = _size + labelSize; + let fullSize = _size + labelSize if (fullSize > 0) { if (isVt) { - plotWidCss -= fullSize; + plotWidCss -= fullSize if (side == 3) { - plotLftCss += fullSize; - hasLftAxis = true; - } - else - hasRgtAxis = true; - } - else { - plotHgtCss -= fullSize; + plotLftCss += fullSize + hasLftAxis = true + } else hasRgtAxis = true + } else { + plotHgtCss -= fullSize if (side == 0) { - plotTopCss += fullSize; - hasTopAxis = true; - } - else - hasBtmAxis = true; + plotTopCss += fullSize + hasTopAxis = true + } else hasBtmAxis = true } } } - }); + }) - sidesWithAxes[0] = hasTopAxis; - sidesWithAxes[1] = hasRgtAxis; - sidesWithAxes[2] = hasBtmAxis; - sidesWithAxes[3] = hasLftAxis; + sidesWithAxes[0] = hasTopAxis + sidesWithAxes[1] = hasRgtAxis + sidesWithAxes[2] = hasBtmAxis + sidesWithAxes[3] = hasLftAxis // hz padding - plotWidCss -= _padding[1] + _padding[3]; - plotLftCss += _padding[3]; + plotWidCss -= _padding[1] + _padding[3] + plotLftCss += _padding[3] // vt padding - plotHgtCss -= _padding[2] + _padding[0]; - plotTopCss += _padding[0]; + plotHgtCss -= _padding[2] + _padding[0] + plotTopCss += _padding[0] } function calcAxesRects() { // will accum + - let off1 = plotLftCss + plotWidCss; - let off2 = plotTopCss + plotHgtCss; + let off1 = plotLftCss + plotWidCss + let off2 = plotTopCss + plotHgtCss // will accum - - let off3 = plotLftCss; - let off0 = plotTopCss; + let off3 = plotLftCss + let off0 = plotTopCss function incrOffset(side, size) { switch (side) { - case 1: off1 += size; return off1 - size; - case 2: off2 += size; return off2 - size; - case 3: off3 -= size; return off3 + size; - case 0: off0 -= size; return off0 + size; + case 1: + off1 += size + return off1 - size + case 2: + off2 += size + return off2 - size + case 3: + off3 -= size + return off3 + size + case 0: + off0 -= size + return off0 + size } } axes.forEach((axis, i) => { if (axis.show && axis._show) { - let side = axis.side; + let side = axis.side - axis._pos = incrOffset(side, axis._size); + axis._pos = incrOffset(side, axis._size) if (axis.label != null) - axis._lpos = incrOffset(side, axis.labelSize); + axis._lpos = incrOffset(side, axis.labelSize) } - }); + }) } - const cursor = self.cursor = assign({}, cursorOpts, {drag: {y: mode == 2}}, opts.cursor); + const cursor = (self.cursor = assign( + {}, + cursorOpts, + { drag: { y: mode == 2 } }, + opts.cursor + )) if (cursor.dataIdx == null) { - let hov = cursor.hover; + let hov = cursor.hover - let skip = hov.skip = new Set(hov.skip ?? []); - skip.add(void 0); // alignment artifacts - let prox = hov.prox = fnOrSelf(hov.prox); - let bias = hov.bias ??= 0; + let skip = (hov.skip = new Set(hov.skip ?? [])) + skip.add(void 0) // alignment artifacts + let prox = (hov.prox = fnOrSelf(hov.prox)) + let bias = (hov.bias ??= 0) // TODO: only scan between in-view idxs (i0, i1) cursor.dataIdx = (self, seriesIdx, cursorIdx, valAtPosX) => { - if (seriesIdx == 0) - return cursorIdx; + if (seriesIdx == 0) return cursorIdx - let idx2 = cursorIdx; + let idx2 = cursorIdx - let _prox = prox(self, seriesIdx, cursorIdx, valAtPosX) ?? inf; - let withProx = _prox >= 0 && _prox < inf; - let xDim = scaleX.ori == 0 ? plotWidCss : plotHgtCss; - let cursorLft = cursor.left; + let _prox = prox(self, seriesIdx, cursorIdx, valAtPosX) ?? inf + let withProx = _prox >= 0 && _prox < inf + let xDim = scaleX.ori == 0 ? plotWidCss : plotHgtCss + let cursorLft = cursor.left - let xValues = data[0]; - let yValues = data[seriesIdx]; + let xValues = data[0] + let yValues = data[seriesIdx] if (skip.has(yValues[cursorIdx])) { - idx2 = null; + idx2 = null let nonNullLft = null, nonNullRgt = null, - j; + j if (bias == 0 || bias == -1) { - j = cursorIdx; + j = cursorIdx while (nonNullLft == null && j-- > 0) { - if (!skip.has(yValues[j])) - nonNullLft = j; + if (!skip.has(yValues[j])) nonNullLft = j } } if (bias == 0 || bias == 1) { - j = cursorIdx; + j = cursorIdx while (nonNullRgt == null && j++ < yValues.length) { - if (!skip.has(yValues[j])) - nonNullRgt = j; + if (!skip.has(yValues[j])) nonNullRgt = j } } if (nonNullLft != null || nonNullRgt != null) { if (withProx) { - let lftPos = nonNullLft == null ? -Infinity : valToPosX(xValues[nonNullLft], scaleX, xDim, 0); - let rgtPos = nonNullRgt == null ? Infinity : valToPosX(xValues[nonNullRgt], scaleX, xDim, 0); - - let lftDelta = cursorLft - lftPos; - let rgtDelta = rgtPos - cursorLft; + let lftPos = + nonNullLft == null + ? -Infinity + : valToPosX( + xValues[nonNullLft], + scaleX, + xDim, + 0 + ) + let rgtPos = + nonNullRgt == null + ? Infinity + : valToPosX( + xValues[nonNullRgt], + scaleX, + xDim, + 0 + ) + + let lftDelta = cursorLft - lftPos + let rgtDelta = rgtPos - cursorLft if (lftDelta <= rgtDelta) { - if (lftDelta <= _prox) - idx2 = nonNullLft; + if (lftDelta <= _prox) idx2 = nonNullLft } else { - if (rgtDelta <= _prox) - idx2 = nonNullRgt; + if (rgtDelta <= _prox) idx2 = nonNullRgt } - } - else { + } else { idx2 = - nonNullRgt == null ? nonNullLft : - nonNullLft == null ? nonNullRgt : - cursorIdx - nonNullLft <= nonNullRgt - cursorIdx ? nonNullLft : nonNullRgt; + nonNullRgt == null + ? nonNullLft + : nonNullLft == null + ? nonNullRgt + : cursorIdx - nonNullLft <= + nonNullRgt - cursorIdx + ? nonNullLft + : nonNullRgt } } - } - else if (withProx) { - let dist = abs(cursorLft - valToPosX(xValues[cursorIdx], scaleX, xDim, 0)); + } else if (withProx) { + let dist = abs( + cursorLft - valToPosX(xValues[cursorIdx], scaleX, xDim, 0) + ) - if (dist > _prox) - idx2 = null; + if (dist > _prox) idx2 = null } - return idx2; - }; + return idx2 + } } - const setCursorEvent = e => { cursor.event = e; }; + const setCursorEvent = (e) => { + cursor.event = e + } - cursor.idxs = activeIdxs; + cursor.idxs = activeIdxs - cursor._lock = false; + cursor._lock = false - let points = cursor.points; + let points = cursor.points - points.show = fnOrSelf(points.show); - points.size = fnOrSelf(points.size); - points.stroke = fnOrSelf(points.stroke); - points.width = fnOrSelf(points.width); - points.fill = fnOrSelf(points.fill); + points.show = fnOrSelf(points.show) + points.size = fnOrSelf(points.size) + points.stroke = fnOrSelf(points.stroke) + points.width = fnOrSelf(points.width) + points.fill = fnOrSelf(points.fill) - const focus = self.focus = assign({}, opts.focus || {alpha: 0.3}, cursor.focus); + const focus = (self.focus = assign( + {}, + opts.focus || { alpha: 0.3 }, + cursor.focus + )) - const cursorFocus = focus.prox >= 0; - const cursorOnePt = cursorFocus && points.one; + const cursorFocus = focus.prox >= 0 + const cursorOnePt = cursorFocus && points.one // series-intersection markers - let cursorPts = []; + let cursorPts = [] // position caches in CSS pixels - let cursorPtsLft = []; - let cursorPtsTop = []; + let cursorPtsLft = [] + let cursorPtsTop = [] function initCursorPt(s, si) { - let pt = points.show(self, si); + let pt = points.show(self, si) if (pt) { - addClass(pt, CURSOR_PT); - addClass(pt, s.class); - elTrans(pt, -10, -10, plotWidCss, plotHgtCss); - over.insertBefore(pt, cursorPts[si]); + addClass(pt, CURSOR_PT) + addClass(pt, s.class) + elTrans(pt, -10, -10, plotWidCss, plotHgtCss) + over.insertBefore(pt, cursorPts[si]) - return pt; + return pt } } function initSeries(s, i) { if (mode == 1 || i > 0) { - let isTime = FEAT_TIME && mode == 1 && scales[s.scale].time; + let isTime = FEAT_TIME && mode == 1 && scales[s.scale].time - let sv = s.value; - s.value = isTime ? (isStr(sv) ? timeSeriesVal(_tzDate, timeSeriesStamp(sv, _fmtDate)) : sv || _timeSeriesVal) : sv || numSeriesVal; - s.label = s.label || (isTime ? timeSeriesLabel : numSeriesLabel); + let sv = s.value + s.value = isTime + ? isStr(sv) + ? timeSeriesVal(_tzDate, timeSeriesStamp(sv, _fmtDate)) + : sv || _timeSeriesVal + : sv || numSeriesVal + s.label = s.label || (isTime ? timeSeriesLabel : numSeriesLabel) } if (cursorOnePt || i > 0) { - s.width = s.width == null ? 1 : s.width; - s.paths = s.paths || linearPath || retNull; - s.fillTo = fnOrSelf(s.fillTo || seriesFillTo); - s.pxAlign = +ifNull(s.pxAlign, pxAlign); - s.pxRound = pxRoundGen(s.pxAlign); - - s.stroke = fnOrSelf(s.stroke || null); - s.fill = fnOrSelf(s.fill || null); - s._stroke = s._fill = s._paths = s._focus = null; - - let _ptDia = ptDia(max(1, s.width), 1); - let points = s.points = assign({}, { - size: _ptDia, - width: max(1, _ptDia * .2), - stroke: s.stroke, - space: _ptDia * 2, - paths: pointsPath, - _stroke: null, - _fill: null, - }, s.points); - points.show = fnOrSelf(points.show); - points.filter = fnOrSelf(points.filter); - points.fill = fnOrSelf(points.fill); - points.stroke = fnOrSelf(points.stroke); - points.paths = fnOrSelf(points.paths); - points.pxAlign = s.pxAlign; + s.width = s.width == null ? 1 : s.width + s.paths = s.paths || linearPath || retNull + s.fillTo = fnOrSelf(s.fillTo || seriesFillTo) + s.pxAlign = +ifNull(s.pxAlign, pxAlign) + s.pxRound = pxRoundGen(s.pxAlign) + + s.stroke = fnOrSelf(s.stroke || null) + s.fill = fnOrSelf(s.fill || null) + s._stroke = s._fill = s._paths = s._focus = null + + let _ptDia = ptDia(max(1, s.width), 1) + let points = (s.points = assign( + {}, + { + size: _ptDia, + width: max(1, _ptDia * 0.2), + stroke: s.stroke, + space: _ptDia * 2, + paths: pointsPath, + _stroke: null, + _fill: null + }, + s.points + )) + points.show = fnOrSelf(points.show) + points.filter = fnOrSelf(points.filter) + points.fill = fnOrSelf(points.fill) + points.stroke = fnOrSelf(points.stroke) + points.paths = fnOrSelf(points.paths) + points.pxAlign = s.pxAlign } if (showLegend) { - let rowCells = initLegendRow(s, i); - legendRows.splice(i, 0, rowCells[0]); - legendCells.splice(i, 0, rowCells[1]); - legend.values.push(null); // NULL_LEGEND_VALS not yet avil here :( + let rowCells = initLegendRow(s, i) + legendRows.splice(i, 0, rowCells[0]) + legendCells.splice(i, 0, rowCells[1]) + legend.values.push(null) // NULL_LEGEND_VALS not yet avil here :( } if (cursor.show) { - activeIdxs.splice(i, 0, null); + activeIdxs.splice(i, 0, null) - let pt = null; + let pt = null if (cursorOnePt) { - if (i == 0) - pt = initCursorPt(s, i); - } - else if (i > 0) - pt = initCursorPt(s, i); + if (i == 0) pt = initCursorPt(s, i) + } else if (i > 0) pt = initCursorPt(s, i) - cursorPts.splice(i, 0, pt); - cursorPtsLft.splice(i, 0, 0); - cursorPtsTop.splice(i, 0, 0); + cursorPts.splice(i, 0, pt) + cursorPtsLft.splice(i, 0, 0) + cursorPtsTop.splice(i, 0, 0) } - fire("addSeries", i); + fire('addSeries', i) } function addSeries(opts, si) { - si = si == null ? series.length : si; + si = si == null ? series.length : si - opts = mode == 1 ? setDefault(opts, si, xSeriesOpts, ySeriesOpts) : setDefault(opts, si, {}, xySeriesOpts); + opts = + mode == 1 + ? setDefault(opts, si, xSeriesOpts, ySeriesOpts) + : setDefault(opts, si, {}, xySeriesOpts) - series.splice(si, 0, opts); - initSeries(series[si], si); + series.splice(si, 0, opts) + initSeries(series[si], si) } - self.addSeries = addSeries; + self.addSeries = addSeries function delSeries(i) { - series.splice(i, 1); + series.splice(i, 1) if (showLegend) { - legend.values.splice(i, 1); + legend.values.splice(i, 1) - legendCells.splice(i, 1); - let tr = legendRows.splice(i, 1)[0]; - offMouse(null, tr.firstChild); - tr.remove(); + legendCells.splice(i, 1) + let tr = legendRows.splice(i, 1)[0] + offMouse(null, tr.firstChild) + tr.remove() } if (cursor.show) { - activeIdxs.splice(i, 1); - cursorPts.splice(i, 1)[0].remove(); - cursorPtsLft.splice(i, 1); - cursorPtsTop.splice(i, 1); + activeIdxs.splice(i, 1) + cursorPts.splice(i, 1)[0].remove() + cursorPtsLft.splice(i, 1) + cursorPtsTop.splice(i, 1) } // TODO: de-init no-longer-needed scales? - fire("delSeries", i); + fire('delSeries', i) } - self.delSeries = delSeries; + self.delSeries = delSeries - const sidesWithAxes = [false, false, false, false]; + const sidesWithAxes = [false, false, false, false] function initAxis(axis, i) { - axis._show = axis.show; + axis._show = axis.show if (axis.show) { - let isVt = axis.side % 2; + let isVt = axis.side % 2 - let sc = scales[axis.scale]; + let sc = scales[axis.scale] // this can occur if all series specify non-default scales if (sc == null) { - axis.scale = isVt ? series[1].scale : xScaleKey; - sc = scales[axis.scale]; + axis.scale = isVt ? series[1].scale : xScaleKey + sc = scales[axis.scale] } // also set defaults for incrs & values based on axis distr - let isTime = FEAT_TIME && sc.time; + let isTime = FEAT_TIME && sc.time - axis.size = fnOrSelf(axis.size); - axis.space = fnOrSelf(axis.space); - axis.rotate = fnOrSelf(axis.rotate); + axis.size = fnOrSelf(axis.size) + axis.space = fnOrSelf(axis.space) + axis.rotate = fnOrSelf(axis.rotate) if (isArr(axis.incrs)) { - axis.incrs.forEach(incr => { - !fixedDec.has(incr) && fixedDec.set(incr, guessDec(incr)); - }); - } - - axis.incrs = fnOrSelf(axis.incrs || ( sc.distr == 2 ? wholeIncrs : (isTime ? (ms == 1 ? timeIncrsMs : timeIncrsS) : numIncrs))); - axis.splits = fnOrSelf(axis.splits || (isTime && sc.distr == 1 ? _timeAxisSplits : sc.distr == 3 ? logAxisSplits : sc.distr == 4 ? asinhAxisSplits : numAxisSplits)); - - axis.stroke = fnOrSelf(axis.stroke); - axis.grid.stroke = fnOrSelf(axis.grid.stroke); - axis.ticks.stroke = fnOrSelf(axis.ticks.stroke); - axis.border.stroke = fnOrSelf(axis.border.stroke); - - let av = axis.values; - - axis.values = ( + axis.incrs.forEach((incr) => { + !fixedDec.has(incr) && fixedDec.set(incr, guessDec(incr)) + }) + } + + axis.incrs = fnOrSelf( + axis.incrs || + (sc.distr == 2 + ? wholeIncrs + : isTime + ? ms == 1 + ? timeIncrsMs + : timeIncrsS + : numIncrs) + ) + axis.splits = fnOrSelf( + axis.splits || + (isTime && sc.distr == 1 + ? _timeAxisSplits + : sc.distr == 3 + ? logAxisSplits + : sc.distr == 4 + ? asinhAxisSplits + : numAxisSplits) + ) + + axis.stroke = fnOrSelf(axis.stroke) + axis.grid.stroke = fnOrSelf(axis.grid.stroke) + axis.ticks.stroke = fnOrSelf(axis.ticks.stroke) + axis.border.stroke = fnOrSelf(axis.border.stroke) + + let av = axis.values + + axis.values = // static array of tick values - isArr(av) && !isArr(av[0]) ? fnOrSelf(av) : - // temporal - isTime ? ( - // config array of fmtDate string tpls - isArr(av) ? - timeAxisVals(_tzDate, timeAxisStamps(av, _fmtDate)) : - // fmtDate string tpl - isStr(av) ? - timeAxisVal(_tzDate, av) : - av || _timeAxisVals - ) : av || numAxisVals - ); - - axis.filter = fnOrSelf(axis.filter || ( sc.distr >= 3 && sc.log == 10 ? log10AxisValsFilt : sc.distr == 3 && sc.log == 2 ? log2AxisValsFilt : retArg1)); - - axis.font = pxRatioFont(axis.font); - axis.labelFont = pxRatioFont(axis.labelFont); - - axis._size = axis.size(self, null, i, 0); - - axis._space = - axis._rotate = - axis._incrs = - axis._found = // foundIncrSpace - axis._splits = - axis._values = null; + isArr(av) && !isArr(av[0]) + ? fnOrSelf(av) + : // temporal + isTime + ? // config array of fmtDate string tpls + isArr(av) + ? timeAxisVals(_tzDate, timeAxisStamps(av, _fmtDate)) + : // fmtDate string tpl + //isStr(av) ? + // timeAxisVal(_tzDate, av) : + av || _timeAxisVals + : av || numAxisVals + + axis.filter = fnOrSelf( + axis.filter || + (sc.distr >= 3 && sc.log == 10 + ? log10AxisValsFilt + : sc.distr == 3 && sc.log == 2 + ? log2AxisValsFilt + : retArg1) + ) + + axis.font = pxRatioFont(axis.font) + axis.labelFont = pxRatioFont(axis.labelFont) + + axis._size = axis.size(self, null, i, 0) + + axis._space = + axis._rotate = + axis._incrs = + axis._found = // foundIncrSpace + axis._splits = + axis._values = + null if (axis._size > 0) { - sidesWithAxes[i] = true; - axis._el = placeDiv(AXIS, wrap); + sidesWithAxes[i] = true + axis._el = placeDiv(AXIS, wrap) } // debug - // axis._el.style.background = "#" + Math.floor(Math.random()*16777215).toString(16) + '80'; + // axis._el.style.background = "#" + Math.floor(Math.random()*16777215).toString(16) + '80'; } } function autoPadSide(self, side, sidesWithAxes, cycleNum) { - let [hasTopAxis, hasRgtAxis, hasBtmAxis, hasLftAxis] = sidesWithAxes; + let [hasTopAxis, hasRgtAxis, hasBtmAxis, hasLftAxis] = sidesWithAxes - let ori = side % 2; - let size = 0; + let ori = side % 2 + let size = 0 if (ori == 0 && (hasLftAxis || hasRgtAxis)) - size = (side == 0 && !hasTopAxis || side == 2 && !hasBtmAxis ? round(xAxisOpts.size / 3) : 0); + size = + (side == 0 && !hasTopAxis) || (side == 2 && !hasBtmAxis) + ? round(xAxisOpts.size / 3) + : 0 if (ori == 1 && (hasTopAxis || hasBtmAxis)) - size = (side == 1 && !hasRgtAxis || side == 3 && !hasLftAxis ? round(yAxisOpts.size / 2) : 0); + size = + (side == 1 && !hasRgtAxis) || (side == 3 && !hasLftAxis) + ? round(yAxisOpts.size / 2) + : 0 - return size; + return size } - const padding = self.padding = (opts.padding || [autoPadSide,autoPadSide,autoPadSide,autoPadSide]).map(p => fnOrSelf(ifNull(p, autoPadSide))); - const _padding = self._padding = padding.map((p, i) => p(self, i, sidesWithAxes, 0)); + const padding = (self.padding = ( + opts.padding || [autoPadSide, autoPadSide, autoPadSide, autoPadSide] + ).map((p) => fnOrSelf(ifNull(p, autoPadSide)))) + const _padding = (self._padding = padding.map((p, i) => + p(self, i, sidesWithAxes, 0) + )) - let dataLen; + let dataLen // rendered data window - let i0 = null; - let i1 = null; - const idxs = mode == 1 ? series[0].idxs : null; + let i0 = null + let i1 = null + const idxs = mode == 1 ? series[0].idxs : null - let data0 = null; + let data0 = null - let viaAutoScaleX = false; + let viaAutoScaleX = false function setData(_data, _resetScales) { - data = _data == null ? [] : _data; + data = _data == null ? [] : _data - self.data = self._data = data; + self.data = self._data = data if (mode == 2) { - dataLen = 0; - for (let i = 1; i < series.length; i++) - dataLen += data[i][0].length; - } - else { - if (data.length == 0) - self.data = self._data = data = [[]]; + dataLen = 0 + for (let i = 1; i < series.length; i++) dataLen += data[i][0].length + } else { + if (data.length == 0) self.data = self._data = data = [[]] - data0 = data[0]; - dataLen = data0.length; + data0 = data[0] + dataLen = data0.length - let scaleData = data; + let scaleData = data if (xScaleDistr == 2) { - scaleData = data.slice(); + scaleData = data.slice() - let _data0 = scaleData[0] = Array(dataLen); - for (let i = 0; i < dataLen; i++) - _data0[i] = i; + let _data0 = (scaleData[0] = Array(dataLen)) + for (let i = 0; i < dataLen; i++) _data0[i] = i } - self._data = data = scaleData; + self._data = data = scaleData } - resetYSeries(true); + resetYSeries(true) - fire("setData"); + fire('setData') // forces x axis tick values to re-generate when neither x scale nor y scale changes // in ordinal mode, scale range is by index, so will not change if new data has same length, but tick values are from data if (xScaleDistr == 2) { - shouldConvergeSize = true; + shouldConvergeSize = true /* or somewhat cheaper, and uglier: if (ready) { @@ -1254,159 +1454,161 @@ export default function uPlot(opts, data, then) { } if (_resetScales !== false) { - let xsc = scaleX; + let xsc = scaleX - if (xsc.auto(self, viaAutoScaleX)) - autoScaleX(); - else - _setScale(xScaleKey, xsc.min, xsc.max); + if (xsc.auto(self, viaAutoScaleX)) autoScaleX() + else _setScale(xScaleKey, xsc.min, xsc.max) - shouldSetCursor = shouldSetCursor || cursor.left >= 0; - shouldSetLegend = true; - commit(); + shouldSetCursor = shouldSetCursor || cursor.left >= 0 + shouldSetLegend = true + commit() } } - self.setData = setData; + self.setData = setData function autoScaleX() { - viaAutoScaleX = true; + viaAutoScaleX = true - let _min, _max; + let _min, _max if (mode == 1) { if (dataLen > 0) { - i0 = idxs[0] = 0; - i1 = idxs[1] = dataLen - 1; + i0 = idxs[0] = 0 + i1 = idxs[1] = dataLen - 1 - _min = data[0][i0]; - _max = data[0][i1]; + _min = data[0][i0] + _max = data[0][i1] if (xScaleDistr == 2) { - _min = i0; - _max = i1; - } - else if (_min == _max) { + _min = i0 + _max = i1 + } else if (_min == _max) { if (xScaleDistr == 3) - [_min, _max] = rangeLog(_min, _min, scaleX.log, false); + [_min, _max] = rangeLog(_min, _min, scaleX.log, false) else if (xScaleDistr == 4) - [_min, _max] = rangeAsinh(_min, _min, scaleX.log, false); - else if (scaleX.time) - _max = _min + round(86400 / ms); - else - [_min, _max] = rangeNum(_min, _max, rangePad, true); + [_min, _max] = rangeAsinh(_min, _min, scaleX.log, false) + else if (scaleX.time) _max = _min + round(86400 / ms) + else [_min, _max] = rangeNum(_min, _max, rangePad, true) } - } - else { - i0 = idxs[0] = _min = null; - i1 = idxs[1] = _max = null; + } else { + i0 = idxs[0] = _min = null + i1 = idxs[1] = _max = null } } - _setScale(xScaleKey, _min, _max); + _setScale(xScaleKey, _min, _max) } - let ctxStroke, ctxFill, ctxWidth, ctxDash, ctxJoin, ctxCap, ctxFont, ctxAlign, ctxBaseline; - let ctxAlpha; + let ctxStroke, + ctxFill, + ctxWidth, + ctxDash, + ctxJoin, + ctxCap, + ctxFont, + ctxAlign, + ctxBaseline + let ctxAlpha function setCtxStyle(stroke, width, dash, cap, fill, join) { - stroke ??= transparent; - dash ??= EMPTY_ARR; - cap ??= "butt"; // (‿|‿) - fill ??= transparent; - join ??= "round"; - - if (stroke != ctxStroke) - ctx.strokeStyle = ctxStroke = stroke; - if (fill != ctxFill) - ctx.fillStyle = ctxFill = fill; - if (width != ctxWidth) - ctx.lineWidth = ctxWidth = width; - if (join != ctxJoin) - ctx.lineJoin = ctxJoin = join; - if (cap != ctxCap) - ctx.lineCap = ctxCap = cap; - if (dash != ctxDash) - ctx.setLineDash(ctxDash = dash); + stroke ??= transparent + dash ??= EMPTY_ARR + cap ??= 'butt' // (‿|‿) + fill ??= transparent + join ??= 'round' + + if (stroke != ctxStroke) ctx.strokeStyle = ctxStroke = stroke + if (fill != ctxFill) ctx.fillStyle = ctxFill = fill + if (width != ctxWidth) ctx.lineWidth = ctxWidth = width + if (join != ctxJoin) ctx.lineJoin = ctxJoin = join + if (cap != ctxCap) ctx.lineCap = ctxCap = cap + if (dash != ctxDash) ctx.setLineDash((ctxDash = dash)) } function setFontStyle(font, fill, align, baseline) { - if (fill != ctxFill) - ctx.fillStyle = ctxFill = fill; - if (font != ctxFont) - ctx.font = ctxFont = font; - if (align != ctxAlign) - ctx.textAlign = ctxAlign = align; - if (baseline != ctxBaseline) - ctx.textBaseline = ctxBaseline = baseline; + if (fill != ctxFill) ctx.fillStyle = ctxFill = fill + if (font != ctxFont) ctx.font = ctxFont = font + if (align != ctxAlign) ctx.textAlign = ctxAlign = align + if (baseline != ctxBaseline) ctx.textBaseline = ctxBaseline = baseline } function accScale(wsc, psc, facet, data, sorted = 0) { - if (data.length > 0 && wsc.auto(self, viaAutoScaleX) && (psc == null || psc.min == null)) { - let _i0 = ifNull(i0, 0); - let _i1 = ifNull(i1, data.length - 1); + if ( + data.length > 0 && + wsc.auto(self, viaAutoScaleX) && + (psc == null || psc.min == null) + ) { + let _i0 = ifNull(i0, 0) + let _i1 = ifNull(i1, data.length - 1) // only run getMinMax() for invalidated series data, else reuse - let minMax = facet.min == null ? (wsc.distr == 3 ? getMinMaxLog(data, _i0, _i1) : getMinMax(data, _i0, _i1, sorted)) : [facet.min, facet.max]; + let minMax = + facet.min == null + ? wsc.distr == 3 + ? getMinMaxLog(data, _i0, _i1) + : getMinMax(data, _i0, _i1, sorted) + : [facet.min, facet.max] // initial min/max - wsc.min = min(wsc.min, facet.min = minMax[0]); - wsc.max = max(wsc.max, facet.max = minMax[1]); + wsc.min = min(wsc.min, (facet.min = minMax[0])) + wsc.max = max(wsc.max, (facet.max = minMax[1])) } } - const AUTOSCALE = {min: null, max: null}; + const AUTOSCALE = { min: null, max: null } function setScales() { - // log("setScales()", arguments); + // log("setScales()", arguments); // implicitly add auto scales, and unranged scales for (let k in scales) { - let sc = scales[k]; + let sc = scales[k] - if (pendScales[k] == null && - ( - // scales that have never been set (on init) - sc.min == null || + if ( + pendScales[k] == null && + // scales that have never been set (on init) + (sc.min == null || // or auto scales when the x scale was explicitly set - pendScales[xScaleKey] != null && sc.auto(self, viaAutoScaleX) - ) + (pendScales[xScaleKey] != null && + sc.auto(self, viaAutoScaleX))) ) { - pendScales[k] = AUTOSCALE; + pendScales[k] = AUTOSCALE } } // implicitly add dependent scales for (let k in scales) { - let sc = scales[k]; + let sc = scales[k] - if (pendScales[k] == null && sc.from != null && pendScales[sc.from] != null) - pendScales[k] = AUTOSCALE; + if ( + pendScales[k] == null && + sc.from != null && + pendScales[sc.from] != null + ) + pendScales[k] = AUTOSCALE } // explicitly setting the x-scale invalidates everything (acts as redraw) - if (pendScales[xScaleKey] != null) - resetYSeries(true); // TODO: only reset series on auto scales? + if (pendScales[xScaleKey] != null) resetYSeries(true) // TODO: only reset series on auto scales? - let wipScales = {}; + let wipScales = {} for (let k in pendScales) { - let psc = pendScales[k]; + let psc = pendScales[k] if (psc != null) { - let wsc = wipScales[k] = copy(scales[k], fastIsObj); + let wsc = (wipScales[k] = copy(scales[k], fastIsObj)) - if (psc.min != null) - assign(wsc, psc); + if (psc.min != null) assign(wsc, psc) else if (k != xScaleKey || mode == 2) { if (dataLen == 0 && wsc.from == null) { - let minMax = wsc.range(self, null, null, k); - wsc.min = minMax[0]; - wsc.max = minMax[1]; - } - else { - wsc.min = inf; - wsc.max = -inf; + let minMax = wsc.range(self, null, null, k) + wsc.min = minMax[0] + wsc.max = minMax[1] + } else { + wsc.min = inf + wsc.max = -inf } } } @@ -1416,117 +1618,139 @@ export default function uPlot(opts, data, then) { // pre-range y-scales from y series' data values series.forEach((s, i) => { if (mode == 1) { - let k = s.scale; - let psc = pendScales[k]; + let k = s.scale + let psc = pendScales[k] - if (psc == null) - return; + if (psc == null) return - let wsc = wipScales[k]; + let wsc = wipScales[k] if (i == 0) { - let minMax = wsc.range(self, wsc.min, wsc.max, k); + let minMax = wsc.range(self, wsc.min, wsc.max, k) - wsc.min = minMax[0]; - wsc.max = minMax[1]; + wsc.min = minMax[0] + wsc.max = minMax[1] - i0 = closestIdx(wsc.min, data[0]); - i1 = closestIdx(wsc.max, data[0]); + i0 = closestIdx(wsc.min, data[0]) + i1 = closestIdx(wsc.max, data[0]) // don't try to contract same or adjacent idxs if (i1 - i0 > 1) { // closest indices can be outside of view - if (data[0][i0] < wsc.min) - i0++; - if (data[0][i1] > wsc.max) - i1--; + if (data[0][i0] < wsc.min) i0++ + if (data[0][i1] > wsc.max) i1-- } - s.min = data0[i0]; - s.max = data0[i1]; - } - else if (s.show && s.auto) - accScale(wsc, psc, s, data[i], s.sorted); + s.min = data0[i0] + s.max = data0[i1] + } else if (s.show && s.auto) + accScale(wsc, psc, s, data[i], s.sorted) - s.idxs[0] = i0; - s.idxs[1] = i1; - } - else { + s.idxs[0] = i0 + s.idxs[1] = i1 + } else { if (i > 0) { if (s.show && s.auto) { // TODO: only handles, assumes and requires facets[0] / 'x' scale, and facets[1] / 'y' scale - let [ xFacet, yFacet ] = s.facets; - let xScaleKey = xFacet.scale; - let yScaleKey = yFacet.scale; - let [ xData, yData ] = data[i]; + let [xFacet, yFacet] = s.facets + let xScaleKey = xFacet.scale + let yScaleKey = yFacet.scale + let [xData, yData] = data[i] - let wscx = wipScales[xScaleKey]; - let wscy = wipScales[yScaleKey]; + let wscx = wipScales[xScaleKey] + let wscy = wipScales[yScaleKey] // null can happen when only x is zoomed, but y has static range and doesnt get auto-added to pending - wscx != null && accScale(wscx, pendScales[xScaleKey], xFacet, xData, xFacet.sorted); - wscy != null && accScale(wscy, pendScales[yScaleKey], yFacet, yData, yFacet.sorted); + wscx != null && + accScale( + wscx, + pendScales[xScaleKey], + xFacet, + xData, + xFacet.sorted + ) + wscy != null && + accScale( + wscy, + pendScales[yScaleKey], + yFacet, + yData, + yFacet.sorted + ) // temp - s.min = yFacet.min; - s.max = yFacet.max; + s.min = yFacet.min + s.max = yFacet.max } } } - }); + }) // range independent scales for (let k in wipScales) { - let wsc = wipScales[k]; - let psc = pendScales[k]; + let wsc = wipScales[k] + let psc = pendScales[k] if (wsc.from == null && (psc == null || psc.min == null)) { let minMax = wsc.range( self, - wsc.min == inf ? null : wsc.min, + wsc.min == inf ? null : wsc.min, wsc.max == -inf ? null : wsc.max, k - ); - wsc.min = minMax[0]; - wsc.max = minMax[1]; + ) + wsc.min = minMax[0] + wsc.max = minMax[1] } } } // range dependent scales for (let k in wipScales) { - let wsc = wipScales[k]; + let wsc = wipScales[k] if (wsc.from != null) { - let base = wipScales[wsc.from]; + let base = wipScales[wsc.from] - if (base.min == null) - wsc.min = wsc.max = null; + if (base.min == null) wsc.min = wsc.max = null else { - let minMax = wsc.range(self, base.min, base.max, k); - wsc.min = minMax[0]; - wsc.max = minMax[1]; + let minMax = wsc.range(self, base.min, base.max, k) + wsc.min = minMax[0] + wsc.max = minMax[1] } } } - let changed = {}; - let anyChanged = false; + let changed = {} + let anyChanged = false for (let k in wipScales) { - let wsc = wipScales[k]; - let sc = scales[k]; + let wsc = wipScales[k] + let sc = scales[k] if (sc.min != wsc.min || sc.max != wsc.max) { - sc.min = wsc.min; - sc.max = wsc.max; + sc.min = wsc.min + sc.max = wsc.max - let distr = sc.distr; + let distr = sc.distr - sc._min = distr == 3 ? log10(sc.min) : distr == 4 ? asinh(sc.min, sc.asinh) : distr == 100 ? sc.fwd(sc.min) : sc.min; - sc._max = distr == 3 ? log10(sc.max) : distr == 4 ? asinh(sc.max, sc.asinh) : distr == 100 ? sc.fwd(sc.max) : sc.max; + sc._min = + distr == 3 + ? log10(sc.min) + : distr == 4 + ? asinh(sc.min, sc.asinh) + : distr == 100 + ? sc.fwd(sc.min) + : sc.min + sc._max = + distr == 3 + ? log10(sc.max) + : distr == 4 + ? asinh(sc.max, sc.asinh) + : distr == 100 + ? sc.fwd(sc.max) + : sc.max - changed[k] = anyChanged = true; + changed[k] = anyChanged = true } } @@ -1534,99 +1758,100 @@ export default function uPlot(opts, data, then) { // invalidate paths of all series on changed scales series.forEach((s, i) => { if (mode == 2) { - if (i > 0 && changed.y) - s._paths = null; + if (i > 0 && changed.y) s._paths = null + } else { + if (changed[s.scale]) s._paths = null } - else { - if (changed[s.scale]) - s._paths = null; - } - }); + }) for (let k in changed) { - shouldConvergeSize = true; - fire("setScale", k); + shouldConvergeSize = true + fire('setScale', k) } if (cursor.show && cursor.left >= 0) - shouldSetCursor = shouldSetLegend = true; + shouldSetCursor = shouldSetLegend = true } - for (let k in pendScales) - pendScales[k] = null; + for (let k in pendScales) pendScales[k] = null } // grabs the nearest indices with y data outside of x-scale limits function getOuterIdxs(ydata) { - let _i0 = clamp(i0 - 1, 0, dataLen - 1); - let _i1 = clamp(i1 + 1, 0, dataLen - 1); + let _i0 = clamp(i0 - 1, 0, dataLen - 1) + let _i1 = clamp(i1 + 1, 0, dataLen - 1) - while (ydata[_i0] == null && _i0 > 0) - _i0--; + while (ydata[_i0] == null && _i0 > 0) _i0-- - while (ydata[_i1] == null && _i1 < dataLen - 1) - _i1++; + while (ydata[_i1] == null && _i1 < dataLen - 1) _i1++ - return [_i0, _i1]; + return [_i0, _i1] } function drawSeries() { if (dataLen > 0) { series.forEach((s, i) => { if (i > 0 && s.show) { - FEAT_PATHS && cacheStrokeFill(i, false); - FEAT_POINTS && cacheStrokeFill(i, true); + FEAT_PATHS && cacheStrokeFill(i, false) + FEAT_POINTS && cacheStrokeFill(i, true) if (s._paths == null) { if (ctxAlpha != s.alpha) - ctx.globalAlpha = ctxAlpha = s.alpha; + ctx.globalAlpha = ctxAlpha = s.alpha - let _idxs = mode == 2 ? [0, data[i][0].length - 1] : getOuterIdxs(data[i]); - s._paths = s.paths(self, i, _idxs[0], _idxs[1]); + let _idxs = + mode == 2 + ? [0, data[i][0].length - 1] + : getOuterIdxs(data[i]) + s._paths = s.paths(self, i, _idxs[0], _idxs[1]) - if (ctxAlpha != 1) - ctx.globalAlpha = ctxAlpha = 1; + if (ctxAlpha != 1) ctx.globalAlpha = ctxAlpha = 1 } } - }); + }) series.forEach((s, i) => { if (i > 0 && s.show) { if (ctxAlpha != s.alpha) - ctx.globalAlpha = ctxAlpha = s.alpha; + ctx.globalAlpha = ctxAlpha = s.alpha - FEAT_PATHS && s._paths != null && drawPath(i, false); + FEAT_PATHS && s._paths != null && drawPath(i, false) if (FEAT_POINTS) { - let _gaps = s._paths != null ? s._paths.gaps : null; + let _gaps = s._paths != null ? s._paths.gaps : null - let show = s.points.show(self, i, i0, i1, _gaps); - let idxs = s.points.filter(self, i, show, _gaps); + let show = s.points.show(self, i, i0, i1, _gaps) + let idxs = s.points.filter(self, i, show, _gaps) if (show || idxs) { - s.points._paths = s.points.paths(self, i, i0, i1, idxs); - drawPath(i, true); + s.points._paths = s.points.paths( + self, + i, + i0, + i1, + idxs + ) + drawPath(i, true) } } - if (ctxAlpha != 1) - ctx.globalAlpha = ctxAlpha = 1; + if (ctxAlpha != 1) ctx.globalAlpha = ctxAlpha = 1 - fire("drawSeries", i); + fire('drawSeries', i) } - }); + }) } } function cacheStrokeFill(si, _points) { - let s = _points ? series[si].points : series[si]; + let s = _points ? series[si].points : series[si] - s._stroke = s.stroke(self, si); - s._fill = s.fill(self, si); + s._stroke = s.stroke(self, si) + s._fill = s.fill(self, si) } function drawPath(si, _points) { - let s = _points ? series[si].points : series[si]; + let s = _points ? series[si].points : series[si] let { stroke, @@ -1635,394 +1860,511 @@ export default function uPlot(opts, data, then) { flags, _stroke: strokeStyle = s._stroke, - _fill: fillStyle = s._fill, - _width: width = s.width, - } = s._paths; + _fill: fillStyle = s._fill, + _width: width = s.width + } = s._paths - width = roundDec(width * pxRatio, 3); + width = roundDec(width * pxRatio, 3) - let boundsClip = null; - let offset = (width % 2) / 2; + let boundsClip = null + let offset = (width % 2) / 2 if (_points && fillStyle == null) - fillStyle = width > 0 ? "#fff" : strokeStyle; + fillStyle = width > 0 ? '#fff' : strokeStyle - let _pxAlign = s.pxAlign == 1 && offset > 0; + let _pxAlign = s.pxAlign == 1 && offset > 0 - _pxAlign && ctx.translate(offset, offset); + _pxAlign && ctx.translate(offset, offset) if (!_points) { let lft = plotLft - width / 2, top = plotTop - width / 2, wid = plotWid + width, - hgt = plotHgt + width; + hgt = plotHgt + width - boundsClip = new Path2D(); - boundsClip.rect(lft, top, wid, hgt); + boundsClip = new Path2D() + boundsClip.rect(lft, top, wid, hgt) } // the points pathbuilder's gapsClip is its boundsClip, since points dont need gaps clipping, and bounds depend on point size if (_points) - strokeFill(strokeStyle, width, s.dash, s.cap, fillStyle, stroke, fill, flags, gapsClip); + strokeFill( + strokeStyle, + width, + s.dash, + s.cap, + fillStyle, + stroke, + fill, + flags, + gapsClip + ) else - fillStroke(si, strokeStyle, width, s.dash, s.cap, fillStyle, stroke, fill, flags, boundsClip, gapsClip); - - _pxAlign && ctx.translate(-offset, -offset); - } - - function fillStroke(si, strokeStyle, lineWidth, lineDash, lineCap, fillStyle, strokePath, fillPath, flags, boundsClip, gapsClip) { - let didStrokeFill = false; + fillStroke( + si, + strokeStyle, + width, + s.dash, + s.cap, + fillStyle, + stroke, + fill, + flags, + boundsClip, + gapsClip + ) + + _pxAlign && ctx.translate(-offset, -offset) + } + + function fillStroke( + si, + strokeStyle, + lineWidth, + lineDash, + lineCap, + fillStyle, + strokePath, + fillPath, + flags, + boundsClip, + gapsClip + ) { + let didStrokeFill = false // for all bands where this series is the top edge, create upwards clips using the bottom edges // and apply clips + fill with band fill or dfltFill - flags != 0 && bands.forEach((b, bi) => { - // isUpperEdge? - if (b.series[0] == si) { - let lowerEdge = series[b.series[1]]; - let lowerData = data[b.series[1]]; - - let bandClip = (lowerEdge._paths || EMPTY_OBJ).band; - - if (isArr(bandClip)) - bandClip = b.dir == 1 ? bandClip[0] : bandClip[1]; - - let gapsClip2; - - let _fillStyle = null; - - // hasLowerEdge? - if (lowerEdge.show && bandClip && hasData(lowerData, i0, i1)) { - _fillStyle = b.fill(self, bi) || fillStyle; - gapsClip2 = lowerEdge._paths.clip; + flags != 0 && + bands.forEach((b, bi) => { + // isUpperEdge? + if (b.series[0] == si) { + let lowerEdge = series[b.series[1]] + let lowerData = data[b.series[1]] + + let bandClip = (lowerEdge._paths || EMPTY_OBJ).band + + if (isArr(bandClip)) + bandClip = b.dir == 1 ? bandClip[0] : bandClip[1] + + let gapsClip2 + + let _fillStyle = null + + // hasLowerEdge? + if ( + lowerEdge.show && + bandClip && + hasData(lowerData, i0, i1) + ) { + _fillStyle = b.fill(self, bi) || fillStyle + gapsClip2 = lowerEdge._paths.clip + } else bandClip = null + + strokeFill( + strokeStyle, + lineWidth, + lineDash, + lineCap, + _fillStyle, + strokePath, + fillPath, + flags, + boundsClip, + gapsClip, + gapsClip2, + bandClip + ) + + didStrokeFill = true } - else - bandClip = null; - - strokeFill(strokeStyle, lineWidth, lineDash, lineCap, _fillStyle, strokePath, fillPath, flags, boundsClip, gapsClip, gapsClip2, bandClip); - - didStrokeFill = true; - } - }); + }) if (!didStrokeFill) - strokeFill(strokeStyle, lineWidth, lineDash, lineCap, fillStyle, strokePath, fillPath, flags, boundsClip, gapsClip); - } - - const CLIP_FILL_STROKE = BAND_CLIP_FILL | BAND_CLIP_STROKE; - - function strokeFill(strokeStyle, lineWidth, lineDash, lineCap, fillStyle, strokePath, fillPath, flags, boundsClip, gapsClip, gapsClip2, bandClip) { - setCtxStyle(strokeStyle, lineWidth, lineDash, lineCap, fillStyle); + strokeFill( + strokeStyle, + lineWidth, + lineDash, + lineCap, + fillStyle, + strokePath, + fillPath, + flags, + boundsClip, + gapsClip + ) + } + + const CLIP_FILL_STROKE = BAND_CLIP_FILL | BAND_CLIP_STROKE + + function strokeFill( + strokeStyle, + lineWidth, + lineDash, + lineCap, + fillStyle, + strokePath, + fillPath, + flags, + boundsClip, + gapsClip, + gapsClip2, + bandClip + ) { + setCtxStyle(strokeStyle, lineWidth, lineDash, lineCap, fillStyle) if (boundsClip || gapsClip || bandClip) { - ctx.save(); - boundsClip && ctx.clip(boundsClip); - gapsClip && ctx.clip(gapsClip); + ctx.save() + boundsClip && ctx.clip(boundsClip) + gapsClip && ctx.clip(gapsClip) } if (bandClip) { if ((flags & CLIP_FILL_STROKE) == CLIP_FILL_STROKE) { - ctx.clip(bandClip); - gapsClip2 && ctx.clip(gapsClip2); - doFill(fillStyle, fillPath); - doStroke(strokeStyle, strokePath, lineWidth); - } - else if (flags & BAND_CLIP_STROKE) { - doFill(fillStyle, fillPath); - ctx.clip(bandClip); - doStroke(strokeStyle, strokePath, lineWidth); - } - else if (flags & BAND_CLIP_FILL) { - ctx.save(); - ctx.clip(bandClip); - gapsClip2 && ctx.clip(gapsClip2); - doFill(fillStyle, fillPath); - ctx.restore(); - doStroke(strokeStyle, strokePath, lineWidth); - } - } - else { - doFill(fillStyle, fillPath); - doStroke(strokeStyle, strokePath, lineWidth); - } - - if (boundsClip || gapsClip || bandClip) - ctx.restore(); + ctx.clip(bandClip) + gapsClip2 && ctx.clip(gapsClip2) + doFill(fillStyle, fillPath) + doStroke(strokeStyle, strokePath, lineWidth) + } else if (flags & BAND_CLIP_STROKE) { + doFill(fillStyle, fillPath) + ctx.clip(bandClip) + doStroke(strokeStyle, strokePath, lineWidth) + } else if (flags & BAND_CLIP_FILL) { + ctx.save() + ctx.clip(bandClip) + gapsClip2 && ctx.clip(gapsClip2) + doFill(fillStyle, fillPath) + ctx.restore() + doStroke(strokeStyle, strokePath, lineWidth) + } + } else { + doFill(fillStyle, fillPath) + doStroke(strokeStyle, strokePath, lineWidth) + } + + if (boundsClip || gapsClip || bandClip) ctx.restore() } function doStroke(strokeStyle, strokePath, lineWidth) { if (lineWidth > 0) { if (strokePath instanceof Map) { strokePath.forEach((strokePath, strokeStyle) => { - ctx.strokeStyle = ctxStroke = strokeStyle; - ctx.stroke(strokePath); - }); - } - else - strokePath != null && strokeStyle && ctx.stroke(strokePath); + ctx.strokeStyle = ctxStroke = strokeStyle + ctx.stroke(strokePath) + }) + } else strokePath != null && strokeStyle && ctx.stroke(strokePath) } } function doFill(fillStyle, fillPath) { if (fillPath instanceof Map) { fillPath.forEach((fillPath, fillStyle) => { - ctx.fillStyle = ctxFill = fillStyle; - ctx.fill(fillPath); - }); - } - else - fillPath != null && fillStyle && ctx.fill(fillPath); + ctx.fillStyle = ctxFill = fillStyle + ctx.fill(fillPath) + }) + } else fillPath != null && fillStyle && ctx.fill(fillPath) } function getIncrSpace(axisIdx, min, max, fullDim) { - let axis = axes[axisIdx]; + let axis = axes[axisIdx] - let incrSpace; + let incrSpace - if (fullDim <= 0) - incrSpace = [0, 0]; + if (fullDim <= 0) incrSpace = [0, 0] else { - let minSpace = axis._space = axis.space(self, axisIdx, min, max, fullDim); - let incrs = axis._incrs = axis.incrs(self, axisIdx, min, max, fullDim, minSpace); - incrSpace = findIncr(min, max, incrs, fullDim, minSpace); - } - - return (axis._found = incrSpace); - } - - function drawOrthoLines(offs, filts, ori, side, pos0, len, width, stroke, dash, cap) { - let offset = (width % 2) / 2; - - pxAlign == 1 && ctx.translate(offset, offset); - - setCtxStyle(stroke, width, dash, cap, stroke); - - ctx.beginPath(); - - let x0, y0, x1, y1, pos1 = pos0 + (side == 0 || side == 3 ? -len : len); + let minSpace = (axis._space = axis.space( + self, + axisIdx, + min, + max, + fullDim + )) + let incrs = (axis._incrs = axis.incrs( + self, + axisIdx, + min, + max, + fullDim, + minSpace + )) + incrSpace = findIncr(min, max, incrs, fullDim, minSpace) + } + + return (axis._found = incrSpace) + } + + function drawOrthoLines( + offs, + filts, + ori, + side, + pos0, + len, + width, + stroke, + dash, + cap + ) { + let offset = (width % 2) / 2 + + pxAlign == 1 && ctx.translate(offset, offset) + + setCtxStyle(stroke, width, dash, cap, stroke) + + ctx.beginPath() + + let x0, + y0, + x1, + y1, + pos1 = pos0 + (side == 0 || side == 3 ? -len : len) if (ori == 0) { - y0 = pos0; - y1 = pos1; - } - else { - x0 = pos0; - x1 = pos1; + y0 = pos0 + y1 = pos1 + } else { + x0 = pos0 + x1 = pos1 } for (let i = 0; i < offs.length; i++) { if (filts[i] != null) { - if (ori == 0) - x0 = x1 = offs[i]; - else - y0 = y1 = offs[i]; + if (ori == 0) x0 = x1 = offs[i] + else y0 = y1 = offs[i] - ctx.moveTo(x0, y0); - ctx.lineTo(x1, y1); + ctx.moveTo(x0, y0) + ctx.lineTo(x1, y1) } } - ctx.stroke(); + ctx.stroke() - pxAlign == 1 && ctx.translate(-offset, -offset); + pxAlign == 1 && ctx.translate(-offset, -offset) } function axesCalc(cycleNum) { - // log("axesCalc()", arguments); + // log("axesCalc()", arguments); - let converged = true; + let converged = true axes.forEach((axis, i) => { - if (!axis.show) - return; + if (!axis.show) return - let scale = scales[axis.scale]; + let scale = scales[axis.scale] if (scale.min == null) { if (axis._show) { - converged = false; - axis._show = false; - resetYSeries(false); + converged = false + axis._show = false + resetYSeries(false) } - return; - } - else { + return + } else { if (!axis._show) { - converged = false; - axis._show = true; - resetYSeries(false); + converged = false + axis._show = true + resetYSeries(false) } } - let side = axis.side; - let ori = side % 2; + let side = axis.side + let ori = side % 2 - let {min, max} = scale; // // should this toggle them ._show = false + let { min, max } = scale // // should this toggle them ._show = false - let [_incr, _space] = getIncrSpace(i, min, max, ori == 0 ? plotWidCss : plotHgtCss); + let [_incr, _space] = getIncrSpace( + i, + min, + max, + ori == 0 ? plotWidCss : plotHgtCss + ) - if (_space == 0) - return; + if (_space == 0) return // if we're using index positions, force first tick to match passed index - let forceMin = scale.distr == 2; - - let _splits = axis._splits = axis.splits(self, i, min, max, _incr, _space, forceMin); + let forceMin = scale.distr == 2 + + let _splits = (axis._splits = axis.splits( + self, + i, + min, + max, + _incr, + _space, + forceMin + )) // tick labels // BOO this assumes a specific data/series - let splits = scale.distr == 2 ? _splits.map(i => data0[i]) : _splits; - let incr = scale.distr == 2 ? data0[_splits[1]] - data0[_splits[0]] : _incr; - - let values = axis._values = axis.values(self, axis.filter(self, splits, i, _space, incr), i, _space, incr); + let splits = + scale.distr == 2 ? _splits.map((i) => data0[i]) : _splits + let incr = + scale.distr == 2 ? data0[_splits[1]] - data0[_splits[0]] : _incr + + let values = (axis._values = axis.values( + self, + axis.filter(self, splits, i, _space, incr), + i, + _space, + incr, + fmtNum + )) // rotating of labels only supported on bottom x axis - axis._rotate = side == 2 ? axis.rotate(self, values, i, _space) : 0; + axis._rotate = side == 2 ? axis.rotate(self, values, i, _space) : 0 - let oldSize = axis._size; + let oldSize = axis._size - axis._size = ceil(axis.size(self, values, i, cycleNum)); + axis._size = ceil(axis.size(self, values, i, cycleNum)) - if (oldSize != null && axis._size != oldSize) // ready && ? - converged = false; - }); + if (oldSize != null && axis._size != oldSize) + // ready && ? + converged = false + }) - return converged; + return converged } function paddingCalc(cycleNum) { - let converged = true; + let converged = true padding.forEach((p, i) => { - let _p = p(self, i, sidesWithAxes, cycleNum); + let _p = p(self, i, sidesWithAxes, cycleNum) - if (_p != _padding[i]) - converged = false; + if (_p != _padding[i]) converged = false - _padding[i] = _p; - }); + _padding[i] = _p + }) - return converged; + return converged } function drawAxesGrid() { for (let i = 0; i < axes.length; i++) { - let axis = axes[i]; + let axis = axes[i] - if (!axis.show || !axis._show) - continue; + if (!axis.show || !axis._show) continue - let side = axis.side; - let ori = side % 2; + let side = axis.side + let ori = side % 2 - let x, y; + let x, y - let fillStyle = axis.stroke(self, i); + let fillStyle = axis.stroke(self, i) - let shiftDir = side == 0 || side == 3 ? -1 : 1; + let shiftDir = side == 0 || side == 3 ? -1 : 1 // axis label if (axis.label) { - let shiftAmt = axis.labelGap * shiftDir; - let baseLpos = round((axis._lpos + shiftAmt) * pxRatio); - - setFontStyle(axis.labelFont[0], fillStyle, "center", side == 2 ? TOP : BOTTOM); + let shiftAmt = axis.labelGap * shiftDir + let baseLpos = round((axis._lpos + shiftAmt) * pxRatio) + + setFontStyle( + axis.labelFont[0], + fillStyle, + 'center', + side == 2 ? TOP : BOTTOM + ) - ctx.save(); + ctx.save() if (ori == 1) { - x = y = 0; + x = y = 0 - ctx.translate( - baseLpos, - round(plotTop + plotHgt / 2), - ); - ctx.rotate((side == 3 ? -PI : PI) / 2); - - } - else { - x = round(plotLft + plotWid / 2); - y = baseLpos; + ctx.translate(baseLpos, round(plotTop + plotHgt / 2)) + ctx.rotate((side == 3 ? -PI : PI) / 2) + } else { + x = round(plotLft + plotWid / 2) + y = baseLpos } - ctx.fillText(axis.label, x, y); + ctx.fillText(axis.label, x, y) - ctx.restore(); + ctx.restore() } - let [_incr, _space] = axis._found; + let [_incr, _space] = axis._found - if (_space == 0) - continue; + if (_space == 0) continue - let scale = scales[axis.scale]; + let scale = scales[axis.scale] - let plotDim = ori == 0 ? plotWid : plotHgt; - let plotOff = ori == 0 ? plotLft : plotTop; + let plotDim = ori == 0 ? plotWid : plotHgt + let plotOff = ori == 0 ? plotLft : plotTop - let axisGap = round(axis.gap * pxRatio); + let axisGap = round(axis.gap * pxRatio) - let _splits = axis._splits; + let _splits = axis._splits // tick labels // BOO this assumes a specific data/series - let splits = scale.distr == 2 ? _splits.map(i => data0[i]) : _splits; - let incr = scale.distr == 2 ? data0[_splits[1]] - data0[_splits[0]] : _incr; + let splits = + scale.distr == 2 ? _splits.map((i) => data0[i]) : _splits + let incr = + scale.distr == 2 ? data0[_splits[1]] - data0[_splits[0]] : _incr - let ticks = axis.ticks; - let border = axis.border; - let tickSize = ticks.show ? round(ticks.size * pxRatio) : 0; + let ticks = axis.ticks + let border = axis.border + let tickSize = ticks.show ? round(ticks.size * pxRatio) : 0 // rotating of labels only supported on bottom x axis - let angle = axis._rotate * -PI/180; - - let basePos = pxRound(axis._pos * pxRatio); - let shiftAmt = (tickSize + axisGap) * shiftDir; - let finalPos = basePos + shiftAmt; - y = ori == 0 ? finalPos : 0; - x = ori == 1 ? finalPos : 0; - - let font = axis.font[0]; - let textAlign = axis.align == 1 ? LEFT : - axis.align == 2 ? RIGHT : - angle > 0 ? LEFT : - angle < 0 ? RIGHT : - ori == 0 ? "center" : side == 3 ? RIGHT : LEFT; - let textBaseline = angle || - ori == 1 ? "middle" : side == 2 ? TOP : BOTTOM; - - setFontStyle(font, fillStyle, textAlign, textBaseline); - - let lineHeight = axis.font[1] * axis.lineGap; - - let canOffs = _splits.map(val => pxRound(getPos(val, scale, plotDim, plotOff))); - - let _values = axis._values; + let angle = (axis._rotate * -PI) / 180 + + let basePos = pxRound(axis._pos * pxRatio) + let shiftAmt = (tickSize + axisGap) * shiftDir + let finalPos = basePos + shiftAmt + y = ori == 0 ? finalPos : 0 + x = ori == 1 ? finalPos : 0 + + let font = axis.font[0] + let textAlign = + axis.align == 1 + ? LEFT + : axis.align == 2 + ? RIGHT + : angle > 0 + ? LEFT + : angle < 0 + ? RIGHT + : ori == 0 + ? 'center' + : side == 3 + ? RIGHT + : LEFT + let textBaseline = + angle || ori == 1 ? 'middle' : side == 2 ? TOP : BOTTOM + + setFontStyle(font, fillStyle, textAlign, textBaseline) + + let lineHeight = axis.font[1] * axis.lineGap + + let canOffs = _splits.map((val) => + pxRound(getPos(val, scale, plotDim, plotOff)) + ) + + let _values = axis._values for (let i = 0; i < _values.length; i++) { - let val = _values[i]; + let val = _values[i] if (val != null) { - if (ori == 0) - x = canOffs[i]; - else - y = canOffs[i]; + if (ori == 0) x = canOffs[i] + else y = canOffs[i] - val = "" + val; + val = '' + val - let _parts = val.indexOf("\n") == -1 ? [val] : val.split(/\n/gm); + let _parts = + val.indexOf('\n') == -1 ? [val] : val.split(/\n/gm) for (let j = 0; j < _parts.length; j++) { - let text = _parts[j]; + let text = _parts[j] if (angle) { - ctx.save(); - ctx.translate(x, y + j * lineHeight); // can this be replaced with position math? - ctx.rotate(angle); // can this be done once? - ctx.fillText(text, 0, 0); - ctx.restore(); - } - else - ctx.fillText(text, x, y + j * lineHeight); + ctx.save() + ctx.translate(x, y + j * lineHeight) // can this be replaced with position math? + ctx.rotate(angle) // can this be done once? + ctx.fillText(text, 0, 0) + ctx.restore() + } else ctx.fillText(text, x, y + j * lineHeight) } } } @@ -2039,12 +2381,12 @@ export default function uPlot(opts, data, then) { roundDec(ticks.width * pxRatio, 3), ticks.stroke(self, i), ticks.dash, - ticks.cap, - ); + ticks.cap + ) } // grid - let grid = axis.grid; + let grid = axis.grid if (grid.show) { drawOrthoLines( @@ -2057,8 +2399,8 @@ export default function uPlot(opts, data, then) { roundDec(grid.width * pxRatio, 3), grid.stroke(self, i), grid.dash, - grid.cap, - ); + grid.cap + ) } if (border.show) { @@ -2072,126 +2414,138 @@ export default function uPlot(opts, data, then) { roundDec(border.width * pxRatio, 3), border.stroke(self, i), border.dash, - border.cap, - ); + border.cap + ) } } - fire("drawAxes"); + fire('drawAxes') } function resetYSeries(minMax) { - // log("resetYSeries()", arguments); + // log("resetYSeries()", arguments); series.forEach((s, i) => { if (i > 0) { - s._paths = null; + s._paths = null if (minMax) { if (mode == 1) { - s.min = null; - s.max = null; - } - else { - s.facets.forEach(f => { - f.min = null; - f.max = null; - }); + s.min = null + s.max = null + } else { + s.facets.forEach((f) => { + f.min = null + f.max = null + }) } } } - }); + }) } - let queuedCommit = false; - let deferHooks = false; - let hooksQueue = []; + let queuedCommit = false + let deferHooks = false + let hooksQueue = [] function flushHooks() { - deferHooks = false; + deferHooks = false - for (let i = 0; i < hooksQueue.length; i++) - fire(...hooksQueue[i]) + for (let i = 0; i < hooksQueue.length; i++) fire(...hooksQueue[i]) - hooksQueue.length = 0; + hooksQueue.length = 0 } function commit() { if (!queuedCommit) { - microTask(_commit); - queuedCommit = true; + microTask(_commit) + queuedCommit = true } } // manual batching (aka immediate mode), skips microtask queue function batch(fn, _deferHooks = false) { - queuedCommit = true; - deferHooks = _deferHooks; + queuedCommit = true + deferHooks = _deferHooks - fn(self); - _commit(); + fn(self) + _commit() - if (_deferHooks && hooksQueue.length > 0) - queueMicrotask(flushHooks); + if (_deferHooks && hooksQueue.length > 0) queueMicrotask(flushHooks) } - self.batch = batch; + self.batch = batch function _commit() { - // log("_commit()", arguments); + // log("_commit()", arguments); if (shouldSetScales) { - setScales(); - shouldSetScales = false; + setScales() + shouldSetScales = false } if (shouldConvergeSize) { - convergeSize(); - shouldConvergeSize = false; + convergeSize() + shouldConvergeSize = false } if (shouldSetSize) { - setStylePx(under, LEFT, plotLftCss); - setStylePx(under, TOP, plotTopCss); - setStylePx(under, WIDTH, plotWidCss); - setStylePx(under, HEIGHT, plotHgtCss); + setStylePx(under, LEFT, plotLftCss) + setStylePx(under, TOP, plotTopCss) + setStylePx(under, WIDTH, plotWidCss) + setStylePx(under, HEIGHT, plotHgtCss) - setStylePx(over, LEFT, plotLftCss); - setStylePx(over, TOP, plotTopCss); - setStylePx(over, WIDTH, plotWidCss); - setStylePx(over, HEIGHT, plotHgtCss); + setStylePx(over, LEFT, plotLftCss) + setStylePx(over, TOP, plotTopCss) + setStylePx(over, WIDTH, plotWidCss) + setStylePx(over, HEIGHT, plotHgtCss) - setStylePx(wrap, WIDTH, fullWidCss); - setStylePx(wrap, HEIGHT, fullHgtCss); + setStylePx(wrap, WIDTH, fullWidCss) + setStylePx(wrap, HEIGHT, fullHgtCss) // NOTE: mutating this during print preview in Chrome forces transparent // canvas pixels to white, even when followed up with clearRect() below - can.width = round(fullWidCss * pxRatio); - can.height = round(fullHgtCss * pxRatio); + can.width = round(fullWidCss * pxRatio) + can.height = round(fullHgtCss * pxRatio) axes.forEach(({ _el, _show, _size, _pos, side }) => { if (_el != null) { if (_show) { - let posOffset = (side === 3 || side === 0 ? _size : 0); - let isVt = side % 2 == 1; - - setStylePx(_el, isVt ? "left" : "top", _pos - posOffset); - setStylePx(_el, isVt ? "width" : "height", _size); - setStylePx(_el, isVt ? "top" : "left", isVt ? plotTopCss : plotLftCss); - setStylePx(_el, isVt ? "height" : "width", isVt ? plotHgtCss : plotWidCss); - - remClass(_el, OFF); - } - else - addClass(_el, OFF); + let posOffset = side === 3 || side === 0 ? _size : 0 + let isVt = side % 2 == 1 + + setStylePx(_el, isVt ? 'left' : 'top', _pos - posOffset) + setStylePx(_el, isVt ? 'width' : 'height', _size) + setStylePx( + _el, + isVt ? 'top' : 'left', + isVt ? plotTopCss : plotLftCss + ) + setStylePx( + _el, + isVt ? 'height' : 'width', + isVt ? plotHgtCss : plotWidCss + ) + + remClass(_el, OFF) + } else addClass(_el, OFF) } - }); + }) // invalidate ctx style cache - ctxStroke = ctxFill = ctxWidth = ctxJoin = ctxCap = ctxFont = ctxAlign = ctxBaseline = ctxDash = null; - ctxAlpha = 1; - - syncRect(true); + ctxStroke = + ctxFill = + ctxWidth = + ctxJoin = + ctxCap = + ctxFont = + ctxAlign = + ctxBaseline = + ctxDash = + null + ctxAlpha = 1 + + syncRect(true) if ( plotLftCss != _plotLftCss || @@ -2199,414 +2553,435 @@ export default function uPlot(opts, data, then) { plotWidCss != _plotWidCss || plotHgtCss != _plotHgtCss ) { - resetYSeries(false); + resetYSeries(false) - let pctWid = plotWidCss / _plotWidCss; - let pctHgt = plotHgtCss / _plotHgtCss; + let pctWid = plotWidCss / _plotWidCss + let pctHgt = plotHgtCss / _plotHgtCss if (cursor.show && !shouldSetCursor && cursor.left >= 0) { - cursor.left *= pctWid; - cursor.top *= pctHgt; - - vCursor && elTrans(vCursor, round(cursor.left), 0, plotWidCss, plotHgtCss); - hCursor && elTrans(hCursor, 0, round(cursor.top), plotWidCss, plotHgtCss); + cursor.left *= pctWid + cursor.top *= pctHgt + + vCursor && + elTrans( + vCursor, + round(cursor.left), + 0, + plotWidCss, + plotHgtCss + ) + hCursor && + elTrans( + hCursor, + 0, + round(cursor.top), + plotWidCss, + plotHgtCss + ) for (let i = 0; i < cursorPts.length; i++) { - let pt = cursorPts[i]; + let pt = cursorPts[i] if (pt != null) { - cursorPtsLft[i] *= pctWid; - cursorPtsTop[i] *= pctHgt; - elTrans(pt, ceil(cursorPtsLft[i]), ceil(cursorPtsTop[i]), plotWidCss, plotHgtCss); + cursorPtsLft[i] *= pctWid + cursorPtsTop[i] *= pctHgt + elTrans( + pt, + ceil(cursorPtsLft[i]), + ceil(cursorPtsTop[i]), + plotWidCss, + plotHgtCss + ) } } } - if (select.show && !shouldSetSelect && select.left >= 0 && select.width > 0) { - select.left *= pctWid; - select.width *= pctWid; - select.top *= pctHgt; - select.height *= pctHgt; + if ( + select.show && + !shouldSetSelect && + select.left >= 0 && + select.width > 0 + ) { + select.left *= pctWid + select.width *= pctWid + select.top *= pctHgt + select.height *= pctHgt for (let prop in _hideProps) - setStylePx(selectDiv, prop, select[prop]); + setStylePx(selectDiv, prop, select[prop]) } - _plotLftCss = plotLftCss; - _plotTopCss = plotTopCss; - _plotWidCss = plotWidCss; - _plotHgtCss = plotHgtCss; + _plotLftCss = plotLftCss + _plotTopCss = plotTopCss + _plotWidCss = plotWidCss + _plotHgtCss = plotHgtCss } - fire("setSize"); + fire('setSize') - shouldSetSize = false; + shouldSetSize = false } if (fullWidCss > 0 && fullHgtCss > 0) { - ctx.clearRect(0, 0, can.width, can.height); - fire("drawClear"); - drawOrder.forEach(fn => fn()); - fire("draw"); + ctx.clearRect(0, 0, can.width, can.height) + fire('drawClear') + drawOrder.forEach((fn) => fn()) + fire('draw') } if (select.show && shouldSetSelect) { - setSelect(select); - shouldSetSelect = false; + setSelect(select) + shouldSetSelect = false } if (cursor.show && shouldSetCursor) { - updateCursor(null, true, false); - shouldSetCursor = false; + updateCursor(null, true, false) + shouldSetCursor = false } if (FEAT_LEGEND && legend.show && legend.live && shouldSetLegend) { - setLegend(); - shouldSetLegend = false; // redundant currently + setLegend() + shouldSetLegend = false // redundant currently } if (!ready) { - ready = true; - self.status = 1; + ready = true + self.status = 1 - fire("ready"); + fire('ready') } - viaAutoScaleX = false; + viaAutoScaleX = false - queuedCommit = false; + queuedCommit = false } self.redraw = (rebuildPaths, recalcAxes) => { - shouldConvergeSize = recalcAxes || false; + shouldConvergeSize = recalcAxes || false - if (rebuildPaths !== false) - _setScale(xScaleKey, scaleX.min, scaleX.max); - else - commit(); - }; + if (rebuildPaths !== false) _setScale(xScaleKey, scaleX.min, scaleX.max) + else commit() + } // redraw() => setScale('x', scales.x.min, scales.x.max); // explicit, never re-ranged (is this actually true? for x and y) function setScale(key, opts) { - let sc = scales[key]; + let sc = scales[key] if (sc.from == null) { if (dataLen == 0) { - let minMax = sc.range(self, opts.min, opts.max, key); - opts.min = minMax[0]; - opts.max = minMax[1]; + let minMax = sc.range(self, opts.min, opts.max, key) + opts.min = minMax[0] + opts.max = minMax[1] } if (opts.min > opts.max) { - let _min = opts.min; - opts.min = opts.max; - opts.max = _min; + let _min = opts.min + opts.min = opts.max + opts.max = _min } - if (dataLen > 1 && opts.min != null && opts.max != null && opts.max - opts.min < 1e-16) - return; + if ( + dataLen > 1 && + opts.min != null && + opts.max != null && + opts.max - opts.min < 1e-16 + ) + return if (key == xScaleKey) { if (sc.distr == 2 && dataLen > 0) { - opts.min = closestIdx(opts.min, data[0]); - opts.max = closestIdx(opts.max, data[0]); + opts.min = closestIdx(opts.min, data[0]) + opts.max = closestIdx(opts.max, data[0]) - if (opts.min == opts.max) - opts.max++; + if (opts.min == opts.max) opts.max++ } } - // log("setScale()", arguments); + // log("setScale()", arguments); - pendScales[key] = opts; + pendScales[key] = opts - shouldSetScales = true; - commit(); + shouldSetScales = true + commit() } } - self.setScale = setScale; + self.setScale = setScale -// INTERACTION + // INTERACTION - let xCursor; - let yCursor; - let vCursor; - let hCursor; + let xCursor + let yCursor + let vCursor + let hCursor // starting position before cursor.move - let rawMouseLeft0; - let rawMouseTop0; + let rawMouseLeft0 + let rawMouseTop0 // starting position - let mouseLeft0; - let mouseTop0; + let mouseLeft0 + let mouseTop0 // current position before cursor.move - let rawMouseLeft1; - let rawMouseTop1; + let rawMouseLeft1 + let rawMouseTop1 // current position - let mouseLeft1; - let mouseTop1; + let mouseLeft1 + let mouseTop1 - let dragging = false; + let dragging = false - const drag = cursor.drag; + const drag = cursor.drag - let dragX = drag.x; - let dragY = drag.y; + let dragX = drag.x + let dragY = drag.y if (cursor.show) { - if (cursor.x) - xCursor = placeDiv(CURSOR_X, over); - if (cursor.y) - yCursor = placeDiv(CURSOR_Y, over); + if (cursor.x) xCursor = placeDiv(CURSOR_X, over) + if (cursor.y) yCursor = placeDiv(CURSOR_Y, over) if (scaleX.ori == 0) { - vCursor = xCursor; - hCursor = yCursor; - } - else { - vCursor = yCursor; - hCursor = xCursor; + vCursor = xCursor + hCursor = yCursor + } else { + vCursor = yCursor + hCursor = xCursor } - mouseLeft1 = cursor.left; - mouseTop1 = cursor.top; + mouseLeft1 = cursor.left + mouseTop1 = cursor.top } - const select = self.select = assign({ - show: true, - over: true, - left: 0, - width: 0, - top: 0, - height: 0, - }, opts.select); + const select = (self.select = assign( + { + show: true, + over: true, + left: 0, + width: 0, + top: 0, + height: 0 + }, + opts.select + )) - const selectDiv = select.show ? placeDiv(SELECT, select.over ? over : under) : null; + const selectDiv = select.show + ? placeDiv(SELECT, select.over ? over : under) + : null function setSelect(opts, _fire) { if (select.show) { for (let prop in opts) { - select[prop] = opts[prop]; + select[prop] = opts[prop] - if (prop in _hideProps) - setStylePx(selectDiv, prop, opts[prop]); + if (prop in _hideProps) setStylePx(selectDiv, prop, opts[prop]) } - _fire !== false && fire("setSelect"); + _fire !== false && fire('setSelect') } } - self.setSelect = setSelect; + self.setSelect = setSelect function toggleDOM(i, onOff) { - let s = series[i]; - let label = showLegend ? legendRows[i] : null; + let s = series[i] + let label = showLegend ? legendRows[i] : null - if (s.show) - label && remClass(label, OFF); + if (s.show) label && remClass(label, OFF) else { - label && addClass(label, OFF); - let pt = cursorOnePt ? cursorPts[0] : cursorPts[i]; - elTrans(pt, -10, -10, plotWidCss, plotHgtCss); + label && addClass(label, OFF) + let pt = cursorOnePt ? cursorPts[0] : cursorPts[i] + elTrans(pt, -10, -10, plotWidCss, plotHgtCss) } } function _setScale(key, min, max) { - setScale(key, {min, max}); + setScale(key, { min, max }) } function setSeries(i, opts, _fire, _pub) { - // log("setSeries()", arguments); + // log("setSeries()", arguments); - if (opts.focus != null) - setFocus(i); + if (opts.focus != null) setFocus(i) if (opts.show != null) { series.forEach((s, si) => { if (si > 0 && (i == si || i == null)) { - s.show = opts.show; - FEAT_LEGEND && toggleDOM(si, opts.show); + s.show = opts.show + FEAT_LEGEND && toggleDOM(si, opts.show) if (mode == 2) { - _setScale(s.facets[0].scale, null, null); - _setScale(s.facets[1].scale, null, null); - } - else - _setScale(s.scale, null, null); + _setScale(s.facets[0].scale, null, null) + _setScale(s.facets[1].scale, null, null) + } else _setScale(s.scale, null, null) - commit(); + commit() } - }); + }) } - _fire !== false && fire("setSeries", i, opts); + _fire !== false && fire('setSeries', i, opts) - _pub && pubSync("setSeries", self, i, opts); + _pub && pubSync('setSeries', self, i, opts) } - self.setSeries = setSeries; + self.setSeries = setSeries function setBand(bi, opts) { - assign(bands[bi], opts); + assign(bands[bi], opts) } function addBand(opts, bi) { - opts.fill = fnOrSelf(opts.fill || null); - opts.dir = ifNull(opts.dir, -1); - bi = bi == null ? bands.length : bi; - bands.splice(bi, 0, opts); + opts.fill = fnOrSelf(opts.fill || null) + opts.dir = ifNull(opts.dir, -1) + bi = bi == null ? bands.length : bi + bands.splice(bi, 0, opts) } function delBand(bi) { - if (bi == null) - bands.length = 0; - else - bands.splice(bi, 1); + if (bi == null) bands.length = 0 + else bands.splice(bi, 1) } - self.addBand = addBand; - self.setBand = setBand; - self.delBand = delBand; + self.addBand = addBand + self.setBand = setBand + self.delBand = delBand function setAlpha(i, value) { - series[i].alpha = value; + series[i].alpha = value - if (cursor.show && cursorPts[i]) - cursorPts[i].style.opacity = value; + if (cursor.show && cursorPts[i]) cursorPts[i].style.opacity = value if (FEAT_LEGEND && showLegend && legendRows[i]) - legendRows[i].style.opacity = value; + legendRows[i].style.opacity = value } // y-distance - let closestDist; - let closestSeries; - let focusedSeries; - const FOCUS_TRUE = {focus: true}; + let closestDist + let closestSeries + let focusedSeries + const FOCUS_TRUE = { focus: true } function setFocus(i) { if (i != focusedSeries) { - // log("setFocus()", arguments); + // log("setFocus()", arguments); - let allFocused = i == null; + let allFocused = i == null - let _setAlpha = focus.alpha != 1; + let _setAlpha = focus.alpha != 1 series.forEach((s, i2) => { if (mode == 1 || i2 > 0) { - let isFocused = allFocused || i2 == 0 || i2 == i; - s._focus = allFocused ? null : isFocused; - _setAlpha && setAlpha(i2, isFocused ? 1 : focus.alpha); + let isFocused = allFocused || i2 == 0 || i2 == i + s._focus = allFocused ? null : isFocused + _setAlpha && setAlpha(i2, isFocused ? 1 : focus.alpha) } - }); + }) - focusedSeries = i; - _setAlpha && commit(); + focusedSeries = i + _setAlpha && commit() } } if (showLegend && cursorFocus) { - onMouse(mouseleave, legendTable, e => { - if (cursor._lock) - return; + onMouse(mouseleave, legendTable, (e) => { + if (cursor._lock) return - setCursorEvent(e); + setCursorEvent(e) if (focusedSeries != null) - setSeries(null, FOCUS_TRUE, true, syncOpts.setSeries); - }); + setSeries(null, FOCUS_TRUE, true, syncOpts.setSeries) + }) } function posToVal(pos, scale, can) { - let sc = scales[scale]; + let sc = scales[scale] - if (can) - pos = pos / pxRatio - (sc.ori == 1 ? plotTopCss : plotLftCss); + if (can) pos = pos / pxRatio - (sc.ori == 1 ? plotTopCss : plotLftCss) - let dim = plotWidCss; + let dim = plotWidCss if (sc.ori == 1) { - dim = plotHgtCss; - pos = dim - pos; + dim = plotHgtCss + pos = dim - pos } - if (sc.dir == -1) - pos = dim - pos; + if (sc.dir == -1) pos = dim - pos let _min = sc._min, _max = sc._max, - pct = pos / dim; + pct = pos / dim - let sv = _min + (_max - _min) * pct; + let sv = _min + (_max - _min) * pct - let distr = sc.distr; + let distr = sc.distr - return ( - distr == 3 ? pow(10, sv) : - distr == 4 ? sinh(sv, sc.asinh) : - distr == 100 ? sc.bwd(sv) : - sv - ); + return distr == 3 + ? pow(10, sv) + : distr == 4 + ? sinh(sv, sc.asinh) + : distr == 100 + ? sc.bwd(sv) + : sv } function closestIdxFromXpos(pos, can) { - let v = posToVal(pos, xScaleKey, can); - return closestIdx(v, data[0], i0, i1); - } - - self.valToIdx = val => closestIdx(val, data[0]); - self.posToIdx = closestIdxFromXpos; - self.posToVal = posToVal; - self.valToPos = (val, scale, can) => ( - scales[scale].ori == 0 ? - getHPos(val, scales[scale], - can ? plotWid : plotWidCss, - can ? plotLft : 0, - ) : - getVPos(val, scales[scale], - can ? plotHgt : plotHgtCss, - can ? plotTop : 0, - ) - ); + let v = posToVal(pos, xScaleKey, can) + return closestIdx(v, data[0], i0, i1) + } + + self.valToIdx = (val) => closestIdx(val, data[0]) + self.posToIdx = closestIdxFromXpos + self.posToVal = posToVal + self.valToPos = (val, scale, can) => + scales[scale].ori == 0 + ? getHPos( + val, + scales[scale], + can ? plotWid : plotWidCss, + can ? plotLft : 0 + ) + : getVPos( + val, + scales[scale], + can ? plotHgt : plotHgtCss, + can ? plotTop : 0 + ) self.setCursor = (opts, _fire, _pub) => { - mouseLeft1 = opts.left; - mouseTop1 = opts.top; - // assign(cursor, opts); - updateCursor(null, _fire, _pub); - }; + mouseLeft1 = opts.left + mouseTop1 = opts.top + // assign(cursor, opts); + updateCursor(null, _fire, _pub) + } function setSelH(off, dim) { - setStylePx(selectDiv, LEFT, select.left = off); - setStylePx(selectDiv, WIDTH, select.width = dim); + setStylePx(selectDiv, LEFT, (select.left = off)) + setStylePx(selectDiv, WIDTH, (select.width = dim)) } function setSelV(off, dim) { - setStylePx(selectDiv, TOP, select.top = off); - setStylePx(selectDiv, HEIGHT, select.height = dim); + setStylePx(selectDiv, TOP, (select.top = off)) + setStylePx(selectDiv, HEIGHT, (select.height = dim)) } - let setSelX = scaleX.ori == 0 ? setSelH : setSelV; - let setSelY = scaleX.ori == 1 ? setSelH : setSelV; + let setSelX = scaleX.ori == 0 ? setSelH : setSelV + let setSelY = scaleX.ori == 1 ? setSelH : setSelV function syncLegend() { if (showLegend && legend.live) { for (let i = mode == 2 ? 1 : 0; i < series.length; i++) { - if (i == 0 && multiValLegend) - continue; + if (i == 0 && multiValLegend) continue - let vals = legend.values[i]; + let vals = legend.values[i] - let j = 0; + let j = 0 for (let k in vals) - legendCells[i][j++].firstChild.nodeValue = vals[k]; + legendCells[i][j++].firstChild.nodeValue = vals[k] } } } @@ -2615,220 +2990,275 @@ export default function uPlot(opts, data, then) { if (opts != null) { if (opts.idxs) { opts.idxs.forEach((didx, sidx) => { - activeIdxs[sidx] = didx; - }); - } - else if (!isUndef(opts.idx)) - activeIdxs.fill(opts.idx); + activeIdxs[sidx] = didx + }) + } else if (!isUndef(opts.idx)) activeIdxs.fill(opts.idx) - legend.idx = activeIdxs[0]; + legend.idx = activeIdxs[0] } if (showLegend && legend.live) { for (let sidx = 0; sidx < series.length; sidx++) { - if (sidx > 0 || mode == 1 && !multiValLegend) - setLegendValues(sidx, activeIdxs[sidx]); + if (sidx > 0 || (mode == 1 && !multiValLegend)) + setLegendValues(sidx, activeIdxs[sidx]) } - syncLegend(); + syncLegend() } - shouldSetLegend = false; + shouldSetLegend = false - _fire !== false && fire("setLegend"); + _fire !== false && fire('setLegend') } - self.setLegend = setLegend; + self.setLegend = setLegend function setLegendValues(sidx, idx) { - let s = series[sidx]; - let src = sidx == 0 && xScaleDistr == 2 ? data0 : data[sidx]; - let val; + let s = series[sidx] + let src = sidx == 0 && xScaleDistr == 2 ? data0 : data[sidx] + let val if (multiValLegend) - val = s.values(self, sidx, idx) ?? NULL_LEGEND_VALUES; + val = s.values(self, sidx, idx) ?? NULL_LEGEND_VALUES else { - val = s.value(self, idx == null ? null : src[idx], sidx, idx); - val = val == null ? NULL_LEGEND_VALUES : {_: val}; + val = s.value( + self, + idx == null ? null : src[idx], + sidx, + idx, + fmtNum + ) + val = val == null ? NULL_LEGEND_VALUES : { _: val } } - legend.values[sidx] = val; + legend.values[sidx] = val } function updateCursor(src, _fire, _pub) { - // ts == null && log("updateCursor()", arguments); + // ts == null && log("updateCursor()", arguments); - rawMouseLeft1 = mouseLeft1; - rawMouseTop1 = mouseTop1; + rawMouseLeft1 = mouseLeft1 + rawMouseTop1 = mouseTop1 - [mouseLeft1, mouseTop1] = cursor.move(self, mouseLeft1, mouseTop1); + ;[mouseLeft1, mouseTop1] = cursor.move(self, mouseLeft1, mouseTop1) - cursor.left = mouseLeft1; - cursor.top = mouseTop1; + cursor.left = mouseLeft1 + cursor.top = mouseTop1 if (cursor.show) { - vCursor && elTrans(vCursor, round(mouseLeft1), 0, plotWidCss, plotHgtCss); - hCursor && elTrans(hCursor, 0, round(mouseTop1), plotWidCss, plotHgtCss); + vCursor && + elTrans(vCursor, round(mouseLeft1), 0, plotWidCss, plotHgtCss) + hCursor && + elTrans(hCursor, 0, round(mouseTop1), plotWidCss, plotHgtCss) } - let idx; + let idx // when zooming to an x scale range between datapoints the binary search // for nearest min/max indices results in this condition. cheap hack :D - let noDataInRange = i0 > i1; // works for mode 1 only + let noDataInRange = i0 > i1 // works for mode 1 only - closestDist = inf; - closestSeries = null; + closestDist = inf + closestSeries = null // TODO: extract - let xDim = scaleX.ori == 0 ? plotWidCss : plotHgtCss; - let yDim = scaleX.ori == 1 ? plotWidCss : plotHgtCss; + let xDim = scaleX.ori == 0 ? plotWidCss : plotHgtCss + let yDim = scaleX.ori == 1 ? plotWidCss : plotHgtCss // if cursor hidden, hide points & clear legend vals if (mouseLeft1 < 0 || dataLen == 0 || noDataInRange) { - idx = cursor.idx = null; + idx = cursor.idx = null for (let i = 0; i < series.length; i++) { - let pt = cursorPts[i]; - pt != null && elTrans(pt, -10, -10, plotWidCss, plotHgtCss); + let pt = cursorPts[i] + pt != null && elTrans(pt, -10, -10, plotWidCss, plotHgtCss) } if (cursorFocus) - setSeries(null, FOCUS_TRUE, true, src == null && syncOpts.setSeries); + setSeries( + null, + FOCUS_TRUE, + true, + src == null && syncOpts.setSeries + ) if (FEAT_LEGEND && legend.live) { - activeIdxs.fill(idx); - shouldSetLegend = true; + activeIdxs.fill(idx) + shouldSetLegend = true } - } - else { - // let pctY = 1 - (y / rect.height); + } else { + // let pctY = 1 - (y / rect.height); - let mouseXPos, valAtPosX, xPos; + let mouseXPos, valAtPosX, xPos if (mode == 1) { - mouseXPos = scaleX.ori == 0 ? mouseLeft1 : mouseTop1; - valAtPosX = posToVal(mouseXPos, xScaleKey); - idx = cursor.idx = closestIdx(valAtPosX, data[0], i0, i1); - xPos = valToPosX(data[0][idx], scaleX, xDim, 0); + mouseXPos = scaleX.ori == 0 ? mouseLeft1 : mouseTop1 + valAtPosX = posToVal(mouseXPos, xScaleKey) + idx = cursor.idx = closestIdx(valAtPosX, data[0], i0, i1) + xPos = valToPosX(data[0][idx], scaleX, xDim, 0) } // closest pt values - let _ptLft = -10; - let _ptTop = -10; - let _ptWid = 0; - let _ptHgt = 0; - let _centered = true; - let _ptFill = ''; - let _ptStroke = ''; + let _ptLft = -10 + let _ptTop = -10 + let _ptWid = 0 + let _ptHgt = 0 + let _centered = true + let _ptFill = '' + let _ptStroke = '' for (let i = mode == 2 ? 1 : 0; i < series.length; i++) { - let s = series[i]; - - let idx1 = activeIdxs[i]; - let yVal1 = idx1 == null ? null : (mode == 1 ? data[i][idx1] : data[i][1][idx1]); - - let idx2 = cursor.dataIdx(self, i, idx, valAtPosX); - let yVal2 = idx2 == null ? null : (mode == 1 ? data[i][idx2] : data[i][1][idx2]); - - shouldSetLegend = shouldSetLegend || yVal2 != yVal1 || idx2 != idx1; - - activeIdxs[i] = idx2; - - let xPos2 = idx2 == idx ? xPos : valToPosX(mode == 1 ? data[0][idx2] : data[i][0][idx2], scaleX, xDim, 0); + let s = series[i] + + let idx1 = activeIdxs[i] + let yVal1 = + idx1 == null + ? null + : mode == 1 + ? data[i][idx1] + : data[i][1][idx1] + + let idx2 = cursor.dataIdx(self, i, idx, valAtPosX) + let yVal2 = + idx2 == null + ? null + : mode == 1 + ? data[i][idx2] + : data[i][1][idx2] + + shouldSetLegend = + shouldSetLegend || yVal2 != yVal1 || idx2 != idx1 + + activeIdxs[i] = idx2 + + let xPos2 = + idx2 == idx + ? xPos + : valToPosX( + mode == 1 ? data[0][idx2] : data[i][0][idx2], + scaleX, + xDim, + 0 + ) if (i > 0 && s.show) { // this doesnt really work for state timeline, heatmap, status history (where the value maps to color, not y coords) - let yPos = yVal2 == null ? -10 : valToPosY(yVal2, mode == 1 ? scales[s.scale] : scales[s.facets[1].scale], yDim, 0); + let yPos = + yVal2 == null + ? -10 + : valToPosY( + yVal2, + mode == 1 + ? scales[s.scale] + : scales[s.facets[1].scale], + yDim, + 0 + ) if (cursorFocus && yVal2 != null) { - let mouseYPos = scaleX.ori == 1 ? mouseLeft1 : mouseTop1; - let dist = abs(focus.dist(self, i, idx2, yPos, mouseYPos)); + let mouseYPos = scaleX.ori == 1 ? mouseLeft1 : mouseTop1 + let dist = abs( + focus.dist(self, i, idx2, yPos, mouseYPos) + ) if (dist < closestDist) { - let bias = focus.bias; + let bias = focus.bias if (bias != 0) { - let mouseYVal = posToVal(mouseYPos, s.scale); + let mouseYVal = posToVal(mouseYPos, s.scale) - let seriesYValSign = yVal2 >= 0 ? 1 : -1; - let mouseYValSign = mouseYVal >= 0 ? 1 : -1; + let seriesYValSign = yVal2 >= 0 ? 1 : -1 + let mouseYValSign = mouseYVal >= 0 ? 1 : -1 // with a focus bias, we will never cross zero when prox testing // it's either closest towards zero, or closest away from zero - if (mouseYValSign == seriesYValSign && ( - mouseYValSign == 1 ? - (bias == 1 ? yVal2 >= mouseYVal : yVal2 <= mouseYVal) : // >= 0 - (bias == 1 ? yVal2 <= mouseYVal : yVal2 >= mouseYVal) // < 0 - )) { - closestDist = dist; - closestSeries = i; + if ( + mouseYValSign == seriesYValSign && + (mouseYValSign == 1 + ? bias == 1 + ? yVal2 >= mouseYVal + : yVal2 <= mouseYVal // >= 0 + : bias == 1 + ? yVal2 <= mouseYVal + : yVal2 >= mouseYVal) // < 0 + ) { + closestDist = dist + closestSeries = i } - } - else { - closestDist = dist; - closestSeries = i; + } else { + closestDist = dist + closestSeries = i } } } if (shouldSetLegend || cursorOnePt) { - let hPos, vPos; + let hPos, vPos if (scaleX.ori == 0) { - hPos = xPos2; - vPos = yPos; - } - else { - hPos = yPos; - vPos = xPos2; + hPos = xPos2 + vPos = yPos + } else { + hPos = yPos + vPos = xPos2 } - let ptWid, ptHgt, ptLft, ptTop, - ptStroke, ptFill, + let ptWid, + ptHgt, + ptLft, + ptTop, + ptStroke, + ptFill, centered = true, - getBBox = points.bbox; + getBBox = points.bbox if (getBBox != null) { - centered = false; + centered = false - let bbox = getBBox(self, i); + let bbox = getBBox(self, i) - ptLft = bbox.left; - ptTop = bbox.top; - ptWid = bbox.width; - ptHgt = bbox.height; - } - else { - ptLft = hPos; - ptTop = vPos; - ptWid = ptHgt = points.size(self, i); + ptLft = bbox.left + ptTop = bbox.top + ptWid = bbox.width + ptHgt = bbox.height + } else { + ptLft = hPos + ptTop = vPos + ptWid = ptHgt = points.size(self, i) } - ptFill = points.fill(self, i); - ptStroke = points.stroke(self, i); + ptFill = points.fill(self, i) + ptStroke = points.stroke(self, i) if (cursorOnePt) { - if (i == closestSeries && closestDist <= focus.prox) { - _ptLft = ptLft; - _ptTop = ptTop; - _ptWid = ptWid; - _ptHgt = ptHgt; - _centered = centered; - _ptFill = ptFill; - _ptStroke = ptStroke; + if ( + i == closestSeries && + closestDist <= focus.prox + ) { + _ptLft = ptLft + _ptTop = ptTop + _ptWid = ptWid + _ptHgt = ptHgt + _centered = centered + _ptFill = ptFill + _ptStroke = ptStroke } - } - else { - let pt = cursorPts[i]; + } else { + let pt = cursorPts[i] if (pt != null) { - cursorPtsLft[i] = ptLft; - cursorPtsTop[i] = ptTop; - - elSize(pt, ptWid, ptHgt, centered); - elColor(pt, ptFill, ptStroke); - elTrans(pt, ceil(ptLft), ceil(ptTop), plotWidCss, plotHgtCss); + cursorPtsLft[i] = ptLft + cursorPtsTop[i] = ptTop + + elSize(pt, ptWid, ptHgt, centered) + elColor(pt, ptFill, ptStroke) + elTrans( + pt, + ceil(ptLft), + ceil(ptTop), + plotWidCss, + plotHgtCss + ) } } } @@ -2840,19 +3270,28 @@ export default function uPlot(opts, data, then) { if (cursorOnePt) { // some of this logic is similar to series focus below, since it matches the behavior by design - let p = focus.prox; + let p = focus.prox - let focusChanged = focusedSeries == null ? closestDist <= p : (closestDist > p || closestSeries != focusedSeries); + let focusChanged = + focusedSeries == null + ? closestDist <= p + : closestDist > p || closestSeries != focusedSeries if (shouldSetLegend || focusChanged) { - let pt = cursorPts[0]; - - cursorPtsLft[0] = _ptLft; - cursorPtsTop[0] = _ptTop; - - elSize(pt, _ptWid, _ptHgt, _centered); - elColor(pt, _ptFill, _ptStroke); - elTrans(pt, ceil(_ptLft), ceil(_ptTop), plotWidCss, plotHgtCss); + let pt = cursorPts[0] + + cursorPtsLft[0] = _ptLft + cursorPtsTop[0] = _ptTop + + elSize(pt, _ptWid, _ptHgt, _centered) + elColor(pt, _ptFill, _ptStroke) + elTrans( + pt, + ceil(_ptLft), + ceil(_ptTop), + plotWidCss, + plotHgtCss + ) } } } @@ -2860,208 +3299,218 @@ export default function uPlot(opts, data, then) { // nit: cursor.drag.setSelect is assumed always true if (select.show && dragging) { if (src != null) { - let [xKey, yKey] = syncOpts.scales; - let [matchXKeys, matchYKeys] = syncOpts.match; - let [xKeySrc, yKeySrc] = src.cursor.sync.scales; + let [xKey, yKey] = syncOpts.scales + let [matchXKeys, matchYKeys] = syncOpts.match + let [xKeySrc, yKeySrc] = src.cursor.sync.scales // match the dragX/dragY implicitness/explicitness of src - let sdrag = src.cursor.drag; - dragX = sdrag._x; - dragY = sdrag._y; + let sdrag = src.cursor.drag + dragX = sdrag._x + dragY = sdrag._y if (dragX || dragY) { - let { left, top, width, height } = src.select; + let { left, top, width, height } = src.select - let sori = src.scales[xKeySrc].ori; - let sPosToVal = src.posToVal; + let sori = src.scales[xKeySrc].ori + let sPosToVal = src.posToVal - let sOff, sDim, sc, a, b; + let sOff, sDim, sc, a, b - let matchingX = xKey != null && matchXKeys(xKey, xKeySrc); - let matchingY = yKey != null && matchYKeys(yKey, yKeySrc); + let matchingX = xKey != null && matchXKeys(xKey, xKeySrc) + let matchingY = yKey != null && matchYKeys(yKey, yKeySrc) if (matchingX && dragX) { if (sori == 0) { - sOff = left; - sDim = width; - } - else { - sOff = top; - sDim = height; + sOff = left + sDim = width + } else { + sOff = top + sDim = height } - sc = scales[xKey]; + sc = scales[xKey] - a = valToPosX(sPosToVal(sOff, xKeySrc), sc, xDim, 0); - b = valToPosX(sPosToVal(sOff + sDim, xKeySrc), sc, xDim, 0); + a = valToPosX(sPosToVal(sOff, xKeySrc), sc, xDim, 0) + b = valToPosX( + sPosToVal(sOff + sDim, xKeySrc), + sc, + xDim, + 0 + ) - setSelX(min(a,b), abs(b-a)); - } - else - setSelX(0, xDim); + setSelX(min(a, b), abs(b - a)) + } else setSelX(0, xDim) if (matchingY && dragY) { if (sori == 1) { - sOff = left; - sDim = width; - } - else { - sOff = top; - sDim = height; + sOff = left + sDim = width + } else { + sOff = top + sDim = height } - sc = scales[yKey]; + sc = scales[yKey] - a = valToPosY(sPosToVal(sOff, yKeySrc), sc, yDim, 0); - b = valToPosY(sPosToVal(sOff + sDim, yKeySrc), sc, yDim, 0); + a = valToPosY(sPosToVal(sOff, yKeySrc), sc, yDim, 0) + b = valToPosY( + sPosToVal(sOff + sDim, yKeySrc), + sc, + yDim, + 0 + ) - setSelY(min(a,b), abs(b-a)); - } - else - setSelY(0, yDim); - } - else - hideSelect(); - } - else { - let rawDX = abs(rawMouseLeft1 - rawMouseLeft0); - let rawDY = abs(rawMouseTop1 - rawMouseTop0); + setSelY(min(a, b), abs(b - a)) + } else setSelY(0, yDim) + } else hideSelect() + } else { + let rawDX = abs(rawMouseLeft1 - rawMouseLeft0) + let rawDY = abs(rawMouseTop1 - rawMouseTop0) if (scaleX.ori == 1) { - let _rawDX = rawDX; - rawDX = rawDY; - rawDY = _rawDX; + let _rawDX = rawDX + rawDX = rawDY + rawDY = _rawDX } - dragX = drag.x && rawDX >= drag.dist; - dragY = drag.y && rawDY >= drag.dist; + dragX = drag.x && rawDX >= drag.dist + dragY = drag.y && rawDY >= drag.dist - let uni = drag.uni; + let uni = drag.uni if (uni != null) { // only calc drag status if they pass the dist thresh if (dragX && dragY) { - dragX = rawDX >= uni; - dragY = rawDY >= uni; + dragX = rawDX >= uni + dragY = rawDY >= uni // force unidirectionality when both are under uni limit if (!dragX && !dragY) { - if (rawDY > rawDX) - dragY = true; - else - dragX = true; + if (rawDY > rawDX) dragY = true + else dragX = true } } - } - else if (drag.x && drag.y && (dragX || dragY)) + } else if (drag.x && drag.y && (dragX || dragY)) // if omni with no uni then both dragX / dragY should be true if either is true - dragX = dragY = true; + dragX = dragY = true - let p0, p1; + let p0, p1 if (dragX) { if (scaleX.ori == 0) { - p0 = mouseLeft0; - p1 = mouseLeft1; - } - else { - p0 = mouseTop0; - p1 = mouseTop1; + p0 = mouseLeft0 + p1 = mouseLeft1 + } else { + p0 = mouseTop0 + p1 = mouseTop1 } - setSelX(min(p0, p1), abs(p1 - p0)); + setSelX(min(p0, p1), abs(p1 - p0)) - if (!dragY) - setSelY(0, yDim); + if (!dragY) setSelY(0, yDim) } if (dragY) { if (scaleX.ori == 1) { - p0 = mouseLeft0; - p1 = mouseLeft1; - } - else { - p0 = mouseTop0; - p1 = mouseTop1; + p0 = mouseLeft0 + p1 = mouseLeft1 + } else { + p0 = mouseTop0 + p1 = mouseTop1 } - setSelY(min(p0, p1), abs(p1 - p0)); + setSelY(min(p0, p1), abs(p1 - p0)) - if (!dragX) - setSelX(0, xDim); + if (!dragX) setSelX(0, xDim) } // the drag didn't pass the dist requirement if (!dragX && !dragY) { - setSelX(0, 0); - setSelY(0, 0); + setSelX(0, 0) + setSelY(0, 0) } } } - drag._x = dragX; - drag._y = dragY; + drag._x = dragX + drag._y = dragY if (src == null) { if (_pub) { if (syncKey != null) { - let [xSyncKey, ySyncKey] = syncOpts.scales; - - syncOpts.values[0] = xSyncKey != null ? posToVal(scaleX.ori == 0 ? mouseLeft1 : mouseTop1, xSyncKey) : null; - syncOpts.values[1] = ySyncKey != null ? posToVal(scaleX.ori == 1 ? mouseLeft1 : mouseTop1, ySyncKey) : null; + let [xSyncKey, ySyncKey] = syncOpts.scales + + syncOpts.values[0] = + xSyncKey != null + ? posToVal( + scaleX.ori == 0 ? mouseLeft1 : mouseTop1, + xSyncKey + ) + : null + syncOpts.values[1] = + ySyncKey != null + ? posToVal( + scaleX.ori == 1 ? mouseLeft1 : mouseTop1, + ySyncKey + ) + : null } - pubSync(mousemove, self, mouseLeft1, mouseTop1, plotWidCss, plotHgtCss, idx); + pubSync( + mousemove, + self, + mouseLeft1, + mouseTop1, + plotWidCss, + plotHgtCss, + idx + ) } if (cursorFocus) { - let shouldPub = _pub && syncOpts.setSeries; - let p = focus.prox; + let shouldPub = _pub && syncOpts.setSeries + let p = focus.prox if (focusedSeries == null) { if (closestDist <= p) - setSeries(closestSeries, FOCUS_TRUE, true, shouldPub); - } - else { + setSeries(closestSeries, FOCUS_TRUE, true, shouldPub) + } else { if (closestDist > p) - setSeries(null, FOCUS_TRUE, true, shouldPub); + setSeries(null, FOCUS_TRUE, true, shouldPub) else if (closestSeries != focusedSeries) - setSeries(closestSeries, FOCUS_TRUE, true, shouldPub); + setSeries(closestSeries, FOCUS_TRUE, true, shouldPub) } } } if (shouldSetLegend) { - legend.idx = idx; - setLegend(); + legend.idx = idx + setLegend() } - _fire !== false && fire("setCursor"); + _fire !== false && fire('setCursor') } - let rect = null; + let rect = null Object.defineProperty(self, 'rect', { get() { - if (rect == null) - syncRect(false); + if (rect == null) syncRect(false) - return rect; - }, - }); + return rect + } + }) function syncRect(defer = false) { - if (defer) - rect = null; + if (defer) rect = null else { - rect = over.getBoundingClientRect(); - fire("syncRect", rect); + rect = over.getBoundingClientRect() + fire('syncRect', rect) } } function mouseMove(e, src, _l, _t, _w, _h, _i) { - if (cursor._lock) - return; + if (cursor._lock) return // Chrome on Windows has a bug which triggers a stray mousemove event after an initial mousedown event // when clicking into a plot as part of re-focusing the browser window. @@ -3069,83 +3518,78 @@ export default function uPlot(opts, data, then) { // However, on touch-only devices Chrome-based browsers trigger a 0-distance mousemove before mousedown // so we don't ignore it when mousedown has set the dragging flag if (dragging && e != null && e.movementX == 0 && e.movementY == 0) - return; + return - cacheMouse(e, src, _l, _t, _w, _h, _i, false, e != null); + cacheMouse(e, src, _l, _t, _w, _h, _i, false, e != null) - if (e != null) - updateCursor(null, true, true); - else - updateCursor(src, true, false); + if (e != null) updateCursor(null, true, true) + else updateCursor(src, true, false) } function cacheMouse(e, src, _l, _t, _w, _h, _i, initial, snap) { - if (rect == null) - syncRect(false); + if (rect == null) syncRect(false) - setCursorEvent(e); + setCursorEvent(e) if (e != null) { - _l = e.clientX - rect.left; - _t = e.clientY - rect.top; - } - else { + _l = e.clientX - rect.left + _t = e.clientY - rect.top + } else { if (_l < 0 || _t < 0) { - mouseLeft1 = -10; - mouseTop1 = -10; - return; + mouseLeft1 = -10 + mouseTop1 = -10 + return } - let [xKey, yKey] = syncOpts.scales; + let [xKey, yKey] = syncOpts.scales - let syncOptsSrc = src.cursor.sync; - let [xValSrc, yValSrc] = syncOptsSrc.values; - let [xKeySrc, yKeySrc] = syncOptsSrc.scales; - let [matchXKeys, matchYKeys] = syncOpts.match; + let syncOptsSrc = src.cursor.sync + let [xValSrc, yValSrc] = syncOptsSrc.values + let [xKeySrc, yKeySrc] = syncOptsSrc.scales + let [matchXKeys, matchYKeys] = syncOpts.match - let rotSrc = src.axes[0].side % 2 == 1; + let rotSrc = src.axes[0].side % 2 == 1 let xDim = scaleX.ori == 0 ? plotWidCss : plotHgtCss, yDim = scaleX.ori == 1 ? plotWidCss : plotHgtCss, _xDim = rotSrc ? _h : _w, _yDim = rotSrc ? _w : _h, _xPos = rotSrc ? _t : _l, - _yPos = rotSrc ? _l : _t; + _yPos = rotSrc ? _l : _t if (xKeySrc != null) - _l = matchXKeys(xKey, xKeySrc) ? getPos(xValSrc, scales[xKey], xDim, 0) : -10; - else - _l = xDim * (_xPos/_xDim); + _l = matchXKeys(xKey, xKeySrc) + ? getPos(xValSrc, scales[xKey], xDim, 0) + : -10 + else _l = xDim * (_xPos / _xDim) if (yKeySrc != null) - _t = matchYKeys(yKey, yKeySrc) ? getPos(yValSrc, scales[yKey], yDim, 0) : -10; - else - _t = yDim * (_yPos/_yDim); + _t = matchYKeys(yKey, yKeySrc) + ? getPos(yValSrc, scales[yKey], yDim, 0) + : -10 + else _t = yDim * (_yPos / _yDim) if (scaleX.ori == 1) { - let __l = _l; - _l = _t; - _t = __l; + let __l = _l + _l = _t + _t = __l } } if (snap) { - if (_l <= 1 || _l >= plotWidCss - 1) - _l = incrRound(_l, plotWidCss); + if (_l <= 1 || _l >= plotWidCss - 1) _l = incrRound(_l, plotWidCss) - if (_t <= 1 || _t >= plotHgtCss - 1) - _t = incrRound(_t, plotHgtCss); + if (_t <= 1 || _t >= plotHgtCss - 1) _t = incrRound(_t, plotHgtCss) } if (initial) { - rawMouseLeft0 = _l; - rawMouseTop0 = _t; + rawMouseLeft0 = _l + rawMouseTop0 = _t - [mouseLeft0, mouseTop0] = cursor.move(self, _l, _t); - } - else { - mouseLeft1 = _l; - mouseTop1 = _t; + ;[mouseLeft0, mouseTop0] = cursor.move(self, _l, _t) + } else { + mouseLeft1 = _l + mouseTop1 = _t } } @@ -3153,342 +3597,355 @@ export default function uPlot(opts, data, then) { width: 0, height: 0, left: 0, - top: 0, - }; + top: 0 + } function hideSelect() { - setSelect(_hideProps, false); + setSelect(_hideProps, false) } - let downSelectLeft; - let downSelectTop; - let downSelectWidth; - let downSelectHeight; + let downSelectLeft + let downSelectTop + let downSelectWidth + let downSelectHeight function mouseDown(e, src, _l, _t, _w, _h, _i) { - dragging = true; - dragX = dragY = drag._x = drag._y = false; + dragging = true + dragX = dragY = drag._x = drag._y = false - cacheMouse(e, src, _l, _t, _w, _h, _i, true, false); + cacheMouse(e, src, _l, _t, _w, _h, _i, true, false) if (e != null) { - onMouse(mouseup, doc, mouseUp, false); - pubSync(mousedown, self, mouseLeft0, mouseTop0, plotWidCss, plotHgtCss, null); + onMouse(mouseup, doc, mouseUp, false) + pubSync( + mousedown, + self, + mouseLeft0, + mouseTop0, + plotWidCss, + plotHgtCss, + null + ) } - let { left, top, width, height } = select; + let { left, top, width, height } = select - downSelectLeft = left; - downSelectTop = top; - downSelectWidth = width; - downSelectHeight = height; + downSelectLeft = left + downSelectTop = top + downSelectWidth = width + downSelectHeight = height - hideSelect(); + hideSelect() } function mouseUp(e, src, _l, _t, _w, _h, _i) { - dragging = drag._x = drag._y = false; + dragging = drag._x = drag._y = false - cacheMouse(e, src, _l, _t, _w, _h, _i, false, true); + cacheMouse(e, src, _l, _t, _w, _h, _i, false, true) - let { left, top, width, height } = select; + let { left, top, width, height } = select - let hasSelect = width > 0 || height > 0; - let chgSelect = ( - downSelectLeft != left || - downSelectTop != top || - downSelectWidth != width || + let hasSelect = width > 0 || height > 0 + let chgSelect = + downSelectLeft != left || + downSelectTop != top || + downSelectWidth != width || downSelectHeight != height - ); - hasSelect && chgSelect && setSelect(select); + hasSelect && chgSelect && setSelect(select) if (drag.setScale && hasSelect && chgSelect) { - // if (syncKey != null) { - // dragX = drag.x; - // dragY = drag.y; - // } + // if (syncKey != null) { + // dragX = drag.x; + // dragY = drag.y; + // } let xOff = left, xDim = width, yOff = top, - yDim = height; + yDim = height if (scaleX.ori == 1) { - xOff = top, - xDim = height, - yOff = left, - yDim = width; + ;(xOff = top), (xDim = height), (yOff = left), (yDim = width) } if (dragX) { - _setScale(xScaleKey, + _setScale( + xScaleKey, posToVal(xOff, xScaleKey), posToVal(xOff + xDim, xScaleKey) - ); + ) } if (dragY) { for (let k in scales) { - let sc = scales[k]; + let sc = scales[k] if (k != xScaleKey && sc.from == null && sc.min != inf) { - _setScale(k, + _setScale( + k, posToVal(yOff + yDim, k), posToVal(yOff, k) - ); + ) } } } - hideSelect(); - } - else if (cursor.lock) { - cursor._lock = !cursor._lock; - updateCursor(null, true, false); + hideSelect() + } else if (cursor.lock) { + cursor._lock = !cursor._lock + updateCursor(null, true, false) } if (e != null) { - offMouse(mouseup, doc, mouseUp); - pubSync(mouseup, self, mouseLeft1, mouseTop1, plotWidCss, plotHgtCss, null); + offMouse(mouseup, doc, mouseUp) + pubSync( + mouseup, + self, + mouseLeft1, + mouseTop1, + plotWidCss, + plotHgtCss, + null + ) } } function mouseLeave(e, src, _l, _t, _w, _h, _i) { - if (cursor._lock) - return; + if (cursor._lock) return - setCursorEvent(e); + setCursorEvent(e) - let _dragging = dragging; + let _dragging = dragging if (dragging) { // handle case when mousemove aren't fired all the way to edges by browser - let snapH = true; - let snapV = true; - let snapProx = 10; + let snapH = true + let snapV = true + let snapProx = 10 - let dragH, dragV; + let dragH, dragV if (scaleX.ori == 0) { - dragH = dragX; - dragV = dragY; - } - else { - dragH = dragY; - dragV = dragX; + dragH = dragX + dragV = dragY + } else { + dragH = dragY + dragV = dragX } if (dragH && dragV) { // maybe omni corner snap - snapH = mouseLeft1 <= snapProx || mouseLeft1 >= plotWidCss - snapProx; - snapV = mouseTop1 <= snapProx || mouseTop1 >= plotHgtCss - snapProx; + snapH = + mouseLeft1 <= snapProx || + mouseLeft1 >= plotWidCss - snapProx + snapV = + mouseTop1 <= snapProx || mouseTop1 >= plotHgtCss - snapProx } if (dragH && snapH) - mouseLeft1 = mouseLeft1 < mouseLeft0 ? 0 : plotWidCss; + mouseLeft1 = mouseLeft1 < mouseLeft0 ? 0 : plotWidCss if (dragV && snapV) - mouseTop1 = mouseTop1 < mouseTop0 ? 0 : plotHgtCss; + mouseTop1 = mouseTop1 < mouseTop0 ? 0 : plotHgtCss - updateCursor(null, true, true); + updateCursor(null, true, true) - dragging = false; + dragging = false } - mouseLeft1 = -10; - mouseTop1 = -10; + mouseLeft1 = -10 + mouseTop1 = -10 // passing a non-null timestamp to force sync/mousemove event - updateCursor(null, true, true); + updateCursor(null, true, true) - if (_dragging) - dragging = _dragging; + if (_dragging) dragging = _dragging } function dblClick(e, src, _l, _t, _w, _h, _i) { - if (cursor._lock) - return; + if (cursor._lock) return - setCursorEvent(e); + setCursorEvent(e) - autoScaleX(); + autoScaleX() - hideSelect(); + hideSelect() if (e != null) - pubSync(dblclick, self, mouseLeft1, mouseTop1, plotWidCss, plotHgtCss, null); + pubSync( + dblclick, + self, + mouseLeft1, + mouseTop1, + plotWidCss, + plotHgtCss, + null + ) } function syncPxRatio() { - axes.forEach(syncFontSize); - _setSize(self.width, self.height, true); + axes.forEach(syncFontSize) + _setSize(self.width, self.height, true) } - on(dppxchange, win, syncPxRatio); + on(dppxchange, win, syncPxRatio) // internal pub/sub - const events = {}; - - events.mousedown = mouseDown; - events.mousemove = mouseMove; - events.mouseup = mouseUp; - events.dblclick = dblClick; - events["setSeries"] = (e, src, idx, opts) => { - let seriesIdxMatcher = syncOpts.match[2]; - idx = seriesIdxMatcher(self, src, idx); - idx != -1 && setSeries(idx, opts, true, false); - }; + const events = {} + + events.mousedown = mouseDown + events.mousemove = mouseMove + events.mouseup = mouseUp + events.dblclick = dblClick + events['setSeries'] = (e, src, idx, opts) => { + let seriesIdxMatcher = syncOpts.match[2] + idx = seriesIdxMatcher(self, src, idx) + idx != -1 && setSeries(idx, opts, true, false) + } if (cursor.show) { - onMouse(mousedown, over, mouseDown); - onMouse(mousemove, over, mouseMove); - onMouse(mouseenter, over, e => { - setCursorEvent(e); - syncRect(false); - }); - onMouse(mouseleave, over, mouseLeave); + onMouse(mousedown, over, mouseDown) + onMouse(mousemove, over, mouseMove) + onMouse(mouseenter, over, (e) => { + setCursorEvent(e) + syncRect(false) + }) + onMouse(mouseleave, over, mouseLeave) - onMouse(dblclick, over, dblClick); + onMouse(dblclick, over, dblClick) - cursorPlots.add(self); + cursorPlots.add(self) - self.syncRect = syncRect; + self.syncRect = syncRect } // external on/off - const hooks = self.hooks = opts.hooks || {}; + const hooks = (self.hooks = opts.hooks || {}) function fire(evName, a1, a2) { - if (deferHooks) - hooksQueue.push([evName, a1, a2]); + if (deferHooks) hooksQueue.push([evName, a1, a2]) else { if (evName in hooks) { - hooks[evName].forEach(fn => { - fn.call(null, self, a1, a2); - }); + hooks[evName].forEach((fn) => { + fn.call(null, self, a1, a2) + }) } } } - (opts.plugins || []).forEach(p => { + ;(opts.plugins || []).forEach((p) => { for (let evName in p.hooks) - hooks[evName] = (hooks[evName] || []).concat(p.hooks[evName]); - }); - - const seriesIdxMatcher = (self, src, srcSeriesIdx) => srcSeriesIdx; - - const syncOpts = assign({ - key: null, - setSeries: false, - filters: { - pub: retTrue, - sub: retTrue, + hooks[evName] = (hooks[evName] || []).concat(p.hooks[evName]) + }) + + const seriesIdxMatcher = (self, src, srcSeriesIdx) => srcSeriesIdx + + const syncOpts = assign( + { + key: null, + setSeries: false, + filters: { + pub: retTrue, + sub: retTrue + }, + scales: [xScaleKey, series[1] ? series[1].scale : null], + match: [retEq, retEq, seriesIdxMatcher], + values: [null, null] }, - scales: [xScaleKey, series[1] ? series[1].scale : null], - match: [retEq, retEq, seriesIdxMatcher], - values: [null, null], - }, cursor.sync); + cursor.sync + ) - if (syncOpts.match.length == 2) - syncOpts.match.push(seriesIdxMatcher); + if (syncOpts.match.length == 2) syncOpts.match.push(seriesIdxMatcher) - cursor.sync = syncOpts; + cursor.sync = syncOpts - const syncKey = syncOpts.key; + const syncKey = syncOpts.key - const sync = _sync(syncKey); + const sync = _sync(syncKey) function pubSync(type, src, x, y, w, h, i) { if (syncOpts.filters.pub(type, src, x, y, w, h, i)) - sync.pub(type, src, x, y, w, h, i); + sync.pub(type, src, x, y, w, h, i) } - sync.sub(self); + sync.sub(self) function pub(type, src, x, y, w, h, i) { if (syncOpts.filters.sub(type, src, x, y, w, h, i)) - events[type](null, src, x, y, w, h, i); + events[type](null, src, x, y, w, h, i) } - self.pub = pub; + self.pub = pub function destroy() { - sync.unsub(self); - cursorPlots.delete(self); - mouseListeners.clear(); - off(dppxchange, win, syncPxRatio); - root.remove(); - FEAT_LEGEND && legendTable?.remove(); // in case mounted outside of root - fire("destroy"); + sync.unsub(self) + cursorPlots.delete(self) + mouseListeners.clear() + off(dppxchange, win, syncPxRatio) + root.remove() + FEAT_LEGEND && legendTable?.remove() // in case mounted outside of root + fire('destroy') } - self.destroy = destroy; + self.destroy = destroy function _init() { - fire("init", opts, data); + fire('init', opts, data) - setData(data || opts.data, false); + setData(data || opts.data, false) - if (pendScales[xScaleKey]) - setScale(xScaleKey, pendScales[xScaleKey]); - else - autoScaleX(); + if (pendScales[xScaleKey]) setScale(xScaleKey, pendScales[xScaleKey]) + else autoScaleX() - shouldSetSelect = select.show && (select.width > 0 || select.height > 0); - shouldSetCursor = shouldSetLegend = true; + shouldSetSelect = select.show && (select.width > 0 || select.height > 0) + shouldSetCursor = shouldSetLegend = true - _setSize(opts.width, opts.height); + _setSize(opts.width, opts.height) } - series.forEach(initSeries); + series.forEach(initSeries) - axes.forEach(initAxis); + axes.forEach(initAxis) if (then) { if (then instanceof HTMLElement) { - then.appendChild(root); - _init(); - } - else - then(self, _init); - } - else - _init(); + then.appendChild(root) + _init() + } else then(self, _init) + } else _init() - return self; + return self } -uPlot.assign = assign; -uPlot.fmtNum = fmtNum; -uPlot.rangeNum = rangeNum; -uPlot.rangeLog = rangeLog; -uPlot.rangeAsinh = rangeAsinh; -uPlot.orient = orient; -uPlot.pxRatio = pxRatio; +uPlot.assign = assign +uPlot.rangeNum = rangeNum +uPlot.rangeLog = rangeLog +uPlot.rangeAsinh = rangeAsinh +uPlot.orient = orient +uPlot.pxRatio = pxRatio if (FEAT_JOIN) { - uPlot.join = join; + uPlot.join = join } if (FEAT_TIME) { - uPlot.fmtDate = fmtDate; - uPlot.tzDate = tzDate; + uPlot.tzDate = tzDate } -uPlot.sync = _sync; +uPlot.sync = _sync if (FEAT_PATHS) { - uPlot.addGap = addGap; - uPlot.clipGaps = clipGaps; - - let paths = uPlot.paths = { - points, - }; - - FEAT_PATHS_LINEAR && (paths.linear = linear); - FEAT_PATHS_STEPPED && (paths.stepped = stepped); - FEAT_PATHS_BARS && (paths.bars = bars); - FEAT_PATHS_SPLINE && (paths.spline = spline); - FEAT_PATHS_SPLINE2 && (paths.spline2 = spline2); + uPlot.addGap = addGap + uPlot.clipGaps = clipGaps + + let paths = (uPlot.paths = { + points + }) + + FEAT_PATHS_LINEAR && (paths.linear = linear) + FEAT_PATHS_STEPPED && (paths.stepped = stepped) + FEAT_PATHS_BARS && (paths.bars = bars) + FEAT_PATHS_SPLINE && (paths.spline = spline) + FEAT_PATHS_SPLINE2 && (paths.spline2 = spline2) } diff --git a/src/utils.js b/src/utils.js index 7f49490a..84723732 100644 --- a/src/utils.js +++ b/src/utils.js @@ -1,4 +1,4 @@ -import { domEnv, nav } from './dom'; +export const browserLocale = new Intl.DateTimeFormat().resolvedOptions().locale // binary search for index of closest value export function closestIdx(num, arr, lo, hi) { @@ -257,10 +257,6 @@ function _rangeNum(_min, _max, cfg) { return [minLim, maxLim]; } -// alternative: https://stackoverflow.com/a/2254896 -const numFormatter = new Intl.NumberFormat(domEnv ? nav.language : 'en-US'); -export const fmtNum = val => numFormatter.format(val); - const M = Math; export const PI = M.PI; @@ -659,4 +655,4 @@ function isAsc(vals, samples = 100) { } return true; -} \ No newline at end of file +}