/**
* Widget that creates a chart of storm surge and tide data
* @module app/widget/TideChart
* @author David Kristiansen <david.kristiansen@nscc.ca>
* @copyright Nova Scotia Community College 2017
*/
define([
"dojo/_base/declare",
"dojo/_base/lang",
"dojo/on",
"dojo/topic",
"dojo/Evented",
"dojo/dom",
"dojo/dom-construct",
"dijit/_WidgetBase",
"dijit/_OnDijitClickMixin",
"dijit/Tooltip",
"moment/moment",
"dstore/charting/StoreSeries",
"dojox/charting/Chart",
"dojox/charting/axis2d/Default",
"dojox/charting/plot2d/Areas",
"dojox/charting/plot2d/Grid",
"dojox/charting/plot2d/Columns",
"dojox/charting/plot2d/Lines",
// "dojox/charting/plot2d/Indicator",
"dojox/charting/action2d/MouseZoomAndPan",
"dojox/charting/action2d/Highlight",
"dojox/charting/themes/Wetland",
"dojox/charting/widget/Legend",
"dojox/charting/widget/SelectableLegend"
],
function (
declare,
lang,
on,
topic,
Evented,
dom,
domConstruct,
_WidgetBase,
_OnDijitClickMixin,
Tooltip,
moment,
StoreSeries,
Chart,
Default,
Areas,
Grid,
Columns,
Lines,
// Indicator,
MouseZoomAndPan,
Highlight,
Theme,
Legend,
SelectableLegend
) {
return declare([_WidgetBase, _OnDijitClickMixin, Evented], {
chart: null,
gridStore: null,
selectedTideStore: null,
nowTideStore: null,
xLabels: null,
yLabels: null,
options: {
dataStore: null,
title: null
},
/** @constructor
* @param {object} args Object of properties to mixin
* @param {object} srcRefNode Dom node for the widget to attach to
**/
constructor: function (param, srcRefNode) {
// console.log("Chart::constructor");
/** mix in settings and defaults
* @mixin args
*/
declare.safeMixin(this.options, param);
/** Dom widget node */
this.domNode = srcRefNode;
// properties
this.set("dataStore", this.options.dataStore);
this.title = this.options.title || "";
},
/**
* Creates the dom elements used by the chart.
**/
postCreate: function () {
// console.log("Chart::postCreate");
// <div id='chart'></div><div id='chartLegend'></div>
var divChart = dom.byId(this.domNode);
domConstruct.create("div", {
id: "tooltipChart"
}, divChart);
domConstruct.create("div", {
id: "chart"
}, divChart);
},
/**
* Starts the widget after it has been constructed.
* Checks to make sure the required data is loaded.
* @public
*
**/
startup: function () {
// console.log("Chart::startup");
/* Data not defined*/
if (!this.dataStore.memDStore) {
this.destroy();
console.warn("Chart::Tide data required");
}
/* When data is loaded*/
if (typeof this.dataStore.memDStore.data !== "undefined" && this.dataStore.memDStore.data !== null && this.dataStore.memDStore.data.length > 0) {
this._init();
} else {
console.warn("Chart::Waiting to load chart..");
on(this.dataStore, "tideData_ready", lang.hitch(this, function () {
this._init();
}));
}
},
/**
* Destroys widget and any lingering tooltips.
* @public
*
**/
destroy: function () {
Tooltip.show("", dom.byId('dijit__MasterTooltip_0'));
Tooltip.hide(dom.byId('dijit__MasterTooltip_0'));
this.inherited(arguments);
// console.log("Chart::destroyed");
},
/**
* Calls the createChart method.
* @private
*
**/
_init: function () {
// console.log("Chart::_init");
this.createChart();
},
/**
* Creates the tide and storm surge chart for a single tide station.
* @public
* @todo Compartmentalize parts of the chart to handled sepearately
**/
createChart: function () {
// console.log("Chart::createChart");
// this.thresLabels = function (text, value, precision) {
// var thresholds = ["Stage 1 Flood", "Stage 2 Flood", "Stage 3 Flood", "Record Water Level"];
// return thresholds[text];
// };
this.xLabels = function (text, value, precision) {
return new Date(this.data[value - 1].fulldate).getHours().toString();
};
// this.markerLabels = function (args, plot) {
// var surgeVal = plot.series[1].data[args.index] - plot.series[0].data[args.index]
// var strTip = "TWL: " + plot.series[1].data[args.index] + "</br> Tide: " + plot.series[0].data[args.index] + "</br> Surge: " + surgeVal.toFixed(3); //To Fix floating point error hopefully
// return strTip;
// }
var startDt = new Date(this.dataStore.memDStore.data[0].fulldate);
var lenDt = this.dataStore.memDStore.data.length - 1;
var endDt = new Date(this.dataStore.memDStore.data[lenDt].fulldate);
var momentLocale = moment.localeData();
var xTitle = "<b>Local Time (hours)</b> (" + momentLocale.longDateFormat('L') + ")</br>From: " + moment(startDt).format('L LT') + " To: " + moment(endDt).format('L LT');
// console.log(momentLocale.longDateFormat('L'));
//////////////////
/* Chart Begins */
//////////////////
var chart = new Chart("chart", {
title: this.title,
titlePos: "top",
titleGap: 5,
titleFont: "normal normal normal 15pt Arial"
});
chart.addPlot("default", {
type: Areas,
line: true,
markers: true,
tension: "X"
});
chart.addPlot("surge", {
type: Lines,
tension: "X"
});
chart.addPlot("grids", {
type: Grid,
vMajorLines: false,
vMinorLines: false,
hAxis: "x",
vAxis: "y"
});
// chart.addPlot("nowPlot", {
// type: "Columns",
// gap: 1,
// minBarSize: 1,
// maxBarSize: 1,
// vAxis: "y2"
// });
chart.addPlot("bargraph", {
type: "Columns",
gap: 0,
// minBarSize: 1,
// maxBarSize: 1,
vAxis: "y2"
});
// chart.addPlot("threshold", {
// type: Indicator,
// vertical: false,
// // values: [2.992,3.092,3.292,2.822,3.592],
// values: [-1.592, -0.092, 1.292, 1.822, 2.92],
// lineStroke: {
// color: "navy",
// style: "dash"
// },
// stroke: "transparent",
// outline: "transparent",
// fill: "transparent",
// fontColor: "rgba(0, 0, 128, 0.8)",
// labelStyle: 'inside',
//
// labelFunc: this.thresLabels //lang.hitch(this.dataStore.memDStore, this.xLabels)
// });
chart.addAxis("x", {
title: xTitle, //"Time (hours) Start: End",
titleOrientation: "away",
titleFont: "normal normal normal 11pt Arial",
minorTicks: false,
majorTickStep: 1,
min: 1,
labelFunc: lang.hitch(this.dataStore.memDStore, this.xLabels)
});
chart.addAxis("y", {
title: "Water Level CGVD28 (m)",
titleFont: "normal normal bold 11pt Arial",
vertical: true,
fixLower: "major",
fixUpper: "major",
});
chart.addAxis("y2", {
vertical: true,
type: "Invisible",
fixLower: "major",
fixUpper: "major",
min: 0,
max: 1.0
});
chart.addSeries("Predicted Storm Surge", new StoreSeries(this.dataStore.memDStore, "surge"), {
stroke: {
color: "#3655ff",
width: 2
},
plot: "surge",
enableCache: true
});
chart.addSeries("Predicted Total Water Level (TWL)", new StoreSeries(this.dataStore.memDStore, "twl"), {
stroke: {
color: "#d32626",
width: 2
},
fill: "rgba(255, 11, 0, 0.2)",
plot: "default",
enableCache: true
});
chart.addSeries("Predicted Tide", new StoreSeries(this.dataStore.memDStore, "tide"), {
stroke: {
color: "rgb(255, 165, 0)",
width: 2
},
fill: "rgba(255, 245, 0, 0.3)",
plot: "default",
marker: "m-0",
enableCache: true
});
// chart.addSeries("Current Time", new StoreSeries(this.dataStore.chartTrack, "now"), {
// stroke: {
// color: "rgb(0, 11, 149)"
// },
// fill: "rgb(0, 11, 149)",
// plot: "nowPlot",
// enableCache: true
// });
chart.addSeries("Hover", new StoreSeries(this.dataStore.chartTrack, "clk"), {
stroke: {
color: "transparent"
},
fill: "transparent",
plot: "bargraph",
enableCache: true
});
// chart.movePlotToFront("nowPlot");
chart.movePlotToFront("surge");
chart.movePlotToFront("bargraph");
var hilite = new Highlight(chart, "bargraph", {
highlight: "rgba(0, 157, 6, 0.48)",
duration: 10
});
chart.setTheme(Theme);
// chart.setAxisWindow("x", 3, 2);
// chart.setWindow(1, 1, 0, 0);
// new MouseZoomAndPan(chart, "default", {
// axis: "x",
// enableScroll: false
// });
chart.render();
var legend = new SelectableLegend({
chart: chart,
horizontal: false
}, "chartLegend");
var tooltip = new Tooltip({
style: "opacity:1;"
});
chart.connectToPlot("bargraph", lang.hitch(this.dataStore.chartTrack, function (evt) {
var surgeVal = chart.getPlot("surge").series[0].data[evt.x]; //surge
var tideVal = chart.getPlot("default").series[1].data[evt.x]; //Tide
var twlVal = chart.getPlot("default").series[0].data[evt.x]; //twl
// console.log("Surge:", surgeVal, " Tide:", tideVal, " TWL:", twlVal);
if (evt.type === "onmouseover") {
var dtVal = new Date(this.data[evt.x].dt);
var around = chart.getPlot("default").toPage({
x: evt.x + 1,
y: maxVertical
});
around.w = 1;
around.h = 1;
tooltip.label = "<div class='ttChart'><p class='ttText'>" + moment(dtVal).format('LT') + "</p><p class='ttText'>" + moment(dtVal).format('L') + "</p><table class='ttTable'><tbody><tr><td>TWL:</td><td>" + twlVal.toFixed(2) + "</td></tr><tr><td>Tide:</td><td>" + tideVal.toFixed(2) + "</td></tr><tr><td>Surge:</td><td>" + surgeVal.toFixed(2) + "</td></tr></tbody></table><div>";
tooltip.position = ["above-centered"];
tooltip.open(around);
} else if (evt.type == "onmouseout") {
tooltip.close();
} else if (evt.type === "onclick") {
// console.log(twlVal); //twl
//emit event of twlVal value to be heard by the other modules
topic.publish("selection", twlVal);
}
}));
var maxVertical = chart.getAxis("y").getScaler().bounds.to;
}
});
});