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

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