DropDown menü készítése jQuery-vel és a velejáró IE-fix

Ügyfelünk kérése alapján el kellett készítenünk egy DropDown menüt a nyitólapjára. Most is - mint általában - a jQuery JavaScript könyvtárban kerestem a megoldást. Rövid keresgélés után megtaláltam a Superfish jQuery plugin-t, mely tökletesen megfelelőnek tűnt a célra...legalábbis első ránézésre.

A probléma a tesztelés során jelentkezett, mégpedig a szokásos IE6/IE7/FF kompatibilitási ellentétek keretében.
Mondanom sem kell, hogy a plugin FF alatt teljesen jól teljesített (ugyanúgy mint Safari-n vagy Opera-n), a Microsoft két böngészőjénél az oldal gyakorlatilag összeomlott.

A menü FF-ban:

DropDown menü FF

Az internet Explorerben elég érdeksen mutatott:

DropDown menü IE

DropDown menü IE

DropDown menü IE

Először úgy gondoltam megkeresem a megoldást, mert biztosan lokális gond van, hiszen az oldalon található bemutatókon nincs gond Internet Explorer alatt sem, de akárhogy csürtem csavartam nem akart működni. Nem csak a kinézettel volt összeakadás, hanem a funkcionalitás sem működött. IE alatt egyszerüen eltünt a DropDown menü amikor elhagytam az egérrel a legfelső meüelemet.

Néhány órányi küszködés után úgy felidegesítettem magam, hogy eldöntöttem inkább írok egy sajátot, hiszen nem egy atomfizika a DropDown menü, főleg a jQuery-t használva.

Nézzük meg, először a HTML osztályokat, az elrendezési szabályokat!

Íme egy főmeü, és a hozzá tartozó DropDown menü:

<div class="menu-sor">
  <div class="ddown-menu">
      <div class="fomenu-ikon">
        <a href="/beteg-vagyok-gyogyulni-akarok"><img src="/themes/nyitolap/images/segiteni_img.jpg" alt="" /></a>
      </div>
      <ul class="submenu">
        <li><?php print l("Pozitív hozzáállás", "pozitiv-hozzaallas"); ?></li>
        <li><?php print l("Gyógyító nevetés", "gyogyito-nevetes"); ?></li>
        <li><?php print l("Függőségek", "fuggosegek"); ?></li>
        <li><?php print l("Mozgásszervi betegségek", "mozgasszervi-betegsegek"); ?></li>
        <li><?php print l("Orvosok, akik agykontrollt végeztek", "orvosok-akik-agykontrollt-vegeztek"); ?></li>
        <li><?php print l("Kiadványok gyógyulni vágyóknak", "kiadvanyok-gyogyulni-vagyoknak"); ?></li>
      </ul>
  </div>
  <div class="fomenu">
    <p><a href="/beteg-vagyok-gyogyulni-akarok">Beteg vagyok és gyógyulni akarok</a></p>
  </div>
  <div class="clear"></div>
</div>

Az l() fgv. használata ne tévesszen meg senkit sem, ez egy beépített Drupal fgv., síma link generálódik belőle.
Tehát a

<li><?php print l("Pozitív hozzáállás", "pozitiv-hozzaallas"); ?></li>

Sorok nyugodtan lecserélhetőek síma HTML elemekre:
<li><a href="/valamilyen-tartalom">Tartalom címe</a></li>

Nézzük meg a css-t, hogy ki is nézzen valahogy, nameg azért vannak benne fontos részek:

