1
0
Fork 0
fgdata/Phi/topics/Simulator/Properties.js

353 lines
9.6 KiB
JavaScript
Raw Normal View History

2015-01-25 12:02:20 +00:00
define([
2015-03-01 17:22:56 +00:00
'jquery', 'knockout', 'text!./Properties.html', 'flot', 'flotresize', 'flottime'
2015-01-25 12:02:20 +00:00
], function(jquery, ko, htmlString) {
2015-02-27 10:24:02 +00:00
2015-03-01 17:22:56 +00:00
function SampleSource(prop, source, params) {
params = params || {};
this.source = source;
this.path = prop.path;
this.maxSamples = params.maxSamples || 100;
this.samples = [];
this.sample = function(timeStamp) {
while (this.samples.length >= this.maxSamples) {
2015-03-01 17:22:56 +00:00
this.samples.shift();
}
2015-03-01 17:22:56 +00:00
this.samples.push([
timeStamp, this.source()
]);
}
}
function PropertySampler(params) {
params = params || {};
this.sources = {};
this.sampleInterval = params.sampleInterval || 1000;
this.start = function() {
this.update(++this.updateId);
return this;
}
this.stop = function() {
++this.updateId;
return this;
}
this.addSource = function(source) {
this.sources[source.path] = source;
return this;
}
this.removeSource = function(source) {
var s = this.sources[source].source;
2015-03-01 17:22:56 +00:00
delete this.sources[source];
return s;
2015-03-01 17:22:56 +00:00
}
this.containsSource = function(source) {
return source in this.sources;
}
this.updateId = 0;
this.update = function(id) {
if (id != this.updateId)
return;
var now = Date.now();
for ( var key in this.sources) {
this.sources[key].sample(now);
}
var self = this;
setTimeout(function() {
self.update(id);
}, self.sampleInterval);
}
}
function PropertyViewModel(propertyPlotter) {
2015-01-25 12:02:20 +00:00
var self = this;
2015-02-27 10:24:02 +00:00
function load() {
jquery.get('/json' + self.path, null, function(data) {
self.hasChildren = data.nChildren > 0;
2015-02-27 15:49:19 +00:00
self.index = data.index;
2015-03-01 17:22:56 +00:00
self.type = data.type;
if (typeof (data.value) != 'undefined') {
self.value(data.value);
self.hasValue = true;
} else {
self.value('');
self.hasValue = false;
}
2015-02-27 10:24:02 +00:00
var a = [];
if (data.children) {
2015-02-27 10:24:02 +00:00
data.children.forEach(function(prop) {
2015-03-01 17:22:56 +00:00
var p = new PropertyViewModel(propertyPlotter);
2015-02-27 10:24:02 +00:00
p.name = prop.name;
p.path = prop.path;
2015-02-27 15:49:19 +00:00
p.index = prop.index;
2015-03-01 17:22:56 +00:00
p.type = prop.type;
2015-02-27 10:24:02 +00:00
p.hasChildren = prop.nChildren > 0;
if (typeof (prop.value) != 'undefined') {
p.value(prop.value);
p.hasValue = true;
} else {
p.hasValue = false;
}
a.push(p);
});
self.children(a.sort(function(a, b) {
if (a.name == b.name) {
return a.index - b.index;
}
return a.name.localeCompare(b.name);
}));
}
});
}
self.name = '';
self.value = ko.observable('');
self.children = ko.observableArray([]);
self.index = 0;
self.path = '';
self.hasChildren = false;
self.hasValue = false;
2015-03-01 17:22:56 +00:00
self.type = '';
2015-02-27 10:24:02 +00:00
2015-03-01 17:22:56 +00:00
self.indexedName = ko.pureComputed(function() {
if (0 == self.index)
return self.name;
return self.name + "[" + self.index + "]";
2015-02-27 15:49:19 +00:00
});
self.isExpanded = ko.observable(false);
self.isExpanded.subscribe(function(newValue) {
if (newValue) {
load();
2015-02-27 10:24:02 +00:00
} else {
self.children.removeAll();
}
});
2015-03-01 17:22:56 +00:00
self.isPlottable = ko.pureComputed(function() {
return [
"double", "float", "int"
].indexOf(self.type) != -1;
});
2015-02-27 10:24:02 +00:00
self.toggle = function() {
if (self.hasChildren) {
self.isExpanded(!self.isExpanded());
} else {
load();
}
2015-02-27 10:24:02 +00:00
}
2015-03-01 17:22:56 +00:00
self.togglePlot = function(prop, evt) {
propertyPlotter.toggleProp(prop);
}
2015-02-27 10:24:02 +00:00
self.valueEdit = function(prop, evt) {
var inplaceEditor = jquery(jquery('#inplace-editor-template').html());
var elem = jquery(evt.target);
elem.hide();
elem.after(inplaceEditor);
inplaceEditor.val(elem.text());
inplaceEditor.focus();
function endEdit(val) {
inplaceEditor.remove();
elem.show();
if (typeof (val) === 'undefined')
return;
var val = val.trim();
elem.text(val);
jquery.post('/json' + self.path, JSON.stringify({
value : val
}));
}
inplaceEditor.on('keyup', function(evt) {
switch (evt.keyCode) {
case 27:
2015-02-27 10:24:02 +00:00
endEdit();
break;
case 13:
2015-02-27 10:24:02 +00:00
endEdit(inplaceEditor.val());
break;
}
});
inplaceEditor.blur(function() {
endEdit(inplaceEditor.val());
});
}
2015-01-25 12:02:20 +00:00
}
2015-02-27 10:24:02 +00:00
2015-01-25 12:02:20 +00:00
function ViewModel(params) {
var self = this;
2015-03-01 17:22:56 +00:00
self.root = new PropertyViewModel(self);
2015-02-27 10:24:02 +00:00
self.root.name = "root";
self.root.path = "/";
self.root.isExpanded(true);
self.properties = self.root.children;
2015-03-01 17:22:56 +00:00
self.startLabel = ko.pureComputed(function() {
return self.running() ? "Pause" : "Start";
});
self.startIcons = ko.pureComputed(function() {
return self.running() ? {
primary : 'ui-icon-pause'
} : {
primary : 'ui-icon-play'
};
});
self.settings = function() {
}
self.running = ko.observable(false);
self.startPause = function() {
if( self.running() ) {
self.stop();
} else {
self.start();
}
}
2015-03-01 17:22:56 +00:00
self.flotOptions = ko.observable({
xaxes : [
{
mode : "time"
}
],
yaxes : [
{
position : "right"
}, {
position : "left"
}
],
legend : {
2015-03-02 15:09:26 +00:00
show : true,
labelFormatter: null,
backgroundOpacity: 0.5,
sorted: "ascending",
2015-03-01 17:22:56 +00:00
},
grid : {
2015-03-02 15:09:26 +00:00
hoverable : false,
backgroundColor: { colors: ["#eee", "#888"] }
2015-03-01 17:22:56 +00:00
}
});
self.flotData = ko.observableArray([]);
self.graphHover = function() {
}
self.hasGraphItems = ko.pureComputed(function() {
return self.flotData().length > 0;
});
self.propertySampler = new PropertySampler({
sampleInterval : 100,
});
self.propertySampler.start();
self.running(true);
2015-03-01 17:22:56 +00:00
self.toggleProp = function(prop) {
if (self.propertySampler.containsSource(prop.path)) {
var obs = self.propertySampler.removeSource(prop.path);
ko.utils.knockprops.removeListener(prop.path, obs);
2015-03-01 17:22:56 +00:00
return;
}
var obs = ko.observable(0);
ko.utils.knockprops.addListener(prop.path, obs);
self.propertySampler.addSource(new SampleSource(prop, obs, {
maxSamples : 300,
}));
2015-03-01 17:22:56 +00:00
}
self.updateId = 0;
self.update = function(id) {
if (self.updateId != id)
return;
2015-03-01 17:22:56 +00:00
var sources = self.propertySampler.sources;
var data = [];
var i = 1;
for ( var key in sources) {
var source = sources[key];
data.push({
// color : 'rgb(192, 128, 0)',
data : source.samples,
2015-03-02 15:09:26 +00:00
label : key,
2015-03-01 17:22:56 +00:00
lines : {
show : true
},
points : {
show : false
},
bars : {
show : false
},
shadowSize : 0,
yaxis : i++,
2015-03-01 17:22:56 +00:00
});
}
self.flotData(data);
setTimeout(function() {
self.update(id);
2015-03-01 17:22:56 +00:00
}, 100);
}
self.start = function() {
self.update(++self.updateId);
self.propertySampler.start();
self.running(true);
}
self.stop = function() {
self.updateId++;
self.propertySampler.stop();
self.running(false);
}
self.start();
2015-01-25 12:02:20 +00:00
}
2015-03-01 17:22:56 +00:00
ViewModel.prototype.dispose = function() {
console.log("disposing pal");
this.propertySampler.stop();
this.updateId++;
2015-03-01 17:22:56 +00:00
}
2015-01-25 12:02:20 +00:00
// Return component definition
return {
viewModel : ViewModel,
template : htmlString
};
});