diff --git a/src/app/charts/chart.component.html b/src/app/charts/chart.component.html
index 9f394ea3..d8d2e862 100644
--- a/src/app/charts/chart.component.html
+++ b/src/app/charts/chart.component.html
@@ -41,7 +41,8 @@
[max]="chart.showMaximum"
[minVal]="chart.minimumValue"
[maxVal]="chart.maximumValue"
- [hover]="isHover">
+ [hover]="isHover"
+ [multiChartScrubber]="multiChartScrubber">
Options
diff --git a/src/app/charts/chart.component.ts b/src/app/charts/chart.component.ts
index ae9b37b3..244744cb 100644
--- a/src/app/charts/chart.component.ts
+++ b/src/app/charts/chart.component.ts
@@ -1,4 +1,4 @@
-import { Component, EventEmitter, Input, OnChanges, Output, HostListener } from '@angular/core';
+import { Component, EventEmitter, OnChanges, Input, Output, HostListener } from '@angular/core';
import { Chart, ChartData } from '../models/chart';
import { City } from '../models/city';
@@ -26,15 +26,18 @@ export class ChartComponent implements OnChanges {
@Input() scenario: Scenario;
@Input() models: ClimateModel[];
@Input() city: City;
+ @Input() multiChartScrubber: Boolean;
private chartData: ChartData[];
private isHover: Boolean = false;
// Mousemove event must be at this level to listen to mousing over rect#overlay
- // Should be configurable to make a cross-chart scrubber
@HostListener('mouseover', ['$event'])
onMouseOver(event) {
this.isHover = event.target.id === 'overlay' ? true : false;
+ if (this.multiChartScrubber) {
+ this.chartService.detectMultiChartHover(this.isHover);
+ }
}
constructor(private chartService: ChartService,
diff --git a/src/app/charts/line-graph.component.ts b/src/app/charts/line-graph.component.ts
index ec237c1e..4a143674 100644
--- a/src/app/charts/line-graph.component.ts
+++ b/src/app/charts/line-graph.component.ts
@@ -1,10 +1,12 @@
-import { Component, ViewEncapsulation, ElementRef, HostListener } from '@angular/core';
+import { Component, ViewEncapsulation, ElementRef, HostListener, OnInit, OnDestroy } from '@angular/core';
import { ChartData, DataPoint } from '../models/chart';
import { Indicator } from '../models/indicator.models';
import * as D3 from 'd3';
import * as _ from 'lodash';
import * as $ from 'jquery';
+import { ChartService } from '../services/chart.service';
+
/*
* Line graph component
* Contains all logic for drawing a line graph
@@ -13,10 +15,10 @@ import * as $ from 'jquery';
selector: 'line-graph',
encapsulation: ViewEncapsulation.None,
template: ``,
- inputs: [ 'data', 'indicator', 'trendline', 'min', 'max', 'minVal', 'maxVal', 'hover' ]
+ inputs: [ 'data', 'indicator', 'trendline', 'min', 'max', 'minVal', 'maxVal', 'hover', 'multiChartScrubber' ]
})
-export class LineGraphComponent {
+export class LineGraphComponent implements OnInit, OnDestroy {
public data: ChartData[];
public extractedData: Array;
@@ -27,6 +29,7 @@ export class LineGraphComponent {
public minVal: number;
public maxVal: number;
public hover: Boolean;
+ public multiChartScrubber: Boolean;
private host; // D3 object referebcing host dom object
private svg; // SVG in which we will print our chart
@@ -49,11 +52,13 @@ export class LineGraphComponent {
// Not a perfect solution should the random int and indicator be the same
// However, this is quite unlikely (1/10000, and even less likely by way of app use)
+ private multiChartScrubberHoverSubscription;
+ private multiChartScrubberInfoSubscription;
/* We request angular for the element reference
* and then we create a D3 Wrapper for our host element
*/
- constructor(private element: ElementRef) {
+ constructor(private element: ElementRef, private chartService: ChartService) {
this.htmlElement = this.element.nativeElement;
this.host = D3.select(this.element.nativeElement);
this.timeOptions = {
@@ -64,18 +69,23 @@ export class LineGraphComponent {
@HostListener('window:resize', ['$event'])
onResize(event) {
- this.ngOnChanges();
+ this.ngOnChanges();
}
// If the chart is being hovered over, handle mouse movements
@HostListener('mousemove', ['$event'])
onMouseMove(event) {
- if (this.hover) {
- this.redrawScrubber(event);
- }
+ // for single-chart scrubber
+ if (this.hover && !this.multiChartScrubber) {
+ this.redrawScrubber(event);
+ }
+ // for multi-chart scrubber
+ if (this.multiChartScrubber) {
+ this.chartService.updateMultiChartScrubberInfo(event);
+ }
}
- /* Will Update on every @Input change */
+ /* Executes on every @Input change */
ngOnChanges(): void {
if (!this.data || this.data.length === 0) return;
this.filterData();
@@ -92,6 +102,30 @@ export class LineGraphComponent {
this.drawScrubber();
}
+ ngOnInit(): void {
+ // Set up global chart mouseover communication chain if set to multi-chart scrubber
+ // ** CURRENTLY ONLY FOR YEARLY INDICATORS**
+ if (this.multiChartScrubber && this.indicator.time_aggregation === 'yearly') {
+ this.multiChartScrubberHoverSubscription = this.chartService.multiChartScrubberHoverObservable.subscribe(data => {
+ this.hover = data;
+ this.hover ? $('.' + this.id).toggleClass('hidden', false) : $('.' + this.id).toggleClass('hidden', true);
+ });
+ this.multiChartScrubberInfoSubscription = this.chartService.multiChartScrubberInfoObservable.subscribe(event => {
+ // Only redraw if a chart is moused over
+ if (this.hover) {
+ this.redrawScrubber(event)
+ }
+ });
+ }
+ }
+
+ ngOnDestroy(): void {
+ if (this.multiChartScrubber && this.indicator.time_aggregation === 'yearly') {
+ this.multiChartScrubberInfoSubscription.unsubscribe();
+ this.multiChartScrubberHoverSubscription.unsubscribe();
+ }
+ }
+
private filterData(): void {
// Preserves parent data by fresh copying indicator data that will undergo processing
let clippedData = _.cloneDeep(_.find(this.data, obj => obj.indicator.name === this.indicator.name));
@@ -372,7 +406,7 @@ export class LineGraphComponent {
// Update text box length
D3.select('.scrubber-box.' + this.id)
- .attr('width', textSVG.node().getBBox().width + 10)
+ .attr('width', labelWidth + 10)
.attr('transform', 'translate(' + -(labelWidth/2 + 5) + ',' + -30 + ')');
}
diff --git a/src/app/lab/lab.component.html b/src/app/lab/lab.component.html
index da9ef60f..4fbf9aed 100755
--- a/src/app/lab/lab.component.html
+++ b/src/app/lab/lab.component.html
@@ -27,6 +27,7 @@
[city]="project.city"
[models]="project.models"
[scenario]="project.scenario"
+ [multiChartScrubber]="project.multiChartScrubber"
(onRemoveChart)="removeChart($event)"
(onChartSettingChanged)="chartSettingChanged()">
diff --git a/src/app/models/project.ts b/src/app/models/project.ts
index b66d74dd..92dc4b53 100644
--- a/src/app/models/project.ts
+++ b/src/app/models/project.ts
@@ -18,6 +18,7 @@ export class Project {
allModels: boolean = true;
models: ClimateModel[] = [];
charts: Chart[] = [];
+ multiChartScrubber: boolean = false;
constructor(object: Object) {
Object.assign(this, object);
@@ -36,7 +37,8 @@ export class Project {
scenario: this.scenario,
allModels: this.allModels,
models: this.models,
- charts: this.charts
+ charts: this.charts,
+ multiChartScrubber: this.multiChartScrubber
};
}
diff --git a/src/app/project/add-edit-project.component.html b/src/app/project/add-edit-project.component.html
index 0711a606..c8025edb 100644
--- a/src/app/project/add-edit-project.component.html
+++ b/src/app/project/add-edit-project.component.html
@@ -33,6 +33,12 @@ Edit project
+
+
+