Onkel Schnitzel: jQuery: Mausposition prüfen mit .is(":hover")

Nabend allerseits,

ich habe auf meiner Seite ein Submenü, das ich beim hovern per jQuery aufklappen lasse:

$("#mainNavi > ul > li").hover(function() {
  $(this).find("nav").stop( false, false ).slideToggle(250);
});

Nun ist aber das Problem, dass beim Klick auf den Hauptmenüpunkt und dem anschließenden Laden der Seite sich die Maus ja immernoch über dem Menüpunkt befindet und deswegen das Submenü sofort wieder aufklappt, was ich ziemlich hässlich finde.

Deshalb würde ich gerne prüfen, ob sich nach dem Laden der Seite der Mauszeiger über dem Navigationmenü befindet, dann ein flag setzen, das das hovern unterbindet und nach .mouseleave() das flag wieder zurücksetzen.

Dazu wollte ich nun .is() nutzen:

$("#mainNavi > ul > li").is(":hover") => liefert mir allerdings die Fehlermeldung: "...unsupported pseudo: hover"

Ändere ich testweise den Selector:

$("#mainNavi").is(":hover") => kommt keine Fehlermeldung, allerdings bekomme ich immer den Rückgabewert false, egal, ob sich die Maus über der #mainNavi befindet oder nicht.

Weiß jemand, warum das so ist? Ist mein Vorgehen vom Ansatz her richtig oder hat jemand eine bessere Idee? Es soll im Prinzip so sein, wie hier: www.fcbayern.de

Besten Dank schonmal

  1. @@Onkel Schnitzel:

    nuqneH

    ich habe auf meiner Seite ein Submenü, das ich beim hovern per jQuery aufklappen lasse:

    Mein Gerät hat keine Maus. Wie soll ich auf deiner Seite navigieren?

    Qapla'

    --
    „Talente finden Lösungen, Genies entdecken Probleme.“ (Hans Krailsheimer)
    1. Hallo Gunnar

      Mein Gerät hat keine Maus. Wie soll ich auf deiner Seite navigieren?

      Indem du auf den Hauptmenüpunkt klickst. Das Untermnür erscheint dann als statisches Untermenü auf der neuen Seite.

      Gruß Onkel Schnitzel

  2. Meine Herren!

    Es soll im Prinzip so sein, wie hier: www.fcbayern.de

    Das hast du aber anders beschrieben. Wenn ich meine Maus ruhig halte, wird nach dem Seiten-Neuaufbau kein Untermenü einblendet, sobald ich sie nur einen Pixel bewege, wird das Untermenü eingeblendet und nicht erst, nachdem mein Maus-Zeiger das Element einmal verlassen hat.

    Nach meinem Wissen verhalten sich alle Browser so. Solang der Maus-Zeiger sich noch nicht bewegt hat, werden auch keine Events (mouseenter, mouseleave) ausgeführt, auch die Pseudoklasse :hover wird erst nach einer Maus-Bewegung vergeben.

    Änderungen an diesem Standard-Verhalten halte ich für kontraproduktiv.

    1. Es soll im Prinzip so sein, wie hier: www.fcbayern.de

      Das hast du aber anders beschrieben. Wenn ich meine Maus ruhig halte, wird nach dem Seiten-Neuaufbau kein Untermenü einblendet, sobald ich sie nur einen Pixel bewege, wird das Untermenü eingeblendet und nicht erst, nachdem mein Maus-Zeiger das Element einmal verlassen hat.

      Im Ernst? Bei mir ist's in Firefox, Chrome und IE so: Ich klicke. z.B. auf den Punkt TEAMS und bewege die Maus anschließend nicht mehr. Das Untermenü verschwindet beim Seitenneuaufbau und erst wenn ich den Punkt TEAMS verlasse und auf einen anderen Menüpunkt wechsle, erscheint es wieder.

  3. Hallo,

    Es gibt einige Browser (z.B. Firefox), die automatisch ein mouseenter feuern, wenn die Seite geladen wird. Das Element unterm Mauszeiger bekommt dann eben das Event. Wenn das zufällig das Menü ist, dann bekommt es eben ein mouseenter-Event.

    Andere Browser feuern den mouseenter erst, wenn der Mauszeiger auf dem Element bewegt wird. Das Element bekommt also initial keinen Event.

    Man kann soweit ich weiß nicht herausbekommen, ob es sich um einen initialen mouseenter handelt oder um einen »normalen« mouseenter-Event. Ich wüsste nicht, an welchem Kriterium man das *eindeutig* erkennen könnte.

    Was du natürlich tun kannst, ist mit dem mousemove-Event zu arbeiten. Das ist aber ein fieser Hack in meinen Augen. Mousemove-Events werden im Gegensatz zu mouseenter auch nicht unbedingt von Geräten emuliert, die eine Touch-Bedienung haben. Von Tastaturbedienung ganz zu schweigen.

    $("#mainNavi > ul > li").is(":hover") => liefert mir allerdings die Fehlermeldung: "...unsupported pseudo: hover"

    Klar. :hover ist ein spezieller CSS-Selektor, den jQuery mit querySelector(All) bzw. der Selektor-Engine Sizzle nicht emulieren kann.

    Es soll im Prinzip so sein, wie hier: www.fcbayern.de

    Dort wird vermutlich serverseitig die active-Klasse gesetzt und clientseitig beim mouseenter auf dem aktive Element geprüft, woher die Maus kommt (event.relatedTarget). Du kannst ja in den Quellcode schauen und die genaue Logik untersuchen.

    Mathias

    1. Hallo molily,

      Dort wird vermutlich serverseitig die active-Klasse gesetzt und clientseitig beim mouseenter auf dem aktive Element geprüft, woher die Maus kommt (event.relatedTarget). Du kannst ja in den Quellcode schauen und die genaue Logik untersuchen.

      das mit der active-Klasse war ne gute Idee, die hatte ich sowieso schon. RelatedTarget hat mich nicht wirklich weitergebracht, aber ich habs jetzt auch so hinbekommen. Es war mal wieder ein Riesenkrampf, obwohls am Ende dann doch recht banal ist. Falls es jemanden interessiert oder jemand noch Optimierungsvorschläge hat, nachfolgend noch das Script.

      Beste Grüße

      Onkel Schnitzel

        
      (function() {  
      		  
      	function slideNavi() {  
      		var li = $("#mainNavi > ul > li");  
      		var sperre = 0;  
      		var checkAktiv = true;  
      		setTimeout(function() {  
      			checkAktiv = false;  
      			// Das SlideDown muss nur gesperrt werden, wenn die Maus direkt nach dem Laden der Seite wirklich noch über dem aktiv-Feld ist => daher kurze Verzögerung. Vorher wurde gesperrt, obwohl die Maus das aktiv-li schon verlassen hatte.  
      		}, 1000);  
      		  
      		li.mouseover(function() {  
      			if ( $(this).hasClass("aktiv") && checkAktiv === true )  {  
      				sperre = 1; // SlideDown sperren  
      			}  
      		});  
      				  
      		li.mouseenter(function() {  
      			if (sperre === 0) {  
      				$(this).find("nav").stop( false, false ).slideDown(250);  
      			}			  
      		});  
        
      		li.mouseleave(function() {  
      				sperre = 0;  
      				checkAktiv = false; // Wenn einmal ein li-Element verlassen wurde, muss nicht mehr gesperrt werden  
      				$(this).find("nav").stop( false, false ).slideUp(250);		  
      		});  
        
      	}  
      	  
      	$(document).ready(slideNavi);  
      	  
      })();