diff --git a/assets/src/scripts/components/hydrograph/index.js b/assets/src/scripts/components/hydrograph/index.js index e84424201775ac564558bc2fb088d63604ebf8c6..4c4dd7ff6a66efe66467502fb381da1ffdb289d1 100644 --- a/assets/src/scripts/components/hydrograph/index.js +++ b/assets/src/scripts/components/hydrograph/index.js @@ -3,7 +3,7 @@ */ const { select } = require('d3-selection'); const { line } = require('d3-shape'); -const { createSelector, createStructuredSelector, defaultMemoize: memoize } = require('reselect'); +const { createSelector, createStructuredSelector} = require('reselect'); const { addSVGAccessibility, addSROnlyTable } = require('../../accessibility'); const { dispatch, link, provide } = require('../../lib/redux'); @@ -14,7 +14,7 @@ const { drawSimpleLegend, legendDisplaySelector, createLegendMarkers } = require const { pointsSelector, lineSegmentsSelector, isVisibleSelector } = require('./points'); const { xScaleSelector, yScaleSelector } = require('./scales'); const { Actions, configureStore } = require('./store'); -const { createTooltip, createTooltipText } = require('./tooltip'); +const { createTooltipFocus, createTooltipText } = require('./tooltip'); @@ -146,7 +146,7 @@ const timeSeriesGraph = function (elem) { yScale: yScaleSelector, tsDataKey: () => 'compare' }))) - .call(link(createTooltip, createStructuredSelector({ + .call(link(createTooltipFocus, createStructuredSelector({ xScale: xScaleSelector('current'), yScale: yScaleSelector, compareXScale: xScaleSelector('compare'), diff --git a/assets/src/scripts/components/hydrograph/store.js b/assets/src/scripts/components/hydrograph/store.js index 3bec54319ee1002338cc23ef7caf1a28f7a0d308..df8cb8b6c9574e74c2e868059a1287f87579546e 100644 --- a/assets/src/scripts/components/hydrograph/store.js +++ b/assets/src/scripts/components/hydrograph/store.js @@ -169,8 +169,8 @@ export const timeSeriesReducer = function (state={}, action) { case 'SET_TOOLTIP_TIME': return { ...state, - tsTooltipTime: { - ...state.tsTooltipTime, + tooltipFocusTime: { + ...state.tsFocusTime, current: action.currentTime, compare: action.compareTime } @@ -211,7 +211,7 @@ export const configureStore = function (initialState) { desc: '', width: 800, showMedianStatsLabel: false, - tsTooltipTime: { + tooltipFocusTime: { current: null, compare: null }, diff --git a/assets/src/scripts/components/hydrograph/tooltip.js b/assets/src/scripts/components/hydrograph/tooltip.js index 94b4743ed358f07c243e30c2aee70c66e56e9557..1dfa910379c5a16080c661e262c395bb4848e7da 100644 --- a/assets/src/scripts/components/hydrograph/tooltip.js +++ b/assets/src/scripts/components/hydrograph/tooltip.js @@ -66,33 +66,48 @@ const getNearestTime = function(data, time) { index: datum === d0 ? index - 1 : index }; }; - -const tooltipTimeSelector = memoize(tsDataKey => (state) => { - return state.tsTooltipTime[tsDataKey]; +/* + * Returns the tooltipFocus time for a given timeseries + * @param {Object} state - Redux store + * @param {String} tsDataKey - Timeseries key + * @return {Date} + */ +const tooltipFocusTimeSelector = memoize(tsDataKey => (state) => { + return state.tooltipFocusTime[tsDataKey]; }); +/* + * Returns the time series data point nearest the tooltip focus time for the given timeseries + * @param {Object} state - Redux store + * @param String} tsDataKey - Timeseries key + * @return {Object} + */ const tsDatumSelector = memoize(tsDataKey => createSelector( pointsSelector(tsDataKey), - tooltipTimeSelector(tsDataKey), - (points, tsTooltipTime) => { - if (tsTooltipTime) { - return getNearestTime(points, tsTooltipTime).datum; + tooltipFocusTimeSelector(tsDataKey), + (points, tooltipFocusTime) => { + if (tooltipFocusTime) { + return getNearestTime(points, tooltipFocusTime).datum; } else { return null; } }) ); -const tooltipText = function(text, {datum}) { +const updateTooltipText = function(text, {datum}) { if (datum) { text.classed('approved', datum.approved) .classed('estimated', datum.estimated); - text.html(datum.label); + text.text(datum.label); } else { - text.html('Hello'); + text.text(''); } }; +/* + * Append a group containing the tooltip text elements to elem + * @param {Object} elem - D3 selector + */ const createTooltipText = function(elem) { const tskeys = ['current', 'compare']; let tooltipTextGroup = elem.append('g') @@ -105,7 +120,7 @@ const createTooltipText = function(elem) { .attr('class', `${tskey}-tooltip-text`) .attr('x', 20) .attr('y', `${y}em`) - .call(link(tooltipText, createStructuredSelector({ + .call(link(updateTooltipText, createStructuredSelector({ datum: tsDatumSelector(tskey) }))); y += 1; @@ -113,10 +128,13 @@ const createTooltipText = function(elem) { }; const updateFocusLine = function(elem, {currentTime, xScale}) { - let x = xScale(currentTime); - elem.select('.focus-line') - .attr('x1', x) - .attr('x2', x); + if (currentTime) { + let x = xScale(currentTime); + elem.select('.focus-line').attr('x1', x).attr('x2', x); + elem.style('display', null); + } else { + elem.style('display', 'none'); + } }; const updateFocusCircle = function(circleFocus, {tsDatum, xScale, yScale}) { @@ -129,8 +147,17 @@ const updateFocusCircle = function(circleFocus, {tsDatum, xScale, yScale}) { } }; - -const createTooltip = function(elem, {xScale, yScale, compareXScale, currentTsData, compareTsData, isCompareVisible}) { +/* + * Appends a group to elem containing a focus line and circles for the current and compare time series + * @param {Object} elem - D3 select + * @param {Object} xScale - D3 X scale for the current time series + * @param {Object} yScale - D3 Y scale for the graph + * @param {Object} compareXScale - D3 X scale for the compate time series + * @param {Array} currentTsData - current time series points + * @param {Array} compareTsData - compare time series points + * @param {Boolean} isCompareVisible + */ +const createTooltipFocus = function(elem, {xScale, yScale, compareXScale, currentTsData, compareTsData, isCompareVisible}) { elem.selectAll('.focus').remove(); elem.select('.tooltip-text-group').remove(); elem.select('.overlay').remove(); @@ -148,7 +175,7 @@ const createTooltip = function(elem, {xScale, yScale, compareXScale, currentTsDa let focusCompareCircle = createFocusCircle(elem); focusLine.call(link(updateFocusLine, createStructuredSelector({ - currentTime: state => state.tsTooltipTime['current'], + currentTime: state => state.tooltipFocusTime['current'], xScale: () => xScale }))); focusCurrentCircle.call(link(updateFocusCircle, createStructuredSelector({ @@ -166,20 +193,15 @@ const createTooltip = function(elem, {xScale, yScale, compareXScale, currentTsDa .attr('class', 'overlay') .attr('width', '100%') .attr('height', '100%') - .on('mouseover', () => { - focusLine.style('display', null); - focusCurrentCircle.style('display', null); - if (isCompareVisible) { - focusCompareCircle.style('display', null); - } - //tooltipText.style('display', null); - }) - .on('mouseout', () => { - focusLine.style('display', 'none'); - focusCurrentCircle.style('display', 'none'); - focusCompareCircle.style('display', 'none'); - //tooltipText.style('display', 'none'); - }) + .on('mouseover', dispatch(function() { + return Actions.setTooltipTime( + xScale.invert(mouse(elem.node())[0]), + isCompareVisible ? compareXScale.invert(mouse(elem.node())[0]) : null + ); + })) + .on('mouseout', dispatch(function() { + return Actions.setTooltipTime(null, null); + })) .on('mousemove', dispatch(function() { return Actions.setTooltipTime( xScale.invert(mouse(elem.node())[0]), @@ -188,4 +210,4 @@ const createTooltip = function(elem, {xScale, yScale, compareXScale, currentTsDa })); }; -module.exports = {getNearestTime, createTooltip, createTooltipText}; \ No newline at end of file +module.exports = {getNearestTime, tooltipFocusTimeSelector, tsDatumSelector, createTooltipFocus, createTooltipText}; \ No newline at end of file