[collectd] [Patch 1/3] php-collection: New graph toolbox

Bruno Prémont bonbons at linux-vserver.org
Mon Apr 20 22:35:25 CEST 2009


This patch creates a new toolbox which can be show on a per-graph base
by clicking on a graph.

This box allows changing the displayed period of the selected graph
as well as toggle the logarithmic scale and legend details flags.

The graph reordering, refresh and delete tools have been moved from
right graph edge to this new toolbox.
---
 contrib/php-collection/browser.js |  217 ++++++++++++++++++++++++++-----------
 contrib/php-collection/index.php  |   33 +++++--
 2 files changed, 179 insertions(+), 71 deletions(-)

diff --git a/contrib/php-collection/browser.js b/contrib/php-collection/browser.js
index a343cba..376f025 100644
--- a/contrib/php-collection/browser.js
+++ b/contrib/php-collection/browser.js
@@ -35,6 +35,7 @@ function toggleDiv(divID) {
 			label.removeChild(label.childNodes[--childCnt]);
 		label.appendChild(document.createTextNode(label_txt));
 	}
+	GraphPositionToolbox(null);
 }
 
 var req = null;
@@ -319,58 +320,12 @@ function GraphDoAppend(host, plugin, pinst, type, tinst, timespan, tinyLegend, l
 		newGraph.setAttribute('class', 'graph');
 		newGraph.setAttribute('id', graph_id);
 		// Graph cell + graph
-		newDiv = document.createElement('div');
-		newDiv.setAttribute('class', 'graph_img');
 		newImg = document.createElement('img');
 		newImg.setAttribute('src', graph_src);
 		newImg.setAttribute('alt', graph_alt);
 		newImg.setAttribute('title', graph_title);
-		newDiv.appendChild(newImg);
-		newGraph.appendChild(newDiv);
-		// Graph tools
-		newDiv = document.createElement('div');
-		newDiv.setAttribute('class', 'graph_opts');
-		// - move up
-		newImg = document.createElement('img');
-		newImg.setAttribute('src', 'move-up.png');
-		newImg.setAttribute('alt', 'UP');
-		newImg.setAttribute('title', 'Move graph up');
-		newA = document.createElement('a');
-		newA.setAttribute('href', 'javascript:GraphMoveUp("'+graph_id+'")');
-		newA.appendChild(newImg);
-		newDiv.appendChild(newA);
-		newDiv.appendChild(document.createElement('br'));
-		// - refresh
-		newImg = document.createElement('img');
-		newImg.setAttribute('src', 'refresh.png');
-		newImg.setAttribute('alt', 'R');
-		newImg.setAttribute('title', 'Refresh graph');
-		newA = document.createElement('a');
-		newA.setAttribute('href', 'javascript:GraphRefresh("'+graph_id+'")');
-		newA.appendChild(newImg);
-		newDiv.appendChild(newA);
-		newDiv.appendChild(document.createElement('br'));
-		// - remove
-		newImg = document.createElement('img');
-		newImg.setAttribute('src', 'delete.png');
-		newImg.setAttribute('alt', 'RM');
-		newImg.setAttribute('title', 'Remove graph');
-		newA = document.createElement('a');
-		newA.setAttribute('href', 'javascript:GraphRemove("'+graph_id+'")');
-		newA.appendChild(newImg);
-		newDiv.appendChild(newA);
-		newDiv.appendChild(document.createElement('br'));
-		// - move down
-		newImg = document.createElement('img');
-		newImg.setAttribute('src', 'move-down.png');
-		newImg.setAttribute('alt', 'DN');
-		newImg.setAttribute('title', 'Move graph down');
-		newA = document.createElement('a');
-		newA.setAttribute('href', 'javascript:GraphMoveDown("'+graph_id+'")');
-		newA.appendChild(newImg);
-		newDiv.appendChild(newA);
-		newGraph.appendChild(newDiv);
-
+		newImg.setAttribute('onclick', 'GraphToggleTools("'+graph_id+'")');
+		newGraph.appendChild(newImg);
 		graphs.appendChild(newGraph);
 	}
 	document.getElementById('nograph').style.display = 'none';
@@ -389,32 +344,159 @@ function GraphDropAll() {
 	RefreshButtons();
 }
 
