diff options
Diffstat (limited to 'web/gui/src/dashboard.js/charting/dygraph.js')
-rw-r--r-- | web/gui/src/dashboard.js/charting/dygraph.js | 1065 |
1 files changed, 0 insertions, 1065 deletions
diff --git a/web/gui/src/dashboard.js/charting/dygraph.js b/web/gui/src/dashboard.js/charting/dygraph.js deleted file mode 100644 index 4b44e7c4..00000000 --- a/web/gui/src/dashboard.js/charting/dygraph.js +++ /dev/null @@ -1,1065 +0,0 @@ -// dygraph - -// Codacy declarations -/* global smoothPlotter */ -/* global Dygraph */ - -NETDATA.dygraph = { - smooth: false -}; - -NETDATA.dygraphToolboxPanAndZoom = function (state, after, before) { - if (after < state.netdata_first) { - after = state.netdata_first; - } - - if (before > state.netdata_last) { - before = state.netdata_last; - } - - state.setMode('zoom'); - NETDATA.globalSelectionSync.stop(); - NETDATA.globalSelectionSync.delay(); - state.tmp.dygraph_user_action = true; - state.tmp.dygraph_force_zoom = true; - // state.log('toolboxPanAndZoom'); - state.updateChartPanOrZoom(after, before); - NETDATA.globalPanAndZoom.setMaster(state, after, before); -}; - -NETDATA.dygraphSetSelection = function (state, t) { - if (typeof state.tmp.dygraph_instance !== 'undefined') { - let r = state.calculateRowForTime(t); - if (r !== -1) { - state.tmp.dygraph_instance.setSelection(r); - return true; - } else { - state.tmp.dygraph_instance.clearSelection(); - state.legendShowUndefined(); - } - } - - return false; -}; - -NETDATA.dygraphClearSelection = function (state) { - if (typeof state.tmp.dygraph_instance !== 'undefined') { - state.tmp.dygraph_instance.clearSelection(); - } - return true; -}; - -NETDATA.dygraphSmoothInitialize = function (callback) { - $.ajax({ - url: NETDATA.dygraph_smooth_js, - cache: true, - dataType: "script", - xhrFields: {withCredentials: true} // required for the cookie - }) - .done(function () { - NETDATA.dygraph.smooth = true; - smoothPlotter.smoothing = 0.3; - }) - .fail(function () { - NETDATA.dygraph.smooth = false; - }) - .always(function () { - if (typeof callback === "function") { - return callback(); - } - }); -}; - -NETDATA.dygraphInitialize = function (callback) { - if (typeof netdataNoDygraphs === 'undefined' || !netdataNoDygraphs) { - $.ajax({ - url: NETDATA.dygraph_js, - cache: true, - dataType: "script", - xhrFields: {withCredentials: true} // required for the cookie - }) - .done(function () { - NETDATA.registerChartLibrary('dygraph', NETDATA.dygraph_js); - }) - .fail(function () { - NETDATA.chartLibraries.dygraph.enabled = false; - NETDATA.error(100, NETDATA.dygraph_js); - }) - .always(function () { - if (NETDATA.chartLibraries.dygraph.enabled && NETDATA.options.current.smooth_plot) { - NETDATA.dygraphSmoothInitialize(callback); - } else if (typeof callback === "function") { - return callback(); - } - }); - } else { - NETDATA.chartLibraries.dygraph.enabled = false; - if (typeof callback === "function") { - return callback(); - } - } -}; - -NETDATA.dygraphChartUpdate = function (state, data) { - let dygraph = state.tmp.dygraph_instance; - - if (typeof dygraph === 'undefined') { - return NETDATA.dygraphChartCreate(state, data); - } - - // when the chart is not visible, and hidden - // if there is a window resize, dygraph detects - // its element size as 0x0. - // this will make it re-appear properly - - if (state.tm.last_unhidden > state.tmp.dygraph_last_rendered) { - dygraph.resize(); - } - - let options = { - file: data.result.data, - colors: state.chartColors(), - labels: data.result.labels, - //labelsDivWidth: state.chartWidth() - 70, - includeZero: state.tmp.dygraph_include_zero, - visibility: state.dimensions_visibility.selected2BooleanArray(state.data.dimension_names) - }; - - if (state.tmp.dygraph_chart_type === 'stacked') { - if (options.includeZero && state.dimensions_visibility.countSelected() < options.visibility.length) { - options.includeZero = 0; - } - } - - if (!NETDATA.chartLibraries.dygraph.isSparkline(state)) { - options.ylabel = state.units_current; // (state.units_desired === 'auto')?"":state.units_current; - } - - if (state.tmp.dygraph_force_zoom) { - if (NETDATA.options.debug.dygraph || state.debug) { - state.log('dygraphChartUpdate() forced zoom update'); - } - - options.dateWindow = (state.requested_padding !== null) ? [state.view_after, state.view_before] : null; - //options.isZoomedIgnoreProgrammaticZoom = true; - state.tmp.dygraph_force_zoom = false; - } else if (state.current.name !== 'auto') { - if (NETDATA.options.debug.dygraph || state.debug) { - state.log('dygraphChartUpdate() loose update'); - } - } else { - if (NETDATA.options.debug.dygraph || state.debug) { - state.log('dygraphChartUpdate() strict update'); - } - - options.dateWindow = (state.requested_padding !== null) ? [state.view_after, state.view_before] : null; - //options.isZoomedIgnoreProgrammaticZoom = true; - } - - options.valueRange = state.tmp.dygraph_options.valueRange; - - let oldMax = null, oldMin = null; - if (state.tmp.__commonMin !== null) { - state.data.min = state.tmp.dygraph_instance.axes_[0].extremeRange[0]; - oldMin = options.valueRange[0] = NETDATA.commonMin.get(state); - } - if (state.tmp.__commonMax !== null) { - state.data.max = state.tmp.dygraph_instance.axes_[0].extremeRange[1]; - oldMax = options.valueRange[1] = NETDATA.commonMax.get(state); - } - - if (state.tmp.dygraph_smooth_eligible) { - if ((NETDATA.options.current.smooth_plot && state.tmp.dygraph_options.plotter !== smoothPlotter) - || (NETDATA.options.current.smooth_plot === false && state.tmp.dygraph_options.plotter === smoothPlotter)) { - NETDATA.dygraphChartCreate(state, data); - return; - } - } - - if (netdataSnapshotData !== null && NETDATA.globalPanAndZoom.isActive() && NETDATA.globalPanAndZoom.isMaster(state) === false) { - // pan and zoom on snapshots - options.dateWindow = [NETDATA.globalPanAndZoom.force_after_ms, NETDATA.globalPanAndZoom.force_before_ms]; - //options.isZoomedIgnoreProgrammaticZoom = true; - } - - if (NETDATA.chartLibraries.dygraph.isLogScale(state)) { - if (Array.isArray(options.valueRange) && options.valueRange[0] <= 0) { - options.valueRange[0] = null; - } - } - - dygraph.updateOptions(options); - - let redraw = false; - if (oldMin !== null && oldMin > state.tmp.dygraph_instance.axes_[0].extremeRange[0]) { - state.data.min = state.tmp.dygraph_instance.axes_[0].extremeRange[0]; - options.valueRange[0] = NETDATA.commonMin.get(state); - redraw = true; - } - if (oldMax !== null && oldMax < state.tmp.dygraph_instance.axes_[0].extremeRange[1]) { - state.data.max = state.tmp.dygraph_instance.axes_[0].extremeRange[1]; - options.valueRange[1] = NETDATA.commonMax.get(state); - redraw = true; - } - - if (redraw) { - // state.log('forcing redraw to adapt to common- min/max'); - dygraph.updateOptions(options); - } - - state.tmp.dygraph_last_rendered = Date.now(); - return true; -}; - -NETDATA.dygraphChartCreate = function (state, data) { - if (NETDATA.options.debug.dygraph || state.debug) { - state.log('dygraphChartCreate()'); - } - - state.tmp.dygraph_chart_type = NETDATA.dataAttribute(state.element, 'dygraph-type', state.chart.chart_type); - if (state.tmp.dygraph_chart_type === 'stacked' && data.dimensions === 1) { - state.tmp.dygraph_chart_type = 'area'; - } - if (state.tmp.dygraph_chart_type === 'stacked' && NETDATA.chartLibraries.dygraph.isLogScale(state)) { - state.tmp.dygraph_chart_type = 'area'; - } - - let highlightCircleSize = NETDATA.chartLibraries.dygraph.isSparkline(state) ? 3 : 4; - - let smooth = NETDATA.dygraph.smooth - ? (NETDATA.dataAttributeBoolean(state.element, 'dygraph-smooth', (state.tmp.dygraph_chart_type === 'line' && NETDATA.chartLibraries.dygraph.isSparkline(state) === false))) - : false; - - state.tmp.dygraph_include_zero = NETDATA.dataAttribute(state.element, 'dygraph-includezero', (state.tmp.dygraph_chart_type === 'stacked')); - let drawAxis = NETDATA.dataAttributeBoolean(state.element, 'dygraph-drawaxis', true); - - state.tmp.dygraph_options = { - colors: NETDATA.dataAttribute(state.element, 'dygraph-colors', state.chartColors()), - - // leave a few pixels empty on the right of the chart - rightGap: NETDATA.dataAttribute(state.element, 'dygraph-rightgap', 5), - showRangeSelector: NETDATA.dataAttributeBoolean(state.element, 'dygraph-showrangeselector', false), - showRoller: NETDATA.dataAttributeBoolean(state.element, 'dygraph-showroller', false), - title: NETDATA.dataAttribute(state.element, 'dygraph-title', state.title), - titleHeight: NETDATA.dataAttribute(state.element, 'dygraph-titleheight', 19), - legend: NETDATA.dataAttribute(state.element, 'dygraph-legend', 'always'), // we need this to get selection events - labels: data.result.labels, - labelsDiv: NETDATA.dataAttribute(state.element, 'dygraph-labelsdiv', state.element_legend_childs.hidden), - //labelsDivStyles: NETDATA.dataAttribute(state.element, 'dygraph-labelsdivstyles', { 'fontSize':'1px' }), - //labelsDivWidth: NETDATA.dataAttribute(state.element, 'dygraph-labelsdivwidth', state.chartWidth() - 70), - labelsSeparateLines: NETDATA.dataAttributeBoolean(state.element, 'dygraph-labelsseparatelines', true), - labelsShowZeroValues: NETDATA.chartLibraries.dygraph.isLogScale(state) ? false : NETDATA.dataAttributeBoolean(state.element, 'dygraph-labelsshowzerovalues', true), - labelsKMB: false, - labelsKMG2: false, - showLabelsOnHighlight: NETDATA.dataAttributeBoolean(state.element, 'dygraph-showlabelsonhighlight', true), - hideOverlayOnMouseOut: NETDATA.dataAttributeBoolean(state.element, 'dygraph-hideoverlayonmouseout', true), - includeZero: state.tmp.dygraph_include_zero, - xRangePad: NETDATA.dataAttribute(state.element, 'dygraph-xrangepad', 0), - yRangePad: NETDATA.dataAttribute(state.element, 'dygraph-yrangepad', 1), - valueRange: NETDATA.dataAttribute(state.element, 'dygraph-valuerange', [null, null]), - ylabel: state.units_current, // (state.units_desired === 'auto')?"":state.units_current, - yLabelWidth: NETDATA.dataAttribute(state.element, 'dygraph-ylabelwidth', 12), - - // the function to plot the chart - plotter: null, - - // The width of the lines connecting data points. - // This can be used to increase the contrast or some graphs. - strokeWidth: NETDATA.dataAttribute(state.element, 'dygraph-strokewidth', ((state.tmp.dygraph_chart_type === 'stacked') ? 0.1 : ((smooth === true) ? 1.5 : 0.7))), - strokePattern: NETDATA.dataAttribute(state.element, 'dygraph-strokepattern', undefined), - - // The size of the dot to draw on each point in pixels (see drawPoints). - // A dot is always drawn when a point is "isolated", - // i.e. there is a missing point on either side of it. - // This also controls the size of those dots. - drawPoints: NETDATA.dataAttributeBoolean(state.element, 'dygraph-drawpoints', false), - - // Draw points at the edges of gaps in the data. - // This improves visibility of small data segments or other data irregularities. - drawGapEdgePoints: NETDATA.dataAttributeBoolean(state.element, 'dygraph-drawgapedgepoints', true), - connectSeparatedPoints: NETDATA.chartLibraries.dygraph.isLogScale(state) ? false : NETDATA.dataAttributeBoolean(state.element, 'dygraph-connectseparatedpoints', false), - pointSize: NETDATA.dataAttribute(state.element, 'dygraph-pointsize', 1), - - // enabling this makes the chart with little square lines - stepPlot: NETDATA.dataAttributeBoolean(state.element, 'dygraph-stepplot', false), - - // Draw a border around graph lines to make crossing lines more easily - // distinguishable. Useful for graphs with many lines. - strokeBorderColor: NETDATA.dataAttribute(state.element, 'dygraph-strokebordercolor', NETDATA.themes.current.background), - strokeBorderWidth: NETDATA.dataAttribute(state.element, 'dygraph-strokeborderwidth', (state.tmp.dygraph_chart_type === 'stacked') ? 0.0 : 0.0), - fillGraph: NETDATA.dataAttribute(state.element, 'dygraph-fillgraph', (state.tmp.dygraph_chart_type === 'area' || state.tmp.dygraph_chart_type === 'stacked')), - fillAlpha: NETDATA.dataAttribute(state.element, 'dygraph-fillalpha', - ((state.tmp.dygraph_chart_type === 'stacked') - ? NETDATA.options.current.color_fill_opacity_stacked - : NETDATA.options.current.color_fill_opacity_area) - ), - stackedGraph: NETDATA.dataAttribute(state.element, 'dygraph-stackedgraph', (state.tmp.dygraph_chart_type === 'stacked')), - stackedGraphNaNFill: NETDATA.dataAttribute(state.element, 'dygraph-stackedgraphnanfill', 'none'), - drawAxis: drawAxis, - axisLabelFontSize: NETDATA.dataAttribute(state.element, 'dygraph-axislabelfontsize', 10), - axisLineColor: NETDATA.dataAttribute(state.element, 'dygraph-axislinecolor', NETDATA.themes.current.axis), - axisLineWidth: NETDATA.dataAttribute(state.element, 'dygraph-axislinewidth', 1.0), - drawGrid: NETDATA.dataAttributeBoolean(state.element, 'dygraph-drawgrid', true), - gridLinePattern: NETDATA.dataAttribute(state.element, 'dygraph-gridlinepattern', null), - gridLineWidth: NETDATA.dataAttribute(state.element, 'dygraph-gridlinewidth', 1.0), - gridLineColor: NETDATA.dataAttribute(state.element, 'dygraph-gridlinecolor', NETDATA.themes.current.grid), - maxNumberWidth: NETDATA.dataAttribute(state.element, 'dygraph-maxnumberwidth', 8), - sigFigs: NETDATA.dataAttribute(state.element, 'dygraph-sigfigs', null), - digitsAfterDecimal: NETDATA.dataAttribute(state.element, 'dygraph-digitsafterdecimal', 2), - valueFormatter: NETDATA.dataAttribute(state.element, 'dygraph-valueformatter', undefined), - highlightCircleSize: NETDATA.dataAttribute(state.element, 'dygraph-highlightcirclesize', highlightCircleSize), - highlightSeriesOpts: NETDATA.dataAttribute(state.element, 'dygraph-highlightseriesopts', null), // TOO SLOW: { strokeWidth: 1.5 }, - highlightSeriesBackgroundAlpha: NETDATA.dataAttribute(state.element, 'dygraph-highlightseriesbackgroundalpha', null), // TOO SLOW: (state.tmp.dygraph_chart_type === 'stacked')?0.7:0.5, - pointClickCallback: NETDATA.dataAttribute(state.element, 'dygraph-pointclickcallback', undefined), - visibility: state.dimensions_visibility.selected2BooleanArray(state.data.dimension_names), - logscale: NETDATA.chartLibraries.dygraph.isLogScale(state) ? 'y' : undefined, - - // Expects a string in the format "<series name>: <style>" where each series is separated by a | - perSeriesStyle: NETDATA.dataAttribute(state.element, 'dygraph-per-series-style', ''), - - axes: { - x: { - pixelsPerLabel: NETDATA.dataAttribute(state.element, 'dygraph-xpixelsperlabel', 50), - ticker: Dygraph.dateTicker, - axisLabelWidth: NETDATA.dataAttribute(state.element, 'dygraph-xaxislabelwidth', 60), - drawAxis: NETDATA.dataAttributeBoolean(state.element, 'dygraph-drawxaxis', drawAxis), - axisLabelFormatter: function (d, gran) { - void(gran); - return NETDATA.dateTime.xAxisTimeString(d); - } - }, - y: { - logscale: NETDATA.chartLibraries.dygraph.isLogScale(state) ? true : undefined, - pixelsPerLabel: NETDATA.dataAttribute(state.element, 'dygraph-ypixelsperlabel', 15), - axisLabelWidth: NETDATA.dataAttribute(state.element, 'dygraph-yaxislabelwidth', 50), - drawAxis: NETDATA.dataAttributeBoolean(state.element, 'dygraph-drawyaxis', drawAxis), - axisLabelFormatter: function (y) { - - // unfortunately, we have to call this every single time - state.legendFormatValueDecimalsFromMinMax( - this.axes_[0].extremeRange[0], - this.axes_[0].extremeRange[1] - ); - - let old_units = this.user_attrs_.ylabel; - let v = state.legendFormatValue(y); - let new_units = state.units_current; - - if (state.units_desired === 'auto' && typeof old_units !== 'undefined' && new_units !== old_units && !NETDATA.chartLibraries.dygraph.isSparkline(state)) { - // console.log(this); - // state.log('units discrepancy: old = ' + old_units + ', new = ' + new_units); - let len = this.plugins_.length; - while (len--) { - // console.log(this.plugins_[len]); - if (typeof this.plugins_[len].plugin.ylabel_div_ !== 'undefined' - && this.plugins_[len].plugin.ylabel_div_ !== null - && typeof this.plugins_[len].plugin.ylabel_div_.children !== 'undefined' - && this.plugins_[len].plugin.ylabel_div_.children !== null - && typeof this.plugins_[len].plugin.ylabel_div_.children[0].children !== 'undefined' - && this.plugins_[len].plugin.ylabel_div_.children[0].children !== null - ) { - this.plugins_[len].plugin.ylabel_div_.children[0].children[0].innerHTML = new_units; - this.user_attrs_.ylabel = new_units; - break; - } - } - - if (len < 0) { - state.log('units discrepancy, but cannot find dygraphs div to change: old = ' + old_units + ', new = ' + new_units); - } - } - - return v; - } - } - }, - legendFormatter: function (data) { - if (state.tmp.dygraph_mouse_down) { - return; - } - - let elements = state.element_legend_childs; - - // if the hidden div is not there - // we are not managing the legend - if (elements.hidden === null) { - return; - } - - if (typeof data.x !== 'undefined') { - state.legendSetDate(data.x); - let i = data.series.length; - while (i--) { - let series = data.series[i]; - if (series.isVisible) { - state.legendSetLabelValue(series.label, series.y); - } else { - state.legendSetLabelValue(series.label, null); - } - } - } - - return ''; - }, - drawCallback: function (dygraph, is_initial) { - - // the user has panned the chart and this is called to re-draw the chart - // 1. refresh this chart by adding data to it - // 2. notify all the other charts about the update they need - - // to prevent an infinite loop (feedback), we use - // state.tmp.dygraph_user_action - // - when true, this is initiated by a user - // - when false, this is feedback - - if (state.current.name !== 'auto' && state.tmp.dygraph_user_action) { - state.tmp.dygraph_user_action = false; - - let x_range = dygraph.xAxisRange(); - let after = Math.round(x_range[0]); - let before = Math.round(x_range[1]); - - if (NETDATA.options.debug.dygraph) { - state.log('dygraphDrawCallback(dygraph, ' + is_initial + '): mode ' + state.current.name + ' ' + (after / 1000).toString() + ' - ' + (before / 1000).toString()); - //console.log(state); - } - - if (before <= state.netdata_last && after >= state.netdata_first) { - // update only when we are within the data limits - state.updateChartPanOrZoom(after, before); - } - } - }, - zoomCallback: function (minDate, maxDate, yRanges) { - - // the user has selected a range on the chart - // 1. refresh this chart by adding data to it - // 2. notify all the other charts about the update they need - - void(yRanges); - - if (NETDATA.options.debug.dygraph) { - state.log('dygraphZoomCallback(): ' + state.current.name); - } - - NETDATA.globalSelectionSync.stop(); - NETDATA.globalSelectionSync.delay(); - state.setMode('zoom'); - - // refresh it to the greatest possible zoom level - state.tmp.dygraph_user_action = true; - state.tmp.dygraph_force_zoom = true; - state.updateChartPanOrZoom(minDate, maxDate); - }, - highlightCallback: function (event, x, points, row, seriesName) { - void(seriesName); - - state.pauseChart(); - - // there is a bug in dygraph when the chart is zoomed enough - // the time it thinks is selected is wrong - // here we calculate the time t based on the row number selected - // which is ok - // let t = state.data_after + row * state.data_update_every; - // console.log('row = ' + row + ', x = ' + x + ', t = ' + t + ' ' + ((t === x)?'SAME':(Math.abs(x-t)<=state.data_update_every)?'SIMILAR':'DIFFERENT') + ', rows in db: ' + state.data_points + ' visible(x) = ' + state.timeIsVisible(x) + ' visible(t) = ' + state.timeIsVisible(t) + ' r(x) = ' + state.calculateRowForTime(x) + ' r(t) = ' + state.calculateRowForTime(t) + ' range: ' + state.data_after + ' - ' + state.data_before + ' real: ' + state.data.after + ' - ' + state.data.before + ' every: ' + state.data_update_every); - - if (state.tmp.dygraph_mouse_down !== true) { - NETDATA.globalSelectionSync.sync(state, x); - } - - // fix legend zIndex using the internal structures of dygraph legend module - // this works, but it is a hack! - // state.tmp.dygraph_instance.plugins_[0].plugin.legend_div_.style.zIndex = 10000; - }, - unhighlightCallback: function (event) { - void(event); - - if (state.tmp.dygraph_mouse_down) { - return; - } - - if (NETDATA.options.debug.dygraph || state.debug) { - state.log('dygraphUnhighlightCallback()'); - } - - state.unpauseChart(); - NETDATA.globalSelectionSync.stop(); - }, - underlayCallback: function (canvas, area, g) { - // the chart is about to be drawn - - // update history_tip_element - if (state.tmp.dygraph_history_tip_element) { - const xHookRightSide = g.toDomXCoord(state.netdata_first); - if (xHookRightSide > area.x) { - state.tmp.dygraph_history_tip_element_displayed = true; - // group the styles for possible better performance - state.tmp.dygraph_history_tip_element.setAttribute( - 'style', - `display: block; left: ${area.x}px; right: calc(100% - ${xHookRightSide}px);` - ) - } else { - if (state.tmp.dygraph_history_tip_element_displayed) { - // additional check just for performance - // don't update the DOM when it's not needed - state.tmp.dygraph_history_tip_element.style.display = 'none'; - state.tmp.dygraph_history_tip_element_displayed = false; - } - } - } - - // this function renders global highlighted time-frame - - if (NETDATA.globalChartUnderlay.isActive()) { - let after = NETDATA.globalChartUnderlay.after; - let before = NETDATA.globalChartUnderlay.before; - - if (after < state.view_after) { - after = state.view_after; - } - - if (before > state.view_before) { - before = state.view_before; - } - - if (after < before) { - let bottom_left = g.toDomCoords(after, -20); - let top_right = g.toDomCoords(before, +20); - - let left = bottom_left[0]; - let right = top_right[0]; - - canvas.fillStyle = NETDATA.themes.current.highlight; - canvas.fillRect(left, area.y, right - left, area.h); - } - } - }, - interactionModel: { - mousedown: function (event, dygraph, context) { - if (NETDATA.options.debug.dygraph || state.debug) { - state.log('interactionModel.mousedown()'); - } - - state.tmp.dygraph_user_action = true; - - if (NETDATA.options.debug.dygraph) { - state.log('dygraphMouseDown()'); - } - - // Right-click should not initiate anything. - if (event.button && event.button === 2) { - return; - } - - NETDATA.globalSelectionSync.stop(); - NETDATA.globalSelectionSync.delay(); - - state.tmp.dygraph_mouse_down = true; - context.initializeMouseDown(event, dygraph, context); - - //console.log(event); - if (event.button && event.button === 1) { - if (event.shiftKey) { - //console.log('middle mouse button dragging (PAN)'); - - state.setMode('pan'); - // NETDATA.globalSelectionSync.delay(); - state.tmp.dygraph_highlight_after = null; - Dygraph.startPan(event, dygraph, context); - } else if (event.altKey || event.ctrlKey || event.metaKey) { - //console.log('middle mouse button highlight'); - - if (!(event.offsetX && event.offsetY)) { - event.offsetX = event.layerX - event.target.offsetLeft; - event.offsetY = event.layerY - event.target.offsetTop; - } - state.tmp.dygraph_highlight_after = dygraph.toDataXCoord(event.offsetX); - Dygraph.startZoom(event, dygraph, context); - } else { - //console.log('middle mouse button selection for zoom (ZOOM)'); - - state.setMode('zoom'); - // NETDATA.globalSelectionSync.delay(); - state.tmp.dygraph_highlight_after = null; - Dygraph.startZoom(event, dygraph, context); - } - } else { - if (event.shiftKey) { - //console.log('left mouse button selection for zoom (ZOOM)'); - - state.setMode('zoom'); - // NETDATA.globalSelectionSync.delay(); - state.tmp.dygraph_highlight_after = null; - Dygraph.startZoom(event, dygraph, context); - } else if (event.altKey || event.ctrlKey || event.metaKey) { - //console.log('left mouse button highlight'); - - if (!(event.offsetX && event.offsetY)) { - event.offsetX = event.layerX - event.target.offsetLeft; - event.offsetY = event.layerY - event.target.offsetTop; - } - state.tmp.dygraph_highlight_after = dygraph.toDataXCoord(event.offsetX); - Dygraph.startZoom(event, dygraph, context); - } else { - //console.log('left mouse button dragging (PAN)'); - - state.setMode('pan'); - // NETDATA.globalSelectionSync.delay(); - state.tmp.dygraph_highlight_after = null; - Dygraph.startPan(event, dygraph, context); - } - } - }, - mousemove: function (event, dygraph, context) { - if (NETDATA.options.debug.dygraph || state.debug) { - state.log('interactionModel.mousemove()'); - } - - if (state.tmp.dygraph_highlight_after !== null) { - //console.log('highlight selection...'); - - NETDATA.globalSelectionSync.stop(); - NETDATA.globalSelectionSync.delay(); - - state.tmp.dygraph_user_action = true; - Dygraph.moveZoom(event, dygraph, context); - event.preventDefault(); - } else if (context.isPanning) { - //console.log('panning...'); - - NETDATA.globalSelectionSync.stop(); - NETDATA.globalSelectionSync.delay(); - - state.tmp.dygraph_user_action = true; - //NETDATA.globalSelectionSync.stop(); - //NETDATA.globalSelectionSync.delay(); - state.setMode('pan'); - context.is2DPan = false; - Dygraph.movePan(event, dygraph, context); - } else if (context.isZooming) { - //console.log('zooming...'); - - NETDATA.globalSelectionSync.stop(); - NETDATA.globalSelectionSync.delay(); - - state.tmp.dygraph_user_action = true; - //NETDATA.globalSelectionSync.stop(); - //NETDATA.globalSelectionSync.delay(); - state.setMode('zoom'); - Dygraph.moveZoom(event, dygraph, context); - } - }, - mouseup: function (event, dygraph, context) { - state.tmp.dygraph_mouse_down = false; - - if (NETDATA.options.debug.dygraph || state.debug) { - state.log('interactionModel.mouseup()'); - } - - if (state.tmp.dygraph_highlight_after !== null) { - //console.log('done highlight selection'); - - NETDATA.globalSelectionSync.stop(); - NETDATA.globalSelectionSync.delay(); - - if (!(event.offsetX && event.offsetY)) { - event.offsetX = event.layerX - event.target.offsetLeft; - event.offsetY = event.layerY - event.target.offsetTop; - } - - NETDATA.globalChartUnderlay.set(state - , state.tmp.dygraph_highlight_after - , dygraph.toDataXCoord(event.offsetX) - , state.view_after - , state.view_before - ); - - state.tmp.dygraph_highlight_after = null; - - context.isZooming = false; - dygraph.clearZoomRect_(); - dygraph.drawGraph_(false); - - // refresh all the charts immediately - NETDATA.options.auto_refresher_stop_until = 0; - } else if (context.isPanning) { - //console.log('done panning'); - - NETDATA.globalSelectionSync.stop(); - NETDATA.globalSelectionSync.delay(); - - state.tmp.dygraph_user_action = true; - Dygraph.endPan(event, dygraph, context); - - // refresh all the charts immediately - NETDATA.options.auto_refresher_stop_until = 0; - } else if (context.isZooming) { - //console.log('done zomming'); - - NETDATA.globalSelectionSync.stop(); - NETDATA.globalSelectionSync.delay(); - - state.tmp.dygraph_user_action = true; - Dygraph.endZoom(event, dygraph, context); - - // refresh all the charts immediately - NETDATA.options.auto_refresher_stop_until = 0; - } - }, - click: function (event, dygraph, context) { - void(dygraph); - void(context); - - if (NETDATA.options.debug.dygraph || state.debug) { - state.log('interactionModel.click()'); - } - - event.preventDefault(); - }, - dblclick: function (event, dygraph, context) { - void(event); - void(dygraph); - void(context); - - if (NETDATA.options.debug.dygraph || state.debug) { - state.log('interactionModel.dblclick()'); - } - NETDATA.resetAllCharts(state); - }, - wheel: function (event, dygraph, context) { - void(context); - - if (NETDATA.options.debug.dygraph || state.debug) { - state.log('interactionModel.wheel()'); - } - - // Take the offset of a mouse event on the dygraph canvas and - // convert it to a pair of percentages from the bottom left. - // (Not top left, bottom is where the lower value is.) - function offsetToPercentage(g, offsetX, offsetY) { - // This is calculating the pixel offset of the leftmost date. - let xOffset = g.toDomCoords(g.xAxisRange()[0], null)[0]; - let yar0 = g.yAxisRange(0); - - // This is calculating the pixel of the highest value. (Top pixel) - let yOffset = g.toDomCoords(null, yar0[1])[1]; - - // x y w and h are relative to the corner of the drawing area, - // so that the upper corner of the drawing area is (0, 0). - let x = offsetX - xOffset; - let y = offsetY - yOffset; - - // This is computing the rightmost pixel, effectively defining the - // width. - let w = g.toDomCoords(g.xAxisRange()[1], null)[0] - xOffset; - - // This is computing the lowest pixel, effectively defining the height. - let h = g.toDomCoords(null, yar0[0])[1] - yOffset; - - // Percentage from the left. - let xPct = w === 0 ? 0 : (x / w); - // Percentage from the top. - let yPct = h === 0 ? 0 : (y / h); - - // The (1-) part below changes it from "% distance down from the top" - // to "% distance up from the bottom". - return [xPct, (1 - yPct)]; - } - - // Adjusts [x, y] toward each other by zoomInPercentage% - // Split it so the left/bottom axis gets xBias/yBias of that change and - // tight/top gets (1-xBias)/(1-yBias) of that change. - // - // If a bias is missing it splits it down the middle. - function zoomRange(g, zoomInPercentage, xBias, yBias) { - xBias = xBias || 0.5; - yBias = yBias || 0.5; - - function adjustAxis(axis, zoomInPercentage, bias) { - let delta = axis[1] - axis[0]; - let increment = delta * zoomInPercentage; - let foo = [increment * bias, increment * (1 - bias)]; - - return [axis[0] + foo[0], axis[1] - foo[1]]; - } - - let yAxes = g.yAxisRanges(); - let newYAxes = []; - for (let i = 0; i < yAxes.length; i++) { - newYAxes[i] = adjustAxis(yAxes[i], zoomInPercentage, yBias); - } - - return adjustAxis(g.xAxisRange(), zoomInPercentage, xBias); - } - - if (event.altKey || event.shiftKey) { - state.tmp.dygraph_user_action = true; - - NETDATA.globalSelectionSync.stop(); - NETDATA.globalSelectionSync.delay(); - - // http://dygraphs.com/gallery/interaction-api.js - let normal_def; - if (typeof event.wheelDelta === 'number' && !isNaN(event.wheelDelta)) - // chrome - { - normal_def = event.wheelDelta / 40; - } else - // firefox - { - normal_def = event.deltaY * -1.2; - } - - let normal = (event.detail) ? event.detail * -1 : normal_def; - let percentage = normal / 50; - - if (!(event.offsetX && event.offsetY)) { - event.offsetX = event.layerX - event.target.offsetLeft; - event.offsetY = event.layerY - event.target.offsetTop; - } - - let percentages = offsetToPercentage(dygraph, event.offsetX, event.offsetY); - let xPct = percentages[0]; - let yPct = percentages[1]; - - let new_x_range = zoomRange(dygraph, percentage, xPct, yPct); - let after = new_x_range[0]; - let before = new_x_range[1]; - - let first = state.netdata_first + state.data_update_every; - let last = state.netdata_last + state.data_update_every; - - if (before > last) { - after -= (before - last); - before = last; - } - if (after < first) { - after = first; - } - - state.setMode('zoom'); - state.updateChartPanOrZoom(after, before, function () { - dygraph.updateOptions({dateWindow: [after, before]}); - }); - - event.preventDefault(); - } - }, - touchstart: function (event, dygraph, context) { - state.tmp.dygraph_mouse_down = true; - - if (NETDATA.options.debug.dygraph || state.debug) { - state.log('interactionModel.touchstart()'); - } - - state.tmp.dygraph_user_action = true; - state.setMode('zoom'); - state.pauseChart(); - - NETDATA.globalSelectionSync.stop(); - NETDATA.globalSelectionSync.delay(); - - Dygraph.defaultInteractionModel.touchstart(event, dygraph, context); - - // we overwrite the touch directions at the end, to overwrite - // the internal default of dygraph - context.touchDirections = {x: true, y: false}; - - state.dygraph_last_touch_start = Date.now(); - state.dygraph_last_touch_move = 0; - - if (typeof event.touches[0].pageX === 'number') { - state.dygraph_last_touch_page_x = event.touches[0].pageX; - } else { - state.dygraph_last_touch_page_x = 0; - } - }, - touchmove: function (event, dygraph, context) { - if (NETDATA.options.debug.dygraph || state.debug) { - state.log('interactionModel.touchmove()'); - } - - NETDATA.globalSelectionSync.stop(); - NETDATA.globalSelectionSync.delay(); - - state.tmp.dygraph_user_action = true; - Dygraph.defaultInteractionModel.touchmove(event, dygraph, context); - - state.dygraph_last_touch_move = Date.now(); - }, - touchend: function (event, dygraph, context) { - state.tmp.dygraph_mouse_down = false; - - if (NETDATA.options.debug.dygraph || state.debug) { - state.log('interactionModel.touchend()'); - } - - NETDATA.globalSelectionSync.stop(); - NETDATA.globalSelectionSync.delay(); - - state.tmp.dygraph_user_action = true; - Dygraph.defaultInteractionModel.touchend(event, dygraph, context); - - // if it didn't move, it is a selection - if (state.dygraph_last_touch_move === 0 && state.dygraph_last_touch_page_x !== 0) { - NETDATA.globalSelectionSync.dontSyncBefore = 0; - NETDATA.globalSelectionSync.setMaster(state); - - // internal api of dygraph - let pct = (state.dygraph_last_touch_page_x - (dygraph.plotter_.area.x + state.element.getBoundingClientRect().left)) / dygraph.plotter_.area.w; - console.log('pct: ' + pct.toString()); - - let t = Math.round(state.view_after + (state.view_before - state.view_after) * pct); - if (NETDATA.dygraphSetSelection(state, t)) { - NETDATA.globalSelectionSync.sync(state, t); - } - } - - // if it was double tap within double click time, reset the charts - let now = Date.now(); - if (typeof state.dygraph_last_touch_end !== 'undefined') { - if (state.dygraph_last_touch_move === 0) { - let dt = now - state.dygraph_last_touch_end; - if (dt <= NETDATA.options.current.double_click_speed) { - NETDATA.resetAllCharts(state); - } - } - } - - // remember the timestamp of the last touch end - state.dygraph_last_touch_end = now; - - // refresh all the charts immediately - NETDATA.options.auto_refresher_stop_until = 0; - } - } - }; - - if (NETDATA.chartLibraries.dygraph.isLogScale(state)) { - if (Array.isArray(state.tmp.dygraph_options.valueRange) && state.tmp.dygraph_options.valueRange[0] <= 0) { - state.tmp.dygraph_options.valueRange[0] = null; - } - } - - if (NETDATA.chartLibraries.dygraph.isSparkline(state)) { - state.tmp.dygraph_options.drawGrid = false; - state.tmp.dygraph_options.drawAxis = false; - state.tmp.dygraph_options.title = undefined; - state.tmp.dygraph_options.ylabel = undefined; - state.tmp.dygraph_options.yLabelWidth = 0; - //state.tmp.dygraph_options.labelsDivWidth = 120; - //state.tmp.dygraph_options.labelsDivStyles.width = '120px'; - state.tmp.dygraph_options.labelsSeparateLines = true; - state.tmp.dygraph_options.rightGap = 0; - state.tmp.dygraph_options.yRangePad = 1; - state.tmp.dygraph_options.axes.x.drawAxis = false; - state.tmp.dygraph_options.axes.y.drawAxis = false; - } - - if (smooth) { - state.tmp.dygraph_smooth_eligible = true; - - if (NETDATA.options.current.smooth_plot) { - state.tmp.dygraph_options.plotter = smoothPlotter; - } - } - else { - state.tmp.dygraph_smooth_eligible = false; - } - - if (netdataSnapshotData !== null && NETDATA.globalPanAndZoom.isActive() && NETDATA.globalPanAndZoom.isMaster(state) === false) { - // pan and zoom on snapshots - state.tmp.dygraph_options.dateWindow = [NETDATA.globalPanAndZoom.force_after_ms, NETDATA.globalPanAndZoom.force_before_ms]; - //state.tmp.dygraph_options.isZoomedIgnoreProgrammaticZoom = true; - } - - let seriesStyles = NETDATA.dygraphGetSeriesStyle(state.tmp.dygraph_options); - state.tmp.dygraph_options.series = seriesStyles; - - state.tmp.dygraph_instance = new Dygraph( - state.element_chart, - data.result.data, - state.tmp.dygraph_options - ); - - state.tmp.dygraph_history_tip_element = document.createElement('div'); - state.tmp.dygraph_history_tip_element.innerHTML = ` - <span class="dygraph__history-tip-content"> - Want to extend your history of real-time metrics? - <br /> - <a href="https://docs.netdata.cloud/docs/configuration-guide/#increase-the-metrics-retention-period" target=_blank> - Configure Netdata's <b>history</b></a> - or use the <a href="https://docs.netdata.cloud/database/engine/" target=_blank>DB engine</a>. - </span> - `; - state.tmp.dygraph_history_tip_element.className = 'dygraph__history-tip'; - state.element_chart.appendChild(state.tmp.dygraph_history_tip_element); - - - state.tmp.dygraph_force_zoom = false; - state.tmp.dygraph_user_action = false; - state.tmp.dygraph_last_rendered = Date.now(); - state.tmp.dygraph_highlight_after = null; - - if (state.tmp.dygraph_options.valueRange[0] === null && state.tmp.dygraph_options.valueRange[1] === null) { - if (typeof state.tmp.dygraph_instance.axes_[0].extremeRange !== 'undefined') { - state.tmp.__commonMin = NETDATA.dataAttribute(state.element, 'common-min', null); - state.tmp.__commonMax = NETDATA.dataAttribute(state.element, 'common-max', null); - } else { - state.log('incompatible version of Dygraph detected'); - state.tmp.__commonMin = null; - state.tmp.__commonMax = null; - } - } else { - // if the user gave a valueRange, respect it - state.tmp.__commonMin = null; - state.tmp.__commonMax = null; - } - - return true; -}; - -NETDATA.dygraphGetSeriesStyle = function(dygraphOptions) { - const seriesStyleStr = dygraphOptions.perSeriesStyle; - let formattedStyles = {}; - - if (seriesStyleStr === '') { - return formattedStyles; - } - - // Parse the config string into a JSON object - let styles = seriesStyleStr.replace(' ', '').split('|'); - - styles.forEach(style => { - const keys = style.split(':'); - formattedStyles[keys[0]] = keys[1]; - }); - - for (let key in formattedStyles) { - if (formattedStyles.hasOwnProperty(key)) { - let settings; - - switch (formattedStyles[key]) { - case 'line': - settings = { fillGraph: false }; - break; - case 'area': - settings = { fillGraph: true }; - break; - case 'dot': - settings = { - fillGraph: false, - drawPoints: true, - pointSize: dygraphOptions.pointSize - }; - break; - default: - settings = undefined; - } - - formattedStyles[key] = settings; - } - } - - return formattedStyles; -}; |