History Date Picker Chart
Description: This component can show up to 7 points. To view the data, a query tag must be put on the component with the value set to the desired query. An example would be or readAll((equipRef==$id) and ((navName=="Damper") or(navName=="AirFlow")))
Download: historyDatePickerChartRange.f5m
Make Your Own
Ractive
Make sure AM|Charts is dragged out into the workspace as well as moment.min.js
Next drag out Ractive and add a marker tag called historyDatePickerChart
Add a string tag to the component called query with the value set to the desired query (Note the point must have a his but you do not need to add .hisRead)
Open up the Ractive Editor under properties
Copy and paste the code below into the corresponding tabs
Template
Template Code
<div class="s-box">
<div class="buttonBar">
<div class="s-button s-selected" id="day" on-click="day">Today</div>
<div class="s-button" id="week" on-click="week">This Week</div>
<div class="s-button" id="month" on-click="month">This Month</div>
<div class="s-button" id="datePicker" on-click="datePicker">{{#if myStart==myEnd}}{{myStart}}{{else}}{{myStart}}-{{myEnd}}{{/if}}</div>
<div class="s-button" id="datePickerStart" on-click="datePickerStart">{{startPick}}</div>
<div class="s-button" id="datePickerEnd" on-click="datePickerEnd">{{endPick}}</div>
</div>
<div id="amChartPoint" style="width:100%; height:100%;"></div>
</div>Model
Model Code
{
data:
{
myStart: "Date Picker",
myEnd: "Date Picker",
startPick: "Start",
endPick: "End"
}
}Style
Style Code
.s-box{
padding: 10px;
border-radius: 5px;
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
flex: 1 1 auto;
}
.buttonBar{
width:100%;
height:35px;
border-radius: 5px;
background-color: #4f7ab3;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
}
.s-button{
color:#fff;
border-radius: 5px;
width:100%;
height: 100%;
font-weight: bold;
padding: 10px 15px 10px 15px;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
cursor: pointer;
}
.s-selected{
background-color: #7093c1;
}Init
Init Code
this.ractive.fire("obtainData");
var template = this;
var model = this.ractive;
var startRange = "";
var endRange = "";
var tpoint = model.queryAll("targetPoint");
if(tpoint.length > 0) tpoint = tpoint[0].pointId;
else tpoint = "undefined";
var query = this.query.replace(/\$id/g, tpoint);
var dataQuery = query+'.hisRead(today)';
function clearTabs(item){
model.set('myStart', "Date Picker");
model.set('myEnd', "Date Picker");
model.set('startPick', "Start");
model.set('endPick', "End");
}
function updateChart(newQuery, buttonInd){
var test = template.view.querySelector("#amChartPoint");
var buttonIds = [
template.view.querySelector("#day"),
template.view.querySelector("#week"),
template.view.querySelector("#month"),
template.view.querySelector("#datePicker"),
template.view.querySelector("#datePickerStart"),
template.view.querySelector("#datePickerEnd")
];
buttonIds.forEach(function(itm){ itm.style.backgroundColor = "#4f7ab3"; });
buttonIds[buttonInd].style.backgroundColor = "#7093c1";
setTimeout(function() {
finstack.eval(newQuery, function(event){
var cols = [];
event.result.columns.forEach(function(itm){
var t = /v\d+/.exec(itm.name);
if(t !== null && t[0] == t.input){
if(itm.metadata) cols.push({dis: itm.metadata.idDis || itm.metadata.dis || itm.metadata.id, col: itm.name, unit: itm.metadata.unit || null, equipRefDis: itm.metadata.equipRefDis});
else cols.push({dis: itm.name, col: itm.name});
}
});
var grphs = [];
var cou = 0;
cols.forEach(function(itm){
grphs.push({
"id": "g"+cou,
"balloonText": ""+itm.equipRefDis+": [["+itm.col+"]] "+itm.unit+"",
"lineThickness": 2,
"title": itm.dis,
"unit" : itm.unit,
"valueField": itm.col,
"fillAlphas": 0.2 //Area
});
cou++;
});
var myData = event.result.toObj();
var chartData =[];
var myData2 = [];
myData.forEach(function(itm){
myData2.push({
"ts": itm.ts,
"tsOffset": itm.tsOffset,
"tsTimezone": itm.tsTimezone,
"v0": itm.v0 || 0,
"v1": itm.v1 || 0,
"v2": itm.v2 || 0,
"v3": itm.v3 || 0,
"v4": itm.v4 || 0,
"v5": itm.v5 || 0,
"v6": itm.v6 || 0,
"v7": itm.v7 || 0
});
});
myData2.forEach(function(itm){
chartData.push({
"ts": itm.ts,
"tsOffset": itm.tsOffset,
"tsTimezone": itm.tsTimezone,
"v0": itm.v0.toFixed(1) || null,
"v1": itm.v1.toFixed(1) || null,
"v2": itm.v2.toFixed(1) || null,
"v3": itm.v3.toFixed(1) || null,
"v4": itm.v4.toFixed(1) || null,
"v5": itm.v5.toFixed(1) || null,
"v6": itm.v6.toFixed(1) || null,
"v7": itm.v7.toFixed(1) || null
});
});
var chart = AmCharts.makeChart(test, {
"type": "serial",
"theme": "light",
"marginRight": 80,
"dataProvider": chartData,
"valueAxes": [{
"axisAlpha": 0.1
}],
"graphs": grphs,
"zoomOutButtonRollOverAlpha": 0.15,
"chartCursor": {
"categoryBalloonDateFormat": "MMMM D L:NN A",
"cursorPosition": "mouse",
"showNextAvailable": true
},
"legend": {
"equalWidths": true,
"position": "top",
"valueAlign": "left",
"valueWidth": 100
},
"autoMarginOffset": 5,
"columnWidth": 1,
"categoryField": "ts",
"categoryAxis": {
"parseDates": true,
"minPeriod": "mm",
"dateFormats":[
{
"period":"fff",
"format":"L:NN:SS A"
},
{
"period":"ss",
"format":"L:NN:SS A"
},
{
"period":"mm",
"format":"L:NN A"
},
{
"period":"hh",
"format":"L:NN A"
},
{
"period":"DD",
"format":"MMM DD"
},
{
"period":"WW",
"format":"MMM DD"
},
{
"period":"MM",
"format":"MMM"
},
{
"period":"YYYY",
"format":"YYYY"
}]
},
"chartScrollbar": {
"enabled": true,
},
"export": {
"enabled": true
},
});
chart.addListener("rendered", zoomChart);
zoomChart();
function zoomChart() {
chart.zoomToIndexes(chart.dataProvider.length - 40, chart.dataProvider.length - 1);
}
});
}, 200);
}
this.ractive.on("day", function(event) {
clearTabs(true);
updateChart(dataQuery.replace(/(\.*\hisRead).*$/g,'.hisRead(today)'), 0);
});
this.ractive.on("week", function(event) {
clearTabs(true);
updateChart(dataQuery.replace(/(\.*\hisRead).*$/g,'.hisRead(thisWeek)'), 1);
});
this.ractive.on("month", function(event) {
clearTabs(true);
updateChart(dataQuery.replace(/(\.*\hisRead).*$/g,'.hisRead(thisMonth)'), 2);
});
this.ractive.on("datePicker", function(event) {
clearTabs(true);
top.app.ShowCalendar(null,function(data){
var start = moment(data.range.start).format("YYYY-MM-DD");
var end = moment(data.range.end).format("YYYY-MM-DD");
var dateStringStart = start;
var startDate = new moment(dateStringStart).format('MM/DD/YYYY');
var dateStringEnd = end;
var endDate = new moment(dateStringEnd).format('MM/DD/YYYY');
model.set('myStart', startDate);
model.set('myEnd', endDate);
var newQuery = "";
if(start == end) newQuery= dataQuery.replace(/(\.*\hisRead).*$/g,'.hisRead('+start+')');
else newQuery= dataQuery.replace(/(\.*\hisRead).*$/g,'.hisRead('+start+'..'+end+')');
updateChart(newQuery, 3);
},
{periods:true});
});
this.ractive.on("datePickerStart", function(event) {
clearTabs(true);
top.app.ShowCalendar(null,function(data){
startRange = moment(data.range.start).format("YYYY-MM-DD");
var dateStringStart = startRange;
var startDate = new moment(dateStringStart).format('MM/DD/YYYY');
model.set('startPick', startDate);
var newQuery = "";
// newQuery = dataQuery.replace(/(\.*\hisRead).*$/g,'.hisRead('+start+')');
updateChart("", 4);
});
});
this.ractive.on("datePickerEnd", function(event) {
model.set('myStart', "Date Picker");
model.set('myEnd', "Date Picker");
top.app.ShowCalendar(null,function(data){
endRange = moment(data.range.end).format("YYYY-MM-DD");
var dateStringEnd = endRange;
var endDate = new moment(dateStringEnd).format('MM/DD/YYYY');
model.set('endPick', endDate);
var newQuery = "";
newQuery= dataQuery.replace(/(\.*\hisRead).*$/g,'.hisRead('+startRange+'..'+endRange+')');
updateChart(newQuery, 5);
});
});Program
Go to programs in the left menu
Click the plus to add a new program, and it will pull up the program editor
In the Program Target Filter type historyDatePickerChart
Click the three dots in the top right corner, and select variables
Click the gear that appears as you hover over "this"
Turn on Invokes the Function
Change the dropdown to Custom Event
In the textbox below the dropdown type obtainData
Click the gray Save button
Click the + next to Program Vars to add another variable
Name it point on the top line, and underneath put id==$virtualPointRef
Click the gray Save button
Copy and paste the code below into the main section and click the blue save
Code
Program Code
var tpoint = queryAll("targetPoint");
if(tpoint.length > 0) tpoint = tpoint[0].pointId;
else tpoint = "undefined";
var query = this.query.replace(/\$id/g, tpoint);
this.ractive.fire("day");