Ich habe kürzlich einem Freund bei einer WordPress-Seite geholfen. Es ging eigentlich um eine Kleinigkeit: Der zweite Level des Menus sollte in der mobilen Ansicht ein- und ausklappen. “Kein Problem” dachte ich und fing an, den vermeintlichen Dreizeiler zu schreiben.

Da ja WordPress sehr sinnvolle CSS-Klassen vergibt, war die Idee, einfach den Klick-Event aller Menu-Einträge, die Kind-Elemente haben (“.menu-item-has-children”) umzubiegen und ein jquery-Toggle auf das Kind-Element zu legen.

Mit ein wenig Herumprobieren und natürlich Herumgoogeln kam ich dann auf folgende Lösung:

jQuery(document).ready(function($) {
  $("ul.sub-menu").toggle();
  $("li.menu-item-has-children > a").live('click',function(e) {
    e.preventDefault();
    $(this).closest("li").find("ul.sub-menu").slideToggle("slow");
    $(this).closest("li").toggleClass("current-menu-item").siblings().removeClass("current-menu-item");
    $(this).closest("li").siblings().find(".sub-menu").slideUp("slow");
  });
});

Das hat auf meinem Androiden und auch in der Chrome-Vorschau wunderbar funktioniert. Also gab ich die Erfolgsmeldung durch und ging davon aus, dass es läuft. Allerdings gab es nun auf dem iPhone den Effekt, dass man den Menu-Punkt zwei Mal klicken musste, um den gewünschten Effekt zu bekommen. Beim ersten Klick bewegte sich gar nichts.

Die erste Spur, die ich mir ergoogelte, gab den Hinweis, dass das iPhone nur dann jquery-Events registrieren lässt, wenn man dem Element das Attribut cursor auf pointer stellt. Hat bei mir aber nichts gebracht.

Beim weiteren Googeln kam ich auf den Hinweis, dass iOS nicht von einem Klick-Event, sondern von einem Touch-Event ausgeht. Jetzt war nur noch das Problem, dass die anderen Geräte ja nach wie vor einen Klick-Event registrieren. Also kurz auf den User-Agent testen und eine Fallunterscheidung einbauen. Insgesamt sieht das Skript dann so aus:

jQuery(document).ready(function($) {
  $("ul.sub-menu").toggle(); // Klappt zunächst alle Untermenupunkte zu
  var ua = navigator.userAgent, 
  pickclick = (ua.match(/iPad/i) || ua.match(/iPhone/)) ? "touchstart" : "click";
  $("li.menu-item-has-children > a").live(pickclick,function(e) {
    e.preventDefault(); // Verhindet, dass durch den Link auf die Unterseite gesprungen wird
    $(this).closest("li").find("ul.sub-menu").slideToggle("slow");
    $(this).closest("li").toggleClass("current-menu-item").siblings().removeClass("current-menu-item");
    $(this).closest("li").siblings().find(".sub-menu").slideUp("slow");
  });
});

Mich würde jetzt nur interessieren, warum das iPhone dann beim zweiten Klick das gewünschte Verhalten gezeigt hat. Wenn es eben einen anderen Event erwartet, ok. Aber warum dann beim zweiten Klick? Falls Ihr eine Erklärung dafür habt oder Verbesserungen bzw. Anmerkungen generell, freue ich mich über Kommentare!