source: trunk/FACT++/www/smartfact/index.js@ 14420

Last change on this file since 14420 was 14416, checked in by tbretz, 12 years ago
Fixed a problem with the new Chromium browser. It tries to avoid reloading POST pages by sending pre-conditionals. This could actually deacrease traffic (although not much) but does not work, because we would have to store the last report internally to issue it again to cross-check the timout for invalidation.
File size: 44.0 KB
Line 
1"use strict";
2
3var debug = false;
4
5var codedMap = "966676:6:A;68656364626Y?\\?;A=A<AGADAN4K4i5g5h5o506W?Z?]?_?>A@A?AJAIAFACAM4J4H4f5d5e5l5m5n516X?[?^?N?P?AA1ABAVAUAKAHAEAO4L4I4G4E4c5a5b5M6j5k5V6Y6\\6_6G?J?O?Q?S?2A4A3AYAXAWAbA_AnAkAhA3404F4D4B4`5^5_5J6K6L6S6T6W6Z6]6E?H?K?M?R?T?V?5A7A6A\\A[AZAeAdAaA^AmAjAgA24o3m3C4A4?4]5[5\\5G6H6I6P6Q6R6U6X6[6^6F?I?L?<?>?U?;@=@8Ah@9AMALA]ABCACfAcA`AoAlAiA4414n3l3<4@4>425Z5X5Y5D6E6F698N6O608E8H8K8H>K>N>?>B>=???A?<@>@@@i@k@j@PAOANAECDCCC<C9CZCWCTC=3:3734313=4;4943515o4W5U5V5A6B6C6687888m7n7C8F8I8F>I>L>=>@>C>E>@?B?D??@A@C@l@n@m@SARAQAHCGCFC?C>C;C8CYCVCSC<393633303n2:4846405n4l4T5R5S5>6?6@6384858j7k7l7o7D8G8J8G>J>M>>>A>D>4>6>C?3?5?B@2@4@o@_@0ALBKBTA0CoBIC8D7D@C=C:C[CXCUC>3;3835323o2m2k27454j3m4k4i4Q5O5P5C7<6=6g71828o8h7i7S9<8?8B8Q>T>W>@=C=F=e<h<5>7>9>4?6?8?3@5@7@`@b@a@OBNBMB3C2C1C;D:D9D_D\\DQCNCKCF3C3@3>2;282Z1W1l2j2h2k3i3g3j4h4f4N5L5M5@7A7B7d7e7f7l8m8n8P9Q9:8=8@8O>R>U>>=A=D=c<f<i<k<8>:><>7?9?;?6@8@:@c@e@d@RBQBPB6C5C4C>D=D<DbDaD^D[DPCMCJCE3B3?3=2:272Y1V1T1i2g2e2h3f3d3g4e4c4K5I5J5=7>7?7a7b7c7i8j8k8M9N9O9R9;8>8A8P>S>V>?=B=E=d<g<j<Z<\\<;>k=m=:?j>l>9@i?k?f@V@g@CBBBSBgBfB7CoCnC?DSDRDcD`D]DRCOCLCG3D3A3?2<292[1X1U1S1Q1f2d2b2e3c3a3d4b4`4H5F5G5:7;7<7^7_7`7f8g8h8J9K9L97:::=:@:C:F:I:I=L=O=7=:===n<1=[<]<_<l=n=0>k>m>o>j?l?n?W@Y@X@FBEBDBjBiBhB2D1D0DVDUDTDCE@EOELEIEXEUERE5222o1l1i1f1c1`1R1P1N1c2a2_2b3`3^3a4_4]4<5:5;5778797[7\\7]7c8d8e8G9H9I94:5:8:;:>:A:D:G:G=J=M=5=8=;=l<o<2=4=^<`<b<o=1>3>n>0?2?m?o?1@Z@\\@[@IBHBGBmBlBkB5D4D3DYDXDWDFEEEBE?ENEKEHEWETEQE4212n1k1h1e1b1_1]1O1M1K1`2^2\\2_3]3[3^4\\4Z4957585475767X7Y7Z7`8a8b8D9E9F91:2:3:6:9:<:?:B:E:H:H=K=N=6=9=<=m<0=3=d;f;a<H<J<2>b=d=1?a>c>0@`?b?]@D@^@:B9BJB^B]BnBfCeC6DJDIDZDnDmDGEDEAEPEMEJEYEVESE623202m1j1g1d1a1^1\\1[0L1J1?1]2[2Y2\\3Z3X3[4Y4W4654555172737U7V7W7]8^8_8A9B9C9e9o90:n9g:j:m:L:O:R:U:X:[:];`;c;T;W;Z;7<9<e;g;i;I<K<M<c=e=g=b>d>f>a?c?e?E@G@F@=B<B;BaB`B_BiChCgCMDLDKD1E0EoD9E7E<F9F6FaE^E[EjEgEdER0O0L0I0F0C0n0l0\\0Z0X0@1>1<1Z2X2V2Y3W3U3X4V4T4E5C5D5n6o607R7S7T7Z8[8\\8>9?9@9b9c9d9l9m9e:h:k:J:M:P:S:V:Y:[;^;a;R;U;X;6<8<:<;<h;j;l;L<N<P<f=h=j=e>g>i>d?f?h?N@Q@H@@B?B>BdBcBbBlCkCjCPDODND4E3E2E;E:E8E6E;F8F5F`E]EZEiEfEcEQ0N0K0H0E0B0m0k0j0Y0W0U0=1;191W2U2S2V3T3R3U4S4Q4B5@5A5k6l6m6O7P7Q7W8X8Y8;9<9=9_9`9a9j9k9\\:_:f:i:l:K:N:Q:T:W:Z:\\;_;b;S;V;Y;C<E<G<<<m;k;1<2<O<Q<S<i=[=P=h>X>Z>g?M@O@R@U@S@J@I@AB1B0BeBTB\\CmCAD@DQDiDhD5EdD<E4F2F0F=F:F7FbE_E\\EkEhEeES0P0M0J0G0D011o0h0g0e0V0T0`0:181Q2T2R2H2S3Q3P3R4P4K3?5=5>5c6i6j6h6M7N7L7U8V8T899:9W9]9^9\\9g9h9i9]:`:c:5;2;o:>;;;8;P;M;J;G;D;A;?<A<D<F<=<><n;o;3<5<R<T<Y=Z=Q=R=Y>[>\\>^>P@T@L@K@5B4B3B2BVBUB^C]CCDBDkDjDfDeD>E=E3F1FnElE@FCFFFIFLFOF;0>0A0205080513101i0f0d0c0b0_0I1H1D1P2O2G2F2D2O3N3M3J3H3a6b6e6f6g6I7J7K7R8S8397989V9Y9Z9[9f9^:a:d:4;1;n:=;:;7;O;L;I;F;C;@;@<B<0<4<U<V<X<`=]=\\=S=U=W=]>_>`>8B7B6BZBXBWB_CaC`CFDEDDDlDgDoEmE>FAFDFGFJFMF90<0?0003060714121a0^0]0G1C1B1N2L2E2C2B2@2L3I3`6d6E7F7G7H7O8Q8192969T9U9X96;3;0;?;<;9;Q;N;K;H;E;B;W<Y<^=_=a=T=V=X=\\B[BYBdCcCbCHDGD?FBFEFHFKFNF:0=0@0104070F1E1A1M2K2J2I2A2D7L8M8N8P809495961b:";
6var map = new Array(1440);
7
8function $(id) { return document.getElementById(id); }
9function $new(name) { return document.createElement(name); }
10function $txt(txt) { return document.createTextNode(txt); }
11function trim(str) { return str.replace(/^\s\s*/, "").replace(/\s*\s$/, ""); }
12function valid(str) { if (!str) return false; if (str.length==0) return false; return true;}
13function isSliding() { var z = $("body").visiblePage/*getAttribute("data-visible")*/; return $("table"+z) ? $("table"+z).offsetLeft!=0 : false; }
14function htmlDecode(input) { var e = $new('div'); e.innerHTML = input; return e.firstChild ? e.firstChild.nodeValue : input; }
15function setUTC(el, time) { var str = time.toUTCString(); var utc = str.substr(str.length-12, 8); el.innerHTML = "&#8226;&nbsp;"+utc+"&nbsp;UTC&nbsp;&#8226;"; }
16
17function cycleCol(el)
18{
19 var col = el.dotColor;//el.getAttribute("data-color");
20 col++;
21 col %= 31;
22 el.dotColor = col; //setAttribute("data-color", col);
23 if (col>16)
24 col = 31-col;
25 var hex = col.toString(16);
26 el.style.color = "#"+hex+"0"+hex+"0"+hex+"f";
27}
28
29function onload()
30{
31 try
32 {
33 var xmlLoad = new XMLHttpRequest();
34 xmlLoad.open('POST', "index.php?load", true);
35 //xmlLoad.setRequestHeader("If-Match", "*");
36 xmlLoad.onload = function()
37 {
38 if (xmlLoad.status==401)
39 login("");
40
41 if (xmlLoad.status!=200)
42 {
43 //alert("ERROR[0] - HTTP request '"+xmlLoad.statusText+" ["+xmlLoad.status+"]");
44 //return;
45 }
46
47 if (xmlLoad.status==200)
48 login(xmlLoad.responseText);
49 };
50 xmlLoad.send(null);
51 }
52 catch(e)
53 {
54 // FIXME: Add a message to the body.
55 alert("Your browser doesn't support dynamic reload.");
56 return;
57 }
58
59 var name = location.hash.length==0 ? "fact" : location.hash.substr(1);
60
61 var args = location.search.substr(1).split('&');
62
63 for (var i=0; i<args.length; i++)
64 {
65 switch (args[i])
66 {
67 //case "max": $("body").setAttribute("data-max", "yes"); continue;
68 //case "noslide": $("body").setAttribute("data-noslide", "yes"); continue;
69 case "max": $("body").displayMax = true; continue;
70 case "noslide": $("body").displayNoslide = true; continue;
71 case "sound": $("body").sound = true; continue;
72 }
73
74 var entry = args[i].split('=');
75 if (entry.length!=2)
76 continue;
77
78 switch (entry[0])
79 {
80 case "w": $("body").displayFixedWidth = entry[1]; break; //setAttribute("data-width", entry[1]); break;
81 case "h": $("body").displayFixedHeight = entry[1]; break; //setAttribute("data-height", entry[1]); break;
82 }
83 }
84
85 /*
86 alert("0 -- "+navigator.appCodeName+"\n"+
87 "1 -- "+navigator.appName+"\n"+
88 "2 -- "+navigator.appVersion+"\n"+
89 "3 -- "+navigator.platform+"\n"+
90 "4 -- "+navigator.userAgent);
91 */
92 loadPage(name, 0, 0);
93}
94
95function login(user)
96{
97 var z = $("body").visiblePage;
98 var l = $("login"+z);
99
100 $("body").user = user;
101
102 if (l)
103 {
104 l.setAttribute("style", "background-position:-"+(user?"720":"755")+"px 50%;");
105 l.alt = user;
106 }
107}
108
109function onresize()
110{
111 var z = $("body").visiblePage/*getAttribute("data-visible")*/;
112
113 //$("table"+z).style.width="100%";
114 $("image"+z).style.width="1px";
115 $("canvas"+z).width=1;
116
117 doresize(z);
118
119}
120
121function loadPage(name, z, dz)
122{
123 if (isSliding())
124 return;
125
126 var xmlPage = new XMLHttpRequest();
127 xmlPage.open('POST', "struct/"+name+'.page', true);
128 //xmlPage.setRequestHeader("If-Match", "*");
129 xmlPage.onload = function ()
130 {
131 if (xmlPage.status!=200)
132 {
133 alert("ERROR[0] - HTTP request '"+name+".page': "+xmlPage.statusText+" ["+xmlPage.status+"]");
134 //setTimeout("loadPage('+name+')", 5000);
135 /****** invalidate ******/
136 return;
137 }
138
139 if (!isSliding())
140 {
141 buildPage(name, xmlPage.responseText, z, dz);
142 changePage(z, z+dz);
143 }
144
145 //changePage(name, xmlHttp.resposeText);
146 //slideOut(name, xmlHttp.responseText);
147 //displayPage(name, xmlHttp.responseText);
148 //onresize(true);
149 };
150
151 xmlPage.send(null);
152
153 location.hash = name;
154}
155
156function sendCommand(command)
157{
158 if (command=="stop")
159 {
160 if (!confirm("Do you really want to stop a running script?"))
161 return;
162 }
163
164 var debug = false;
165
166 var uri = "index.php?";
167 if (debug==true)
168 uri += "debug&";
169 uri += command;
170
171 var xmlCmd = new XMLHttpRequest();
172 xmlCmd.open('POST', uri, true);
173 xmlCmd.setRequestHeader("If-Match", "*");
174 xmlCmd.onload = function ()
175 {
176 if (xmlCmd.status==401)
177 login("");
178
179 if (xmlCmd.status!=200)
180 {
181 alert("ERROR[1] - HTTP request: "+xmlCmd.statusText+" ["+xmlCmd.status+"]");
182 return;
183 }
184
185 if (xmlCmd.responseText.length==0)
186 {
187 alert("No proper acknowledgment of command execution received.");
188 return;
189 }
190
191 var txt = xmlCmd.responseText.split('\n');
192
193 login(txt[0]);
194
195 switch (txt[1])
196 {
197 case "1": alert("dimctrl unreachable."); break;
198 case "2": /*success*/ break;
199 default: alert("Return code '"+txt[0]+"' unknown."); break;
200 }
201 if (txt.length>2)
202 alert(xmlCmd.responseText);
203 };
204 xmlCmd.send(null);
205}
206
207
208function submit(script)
209{
210 var inputs = document.getElementsByTagName("input");
211
212 var args = "start="+script+".dim";
213 for (var i=0; i<inputs.length; i++)
214 args += "&"+inputs[i].name+"="+inputs[i].value;
215
216 var selects = document.getElementsByTagName("select");
217 for (var i=0; i<selects.length; i++)
218 args += "&"+selects[i].name+"="+selects[i].value;
219
220 sendCommand(args);
221}
222
223function buildPage(name, text, oldz, dz)
224{
225 var fname = dz==0 ? "fact" : $("table"+oldz).pageName;//getAttribute("data-file");
226
227 var z = oldz + dz;
228
229 var lines = text.split('\n');
230
231 if (lines.length==0)
232 {
233 alert("buildPage - received data empty.");
234 return;
235 }
236
237 if (lines[0].length==0)
238 {
239 alert("buildPage - title missing");
240 return;
241 }
242
243 $("audio").date = new Date();
244
245 var title = lines[0];
246 var is_cmd = title[0]=='*';
247 if (is_cmd)
248 title = title.substr(1);
249
250 // ==================================================================
251
252 var th = $new("thead");
253 th.colSpan = 3;
254 th.width = "100%";
255
256 var htr = $new("tr");
257 th.appendChild(htr);
258
259 var htd = $new("td");
260 htd.setAttribute("class", "thead");
261 htd.colSpan = 3;
262 htd.width = "100%";
263 htr.appendChild(htd);
264
265 // -------------
266
267 var htab = $new("table");
268 htab.width = "100%";
269 htd.appendChild(htab);
270
271 var hhtr = $new("tr");
272 htab.appendChild(hhtr);
273
274 var htd0 = $new("td");
275 var htd1 = $new("td");
276 var htd2 = $new("td");
277 var htd3 = $new("td");
278 var htd4 = $new("td");
279 var htd5 = $new("td");
280 var htd6 = $new("td");
281 htd0.setAttribute("class", "tcell1");
282 htd1.setAttribute("class", "tcell2");
283 htd2.setAttribute("class", "tcell1");
284 htd2.setAttribute("width", "1px");
285 htd3.setAttribute("class", "tcell1");
286 htd3.setAttribute("width", "1px");
287 htd4.setAttribute("width", "1px");
288 htd5.setAttribute("width", "1px");
289 htd6.setAttribute("width", "1px");
290 hhtr.appendChild(htd6);
291 hhtr.appendChild(htd4);
292 hhtr.appendChild(htd3);
293 hhtr.appendChild(htd0);
294 hhtr.appendChild(htd1);
295 hhtr.appendChild(htd2);
296 hhtr.appendChild(htd5);
297
298 var div0 = $new("div");
299 var div1 = $new("div");
300 var div2 = $new("div");
301 var div3 = $new("div");
302 var div4 = $new("div");
303 var div5 = $new("div");
304 div0.id = "login"+z;
305 div0.alt = $("body").user;
306 div4.id = "warn"+z;
307 div5.id = "speaker"+z;
308 div0.setAttribute("class", "icon_login");
309 div2.setAttribute("class", "icon_white");
310 div4.setAttribute("class", "icon_color");
311 div5.setAttribute("class", "icon_color");
312 div0.setAttribute("style", "background-position:-"+($("body").user?"720":"755")+"px 50%;");
313 div2.setAttribute("style", "background-position:-396px 50%;");
314 div4.setAttribute("style", "background-position:-12px -13px;display:none;");
315 div5.setAttribute("style", "background-position:-189px -57px;");
316 div0.onclick = function () { sendCommand("logout"); };
317 div2.onclick = function () { this.style.backgroundColor='rgba(0,0,0,0.77)'; loadPage(fname, z, -dz); };
318 div4.onclick = function () { this.style.backgroundColor='rgba(0,0,0,0.77)'; loadPage('error', z, +1); };
319
320 if (name=="fact")
321 {
322 div3.setAttribute("class", "icon_color");
323 div3.setAttribute("style", "background-position:-58px -146px;");
324 }
325 else
326 {
327 div3.setAttribute("class", "icon_white");
328 div3.setAttribute("style", "background-position:-575px 50%;");
329 div3.onclick = function () { this.style.backgroundColor='rgba(0,0,0,0.77)'; loadPage('fact', z, -1); };
330 }
331
332 var sp0 = $new("span");
333 var sp1 = $new("span");
334 var sp2 = $new("span");
335 sp0.id = "ldot" +z;
336 sp1.id = "title"+z;
337 sp2.id = "rdot" +z;
338 sp1.setAttribute("style", "font-size:large;");
339 //sp0.setAttribute("data-color", "3");
340 //sp2.setAttribute("data-color", "3");
341 sp0.dotColor = 3;
342 sp2.dotColor = 3;
343 sp0.appendChild($txt(" \u2022 "));
344 sp1.appendChild($txt(title));
345 sp2.appendChild($txt(" \u2022 "));
346 if (is_cmd)
347 {
348 sp1.onclick = function () { this.style.backgroundColor='rgba(0,0,0,0.77)'; submit(name); this.style.backgroundColor=''; };
349 }
350 else
351 {
352 if (name!='control')
353 sp1.onclick = function () { this.style.backgroundColor='rgba(0,0,0,0.15)'; loadPage('control', z, +1); };
354 }
355
356 div1.setAttribute("style", "font-size:small;");
357 div1.id = "reporttime"+z;
358 div1.appendChild($txt("---"));
359
360 div1.onclick = function () { this.style.backgroundColor='rgba(0,0,0,0.77)'; sendCommand('stop'); this.style.backgroundColor=''; };
361
362 htd0.appendChild(sp0);
363 htd0.appendChild(sp1);
364 htd0.appendChild(sp2);
365
366 htd6.appendChild(div0); // Login
367 htd1.appendChild(div1);
368 if (dz!=0/* && z+dz!=0*/)
369 htd2.appendChild(div2); // back
370 htd3.appendChild(div3); // home
371 htd4.appendChild(div4); // Warning
372 htd5.appendChild(div5); // Speaker
373
374 // ==================================================================
375
376 var tf = $new("tfoot");
377
378 var ftr = $new("tr");
379 tf.appendChild(ftr);
380
381 var ftd = $new("td");
382 ftd.setAttribute("class", "tfoot");
383 ftd.width = "100%";
384 ftd.colSpan = 3;
385 ftr.appendChild(ftd);
386
387 var ftab = $new("table");
388 ftab.width = "100%";
389 ftd.appendChild(ftab);
390
391 var ftdH = $new("td");
392 var ftd0 = $new("td");
393 var ftd1 = $new("td");
394 var ftd2 = $new("td");
395 var ftd3 = $new("td");
396 var ftd4 = $new("td");
397 ftdH.setAttribute("width", "1px");
398 ftd2.setAttribute("width", "1px");
399 ftd3.setAttribute("width", "1px");
400 ftd4.setAttribute("width", "1px");
401
402 ftdH.setAttribute("class", "tcell1");
403 ftd0.setAttribute("class", "tcell1");
404 ftd1.setAttribute("class", "tcell2");
405 ftd2.setAttribute("class", "tcell2");
406 ftd3.setAttribute("class", "tcell2");
407 ftd4.setAttribute("class", "tcell2");
408
409 ftab.appendChild(ftdH);
410 ftab.appendChild(ftd0);
411 ftab.appendChild(ftd1);
412 ftab.appendChild(ftd2);
413 ftab.appendChild(ftd3);
414 ftab.appendChild(ftd4);
415
416 var fdivH = $new("div");
417 var fdiv0 = $new("span");
418 var fdiv1 = $new("span");
419 var fdiv2 = $new("div");
420 var fdiv3 = $new("div");
421 var fdiv4 = $new("div");
422 ftd0.style.paddingLeft = "5px";
423 fdiv4.id="cmd"+z;
424
425 fdiv2.setAttribute("class", "icon_white");
426 fdiv3.setAttribute("class", "icon_white");
427 fdiv4.setAttribute("class", "icon_white");
428 fdiv2.setAttribute("style", "background-position:-72px 50%;");
429 fdiv4.setAttribute("style", "background-position:-432px 50%;");
430 fdiv2.onclick = function () { this.style.backgroundColor='rgba(0,0,0,0.77)'; sendCommand('stop'); this.style.backgroundColor=''; };
431 if (is_cmd)
432 {
433 fdiv3.onclick = function () { this.style.backgroundColor='rgba(0,0,0,0.77)'; submit(name); this.style.backgroundColor=''; };
434 fdiv3.setAttribute("style", "background-position:-109px 50%;");
435 }
436 else
437 {
438 fdiv3.onclick = function () { this.style.backgroundColor='rgba(0,0,0,0.77)'; loadPage('control', z, +1); };
439 fdiv3.setAttribute("style", "background-position:-288px 50%;");
440 }
441
442 if (name.substr(0, 5)=="help-")
443 {
444 fdivH.setAttribute("class", "icon_color");
445 fdivH.setAttribute("style", "background-position:-408px -57px;");
446 //fdivH.setAttribute("style", "background-position:-13px -57px;");
447 }
448 else
449 {
450 fdivH.setAttribute("class", "icon_white");
451 fdivH.setAttribute("style", "background-position:-611px 50%;");
452 fdivH.onclick = function () { this.style.backgroundColor='rgba(0,0,0,0.77)'; loadPage('help-'+name, z, +1); };
453 }
454 fdiv4.onclick = function () { this.style.backgroundColor='rgba(0,0,0,0.77)'; loadPage('scriptlog', z, +1); };
455
456
457 fdiv0.setAttribute("style", "font-size:large;");
458 fdiv1.setAttribute("style", "font-size:small;");
459 fdiv1.id = "localtime"+z;
460
461 fdiv0.onclick = function () { window.location='https://www.fact-project.org/logbook/misc.php?action=mobile'; }
462 fdiv0.appendChild($txt("logbook"));
463 fdiv1.appendChild($txt("loading..."));
464
465 ftdH.appendChild(fdivH);
466 ftd0.appendChild(fdiv0);
467 ftd1.appendChild(fdiv1);
468 ftd2.appendChild(fdiv2);
469 if (name!='control')
470 ftd3.appendChild(fdiv3);
471 if (name!='scriptlog')
472 ftd4.appendChild(fdiv4);
473
474 // ==================================================================
475
476 var tbody = $new("tbody");
477
478 for (var i=0; i<lines.length; i++)
479 {
480 lines[i] = trim(lines[i]);
481
482 if (lines[i][0] == '#')
483 lines.splice(i--, 1);
484 }
485
486 // Concatenate consecutive lines until they have at least two colons
487 for (var i=2; i<lines.length; i++)
488 {
489 if (lines[i].length==0)
490 continue;
491
492 while (i<lines.length)
493 {
494 var cols = lines[i-1].split('|');
495 if (cols.length>=3)
496 break;
497
498 lines[i-1] += lines[i].length==0 ? '<p/>' : " "+lines[i];
499 lines.splice(i,1);
500 }
501 }
502
503 var counter = 1;
504 for (var i=1; i<lines.length; i++)
505 {
506 lines[i] = trim(lines[i]);
507
508 if (lines[i].length==0)
509 continue;
510
511 var cols = lines[i].split('|');
512 if (cols.length != 3 && cols.length !=4)
513 {
514 alert("Wrong number of columns in line #"+i+" in '"+name+"': '"+lines[i]+"' N(cols)="+cols.length);
515 continue;
516 }
517
518 var check = cols[1].split("=");
519
520 if (check.length>1 && (check[0]=="camera" || check[0]=="hist"))
521 {
522 var data = cols[1].substring(check[0].length+1).split("/");
523
524 var tr = $new("tr");
525 tr.setAttribute("class", "row");
526 //tr.setAttribute("style", "margin:0;padding:0;");
527
528 var td = $new("td");
529 td.setAttribute("class", "container");
530 td.id = "container";
531 td.colSpan = 3;
532 tr.appendChild(td);
533
534 var canv = $new("canvas");
535 canv.id = "canvas"+z;
536 canv.width = "1";
537 canv.height = "1";
538 //canv.onclick = function () { save(); }
539 //canv.setAttribute("data-type", check[0]);
540 //canv.setAttribute("data-file", data[0]);
541 //canv.setAttribute("data-data", cols[1].substring(check[0].length+data[0].length+2));
542 canv.dataType = check[0];
543 canv.fileName = data[0];
544 canv.dataUnit = htmlDecode(cols[1].substring(check[0].length+data[0].length+2));
545// canv.setAttribute("style", "display:none;");
546 td.appendChild(canv);
547
548 var img = $new("img");
549 img.src = "img/dummy.png";//needed in firefox
550 img.id = "image"+z;
551 img.setAttribute("style", "width:1px;height:15px;display:none;");
552 td.appendChild(img);
553
554 tbody.appendChild(tr);
555 continue;
556 }
557
558 var tr = $new("tr");
559 tr.setAttribute("class", "row");
560
561 if (valid(cols[0]))
562 {
563 tr.linkName = cols[0];
564 tr.onclick = function () { this.style.background='#ccb'; loadPage(this.linkName, z, -1); };
565 }
566
567 if (valid(cols[3]))
568 {
569 tr.linkName = cols[3];
570 tr.onclick = function () { this.style.background='#cbb'; loadPage(this.linkName, z, +1); };
571 }
572
573 var td0 = $new("td");
574 td0.setAttribute("class", "tcol0");
575 tr.appendChild(td0);
576
577 if (check.length>0 && check[0]=="image")
578 {
579 var img = $new("img");
580 img.style.width="100%";
581 img.style.display="block";
582 img.src = "img/"+check[1];
583 td0.style.paddingLeft=0;
584 td0.style.border=0;
585 td0.colSpan=3;
586 td0.appendChild(img);
587
588 tbody.appendChild(tr);
589 continue;
590 }
591
592 if (valid(cols[0]))
593 {
594 var sp = $new("div");
595 sp.setAttribute("class", "icon_black");
596 sp.setAttribute("style", "background-position: -144px 50%;");
597 td0.appendChild(sp);
598 }
599
600 var td1 = $new("td");
601 td1.setAttribute("class", "tcol1");
602 td1.width = "100%";
603 tr.appendChild(td1);
604
605 var td2 = $new("td");
606 td2.setAttribute("class", "tcol2");
607 td2.width = "18px";
608
609 if (valid(cols[3]))
610 {
611 var sp = $new("div");
612 sp.setAttribute("class", "icon_black");
613 sp.setAttribute("style", "background-position: -108px 50%;");
614 td2.appendChild(sp);
615 }
616 tr.appendChild(td2);
617
618 var tab = $new("table");
619 tab.width = "100%";
620 td1.appendChild(tab);
621
622 var innertr = $new("tr");
623 tab.appendChild(innertr);
624
625 var cell1 = $new("td");
626 cell1.setAttribute("class", "tcell1");
627
628 var cell2 = $new("td");
629 cell2.setAttribute("class", valid(cols[1]) ? "tcell2" : "tcell2l");
630
631 if (check.length>0 && check[0]=="select")
632 {
633 var args = check[1].split('/');
634
635 if (args.length<2)
636 alert("Argument name missing for'"+check[1]+"'");
637 else
638 {
639 var div = $new("div");
640 div.innerHTML = args[0];
641 cell1.appendChild(div);
642
643 var input = $new("SELECT");
644 input.name = args[1];
645 for (var j=2; j<args.length; j++)
646 input.options.add(new Option(args[j]));
647 cell2.appendChild(input);
648 }
649
650 }
651 if (check.length>0 && check[0]=="input")
652 {
653 var opt = check[1].split('/');
654
655 if (opt.length<2)
656 alert("Argument name missing for'"+check[1]+"'");
657 else
658 {
659 var div = $new("div");
660 div.innerHTML = opt[0];
661 cell1.appendChild(div);
662
663 var input = $new("input");
664 input.name = opt[1];
665 input.type = "text";
666 input.maxlength = 80;
667 input.style.textAlign = "right";
668 input.style.width = "100%";
669 if (opt.length>2)
670 input.value=opt[2];
671
672 cell2.appendChild(input);
673 }
674 }
675 if (check.length==0 || (check[0]!="input" && check[0]!="select"))
676 {
677 var div = $new("div");
678 div.innerHTML = cols[1];
679 cell1.appendChild(div);
680
681 if (cols.length>2 && cols[2].length>0)
682 {
683 cell2.id = "data"+z+"-"+counter;
684 cell2.dataFormat = cols[2];
685 cell2.appendChild($txt("---"));
686 counter++;
687 }
688 else
689 cell1.setAttribute("class", "description");
690 }
691
692 innertr.appendChild(cell1);
693 innertr.appendChild(cell2);
694
695 tbody.appendChild(tr);
696 }
697
698 // ==================================================================
699
700 if (debug == true)
701 {
702 tr = $new("tr");
703 tr.setAttribute("class", "row");
704
705 td = $new("td");
706 td.id = "debug"+z;
707 td.colSpan = 3;
708 tr.appendChild(td);
709
710 tbody.appendChild(tr);
711 }
712
713 // ==================================================================
714
715 var table = $("table"+z);
716 if (table)
717 $("body").removeChild(table);
718
719 table = $new("table");
720 table.id = "table"+z;
721 table.border = 0;
722 table.cellSpacing = 0;
723 table.cellPadding = "0px";
724 //table.setAttribute("style", "overflow:hidden;position:fixed;top:0px;left:"+window.innerWidth+"px;")
725 table.setAttribute("style",
726 "position:fixed;width:100%;top:0px;"+
727 "left:"+window.innerWidth+"px;");
728
729 table.appendChild(th);
730 table.appendChild(tbody);
731 table.appendChild(tf);
732
733 $("body").appendChild(table);
734
735 // ==================================================================
736
737 /*
738 // Scrollbar for just the body
739 table.style.position = "fixed";
740 th.style.position = "aboslute";
741 tf.style.position = "aboslute";
742 tbody.style.overflowY = "auto";
743 tbody.style.display = "block";
744 tbody.style.height = (window.innerHeight-th.clientHeight-tf.clientHeight)+"px";
745 tbody.id = "tbody"+z;
746 th.id = "thead"+z;
747 tf.id = "tfoot"+z;
748 */
749
750 // ==================================================================
751
752 table.pageName = name;//setAttribute("data-file", name);
753
754 // This is needed so that the page is extended in height
755 // _before_ the sliding (in case it contains graphics
756 doresize(z);
757}
758
759function doresize(z)
760{
761 var img = $("image"+z);
762 var canv = $("canvas"+z);
763 if (!img || !canv)
764 return;
765
766 var h = $("table"+z).offsetHeight;
767 if (h == 0)
768 return;
769
770 // ===========================================
771 /*
772 var tb = $("tbody"+z);
773 var hw = $("thead"+z).clientHeight;
774 var fw = $("tfoot"+z).clientHeight;
775
776 tb.style.height = (window.innerHeight-hw-fw)+"px";
777 */
778 // ===========================================
779
780 var fixedw = $("body").displayFixedWidth;//getAttribute("data-width");
781 var fixedh = $("body").displayFixedHeight;//getAttribute("data-height");
782
783 var W = fixedw>0 ? fixedw : window.innerWidth;
784 var H = fixedh>0 ? fixedh : window.innerHeight;
785
786 //var max = $("body").getAttribute("data-max")=="yes";
787 var max = $("body").displayMax;
788
789 var ih = max ? W : H - h + parseInt(img.style.height, 10);
790
791 // This might create the scroll bar
792
793 if (img.style.height!=ih+"px")
794 img.style.height = ih+"px";
795 if (canv.height!=ih)
796 canv.height = ih;
797
798 // now we can evaluate the correct view-port
799 // (-2 is the border size of the parent element 'container')
800 //var sW = (fixedw ? fixedw : $("table"+z).scrollWidth)-2;
801 var sW = fixedw ? fixedw : canv.parentNode.clientWidth;
802
803 if (img.style.width!=sW+"px")
804 img.style.width = sW+"px";
805 if (canv.width!=sW)
806 canv.width = sW;
807
808 // ------ debug -----
809 if (debug == true)
810 {
811 $('debug'+z).innerHTML = "";
812 $('debug'+z).innerHTML += "|W="+W +"/"+H;
813 $('debug'+z).innerHTML += "|H="+h+"/"+$("table"+z).offsetHeight+"/"+img.offsetHeight;
814 $('debug'+z).innerHTML += "|I="+img.style.height+"+"+H+"-"+h;
815 }
816}
817
818var intervalSlide = null;
819
820function changePage(oldz, newz)
821{
822 // No page displayed yet
823 if (oldz==newz)
824 {
825 var tab = $("table"+newz);
826
827 tab.style.left="0px";
828 tab.style.position="absolute";
829
830 $("body").visiblePage = newz; //.setAttribute("data-visible", newz);
831
832 doresize(newz);
833
834 //setInterval(refresh_text, 1000);
835 //setInterval(refresh_graphics, 5000);
836
837 refresh_text();
838
839 // first: decode the pixel mapping!
840 var sum = 1036080;
841 for (var i=0; i<1440; i++)
842 {
843 var d0 = codedMap.charCodeAt(i*2) -48;
844 var d1 = codedMap.charCodeAt(i*2+1)-48;
845
846 map[i] = d0 | (d1<<6);
847 sum -= map[i];
848 }
849 if (sum!=0)
850 alert("Pixel mapping table corrupted!");
851
852 refresh_graphics();
853 return;
854 }
855
856 var W = window.innerWidth;
857 if (W==0 || $("body").displayNoslide)//$("body").getAttribute("data-noslide")=="yes")
858 {
859 $("body").visiblePage = newz;//setAttribute("data-visible", newz);
860 $("body").removeChild($("table"+oldz));
861 $("table"+newz).style.left="0px";
862 return;
863 }
864
865 if (newz>oldz)
866 $("table"+newz).style.left = W+"px";
867 else
868 $("table"+newz).style.left = (-W-1)+"px";
869
870 $("body").visiblePage = newz;//setAttribute("data-visible", newz);
871
872 // This is needed on my mobile to ensure that te browser
873 // doesn't try to zoom during shifting
874 $("table"+newz).style.position="fixed";
875 $("table"+oldz).style.position="fixed";
876
877 intervalSlide = setInterval(function (){doShift(oldz,newz);}, 75);
878}
879
880function doShift(oldz, newz)
881{
882 var t0 = $("table"+oldz);
883 var t1 = $("table"+newz);
884
885 if (t0.style.display=="none")
886 {
887 clearInterval(intervalSlide);
888 $("body").removeChild(t0);
889
890 t1.style.position="absolute";
891
892 // Now the scroll bar might have to appear or disappear
893 doresize(newz);
894 return;
895 }
896
897 var x0 = t0.offsetLeft;
898 var x1 = t1.offsetLeft;
899
900 var W = window.innerWidth;
901
902 if (newz<oldz)
903 {
904 x0 += W/5;
905 x1 += W/5;
906 }
907
908 if (newz>oldz)
909 {
910 x0 -= W/5;
911 x1 -= W/5;
912 }
913
914 if ((newz<oldz && x1>=0) || (newz>oldz && x1<=0))
915 {
916 t0.style.display="none";
917 x1 = 0;
918 }
919
920 t0.style.left = x0+"px";
921 t1.style.left = x1+"px";
922}
923
924var timeoutText = null;
925var timeoutGraphics = null;
926
927function refresh_text()
928{
929 var z=$("body").visiblePage;//getAttribute("data-visible");
930
931 var fname = $("table"+z).pageName;//getAttribute("data-file");
932
933 var is_help = fname.substr(0,5)=="help-";
934
935 // Is sliding, no file defined or just help text?
936 if (isSliding() || !valid(fname) || is_help)
937 {
938 if (is_help)
939 {
940 setUTC($("localtime"+z), new Date());
941 $("reporttime"+z).innerHTML="";
942 }
943
944 // invalidate?
945 timeoutText = setTimeout(refresh_text, 1000);
946 return;
947 }
948
949 var xmlText = new XMLHttpRequest();
950 xmlText.open('POST', "data/"+fname+'.data', true);
951 //xmlText.setRequestHeader("If-Match", "*");
952 xmlText.onload = function ()
953 {
954// if (xmlText.status==412)
955// {
956// timeoutText = setTimeout(refresh_text, 3000);
957// return;
958// }
959
960 if (xmlText.status!=200 && xmlText.status!=412)
961 {
962 alert("ERROR[2] - HTTP request '"+fname+".data': "+xmlText.statusText+" ["+xmlText.status+"]");
963 timeoutText = setTimeout(refresh_text, 10000);
964 return;
965 }
966
967 if (!isSliding())
968 {
969 cycleCol($("ldot"+z));
970 update_text(fname, xmlText.responseText);
971 doresize(z);
972 }
973 timeoutText = setTimeout(refresh_text, 3000);
974 };
975 xmlText.send(null);
976}
977
978var date0 = null;
979
980var test = 0;
981function update_text(fname, result)
982{
983 var z=$("body").visiblePage;//getAttribute("data-visible");
984 var table = $("table"+z);
985
986 if (table.pageName/*getAttribute("data-file")*/ != fname)
987 return;
988
989 var tokens = result.split('\n');
990
991 // ----------------------------------------------------
992
993 var rtime = $("reporttime"+z);
994 var ltime = $("localtime"+z);
995
996 var now = new Date();
997
998 var header = tokens[0].split('\t');
999
1000 // File corrupted / should we remove the date?)
1001 if ((header.length>5 || header.length==2 || header.length==0) && header[0].length!=13)
1002 {
1003 // we ignore corrupted files for one minute
1004 if (date0==null || date0.getTime()+60000<now.getTime())
1005 rtime.style.color = "darkred";
1006
1007 return;
1008 }
1009
1010 // File OK
1011 date0 = now;
1012
1013 var stamp = new Date();
1014 stamp.setTime(header[0]);
1015
1016 // File older than 1min
1017 if (stamp.getTime()+60000<now.getTime())
1018 rtime.style.color = "darkred";
1019 else
1020 rtime.style.color = "";
1021
1022 setUTC(rtime, stamp);
1023 setUTC(ltime, now);
1024
1025 // ----------------------------------------------------
1026
1027 $("warn"+z).style.display = header.length>=4 && header[3]=='1' ? "" : "none";
1028
1029 if (header.length>=5)
1030 $("cmd"+z).style.backgroundColor = header[4]=='1' ? "darkgreen" : "darkred";
1031
1032 if (header.length>=3 && $("body").sound)
1033 {
1034 $("speaker"+z).style.display = "none";
1035
1036 var audio = $("audio");
1037
1038 var audio_date = new Date();
1039 audio_date.setTime(header[1]);
1040
1041 // Time stamp of audio file must be newer than page load
1042 // or last audio play respecitvely
1043 if (audio_date>audio.date && header[2].length>0)
1044 {
1045 var name = "audio/"+header[2];
1046
1047 var mp3 = $new("SOURCE");
1048 var ogg = $new("SOURCE");
1049 mp3.src = name+".mp3";
1050 ogg.src = name+".ogg";
1051
1052 audio.replaceChild(mp3, audio.firstChild);
1053 audio.replaceChild(ogg, audio.lastChild);
1054
1055 audio.load();
1056 audio.play();
1057
1058 audio.date = audio_date;
1059 }
1060 }
1061
1062 // ----------------------------------------------------
1063
1064 //var p = table.tBodies.length==3 ? 1 : 0;
1065 //var tbody = table.tBodies[p];
1066
1067 for (var line=1; line<tokens.length; line++)
1068 {
1069 if (tokens[line].length==0)
1070 continue;
1071
1072 var e = $("data"+z+"-"+line);
1073 if (!e)
1074 continue;
1075
1076 var form = e.dataFormat;//getAttribute("data-form");
1077 if (!form)
1078 continue;
1079
1080 var cols = tokens[line].split('\t');
1081 for (var col=1; col<cols.length; col++)
1082 form = form.replace("\$"+(col-1), cols[col].length==0 ? "&mdash;" : cols[col]);
1083
1084 if (cols.length<=1)
1085 form = "&mdash;";
1086
1087 form = form.replace(/<#(.*?)>/g, "<font color='$1'>");
1088 form = form.replace(/<([\+-])>/g, "<font size='$11'>");
1089 form = form.replace(/<\/([#\+-])>/g, "</font>");
1090 form = form.replace(/([0-9][0-9]):([0-9][0-9]):([0-9][0-9])/g,
1091 "<pre>$1</pre>:<pre>$2</pre>:<pre>$3</pre>");
1092 form = form.replace(/--:--:--/g, "<pre> </pre> <pre> </pre> <pre> </pre>");
1093
1094 var newe = $new("div");
1095 newe.innerHTML = form;
1096 e.replaceChild(newe, e.lastChild);
1097
1098 e.parentNode.parentNode.parentNode.parentNode.style.background=cols[0];
1099 }
1100}
1101
1102// http://billmill.org/static/canvastutorial/index.html
1103// http://www.netmagazine.com/tutorials/learning-basics-html5-canvas
1104// http://www.alistapart.com/articles/responsive-web-design/
1105
1106function refresh_graphics()
1107{
1108 var z = $("body").visiblePage;//getAttribute("data-visible");
1109
1110 var canvas = $("canvas"+z);
1111
1112 // Is sliding or no data file defined?
1113 var fname = canvas==null ? "" : canvas.fileName;//getAttribute("data-file");
1114 if (isSliding() || !valid(fname))
1115 {
1116 // invalidate?
1117 timeoutGraphics = setTimeout(refresh_graphics, 3000);
1118 return;
1119 }
1120
1121 var xmlGfx = new XMLHttpRequest();
1122 xmlGfx.open('POST', "data/"+fname, true);
1123 xmlGfx.setRequestHeader("If-Match", "*");
1124 xmlGfx.onload = function ()
1125 {
1126// if (xmlGfx.status==412)
1127// {
1128// timeoutGraphics = setTimeout(refresh_graphics, 5000);
1129// return;
1130// }
1131
1132 if (xmlGfx.status!=200 && xmlGfx.status!=412)
1133 {
1134 alert("ERROR[3] - Request '"+fname+"': "+xmlGfx.statusText+" ["+xmlGfx.status+"]");
1135 timeoutGraphics = setTimeout(refresh_graphics, 10000);
1136 //****** invalidate ******
1137 return;
1138 }
1139
1140 if (!isSliding())
1141 {
1142 cycleCol($("rdot"+z));
1143 process_eventdata(xmlGfx.responseText);
1144 }
1145 timeoutGraphics = setTimeout(refresh_graphics, 5000)
1146 };
1147 xmlGfx.send(null);
1148}
1149
1150
1151function hueToRGB(hue)
1152{
1153 hue /= 3;
1154 hue %= 6;
1155
1156 if (hue<1) return parseInt(255*hue, 10);
1157 if (hue<3) return parseInt(255, 10);
1158 if (hue<4) return parseInt(255*(4-hue), 10);
1159
1160 return 0.
1161}
1162
1163function hueToHex(flt)
1164{
1165 var s = hueToRGB(flt).toString(16);
1166 return s.length==2 ? s : "0"+s;
1167}
1168
1169function HLStoRGB(hue)
1170{
1171 hue *= 14;
1172
1173 var sr = hueToHex(20-hue);
1174 var sg = hueToHex(14-hue);
1175 var sb = hueToHex(26-hue);
1176
1177 return sr+sg+sb;
1178}
1179
1180function color(col)
1181{
1182 if (col==65533)
1183 return HLStoRGB(0);
1184
1185 var hue = col/126;
1186 return HLStoRGB(hue);
1187}
1188
1189function toHex(str, idx)
1190{
1191 var ch = str[idx].toString(16);
1192 return ch.length==2 ? ch : "0"+ch;
1193}
1194
1195function drawHex(ctx, x, y, col)
1196{
1197 ctx.fillStyle = "#"+color(col);
1198
1199 ctx.save();
1200
1201 ctx.translate(x, y);
1202 ctx.scale(1/2, 1/3);
1203
1204 ctx.beginPath();
1205 ctx.moveTo( 1, 1);
1206 ctx.lineTo( 0, 2);
1207 ctx.lineTo(-1, 1);
1208 ctx.lineTo(-1, -1);
1209 ctx.lineTo( 0, -2);
1210 ctx.lineTo( 1, -1);
1211 ctx.fill();
1212
1213 ctx.restore();
1214}
1215
1216function drawDisc(ctx, x, y, r, col)
1217{
1218 ctx.fillStyle = "#"+color(col);
1219
1220 ctx.save();
1221
1222 ctx.translate(x, y);
1223
1224 ctx.beginPath();
1225 ctx.arc(0, 0, r, 0, Math.PI*2, true);
1226 ctx.fill();
1227
1228 ctx.restore();
1229}
1230
1231function beginDrawCam(scale)
1232{
1233 var z = $("body").visiblePage;//getAttribute("data-visible");
1234 var canv = $("canvas"+z);
1235
1236 var w = Math.min(canv.width/scale, canv.height/scale);
1237
1238 var ctx = canv.getContext("2d");
1239
1240 ctx.save();
1241 ctx.translate(canv.width/2, canv.height/2);
1242 ctx.scale(w*2, w*2);
1243
1244 return ctx;
1245}
1246
1247/**
1248 * @constructor
1249 */
1250function Position(s, ring, i)
1251{
1252 switch (s)
1253 {
1254 case 1: this.x = ring - i*0.5; this.y = + i; break;
1255 case 2: this.x = ring*0.5 - i; this.y = ring ; break;
1256 case 3: this.x = -ring*0.5 - i*0.5; this.y = ring - i; break;
1257 case 4: this.x = -ring + i*0.5; this.y = - i; break;
1258 case 5: this.x = -ring*0.5 + i; this.y = -ring ; break;
1259 case 0: this.x = ring*0.5 + i*0.5; this.y = -ring + i; break;
1260 }
1261 this.d = (function () { return this.x*this.x + this.y*this.y*3/4; });
1262}
1263
1264function drawFullCam(data)
1265{
1266 if (data.length!=40 && data.length!=160 && data.length!=320 && data.length!=1440)
1267 {
1268 alert("Camera - Received data has invalid size ("+data.length+"b)");
1269 return;
1270 }
1271
1272 var div = map.length/data.length;
1273 var off = data.length==320 ? 0.2 : 0;
1274
1275 var ctx = beginDrawCam(83);
1276 // ctx.rotate(Math.PI/3);
1277
1278 ctx.scale(1, Math.sqrt(3)/2);
1279 ctx.translate(-0.5, 0);
1280
1281 drawHex(ctx, 0, 0, data.charCodeAt(parseInt(map[0]/div+off, 10)));
1282
1283 var cnt = 1;
1284 for (var ring=1; ring<24; ring++)
1285 {
1286 for (var s=0; s<6; s++)
1287 {
1288 for (var i=1; i<=ring; i++)
1289 {
1290 var pos = new Position(s, ring, i);
1291 if (pos.d() - pos.x > 395.75)
1292 continue;
1293
1294 var p = parseInt(map[cnt]/div+off, 10);
1295
1296 drawHex(ctx, pos.x, pos.y, data.charCodeAt(p));
1297 cnt++;
1298 }
1299 }
1300 }
1301
1302 drawHex(ctx, 7, -22, data.charCodeAt(parseInt(map[1438]/div+off, 10)));
1303 drawHex(ctx, 7, 22, data.charCodeAt(parseInt(map[1439]/div+off, 10)));
1304
1305 ctx.restore();
1306}
1307
1308function drawCam(data)
1309{
1310 var ctx = beginDrawCam(27);
1311 ctx.rotate(Math.PI/6);
1312 ctx.scale(1, Math.sqrt(3)/2);
1313
1314 drawHex(ctx, 0, 0, data.charCodeAt(0));
1315
1316 var cnt = 1;
1317 for (var ring=1; ring<=7; ring++)
1318 {
1319 for (var s=0; s<6; s++)
1320 {
1321 for (var i=1; i<=ring; i++)
1322 {
1323 var pos = new Position(s, ring, i);
1324 if (pos.d() > 44)
1325 continue;
1326
1327 if (ring==7)
1328 {
1329 if (i==6 && (s==0 || s==3))
1330 continue;
1331 if (i==1 && (s==1 || s==4))
1332 continue;
1333 }
1334
1335 drawHex(ctx, pos.x, pos.y, data.charCodeAt(cnt++));
1336 }
1337 }
1338 }
1339
1340 ctx.restore();
1341}
1342
1343function drawCamLegend(canv, data)
1344{
1345 var unit = canv.dataUnit;//htmlDecode(canv.getAttribute("data-data"));
1346
1347 var umin = data[1];
1348 var umax = data[2];
1349
1350 var min = data[3]+unit
1351 var med = data[4]+unit;
1352 var max = data[5]+unit;
1353
1354 var v0 = parseFloat(umin);
1355 var v1 = parseFloat(umax);
1356
1357 var diff = v1-v0;
1358
1359 var cw = canv.width;
1360 //var ch = canv.height;
1361
1362 var ctx = canv.getContext("2d");
1363
1364 ctx.font = "8pt Arial";
1365 ctx.textAlign = "right";
1366 ctx.textBaseline = "top";
1367
1368 for (var i=0; i<11; i++)
1369 {
1370 ctx.strokeStyle = "#"+color(126*i/10);
1371 ctx.strokeText((v0+diff*i/10).toPrecision(3)+unit, cw-5, 125-i*12);
1372 }
1373
1374 var mw = Math.max(ctx.measureText(min).width,
1375 ctx.measureText(med).width,
1376 ctx.measureText(max).width);
1377
1378 ctx.textBaseline = "top";
1379 ctx.strokeStyle = "#000";
1380
1381 ctx.strokeText(min, 5+mw, 5+24);
1382 ctx.strokeText(med, 5+mw, 5+12);
1383 ctx.strokeText(max, 5+mw, 5);
1384}
1385
1386function drawGraph(canv, vals, data)
1387{
1388 var unit = canv.dataUnit;//htmlDecode(canv.getAttribute("data-data"));//.split("/");
1389
1390 var umin = vals[1]+unit;
1391 var umax = vals[2]+unit;
1392
1393 var stat = vals.length==4 ? vals[3] :
1394 vals[3]+unit+" / "+vals[4]+unit+" / "+vals[5]+unit;
1395
1396 var cw = canv.width;
1397 var ch = canv.height;
1398
1399 var ctx = canv.getContext("2d");
1400
1401 var dw = 3; // tick width
1402 var fs = 8; // font size
1403
1404 ctx.font = fs+"pt Arial";
1405 ctx.textAlign = "right";
1406
1407 var dim0 = ctx.measureText(umin);
1408 var dim1 = ctx.measureText(umax);
1409
1410 var tw = Math.max(dim0.width, dim1.width)+dw+2;
1411
1412 var ml = 5+tw; // margin left
1413 var mr = 10; // margin right
1414
1415 var mt = 5+2*fs+4; // margin top
1416 var mb = fs/2+4; // margin bottom
1417
1418 var nx = 20;
1419 var ny = 10;
1420
1421 var w = cw-ml-mr;
1422 var h = ch-mt-mb;
1423
1424 ctx.strokeStyle = "#666";
1425
1426 // --- data ---
1427 var cnt = 0;
1428 for (var j=1; j<data.length; j++)
1429 {
1430 if (data[j].length<2)
1431 continue;
1432
1433 ctx.beginPath();
1434 ctx.moveTo(ml, ch-mb-data[j].charCodeAt(0)/126*h);
1435 for (var i=1; i<data[j].length; i++)
1436 ctx.lineTo(ml+w/(data[j].length-1)*i, ch-mb-data[j].charCodeAt(i)/126*h);
1437
1438 // --- finalize data ---
1439 ctx.lineTo(cw-mr, ch-mb);
1440 ctx.lineTo(ml, ch-mb);
1441 ctx.fillStyle = "#"+color(100);
1442 ctx.stroke();
1443
1444 cnt++;
1445 }
1446 if (cnt==1)
1447 ctx.fill();
1448
1449 ctx.beginPath();
1450
1451 // --- grid ---
1452
1453 ctx.strokeStyle = "#eee";
1454
1455 for (var i=1; i<=nx; i++)
1456 {
1457 ctx.moveTo(ml+w*i/nx, ch-mb);
1458 ctx.lineTo(ml+w*i/nx, mt);
1459 }
1460 for (var i=0; i<ny; i++)
1461 {
1462 ctx.moveTo(ml, mt+h*i/ny);
1463 ctx.lineTo(ml+w, mt+h*i/ny);
1464 }
1465 ctx.stroke();
1466 ctx.closePath();
1467 ctx.beginPath();
1468
1469 ctx.strokeStyle = "#000";
1470
1471 // --- axes ---
1472 ctx.moveTo(ml, mt);
1473 ctx.lineTo(ml, ch-mb);
1474 ctx.lineTo(cw-mr, ch-mb);
1475
1476 for (var i=1; i<=nx; i++)
1477 {
1478 ctx.moveTo(ml+w*i/nx, ch-mb-dw);
1479 ctx.lineTo(ml+w*i/nx, ch-mb+dw);
1480 }
1481 for (var i=0; i<ny; i++)
1482 {
1483 ctx.moveTo(ml-dw, mt+h*i/ny);
1484 ctx.lineTo(ml+dw, mt+h*i/ny);
1485 }
1486 ctx.stroke();
1487 ctx.closePath();
1488
1489 ctx.textBaseline = "bottom";
1490 ctx.strokeText(umin, ml-dw-2, ch-1);
1491
1492 ctx.textBaseline = mt>fs/2 ? "middle" : "top";
1493 ctx.strokeText(umax, ml-dw-2, mt);
1494
1495 ctx.textBaseline = "top";
1496 ctx.textAlign = "center";
1497 ctx.strokeText(stat, ml+w/2, 5);
1498}
1499
1500function invalidateCanvas(canv)
1501{
1502 var ctx = canv.getContext("2d");
1503
1504 ctx.fillStyle = "rgba(255, 255, 255, 0.75)";
1505 ctx.fillRect(0, 0, canv.width, canv.height);
1506}
1507
1508function processGraphicsData(canv, result)
1509{
1510 if (result.length==0)
1511 return false;
1512
1513 var ctx = canv.getContext("2d");
1514 ctx.clearRect(0, 0, canv.width, canv.height);
1515
1516 var data = result.split('\x7f');
1517 if (data.length<2)
1518 return false;
1519
1520 var header = data[0].split('\n');
1521 if (header.length<4)
1522 return false;
1523
1524 switch (canv.dataType)
1525 {
1526 //case "camera": drawCam(result); break;
1527 case "hist":
1528 drawGraph(canv, header, data);
1529 break;
1530 case "camera":
1531 drawFullCam(data[1]);
1532 drawCamLegend(canv, header);
1533 break;
1534 }
1535
1536 var now = new Date();
1537 var tm = new Date();
1538 tm.setTime(header[0]);
1539
1540 if (tm.getTime()+60000<now.getTime())
1541 return false;
1542
1543 //$("image"+z).src = canv.toDataURL("image/png");
1544
1545 return true;
1546}
1547
1548function process_eventdata(result)
1549{
1550 var z = $("body").visiblePage;//getAttribute("data-visible");
1551 var canv = $("canvas"+z);
1552 if (!canv)
1553 return;
1554
1555 if (!processGraphicsData(canv, result))
1556 invalidateCanvas(canv);
1557}
1558
1559function save()
1560{
1561 var z = $("body").visiblePage;//getAttribute("data-visible");
1562
1563 var canvas = $("canvas"+z);
1564 var img = canvas.toDataURL("image/png");
1565
1566 img = img.replace("image/png", "image/octet-stream");
1567
1568 document.location.href = img;
1569}
1570
1571window['onload'] = onload;
Note: See TracBrowser for help on using the repository browser.