4 Animated miniTabs by frequency decoder (http://www.frequency-decoder.com/)
6 Based on an idea by Rob L Glazebrook (http://www.rootarcana.com/test/smartmini/) itself
7 derived from the original idea of Stephen Clark (http://www.sgclark.com/sandbox/minislide/)
9 Rewritten by Thierry Parmentelat -- INRIA
11 support multiple instances
17 function minitabs () {
26 this.animInterval = null;
31 minitabs.prototype.init = function (div) {
32 this.ul = div.down('ul');
33 /* the array of <li>'s */
34 this.li_s = this.ul.select('li');
35 /* the array of active <input>'s - without any hidden one */
36 this.input_s = this.ul.select('input.minitabs-submit');
38 /* attach event handlers */
39 this.li_s.each ( function (li) {
40 li.observe ('mouseover', function(event) {
41 var elem = event.element();
42 /* make sure we're on the 'li' element */
43 if ( ! elem.match('li') ) elem=elem.up('li');
44 /* determine current position */
46 while(elem.previousSibling) {
47 elem = elem.previousSibling;
48 if (elem.tagName && elem.tagName == "LI") pos++;
50 minitabs_namespace.the_minitabs(elem).initSlide(pos,true);
54 this.ul.observe('mouseout', function (event) {
55 var mt = minitabs_namespace.the_minitabs(event.element());
56 mt.initSlide(mt.currentTab,true);
57 mt.setActive (mt.activeTab,false);
60 /* set active and current, default is index 0, set 'active' class otherwise */
61 this.input_s.each ( function (input) {
62 if (input.hasClassName("active")) this.activeTab = this.currentTab = i;
65 /* create slice object */
66 this.slideObj = this.ul.parentNode.appendChild(document.createElement("div"));
67 this.slideObj.appendChild(document.createTextNode(String.fromCharCode(160)));
68 this.slideObj.id = "minitabs-sliding";
72 this.slideObj.style.left = (this.ul.offsetLeft + this.li_s[this.activeTab].offsetLeft +
73 this.input_s[this.activeTab].offsetLeft) + "px";
74 this.slideObj.style.width = this.input_s[this.activeTab].offsetWidth + "px";
75 this.aHeight = (this.ul.offsetTop + this.li_s[this.activeTab].offsetTop +
76 this.input_s[this.activeTab].offsetTop);
78 this.initSlide(this.activeTab, true);
82 minitabs.prototype.initSlide = function (pos, force) {
84 if(!force && pos == this.activeTab) return;
85 this.setActive (this.activeTab,false);
87 this.setActive (this.activeTab,true);
91 minitabs.prototype.setActive = function (pos,active) {
92 var input=this.li_s[pos].select('input.minitabs-submit')[0];
94 input.addClassName('active');
96 input.removeClassName('active');
99 minitabs.prototype.setSlidingTop = function () {
101 /* up 5px for firefox */
102 /*window.console.log('agent=' + navigator.userAgent);*/
103 if (navigator.userAgent.match(/Firefox/)) delta=-5;
104 this.slideObj.style.top = (this.ul.offsetTop + this.li_s[this.activeTab].offsetTop
105 + this.input_s[this.activeTab].offsetTop + delta ) + "px";
108 minitabs.prototype.initAnim = function() {
109 /* search for the input with type != hidden */
110 var input=this.li_s[this.activeTab].select('input.minitabs-submit')[0];
111 this.destX = parseInt(this.li_s[this.activeTab].offsetLeft + input.offsetLeft
112 + this.ul.offsetLeft);
113 this.destW = parseInt(input.offsetWidth);
115 this.b = this.slideObj.offsetLeft;
116 this.c = this.destX - this.b;
118 this.bW = this.slideObj.offsetWidth;
119 this.cW = this.destW - this.bW;
121 this.setSlidingTop();
124 minitabs.prototype.slideIt = function() {
126 // Has the browser text size changed?
127 var active_li = this.li_s[this.activeTab];
128 var active_input = this.input_s[this.activeTab];
129 if (this.aHeight != this.ul.offsetTop + active_li.offsetTop + active_input.offsetTop) {
131 this.aHeight = this.ul.offsetTop + active_li.offsetTop + active_input.offsetTop;
135 if (this.t++ < this.d) {
136 var x = this.animate(this.t,this.b,this.c,this.d);
137 var w = this.animate(this.t,this.bW,this.cW,this.d);
139 this.slideObj.style.left = parseInt(x) + "px";
140 this.slideObj.style.width = parseInt(w) + "px";
142 this.slideObj.style.left = this.destX + "px";
143 this.slideObj.style.width = this.destW +"px";
147 minitabs.prototype.animate = function(t,b,c,d) {
148 if ((t/=d/2) < 1) return c/2*t*t + b;
149 return -c/2 * ((--t)*(t-2) - 1) + b;
152 minitabs.prototype.submit = function (message) {
153 /* save activeTab before confirmation; some browsers - firefox - send mouseout during confirm .. */
154 var submitTab = this.activeTab;
155 /* ask for confirmation if message is not empty */
156 if (message && ! confirm (message) ) return;
158 /* get the form and trigger */
159 this.li_s[submitTab].down('form').submit();
164 var minitabs_namespace = {
166 $$('div.minitabs').each (function (div) {
167 /* create instance and attach it to the <div> element */
168 div.minitabs = new minitabs ();
169 div.minitabs.init(div);
172 var intervalMethod = function () {
173 $$('div.minitabs').each (function (div) {
174 minitabs_namespace.the_minitabs(div).slideIt();
177 minitabs_namespace.animInterval = setInterval(intervalMethod,10);
180 cleanUp: function() {
181 clearInterval(minitabs_namespace.animInterval);
182 minitabs_namespace.animInterval = null;
185 resize: function (e) {
186 $$('div.minitabs').each ( function (div) {
187 var mt = div.minitabs;
188 mt.initSlide(mt.activeTab,true);
192 submit: function (id,message) {
193 $(id).minitabs.submit(message);
196 // find the enclosing minitabs object
197 the_minitabs: function (elem) {
198 if (elem.match('div.minitabs'))
199 return elem.minitabs;
201 return elem.up('div.minitabs').minitabs;
206 window.onload = minitabs_namespace.init;
207 window.onunload = minitabs_namespace.cleanUp;
208 window.onresize = minitabs_namespace.resize;