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

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