Fix another graph bug + some more work on control page
[matches/MCTX3420.git] / testing / MCTXWeb / public_html / static / mctx.gui.js
1 /**
2 * MCTX3420 2013 GUI stuff.
3 * Coding style:
4 *  - Always end statements with semicolons
5 *  - Egyptian brackets are highly recommended (*cough*).
6 *  - Don't use synchronous stuff - hook events into callbacks
7 *  - $.fn functions should return either themselves or some useful object
8 *    to allow for chaining of method calls
9 */
10
11 mctx = {};
12 //Don't use this in the final version
13 mctx.location = window.location.pathname;
14 mctx.location = mctx.location.substring(0, mctx.location.lastIndexOf('/')) + "/";
15 //mctx.location = location.protocol + "//" + location.host + "/";
16 mctx.api = location.protocol + "//" + location.host + "/" + "api/";
17 mctx.expected_api_version = 0;
18 mctx.has_control = false;
19 mctx.debug = true;
20
21 mctx.menu = [
22     {'text' : 'Home', href : mctx.location + 'index.html'},
23     {'text' : 'Experiment control', href : mctx.location + 'control.html'},
24     {'text' : 'Pin debugging', href : mctx.location + 'pintest.html'},
25     {'text' : 'Help', href : mctx.location + 'help.html'}
26 ];
27
28 mctx.status = {
29     OK : 1,
30     ERROR : -1,
31     UNAUTHORIZED : -2,
32     NOTRUNNING : -3,
33     ALREADYEXISTS : -4
34 };
35
36 mctx.statusCodesDescription = {
37     "1" : "Ok",
38     "-1" : "General error",
39     "-2" : "Unauthorized",
40     "-3" : "Not running",
41     "-4" : "Already exists"
42 };
43
44 mctx.sensors = {
45     0 : {name : "Strain gauge 1"},
46     1 : {name : "Strain gauge 2"},
47     2 : {name : "Strain gauge 3"},
48     3 : {name : "Strain gauge 4"},
49     4 : {name : "Pressure sensor 1"},
50     5 : {name : "Pressure sensor 2"},
51     6 : {name : "Pressure sensor 3"}
52 };
53
54 mctx.actuators = {
55     0 : {name : "Solenoid 1"},
56     1 : {name : "Solenoid 2"},
57     2 : {name : "Solenoid 3"},
58     3 : {name : "Pressure regulator"}
59 };
60
61 mctx.strain_gauges = {};
62 mctx.strain_gauges.ids = [0, 1, 2, 3];
63 mctx.strain_gauges.time_limit = 20;
64
65 /**
66 * Logs a message if mctx.debug is enabled. This function takes
67 * a variable number of arguments and passes them 
68 * to alert or console.log (based on browser support).
69 * @returns {undefined}
70 */
71 function debugLog () {
72     if (mctx.debug) {
73         if (typeof console === "undefined" || typeof console.log === "undefined") {
74             for (var i = 0; i < arguments.length; i++) {
75                 alert(arguments[i]);
76             }
77         } else {
78             try {
79               console.log.apply(this, arguments);
80             } catch (e) {
81               //Chromie
82               for (var i = 0; i < arguments.length; i++) {
83                 console.log(arguments[i]);
84               }
85             }
86         }
87     }
88 }
89
90 /**
91 * Writes the current date to wherever it's called.
92 */
93 function getDate() {
94     document.write((new Date()).toDateString());
95 }
96
97 /**
98 * Should be run before the load of any GUI page.
99 * To hook events to be called after this function runs,
100 * use the 'always' method, e.g runBeforeLoad().always(function() {my stuff});
101 * @param {type} isLoginPage
102 * @returns The return value of calling $.ajax
103 */
104 function runBeforeLoad(isLoginPage) {
105     return $.ajax({
106         url : mctx.api + "identify"
107     }).done(function (data) {
108         if (data.logged_in && isLoginPage) {
109             if (mctx.debug) {
110                 debugLog("Redirect disabled!");
111             } else {
112                 window.location = mctx.location;
113             }
114         } else if (!data.logged_in && !isLoginPage) {
115             if (mctx.debug) {
116                 debugLog("Redirect disabled!");
117             } else {
118                 //Note: this only clears the nameless cookie
119                 document.cookie = ""; 
120                 window.location = mctx.location + "login.html";
121             }
122         } else {
123             mctx.friendlyName = data.friendly_name;
124         }
125     }).fail(function (jqHXR) {
126         if (mctx.debug) {
127             debugLog("Failed to ident server. Is API running?")
128         } else if (!isLoginPage) {
129             window.location = mctx.location + "login.html";
130         }
131     }).always(function () {
132         
133     });
134 }
135
136 /**
137  * Populates the navigation menu.
138  */
139 $.fn.populateNavMenu = function() {
140     var root = $("<ul/>")
141     for (var i = 0; i < mctx.menu.length; i++) {
142         var item = mctx.menu[i];
143         var entry = $("<li/>").append(
144             $("<a/>", {text : item.text, href: item.href})
145         );
146         root.append(entry);
147     }
148     $(this).append(root);
149     return this;
150 }
151
152 /**
153 * Sets the camera autoupdater
154 * Obsolete?
155 * @returns {$.fn}
156 */
157 $.fn.setCamera = function () {
158     var url = mctx.api + "image";  //http://beaglebone/api/image
159     var update = true;
160
161     //Stop updating if we can't retrieve an image!
162     this.error(function() {
163         update = false;
164     });
165
166     var parent = this;
167
168     var updater = function() {
169         if (!update) {
170             alert("Cam fail");
171             parent.attr("src", "");
172             return;
173         }
174         
175         parent.attr("src", url + "#" + (new Date()).getTime());
176         
177         setTimeout(updater, 10000);
178     };
179
180     updater();
181     return this;
182 };
183
184 /**
185 * Sets the strain graphs to graph stuff. Obsolete?
186 * @returns {$.fn}
187 */
188 $.fn.setStrainGraphs = function () {
189     var sensor_url = mctx.api + "sensors";
190     var graphdiv = this;
191
192     var updater = function () {
193         var time_limit = mctx.strain_gauges.time_limit;
194         var responses = new Array(mctx.strain_gauges.ids.length);
195         
196         for (var i = 0; i < mctx.strain_gauges.ids.length; i++) {
197             var parameters = {id : i, start_time: -time_limit};
198             responses[i] = $.ajax({url : sensor_url, data : parameters});
199         }
200         
201         $.when.apply(this, responses).then(function () {
202             var data = new Array(arguments.length);
203             for (var i = 0; i < arguments.length; i++) {
204                 var raw_data = arguments[i][0].data;
205                 var pruned_data = [];
206                 var step = ~~(raw_data.length/100);
207                 for (var j = 0; j < raw_data.length; j += step)
208                 pruned_data.push(raw_data[j]); 
209                 data[i] = pruned_data;
210             }
211             $.plot(graphdiv, data);
212             setTimeout(updater, 1000);
213         }, function () {debugLog("It crashed");});
214     };
215
216     updater();
217     return this;
218 };
219
220 /**
221 * Performs a login attempt.
222 * @returns The AJAX object of the login request */
223 $.fn.login = function () {
224     var username = this.find("input[name='username']").val();
225     var password = this.find("input[name='pass']").val();
226     var out = this.find("#result");
227     var redirect = function () {
228         window.location.href = mctx.location;
229     };
230
231     out.removeAttr("class");
232     out.text("Logging in...");
233
234     return $.ajax({
235         url : mctx.api + "bind",
236         data : {user: username, pass : password}
237     }).done(function (data) {
238         if (data.status < 0) {
239             mctx.has_control = false;
240             out.attr("class", "fail");
241             out.text("Login failed: " + data.description);
242         } else {
243             //todo: error check
244             mctx.has_control = true;
245             out.attr("class", "pass");
246             out.text("Login ok!");
247             setTimeout(redirect, 800);      
248         }
249     }).fail(function (jqXHR) {
250         mctx.has_control = false;
251         out.attr("class", "fail");
252         out.text("Login request failed - connection issues.")
253     });
254 };
255
256 /**
257 * Performs a logout request. The nameless cookie is
258 * always cleared and the browser redirected to the login page,
259 * independent of whether or not logout succeeded.
260 * @returns  The AJAX object of the logout request.
261 */
262 $.fn.logout = function () {
263     return $.ajax({
264         url : mctx.api + "unbind"
265     }).always(function () {
266         //Note: this only clears the nameless cookie
267         document.cookie = ""; 
268         window.location = mctx.location + "login.html";
269     });
270 };
271
272 /**
273 * Sets the error log to continuously update.
274 * @returns itself */
275 $.fn.setErrorLog = function () {
276     var url = mctx.api + "errorlog";
277     var outdiv = this;
278
279     if ($(this).length <= 0) {
280       //No error log, so do nothing.
281       return;
282     }
283
284     var updater = function () {
285         $.ajax({url : url}).done(function (data) {
286             outdiv.text(data);
287             outdiv.scrollTop(
288               outdiv[0].scrollHeight - outdiv.height()
289             );
290             setTimeout(updater, 3000);
291         }).fail(function (jqXHR) {
292             if (jqXHR.status === 502 || jqXHR.status === 0) {
293                 outdiv.text("Failed to retrieve the error log.");
294             }
295             setTimeout(updater, 10000); //poll at slower rate
296         });
297     };
298
299     updater();
300     return this;
301 };
302
303 $.fn.checkStatus = function(data) {
304   if (data.status !== mctx.status.OK) {
305     $(this).text(data.description).addClass("fail");
306     return false;
307   }
308   return true;
309 };
310
311 $(document).ready(function () {
312   //Show the content!
313   $("#content").css("display", "block");
314   
315   //Set the welcome bar
316   var name = " " + (mctx.friendlyName ? mctx.friendlyName : "");
317   $("#welcome-container").text("Welcome"+ name + "!");
318   $("#logout-container").css("display", "block");
319   //$("#menu-container").populateNavbar();
320
321   $("#logout").click(function () {
322     $("#logout").logout();
323   });
324   
325   //Enable the error log, if present
326   $("#errorlog").setErrorLog();
327   
328   //Enable the hide/show clicks
329   $("#sidebar-hide").click(function () {
330     $("#sidebar").css("display", "none");
331     $("#sidebar-show").css("display", "inherit");
332     return this;
333   });
334
335   $("#sidebar-show").click(function () {
336     $("#sidebar-show").css("display", "none");
337     $("#sidebar").css("display", "inherit");
338     return this;
339   });
340 });
341 $(document).ajaxError(function (event, jqXHR) {
342     //console.log("AJAX query failed with: " + jqXHR.status + " (" + jqXHR.statusText + ")");
343 });

UCC git Repository :: git.ucc.asn.au