Node dragging works, no saving yet

master
James Gao 2014-11-01 13:15:19 -07:00
rodzic c678d10e56
commit fae13053ee
5 zmienionych plików z 114 dodań i 39 usunięć

Wyświetl plik

@ -52,5 +52,12 @@ body {
stroke-width:1px; stroke-width:1px;
} }
.profile-line.dot:hover { .profile-line.dot:hover {
stroke-width:5px; stroke-width:3px;
}
#profile-node-info {
float:left;
position:absolute;
display:none;
width:200px;
} }

Wyświetl plik

@ -34,8 +34,8 @@ var tempgraph = (function(module) {
this.x = d3.time.scale().range([0, this.width]); this.x = d3.time.scale().range([0, this.width]);
this.y = d3.scale.linear().range([this.height, 0]); this.y = d3.scale.linear().range([this.height, 0]);
this.zoom = d3.behavior.zoom().on("zoom", this.draw.bind(this)) this.zoom = d3.behavior.zoom(this.obj).on("zoom", this.draw.bind(this))
.on("zoomend", this.recenter.bind(this)); .on("zoomend", this.recenter.bind(this, .2));
if (options.show_axes === undefined || options.show_axes) { if (options.show_axes === undefined || options.show_axes) {
this.x_axis = d3.svg.axis().scale(this.x).orient("bottom") this.x_axis = d3.svg.axis().scale(this.x).orient("bottom")
@ -71,7 +71,6 @@ var tempgraph = (function(module) {
}; };
module.Graph.prototype.plot = function(data, className, marker) { module.Graph.prototype.plot = function(data, className, marker) {
this.x.domain(d3.extent(data, function(d) { return d.x; })); this.x.domain(d3.extent(data, function(d) { return d.x; }));
this.y.domain(d3.extent(data, function(d) { return d.y; }));
this.zoom.x(this.x); this.zoom.x(this.x);
var line = d3.svg.line() var line = d3.svg.line()
@ -97,7 +96,8 @@ var tempgraph = (function(module) {
this.lines[className] = {line:line, data:data, marker:marker}; this.lines[className] = {line:line, data:data, marker:marker};
this.svg.call(this.zoom); this.svg.call(this.zoom);
this.draw(); this.draw();
return line; this.recenter(.2);
return this.lines[className];
} }
module.Graph.prototype.draw = function() { module.Graph.prototype.draw = function() {
this.svg.select("g.x.axis").call(this.x_axis); this.svg.select("g.x.axis").call(this.x_axis);
@ -130,15 +130,24 @@ var tempgraph = (function(module) {
this.height = height; this.height = height;
this.draw(); this.draw();
} }
module.Graph.prototype.recenter = function() { module.Graph.prototype.recenter = function(margin) {
//Argument margin gives the fraction of (max - min) to add to the margin
//Defaults to 0
var extent = [], data, valid, var extent = [], data, valid,
low = this.x.domain()[0], high=this.x.domain()[1]; low = this.x.domain()[0], high=this.x.domain()[1];
for (var name in this.lines) { for (var name in this.lines) {
data = this.lines[name].data; data = this.lines[name].data;
valid = data.filter(function(d) { return low <= d.x && d.x <= high; }) valid = data.filter(function(d) { return low <= d.x && d.x <= high; })
extent = extent.concat(valid); extent = extent.concat(valid);
} }
this.y.domain(d3.extent(extent, function(d) {return d.y;})); extent = d3.extent(extent, function(d){return d.y});
if (margin > 0) {
var range = extent[1]-extent[0];
extent[0] -= margin*range;
extent[1] += margin*range;
}
this.y.domain(extent);
this.draw(); this.draw();
} }
module.Graph.prototype.update = function(className, data) { module.Graph.prototype.update = function(className, data) {

Wyświetl plik

@ -3,9 +3,7 @@ var tempgraph = (function(module) {
this.temperature = initial; this.temperature = initial;
this.profile = null; this.profile = null;
//default to F //default to F
this.scalefunc = module.temp_to_F; this.scalefunc = new module.TempScale("F");
this.temp_suffix = "°F"
this.temp_prefix = ""
this.graph = new module.Graph(); this.graph = new module.Graph();
this._mapped = this.temperature.map(this._map_temp.bind(this)); this._mapped = this.temperature.map(this._map_temp.bind(this));
@ -16,13 +14,11 @@ var tempgraph = (function(module) {
} }
module.Monitor.prototype.updateTemp = function(data) { module.Monitor.prototype.updateTemp = function(data) {
var now = new Date(data.time*1000.); var now = new Date(data.time*1000.);
var temp = this.scalefunc(data.temp); var temp = this.scalefunc.scale(data.temp);
var nowstr = module.format_time(now); var nowstr = module.format_time(now);
var tempstr = Math.round(temp*100) / 100;
$("#current_time").text(nowstr); $("#current_time").text(nowstr);
$("#current_temp").text(this.temp_prefix+tempstr+this.temp_suffix); $("#current_temp").text(this.scalefunc.print(Math.round(temp*100) / 100));
if (this.profile) { if (this.profile) {
var finish = module.format_time(this.profile.time_finish(now)); var finish = module.format_time(this.profile.time_finish(now));
@ -42,11 +38,9 @@ var tempgraph = (function(module) {
} }
//If incoming sample is higher or lower than the ylims, expand that as well //If incoming sample is higher or lower than the ylims, expand that as well
var ylims = this.graph.y.domain(), range = 2*(ylims[1] - ylims[0]); var ylims = this.graph.y.domain();
if (temp >= ylims[1]) { if (temp >= ylims[1] || temp <= ylims[0]) {
this.graph.y.domain([ylims[0], ylims[0]+range]); this.graph.recenter(.2);
} else if (temp <= ylims[0]) {
this.graph.y.domain([ylims[1]-range, ylims[1]]);
} }
this.graph.update("temperature", this._mapped); this.graph.update("temperature", this._mapped);
} }
@ -86,22 +80,16 @@ var tempgraph = (function(module) {
$("a#temp_scale_cone").parent().removeClass("active"); $("a#temp_scale_cone").parent().removeClass("active");
if (scale == "C") { if (scale == "C") {
$("li a#temp_scale_C").parent().addClass("active"); $("li a#temp_scale_C").parent().addClass("active");
this.scalefunc = module.temp_to_C; this.scalefunc = new module.TempScale("C");
this.graph.ylabel("Temperature (°C)") this.graph.ylabel("Temperature (°C)")
this.temp_suffix = "°C";
this.temp_prefix = "";
} else if (scale == "F") { } else if (scale == "F") {
$("li a#temp_scale_F").parent().addClass("active"); $("li a#temp_scale_F").parent().addClass("active");
this.scalefunc = module.temp_to_F; this.scalefunc = new module.TempScale("F");
this.graph.ylabel("Temperature (°F)") this.graph.ylabel("Temperature (°F)")
this.temp_suffix = "°F";
this.temp_prefix = "";
} else if (scale == "cone") { } else if (scale == "cone") {
$("li a#temp_scale_cone").parent().addClass("active"); $("li a#temp_scale_cone").parent().addClass("active");
this.scalefunc = module.temp_to_cone; this.scalefunc = new module.TempScale("cone");
this.graph.ylabel("Temperature (Δ)"); this.graph.ylabel("Temperature (Δ)");
this.temp_prefix = "Δ";
this.temp_suffix = "";
} }
this._mapped = this.temperature.map(this._map_temp.bind(this)); this._mapped = this.temperature.map(this._map_temp.bind(this));
this.graph.y.domain(d3.extent(this._mapped, function(d) { return d.y; })); this.graph.y.domain(d3.extent(this._mapped, function(d) { return d.y; }));
@ -113,7 +101,7 @@ var tempgraph = (function(module) {
} }
module.Monitor.prototype._map_temp = function(d) { module.Monitor.prototype._map_temp = function(d) {
return {x:new Date(d.time*1000), y:this.scalefunc(d.temp)}; return {x:new Date(d.time*1000), y:this.scalefunc.scale(d.temp)};
} }
module.Monitor.prototype.setState = function(name) { module.Monitor.prototype.setState = function(name) {
@ -193,11 +181,19 @@ var tempgraph = (function(module) {
$("input").attr("disabled", "disabled"); $("input").attr("disabled", "disabled");
} }
module.temp_to_C = function(temp) { return temp; }
module.temp_to_F = function(temp) { module.TempScale = function(name) {
return temp * 9 / 5 + 32; if (name == "C") {
this.scale = function(t) { return t;};
this.inverse = function(t) { return t;};
this.print = function(t) { return t+"°C"}
} else if (name == "F") {
this.scale = function(temp) { return temp * 9 / 5 + 32; }
this.inverse = function(temp) { return (temp - 32) * 5 / 9;}
this.print = function(t) { return t+"°F"}
}
} }
module.temp_to_cone = function(temp) { module.TempScale.C_to_cone = function(temp) {
var cones = [600,614,635,683,717,747,792,804,838,852,884,894,900,923,955,984,999,1046,1060,1101,1120,1137,1154,1162,1168,1186,1196,1222,1240,1263,1280,1305,1315,1326,1346] var cones = [600,614,635,683,717,747,792,804,838,852,884,894,900,923,955,984,999,1046,1060,1101,1120,1137,1154,1162,1168,1186,1196,1222,1240,1263,1280,1305,1315,1326,1346]
var names = []; var names = [];
for (var i = -22; i < 0; i++) { for (var i = -22; i < 0; i++) {

Wyświetl plik

@ -25,6 +25,7 @@ var tempgraph = (function(module) {
module.Profile.prototype.setScale = function(scale) { module.Profile.prototype.setScale = function(scale) {
this.scalefunc = scale; this.scalefunc = scale;
this.update();
} }
module.Profile.prototype.setupGraph = function() { module.Profile.prototype.setupGraph = function() {
//immediately view range from 10 min before to end time of profile //immediately view range from 10 min before to end time of profile
@ -37,16 +38,35 @@ var tempgraph = (function(module) {
.attr("class", "profile-pane") .attr("class", "profile-pane")
.attr("height", this.graph.height) .attr("height", this.graph.height)
this.graph.zoom.on("zoom.profile", this.update.bind(this));
this.line = this.graph.plot(this._schedule(), "profile-line", true); this.line = this.graph.plot(this._schedule(), "profile-line", true);
this.update(); this.update();
//events
this.drag = d3.behavior.drag().origin(function(d) {
return {x:this.graph.x(d.x), y:this.graph.y(d.y)};
}.bind(this)).on("dragstart", function(d) {
d3.event.sourceEvent.stopPropagation();
this._node = this._findNode(d);
}.bind(this)).on("drag", this.dragNode.bind(this));
this.line.marker.call(this.drag);
var hide_info = function() {
this.hide_timeout = setTimeout(function() { $("#profile-node-info").hide(); }, 250);
};
this.graph.zoom.on("zoom.profile", this.update.bind(this));
this.line.marker.on("mouseover", this.hoverNode.bind(this));
this.line.marker.on("mouseout", hide_info.bind(this));
$("#profile-node-info").on("mouseout.profile", hide_info.bind(this));
$("#profile-node-info").on("mouseover.profile", function() {
clearTimeout(this.hide_timeout);
}.bind(this));
} }
module.Profile.prototype._schedule = function() { module.Profile.prototype._schedule = function() {
var start_time = this.time_start instanceof Date ? this.time_start : new Date(); var start_time = this.time_start instanceof Date ? this.time_start : new Date();
var schedule = []; var schedule = [];
for (var i = 0; i < this.schedule.length; i++) { for (var i = 0; i < this.schedule.length; i++) {
var time = new Date(start_time.getTime() + this.schedule[i][0]*1000); var time = new Date(start_time.getTime() + this.schedule[i][0]*1000);
var temp = this.scalefunc(this.schedule[i][1]); var temp = this.scalefunc.scale(this.schedule[i][1]);
schedule.push({x:time, y:temp}); schedule.push({x:time, y:temp});
} }
return schedule; return schedule;
@ -64,15 +84,42 @@ var tempgraph = (function(module) {
this.scalefunc = scale; this.scalefunc = scale;
this.update(); this.update();
} }
module.Profile.prototype._findNode = function(d) {
var time, temp,
start_time = this.time_start instanceof Date ? this.time_start : new Date();
for (var i = 0; i < this.schedule.length; i++) {
time = new Date((start_time.getTime() + this.schedule[i][0]*1000));
temp = this.schedule[i][1];
//if time is within 10 seconds and temperature matches exactly
if ((time - d.x) < 10000 && d.y == this.scalefunc.scale(temp))
return i;
}
}
module.Profile.prototype.addNode = function() { module.Profile.prototype.addNode = function() {
} }
module.Profile.prototype.delNode = function() { module.Profile.prototype.delNode = function() {
} }
module.Profile.prototype.dragNode = function() { module.Profile.prototype.dragNode = function(d) {
var time = this.graph.x.invert(d3.event.x);
var temp = this.graph.y.invert(d3.event.y);
var start_time = this.time_start instanceof Date ? this.time_start : new Date();
this.schedule[this._node][0] = (time - start_time) / 1000;
this.schedule[this._node][1] = this.scalefunc.inverse(temp);
this.update();
}
module.Profile.prototype.hoverNode = function(d) {
clearTimeout(this.hide_timeout);
var node = this._findNode(d);
$("#profile-node-info")
.css('left', this.graph.x(d.x)+80)
.css('top', this.graph.y(d.y)+50)
.show();
$("#profile-node-info div.name").text("Set point "+(node+1));
$("#profile-node-info input.temp").val(this.scalefunc.scale(this.schedule[node][1]));
$("#profile-node-info input.time");
} }
return module; return module;

Wyświetl plik

@ -23,7 +23,6 @@
<![endif]--> <![endif]-->
</head> </head>
<body> <body>
<div class="navbar navbar-default navbar-fixed-top" role="navigation"> <div class="navbar navbar-default navbar-fixed-top" role="navigation">
<div class="container-fluid"> <div class="container-fluid">
<div class="navbar-header"> <div class="navbar-header">
@ -61,8 +60,9 @@
<div class="row"> <div class="row">
<div class="col-sm-8 col-md-8 row-space"> <div class="col-sm-8 col-md-8 row-space">
<svg id="graph" class="row-space"></svg>
<svg id="graph" class="row-space"></svg>
<div class="btn-group btn-group-justified row-space"> <div class="btn-group btn-group-justified row-space">
<div class="btn-group"> <div class="btn-group">
<button id="stop_button" type="button" class="btn btn-primary disabled"><span class="glyphicon glyphicon-stop"></span> Off</button> <button id="stop_button" type="button" class="btn btn-primary disabled"><span class="glyphicon glyphicon-stop"></span> Off</button>
@ -109,6 +109,22 @@
</div> </div>
</div> </div>
<div id='profile-node-info' class='panel panel-info'>
<div class='panel-heading name'>
Set point
</div>
<div class='panel-body'>
<div class="input-group input-group-sm row-space">
<span class="input-group-addon">Time</span>
<input type="text" class="form-control time">
</div>
<div class="input-group input-group-sm">
<span class="input-group-addon">Temp</span>
<input type="text" class="form-control temp">
</div>
</div>
</div>
</div> <!-- /container --> </div> <!-- /container -->
<script src="js/jquery.min.js"></script> <script src="js/jquery.min.js"></script>