diff --git a/build/queryOverview.js b/build/queryOverview.js index bebbc5d..171f9e3 100644 --- a/build/queryOverview.js +++ b/build/queryOverview.js @@ -309,7 +309,7 @@ }) ]) .map(function(item) { - var itemObject = {}; + var itemObject = item instanceof Object ? Object.assign({}, item) : {}; itemObject.value_col = item instanceof Object ? item.value_col : item; itemObject.label = @@ -1211,38 +1211,42 @@ function addSelectAll() { var context = this; - this.controls.filters.labels.each(function(d) { - var label = d3 - .select(this) - .html(d.label + ' '); - var checkbox = label - .select('input') - .datum(d) - .attr('title', 'Deselect All ' + d.label + ' Options') - .property('checked', true) - .on('click', function(di) { - var checkbox = d3.select(this); - var checked = this.checked; - - //Update checkbox tooltip. - checkbox.attr( - 'title', - checked - ? 'Deselect All ' + di.label + ' Options' - : 'Select All ' + di.label + ' Options' - ); - - //Update filter object. - var filter = context.filters.find(function(filter) { - return filter.col === di.value_col; + this.controls.filters.labels + .filter(function(d) { + return d.multiple; + }) + .each(function(d) { + var label = d3 + .select(this) + .html(d.label + ' '); + var checkbox = label + .select('input') + .datum(d) + .attr('title', 'Deselect All ' + d.label + ' Options') + .property('checked', true) + .on('click', function(di) { + var checkbox = d3.select(this); + var checked = this.checked; + + //Update checkbox tooltip. + checkbox.attr( + 'title', + checked + ? 'Deselect All ' + di.label + ' Options' + : 'Select All ' + di.label + ' Options' + ); + + //Update filter object. + var filter = context.filters.find(function(filter) { + return filter.col === di.value_col; + }); + if (checked) filter.val = filter.choices; + else filter.val = []; + + //Redraw. + context.draw(); }); - if (checked) filter.val = filter.choices; - else filter.val = []; - - //Redraw. - context.draw(); - }); - }); + }); this.controls.filters.checkboxes = this.controls.filters.labels.selectAll('.qo-select-all'); } @@ -1251,21 +1255,23 @@ var filter = this.filters.find(function(filter) { return filter.col === d.value_col; }); - filter.val = selectedOptions; - var checked = filter.val.length === filter.choices.length; + filter.val = d.multiple ? selectedOptions : selectedOptions.pop(); //Update checkbox. - var checkbox = this.controls.filters.checkboxes - .filter(function(di) { - return di.value_col === d.value_col; - }) - .attr( - 'title', - checked - ? 'Deselect All ' + d.label + ' Options' - : 'Select All ' + d.label + ' Options' - ) - .property('checked', checked); + if (d.multiple) { + var checked = filter.val.length === filter.choices.length; + var checkbox = this.controls.filters.checkboxes + .filter(function(di) { + return di.value_col === d.value_col; + }) + .attr( + 'title', + checked + ? 'Deselect All ' + d.label + ' Options' + : 'Select All ' + d.label + ' Options' + ) + .property('checked', checked); + } } function updateFilterEventListeners() { @@ -1502,6 +1508,10 @@ ); } + function setXDomain() { + if (this.filtered_data.length === 0) this.x_dom = [0, 0]; + } + function setYDomain() { var _this = this; @@ -1549,9 +1559,10 @@ function setChartHeight() { //Match chart height to number of bars currently displayed. - this.raw_height = - (+this.config.range_band + this.config.range_band * this.config.padding) * - this.y_dom.length; + this.raw_height = this.filtered_data.length + ? (+this.config.range_band + this.config.range_band * this.config.padding) * + this.y_dom.length + : 100; } function updateXAxisLabel() { @@ -1572,6 +1583,7 @@ function onDraw() { setLeftMargin.call(this); + setXDomain.call(this); setYDomain.call(this); setChartHeight.call(this); updateXAxisLabel.call(this); @@ -1735,7 +1747,7 @@ color: 'red' }) .transition() - .delay(5000) + .delay(3000) .style({ 'font-weight': 'normal', 'text-decoration': 'none', @@ -1762,7 +1774,7 @@ color: 'red' }) .transition() - .delay(5000) + .delay(3000) .style({ 'font-weight': 'normal', 'text-decoration': 'none', @@ -1803,7 +1815,7 @@ fill: 'red' }) .transition() - .delay(5000) + .delay(3000) .style({ 'font-weight': 'normal', 'text-decoration': 'none', @@ -2043,6 +2055,21 @@ }); } + function addNoDataIndicator() { + this.svg.select('.qo-no-data').remove(); + console.log(this.filtered_data); + if (this.filtered_data.length === 0) + this.svg + .append('text') + .classed('qo-no-data', true) + .attr({ + x: this.plot_width / 2, + y: this.plot_height / 2, + 'text-anchor': 'middle' + }) + .text('No queries selected. Verify that no filter selections are in conflict.'); + } + function onResize() { //Add filter functionality to legend. legendFilter.call(this); @@ -2067,6 +2094,9 @@ //Add bar deselection. addBarDeselection.call(this); + + //Add informational text to the chart canvas when filters are in conflict. + addNoDataIndicator.call(this); } function onDestroy() {} @@ -2267,17 +2297,20 @@ function truncateCellText() { var _this = this; - this.tbody - .selectAll('td') - .attr('title', function(d) { - return d.text; - }) - .filter(function(d) { - return d.text.length > _this.chart.initialSettings.truncation_cutoff; - }) - .text(function(d) { - return d.text.substring(0, _this.chart.initialSettings.truncation_cutoff) + '...'; - }); + if (this.data.raw.length) + this.tbody + .selectAll('td') + .attr('title', function(d) { + return d.text; + }) + .filter(function(d) { + return d.text.length > _this.chart.initialSettings.truncation_cutoff; + }) + .text(function(d) { + return ( + d.text.substring(0, _this.chart.initialSettings.truncation_cutoff) + '...' + ); + }); } function moveScrollBarLeft() { diff --git a/src/chart/onDraw.js b/src/chart/onDraw.js index 2dd8554..51ed83c 100644 --- a/src/chart/onDraw.js +++ b/src/chart/onDraw.js @@ -1,10 +1,12 @@ import setLeftMargin from './onDraw/setLeftMargin'; +import setXDomain from './onDraw/setXDomain'; import setYDomain from './onDraw/setYDomain'; import setChartHeight from './onDraw/setChartHeight'; import updateXAxisLabel from './onDraw/updateXAxisLabel'; export default function onDraw() { setLeftMargin.call(this); + setXDomain.call(this); setYDomain.call(this); setChartHeight.call(this); updateXAxisLabel.call(this); diff --git a/src/chart/onDraw/setChartHeight.js b/src/chart/onDraw/setChartHeight.js index feb9245..594b895 100644 --- a/src/chart/onDraw/setChartHeight.js +++ b/src/chart/onDraw/setChartHeight.js @@ -1,6 +1,7 @@ export default function setChartHeight() { //Match chart height to number of bars currently displayed. - this.raw_height = - (+this.config.range_band + this.config.range_band * this.config.padding) * - this.y_dom.length; + this.raw_height = this.filtered_data.length + ? (+this.config.range_band + this.config.range_band * this.config.padding) * + this.y_dom.length + : 100; } diff --git a/src/chart/onDraw/setXDomain.js b/src/chart/onDraw/setXDomain.js new file mode 100644 index 0000000..de30f1c --- /dev/null +++ b/src/chart/onDraw/setXDomain.js @@ -0,0 +1,3 @@ +export default function setXDomain() { + if (this.filtered_data.length === 0) this.x_dom = [0, 0]; +} diff --git a/src/chart/onLayout/addSelectAll.js b/src/chart/onLayout/addSelectAll.js index ce32c24..32030d4 100644 --- a/src/chart/onLayout/addSelectAll.js +++ b/src/chart/onLayout/addSelectAll.js @@ -1,7 +1,7 @@ export default function addSelectAll() { const context = this; - this.controls.filters.labels.each(function(d) { + this.controls.filters.labels.filter(d => d.multiple).each(function(d) { const label = d3 .select(this) .html(`${d.label} `); diff --git a/src/chart/onLayout/updateFilterEventListeners/updateSelectAll.js b/src/chart/onLayout/updateFilterEventListeners/updateSelectAll.js index 40adb0e..0959015 100644 --- a/src/chart/onLayout/updateFilterEventListeners/updateSelectAll.js +++ b/src/chart/onLayout/updateFilterEventListeners/updateSelectAll.js @@ -1,15 +1,17 @@ export default function updateSelectAll(d, selectedOptions) { //Update filter object. const filter = this.filters.find(filter => filter.col === d.value_col); - filter.val = selectedOptions; - const checked = filter.val.length === filter.choices.length; + filter.val = d.multiple ? selectedOptions : selectedOptions.pop(); //Update checkbox. - const checkbox = this.controls.filters.checkboxes - .filter(di => di.value_col === d.value_col) - .attr( - 'title', - checked ? `Deselect All ${d.label} Options` : `Select All ${d.label} Options` - ) - .property('checked', checked); + if (d.multiple) { + const checked = filter.val.length === filter.choices.length; + const checkbox = this.controls.filters.checkboxes + .filter(di => di.value_col === d.value_col) + .attr( + 'title', + checked ? `Deselect All ${d.label} Options` : `Select All ${d.label} Options` + ) + .property('checked', checked); + } } diff --git a/src/chart/onResize.js b/src/chart/onResize.js index 22a6b4d..1a2f752 100644 --- a/src/chart/onResize.js +++ b/src/chart/onResize.js @@ -6,6 +6,7 @@ import hideBars from './onResize/hideBars'; import annotateNumberOfQueries from './onResize/annotateNumberOfQueries'; import addBarClick from './onResize/addBarClick'; import addBarDeselection from './onResize/addBarDeselection'; +import addNoDataIndicator from './onResize/addNoDataIndicator'; export default function onResize() { //Add filter functionality to legend. @@ -31,4 +32,7 @@ export default function onResize() { //Add bar deselection. addBarDeselection.call(this); + + //Add informational text to the chart canvas when filters are in conflict. + addNoDataIndicator.call(this); } diff --git a/src/chart/onResize/addNoDataIndicator.js b/src/chart/onResize/addNoDataIndicator.js new file mode 100644 index 0000000..9136fd8 --- /dev/null +++ b/src/chart/onResize/addNoDataIndicator.js @@ -0,0 +1,14 @@ +export default function addNoDataIndicator() { + this.svg.select('.qo-no-data').remove(); + console.log(this.filtered_data); + if (this.filtered_data.length === 0) + this.svg + .append('text') + .classed('qo-no-data', true) + .attr({ + x: this.plot_width / 2, + y: this.plot_height / 2, + 'text-anchor': 'middle' + }) + .text('No queries selected. Verify that no filter selections are in conflict.'); +} diff --git a/src/chart/onResize/addYAxisTickClick.js b/src/chart/onResize/addYAxisTickClick.js index 86d1fa6..de40755 100644 --- a/src/chart/onResize/addYAxisTickClick.js +++ b/src/chart/onResize/addYAxisTickClick.js @@ -19,7 +19,7 @@ export default function addYAxisTickClick() { color: 'red' }) .transition() - .delay(5000) + .delay(3000) .style({ 'font-weight': 'normal', 'text-decoration': 'none', @@ -44,7 +44,7 @@ export default function addYAxisTickClick() { color: 'red' }) .transition() - .delay(5000) + .delay(3000) .style({ 'font-weight': 'normal', 'text-decoration': 'none', @@ -79,7 +79,7 @@ export default function addYAxisTickClick() { fill: 'red' }) .transition() - .delay(5000) + .delay(3000) .style({ 'font-weight': 'normal', 'text-decoration': 'none', diff --git a/src/configuration/syncSettings/arrayOfVariablesCheck.js b/src/configuration/syncSettings/arrayOfVariablesCheck.js index e1502d9..9484485 100644 --- a/src/configuration/syncSettings/arrayOfVariablesCheck.js +++ b/src/configuration/syncSettings/arrayOfVariablesCheck.js @@ -16,7 +16,7 @@ export default function arrayOfVariablesCheck(defaultVariables, userDefinedVaria ) ]) .map(item => { - const itemObject = {}; + const itemObject = item instanceof Object ? Object.assign({}, item) : {}; itemObject.value_col = item instanceof Object ? item.value_col : item; itemObject.label = diff --git a/src/listing/onDraw/truncateCellText.js b/src/listing/onDraw/truncateCellText.js index 8793fcb..58e5fb8 100644 --- a/src/listing/onDraw/truncateCellText.js +++ b/src/listing/onDraw/truncateCellText.js @@ -1,7 +1,8 @@ export default function truncateCellText() { - this.tbody - .selectAll('td') - .attr('title', d => d.text) - .filter(d => d.text.length > this.chart.initialSettings.truncation_cutoff) - .text(d => `${d.text.substring(0, this.chart.initialSettings.truncation_cutoff)}...`); + if (this.data.raw.length) + this.tbody + .selectAll('td') + .attr('title', d => d.text) + .filter(d => d.text.length > this.chart.initialSettings.truncation_cutoff) + .text(d => `${d.text.substring(0, this.chart.initialSettings.truncation_cutoff)}...`); } diff --git a/test-page/index.js b/test-page/index.js index f999329..ae83c5c 100644 --- a/test-page/index.js +++ b/test-page/index.js @@ -6,7 +6,7 @@ d3.csv( console.log(error); var settings = { - truncation_cutoff: 10, + filters: [{value_col: 'fieldname', multiple: true}], }; var instance = queryOverview( '#container',