diff --git a/frontend/index.html b/frontend/index.html index 009f70e..9c03afc 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -8,14 +8,12 @@ - - - - - - - - + + + + + + diff --git a/frontend/javascripts/backend.js b/frontend/javascripts/backend.js index f946e41..c618cb9 100644 --- a/frontend/javascripts/backend.js +++ b/frontend/javascripts/backend.js @@ -45,10 +45,7 @@ function showEntities() { var i = 0; eachRecursive(vz.entities, function(entity, parent) { entity.active = true; // TODO active by default or via backend property? - entity.color = vz.options.plot.seriesColors[i++ % vz.options.plot.seriesColors.length]; - - vz.plot.series[vz.plot.series.length] = vz.plot.seriesDefault; - + entity.color = vz.options.plot.colors[i++ % vz.options.plot.colors.length]; $('#entities tbody').append( $('') @@ -137,7 +134,7 @@ function showEntityDetails(entity) { }); } -function validateChannel(form) { +function validateEntity(form) { var entity = getDefinition(entities, form.type.value); $.each(entity.required, function(index, property) { @@ -184,57 +181,13 @@ function validateProperty(property, value) { } } -/** - * Get entities from backend - */ -function fetchEntities() { - $.getJSON(backend + '/capabilities/definition/entity.json', function(data) { - entities = data.definition.entity; - - // Add channel types to dropdown - $('#new select').empty(); - $.each(entities, function(index, entity) { - if (entity.model == 'Volkszaehler\\Model\\Channel') { - $('#new select').append(''); - } - }); - - // show related properties - $('#new select').trigger('change'); - }); -} - -/** - * Get properties from backend - */ -function fetchProperties() { - $.getJSON(backend + '/capabilities/definition/property.json', function(data) { - properties = data.definition.property; - - // show related properties - $('#new select').trigger('change'); - }); -} - -/** - * Get channels from controller - */ -function fetchChannels() { - $.getJSON(controller, function(data) { - channels = data; - - // add fetched channels to table - showChannels(); - }); -} - /** * Show from for new Channel * * @param type * @return */ -function showEntityForm(type) { +function getEntityDOM(type) { $('#properties').empty(); var entity = getDefinition(entities, type); @@ -255,66 +208,7 @@ function showEntityForm(type) { }); } -/** - * @param uuid - * @return - */ -function deleteChannel(uuid) { - $.getJSON(controller, { operation: 'delete', uuid: uuid }, function(data) { - channels = data; - showChannels(); - }); -} - -function addChannel(form) { - var uuid = false; - - if (validateChannel(form)) { - //if (uuid = addChannelBackend(form)) { - if (addChannelController(form, randomUUID)) { //uuid)) { - fetchChannels(); - return true; - } - else { - //removeChannelBackend(uuid); - alert('Error: adding channel to controller'); - } - /*} - else { - alert('Error: adding channel to backend'); - }*/ - } - else { - alert('Please correct your input'); - } -} - -function addChannelController(form, uuid) { - $.getJSON(controller, { operation: 'add', uuid: uuid, port: form.port.value, type: form.type.value }, function(data) { - channels = data; - showChannels(); - }); - - return true; // TODO -} - -function addChannelBackend(form) { - $.getJSON(backend + '/channel.json', { operation: 'add' }, function(data) { - - }); - - return true; // TODO -} - -function getDefinition(definition, type) { - for (var i in definition) { - if (definition[i].name == type) { - return definition[i]; - } - } -} - -function getPropertyForm(property) { +function getPropertyDOM(property) { switch (property.type) { case 'string': case 'float': diff --git a/frontend/javascripts/frontend.js b/frontend/javascripts/frontend.js index 06f06d2..3c57e66 100644 --- a/frontend/javascripts/frontend.js +++ b/frontend/javascripts/frontend.js @@ -32,6 +32,13 @@ * Initialize the WUI (Web User Interface) */ function initInterface() { + /*$('#content').resizable({ + alsoResize: $('#plot'), + //ghost: true, + //animate: true, + autoHide: true + });*/ + $('#accordion h3').click(function() { $(this).next().toggle('fast'); return false; @@ -54,13 +61,13 @@ function initInterface() { }); // bind controls - $('#move input').click(panPlot); + $('#move input').click(handleControl); // options - $('input[name=trendline]').attr('checked', vz.options.plot.seriesDefaults.trendline.show).change(function() { + /*$('input[name=trendline]').attr('checked', vz.options.plot.seriesDefaults.trendline.show).change(function() { vz.options.plot.seriesDefaults.trendline.show = $(this).attr('checked'); drawPlot(); - }); + });*/ $('input[name=backendUrl]').val(vz.options.backendUrl).change(function() { vz.options.backendUrl = $(this).val(); @@ -88,6 +95,9 @@ function initInterface() { */ function refreshWindow() { if ($('input[name=refresh]').attr('checked')) { + var delta = vz.to - vz.from; + vz.to = new Date().getTime(); // move plot + vz.from = vz.to - delta; // move plot loadData(); } } @@ -95,12 +105,13 @@ function refreshWindow() { /** * Move & zoom in the plotting area */ -function panPlot() { - delta = vz.to - vz.from; +function handleControl() { + var delta = vz.to - vz.from; + var middle = Math.round(vz.from + delta/2); switch(this.value) { case 'move_last': - vz.to = (new Date()).getTime(); + vz.to = new Date().getTime(); vz.from = vz.to - delta; break; @@ -114,15 +125,18 @@ function panPlot() { break; case 'zoom_reset': - // TODO + vz.from = middle - Math.floor(defaultInterval/2); + vz.to = middle + Math.ceil(defaultInterval/2); break; case 'zoom_in': - // TODO + vz.from += Math.floor(delta/4); + vz.to -= Math.ceil(delta/4); break; case 'zoom_out': - // TODO + vz.from -= delta; + vz.to += delta; break; case 'refresh': @@ -146,12 +160,19 @@ function loadData() { } function drawPlot() { - vz.plot.axes.xaxis.min = vz.from; - vz.plot.axes.xaxis.max = vz.to; - - vz.plot.replot({ - resetAxes: 'yaxis', - clear: true + var data = new Array; + eachRecursive(vz.entities, function(entity, parent) { + if (entity.active && entity.type != 'group') { + data.push({ + data: entity.data.tuples, + color: entity.color + }); + } }); + + vz.options.plot.xaxis.min = vz.from; + vz.options.plot.xaxis.max = vz.to; + + vz.plot = $.plot($('#plot'), data, vz.options.plot); } diff --git a/frontend/javascripts/init.js b/frontend/javascripts/init.js index c40eb46..40913fd 100644 --- a/frontend/javascripts/init.js +++ b/frontend/javascripts/init.js @@ -25,6 +25,9 @@ * along with volkszaehler.org. If not, see . */ +// default time interval to show +const defaultInterval = 7*24*60*60*1000; // 1 week + // volkszaehler.org object // holds all data and options for the frontend var vz = { @@ -35,57 +38,45 @@ var vz = { // parameter for json server to: new Date().getTime(), - //parameter for json server (last 24 hours) - from: new Date().getTime() - 24*60*60*1000, + //parameter for json server (last week) + from: new Date().getTime() - defaultInterval, options: { backendUrl: '../backend/index.php', tuples: 300, plot: { - series: [], - seriesColors: ['#83CAFF', '#7E0021', '#579D1C', '#FFD320', '#FF420E', '#004586', '#0084D1', '#C5000B', '#FF950E', '#4B1F6F', '#AECF00', '#314004'], - cursor: { - zoom: true, - showTooltip: true, - constrainZoomTo: 'x', - showVerticalLine: true - }, - seriesDefaults: { - lineWidth: 1, - showMarker: true, - showLine: false, - markerOptions: { - style: 'dash', - shadow: false, - size: 2 - }, - trendline: { + colors: ['#83CAFF', '#7E0021', '#579D1C', '#FFD320', '#FF420E', '#004586', '#0084D1', '#C5000B', '#FF950E', '#4B1F6F', '#AECF00', '#314004'], + series: { + lines: { show: false }, + points: { show: true, - shadow: false, - color: 'red' - } - }, - axes: { - yaxis: { - autoscale: true, - label: 'Leistung (Watt)', - tickOptions: { - formatString: '%.3f' - }, - labelRenderer: $.jqplot.CanvasAxisLabelRenderer - }, - xaxis: { - autoscale: true, - tickOptions: { - formatString: '%d.%m.%y %H:%M', - angle: -35 - }, - pad: 1, - renderer: $.jqplot.DateAxisRenderer, - rendererOptions: { - tickRenderer: $.jqplot.CanvasAxisTickRenderer + radius: 1, + //symbol: 'square' + symbol: function(ctx, x, y, radius, shadow) { + ctx.rect(x, y, radius, radius); } } + }, + legend: { show: false }, + xaxis: { + mode: 'time', + timeformat: '%d.%b %h:%M', + monthNames: ['Jan', 'Feb', 'Mär', 'Apr', 'Mai', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dez'] + }, + yaxis: { + min: 0, + zoomRange: [1, null] // dont scale yaxis when zooming + }, + selection: { mode: "x" }, + //crosshair: { mode: "x" }, + grid: { hoverable: true, autoHighlight: false }, + zoom: { + interactive: true, + frameRate: null + }, + pan: { + interactive: false, + frameRate: 20 } } } @@ -108,17 +99,34 @@ $(document).ready(function() { // start auto refresh timer window.setInterval(refreshWindow, 5000); - // initialize plot - vz.plot = $.jqplot('plot', vz.options.plot); + // handle zooming & panning + var plot = $('#plot'); + plot + .bind("plotselected", function (event, ranges) { + vz.from = Math.floor(ranges.xaxis.from); + vz.to = Math.ceil(ranges.xaxis.to); + loadData(); + }) + /*.bind('plotpan', function (event, plot) { + var axes = plot.getAxes(); + vz.from = Math.floor(axes.xaxis.min); + vz.to = Math.ceil(axes.xaxis.max); + vz.options.plot.yaxis.min = axes.yaxis.min; + vz.options.plot.yaxis.max = axes.yaxis.max; + })*/ + .bind('plotzoom', function (event, plot) { + var axes = plot.getAxes(); + vz.from = Math.floor(axes.xaxis.min); + vz.to = Math.ceil(axes.xaxis.max); + //vz.options.plot.yaxis.min = axes.yaxis.min; + //vz.options.plot.yaxis.max = axes.yaxis.max; + vz.options.plot.yaxis.min = 0; + vz.options.plot.yaxis.max = null; // autoscaling + loadData(); + }) + .bind('mouseup', function(event) { + loadData(); + }); - // zoom events - vz.plot.target.bind('jqplotZoom', function(event, gridpos, datapos, plot, cursor) { - //alert('zoomed'); // TODO refresh of data - }); - - vz.plot.target.bind('jqplotResetZoom', function(event, plot, cursor) { - alert('zoom reset'); // TODO refresh of data - }); - loadEntities(); }); diff --git a/frontend/stylesheets/style.css b/frontend/stylesheets/style.css index 16e5d38..defdb27 100644 --- a/frontend/stylesheets/style.css +++ b/frontend/stylesheets/style.css @@ -23,7 +23,7 @@ tbody tr td { } #content { - margin: 100px auto 20px; + margin: 50px auto 20px; width: 800px; padding: 10px; -moz-border-radius: 10px; @@ -31,6 +31,11 @@ tbody tr td { border: 1px solid black; } +#plot { + width: 800px; + height: 400px; +} + #footer { text-align: center; font-size: 0.7em;