fcceb1ed0798d9c914b6a0193095daabb817a7a8
[plewww.git] / planetlab / minitabs / minitabs.js
1 /*
2  
3   Animated miniTabs by frequency decoder (http://www.frequency-decoder.com/)
4  
5   Based on an idea by Rob L Glazebrook (http://www.rootarcana.com/test/smartmini/) itself
6   derived from the original idea of Stephen Clark (http://www.sgclark.com/sandbox/minislide/)
7  
8   Adjusted by Thierry Parmentelat -- INRIA - uses only forms rather than <a> tags, for supporting http-POST
9   
10   $Id$
11
12 */
13  
14 var miniTab = {
15  currentTab:     0,
16  activeTab:      0,
17  destX:          0,
18  destW:          0,
19  t:              0,
20  b:              0,
21  c:              0,
22  d:              20,
23  animInterval:   null,
24  sliderObj:      null,
25  aHeight:        0,
26  ul:             [],
27  liArr:          [],
28  inputArr:       [],
29         
30  init: function() {
31     if(!document.getElementById || !document.getElementById("miniflex")) return;
32  
33     miniTab.ul          = document.getElementById("miniflex");
34     miniTab.liArr       = miniTab.ul.getElementsByTagName("li");
35     // Thierry: the original impl. relied on <a> links rather than forms - we use ids
36     miniTab.inputArr        = miniTab.ul.getElementsByClassName("minitabs-submit");
37  
38     for(var i = 0, li; li = miniTab.liArr[i]; i++) {
39       li.onmouseover = miniTab.inputArr[i].onfocus = function(e) {
40         var pos = 0;
41         var elem = this;
42         /* move up twice until we find the 'LI' tag */
43         elem = (elem.nodeName == "LI") ? this : this.parentNode;
44         elem = (elem.nodeName == "LI") ? this : this.parentNode;
45         while(elem.previousSibling) {
46           elem = elem.previousSibling;
47           if(elem.tagName && elem.tagName == "LI") pos++;
48  
49         }
50         miniTab.initSlide(pos);
51       }
52     }
53  
54     miniTab.ul.onmouseout = function(e) {
55       miniTab.initSlide(miniTab.currentTab);
56       miniTab.setActive (miniTab.activeTab,false);
57     };
58  
59     for(var i = 0, a; a = miniTab.inputArr[i]; i++) {
60       if(a.className.search("active") != -1) {
61         miniTab.activeTab = miniTab.currentTab = i;
62       }
63       a.style.borderBottom  = "0px";
64       /*a.style.paddingBottom = "6px";*/
65     }
66  
67     miniTab.slideObj                = miniTab.ul.parentNode.appendChild(document.createElement("div"));
68     miniTab.slideObj.appendChild(document.createTextNode(String.fromCharCode(160)));
69     miniTab.slideObj.id             = "animated-tab";
70     miniTab.slideObj.style.top      = (miniTab.ul.offsetTop + miniTab.liArr[miniTab.activeTab].offsetTop + miniTab.inputArr[miniTab.activeTab].offsetTop) + "px";
71     miniTab.slideObj.style.left     = (miniTab.ul.offsetLeft + miniTab.liArr[miniTab.activeTab].offsetLeft + miniTab.inputArr[miniTab.activeTab].offsetLeft) + "px";
72     miniTab.slideObj.style.width    = miniTab.inputArr[miniTab.activeTab].offsetWidth + "px";
73     miniTab.aHeight                 = miniTab.ul.offsetTop + miniTab.liArr[miniTab.activeTab].offsetTop + miniTab.inputArr[miniTab.activeTab].offsetTop;
74  
75     miniTab.initSlide(miniTab.activeTab, true);
76  
77     var intervalMethod = function() { miniTab.slideIt(); }
78     miniTab.animInterval = setInterval(intervalMethod,10);
79   },
80  
81  cleanUp: function() {
82     clearInterval(miniTab.animInterval);
83     miniTab.animInterval = null;
84   },
85  
86  initSlide: function(pos, force) {
87     if(!force && pos == miniTab.activeTab) return;
88     miniTab.setActive (miniTab.activeTab,false);
89     miniTab.activeTab = pos;
90     miniTab.setActive (miniTab.activeTab,true);
91     miniTab.initAnim();
92   },
93  
94  setActive: function (pos,active) {
95     var input=miniTab.liArr[pos].getElementsByClassName("minitabs-submit")[0];
96     var cn=input.className;
97     cn=cn.replace(" active","");
98     if (active) cn += " active";
99     input.className=cn;
100   },
101  
102  initAnim: function() {
103     /* search for the input with type != hidden */
104     var input=miniTab.liArr[miniTab.activeTab].getElementsByClassName("minitabs-submit")[0];
105     miniTab.destX = parseInt(miniTab.liArr[miniTab.activeTab].offsetLeft + input.offsetLeft + miniTab.ul.offsetLeft);
106     miniTab.destW = parseInt(input.offsetWidth);
107     miniTab.t = 0;
108     miniTab.b = miniTab.slideObj.offsetLeft;
109     miniTab.c = miniTab.destX - miniTab.b;
110  
111     miniTab.bW = miniTab.slideObj.offsetWidth;
112     miniTab.cW = miniTab.destW - miniTab.bW;
113  
114     miniTab.slideObj.style.top = (miniTab.ul.offsetTop + miniTab.liArr[miniTab.activeTab].offsetTop + miniTab.inputArr[miniTab.activeTab].offsetTop) + "px";
115   },
116  
117  slideIt:function() {
118  
119     // Has the browser text size changed?
120     if(miniTab.aHeight != miniTab.ul.offsetTop + miniTab.liArr[miniTab.activeTab].offsetTop + miniTab.inputArr[miniTab.activeTab].offsetTop) {
121       miniTab.initAnim();
122       miniTab.aHeight = miniTab.ul.offsetTop + miniTab.liArr[miniTab.activeTab].offsetTop + miniTab.inputArr[miniTab.activeTab].offsetTop
123     };
124  
125     if(miniTab.t++ < miniTab.d) {
126       var x = miniTab.animate(miniTab.t,miniTab.b,miniTab.c,miniTab.d);
127       var w = miniTab.animate(miniTab.t,miniTab.bW,miniTab.cW,miniTab.d);
128  
129       miniTab.slideObj.style.left = parseInt(x) + "px";
130       miniTab.slideObj.style.width = parseInt(w) + "px";
131     } else {
132       miniTab.slideObj.style.left = miniTab.destX + "px";
133       miniTab.slideObj.style.width = miniTab.destW +"px";
134     }
135   },
136  
137  animate: function(t,b,c,d) {
138     if ((t/=d/2) < 1) return c/2*t*t + b;
139     return -c/2 * ((--t)*(t-2) - 1) + b;
140   },
141
142  submit: function (message) {
143     /* ask for confirmation if message is not empty */
144     if (message && ! confirm (message) ) return;
145     this.inputArr[this.activeTab].parentNode.submit();
146   },
147 }
148  
149 window.onload = miniTab.init;
150 window.onunload = miniTab.cleanUp;
151