PageRenderTime 27ms CodeModel.GetById 4ms RepoModel.GetById 0ms app.codeStats 0ms

/web/scripts/graph.js

https://code.google.com/p/energyathome/
JavaScript | 445 lines | 281 code | 54 blank | 110 comment | 61 complexity | a856698e7bc35fc5a003e8eaf1b61cfb MD5 | raw file
Possible License(s): Apache-2.0, GPL-2.0, GPL-3.0
  1. /*
  2. This file is part of Energy@Home.
  3. Copyright (C) 2009 Danny Tsang
  4. This file is part of Energy@Home.
  5. Energy@Home is free software: you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation, either version 3 of the License, or
  8. (at your option) any later version.
  9. Energy@Home is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with Energy@Home. If not, see <http://www.gnu.org/licenses/>.
  15. */
  16. var stopWatchTimer;
  17. var startStopwatch = false;
  18. var stopWatchCount = 0;
  19. var PERIOD_OF_TIME = new Array ("Hour", "Day", "Week", "Month", "Year");
  20. var HOURS_OF_THE_DAY = new Array ("Today", "Yesterday", "Week", "Month", "Year");
  21. var LOAD_TIMEOUT = 100;
  22. // Default date format
  23. var DATE_FORMAT = "dd-mmm-yyyy HH:MM:ss";
  24. var TIME_FORMAT = "HH:MM:ss";
  25. // Initialises graph and page. Always displays loading image
  26. function graphInit()
  27. {
  28. // Attach view to controller on model update
  29. attachUpdateView(updateGraph);
  30. // Add graph bindings
  31. var previousPoint = null;
  32. $("#placeholder").bind("plothover", graphHover);
  33. $("#placeholder").bind("plotclick", graphClick);
  34. $("#placeholder").bind("plotselected", function (event, ranges) {
  35. // Only zoom if tick box is true
  36. if(document.getElementById('ZoomSelect').checked)
  37. {
  38. // re-plot zooming
  39. $.plot($("#placeholder"), graphData,
  40. $.extend(true, {}, getTimeOptions(), {
  41. xaxis: { min: ranges.xaxis.from, max: ranges.xaxis.to }
  42. }));
  43. document.getElementById('AutoRefresh').checked = false;
  44. }
  45. });
  46. // Populate range dropdown box
  47. populateDisplayRange();
  48. // Display loading graph
  49. $('#placeholder').html('<p><img src="images/ajax-loader.gif" width="220" height="19" /></p>');
  50. }
  51. // Model has been updated
  52. function updateGraph()
  53. {
  54. // Retrieve data
  55. graphData = getModel();
  56. // Get graph options
  57. options = getOptions();
  58. // Set graph
  59. setGraph(graphData, options)
  60. // Update raw grid data
  61. //drawGrid();
  62. // Call post load function
  63. modelChangeComplete();
  64. }
  65. function modelReset()
  66. {
  67. // Stop the stop watch if it's currently running
  68. startStopwatch = false;
  69. // Display loading graph
  70. $('#placeholder').html('<p><img src="images/ajax-loader.gif" width="220" height="19" /></p>');
  71. // Change graph to loading image
  72. $('#lastUpdated').html('<p><img src="images/ajax-loader_small.gif" /> Loading... <span id="timeElapsed"></span></p>');
  73. // Clear clicked data points
  74. $("#clickdata").text("");
  75. $("#clickoverlay").text("");
  76. // Reset count
  77. stopWatchCount = 0;
  78. // Display time taken on page
  79. $('#timeElapsed').html(stopWatchCount + "ms");
  80. // Start timer to count how long the request took
  81. startStopwatch = true;
  82. stopWatch();
  83. }
  84. // Notify view a data update has started
  85. function modelUpdate()
  86. {
  87. // Stop the stop watch if it's currently running
  88. startStopwatch = false;
  89. // Change graph to loading image
  90. $('#ajaxLoadImg').html('<img src="images/ajax-loader_small.gif" />');
  91. // Clear clicked data points
  92. $("#clickdata").text("");
  93. $("#clickoverlay").text("");
  94. // Reset count
  95. stopWatchCount = 0;
  96. // Display time taken on page
  97. //$('#timeTaken').html(stopWatchCount + "ms");
  98. // Start timer to count how long the request took
  99. startStopwatch = true;
  100. stopWatch();
  101. }
  102. // Notify view data model changes have been complete
  103. function modelChangeComplete()
  104. {
  105. // Stop the timer
  106. startStopwatch = false;
  107. // Change the last updated text
  108. $('#lastUpdated').html('<span id="ajaxLoadImg"></span><i>Last Updated: ' + new Date().toLocaleString() + ' and took <span id="timeTaken"></span></i>');
  109. // Add time taken to load into the text
  110. $('#timeTaken').html(stopWatchCount + "ms");
  111. }
  112. // Count time taken for AJAX request
  113. function stopWatch()
  114. {
  115. if (startStopwatch)
  116. {
  117. // Increment time taken
  118. stopWatchCount+= LOAD_TIMEOUT;
  119. // Display time taken on page
  120. $('#timeElapsed').html(stopWatchCount + "ms");
  121. // Call recursive loop
  122. stopWatchTimer = setTimeout("stopWatch()", LOAD_TIMEOUT);
  123. }
  124. else
  125. {
  126. if (stopWatchTimer)
  127. {
  128. clearTimeout(stopWatchTimer);
  129. }
  130. }
  131. }
  132. // Graph type change event
  133. function graphTypeChange()
  134. {
  135. // Change view options depending on graph type
  136. populateDisplayRange();
  137. // Notify controller of graph type change request
  138. refreshData();
  139. }
  140. // Change in graph parameter
  141. function graphParameterChange()
  142. {
  143. // Check input is valid
  144. // Ensure display range is set before generating new graph
  145. var range = parseInt(document.getElementById('displayRange').value);
  146. if(!document.getElementById('displayRange').value.match(/\D/g) && document.getElementById('displayRange').value.length > 0)
  147. {
  148. // Reset the background colour of the display range text box
  149. document.getElementById('displayRange').style.background = "#FFFFFF";
  150. // Notify controller of graph type change request
  151. refreshData();
  152. }
  153. else // Invalid entry
  154. {
  155. // Set the background colour of the display range text box to red
  156. document.getElementById('displayRange').style.background = "#FC0000";
  157. }
  158. }
  159. // Get graph options depending on select graph parameters
  160. function getOptions()
  161. {
  162. // Get graph options
  163. var options;
  164. if (document.getElementById('graphType') != null && document.getElementById('graphType').value == "Time")
  165. {
  166. options = getTimeOptions();
  167. }
  168. else if (document.getElementById('graphType') != null && document.getElementById('graphType').value == "Hour")
  169. {
  170. options = getHourOptions();
  171. }
  172. return options;
  173. }
  174. // Populates display range dropdown with necessary values and sets other options on graph form
  175. function populateDisplayRange()
  176. {
  177. if (document.getElementById('graphType') != null && document.getElementById('graphType').value == "Time")
  178. {
  179. // Repopulate time frame drop down with new values
  180. loadTimeFrame(PERIOD_OF_TIME);
  181. // Enable range textbox
  182. document.getElementById('displayRange').disabled = false;
  183. // Set textbox background colour to white
  184. document.getElementById('displayRange').style.backgroundColor="#fff";
  185. // Set display range if it's empty
  186. if(document.getElementById('displayRange').value.match(/\d/g) == null)
  187. {
  188. document.getElementById('displayRange').value = "1";
  189. }
  190. // Enable auto refresh
  191. document.getElementById('AutoRefresh').checked = true;
  192. }
  193. else if (document.getElementById('graphType') != null && document.getElementById('graphType').value == "Hour")
  194. {
  195. // Repopulate time fram drop down with new values
  196. loadTimeFrame(HOURS_OF_THE_DAY);
  197. // Disable range textbox
  198. document.getElementById('displayRange').disabled = true;
  199. // Make disabled textbox grey
  200. document.getElementById('displayRange').style.backgroundColor="#c0c0c0";
  201. // Disable auto refresh
  202. document.getElementById('AutoRefresh').checked = false;
  203. }
  204. else if (document.getElementById('graphType') != null && document.getElementById('graphType').value == "Distribution")
  205. {
  206. // Repopulate time fram drop down with new values
  207. loadTimeFrame(PERIOD_OF_TIME);
  208. // Enable range textbox
  209. document.getElementById('displayRange').disabled = false;
  210. // Make disabled textbox grey
  211. document.getElementById('displayRange').style.backgroundColor="#c0c0c0";
  212. // Disable auto refresh
  213. document.getElementById('AutoRefresh').checked = false;
  214. }
  215. }
  216. // Populates a dropdown with list which is passed in as parameter
  217. function loadTimeFrame(list)
  218. {
  219. // Get drop down list
  220. var dropdown = document.getElementById("timeScale");
  221. // Clear drop down
  222. dropdown.options.length = 0;
  223. // Load drop down with array
  224. for (var i = 0; i < list.length; i++)
  225. {
  226. dropdown.options[dropdown.options.length] = new Option(list[i], list[i]);
  227. }
  228. }
  229. // Build time graph once data request response is returned
  230. function setGraph(graphData, options)
  231. {
  232. $.plot($("#placeholder"),
  233. graphData
  234. , options);
  235. }
  236. // Show / hide legend
  237. function showLegendChange()
  238. {
  239. // Get model data
  240. var graphData = getModel();
  241. // Get graph options
  242. var options = getOptions();
  243. $.plot($("#placeholder"),
  244. graphData
  245. , options);
  246. }
  247. // Enable / disable zoom
  248. function zoomOnSelectChange()
  249. {
  250. // Get model data
  251. var graphData = getModel();
  252. // Get graph options
  253. var options = getOptions();
  254. // Re-draw graph
  255. $.plot($("#placeholder"),
  256. graphData
  257. , options);
  258. }
  259. // Resets the zoom
  260. function resetZoom()
  261. {
  262. // Get model data
  263. var graphData = getModel();
  264. // Get graph options
  265. var options = getOptions();
  266. $.plot($("#placeholder"),
  267. graphData
  268. , options);
  269. document.getElementById('AutoRefresh').checked = true;
  270. }
  271. // Enables / disables auto refresh
  272. function autoRefreshChange(enabled)
  273. {
  274. if(enabled)
  275. {
  276. // Add
  277. attachUpdateView(updateGraph);
  278. }
  279. else
  280. {
  281. // Remove
  282. detachUpdateView(updateGraph);
  283. }
  284. }
  285. // Graph click event
  286. function graphClick(event, pos, item)
  287. {
  288. if (item) {
  289. // Check what type of graph is showing. For future use
  290. if (document.getElementById('graphType').value == "Time")
  291. {
  292. //$("#clickdata").text("You clicked point " + item.dataIndex + " in " + item.series.label + ".");
  293. if(item.series.label == "Energy Used")
  294. {
  295. $("#clickdata").text("Current: " + parseInt(item.datapoint[1].toFixed(2)) + " Watts was used on " +
  296. new Date(parseInt(item.datapoint[0].toFixed(2))).toGMTString() + ".");
  297. }
  298. else if(item.series.label == "Temperature")
  299. {
  300. $("#clickdata").text("Current: It was " + item.datapoint[1].toFixed(1) + " degrees celsius at " +
  301. new Date(parseInt(item.datapoint[0].toFixed(2))).toGMTString() + ".");
  302. }
  303. else if(item.series.label == "Energy Overlay")
  304. {
  305. // Get offset time
  306. var subtrackTime = getSubtrackOverlay(document.getElementById('timeScale').value);
  307. $("#clickoverlay").text("Overlay: " + parseInt(item.datapoint[1].toFixed(2)) + " Watts was used on " +
  308. new Date(parseInt(item.datapoint[0].toFixed(2)) - subtrackTime).toGMTString() + ".");
  309. }
  310. else if(item.series.label == "Temperature Overlay")
  311. {
  312. // Get offset time
  313. var subtrackTime = getSubtrackOverlay(document.getElementById('timeScale').value);
  314. $("#clickoverlay").text("Overlay: It was " + item.datapoint[1].toFixed(1) + " degrees celsius at " +
  315. new Date(parseInt(item.datapoint[0].toFixed(2)) - subtrackTime).toGMTString() + ".");
  316. }
  317. }
  318. }
  319. }
  320. // Graph hover event
  321. function graphHover(event, pos, item)
  322. {
  323. // Tooltip displayed on the graph
  324. if (item)
  325. {
  326. if (previousPoint == undefined || (previousPoint != item.datapoint))
  327. {
  328. previousPoint = item.datapoint;
  329. $("#tooltip").remove();
  330. var x = 0, y = new Date();
  331. // Check what type of graph is showing. For future use
  332. if (document.getElementById('graphType').value == "Time")
  333. {
  334. if(item.series.channel != "temp")
  335. {
  336. x = parseInt(item.datapoint[1].toFixed(2)),
  337. y = new Date(parseInt(item.datapoint[0].toFixed(2)));
  338. showTooltip(item.pageX, item.pageY,
  339. "<span>" + item.series.label + "</span><br/><span class=\"energyvalue\" style=\"color:" + item.series.color + "\">" + x + " " + item.series.data[item.dataIndex][2] + "</span><br/><span>" + y.format(DATE_FORMAT) + "</span>");
  340. }
  341. else
  342. {
  343. x = item.datapoint[1].toFixed(1),
  344. y = new Date(parseInt(item.datapoint[0].toFixed(2)));
  345. showTooltip(item.pageX, item.pageY,
  346. "<span>" + item.series.label + "</span><br/><span class=\"temperaturevalue\" style=\"color:" + item.series.color + "\">" + x + "&deg; " + item.series.data[item.dataIndex][2] + "</span><br/><span>" + y.format(DATE_FORMAT) + "</span>");
  347. }
  348. }
  349. else if (document.getElementById('graphType').value == "Hour")
  350. {
  351. x = item.datapoint[1].toFixed(0);
  352. var y1 = item.datapoint[0];
  353. var y2 = item.datapoint[0] + 1;
  354. // Pad time with leading 0
  355. if(y1 < 10)
  356. {
  357. y1 = "0" + y1;
  358. }
  359. if(y2 < 10)
  360. {
  361. y2 = "0" + y2;
  362. }
  363. showTooltip(item.pageX, item.pageY,
  364. "<span>" + item.series.label + "</span><br/><span class=\"energyvalue\" style=\"color:" + item.series.color + "\">" + x + " Watt(s)</span><br/><span>were used between " + y1 + ":00 - " + y2 + ":00</span>");
  365. }
  366. }
  367. }
  368. else
  369. {
  370. $("#tooltip").remove();
  371. previousPoint = null;
  372. }
  373. }
  374. // Tooltip look
  375. function showTooltip(x, y, contents)
  376. {
  377. $('<div id="tooltip">' + contents + '</div>').css( {
  378. position: 'absolute',
  379. display: 'none',
  380. top: y + 20,
  381. left: x + 5,
  382. border: '1px solid #fdd',
  383. padding: '2px',
  384. 'background-color': '#FFFCEF',
  385. opacity: 0.95
  386. }).appendTo("body").fadeIn(100);
  387. }