<style type="text/css">
ul.submenu {
  position: absolute;
  display: inline;
  z-index: 99;
  border: 5px solid #962ab2;
  display: none;
  margin-left: 65px;
  margin-top: 0;
  width: 250px;
  margin-bottom: 0;
}
ul.submenu li {
  margin: 0;
  padding: 0;
  width: 250px;
}
ul.submenu li a {
  font-size: 10pt;
  display: block;
  color: #409066;
  background: #fdf3fd;
  padding: 5px 20px;
  border-bottom: 1px solid #962ab2;

  margin: 0;
  width: 210px;
  line-height: 14pt;
}
ul.submenu li a:hover {
  background: white;
  text-decoration: none;
}
div.ddown-menu {
  width: 70px;
  float: left;
}
div.ddown-menu div.fomenu-ikon {
  width: 70px;
}
div.fomenu {
  width: 250px;
  float: left;
}
div.fomenu p {
  padding-left: 10px;
  padding-top: 5px;
}
div.menu-sor {
  padding-top: 10px;
}
div.clear {
  clear: both;
}
</style>

Itt volt egy-két érdekesség, amit mindenképpen szeretnék megmelíteni!

Az ul.submenu css definícióban fontos elemek:

  position: absolute;
  display: inline;
  z-index: 99;
  width: 250px;

Az első három nélkül az oldal IE-ben szétcsúszik, a szélesség megadása nélkül pedig IE6-ban csak 70px lesz a lehullómenü szélessége.

Az "ul.submenu" és az "ul.submenu li a" css definíciónál is nagyon fontos a szélesség megadása, mert különben IE6-ban eltűnik a DropDown menü ha az első elemet elhagyjuk (tehát nem tudjuk kivűlasztani mondjuk a második, vagy harmadik elemet a mnüből).
Az a (link) elemnél nyiván a paddingot kivonjuk a szélességből, ezért lesz 40px-el kevesebb.

A harmadik dolog amire figyelni kell az, hogy mindenhol megadtam a margin-bottom értékét, mégpedig 0-nak. Ez is fontos, különben IE6 alatt nagy alsó margót rak minden menüelem alá.

Végül, mint IE6 mint IE7 alatt nem volt megfelelő az "ul.submenu" bal oldali margó értéke (65px), ezért teljesen kiment a DropDown menü a jobb oldalra. Erre a Conditional comments megoldással probálkoztam, vagyis:

<!--[if lte IE 7]>
  margin-left: -5px;
<![endif]-->

De sajnos ez nem reagált semmit, úgyhogy megoldottam ezt is JavaScript-el:

<script type="text/javascript">
$(function() {
  if ($.browser.msie) {
    $('ul.submenu').css("margin-left", "-5px");
  }
});
</script>

Nézzük meg végül a lényeget, a HTML-hez tarotó jQuery kódot, amiben kivitelezzük a DropDown menüt:

<script type="text/javascript">
$(function() {
  var submenu_active = false;
  $(".ddown-menu").hover(
  function() {
    $("ul.submenu", $(this)).show();
    $("ul.submenu", $(this)).hover(
    function() {
      submenu_active = true;
    },
    function() {
      $(this).hide();
      submenu_active = false;
    });
  },
  function() {
    if (!submenu_active) {
      $("ul.submenu", $(this)).hide();
    }
  }
  );
});
</script>

Mit is csinál?

Az oldal betöltődése után létrehoz egy bool tipusú változót, melyben a DropDown menü aktivitását figyeljük, majd végigmegy az összes ddown-menu osztályon, és figyeli a hover esemény.
Amikor bekövetkezik, a hozzá tartozó submenu osztályt előhozza (show), majd ennek a megjelenített menünek figyeli a hover eseményét.
Ha bekövetkezik, akkor a submenu_active változó értéke igaz lesz, hiszen éppen a menüben vagyunk, ha pedig elhagyjuk, akkor elrejtjük, és a submenu_active értékét hamisra állítjuk.
Végül megnézzük, hogy a ddown-menu osztályba tartozó elemek hover eseményének végén a submenu_active igaz-e, és ha nem akkor a DropDown listát eltávolítjuk. Erre azért van szükség, mert olyan szituáció is elképzelhető, hogy valaki nem lép be a submenu-be, csak előhozza. Ha ez a sor kimaradna, akkor ilyen esetekben a sumenu nem tunne el.

szép munka, gracc!