dashboard
Version:
Create dashboards with gadgets on node.js
581 lines (505 loc) • 19.9 kB
HTML
<!-- plot_dataset.xml -->
<!-- Author: Ian Smith (imsmith@uw.edu) -->
<html lang="en">
<meta http-equiv="Pragma" content="no-cache">
<head>
<title>Plot View</title>
<!-- chart dependencies -->
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.5.2/jquery.min.js" type="text/javascript"></script>
<script src="/js/highcharts_old/highcharts.src.js" type="text/javascript"></script>
<!-- ASCOT Basic Style Sheets -->
<link href="/css/960/reset.css" rel="stylesheet" type="text/css">
<link href="/css/960/text.css" rel="stylesheet" type="text/css">
<script type="text/javascript">
// Plot (pl) object is global
var pl = null;
// GLOBAL CONSTANTS
var chart1; // globally available
// PROPERTIES
var skyViewCenterCoordinate;
var activePointsList;
var skyViewPointsList;
var dataSetList;
// create new Plotter object
function init(){
setHtmlStyles();
pl = new Plotter();
// add colors to the select box (pass the select Name and color array)
pl.setSelectOptions("selSelectionColor", ["red", "green", "blue", "yellow", "unselect"]);
gadget.resize();
}
function setHtmlStyles() {
$(document).ready(function(){
$('a#button').click(function(){
$(this).toggleClass("down");
});
});
}
function Plotter(){
var my = new Object();
// CONSTANTS
var PLOT_HEIGHT = 400,
PLOT_WIDTH = 300;
// CHART CONSTANTS
var DEFAULT_MARKER_COLOR = 'rgba(100, 100, 100, .7)'; // old red: 'rgba(223, 83, 83, .5)';
SELECTED_MARKER_COLOR = 'rgba(210,30,100,.9)'// old yellow: 'rgba(210,210,0,.5)',
DEFAULT_MARKER_SHAPE = 'circle',
SERIES_NAME = 'series1',
MARKER_COLOR = { red: 'rgba(255, 0, 0, .7)',
green: 'rgba(0, 255, 0, .7)',
blue: 'rgba(0, 0, 255, .7)',
yellow: 'rgba(220, 220, 0, .7)',
unselect: DEFAULT_MARKER_COLOR
}
// PRIVATE
_objList = [],
_lastSelectedObjs = [],
_currentDatasetName = "",
// contains pointers to HTML fields on page so we can avoid many document.getElementById() calls
_myFields = { },
_axisInverted = { x: false,
y: false
};
gadget.dashboard.bind('dataSetListChanged', updateDataSetList);
// When the list of public datasets change, rewrite the list of available datasets to plot
function updateDataSetList(){
setSelectOptions("selDatasetName", gadget.dashboard.getDataSetList());
updateSelectedPoints();
}
// GETS for the HTML controls on the page
function getSelectedDataset() {
return getSelectedOption("selDatasetName");
}
function getSelectedXAxis() {
return getSelectedOption("selXAxis");
}
function getSelectedYAxis() {
return getSelectedOption("selYAxis");
}
function setSelectedByMinMax(seriesId, xMin, xMax, yMin, yMax) {
//debugLog('x: ' + xMin + ', ' + xMax + '\ny: ' + yMin + ', ' + yMax);
// 'select' all the points in the chart to change the way they look
var data = chart1.get(seriesId).data;
var ds = gadget.dashboard.getDataSet(getSelectedDataset());
var selectedIds = [];
var selectedMarkerColor = getSelectionMarkerColor();
for (var i=0, len=data.length; i<len; i++){
var point = data[i];
if (point.x <= xMax && point.x >= xMin && point.y <= yMax && point.y >= yMin) {
// point.id looks like: p0
// so we strip the first letter to get the db_id
selectedIds.push(getPointId(point));
colorChartPoint(point, selectedMarkerColor);
}
}
chart1.redraw();
var color = (selectedMarkerColor === "unselect") ? "" : selectedMarkerColor;
// update the dataset with the selected points
// set dataset points colors in bulk
ds.setIndexesColor(selectedIds, color);
//gadget.dashboard.setDataSet(getSelectedDataset(), ds);
}
// Checks the public dataset to update the selection status of all the points in the chart
// TODO: set the color according to the ds color
function updateSelectedPoints() {
if(chart1 == null)
return;
chart1.showLoading();
// select or unselect all the points in the chart to change the way they look
var ds = gadget.dashboard.getDataSet(getSelectedDataset());
if (ds === undefined || ds === null) {
return;
}
var colorIndexArray = ds.getColoredIndexArray();
// color selected points
for (var i=0, len=colorIndexArray.length; i<len; i++){
var point = chart1.get("p" + colorIndexArray[i][0]); // id is [0]
if (point !== null) {
colorChartPoint(point, colorIndexArray[i][1] ); // color is [1]
}
}
chart1.redraw();
chart1.hideLoading();
//gadget.dashboard.setDataSet(getSelectedDataset(), ds);
}
// Colors a selected point on chart by the color name
function colorChartPoint(point, colorName) {
if (colorName === "") {
colorName = "unselect";
}
point.update({color: MARKER_COLOR[colorName], marker: {fillColor: MARKER_COLOR[colorName]}}, false);
}
// colors chart point and writes it to dataset
function setPointColor(point, colorName) {
//debugLog("setPointColor(" + colorName + ")");
if (colorName === "unselect") {
colorName = "";
}
colorChartPoint(point, colorName);
// write to dataset
setTimeout( function() {
var dsName = getCurrentDatasetName();
var ds = gadget.dashboard.getDataSet(dsName);
ds.setIndexesColor( [ getPointId(point) ], colorName);
//gadget.dashboard.setDataSet(dsName, newDataSetList);
}, 1 );
}
// Zooms the viewport to point by writing CelestialCoordinate to public variable
function zoomToPoint(point) {
// get the cc of the point
// write cc to public variable
var cc = getPointCc(point);
if (cc !== null && cc !== undefined) {
gadget.dashboard.trigger("centerOfCoordinatesChanged",cc);
}
}
function getPointColor(point) {
var ds = gadget.dashboard.getDataSet(getCurrentDatasetName());
return ds.getColorByIndex(getPointId(point));
}
function getPointId(point) {
return point.id.substr(1);
}
function getPointCc(point) {
var ds = gadget.dashboard.getDataSet(getCurrentDatasetName());
return ds.getCelestialCoordByIndex(getPointId(point));
}
function plotDataset(args) {
// TODO: verify the necessary args were passed
var xCol = args.xAxis;
var yCol = args.yAxis;
var ds = args.dataset;
var graphData = [];
var dsData = ds.toJSON();
for (i=0,len=dsData.length; i<len; i++) {
var xVal = parseFloat(dsData[i][xCol]);
var yVal = parseFloat(dsData[i][yCol]);
// each point has unique id so a pointer to point can be had by chart.get(id)
var id = "p" + dsData[i]["db_id"];
if (xVal !== NaN && yVal !== NaN){
graphData.push( {
id: id,
x: xVal,
y: yVal,
color: DEFAULT_MARKER_COLOR,
marker: {
// symbol: DEFAULT_MARKER_SHAPE,
// radius: 2,
fillColor: DEFAULT_MARKER_COLOR
}
});
}
}
if (chart1 !== null && chart1 !== undefined) {
chart1.destroy();
}
displayPlot({graphData:graphData, title:ds.getId(), xAxis:args.xAxis, yAxis:args.yAxis, seriesName:args.yAxis + " vs " + args.xAxis });
}
function displayPlot(args) {
$(document).ready(function() {
chart1 = new Highcharts.Chart({
chart: {
renderTo: 'divChart1',
defaultSeriesType: 'scatter',
zoomType: 'xy',
events : {
selection: function(event) {
// check if the zoom or select radio is checked
// also, only select if there is an xAxis property in event (allows reset zoom)
if (!isRadioZoom() && ("xAxis" in event)) {
event.preventDefault();
setSelectedByMinMax(SERIES_NAME, event.xAxis[0].min, event.xAxis[0].max, event.yAxis[0].min, event.yAxis[0].max);
}
}
}
},
credits: {
enabled: false
},
title: {
text: args.title
},
loading: {
showDuration: 0,
hideDuration: 0
},
xAxis: {
title: {
enabled: false,
text: args.xAxis
},
reversed: _axisInverted.x,
startOnTick: true,
endOnTick: true,
showLastLabel: true
},
yAxis: {
title: {
text: args.yAxis
},
reversed: _axisInverted.y
},
tooltip: {
formatter: function() {
// EVALUATED ON CHART DRAW, NOT ON MOUSEOVER
if (isVerboseInfo()) {
return getVerboseInfo(this.point.id);
} else {
return args.yAxis + ': ' + this.y + '<br/>' + args.xAxis + ': ' + this.x;
}
}
},
plotOptions: {
scatter: {
animation: false,
color: DEFAULT_MARKER_COLOR,
//cursor: 'pointer',
id: SERIES_NAME
}
},
series: [{
name: args.seriesName,
data: args.graphData,
point: {
events: {
click: function(event) {
if (!(event.ctrlKey || event.metaKey)) { // check windows ctrl and mac meta
// color point
var selectedMarkerColor = getSelectionMarkerColor();
if (getPointColor(this) !== selectedMarkerColor) {
setPointColor(this, selectedMarkerColor);
} else {
setPointColor(this, "");
}
chart1.redraw();
} else { // zoom to point
zoomToPoint(this);
}
}
}
}
}]
});
});
getField('divChart1').style.height = PLOT_HEIGHT + "px";
// colors already selected points
updateSelectedPoints();
showVisualization(true);
}
// TODO: This should remove the unselected points from the plot
toggleViewUnselected = function() {
}
// HELPER
function getVerboseInfo(pointId) {
if (pointId === "") {
return "no info";
}
var info = [];
ds = gadget.dashboard.getDataSet(getCurrentDatasetName());
rec = ds.getRecordByIndex(pointId.substr(1)); // substr chops the 'p' off the point id
for (var prop in rec) {
if (!(rec[prop] instanceof Function)) {
info.push(prop + ": " + rec[prop] + "<br/>");
}
}
return info.join("");
}
// returns the color name in the selection color dropdown
function getSelectionMarkerColor() {
return colorText = getSelectedOption("selSelectionColor");
}
// returns the value in the selection color dropdown as an 'rgba(r,g,b,a)' string for chart
function getSelectionMarkerRgba() {
return MARKER_COLOR[getSelectionMarkerColor()];
}
function isViewUnselected(view) {
return getField('ckViewUnselected').checked;
}
function showVisualization(show) {
if (show) {
getField('divChart1').style.display = "block";
}
else {
getField('divChart1').style.display = "hidden";
}
gadget.resize();
}
function xmlStringToDoc(text){
if (window.DOMParser){
parser=new DOMParser();
xmlDoc=parser.parseFromString(text,"text/xml");
}
else // Internet Explorer
{
xmlDoc=new ActiveXObject("Microsoft.XMLDOM");
xmlDoc.async="false";
xmlDoc.loadXML(text);
}
// TODO: test to verify its created
return xmlDoc;
}
function getRadioValue(radio) {
if (!radio) {
return "";
}
for (var i=0, len=radio.length; i<len; i++) {
if (radio[i].checked) {
return radio[i].value;
}
}
return "";
}
function isRadioZoom() {
return (getRadioValue(document.formSelectZoom.radSelectZoom) === "zoom");
}
function isVerboseInfo() {
return getField("ckVerboseInfo").checked;
}
// accepts name of select box
// returns the value in the select box, or ""
function getSelectedOption(select) {
var selName = getField(select);
if (selName.length > 0){
return selName.options[selName.selectedIndex].value;
} else {
return "";
}
}
// Accepts the name of a select object, and an array of strings
// replaces the options with the array of strings
function setSelectOptions(selectName, options) {
var select = getField(selectName);
if (select === null) {
return;
}
// save old selected option so maybe it can be reselected
var selectedOption = getSelectedOption(selectName);
// Default. First option selected
if (selectedOption == "")
selectedOption == options[0];
// clear options
select.length = 0;
// add options
for (var i=0, len=options.length; i<len; i++) {
// if oldOption is in the list, then select it
select.add(new Option(options[i], options[i], false, (selectedOption == options[i])), null);
}
if(select.onchange)
select.onchange();
}
function getCurrentDatasetName() {
// TODO: get it from this._currentDatasetName
return getSelectedDataset();
}
function getField(field) {
if (!(field in _myFields) || (_myFields[field] === null)) {
_myFields[field] = document.getElementById(field);
}
return _myFields[field];
}
//activePointsList = gadget.addProperty("activePointsList");
//skyViewPointsList = gadget.addProperty("skyViewPointsList");
// PUBLIC METHODS
my.invertX = function() {
var anchor = document.getElementById('butXInvert');
if (anchor.value === ">") {
anchor.value = "<";
} else {
anchor.value = ">";
}
_axisInverted.x = !_axisInverted.x;
if (chart1 !== null && chart1 !== undefined) {
this.doPlot();
}
}
my.invertY = function() {
var anchor = document.getElementById('butYInvert');
if (anchor.value === "^") {
anchor.value = "v";
} else {
anchor.value = "^";
}
_axisInverted.y = !_axisInverted.y;
if (chart1 !== null && chart1 !== undefined) {
this.doPlot();
}
}
// Populates the X/Y axis dropdowns with values from the chosen datasets column names
// If no dataset is chosen, then it blanks them
my.populateXYSelect = function(datasetName) {
// TODO get dataset names
var columnNames = [""];
if (datasetName !== "") {
var ds = gadget.dashboard.getDataSet(datasetName);
columnNames = ds.getNonDBColumns();
}
setSelectOptions("selXAxis", columnNames);
setSelectOptions("selYAxis", columnNames);
}
my.doPlot = function() {
this._currentDatasetName = getSelectedDataset();
var datasetName = this._currentDatasetName;
var xAxisName = getSelectedXAxis();
var yAxisName = getSelectedYAxis();
//TODO: confirm dataset actually exists with this name
if (datasetName === "" || xAxisName === "" || yAxisName === "") {
alert("Choose a dataset, x axis, and y axis");
return;
}
var ds = gadget.dashboard.getDataSet(datasetName);
plotDataset({ dataset:ds,
xAxis: getSelectedXAxis(),
yAxis: getSelectedYAxis()
});
// TODO: need to unregister the previous dataset!
}
my.setSelectOptions = function(sel, array) {
setSelectOptions(sel, array);
}
my.redrawChart = function() {
if (chart1 !== null && chart1 !== undefined) {
chart1.redraw();
}
}
return my;
}
</script>
</head>
<body onLoad="init();">
<div id="content">
<div id="divSelectDataset" style="width: 100%;">
<table><tbody>
<tr>
<td> Dataset: <select id="selDatasetName" onchange="pl.populateXYSelect(this.options[this.selectedIndex].value);"></select>
</td>
<td>
X Axis: <input id="butXInvert" type="button" title="Invert X Axis" value=">" onclick="pl.invertX();"></input> <select id="selXAxis"></select>
</td>
<td>
Y Axis: <input id="butYInvert" type="button" title="Invert Y Axis" value="^" onclick="pl.invertY();"></input> <select id="selYAxis"></select>
</td>
</tr>
<tr>
<td>
<input id="btDoPlot" onclick="pl.doPlot();" type="button" value="Plot"/>
</td>
</tr>
</tbody></table>
</div>
<div id="divPlotToolbar" style="padding-left: 5px; display: inline-table;">
<form name="formSelectZoom">
<div id="divSelectZoom">
Selection Color: <select id="selSelectionColor">
</select>
<input type="radio" id="radSelectZoom" name="radSelectZoom" value="select" checked="checked" /><label for="radSelect">Select</label>
<input type="radio" id="radSelectZoom" name="radSelectZoom" value="zoom" /><label for="radZoom">Zoom</label>
Info: <input type='checkbox' id='ckVerboseInfo' onclick="pl.redrawChart();" value="0"/>
</div>
</form>
</div>
<div id="divChart1">
</div>
</div>
</body>
</html>