Another blog



HTML, z-index, Javascript : afficher au dessus un objet select

Publié le 21/03/2008 par Another

Générer du code HTML au dessus d'un select HTML

Vous avez peut être constaté, lorsque vous générer du code HTML en Javascript, que si ce dernier chevauche un objet HTML select, que le select à une priorité d'affichage sur votre code et que par conséquent le select se dessine en plein milieu de votre code. C'est gênant. :-)

Il existe un règle, je ne sais pas vraiment pourquoi, qui fait que le select est toujours au dessus des autres contrôles HTML, et ceci quelque soit les z-index que vous définissez. C'est gênant également :-)

Néanmoins il existe un contrôle qui fait exception à l'hégémonie du select : l'iFrame

Pour masque un objet select, nous avons plusieurs possibilités, je vous propose de découvrir ensemble deux solutions en JavaScript pour palier votre problème.

1. Cacher un objet SELECT ave un JavaScript

Une solution rapide pour résoudre le problème consiste à cacher le ou les objets select gênants, lorsqu'il est nécessaire. Par exemple on peut cacher les select sur le onfocus d'un champ, et les réafficher sur le onblur de ce même champ.

Ceci est une solution bien que personnellement je préfère la seconde (Avec l'iFrame), car cette dernière est plus facilement implémentable et présente l'avantage de ne pas faire disparaitre les select, ce qui fait quand même plus professionnelle.

Exemple de code HTML, JavaScript :

<html>  
  <body>
    <p>
      <label>Mon input</label>
      <input type="text" onfocus="javascript:ClickClack(true);"
                         onblur="javascript:ClickClack(false);">
    </p>
    <p>
      <label>Mon Select juste en dessous</label>
      <select id="selectId">
        <option value="1">Option 1</option>
        <option value="2">Option 2</option>
      </select>
    </p>
  </body>
</html>

<script type="text/javascript">
  function ClickClack(hide) {
    var select = document.getElementById("selectId");
    if (select != null) {
      if (hide) {
        select.style.visibility = "hidden";
      } else {
        select.style.visibility = "visible";
      }
    }
  }
</script>

Dans l'exemple ci-dessus, nous utilisons la propriété Visibility de l'objet select pour le masquer. On pourrait également utiliser la propriété Display, mais pour rappel la différence entre Visibility et Display réside dans le fait que l'espace occupé par le select est conservé dans le cas de Visibility alors que pour Display, l'espace est supprimé ce qui peut donner l'impression que la page bouge lorsque vous effectué le ClickClack

Bien sûr si vous utilisez ce morceau de code JavaScript, je vous conseil grandement d'optimiser la fonction ClickClack, notamment en vue de récupérer les identifiants des Select dynamiquement par exemple.

2. Utilisez une iFrame pour cacher un objet select

L'objet iFrame permet également de régler le problème, car ce dernier peut s'afficher au dessus d'un objet select, et peut surtout s'afficher au dessous d'un autre contrôle Html, par exemple un div.

Dans cette solution, l'iFrame joue un rôle tampon, l'idée est de créer un div avec un z-index de 999 par exemple, puis de créer une iFrame ayant une taille absolument identique au div avec z-index de 998.

De cette manière le select se trouve caché par l'iFrame qui elle même est caché par le div fin de l'histoire.

C'est cette méthode que j'ai utilisé afin d'afficher au dessus des selects dans le WebControl AutoCompletion que je traite dans mon précédent billet.

Je vous propose les fonctions JavaScripts suivantes, extrait du fichier AutoComplete.js du WebControl AutoCompletion en guise d'exemple :

function ShowPanel(htmlResult) {
  if (_div == null) {
	// Création dynamique du div d'affichage des résultats
    _div = window.document.createElement("div");						
    _div.style.top = findY(_sender) + _sender.offsetHeight + "px";
    _div.style.left = findX(_sender) + "px";
    _div.style.width = _sender.offsetWidth + "px";
    _div.className = "AjaxTextbox";
    window.document.body.insertBefore(_div,null);

	// Création de l'iframe avec les mêmes dimensions
	// que le div de résultats
    _iframe = window.document.createElement("iframe");
    _iframe.style.top = _div.offsetTop + "px";
    _iframe.style.left = _div.offsetLeft + "px";
    _iframe.style.width = _div.offsetWidth + "px";
    _iframe.className = "AjaxTextbox";
    window.document.body.insertBefore(_iframe,null);
  }
  _div.innerHTML = htmlResult;
  _div.style.display = "inline";
  _iframe.style.height = _div.offsetHeight + "px";
  _iframe.style.display = "inline";
  _inline = true;
  MoveTo(1);
}

La fonction findX, permet de trouver les coordonnées horizontales
d'un contrôle html dans un page

// Return Aboslute X Position
function findX(obj) {
  var offSet = 0;
  while(obj.offsetParent) {
    offSet += obj.offsetLeft;
    obj = obj.offsetParent;
  }
  return offSet;
}

La fonction findY, permet de trouver les coordonnées verticales 
d'un contrôle html dans un page

// Return Aboslute Y Position
function findY(obj) {
  var offSet = 0;
  while(obj.offsetParent) {
    offSet += obj.offsetTop;
    obj = obj.offsetParent;
  }
  return offSet;
}