// Requiert util.js (Element.getChildElements, Object.extend)

/******************************************************************/

/** Syntaxe : uneInfoBox = new InfoBox(idDunDiv, collapsed)
 * En HTML :
 * <div id="idDunDiv">
 *   <div>Texte de l'en-tete</div>
 *   <div>Contenu du corps</div>
 * </div>
 * En JS :
 * var uneBoite = new Infobox("idDunDiv");
*/
/**
 * @class
 * Boîte d'information, avec une en-tête (titre) et un corps (détails)
 * Un clic sur l'en-tête affiche le corps s'il etait masqué, et le
 * masque s'il était affiché.<br/>
 *
 * La boîte a deux icônes, une indiquant qu'elle est déployée, et
 * l'autre qu'elle est repliée. L'url de ces deux icônes est défini
 * dans le prototype de InfoBox : <code>openImgUrl</code> et 
 * <code>closedImgUrl</code>.<br/>
 * 
 * Si les div n'ont pas de classe CSS, le composant leur en ajoute :
 * <code>infoBox</code> pour le div englobant, 
 * <code>infoBoxHeader</code> pour l'en-tête, et
 * <code>infoBoxBody</code> pour le corps. Evidemment, il faut 
 * qu'une feuille de style définisse ces classes.
 * @constructor
 * @param idBox id HTML de la boite
 * @param collapsed (optionnel) booleen indiquant si la boite
 * est fermee (defaut : false)
 */
function InfoBox(idBox, collapsed) {
  /** L'element HTML racine de la boite d'information 
   * @type HTMLTable */
  this.box = document.getElementById(idBox);
  this.checkStructure(idBox);
  /** L'en-tete @type HTMLDiv*/
  this.header = Element.getChildElements(this.box, "div")[0];
  /** Le corps @type HTMLDiv */
  this.body = Element.getChildElements(this.box, "div")[1];
  /** Zone contenant l'icone sur laquelle cliquer @type HTMLSpan */
  this.icon = document.createElement("span");
  /** Icone montrant que le contenu est visible @type HTMLImage*/
  this.openImg = document.createElement("img");
  /** Icone montrant que le contenu est masque @type HTMLImage */
  this.closedImg = document.createElement("img");
  // Initialiser la structure HTML
  this.setStructure();
  // Mettre les styles
  this.setStyle();
  // Faire reagir au clics
  this.setOnClick();
  // Au depart, reduire a l'en-tete ou afficher le contenu
  if (collapsed) {
    this.collapse();
  }
  else {
    this.expand();
  }
}

/** Prototype de Infobox */
InfoBox.prototype = {
  /** Icone par defaut indiquant que le contenu est visible
   * @type String */
  openImgUrl: "ajax/images/open.gif",
  /** Icone par defaut indiquant que le contenu est masque
   * @type String */
  closedImgUrl: "ajax/images/closed.gif",
  /** Couleur de fond du span englobant les icones @type String */
  iconBackground: "white",

  /** Verifier que la boite a 2 enfants div et 2 seulement */
  checkStructure: function(idBox) {
    if (this.box == null || this.box.nodeName != "DIV") {
      Log.error("Element <div id='" + idBox + 
        "'> not found in document");
    }
    else {
      Element.cleanWhiteSpace(this.box);
      var divs = Element.getChildElements(this.box, "div");
      var children = this.box.childNodes;
      var msg = new Array();
      if (divs.length != 2) {
        msg.push("must have 2 inner div (found " 
          + divs.length + ")");
      }
      if ((children.length - divs.length) > 0) {
        msg.push("must contain nothing than 2 div"
          + " (found " + (children.length - divs.length) 
          + " other element(s))");
      }
      if (msg.length > 0) {
        Log.error("Element " + idBox + "\n" + msg.join("\n"));
      }
    }
  },
  
  /** Initialiser la structure HTML */
  setStructure: function() {
    // Reorganiser l'en-tete : ajouter les images devant
    var content = this.header.innerHTML;
    this.header.innerHTML = "";
    this.header.appendChild(this.icon);
    this.icon.appendChild(this.openImg);
    this.openImg.src = this.openImgUrl;
    this.icon.appendChild(this.closedImg);
    this.closedImg.src = this.closedImgUrl;
    this.header.appendChild(document.createElement("span"));
    this.header.lastChild.innerHTML = content;
  },
  
  /* alternative, si on veut rajouter des elements dans l'en-tete
  setStructure: function() {
    // Deplacer le contenu de l'en-tet dans un nouveau di
    var div = document.createElement("div");
    while (this.header.firstChild) {
      div.appendChild(this.header.removeChild(this.header.firstChild));
    }
    // Creer un tableau avec a gauche l'icone
    // et a droite le contenu du div en-tete
    var table = document.createElement("table");
    this.header.appendChild(table);
    table.setAttribute("border", 0);
    table.setAttribute("cellpadding", 0);
    table.setAttribute("cellspacing", 0);
    var tbody = document.createElement("tbody");
    table.appendChild(tbody);
    var tr = document.createElement("tr");
    tbody.appendChild(tr);
    // Le td des icones
    var td = document.createElement("td");
    tr.appendChild(td);
    td.appendChild(this.icon);
    this.icon.appendChild(this.openImg);
    this.icon.appendChild(this.closedImg);
    // Le td du contenu
    td = document.createElement("td");
    td.appendChild(div);
    tr.appendChild(td);
    div.style.marginLeft = "1ex";
  }, */
  
  /** Initialiser l'apparence */
  setStyle: function() {
    // Les classes
    if (this.box.className == "") {
      this.box.className = "infoBox";
    }
    if (this.header.className == "") {
      this.header.className = "infoBoxHeader";
    }
    if (this.body.className == "") {
      this.body.className = "infoBoxBody";
    }
    this.header.style.fontWeight = "bold";
    // Les icones
    this.icon.style.background = this.iconBackground;
    this.icon.style.cursor = "pointer";
    this.icon.style.margin = "0em 1ex 0em 0em";
    this.icon.style.verticalAlign = "middle";
  },
  
  /** Definir la reaction au clic sur l'icone */
  setOnClick: function() {
    var current = this;
    this.icon.onclick = function() {
      if (current.openImg.style.display == "none") {
        current.expand();
      }
      else {
        current.collapse();
      }
    }
  },
  
  /** Montrer le corps (les infos) */
  expand: function() {
    this.openImg.style.display = "";
    this.closedImg.style.display = "none";
    this.body.style.display = "";
  },
  
  /** Cacher le corps */
  collapse: function() {
    this.openImg.style.display = "none";
    this.closedImg.style.display = "";
    this.body.style.display = "none";
  }
};

// Faire de InfoBox le constructeur de son prototype
InfoBox.prototype.constructor = InfoBox;
