improved channel activation/selection

extracted options
This commit is contained in:
Steffen Vogel 2010-10-28 01:31:44 +02:00
parent 286b68635b
commit debae35550
8 changed files with 7675 additions and 134 deletions

View file

@ -24,26 +24,6 @@
* volkszaehler.org. If not, see <http://www.gnu.org/licenses/>.
*/
vz.definitions.load = function() {
$.ajax({
cache: true,
dataType: 'json',
url: vz.options.backendUrl + '/capabilities/definition/entity.json',
success: function(json) {
vz.definitions.entity = json.definition.entity;
}
});
$.ajax({
cache: true,
dataType: 'json',
url: vz.options.backendUrl + '/capabilities/definition/property.json',
success: function(json) {
vz.definitions.property = json.definition.property;
}
});
};
/**
* Entity constructor
* @todo add validation
@ -53,6 +33,7 @@ var Entity = function(json) {
switch(i) {
case 'children':
this.children = new Array;
this.children.each = vz.entities.each;
for (var j = 0; j < json.children.length; j++) {
var child = new Entity(json.children[j]);
this.children.push(child);
@ -65,6 +46,8 @@ var Entity = function(json) {
this[i] = json[i];
}
}
//this.definition = vz.definitions.get('entity', this.type);
};
/**
@ -160,4 +143,4 @@ Entity.prototype.each = function(cb, parent) {
this.children[i].each(cb, this); // call recursive
}
}
};
};

File diff suppressed because one or more lines are too long

View file

@ -41,10 +41,6 @@ vz.initInterface = function() {
// make buttons fancy
$('button, input[type=button]').button();
$('#backendUrl').val(vz.options.backendUrl).change(function() {
vz.options.backendUrl = $(this).val();
});
// tuple resolution
$('#tuples').val(vz.options.tuples).change(function() {
vz.options.tuples = $(this).val();
@ -67,8 +63,18 @@ vz.initInterface = function() {
vz.options.plot.series.points.show = $(this).attr('checked');
vz.drawPlot();
});
$('#timespan input').datepicker();
$('#backendUrl')
.val(vz.options.backendUrl)
.change(function() {
vz.options.backendUrl = $(this).val();
});
$('#refresh')
.attr('checked', vz.options.refresh)
.change(function() {
vz.options.refresh = $(this).val();
});
};
/**
@ -153,10 +159,10 @@ vz.bindEvents = function() {
* Refresh plot with new data
*/
vz.refresh = function() {
if ($('#refresh').attr('checked')) {
var delta = vz.options.plot.xaxis.min - vz.options.plot.xaxis.max;
vz.options.plot.xaxis.max = new Date().getTime(); // move plot
vz.options.plot.xaxis.min = vz.options.plot.xaxis.max - delta; // move plot
if (vz.options.refresh) {
var delta = vz.options.plot.xaxis.max - vz.options.plot.xaxis.min;
vz.options.plot.xaxis.max = new Date().getTime(); // move plot
vz.options.plot.xaxis.min = vz.options.plot.xaxis.max - delta; // move plot
vz.entities.loadData();
}
};
@ -184,8 +190,8 @@ vz.handleControls = function () {
break;
case 'zoom_reset':
vz.options.plot.xaxis.min = middle - defaultInterval/2;
vz.options.plot.xaxis.max = middle + defaultInterval/2;
vz.options.plot.xaxis.min = middle - vz.options.defaultInterval/2;
vz.options.plot.xaxis.max = middle + vz.options.defaultInterval/2;
break;
case 'zoom_in':
@ -216,13 +222,9 @@ vz.handleControls = function () {
* Get all entity information from backend
*/
vz.entities.loadDetails = function() {
vz.entities.clear();
this.clear();
vz.uuids.each(function(index, value) {
vz.load('entity', value, {}, waitAsync(function(json) {
if (json.exception) {
alert(exception.message);
return false;
}
vz.entities.push(new Entity(json.entity));
}, vz.entities.show, 'information'));
});
@ -234,30 +236,37 @@ vz.entities.loadDetails = function() {
*/
vz.entities.show = function() {
$('#entities tbody').empty();
var i = 0;
vz.entities.each(function(entity, parent) {
entity.color = vz.options.plot.colors[i++ % vz.options.plot.colors.length];
entity.active = (entity.active) ? entity.active : true;
var row = $('<tr>')
.addClass((parent) ? 'child-of-entity-' + parent.uuid : '')
.attr('id', 'entity-' + entity.uuid)
.append($('<td>')
.addClass('visibility')
.css('background-color', entity.color)
.css('width', 19)
.append($('<input>')
.attr('type', 'checkbox')
.attr('checked', entity.active)
.bind('change', entity, function(event) {
event.data.active = $(this).attr('checked');
var state = $(this).attr('checked');
event.data.active = state;
if (entity.type == 'group') {
entity.children.each(function(entity) {
$('#entity-' + entity.uuid + ' input[type=checkbox]').attr('checked', state);
entity.active = state;
});
}
vz.drawPlot();
})
)
)
.append($('<td>')
.css('width', 20)
)
.append($('<td>').addClass('expander'))
.append($('<td>')
.append($('<span>')
.text(entity.title)
@ -265,18 +274,18 @@ vz.entities.show = function() {
.addClass((entity.type == 'group') ? 'group' : 'channel')
)
)
.append($('<td>').text(entity.type))
.append($('<td>')) // min
.append($('<td>')) // max
.append($('<td>')) // avg
.append($('<td>') // operations
.append($('<td>').text(entity.type)) // channel type
.append($('<td>').addClass('min')) // min
.append($('<td>').addClass('max')) // max
.append($('<td>').addClass('average')) // avg
.append($('<td>') // operations
.addClass('ops')
/*.append($('<input>')
.append($('<input>')
.attr('type', 'image')
.attr('src', 'images/information.png')
.attr('alt', 'details')
.bind('click', entity, function(event) { event.data.showDetails(); })
)*/
)
);
if (parent == null) {
@ -308,8 +317,8 @@ vz.entities.show = function() {
* Overwritten each iterator for entity array
*/
vz.entities.each = function(cb) {
for (var i = 0; i < vz.entities.length; i++) {
vz.entities[i].each(cb);
for (var i = 0; i < this.length; i++) {
this[i].each(cb);
}
}
@ -317,9 +326,9 @@ vz.entities.each = function(cb) {
* Load json data from the backend
*/
vz.entities.loadData = function() {
$('#plot').html('<div class="plotcenter"><img src="images/loading.gif" alt="loading..." /><p>Loading...</p></div>');
vz.entities.each(function(entity, parent) {
if (entity.active && entity.type != 'group') {
//$('#plot').html('<div class="plotcenter"><img src="images/loading.gif" alt="loading..." /><p>Loading...</p></div>');
this.each(function(entity, parent) {
if (entity.active && entity.type != 'group') { // TODO add group data aggregation
vz.load('data', entity.uuid,
{
from: Math.floor(vz.options.plot.xaxis.min),
@ -328,6 +337,18 @@ vz.entities.loadData = function() {
},
waitAsync(function(json) {
entity.data = json.data;
// update entity table
// TODO add units
if (entity.data.min && entity.data.max && entity.data.min) {
$('#entity-' + entity.uuid + ' .min')
.text(entity.data.min.value)
.attr('title', $.plot.formatDate(new Date(entity.data.min.timestamp), vz.options.plot.xaxis.timeformat, vz.options.plot.xaxis.monthNames));
$('#entity-' + entity.uuid + ' .max')
.text(entity.data.max.value)
.attr('title', $.plot.formatDate(new Date(entity.data.max.timestamp), vz.options.plot.xaxis.timeformat, vz.options.plot.xaxis.monthNames));
$('#entity-' + entity.uuid + ' .average').text(entity.data.average);
}
}, vz.drawPlot, 'data')
);
}
@ -356,7 +377,14 @@ vz.drawPlot = function () {
}
};
/**
* Universal helper for backend ajax requests with error handling
*/
vz.load = function(context, identifier, data, success) {
$.getUrlVars().each(function (key, value) { // TODO parse only once
data[key] = value;
});
$.ajax({
success: success,
url: vz.options.backendUrl + '/' + context + '/' + identifier + '.json',
@ -364,11 +392,43 @@ vz.load = function(context, identifier, data, success) {
data: data,
error: function(xhr) {
json = JSON.parse(xhr.responseText);
vz.errorDialog(xhr.statusText, json.exception.message, xhr.status);
vz.errorDialog(xhr.statusText, json.exception.message, xhr.status); // TODO error vs. exception
}
});
};
/**
* Load definitions from backend
*/
vz.definitions.load = function() {
$.ajax({
cache: true,
dataType: 'json',
url: vz.options.backendUrl + '/capabilities/definition/entity.json',
success: function(json) {
vz.definitions.entity = json.definition.entity
}
});
$.ajax({
cache: true,
dataType: 'json',
url: vz.options.backendUrl + '/capabilities/definition/property.json',
success: function(json) {
vz.definitions.property = json.definition.property
}
});
};
vz.definitions.get = function(section, iname) {
for (var i in vz.definitions[section]) {
alert(vz.definitions[section][i].name);
if (vz.definitions[section][i].name == iname) {
return definition;
}
}
}
/*
* Error & Exception handling
*/
@ -379,11 +439,18 @@ vz.errorDialog = function(error, description, code) {
}
$('<div>')
.addClass('error')
.append($('<span>').text(description))
.dialog({
title: error,
width: 450
width: 450,
dialogClass: 'ui-error',
resizable: false,
modal: true,
buttons: {
Ok: function() {
$( this ).dialog( "close" );
}
}
});
};
@ -391,7 +458,7 @@ vz.exceptionDialog = function(exception) {
vz.errorDialog(exception.type, exception.message, exception.code);
};
var Exception(type, message, code) {
var Exception = function(type, message, code) {
return {
type: type,
message: message,

View file

@ -25,12 +25,8 @@
* along with volkszaehler.org. If not, see <http://www.gnu.org/licenses/>.
*/
// default time interval to show
const defaultInterval = 1*24*60*60*1000; // 1 day
// volkszaehler.org object
// holds all data, options and functions for the frontend
// acts like a namespace (we dont want to pollute the global one)
// volkszaehler.org namespace (holds all data, options and functions for the frontend)
// we dont want to pollute the global namespace
var vz = {
// entity information & properties
entities: new Array,
@ -38,71 +34,34 @@ var vz = {
// known UUIDs in the browser
uuids: new Array,
// plot including data
plot: {
// data for plot
data: new Array,
// container for flot instance
flot: { }
},
// flot instance
plot: { },
// definitions of entities & properties
// for validation, translation etc..
definitions: { },
options: {
backendUrl: '../backend/index.php',
tuples: 300,
plot: {
colors: ['#83CAFF', '#7E0021', '#579D1C', '#FFD320', '#FF420E', '#004586', '#0084D1', '#C5000B', '#FF950E', '#4B1F6F', '#AECF00', '#314004'],
series: {
lines: { show: true },
shadowSize: 0,
points: {
show: false,
radius: 1,
//symbol: 'square'
symbol: function(ctx, x, y, radius, shadow) {
ctx.lineWidth = 1;
ctx.strokeRect(x-0.5, y-0.5, 1, 1);
}
}
},
legend: { show: false },
xaxis: {
mode: 'time',
max: new Date().getTime(), // timeinterval to request
min: new Date().getTime() - defaultInterval,
timeformat: '%d.%b %h:%M',
monthNames: ['Jan', 'Feb', 'Mär', 'Apr', 'Mai', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dez']
},
yaxis: { },
selection: { mode: 'x' },
//crosshair: { mode: 'x' },
grid: { hoverable: true, autoHighlight: false },
zoom: {
interactive: true,
frameRate: null
},
pan: {
interactive: false,
frameRate: 20
}
}
}
// options loaded from cookies in options.js
options: { }
};
// check for debugging & load firebug
if ($.getUrlVar('debug')) {
$.getScript('javascripts/firebug-lite.js');
}
// executed on document loaded complete
// this is where it all starts...
$(document).ready(function() {
// parse uuids & options from cookie
vz.uuids.load();
vz.options.load();
// initialize user interface
vz.initInterface();
vz.initDialogs();
vz.bindEvents();
// parse uuids from cookie
vz.uuids.parseCookie();
// add optional uuid from url
if($.getUrlVar('uuid')) {
vz.uuids.add($.getUrlVar('uuid'));
@ -118,3 +77,8 @@ $(document).ready(function() {
vz.definitions.load();
vz.entities.loadDetails();
});
$(window).unload(function() {
vz.uuids.save();
vz.options.save();
});

View file

@ -35,7 +35,6 @@ $.extend( {
window.location.href.indexOf('?') + 1).split('&');
for (var i = 0; i < hashes.length; i++) {
hash = hashes[i].split('=');
vars.push(hash[0]);
vars[hash[0]] = hash[1];
}
return vars;

View file

@ -84,6 +84,7 @@ vz.options.load = function() {
for (var key in this) {
if (typeof this[key] == 'string' || typeof this[key] == 'number') {
this[key] = $.getCookie('vz_' + key);
//console.log('loaded option', key, this[key]);
}
}
};

View file

@ -24,17 +24,6 @@
* volkszaehler.org. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* Read UUIDs from cookie and add them to the array
*/
vz.uuids.parseCookie = function() {
if ($.getCookie('vz_uuids')) {
$.each(JSON.parse($.getCookie('vz_uuids')), function(index, uuid) {
vz.uuids.push(uuid);
});
}
};
/**
* Add given UUID and update cookie
*/
@ -42,7 +31,6 @@ vz.uuids.add = function(uuid) {
if (vz.uuids.validate(uuid)) {
if (!vz.uuids.contains(uuid)) {
vz.uuids.push(uuid);
$.setCookie('vz_uuids', JSON.stringify(vz.uuids));
}
else {
throw new Exception('UUIDException', 'UUID already added');
@ -57,10 +45,8 @@ vz.uuids.add = function(uuid) {
* Remove UUID and update cookie
*/
vz.uuids.remove = function(uuid) {
console.log(vz.uuids.contains(uuid));
if (vz.uuids.contains(uuid)) {
vz.uuids.splice(this.indexOf(uuid), 1); // remove uuid from array
$.setCookie('vz_uuids', JSON.stringify(vz.uuids));
vz.uuids.remove(uuid); // remove uuid from array
}
else {
throw new Exception('UUIDException', 'UUID unkown: ' + uuid);
@ -73,3 +59,22 @@ vz.uuids.remove = function(uuid) {
vz.uuids.validate = function(uuid) {
return uuid.match(/^[0-9a-zA-Z]{8}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{12}$/);
};
/**
* Save uuids as cookie
*/
vz.uuids.save = function() {
$.setCookie('vz_uuids', vz.uuids.join(';'));
};
/**
* Load uuids from cookie
*/
vz.uuids.load = function() {
var cookie = $.getCookie('vz_uuids');
if (cookie) {
cookie.split(';').each(function(index, uuid) {
vz.uuids.add(uuid);
});
}
};

View file

@ -121,6 +121,14 @@ tbody tr td {
text-align: right;
}
.visibility {
width: 18px;
}
.expander {
width: 20px;
}
.plotcenter {
display: block;
margin: auto;