+function GraphToggleTools(graph) {
+	var graphId = document.getElementById('ge_graphid').value;
+	var ref_img = null;
+	if (graphId == graph || graph == '') {
+		ref_img = null;
+	} else {
+		var graphDiv = document.getElementById(graph);
+		var imgs     = graphDiv ? graphDiv.getElementsByTagName('img') : null;
+		var imgCnt   = imgs ? imgs.length : 0;
+		while (imgCnt > 0)
+			if (imgs[--imgCnt].parentNode.getAttribute('class') == 'graph')
+				ref_img = imgs[imgCnt];
+	}
+	if (ref_img) {
+		var ts_sel  =  document.getElementById('ge_timespan');
+		var src_url = ref_img.src;
+		var ge      = document.getElementById('ge');
+		// Fix field values
+		var ts = src_url.match(/&timespan=[^&]*/);
+		ts = ts ? ts[0].substr(10) : '';
+		document.getElementById('ge_graphid').value = graph;
+		document.getElementById('ge_tinylegend').checked = src_url.match(/&tinylegend=1/);
+		document.getElementById('ge_logarithmic').checked = src_url.match(/&logarithmic=1/);
+		for (i = 0; i < ts_sel.options.length; i++)
+			if (ts_sel.options[i].value == ts) {
+				ts_sel.selectedIndex = i;
+				break;
+			}
+		// show tools box and position it properly
+		ge.style.display = 'table';
+		GraphPositionToolbox(ref_img);
+	} else {
+		// hide tools box
+		document.getElementById('ge').style.display = 'none';
+		document.getElementById('ge_graphid').value = '';
+	}
+}
+
+function GraphPositionToolbox(ref_img) {
+	var ge      = document.getElementById('ge');
+	if (ge.style.display != 'none') {
+		var wl = 0; var wt = 0;
+		var x = ref_img;
+		if (ref_img == null) {
+			var graphDiv = document.getElementById(document.getElementById('ge_graphid').value);
+			var imgs     = graphDiv ? graphDiv.getElementsByTagName('img') : null;
+			var imgCnt   = imgs ? imgs.length : 0;
+			while (imgCnt > 0)
+				if (imgs[--imgCnt].parentNode.getAttribute('class') == 'graph')
+					ref_img = imgs[imgCnt];
+
+			if (ref_img == null) {
+				document.getElementById('ge_graphid').value = '';
+				ge.style.display = 'none';
+				return;
+			} else
+				x = ref_img;
+		}
+		while (x != null) {
+			wl += x.offsetLeft;
+			wt += x.offsetTop;
+			x = x.offsetParent;
+		}
+		ge.style.left    = (wl + (ref_img.offsetWidth - ge.offsetWidth) / 2)+'px';
+		ge.style.top     = (wt + (ref_img.offsetHeight - ge.offsetHeight) / 2)+'px';
+	}
+}
+
+function GraphRefreshAll() {
+	var imgs   = document.getElementById('graphs').getElementsByTagName('img');
+	var imgCnt = imgs.length;
+	var now    = new Date();
+	var newTS  = '&ts='+now.getTime();
+	while (imgCnt > 0)
+		if (imgs[--imgCnt].parentNode.getAttribute('class') == 'graph') {
+			var oldSrc = imgs[imgCnt].src;
+			var newSrc = oldSrc.replace(/&ts=[0-9]+/, newTS);
+			if (newSrc == oldSrc)
+				newSrc = newSrc + newTS;
+			imgs[imgCnt].setAttribute('src', newSrc);
+		}
+}
+
 function GraphRefresh(graph) {
+	var graphElement = null;
 	if (graph == null) {
-		var imgs   = document.getElementById('graphs').getElementsByTagName('img');
+		var graphId = document.getElementById('ge_graphid').value;
+		if (graphId != '')
+			graphElement = document.getElementById(graphId);
+	} else 
+		graphElement = document.getElementById(graph);
+	if (graphElement != null) {
+		var imgs = graphElement.getElementsByTagName('img');
 		var imgCnt = imgs.length;
-		var now    = new Date();
-		var newTS  = '&ts='+now.getTime();
 		while (imgCnt > 0)
-			if (imgs[--imgCnt].parentNode.getAttribute('class') == 'graph_img') {
+			if (imgs[--imgCnt].parentNode.getAttribute('class') == 'graph') {
+				var now    = new Date();
+				var newTS  = '&ts='+now.getTime();
 				var oldSrc = imgs[imgCnt].src;
 				var newSrc = oldSrc.replace(/&ts=[0-9]+/, newTS);
 				if (newSrc == oldSrc)
-					newSrc = newSrc + newTS;
+					newSrc = newSrc+newTS;
 				imgs[imgCnt].setAttribute('src', newSrc);
+				break;
 			}
-	} else if (document.getElementById(graph)) {
-		var imgs = document.getElementById(graph).getElementsByTagName('img');
+	}
+}
+
+function GraphAdjust(graph) {
+	var graphId = graph == null ? document.getElementById('ge_graphid').value : graph;
+	var graphElement = document.getElementById(graphId);
+	if (graphElement != null) {
+		var time_list   = document.getElementById('ge_timespan');
+		var timespan    = time_list.selectedIndex >= 0 ? time_list.options[time_list.selectedIndex].value : '';
+		var tinyLegend  = document.getElementById('ge_tinylegend').checked;
+		var logarithmic = document.getElementById('ge_logarithmic').checked
+		var imgs = graphElement.getElementsByTagName('img');
 		var imgCnt = imgs.length;
+		var ref_img     = null;
 		while (imgCnt > 0)
-			if (imgs[--imgCnt].parentNode.getAttribute('class') == 'graph_img') {
+			if (imgs[--imgCnt].parentNode.getAttribute('class') == 'graph') {
 				var now    = new Date();
 				var newTS  = '&ts='+now.getTime();
 				var oldSrc = imgs[imgCnt].src;
-				var newSrc = oldSrc.replace(/&ts=[0-9]+/, newTS);
+				var newSrc = oldSrc.replace(/&ts=[^&]*/, newTS);
 				if (newSrc == oldSrc)
 					newSrc = newSrc+newTS;
+				newSrc     = newSrc.replace(/&logarithmic=[^&]*/, '');
+				if (logarithmic)
+					newSrc += '&logarithmic=1';
+				newSrc     = newSrc.replace(/&tinylegend=[^&]*/, '');
+				if (tinyLegend)
+					newSrc += '&tinylegend=1';
+				newSrc     = newSrc.replace(/&timespan=[^&]*/, '');
+				if (timespan)
+					newSrc += '&timespan='+encodeURIComponent(timespan);
 				imgs[imgCnt].setAttribute('src', newSrc);
+
+				var myList = Array();
+				for (i = 0; i < graphList.length; i++)
+					if (graphList[i].substring(0, graphId.length) == graphId && graphList[i].charAt(graphId.length) == ' ') {
+						newSrc = graphList[i];
+						newSrc = newSrc.replace(/&logarithmic=[^&]*/, '');
+						newSrc = newSrc.replace(/&tinylegend=[^&]*/, '');
+						newSrc = newSrc.replace(/&timespan=[^&]*/, '');
+						newSrc = newSrc+(logarithmic ? '&logarithmic=1' : '')+(tinyLegend ? '&tinylegend=1' : '')+'&timespan='+encodeURIComponent(timespan);
+						myList.push(newSrc);
+						continue;
+					} else
+						myList.push(graphList[i]);
+				graphList = myList;
+				window.setTimeout("GraphPositionToolbox(null)", 10);
+				// GraphPositionToolbox(imgs[imgCnt]);
 				break;
 			}
 	}
@@ -422,15 +504,18 @@ function GraphRefresh(graph) {
 
 function GraphRemove(graph) {
 	var graphs = document.getElementById('graphs');
-	if (document.getElementById(graph)) {
-		graphs.removeChild(document.getElementById(graph));
+	var graphId = graph == null ? document.getElementById('ge_graphid').value : graph;
+	var graphElement = document.getElementById(graphId);
+	if (graphElement) {
+		GraphToggleTools('');
+		graphs.removeChild(graphElement);
 		RefreshButtons();
 		if (graphs.getElementsByTagName('div').length == 1)
 			document.getElementById('nograph').style.display = 'block';
 
 		var myList = Array();
 		for (i = 0; i < graphList.length; i++)
-			if (graphList[i].substring(0, graph.length) == graph && graphList[i].charAt(graph.length) == ' ')
+			if (graphList[i].substring(0, graphId.length) == graphId && graphList[i].charAt(graphId.length) == ' ')
 				continue;
 			else
 				myList.push(graphList[i]);
@@ -440,13 +525,14 @@ function GraphRemove(graph) {
 
 function GraphMoveUp(graph) {
 	var graphs    = document.getElementById('graphs');
+	var graphId   = graph == null ? document.getElementById('ge_graphid').value : graph;
 	var childCnt  = graphs.childNodes.length;
 	var prevGraph = null;
 	for (i = 0; i < childCnt; i++)
 		if (graphs.childNodes[i].nodeName == 'div' || graphs.childNodes[i].nodeName == 'DIV') {
 			if (graphs.childNodes[i].id == 'nograph') {
 				// Skip
-			} else if (graphs.childNodes[i].id == graph) {
+			} else if (graphs.childNodes[i].id == graphId) {
 				var myGraph = graphs.childNodes[i];
 				if (prevGraph) {
 					graphs.removeChild(myGraph);
@@ -457,7 +543,7 @@ function GraphMoveUp(graph) {
 				prevGraph = graphs.childNodes[i];
 		}
 	for (i = 0; i < graphList.length; i++)
-		if (graphList[i].substring(0, graph.length) == graph && graphList[i].charAt(graph.length) == ' ') {
+		if (graphList[i].substring(0, graphId.length) == graphId && graphList[i].charAt(graphId.length) == ' ') {
 			if (i > 0) {
 				var tmp = graphList[i-1];
 				graphList[i-1] = graphList[i];
@@ -465,10 +551,12 @@ function GraphMoveUp(graph) {
 			}
 			break;
 		}
+	GraphPositionToolbox(null);
 }
 
 function GraphMoveDown(graph) {
 	var graphs    = document.getElementById('graphs');
+	var graphId   = graph == null ? document.getElementById('ge_graphid').value : graph;
 	var childCnt  = graphs.childNodes.length;
 	var nextGraph = null;
 	var myGraph   = null;
@@ -476,7 +564,7 @@ function GraphMoveDown(graph) {
 		if (graphs.childNodes[i].nodeName == 'div' || graphs.childNodes[i].nodeName == 'DIV') {
 			if (graphs.childNodes[i].id == 'nograph') {
 				// Skip
-			} else if (graphs.childNodes[i].id == graph) {
+			} else if (graphs.childNodes[i].id == graphId) {
 				myGraph = graphs.childNodes[i];
 			} else if (myGraph) {
 				nextGraph = graphs.childNodes[i];
@@ -486,7 +574,7 @@ function GraphMoveDown(graph) {
 			}
 		}
 	for (i = 0; i < graphList.length; i++)
-		if (graphList[i].substring(0, graph.length) == graph && graphList[i].charAt(graph.length) == ' ') {
+		if (graphList[i].substring(0, graphId.length) == graphId && graphList[i].charAt(graphId.length) == ' ') {
 			if (i+1 < graphList.length) {
 				var tmp = graphList[i+1];
 				graphList[i+1] = graphList[i];
@@ -494,6 +582,7 @@ function GraphMoveDown(graph) {
 			}
 			break;
 		}
+	GraphPositionToolbox(null);
 }
 
 function GraphListFromCookie(lname) {
diff --git a/contrib/php-collection/index.php b/contrib/php-collection/index.php
index 1abf40d..837d261 100644
--- a/contrib/php-collection/index.php
+++ b/contrib/php-collection/index.php
@@ -66,7 +66,7 @@ function build_page() {
 		<style type="text/css">
 			body, html { background-color: #EEEEEE; color: #000000; }
 			h1 { text-align: center; }
-			div.body { margin: auto; width: <?php echo isset($config['rrd_width']) ? 125+(int)$config['rrd_width'] : 600; ?>px; background: #FFFFFF; border: 1px solid #DDDDDD; }
+			div.body { margin: auto; width: <?php echo isset($config['rrd_width']) ? 110+(int)$config['rrd_width'] : 600; ?>px; background: #FFFFFF; border: 1px solid #DDDDDD; }
 			p.error { color: #CC0000; margin: 0em; }
 			div.selector { margin: 0.5em 2em; }
 			div.selectorbox { padding: 5px; border: 1px solid #CCCCCC; background-color: #F8F8F8; }
@@ -77,11 +77,12 @@ function build_page() {
 			div.selectorbox table td.sc { padding: 0.5em 2em; text-align: center; }
 			a img { border: none; }
 			div.graphs { border-top: 1px solid #DDDDDD; padding: 5px; overflow: auto; }
-			div.graphs_t { display: table; }
-			div.graph { display: table-row; }
-			div.graph_img { display: table-cell; vertical-align: middle; text-align: right; }
-			div.graph_opts { display: table-cell; vertical-align: middle; text-align: center; line-height: 2em; }
-			select { width: 100%; }
+			div.graphs_t { position: relative; }
+			div.graph { text-align: right; }
+			div.selector select { width: 100%; }
+			table.toolbox { border: 1px solid #5500dd; padding: 0px; margin: 0px; background: #ffffff;}
+			table.toolbox td.c1 { vertical-align: middle; text-align: left; padding-left: 0.3em; padding-right: 1em; border-right: 1px solid #5500dd; }
+			table.toolbox td.c2 { vertical-align: middle; text-align: center; padding-left: 5px; padding-right: 5px; }
 		</style>
 		<script type="text/javascript">// <![CDATA[
 var dhtml_url = '<?php echo addslashes($url_base.basename($_SERVER['PHP_SELF'])); ?>';
@@ -137,7 +138,7 @@ var graph_url = '<?php echo addslashes($url_base.'graph.php'); ?>';
 				<tr>
 					<td class="sc" colspan="3"><input id="btnAdd"     name="btnAdd"     type="button" disabled="disabled" onclick="GraphAppend()" value="Add graph" />
 					<input id="btnClear"   name="btnClear"   type="button" disabled="disabled" onclick="GraphDropAll()" value="Remove all graphs" />
-					<input id="btnRefresh" name="btnRefresh" type="button" disabled="disabled" onclick="GraphRefresh(null)" value="Refresh all graphs" /></td>
+					<input id="btnRefresh" name="btnRefresh" type="button" disabled="disabled" onclick="GraphRefreshAll()" value="Refresh all graphs" /></td>
 				</tr>
 				<tr>
 					<td class="s1" rowspan="2">Graph list favorites:</td>
@@ -193,6 +194,24 @@ var graph_url = '<?php echo addslashes($url_base.'graph.php'); ?>';
 				echo '<p class="error">Config error: RRDTOOL ('.htmlspecialchars(RRDTOOL).') is not executable</p>';
 			?></div>
 		</div></div>
+		<input type="hidden" name="ge_graphid" id="ge_graphid" value="" />
+		<table id="ge" class="toolbox" style="position: absolute; display: none; " cellspacing="1" cellpadding="0">
+			<tr>
+				<td class="c1" rowspan="3"><select id="ge_timespan" name="ge_timespan" onchange="GraphAdjust(null)"><?php
+				foreach ($config['timespan'] as &$timespan)
+					printf("\t\t\t\t\t\t<option value=\"%s\">%s</option>\n", htmlspecialchars($timespan['name']), htmlspecialchars($timespan['label']));
+				?></select><br />
+				<label><input id="ge_logarithmic"  name="ge_logarithmic" type="checkbox" value="1" onchange="GraphAdjust(null)" /> Logarithmic scale</label><br />
+				<label><input id="ge_tinylegend"  name="ge_tinylegend" type="checkbox" value="1" onchange="GraphAdjust(null)" /> Minimal legend</label></td>
+				<td class="c2"><a href="javascript:GraphMoveUp(null)"><img src="move-up.png" alt="UP" title="Move graph up"/></a></td>
+			</tr>
+			<tr>
+				<td class="c2"><a href="javascript:GraphRefresh(null)"><img src="refresh.png" alt="R" title="Refresh graph"/></a>&nbsp;<a href="javascript:GraphRemove(null)"><img src="delete.png" alt="RM" title="Remove graph"/></a></td>
+			</tr>
+			<tr>
+				<td class="c2"><a href="javascript:GraphMoveDown(null)"><img src="move-down.png" alt="DN" title="Move graph down"/></a></td>
+			</tr>
+		</table>
 	</div></body>
 </html><?php
 }
-- 
1.6.0.6




More information about the collectd mailing list