treewide: Fix typos in comments
[project/luci.git] / applications / luci-app-olsr-viz / htdocs / luci-static / resources / olsr-viz.js
1 /*
2 Copyright (c) 2006, Lorenz Schori <lo@znerol.ch>
3 All rights reserved (Naja: Ich hab' trotzdem was geaendert. Sven-Ola). (Naja:
4 diese Rechte garantiert dir die BSD-Lizenz ja ausdrücklich. Lorenz)
5
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions are met:
8
9 - Redistributions of source code must retain the above copyright notice, this
10 list of conditions and the following disclaimer.
11 - Redistributions in binary form must reproduce the above copyright notice,
12 this list of conditions and the following disclaimer in the documentation
13 and/or other materials provided with the distribution.
14 - Neither the name of the <ORGANIZATION> nor the names of its contributors may
15 be used to endorse or promote products derived from this software without
16 specific prior written permission.
17
18 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
22 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
29 OLSR-Viz is inspired by Wi-viz: http://wiviz.natetrue.com
30
31 Changes:
32 2007-10-04: Added hostname display option -- Stefan Katerkamp <stefan@katerkamp.de>.
33 2007-10-04: Optimized display by moving presentation css out of js -- lo
34 2010-12-11: Changed some paths to make it work with Kamikaze and Luci -- soma
35 */
36
37 var cgi_url = "/cgi-bin/vizdata.sh";
38
39 var maxmetric = 3;
40 var iconvariant = "-mini";
41 var nodes = new Array();
42 var ncount = 0;
43 var newnodes = new Array();
44 var edges = new Array();
45 var iel = 220; // ideal edge length
46 var optsize = 10; // boundingbox around nodes
47
48 var vwidth = 0;
49 var vheight = 0;
50
51 var xoff = 0;
52 var yoff = 0;
53 var scale = 1.0;
54
55 var idle_timeout = 15;
56 var erase_timeout = 60;
57 var dcl_timeout = 250;
58 var dcllow_timeout = 500;
59 var auto_declump = true;
60 var showdesc = true;
61 var auto_save = 1;
62 var now_secs = 5;
63
64 // dom elements
65 var IFrameObj;
66 var maindiv;
67 var nodediv;
68 var edgediv;
69
70 /******* CALL TO SERVER ********/
71 function callToServer(URL) {
72 var IFrameDoc;
73
74 if (IFrameObj.document) {
75 // For IE5 + opera
76 IFrameDoc = IFrameObj.document;
77 }
78 else if (IFrameObj.contentDocument) {
79 // For NS6
80 IFrameDoc = IFrameObj.contentDocument;
81 }
82 else if (IFrameObj.contentWindow) {
83 // For IE5.5 and IE6
84 IFrameDoc = IFrameObj.contentWindow.document;
85 }
86 else {
87 // opera? hmmmm
88 return true;
89 }
90
91 IFrameDoc.location.replace(URL);
92 return false;
93 }
94
95
96 /******** EDGE CLASS ********/
97 function edge(n1,n2){
98 this.getHTML = function()
99 {
100 var nh = "";
101
102 if(this.n1.metric > maxmetric || this.n2.metric > maxmetric) {
103 return "";
104 }
105
106 x = this.n1.x*scale;
107 y = this.n1.y*scale;
108 dx = this.n2.x*scale - x;
109 dy = this.n2.y*scale - y;
110
111 x += xoff*scale + 75;
112 y += yoff*scale + 15;
113
114 imgtag = "<img src='/luci-static/resources/olsr-viz/dot_"
115 if (this.etx > 0 && this.etx < 2) {
116 imgtag += "good.gif'";
117 }
118 else if(this.etx > 2 && this.etx < 5) {
119 imgtag += "ok.gif'";
120 }
121 else if(this.etx > 5 && this.etx < 10) {
122 imgtag += "weak.gif'";
123 }
124 else {
125 imgtag += "down.gif'";
126 }
127 imgtag += " alt='ETX: " + this.etx + "' title='ETX: " + this.etx + "' ";
128
129 d = Math.sqrt(dx*dx+dy*dy);
130
131 for (j = 0; j < d; j += 15) {
132 nh += imgtag + "style='top:"
133 + parseInt(y+dy * j / d) + "px; left:"
134 + parseInt(x+dx * j / d) + "px; "
135 + "width: 4px; height: 4px; position: absolute; z-index: 2' >";
136 }
137
138 nh += "<div style='top:"
139 + parseInt(y+dy * 0.5 - 5) + "px; left:"
140 + parseInt(x+dx * 0.5 - 24) + "px; "
141 + "position: absolute; z-index: 3; width: 48px; text-align: center;' >"
142 + "<span class='label etx' >" + this.etx + "</span></div>";
143
144 return nh;
145 }
146
147 this.isIdle = function()
148 {
149 return (now_secs - this.lastseen > idle_timeout);
150 }
151
152 this.isDead = function()
153 {
154 return (now_secs - this.lastseen > erase_timeout);
155 }
156
157 this.cleanup = function()
158 {
159 if(this.n1 && this.n1.weight) {
160 this.n1.weight--;
161 }
162 if(this.n2 && this.n2.weight) {
163 this.n2.weight--;
164 }
165 if(this.n1 && this.n2) {
166 delete this.n1.edges[n2.ip];
167 delete this.n2.edges[n1.ip];
168 }
169 }
170
171 this.n1 = n1;
172 this.n2 = n2;
173
174 // setup edges within node objects
175 this.n1.weight++;
176 this.n1.edges[n2.ip] = this;
177 this.n2.weight++;
178 this.n2.edges[n1.ip] = this;
179
180 return this;
181 }
182
183 function getEdgeKey(ip1,ip2)
184 {
185 key = "";
186 if(ip1 > ip2) {
187 key = ip2 + "-" + ip1;
188 }
189 else {
190 key = ip1 + "-" + ip2;
191 }
192 return key;
193 }
194
195 function touch_edge(n1,n2,etx)
196 {
197 var key = getEdgeKey(n1.ip,n2.ip);
198 var e = edges[key];
199 if(!e) {
200 e = new edge(n1,n2);
201 edges[key] = e;
202 }
203 e.etx = etx;
204 e.lastseen = now_secs;
205 return e;
206 }
207
208 /******** NODE CLASS ********/
209 function node(ip) {
210 this.getHTML = function()
211 {
212 var nh;
213
214 if(this.metric > maxmetric) {
215 return "";
216 }
217 var igw = 0;
218 for(h in this.hna) {
219 if(h == "0.0.0.0") {
220 igw = 1;
221 break;
222 }
223 }
224 nh =
225 "<div id='node_" + this.ip + "' onmousedown='dragstart(this)' style="
226 + "'top: " + parseInt((this.y+yoff)*scale) + "px; "
227 + "left: " + parseInt((this.x+xoff)*scale) + "px; "
228 + "width: 150px; height: 1px; z-index: 4; "
229 + "position: absolute; background-color: transparent;' >"
230 + "<div><img src='/luci-static/resources/olsr-viz/node"+(igw ? "-hna" : "")+iconvariant + ".gif'"
231 + " alt='node " + this.ip + "' style='border: none;'><br>"
232 + "<a href='http://" + this.ip + "/'>"
233 + "<span class='label ip'>" + this.ip + "</span></a>"
234 + (showdesc && this.desc != "" ?
235 "<br><span class='label desc'>" + this.desc + "</span>" : "")
236 + "</div></div>";
237 return nh;
238 }
239
240 this.isIdle = function()
241 {
242 return (now_secs - this.lastseen > idle_timeout);
243 }
244
245 this.isDead = function()
246 {
247 return (now_secs - this.lastseen > erase_timeout);
248 }
249
250 this.cleanup = function()
251 {
252 ncount--;
253 }
254
255 this.set_metric = function(metric) {
256 this.metric = metric;
257 return this;
258 }
259
260 this.set_desc = function(desc) {
261 this.desc = desc
262 return this;
263 }
264
265 this.update = function() {
266 this.lastseen = now_secs;
267 return this;
268 }
269
270 this.ip = ip;
271 this.x = 0;
272 this.y = 0;
273 this.dx_last=0;
274 this.dy_last=0;
275 this.placed = false;
276 this.weight = 0;
277 this.edges = new Array();
278 this.hna = new Array();
279 this.pinned = false;
280 this.metric = 999;
281 this.desc = "";
282
283 ncount++;
284 return this;
285 }
286
287 function touch_node(ip) {
288 n = nodes[ip];
289 if(!n) {
290 n = new node(ip);
291 nodes[ip] = n;
292 // newnodes.push(n);
293 // push and pop not supported in old ie. shit.
294 newnodes[newnodes.length] = n;
295 }
296 return n;
297 }
298
299 function place_new_nodes() {
300 var nc = 0;
301 for(i = 0;i<newnodes.length;i++){
302 n = newnodes[i];
303 if(n.placed){continue;}
304 if(sp = getCookie("node_"+n.ip)) {
305 xy = sp.split("x");
306 debug_writeln("sp: "+sp+" xy[0]: "+xy[0]+" xy[1]: "+xy[1]);
307 n.x = parseFloat(xy[0]);
308 n.y = parseFloat(xy[1]);
309 }
310 else if(n.weight>1){
311 // see if we find allredy placed nodes
312 ox=0,oy=0;dx=0,dy=0;c=0;
313 for(e in n.edges){
314 if(nodes[e] && nodes[e].placed){
315 if(!ox && !oy) {
316 ox = nodes[e].x;
317 oy = nodes[e].y;
318 }
319 else {
320 dx += nodes[e].x - ox;
321 dy += nodes[e].y - oy;
322 }
323 c++;
324 }
325 }
326 if(c>0) {
327 n.x = ox + dx/c + Math.random()*iel/2-iel/4;
328 n.y = oy + dy/c + Math.random()*iel/2-iel/4;
329 }
330 }
331 else {
332 // begin somewhere
333 n.x = Math.random()*400;
334 n.y = Math.random()*400;
335 }
336 n.placed = true;
337 nc++;
338 }
339 newnodes.length=0;
340 return nc;
341 }
342
343 /******** HNA CLASS ********/
344 function hna(gw,net,mask) {
345 this.gw = gw;
346 this.net = net;
347 this.mask = mask;
348 return this;
349 }
350
351 function touch_hna(node,net,mask) {
352 h = node.hna[net];
353 if(!h) {
354 h = new hna(node.ip,net,mask);
355 node.hna[net] = h;
356 }
357
358 h.lastseen = now_secs;
359 return h;
360 }
361
362 /******** VIZ SETUP AND SETTINGS ********/
363 function viz_setup(iframeid,maindivid,nodedivid,edgedivid) {
364 // assign a reference to the
365 // object to our global variable IFrameObj.
366 IFrameObj=document.getElementById(iframeid);
367 if (document.frames) {
368 // this is for IE5 Mac, because it will only
369 // allow access to the document object
370 // of the IFrame if we access it through
371 // the document.frames array
372 IFrameObj = document.frames[iframeid];
373 }
374
375 draginit();
376
377 maindiv=document.getElementById(maindivid);
378 nodediv=document.getElementById(nodedivid);
379 edgediv=document.getElementById(edgedivid);
380
381 // autosave on exit?
382 if((autosave = getCookie("prefs_autosave"))) {
383 auto_save = parseInt(autosave);
384 }
385 viz_autosave(auto_save);
386
387 // maximum metric of surrounding nodes
388 if(mmx = getCookie("prefs_maxmetric")) {
389 set_maxmetric(mmx,true,true);
390 }
391
392 // scale of view
393 if((savescale = getCookie("prefs_scale")) &&
394 (savescale = parseFloat(savescale))) {
395 set_scale(savescale,true);
396 }
397
398 // scroll - FIXME
399 /*
400 if(val = getCookie("prefs_innerview")) {
401 iv = val.split("x");
402 if (iv[0] && (iv[0] = parseInt(iv[0])) &&
403 iv[1] && (iv[2] = parseInt(iv[2])) &&
404 iv[3] && (iv[3] = parseInt(iv[3])) &&
405 iv[4] && (iv[4] = parseInt(iv[4])))
406 {
407 maindiv.scrollLeft = iv[0] + "px";
408 maindiv.scrollHeight = iv[1] + "px";
409 }
410 }
411 */
412 }
413
414 function viz_save()
415 {
416 // let cookie survive a month
417 exp = new Date();
418 exp.setTime(exp.getTime() + 2592000000);
419 // save node positions
420 for(ip in nodes)
421 {
422 if(nodes[ip].metric > maxmetric) {
423 continue;
424 }
425 setCookie("node_"+ip,nodes[ip].x+"x"+nodes[ip].y,exp);
426 }
427
428 // save maxmetric
429 setCookie("prefs_maxmetric",maxmetric,exp);
430
431 // save zooming
432 setCookie("prefs_scale",scale,exp);
433
434 // save scroll - FIXME
435 setCookie("prefs_innerview",
436 parseInt(maindiv.scrollLeft)+"x"+parseInt(maindiv.scrollTop)+"x"+
437 parseInt(vwidth*scale)+"x"+parseInt(vheight*scale),exp);
438 }
439
440 function viz_autosave(autosave)
441 {
442 auto_save = autosave;
443 if(auto_save) {
444 document.body.onunload=viz_save;
445 }
446 else {
447 deleteCookie("prefs_autosave");
448 }
449 }
450
451 function viz_reset()
452 {
453 deleteAllCookies();
454 for(ip in nodes) {
455 delete nodes[ip];
456 }
457 for(e in edges) {
458 delete edges[e];
459 }
460 viz_update();
461 }
462
463 var updateTimer = 0;
464 function viz_update() {
465 if (updateTimer) {
466 clearTimeout(updateTimer);
467 }
468 now_secs = new Date().getTime()/1000;
469 callToServer(cgi_url);
470 }
471
472 function viz_callback() {
473 if (updateTimer) {
474 clearTimeout(updateTimer);
475 }
476
477 if(place_new_nodes() > 0 && auto_declump) {
478 declump();
479 }
480 refresh();
481 updateTimer = setTimeout('viz_update()', 5000);
482 }
483
484 var refresh_running = false;
485 function refresh() {
486 if(refresh_running) {
487 return;
488 }
489 refresh_running = true;
490
491 var nh = "";
492
493 // refresh nodes
494 nh = "";
495 for (var n in nodes) {
496 if(nodes[n].isDead()) {
497 nodes[n].cleanup();
498 delete nodes[n];
499 }
500 else {
501 nh += nodes[n].getHTML();
502 }
503 }
504 nodediv.innerHTML = nh;
505
506 // refresh edges
507
508 nh = "";
509 for (var e in edges) {
510 if(edges[e].isDead()) {
511 edges[e].cleanup();
512 delete edges[e];
513 }
514 else {
515 nh += edges[e].getHTML();
516 }
517 }
518 edgediv.innerHTML = nh;
519 refresh_running = false;
520 }
521
522 function set_showdesc(doit)
523 {
524 showdesc = doit;
525 if(!noupdate) refresh();
526 }
527
528 function set_autodeclump(doit)
529 {
530 auto_declump = doit;
531 if(doit) {
532 declump();
533 }
534 else {
535 clearTimeout(dclTimer);
536 }
537 }
538
539 function set_scale(inscale,noupdate)
540 {
541 if(!inscale) {
542 inscale = parseFloat(document.getElementById("zoom").value/2);
543 }
544 scale = Math.round(inscale*100)/100;
545 if(!scale || scale<0.1) {
546 scale = 0.1;
547 }
548 document.getElementById("zoom").value = scale*2;
549 if(!noupdate) refresh();
550 }
551
552 function set_maxmetric(inmetric,noupdate,noconfirm)
553 {
554 inmetric = parseInt(inmetric);
555 if(inmetric > 0 || !noconfirm || confirm("warning. setting the maximum metric to zero can lead to expensive calculations if you are connected to a network with many nodes. do you want to proceed?")) {
556 maxmetric = inmetric;
557 }
558 document.getElementById("maxmetric").value = maxmetric;
559 if(!noupdate) refresh();
560 }
561
562 // k = area / nodes
563 function fr(x) {
564 return Math.pow((iel*iel)/x,2);
565 }
566
567 function fa(x) {
568 return Math.pow((x*x)/iel,2);
569 }
570
571 var dclTimer = 0;
572 var declump_running = false;
573 function declump(t) {
574 // clear declump timer
575 if(dclTimer) {
576 clearTimeout(dclTimer);
577 }
578 if(declump_running) {
579 return;
580 }
581 declump_running = true;
582
583 // nodes
584 nc = 0;
585 for (var ip1 in nodes) {
586 nodes[ip1].fr_x=0;
587 nodes[ip1].fr_y=0;
588 nodes[ip1].fa_x=0;
589 nodes[ip1].fa_y=0;
590 nodes[ip1].x_next = nodes[ip1].x;
591 nodes[ip1].y_next = nodes[ip1].y;
592 nodes[ip1].randdisplace = 0;
593 }
594 for (var ip1 in nodes) {
595 if(nodes[ip1].metric > maxmetric || nodes[ip1].pinned) {
596 continue;
597 }
598 for (ip2 in nodes) {
599 if (nodes[ip2].metric > maxmetric || ip1 == ip2) {
600 continue;
601 }
602 dx = (nodes[ip1].x_next - nodes[ip2].x_next);
603 dy = (nodes[ip1].y_next - nodes[ip2].y_next);
604 d = Math.sqrt(dx*dx+dy*dy);
605 d = Math.max(d-optsize,(d+optsize)/optsize);
606
607 nodes[ip1].fr_x += (dx/d) * fr(d);
608 nodes[ip1].fr_y += (dy/d) * fr(d);
609 }
610
611 dx = nodes[ip1].fr_x;
612 dy = nodes[ip1].fr_y;
613 d = Math.sqrt(dx*dx+dy*dy);
614 md = Math.min(d,iel/nodes[ip1].weight);
615 nodes[ip1].x_next += (dx / d) * md;
616 nodes[ip1].y_next += (dy / d) * md;
617 nc++;
618 }
619
620 // edges
621 ec = 0;
622 for (var e in edges) {
623 if (!edges[e].n1 || !edges[e].n2 ||
624 edges[e].n1.metric > maxmetric || edges[e].n2.metric > maxmetric) {
625 continue;
626 }
627 dx = (edges[e].n1.x_next - edges[e].n2.x_next);
628 dy = (edges[e].n1.y_next - edges[e].n2.y_next);
629 d = Math.sqrt(dx*dx+dy*dy);
630 // d = Math.max(d-optsize,(d+optsize)/optsize);
631
632 edges[e].n1.fa_x -= (dx/d) * fa(d);
633 edges[e].n1.fa_y -= (dy/d) * fa(d);
634 edges[e].n2.fa_x += (dx/d) * fa(d);
635 edges[e].n2.fa_y += (dy/d) * fa(d);
636 ec++;
637 }
638
639 // displacement
640 xmin=-20;ymin=-20;xmax=20;ymax=20;dsum=0;
641 for (var ip in nodes) {
642 if(nodes[ip].metric > maxmetric || nodes[ip].pinned) {
643 continue;
644 }
645
646 dx = nodes[ip].fa_x;
647 dy = nodes[ip].fa_y;
648 d = Math.sqrt(dx*dx+dy*dy);
649 dx = (dx / d) * Math.min(d,iel/nodes[ip].weight) * 0.75 + nodes[ip].dx_last * 0.25;
650 dy = (dy / d) * Math.min(d,iel/nodes[ip].weight) * 0.75 + nodes[ip].dy_last * 0.25;
651
652 nodes[ip].dx_last = dx;
653 nodes[ip].dy_last = dy;
654 nodes[ip].x_next += dx;
655 nodes[ip].y_next += dy;
656
657 if(!nodes[ip].x_next || !nodes[ip].y_next) {
658 continue;
659 }
660
661 dx = (nodes[ip].x - nodes[ip].x_next);
662 dy = (nodes[ip].y - nodes[ip].y_next);
663 dsum += Math.sqrt(dx*dx+dy*dy);
664
665 nodes[ip].x = nodes[ip].x_next;
666 nodes[ip].y = nodes[ip].y_next;
667
668 xmin = Math.min(xmin,nodes[ip].x);
669 xmax = Math.max(xmax,nodes[ip].x);
670 ymin = Math.min(ymin,nodes[ip].y);
671 ymax = Math.max(ymax,nodes[ip].y);
672 }
673 vwidth=(xmax-xmin);
674 vheight=(ymax-ymin);
675
676 xoff=-xmin;
677 yoff=-ymin;
678 /*
679 document.getElementById('debug').innerHTML = "<br>" +
680 "offset: " + xoff + "x" + yoff + " dsum: " + dsum + "<br>" +
681 "nc: " + nc + " ec: " + ec + "xmax: " + xmax + " xmin: " + xmin + "<br>" +
682 "optsize: " + optsize + "<br>";
683 */
684 refresh();
685 if(auto_declump) {
686 dclTimer = setTimeout("declump()", dsum>ncount ? dcl_timeout : dcllow_timeout );
687 }
688 declump_running = false;
689 }
690
691 //Das Objekt, das gerade bewegt wird.
692 var dragip = null;
693
694 // Position, an der das Objekt angeklickt wurde.
695 var dragx = 0;
696 var dragy = 0;
697
698 // Mausposition
699 var posx = 0;
700 var posy = 0;
701
702 function draginit() {
703 // Initialisierung der ãberwachung der Events
704
705 document.onmousemove = drag;
706 document.onmouseup = dragstop;
707 }
708
709
710 function dragstart(element) {
711 //Wird aufgerufen, wenn ein Objekt bewegt werden soll.
712 dragip = element.id.split("_")[1];
713 dragx = posx - element.offsetLeft;
714 dragy = posy - element.offsetTop;
715
716 n = nodes[dragip];
717 if(n) {
718 n.pinned = true;
719 }
720 }
721
722
723 function dragstop() {
724 //Wird aufgerufen, wenn ein Objekt nicht mehr bewegt werden soll.
725
726 n = nodes[dragip];
727 if(n) {
728 n.pinned = false;
729 }
730 refresh();
731 dragip=null;
732 }
733
734
735 function drag(ereignis) {
736 //Wird aufgerufen, wenn die Maus bewegt wird und bewegt bei Bedarf das Objekt.
737
738 posx = document.all ? window.event.clientX : ereignis.pageX;
739 posy = document.all ? window.event.clientY : ereignis.pageY;
740 if(dragip != null) {
741 n = nodes[dragip];
742 if(n) {
743 n.x = (posx - dragx)/scale - xoff;
744 n.y = (posy - dragy)/scale - yoff;
745 }
746 e = document.getElementById('node_'+dragip);
747 e.style.left = parseInt((n.x+xoff)*scale) + "px";
748 e.style.top = parseInt((n.y+yoff)*scale) + "px";
749 }
750 }
751
752 function debug_writeln(line)
753 {
754 document.getElementById('debug').innerHTML = line + "<br>" + document.getElementById('debug').innerHTML;
755 }
756
757 /**
758 * Sets a Cookie with the given name and value.
759 *
760 * name Name of the cookie
761 * value Value of the cookie
762 * [expires] Expiration date of the cookie (default: end of current session)
763 * [path] Path where the cookie is valid (default: path of calling document)
764 * [domain] Domain where the cookie is valid
765 * (default: domain of calling document)
766 * [secure] Boolean value indicating if the cookie transmission requires a
767 * secure transmission
768 */
769
770 function setCookie(name, value, expires, path, domain, secure) {
771 document.cookie= name + "=" + escape(value) +
772 ((expires) ? "; expires=" + expires.toGMTString() : "") +
773 ((path) ? "; path=" + path : "") +
774 ((domain) ? "; domain=" + domain : "") +
775 ((secure) ? "; secure" : "");
776 }
777
778 /**
779 * Gets the value of the specified cookie.
780 *
781 * name Name of the desired cookie.
782 *
783 * Returns a string containing value of specified cookie,
784 * or null if cookie does not exist.
785 */
786
787 function getCookie(name)
788 {
789 var results = document.cookie.match ( name + '=(.*?)(;|$)' );
790 if (results) {
791 return unescape(results[1]);
792 }
793 return null;
794 }
795
796 /**
797 * Deletes the specified cookie.
798 *
799 * name name of the cookie
800 * [path] path of the cookie (must be same as path used to create cookie)
801 * [domain] domain of the cookie (must be same as domain used to create cookie)
802 */
803
804 function deleteCookie(name, path, domain) {
805 if (getCookie(name)) {
806 document.cookie = name + "=" +
807 ((path) ? "; path=" + path : "") +
808 ((domain) ? "; domain=" + domain : "") +
809 "; expires=Thu, 01-Jan-70 00:00:01 GMT";
810 }
811 }
812
813 function deleteAllCookies() {
814 cookies = document.cookie.split("; ");
815 for(i=0;i<cookies.length;i++) {
816 deleteCookie(cookies[i].split("=")[0]);
817 }
818 }