QuickPlot-0.1.0.0: src/frontend/quickplot-client.js
/*
Known Bugs:
- vis plots don't work except Network plots
- vis plot becomes unresponsive once you click it
*/
"use strict";
/**************************************************************************************/
/* Connectivity */
/**************************************************************************************/
var websocketURL = "ws://127.0.0.1:8000/ws";
var websocket;
connectToWebsocket(websocketURL);
/**
* Connect to the QuickPlot websocket server
* @param websocketURL url of the websocket
*/
function connectToWebsocket(websocketURL) {
websocket = new WebSocket(websocketURL);
websocket.onmessage = function(event) {
var message = JSON.parse(event.data);
procedures[message.library][message.procedure](message.content);
};
websocket.onopen = function(event) {
log("Connected to QuickPlot");
};
websocket.onclose = function(event) {
log("What did you do?? D: ... Trying to reconnect");
setTimeout(function() { connectToWebsocket(websocketURL); }, 3000);
};
}
/**************************************************************************************/
/* Plotting */
/**************************************************************************************/
/* Global options ********************************************************************/
var LIBRARIES = {
vis : "vis",
plotly : "plotly"
}
var DEFAULT_PLOT_SETTINGS = {
sizeX : 12, // full width
sizeY : 6,
controlBoxHeight : 50
};
var gridStackOptions = {
cell_height: 80,
vertical_margin: 10,
always_show_resize_handle : true,
animate : true,
resizable : {
handles : 'e, se, s, w, nw, n, ne'
},
handle : ".control-box"
};
/* Plot Manager **********************************************************************/
/*
All the plots are inside #plots which is a gridstack. Which contains grid-stack-items
that are controlled by gridstack.js.
Here is a little visualization
-------------------------------------------------------------------------
| grid-stack (aka #plots div) |
| |---------------------------------------------------------| |
| | .grid-stack-item | |
| | |--------------------------------------------------| | |
| | | .grid-stack-item-content | | |
| | | |--------------------------------------------| | | |
| | | | .plot-box | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | |--------------------------------------------| | | |
| | | | Here could be controls | | | |
| | | |--------------------------------------------| | | |
| | |--------------------------------------------------| | |
| | | |
| |---------------------------------------------------------| |
| |
| |---------------------------------------------------------| |
| | another grid-stack-item | |
| | | |
| | ....... the same as above | |
| | | |
| |---------------------------------------------------------| |
| |
|-----------------------------------------------------------------------|
*/
// init gridstack
$("#plots").gridstack(gridStackOptions);
/**
* Handle resizing of the plots by putting an eventlistener on the grid-stack-item
*/
$("#plots").on("resizestop", function(event, ui) {
var gridStackItem = ui.element[0];
var plotBox = gridStackItem.childNodes[0].childNodes[0];
var newSize = {
width : plotBox.offsetWidth,
height : (plotBox.offsetHeight - DEFAULT_PLOT_SETTINGS.controlBoxHeight)
};
// e.g. plotly_name_id
switch (gridStackItem.id.split("_")[0]) {
case LIBRARIES.plotly:
Plotly.relayout(plotBox, newSize);
break;
}
});
var PlotManager = {
/**
* Add a new plot to the grid
* @param data json data
* @param library which library this plot uses
* @param name unique name (if not supplied it will be assigned)
*/
addPlot : function(data, library, name) {
// Give unique name
if (name === undefined) {
name = library + "_plot_" + (new Date()).getTime();
} else {
name = library + "_" + name;
}
var plot = new Plot(data, name);
$("#plots").data("gridstack").add_widget(plot.gridStackItem, 0, 0,
DEFAULT_PLOT_SETTINGS.sizeX, DEFAULT_PLOT_SETTINGS.sizeY, true);
$("#no-plots-message").hide();
debug("Added plot: \"" + plot.name + "\"");
return plot;
},
/**
* Removes a plot by id (which is also the name)
*/
removePlotById : function(id) {
var gridStackItem = $("#" + id).get(0);
$("#plots").data("gridstack").remove_widget(gridStackItem);
// TODO: Check if grid is empty then show no-plots-message
debug("Removed plot: \"" + id + "\"");
},
/**
* Removes all the plots
*/
removeAllPlots : function() {
$("#plots").data("gridstack").remove_all();
$("#no-plots-message").show();
debug("Removing all plots");
}
};
/**
* A plot.
*
* Every plot is inside a gridStackItem (to be specific inside gridStackItemContent)
* and has
* - unique name that looks like this "library_name"
*
* After you created the plot you still have to put it into the grid
*/
function Plot(data, name) {
this.name = name;
this.data = data;
this.gridStackItem = $("<div id='" + name + "'>");
this.gridStackItemContent = $("<div class='grid-stack-item-content'>");
this.plotBox = $("<div class='plot-box'>");
this.controlBox = $("<div class='control-box'>");
var removeButton = $("<button class='remove-plot-button'>");
this.controlBox.append(removeButton);
this.gridStackItemContent.append(this.plotBox);
this.gridStackItemContent.append(this.controlBox);
this.gridStackItem.append(this.gridStackItemContent);
removeButton.on("click", function() {
PlotManager.removePlotById(name);
});
this.getPlotBox = function() {
return this.plotBox.get(0);
};
debug("Created plot with name: " + name);
}
/**
* Map with all the local methods the server can execute
*/
var procedures = {
// For project speficic procedures
QuickPlot : {
/**
* Remove all plots from the DOM
*/
clear : function() {
debug("clear");
PlotManager.removeAllPlots();
}
},
plotly : {
/**
* Create a new plot and show it in the browser
*
* @param json data to plot
*/
newPlot : function(json) {
debug("plotly newPlot:", json);
var plot = PlotManager.addPlot(json.data, LIBRARIES.plotly);
Plotly.newPlot(plot.getPlotBox(), json.data, json.layout);
}
},
vis : {
/**
* Create a new plot and show it in the browser
* TODO: Only works for networks. Other plot types "Say that drawing is too limiting"
* @param json data to plot
*/
newPlot : function(json) {
var plot = PlotManager.addPlot(json.data, LIBRARIES.vis);
var dataset = new vis.DataSet(json.data);
switch (json.plotType) {
case "network":
var network = new vis.Network(plot.getPlotBox(), json.data, json.options);
break;
case "timeline":
var timeline = new vis.Timeline(plot.getPlotBox(), dataset, json.options);
break;
case "graph2d":
var graph2d = new vis.Graph2d(plot.getPlotBox(), dataset, json.options);
break;
case "graph3d":
var graph3d = new vis.Graph3d(plot.getPlotBox(), dataset, json.options);
break;
default:
debug("vis plottype doesn't exist");
}
debug("vis newPlot:", json);
}
}
};
/**************************************************************************************/
/* General */
/**************************************************************************************/
var show_debug_messages = true;
/**
* If show_debug_messages is true then message will be printed to console
* @param message message to print
*/
function debug(one, two, three, four) {
if (show_debug_messages) {
if (two === undefined) {
console.log("DEBUG || ", one);
} else if (three === undefined) {
console.log("DEBUG || ", one, two);
} else if (four === undefined){
console.log("DEBUG || ", one, two, three);
} else {
console.log("DEBUG || ", one, two, three, four);
}
}
}
/**
* Log to the user and show that message is from QuickPlot
*/
function log(message) {
console.log("QuickPlot: " + message);
}