diff --git a/frontend/images/link.png b/frontend/images/link.png
new file mode 100644
index 0000000..25eacb7
Binary files /dev/null and b/frontend/images/link.png differ
diff --git a/frontend/images/save.png b/frontend/images/save.png
new file mode 100644
index 0000000..99d532e
Binary files /dev/null and b/frontend/images/save.png differ
diff --git a/frontend/index.html b/frontend/index.html
index 304ee3e..cdd85e0 100644
--- a/frontend/index.html
+++ b/frontend/index.html
@@ -17,10 +17,8 @@
-
-
-
+
@@ -37,7 +35,13 @@
+
+
+
+
+
+
@@ -122,15 +130,17 @@
Hier können Sie einen neuen Kanal erstellen
-
+
Hier können Sie demnächst öffentliche Kanäle abonnieren.
+
+
diff --git a/frontend/javascripts/frontend.js b/frontend/javascripts/frontend.js
index fbcf568..33de892 100644
--- a/frontend/javascripts/frontend.js
+++ b/frontend/javascripts/frontend.js
@@ -24,65 +24,82 @@
* volkszaehler.org. If not, see .
*/
-/*
- * Frontend related functions
- */
-
/**
* Initialize the WUI (Web User Interface)
*/
vz.wui.init = function() {
- // start auto refresh timer
- window.setInterval(this.refresh, 3000);
-
// initialize dropdown accordion
$('#accordion h3').click(function() {
$(this).next().toggle('fast');
return false;
}).next().hide();
- // make buttons fancy
+ // buttons
$('button, input[type=button],[type=image]').button();
+ $('button[name=options-save]').click(function() { vz.options.save(); });
+ $('#permalink').click(function() { // TODO add uuids
+ var u = window.location.protocol + '//' +
+ window.location.host +
+ window.location.pathname +
+ '?from=' + vz.options.plot.xaxis.min +
+ '&to=' + vz.options.plot.xaxis.max;
+
+ window.location = u;
+ });
+ $('button[name=entity-add]').click(function() { $('#entity-add').dialog('open'); });
+ $('#entity-subscribe input[type=button]').click(function() {
+ try {
+ vz.uuids.add($('#entity-subscribe input[type=text]').val());
+ $('#entity-subscribe input[type=text]').val('');
+ $('#entity-add').dialog('close');
+ vz.entities.loadDetails();
+ }
+ catch (exception) {
+ vz.wui.dialogs.exception(exception);
+ }
+ });
// bind plot actions
$('#controls button').click(this.handleControls);
$('#controls').buttonset();
// tuple resolution
- vz.options.tuples = Math.round($('#flot').width() / 3);
+ vz.options.tuples = Math.round($('#flot').width() / 4);
$('#tuples').val(vz.options.tuples).change(function() {
vz.options.tuples = $(this).val();
vz.entities.loadData();
});
+ // backend address
$('#backend-url')
.val(vz.options.backendUrl)
.change(function() {
vz.options.backendUrl = $(this).val();
});
+ // auto refresh
$('#refresh')
.attr('checked', vz.options.refresh)
.change(function() {
- vz.options.refresh = $(this).val();
+ if ($(this).attr('checked')) {
+ vz.options.refresh = true;
+ vz.wui.refreshTimeout = window.setTimeout(vz.wui.refresh, vz.options.refreshInterval);
+ }
+ else {
+ vz.options.refresh = false;
+ window.clearTimeout(vz.wui.refreshTimeout);
+ }
});
// plot rendering
- $('#render-lines')
- .attr('checked', vz.options.plot.series.lines.show)
- .change(function() {
- vz.options.plot.series.lines.show = $(this).attr('checked');
- vz.options.plot.series.points.show = !$(this).attr('checked');
+ $('#render-lines').attr('checked', (vz.options.render == 'lines'));
+ $('#render-points').attr('checked', (vz.options.render == 'points'));
+ $('input[name=render][type=radio]').change(function() {
+ if ($(this).attr('checked')) {
+ vz.options.render = $(this).val();
vz.drawPlot();
- });
-
- $('#render-points')
- .attr('checked', vz.options.plot.series.points.show)
- .change(function() {
- vz.options.plot.series.lines.show = !$(this).attr('checked');
- vz.options.plot.series.points.show = $(this).attr('checked');
- vz.drawPlot();
- });
+ }
+ });
};
/**
@@ -93,28 +110,10 @@ vz.wui.dialogs.init = function() {
$('#entity-add.dialog').dialog({
autoOpen: false,
title: 'Kanal hinzufügen',
- width: 600,
+ width: 530,
resizable: false
});
$('#entity-add.dialog > div').tabs();
-
- // open entity dialogs
- $('button[name=entity-add]').click(function() {
- $('#entity-add').dialog('open');
- });
-
- // subscribe UUID
- $('#entity-subscribe input[type=button]').click(function() {
- try {
- vz.uuids.add($('#entity-subscribe input[type=text]').val());
- $('#entity-subscribe input[type=text]').val('');
- $('#entity-add').dialog('close');
- vz.entities.loadDetails();
- }
- catch (exception) {
- vz.exceptionDialog(exception);
- }
- });
};
/**
@@ -153,12 +152,13 @@ vz.wui.initEvents = function() {
* Refresh plot with new data
*/
vz.wui.refresh = function() {
- 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();
- }
+ 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();
+
+ // schedule next refresh
+ this.refreshTimeout = window.setTimeout(vz.wui.refresh, vz.options.refreshInterval);
};
/**
@@ -251,7 +251,6 @@ vz.entities.loadDetails = function() {
/**
* Create nested entity list
- * @param data
*/
vz.entities.show = function() {
var i = 0;
@@ -373,10 +372,18 @@ vz.entities.loadData = function() {
});
};
+vz.wui.updateHeadline = function() {
+ var from = $.plot.formatDate(new Date(vz.options.plot.xaxis.min + vz.options.timezoneOffset), vz.options.plot.xaxis.timeformat, vz.options.plot.xaxis.monthNames);
+ var to = $.plot.formatDate(new Date(vz.options.plot.xaxis.max + vz.options.timezoneOffset), vz.options.plot.xaxis.timeformat, vz.options.plot.xaxis.monthNames);
+ $('#title').text(from + ' - ' + to);
+}
+
/**
* Draws plot to container
*/
vz.drawPlot = function () {
+ vz.wui.updateHeadline();
+
var data = new Array;
vz.entities.each(function(entity, parent) {
if (entity.active && entity.data && entity.data.count > 0) {
@@ -395,6 +402,9 @@ vz.drawPlot = function () {
$('#overlay').empty();
}
+ vz.options.plot.series.lines.show = (vz.options.render == 'lines');
+ vz.options.plot.series.points.show = (vz.options.render == 'points');
+
vz.plot = $.plot($('#flot'), data, vz.options.plot);
};
@@ -402,22 +412,47 @@ 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',
+ url: this.options.backendUrl + '/' + context + '/' + identifier + '.json',
dataType: 'json',
data: data,
error: function(xhr) {
json = JSON.parse(xhr.responseText);
- vz.wui.dialogs.error(xhr.statusText, json.exception.message, xhr.status); // TODO throw exception?
+ vz.wui.dialogs.error(xhr.statusText, json.exception.message, xhr.status); // TODO or throw exception?
}
});
};
+/**
+ * Parse URL GET parameters
+ */
+vz.parseUrlVars = function() {
+ var vars = $.getUrlVars();
+ for (var key in vars) {
+ if (vars.hasOwnProperty(key)) {
+ switch (key) {
+ case 'uuid': // add optional uuid from url
+ try {
+ vz.uuids.add(vars[key]);
+ } catch (exception) {
+ vz.wui.dialogs.exception(exception);
+ }
+ break;
+ case 'from':
+ vz.options.plot.xaxis.min = parseInt(vars[key]);
+ break;
+ case 'to':
+ vz.options.plot.xaxis.max = parseInt(vars[key]);
+ break;
+ case 'debug':
+ $.getScript('javascripts/firebug-lite.js');
+ break;
+ }
+ }
+ }
+};
+
/**
* Load definitions from backend
*/
diff --git a/frontend/javascripts/init.js b/frontend/javascripts/init.js
index 1424058..7b216ed 100644
--- a/frontend/javascripts/init.js
+++ b/frontend/javascripts/init.js
@@ -50,43 +50,29 @@ var vz = {
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() {
- $(window).unload(function() {
- vz.uuids.save();
- vz.options.save();
- });
-
$(window).resize(function() {
vz.options.tuples = Math.round($('#flot').width() / 3);
$('#tuples').val(vz.options.tuples);
vz.drawPlot();
});
- // parse uuids & options from cookie
- vz.uuids.load();
- vz.options.load();
-
// initialize user interface
vz.wui.init();
vz.wui.initEvents();
vz.wui.dialogs.init();
-
- // add optional uuid from url
- if($.getUrlVar('uuid')) {
- vz.uuids.add($.getUrlVar('uuid'));
- }
-
- if (vz.uuids.length == 0) {
- $('#addUUID').dialog('open');
- }
-
+
+ // parse uuids & options from cookie
vz.definitions.load();
+ vz.uuids.load();
+ vz.options.load();
+ vz.parseUrlVars();
+
+ if (vz.uuids.length == 0) {
+ $('#entity-add').dialog('open');
+ }
+
vz.entities.loadDetails();
});
diff --git a/frontend/javascripts/options.js b/frontend/javascripts/options.js
index 062088f..8f24726 100644
--- a/frontend/javascripts/options.js
+++ b/frontend/javascripts/options.js
@@ -26,10 +26,13 @@
// default time interval to show
vz.options = {
+ language: 'de',
backendUrl: '../backend/index.php',
tuples: 300,
+ render: 'lines',
refresh: false,
- defaultInterval: 1*24*60*60*1000, // 1 day
+ refreshInterval: 5*1000, // 5 secs
+ defaultInterval: 24*60*60*1000, // 1 day
timezoneOffset: -(new Date().getTimezoneOffset() * 60*1000) // TODO add option with timezone dropdown
};
@@ -69,20 +72,12 @@ vz.options.plot = {
grid: {
hoverable: true,
autoHighlight: false
- },
- zoom: {
- interactive: true,
- frameRate: null
- },
- pan: {
- interactive: false,
- frameRate: 20
}
}
vz.options.save = function() {
for (var key in this) {
- if (typeof this[key] == 'string' || typeof this[key] == 'number') {
+ if (this.hasOwnProperty(key) && typeof this[key] != 'function' && typeof this[key] != 'object' && typeof this[key] != 'undefined') {
$.setCookie('vz_' + key, this[key]);
}
}
@@ -90,10 +85,18 @@ vz.options.save = function() {
vz.options.load = function() {
for (var key in this) {
- if (typeof this[key] == 'string' || typeof this[key] == 'number') {
- var value = $.getCookie('vz_' + key);
- if (typeof value != undefined) {
- this[key] = (typeof this[key] == 'number') ? parseFloat(value) : value;
+ var value = $.getCookie('vz_' + key);
+ if (typeof value != 'undefined') {
+ switch(typeof this[key]) {
+ case 'string':
+ this[key] = value;
+ break;
+ case 'number':
+ this[key] = Number(value);
+ break;
+ case 'boolean':
+ this[key] = (value == 'true');
+ break;
}
}
}
diff --git a/frontend/javascripts/uuid.js b/frontend/javascripts/uuid.js
index eb56737..b343b22 100644
--- a/frontend/javascripts/uuid.js
+++ b/frontend/javascripts/uuid.js
@@ -31,9 +31,10 @@ vz.uuids.add = function(uuid) {
if (this.validate(uuid)) {
if (!this.contains(uuid)) {
this.push(uuid);
+ this.save();
}
else {
- throw new Exception('UUIDException', 'UUID already added');
+ throw new Exception('UUIDException', 'UUID already added: ' + uuid);
}
}
else {
@@ -47,6 +48,7 @@ vz.uuids.add = function(uuid) {
vz.uuids.remove = function(uuid) {
if (this.contains(uuid)) {
this.splice(this.indexOf(uuid), 1); // remove uuid from array
+ this.save();
}
else {
throw new Exception('UUIDException', 'UUID unkown: ' + uuid);
diff --git a/frontend/stylesheets/jquery.ui.custom.css b/frontend/stylesheets/jquery.ui.custom.css
index bf85b58..8350839 100644
--- a/frontend/stylesheets/jquery.ui.custom.css
+++ b/frontend/stylesheets/jquery.ui.custom.css
@@ -1,9 +1,21 @@
-/* jQuery UI */
+/* jQuery UI customizations */
input.ui-button {
padding: 0.1em 0.5em;
}
.ui-button-text-only .ui-button-text {
- padding:0.1em 0.5em;
+ padding: 0.1em 0.5em;
+}
+
+.ui-error .ui-widget-header {
+ background-image: url("../images/ui-bg_gloss-wave_35_red_500x100.png");
+}
+
+#entity-add.ui-dialog-content {
+ padding: 0.3em 0 0;
+}
+
+.ui-tabs .ui-tabs-nav li a {
+ padding: 0.1em 0.7em;
}
diff --git a/frontend/stylesheets/style.css b/frontend/stylesheets/style.css
index a911338..13414e9 100644
--- a/frontend/stylesheets/style.css
+++ b/frontend/stylesheets/style.css
@@ -137,7 +137,15 @@ tbody tr td {
width: 20px;
}
-/* additional theming for user interface */
-.ui-error .ui-widget-header {
- background-image: url("../images/ui-bg_gloss-wave_35_red_500x100.png");
+#headline {
+ margin-bottom: 15px;
+}
+
+#title {
+ margin: 0.2em;
+ float: left;
+}
+
+#permalink {
+ float: right;
}