2 * Copyright (C) 2009 Bruno Prémont <bonbons AT linux-vserver.org>
4 * This program is free software; you can redistribute it and/or modify it under
5 * the terms of the GNU General Public License as published by the Free Software
6 * Foundation; only version 2 of the License is applicable.
8 * This program is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
10 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
13 * You should have received a copy of the GNU General Public License along with
14 * this program; if not, write to the Free Software Foundation, Inc.,
15 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 // Toggle visibility of a div
19 function toggleDiv(divID) {
20 var div = document.getElementById(divID);
21 var label = document.getElementById(divID+'_sw');
24 if (div.style.display == 'none') {
25 div.style.display = 'block';
28 div.style.display = 'none';
32 if (label_txt && label) {
33 var childCnt = label.childNodes.length;
35 label.removeChild(label.childNodes[--childCnt]);
36 label.appendChild(document.createTextNode(label_txt));
42 // DHTML helper code to asynchronous loading of content
43 function loadXMLDoc(url, query) {
44 if (window.XMLHttpRequest) {
45 req = new XMLHttpRequest();
46 req.onreadystatechange = processReqChange;
47 req.open('POST', url, true);
48 req.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
50 } else if (window.ActiveXObject) {
51 req = new ActiveXObject("Microsoft.XMLHTTP");
53 req.onreadystatechange = processReqChange;
54 req.open('POST', url, true);
55 req.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
61 // DHTML new-content dispatcher
62 function processReqChange(evt) {
63 if (req.readyState == 4) {
64 if (req.status == 200) {
65 var response = req.responseXML.documentElement;
66 var method = response.getElementsByTagName('method')[0].firstChild.data;
67 var result = response.getElementsByTagName('result')[0];
69 eval(method + '(result)');
74 // Update contents of a <select> drop-down list
75 function refillSelect(options, select) {
79 var childCnt = select.childNodes.length;
80 var oldValue = select.selectedIndex > 0 ? select.options[select.selectedIndex].value : '/';
82 select.removeChild(select.childNodes[--childCnt]);
84 var optCnt = options ? options.length : 0;
86 select.setAttribute('disabled', 'disabled');
89 select.removeAttribute('disabled');
90 var keepSelection = false;
93 oldValue = options[0].firstChild ? options[0].firstChild.data : '';
94 } else if (oldValue != '/') {
95 for (i = 0; i < optCnt && !keepSelection; i++)
96 if (oldValue == (options[i].firstChild ? options[i].firstChild.data : ''))
99 newOption = document.createElement("option");
100 newOption.value = '/';
102 newOption.setAttribute('disabled', 'disabled');
104 newOption.setAttribute('selected', 'selected');
105 newOption.setAttribute('style', 'font-style: italic');
106 newOption.appendChild(document.createTextNode('- please select -'));
107 select.appendChild(newOption);
108 for (i = 0; i < optCnt; i++) {
109 newOption = document.createElement("option");
110 newOption.value = options[i].firstChild ? options[i].firstChild.data : '';
111 if (keepSelection && newOption.value == oldValue)
112 newOption.setAttribute('selected', 'selected');
113 if (keepSelection && optCnt == 1 && newOption.value == '@') {
114 newOption.setAttribute('style', 'font-style: italic');
115 newOption.appendChild(document.createTextNode('Meta graph'));
117 newOption.appendChild(document.createTextNode(newOption.value));
118 select.appendChild(newOption);
120 return keepSelection ? select.selectedIndex : -1;
124 // Request refresh of host list
125 function ListRefreshHost() {
126 var query = 'action=list_hosts';
127 loadXMLDoc(dhtml_url, query);
130 // Handle update to host list
131 function ListOfHost(response) {
132 var select = document.getElementById('host_list');
133 var idx = refillSelect(response ? response.getElementsByTagName('option') : null, select);
140 // Request refresh of plugin list
141 function ListRefreshPlugin() {
142 var host_list = document.getElementById('host_list');
143 var host = host_list.selectedIndex >= 0 ? host_list.options[host_list.selectedIndex].value : '/';
145 var query = 'action=list_plugins&host='+encodeURIComponent(host);
146 loadXMLDoc(dhtml_url, query);
152 // Handle update to plugin list
153 function ListOfPlugin(response) {
154 var select = document.getElementById('plugin_list');
155 var idx = refillSelect(response ? response.getElementsByTagName('option') : null, select);
157 ListRefreshPluginInstance();
159 ListOfPluginInstance(null);
162 // Request refresh of plugin instance list
163 function ListRefreshPluginInstance() {
164 var host_list = document.getElementById('host_list');
165 var host = host_list.selectedIndex >= 0 ? host_list.options[host_list.selectedIndex].value : '/';
166 var plugin_list = document.getElementById('plugin_list');
167 var plugin = plugin_list.selectedIndex >= 0 ? plugin_list.options[plugin_list.selectedIndex].value : '/';
168 if (host != '/' && plugin != '/') {
169 var query = 'action=list_pinsts&host='+encodeURIComponent(host)+'&plugin='+encodeURIComponent(plugin);
170 loadXMLDoc(dhtml_url, query);
172 ListOfPluginInstance(null);
176 // Handle update of plugin instance list
177 function ListOfPluginInstance(response) {
178 var select = document.getElementById('pinst_list');
179 var idx = refillSelect(response ? response.getElementsByTagName('option') : null, select);
186 // Request refresh of type list
187 function ListRefreshType() {
188 var host_list = document.getElementById('host_list');
189 var host = host_list.selectedIndex >= 0 ? host_list.options[host_list.selectedIndex].value : '/';
190 var plugin_list = document.getElementById('plugin_list');
191 var plugin = plugin_list.selectedIndex >= 0 ? plugin_list.options[plugin_list.selectedIndex].value : '/';
192 var pinst_list = document.getElementById('pinst_list');
193 var pinst = pinst_list.selectedIndex >= 0 ? pinst_list.options[pinst_list.selectedIndex].value : '/';
194 if (host != '/' && plugin != '/' && pinst != '/') {
195 var query = 'action=list_types&host='+encodeURIComponent(host)+'&plugin='+encodeURIComponent(plugin)+'&plugin_instance='+encodeURIComponent(pinst);
196 loadXMLDoc(dhtml_url, query);
202 // Handle update of type list
203 function ListOfType(response) {
204 var select = document.getElementById('type_list');
205 var idx = refillSelect(response ? response.getElementsByTagName('option') : null, select);
207 ListRefreshTypeInstance();
209 ListOfTypeInstance(null);
212 // Request refresh of type instance list
213 function ListRefreshTypeInstance() {
214 var host_list = document.getElementById('host_list');
215 var host = host_list.selectedIndex >= 0 ? host_list.options[host_list.selectedIndex].value : '/';
216 var plugin_list = document.getElementById('plugin_list');
217 var plugin = plugin_list.selectedIndex >= 0 ? plugin_list.options[plugin_list.selectedIndex].value : '/';
218 var pinst_list = document.getElementById('pinst_list');
219 var pinst = pinst_list.selectedIndex >= 0 ? pinst_list.options[pinst_list.selectedIndex].value : '/';
220 var type_list = document.getElementById('type_list');
221 var type = type_list.selectedIndex >= 0 ? type_list.options[type_list.selectedIndex].value : '/';
222 if (host != '/' && plugin != '/' && pinst != '/' && type != '/') {
223 var query = 'action=list_tinsts&host='+encodeURIComponent(host)+'&plugin='+encodeURIComponent(plugin)+'&plugin_instance='+encodeURIComponent(pinst)+'&type='+encodeURIComponent(type);
224 loadXMLDoc(dhtml_url, query);
226 ListOfTypeInstance(null);
230 // Handle update of type instance list
231 function ListOfTypeInstance(response) {
232 var select = document.getElementById('tinst_list');
233 var idx = refillSelect(response ? response.getElementsByTagName('option') : null, select);
238 // Disable add button
243 function RefreshButtons() {
244 var host_list = document.getElementById('host_list');
245 var host = host_list.selectedIndex >= 0 ? host_list.options[host_list.selectedIndex].value : '/';
246 var plugin_list = document.getElementById('plugin_list');
247 var plugin = plugin_list.selectedIndex >= 0 ? plugin_list.options[plugin_list.selectedIndex].value : '/';
248 var pinst_list = document.getElementById('pinst_list');
249 var pinst = pinst_list.selectedIndex >= 0 ? pinst_list.options[pinst_list.selectedIndex].value : '/';
250 var type_list = document.getElementById('type_list');
251 var type = type_list.selectedIndex >= 0 ? type_list.options[type_list.selectedIndex].value : '/';
252 var tinst_list = document.getElementById('tinst_list');
253 var tinst = tinst_list.selectedIndex >= 0 ? tinst_list.options[tinst_list.selectedIndex].value : '/';
254 if (host != '/' && plugin != '/' && pinst != '/' && type != '/' && tinst != '/') {
255 document.getElementById('btnAdd').removeAttribute('disabled');
257 document.getElementById('btnAdd').setAttribute('disabled', 'disabled');
260 var graphs = document.getElementById('graphs');
261 if (graphs.getElementsByTagName('div').length > 1) {
262 document.getElementById('btnClear').removeAttribute('disabled');
263 document.getElementById('btnRefresh').removeAttribute('disabled');
265 document.getElementById('btnClear').setAttribute('disabled', 'disabled');
266 document.getElementById('btnRefresh').setAttribute('disabled', 'disabled');
271 var graphList = new Array();
273 function GraphAppend() {
274 var host_list = document.getElementById('host_list');
275 var host = host_list.selectedIndex >= 0 ? host_list.options[host_list.selectedIndex].value : '/';
276 var plugin_list = document.getElementById('plugin_list');
277 var plugin = plugin_list.selectedIndex >= 0 ? plugin_list.options[plugin_list.selectedIndex].value : '/';
278 var pinst_list = document.getElementById('pinst_list');
279 var pinst = pinst_list.selectedIndex >= 0 ? pinst_list.options[pinst_list.selectedIndex].value : '/';
280 var type_list = document.getElementById('type_list');
281 var type = type_list.selectedIndex >= 0 ? type_list.options[type_list.selectedIndex].value : '/';
282 var tinst_list = document.getElementById('tinst_list');
283 var tinst = tinst_list.selectedIndex >= 0 ? tinst_list.options[tinst_list.selectedIndex].value : '/';
284 var time_list = document.getElementById('timespan');
285 var timespan = time_list.selectedIndex >= 0 ? time_list.options[time_list.selectedIndex].value : '';
286 var tinyLegend = document.getElementById('tinylegend').checked;
287 var logarithmic = document.getElementById('logarithmic').checked
288 GraphDoAppend(host, plugin, pinst, type, tinst, timespan, tinyLegend, logarithmic);
291 function GraphDoAppend(host, plugin, pinst, type, tinst, timespan, tinyLegend, logarithmic) {
292 var graphs = document.getElementById('graphs');
294 if (host != '/' && plugin != '/' && pinst != '/' && type != '/') {
295 var graph_id = 'graph_'+nextGraphId++;
296 var graph_src = graph_url+'?host='+encodeURIComponent(host)+'&plugin='+encodeURIComponent(plugin)+'&plugin_instance='+encodeURIComponent(pinst)+'&type='+encodeURIComponent(type);
300 graph_alt = host+'/'+plugin+(pinst.length > 0 ? '-'+pinst : '')+'/'+type;
301 graph_title = type+' of '+plugin+(pinst.length > 0 ? '-'+pinst : '')+' plugin for '+host;
303 graph_alt = host+'/'+plugin+(pinst.length > 0 ? '-'+pinst : '')+'/'+type+(tinst.length > 0 ? '-'+tinst : '');
304 graph_title = type+(tinst.length > 0 ? '-'+tinst : '')+' of '+plugin+(pinst.length > 0 ? '-'+pinst : '')+' plugin for '+host;
305 graph_src += '&type_instance='+encodeURIComponent(tinst);
308 graph_src += '&logarithmic=1';
310 graph_src += '&tinylegend=1';
312 graph_src += '×pan='+encodeURIComponent(timespan);
313 var now = new Date();
314 graph_src += '&ts='+now.getTime();
315 graphList.push(graph_id+' '+encodeURIComponent(graph_alt)+(logarithmic ? '&logarithmic=1' : '')+(tinyLegend ? '&tinylegend=1' : '')+'×pan='+encodeURIComponent(timespan));
318 newGraph = document.createElement('div');
319 newGraph.setAttribute('class', 'graph');
320 newGraph.setAttribute('id', graph_id);
321 // Graph cell + graph
322 newDiv = document.createElement('div');
323 newDiv.setAttribute('class', 'graph_img');
324 newImg = document.createElement('img');
325 newImg.setAttribute('src', graph_src);
326 newImg.setAttribute('alt', graph_alt);
327 newImg.setAttribute('title', graph_title);
328 newDiv.appendChild(newImg);
329 newGraph.appendChild(newDiv);
331 newDiv = document.createElement('div');
332 newDiv.setAttribute('class', 'graph_opts');
334 newImg = document.createElement('img');
335 newImg.setAttribute('src', 'move-up.png');
336 newImg.setAttribute('alt', 'UP');
337 newImg.setAttribute('title', 'Move graph up');
338 newA = document.createElement('a');
339 newA.setAttribute('href', 'javascript:GraphMoveUp("'+graph_id+'")');
340 newA.appendChild(newImg);
341 newDiv.appendChild(newA);
342 newDiv.appendChild(document.createElement('br'));
344 newImg = document.createElement('img');
345 newImg.setAttribute('src', 'refresh.png');
346 newImg.setAttribute('alt', 'R');
347 newImg.setAttribute('title', 'Refresh graph');
348 newA = document.createElement('a');
349 newA.setAttribute('href', 'javascript:GraphRefresh("'+graph_id+'")');
350 newA.appendChild(newImg);
351 newDiv.appendChild(newA);
352 newDiv.appendChild(document.createElement('br'));
354 newImg = document.createElement('img');
355 newImg.setAttribute('src', 'delete.png');
356 newImg.setAttribute('alt', 'RM');
357 newImg.setAttribute('title', 'Remove graph');
358 newA = document.createElement('a');
359 newA.setAttribute('href', 'javascript:GraphRemove("'+graph_id+'")');
360 newA.appendChild(newImg);
361 newDiv.appendChild(newA);
362 newDiv.appendChild(document.createElement('br'));
364 newImg = document.createElement('img');
365 newImg.setAttribute('src', 'move-down.png');
366 newImg.setAttribute('alt', 'DN');
367 newImg.setAttribute('title', 'Move graph down');
368 newA = document.createElement('a');
369 newA.setAttribute('href', 'javascript:GraphMoveDown("'+graph_id+'")');
370 newA.appendChild(newImg);
371 newDiv.appendChild(newA);
372 newGraph.appendChild(newDiv);
374 graphs.appendChild(newGraph);
376 document.getElementById('nograph').style.display = 'none';
380 function GraphDropAll() {
381 var graphs = document.getElementById('graphs');
382 var childCnt = graphs.childNodes.length;
384 if (graphs.childNodes[--childCnt].id != 'nograph' && (graphs.childNodes[childCnt].nodeName == 'div' || graphs.childNodes[childCnt].nodeName == 'DIV'))
385 graphs.removeChild(graphs.childNodes[childCnt]);
386 else if (graphs.childNodes[childCnt].id == 'nograph')
387 graphs.childNodes[childCnt].style.display = 'block';
388 graphList = new Array();
392 function GraphRefresh(graph) {
394 var imgs = document.getElementById('graphs').getElementsByTagName('img');
395 var imgCnt = imgs.length;
396 var now = new Date();
397 var newTS = '&ts='+now.getTime();
399 if (imgs[--imgCnt].parentNode.getAttribute('class') == 'graph_img') {
400 var oldSrc = imgs[imgCnt].src;
401 var newSrc = oldSrc.replace(/&ts=[0-9]+/, newTS);
402 if (newSrc == oldSrc)
403 newSrc = newSrc + newTS;
404 imgs[imgCnt].setAttribute('src', newSrc);
406 } else if (document.getElementById(graph)) {
407 var imgs = document.getElementById(graph).getElementsByTagName('img');
408 var imgCnt = imgs.length;
410 if (imgs[--imgCnt].parentNode.getAttribute('class') == 'graph_img') {
411 var now = new Date();
412 var newTS = '&ts='+now.getTime();
413 var oldSrc = imgs[imgCnt].src;
414 var newSrc = oldSrc.replace(/&ts=[0-9]+/, newTS);
415 if (newSrc == oldSrc)
416 newSrc = newSrc+newTS;
417 imgs[imgCnt].setAttribute('src', newSrc);
423 function GraphRemove(graph) {
424 var graphs = document.getElementById('graphs');
425 if (document.getElementById(graph)) {
426 graphs.removeChild(document.getElementById(graph));
428 if (graphs.getElementsByTagName('div').length == 1)
429 document.getElementById('nograph').style.display = 'block';
431 var myList = Array();
432 for (i = 0; i < graphList.length; i++)
433 if (graphList[i].substring(0, graph.length) == graph && graphList[i].charAt(graph.length) == ' ')
436 myList.push(graphList[i]);
441 function GraphMoveUp(graph) {
442 var graphs = document.getElementById('graphs');
443 var childCnt = graphs.childNodes.length;
444 var prevGraph = null;
445 for (i = 0; i < childCnt; i++)
446 if (graphs.childNodes[i].nodeName == 'div' || graphs.childNodes[i].nodeName == 'DIV') {
447 if (graphs.childNodes[i].id == 'nograph') {
449 } else if (graphs.childNodes[i].id == graph) {
450 var myGraph = graphs.childNodes[i];
452 graphs.removeChild(myGraph);
453 graphs.insertBefore(myGraph, prevGraph);
457 prevGraph = graphs.childNodes[i];
459 for (i = 0; i < graphList.length; i++)
460 if (graphList[i].substring(0, graph.length) == graph && graphList[i].charAt(graph.length) == ' ') {
462 var tmp = graphList[i-1];
463 graphList[i-1] = graphList[i];
470 function GraphMoveDown(graph) {
471 var graphs = document.getElementById('graphs');
472 var childCnt = graphs.childNodes.length;
473 var nextGraph = null;
475 for (i = 0; i < childCnt; i++)
476 if (graphs.childNodes[i].nodeName == 'div' || graphs.childNodes[i].nodeName == 'DIV') {
477 if (graphs.childNodes[i].id == 'nograph') {
479 } else if (graphs.childNodes[i].id == graph) {
480 myGraph = graphs.childNodes[i];
481 } else if (myGraph) {
482 nextGraph = graphs.childNodes[i];
483 graphs.removeChild(nextGraph);
484 graphs.insertBefore(nextGraph, myGraph);
488 for (i = 0; i < graphList.length; i++)
489 if (graphList[i].substring(0, graph.length) == graph && graphList[i].charAt(graph.length) == ' ') {
490 if (i+1 < graphList.length) {
491 var tmp = graphList[i+1];
492 graphList[i+1] = graphList[i];
499 function GraphListFromCookie() {
500 if (document.cookie.length > 0) {
501 cookies = document.cookie.split('; ');
502 for (i = 0; i < cookies.length; i++)
503 if (cookies[i].substring(0, 9) == 'graphLst=')
504 return cookies[i].substring(9).split('/');
509 function GraphSave() {
510 if (graphList.length > 0) {
511 // Save graph list to cookie
513 for (i = 0; i < graphList.length; i++) {
514 var g = graphList[i].indexOf(' ');
517 str += graphList[i].substring(g+1);
520 document.cookie = 'graphLst='+str;
521 if (GraphListFromCookie().length == 0)
522 alert("Failed to save graph list to cookie.");
524 alert("Successfully saved current graph list.");
526 document.cookie = 'graphLst=; expires='+new Date().toGMTString();
527 alert("Cleared saved graph list.");
531 function GraphLoad() {
532 // Load graph list from cookie
533 var grLst = GraphListFromCookie();
534 for (i = 0; i < grLst.length; i++) {
541 var logarithmic = false;
542 var tinyLegend = false;
543 var graph = grLst[i].split('&');
544 for (j = 0; j < graph.length; j++)
545 if (graph[j] == 'logarithmic=1')
547 else if (graph[j] == 'tinylegend=1')
549 else if (graph[j].substring(0, 9) == 'timespan=')
550 timespan = decodeURIComponent(graph[j].substring(9));
551 graph = decodeURIComponent(graph[0]).split('/');
553 if (graph.length > 1) {
554 var g = graph[1].indexOf('-');
556 plugin = graph[1].substring(0, g);
557 pinst = graph[1].substring(g+1);
561 if (graph.length > 2) {
562 var g = graph[2].indexOf('-');
564 type = graph[2].substring(0, g);
565 tinst = graph[2].substring(g+1);
570 if (host && plugin && type)
571 GraphDoAppend(host, plugin, pinst, type, tinst, timespan, tinyLegend, logarithmic);
573 if (grLst.length == 0)
574 alert("No list found for loading.");
575 else if (grLst.length != graphList.length)
576 alert("Could not load all graphs, probably damaged cookie.");