// $Id$
drupal_set_html_head('
+<script type="text/javascript" src="/planetlab/prototype/prototype.js"></script>
<script type="text/javascript" src="/planetlab/minitabs/minitabs.js"></script>
<link href="/planetlab/minitabs/minitabs.css" rel="stylesheet" type="text/css" />
');
// (*) 'id' : assign given id to the <li> element
// NOTE
-// values can also be set in the URL, e.g. ?var=value&foo=bar, even for POST'ing
+// (*) values can also be set in the URL, e.g. ?var=value&foo=bar, even for POST'ing
+// (*) several instances can appear on the same page but you need to give them different id's
-// examples
+// EXAMPLES
// function my_tab () { return array('label'=>'Go to google','url'=>'http://google.com'); }
// $tabs=array();
// $tabs[] = my_tab();
// (the form gets submitted whatever the confirmation....)
// (*) you need to tune the image size, which is wrong, as the image should rather be bottom-aligned
-function plc_tabs ($array) {
- print '<div id="minitabs-container">';
- print '<ul id="minitabs-list">';
- print "\n";
+function plc_tabs ($array, $id=NULL) {
+ if (! $id) $id="minitabs";
+ print "<div id='$id' class='minitabs'>";
+ print "<ul>";
foreach ($array as $label=>$todo) {
// in case we have a simple string, rewrite it as an array
if (is_string ($todo)) $todo=array('method'=>'GET','url'=>$todo);
$tracer="class=minitabs";
if ($todo['id'])
$tracer .= " id=".$todo['id'];
- printf ("<li %s>\n",$tracer);
+ print "<li $tracer>";
// set default method
if ( ! $todo['method'] ) $todo['method']='GET';
// extract var=value settings from url if any
if ( ! $values) $values = array();
if ($url_values) $values = array_merge($values,$url_values);
if ( $values ) foreach ($values as $key=>$value) {
- printf('<input class="minitabs-hidden" type=hidden name="%s" value="%s" />',$key,$value);
+ print "<input class='minitabs-hidden' type=hidden name='$key' value='$value' />";
}
$tracer="class=minitabs-submit";
// image and its companions 'height'
} else {
$type='type=button value="' . $label . '"';
}
- printf('<span title="%s">',$todo['bubble']);
+ $bubble=$todo['bubble'];
+ print "<span title='$bubble'>";
$message="";
if ($todo['confirm']) $message=$todo['confirm'] . " ?";
- printf('<input %s %s onclick=\'miniTab.submit("%s");\' />',$tracer,$type,$message);
- printf('</span>',$todo['bubble']);
- printf("</form></li>\n");
+ print "<input $tracer $type onclick='minitabs_namespace.submit(\"$id\",\"$message\")' />";
+ print "</span>";
+ print "</form></li>\n";
}
print '</ul>';
print '</div>';
/*
+ $Id$
Animated miniTabs by frequency decoder (http://www.frequency-decoder.com/)
Based on an idea by Rob L Glazebrook (http://www.rootarcana.com/test/smartmini/) itself
derived from the original idea of Stephen Clark (http://www.sgclark.com/sandbox/minislide/)
- Adjusted by Thierry Parmentelat -- INRIA - uses only forms rather than <a> tags, for supporting http-POST
-
- $Id$
+ Rewritten by Thierry Parmentelat -- INRIA
+ support http-POST
+ support multiple instances
+ uses prototype.js
*/
-/* I'm done with this - write it ourselves - don't care about perfs so much anyway */
-/* define getElementsByClassName on Element if missing */
-function getElementsByClassName (elt,cls) {
- try {
- var retval= elt.getElementsByClassName(cls);
- return retval;
- } catch (err) {
- var retVal = new Array();
- var elements = elt.getElementsByTagName("*");
- for (var i = 0; i < elements.length; i++) {
- var element = elements[i];
- var classes = element.className.split(" ");
- for (var c = 0; c < classes.length; c++)
- if (classes[c] == cls)
- retVal.push(elements[i]);
- }
- return retVal;
- }
+/* class */
+function minitabs () {
+ this.currentTab = 0;
+ this.activeTab = 0;
+ this.destX = 0;
+ this.destW = 0;
+ this.t = 0;
+ this.b = 0;
+ this.c = 0;
+ this.d = 20;
+ this.animInterval = null;
+ this.slideObj = null;
+ this.aHeight = 0;
}
-var miniTab = {
- currentTab: 0,
- activeTab: 0,
- destX: 0,
- destW: 0,
- t: 0,
- b: 0,
- c: 0,
- d: 20,
- animInterval: null,
- sliderObj: null,
- aHeight: 0,
- ul: [],
- liArr: [],
- inputArr: [],
-
- init: function() {
-
- miniTab.ul = document.getElementById("minitabs-list");
- miniTab.liArr = miniTab.ul.getElementsByTagName("li");
- // Thierry: the original impl. relied on <a> links rather than forms
- // we use <input>s and there might be hidden ones, so use a class marker instead
- miniTab.inputArr = getElementsByClassName(miniTab.ul,"minitabs-submit");
-
- for(var i = 0, li; li = miniTab.liArr[i]; i++) {
- li.onmouseover = miniTab.inputArr[i].onfocus = function(e) {
- var pos = 0;
- var elem = this;
- /* some browsers - firefox - somehow trigger this on <input> */
- if (this.nodeName != "LI") return;
- /* move up until we find the 'LI' tag */
- while(elem.previousSibling) {
- elem = elem.previousSibling;
- if(elem.tagName && elem.tagName == "LI") pos++;
-
- }
- miniTab.initSlide(pos,true);
- }
- }
-
- miniTab.ul.onmouseout = function(e) {
- miniTab.initSlide(miniTab.currentTab,true);
- miniTab.setActive (miniTab.activeTab,false);
- };
-
- window.onresize = function (e) {
- miniTab.initSlide (miniTab.activeTab,true);
- }
+minitabs.prototype.init = function (div) {
+ this.ul = div.down('ul');
+ /* the array of <li>'s */
+ this.li_s = this.ul.select('li');
+ /* the array of active <input>'s - without any hidden one */
+ this.input_s = this.ul.select('input.minitabs-submit');
+
+ /* attach event handlers */
+ this.li_s.each ( function (li) {
+ li.observe ('mouseover', function(event) {
+ var elem = event.element();
+ /* make sure we're on the 'li' element */
+ if ( ! elem.match('li') ) elem=elem.up('li');
+ /* determine current position */
+ var pos = 0;
+ while(elem.previousSibling) {
+ elem = elem.previousSibling;
+ if (elem.tagName && elem.tagName == "LI") pos++;
+ }
+ minitabs_namespace.the_minitabs(elem).initSlide(pos,true);
+ } )
+ } );
+
+ this.ul.observe('mouseout', function (event) {
+ var mt = minitabs_namespace.the_minitabs(event.element());
+ mt.initSlide(mt.currentTab,true);
+ mt.setActive (mt.activeTab,false);
+ });
+
+ /* set active and current, default is index 0, set 'active' class otherwise */
+ this.input_s.each ( function (input) {
+ if (input.hasClassName("active")) this.activeTab = this.currentTab = i;
+ });
+
+ /* create slice object */
+ this.slideObj = this.ul.parentNode.appendChild(document.createElement("div"));
+ this.slideObj.appendChild(document.createTextNode(String.fromCharCode(160)));
+ this.slideObj.id = "minitabs-sliding";
+
+ /* position it */
+ this.setSlidingTop();
+ this.slideObj.style.left = (this.ul.offsetLeft + this.li_s[this.activeTab].offsetLeft +
+ this.input_s[this.activeTab].offsetLeft) + "px";
+ this.slideObj.style.width = this.input_s[this.activeTab].offsetWidth + "px";
+ this.aHeight = (this.ul.offsetTop + this.li_s[this.activeTab].offsetTop +
+ this.input_s[this.activeTab].offsetTop);
+
+ this.initSlide(this.activeTab, true);
+
+};
- for(var i = 0, input; input = miniTab.inputArr[i]; i++) {
- if(input.className.search("active") != -1) {
- miniTab.activeTab = miniTab.currentTab = i;
- }
- /*input.style.borderBottom = "0px";*/
- /*input.style.paddingBottom = "6px";*/
- }
-
- miniTab.slideObj = miniTab.ul.parentNode.appendChild(document.createElement("div"));
- miniTab.slideObj.appendChild(document.createTextNode(String.fromCharCode(160)));
- miniTab.slideObj.id = "minitabs-sliding";
+minitabs.prototype.initSlide = function (pos, force) {
+
+ if(!force && pos == this.activeTab) return;
+ this.setActive (this.activeTab,false);
+ this.activeTab = pos;
+ this.setActive (this.activeTab,true);
+ this.initAnim();
+};
+
+minitabs.prototype.setActive = function (pos,active) {
+ var input=this.li_s[pos].select('input.minitabs-submit')[0];
+ if (active)
+ input.addClassName('active');
+ else
+ input.removeClassName('active');
+};
+
+minitabs.prototype.setSlidingTop = function () {
+ var delta=0;
+ /* up 5px for firefox */
+ /*window.console.log('agent=' + navigator.userAgent);*/
+ if (navigator.userAgent.match(/Firefox/)) delta=-5;
+ this.slideObj.style.top = (this.ul.offsetTop + this.li_s[this.activeTab].offsetTop
+ + this.input_s[this.activeTab].offsetTop + delta ) + "px";
+};
+
+minitabs.prototype.initAnim = function() {
+ /* search for the input with type != hidden */
+ var input=this.li_s[this.activeTab].select('input.minitabs-submit')[0];
+ this.destX = parseInt(this.li_s[this.activeTab].offsetLeft + input.offsetLeft
+ + this.ul.offsetLeft);
+ this.destW = parseInt(input.offsetWidth);
+ this.t = 0;
+ this.b = this.slideObj.offsetLeft;
+ this.c = this.destX - this.b;
+
+ this.bW = this.slideObj.offsetWidth;
+ this.cW = this.destW - this.bW;
+
+ this.setSlidingTop();
+};
+
+minitabs.prototype.slideIt = function() {
+
+ // Has the browser text size changed?
+ var active_li = this.li_s[this.activeTab];
+ var active_input = this.input_s[this.activeTab];
+ if (this.aHeight != this.ul.offsetTop + active_li.offsetTop + active_input.offsetTop) {
+ this.initAnim();
+ this.aHeight = this.ul.offsetTop + active_li.offsetTop + active_input.offsetTop;
+ }
+
+
+ if (this.t++ < this.d) {
+ var x = this.animate(this.t,this.b,this.c,this.d);
+ var w = this.animate(this.t,this.bW,this.cW,this.d);
+
+ this.slideObj.style.left = parseInt(x) + "px";
+ this.slideObj.style.width = parseInt(w) + "px";
+ } else {
+ this.slideObj.style.left = this.destX + "px";
+ this.slideObj.style.width = this.destW +"px";
+ }
+};
+
+minitabs.prototype.animate = function(t,b,c,d) {
+ if ((t/=d/2) < 1) return c/2*t*t + b;
+ return -c/2 * ((--t)*(t-2) - 1) + b;
+};
- miniTab.setTop();
+minitabs.prototype.submit = function (message) {
+ /* save activeTab before confirmation; some browsers - firefox - send mouseout during confirm .. */
+ var submitTab = this.activeTab;
+ /* ask for confirmation if message is not empty */
+ if (message && ! confirm (message) ) return;
- miniTab.slideObj.style.left = (miniTab.ul.offsetLeft + miniTab.liArr[miniTab.activeTab].offsetLeft +
- miniTab.inputArr[miniTab.activeTab].offsetLeft) + "px";
- miniTab.slideObj.style.width = miniTab.inputArr[miniTab.activeTab].offsetWidth + "px";
- miniTab.aHeight = (miniTab.ul.offsetTop + miniTab.liArr[miniTab.activeTab].offsetTop +
- miniTab.inputArr[miniTab.activeTab].offsetTop);
-
- miniTab.initSlide(miniTab.activeTab, true);
-
- var intervalMethod = function() { miniTab.slideIt(); }
- miniTab.animInterval = setInterval(intervalMethod,10);
+ /* get the form and trigger */
+ /* window.console.log ("form=" + this.li_s[submitTab].up('form').submit(); */
+ this.li_s[submitTab].down('form').submit();
+
+}
+
+// globals
+var minitabs_namespace = {
+ init: function () {
+ window.console.log('init');
+ $$('div.minitabs').each (function (div) {
+ /* create instance and attach it to the <div> element */
+ div.minitabs = new minitabs ();
+ div.minitabs.init(div);
+ } ) ;
+
+ var intervalMethod = function () {
+ $$('div.minitabs').each (function (div) {
+ minitabs_namespace.the_minitabs(div).slideIt();
+ } ) ;
+ } ;
+ minitabs_namespace.animInterval = setInterval(intervalMethod,10);
},
cleanUp: function() {
- clearInterval(miniTab.animInterval);
- miniTab.animInterval = null;
- },
-
- initSlide: function(pos, force) {
- if(!force && pos == miniTab.activeTab) return;
- miniTab.setActive (miniTab.activeTab,false);
- miniTab.activeTab = pos;
- miniTab.setActive (miniTab.activeTab,true);
- miniTab.initAnim();
- },
-
- setActive: function (pos,active) {
- var input=getElementsByClassName(miniTab.liArr[pos],"minitabs-submit")[0];
- var cn=input.className;
- cn=cn.replace(" active","");
- if (active) cn += " active";
- input.className=cn;
- },
-
- initAnim: function() {
- /* search for the input with type != hidden */
- var input=getElementsByClassName(miniTab.liArr[miniTab.activeTab],"minitabs-submit")[0];
- miniTab.destX = parseInt(miniTab.liArr[miniTab.activeTab].offsetLeft + input.offsetLeft + miniTab.ul.offsetLeft);
- miniTab.destW = parseInt(input.offsetWidth);
- miniTab.t = 0;
- miniTab.b = miniTab.slideObj.offsetLeft;
- miniTab.c = miniTab.destX - miniTab.b;
-
- miniTab.bW = miniTab.slideObj.offsetWidth;
- miniTab.cW = miniTab.destW - miniTab.bW;
-
- miniTab.setTop();
+ clearInterval(minitabs_namespace.animInterval);
+ minitabs_namespace.animInterval = null;
},
- setTop: function () {
- var delta=0;
- /* up 5px for firefox */
- if (navigator.userAgent.match(/Firefox/)) delta=-5;
- miniTab.slideObj.style.top = (miniTab.ul.offsetTop + miniTab.liArr[miniTab.activeTab].offsetTop
- + miniTab.inputArr[miniTab.activeTab].offsetTop + delta ) + "px";
-
+ resize: function (e) {
+ $$('div.minitabs').each ( function (div) {
+ var mt = div.minitabs;
+ mt.initSlide(mt.activeTab,true);
+ } );
},
- slideIt:function() {
-
- // Has the browser text size changed?
- if(miniTab.aHeight != miniTab.ul.offsetTop + miniTab.liArr[miniTab.activeTab].offsetTop + miniTab.inputArr[miniTab.activeTab].offsetTop) {
- miniTab.initAnim();
- miniTab.aHeight = miniTab.ul.offsetTop + miniTab.liArr[miniTab.activeTab].offsetTop + miniTab.inputArr[miniTab.activeTab].offsetTop
- };
-
- if(miniTab.t++ < miniTab.d) {
- var x = miniTab.animate(miniTab.t,miniTab.b,miniTab.c,miniTab.d);
- var w = miniTab.animate(miniTab.t,miniTab.bW,miniTab.cW,miniTab.d);
-
- miniTab.slideObj.style.left = parseInt(x) + "px";
- miniTab.slideObj.style.width = parseInt(w) + "px";
- } else {
- miniTab.slideObj.style.left = miniTab.destX + "px";
- miniTab.slideObj.style.width = miniTab.destW +"px";
- }
- },
-
- animate: function(t,b,c,d) {
- if ((t/=d/2) < 1) return c/2*t*t + b;
- return -c/2 * ((--t)*(t-2) - 1) + b;
+ submit: function (id,message) {
+ $(id).minitabs.submit(message);
},
- submit: function (message) {
- /* save activeTab before confirmation; some browsers - firefox - send mouseout during confirm .. */
- var submitTab = this.activeTab;
- /* ask for confirmation if message is not empty */
- if (message && ! confirm (message) ) return;
- this.inputArr[submitTab].parentNode.parentNode.submit();
+ // find the enclosing minitabs object
+ the_minitabs: function (elem) {
+ if (elem.match('div.minitabs'))
+ return elem.minitabs;
+ else
+ return elem.up('div.minitabs').minitabs;
}
-}
-window.onload = miniTab.init;
-window.onunload = miniTab.cleanUp;
+};
+window.onload = minitabs_namespace.init;
+window.onunload = minitabs_namespace.cleanUp;
+window.onresize = minitabs_namespace.resize;