// objet Widget permettant de mettre en place des menus surgissants
// le constructeur prend comme argument deux id d'éléments htmls.

// le passage de la souris sur l'élément opener déclanche le surgissement 
// de l'élément content. Il suffit ensuite de sortir de l'élément content 
// pour le refermer. A l'initialisation l'élément content doit être déclaré 
// caché: style="visibility:hidden". Aucun des éléments qu'il contient ne doit 
// être explicitement déclaré visible, sinon ils restent visibles en permanence.
// l'élément opener doit être géométriquement à l'intérieur du cadre de content,
// mais situé dessous (soit déclaré avant, soit z-index plus petit que le content).

// pour ie: les deux éléments doivent avoir un fond solide (soit background-color
// soit background-image, éventuellement un png transparent pour simuler pas de fond)
// il est possible de déclarer l'élément content à l'intérieur de l'élément opener, 
// ils partagent alors un seul et même positionnement commun (par l'intermédiaire 
// de l'opener), mais il faut décaler content de l'épaisseur des bords de l'opener.

// il semble possible de mettre des widget à l'intérieur des widget: déclarer 
// sous-opener et sous-content à l'intérieur du bloc content de niveau supérieur 
// (sous-opener doit être sans spécification de visibility et sous-content en hidden)
// les sous éléments doivent être strictement contenus à l'intérieur des conteneurs.


/* exemple d'utilisation (positionnement séparé):


<html>
<head>

<script src="widget.js"></script>

<script>
function init(){
  widget=new Widget("myopener","mycontent");
}
</script>

</head>
<body onLoad="setTimeout('init()',200)">

<div id="myopener" style="position:absolute; background-color: lightblue; border: 1px solid black; width:64px; height:64px; top:32px; left:32px;">
MENU
</div>

<div id="mycontent" style="position:absolute; visibility:hidden; background-color: pink; border: 1px solid black; width:256px; height:512px; top:32px; left:32px;">
my content...
</div>

</body>
</html>

*/

function Widget(opener,content){
  this.closing_delay=200;
  
  this.opener=document.getElementById(opener);
  this.opener.widget=this;
  this.opener.onmouseover=function() {this.widget.open();};
  
  this.content=document.getElementById(content);
  this.content.widget=this;
  this.content.onmouseover=function() {this.widget.mouseover();};
  this.content.onmouseout=function() {this.widget.mouseout();};

  this.isopen=false;
  this.closing=false;

  // pour les timeout qui se font dans un contexte global
  // il faut avoir un nom de référence en variable globale
  this.name="widget_"+content;
  eval(this.name+"=this;");
}

// L'ouverture consiste simplement à rendre le cadre content visible
Widget.prototype.open = function(){
  if (!this.isopen){
    this.isopen=true;
    // à l'ouverture la souris est "hors" du cadre surgissant (encore invisible)
    this.mouseout();
    // si dans closing_delay il n'y a pas eu d'événement mouseover sur le content
    // c'est que la souris est ressortie du cadre avant qu'il ne devienne actif
    // donc il se referme (sans attendre un événement mouseout réel qui ne viendra pas)
    this.content.style.visibility="visible"    
  }
}

// La fermeture rend le cadre invisible (et reset des variables internes)
Widget.prototype.close = function(){
  if (this.isopen){
    this.content.style.visibility="hidden"
    this.isopen=false;
    if (this.closing) this.closing=false;
  }
}

// pour vérifier que la souris est bien dans le contenu au moment 
// ou le cadre devient actif, et pour neutraliser la fermeture 
// sur les séquences mouseout/mouseover.
Widget.prototype.mouseover = function (){
  if (this.isopen && this.closing){
    clearTimeout(this.closing);
    this.closing=false;
  }
}

// les passages sur d'autres éléments à l'intérieur de l'élément content 
// génèrent des séquences mouseout/mouseover (il sort et rentre immédiatement): 
// d'ou la nécessité d'un timeout sur la fermeture: si un mouseover apparait 
// rapidement la fermeture est annulée.

Widget.prototype.mouseout = function (){
  if (this.isopen && !this.closing)
    this.closing=setTimeout(this.name+".close()",this.closing_delay);
}


