Linuchs: Javascript-Fehler im PaleMoon

problematische Seite

Moin,

mehrmals am Tag wurde Ubuntu bei mir eingefroren, Verdacht fiel auf den Firefox in Verbindung mit Videos. Deshalb nutze ich ersatzweise PaleMoon.

Auf vielen meiner Seiten gibt es Info-Schaltflächen, die bei Klick einen Hilfstext einblenden. So auch auf der problematischen Seite das Menü.

So soll es aussehen (Firefox):

Beim PaleMoon kommt der Hilfstext nicht, aber die Meldung

Zeile 38 ist event.stopPropagation();

function getHelptextXY( obj, x, y ) {
  getHelptextVar.obj  = obj;
  getHelptextVar.x    = x;  // Mausposition sichern
  getHelptextVar.y    = y;

  if ( obj.id ) {
    event.stopPropagation();  // Klick nicht weiterreichen (liedtexte: Musik springt an)

...

Was ist zu korrigieren?

fragt Linuchs

Edit: Ich hatte keine Idee, welches event undefiniert sein sollte. Gemeint ist vielleicht das Wort „event“?

  1. problematische Seite

    Hallo Linuchs,

    ja, das dürfte die Variable "event" sein. Frage ist: wo kommt sie her? Du deklarierst sie ja nicht oder zeigst nicht, wo sie deklariert wird.

    event ist aber auch eine Variable, die bspw. vom IE bereitgestellt wurde, wenn man ein Event in einem onxxxxx Handler bearbeitet hat. Man konnte dann z.B. sowas schreiben:

    <button onclick="myHandler(event)">Klack</button>
    

    An dieser Stelle weiß ich nicht so genau, wie der Scope dieser event Variablen ist. In Chrome scheint sie global zu sein, so dass Du bei einem Klick dort das Mausevent hast. Da diese Variable legacy ist, hat PaleMoon sie möglicherweise nicht.

    Aber Du kannst es einfach lösen.

    getHelptext.js, Zeile 176ff:

        obj_help[i].addEventListener('click', function (event) {                
          getHelptextXY( this, event.clientX, event.clientY );
          event.stopPropagation(); 
        });
    

    (1) Du rufst hier stopPropagation auf dem event-Parameter auf, den dein Klick-Handler bekommen hat. Brauchst Du den stopPropagation-Aufruf in getHelptextXY überhaupt noch?

    (2) Wenn ja: Übergib event an die Funktion, statt event.clientX und event.clientY, dann kannst Du damit alles machen was Du brauchst. Oder, wenn Du X und Y unbedingt getrennt übergeben willst, übergib event zusätzlich. In event.currentTarget findest Du übrigens auch das Objekt, das geklickt wurde (event.target: Wo wurde das Event ausgelöst, event.currentTarget: Auf welchem Objekt ist der Eventhandler registriert, der das Event bearbeitet. Bei Bubbling relevant)

    Rolf

    --
    sumpsi - posui - obstruxi
    1. problematische Seite

      Hallo Rolf,

      komme erst heute dazu, deinen Rat umzusetzen. Das hat gut geklappt, danke dafür.

      Brauchst Du den stopPropagation-Aufruf in getHelptextXY überhaupt noch?

      Ja, gleich zu Beginn. Ansonsten würde getHelptextXY durchlaufen und erst danach stopPropagation. Da ist der Klick offenbar aber schon weitergeleitet worden.

      Also hier in getHelptext.js 189 kommt er zu spät, habe ihn auskommentiert:

          obj_help[i].addEventListener('click', function (event) {                
            getHelptextXY( event );
      //    event.stopPropagation();
          });
      

      Gruß, Linuchs

      Edit: Habe dieses ausprobiert, funktioniert auch. Ich dachte, stopPropagation „verbrennt“ das Event.

          obj_help[i].addEventListener('click', function (event) {                
            event.stopPropagation();
            getHelptextXY( event );
          });
      

      Edit2: Nee, ziehe ich zurück. stopPropagation braucht eine Bedingung:

        if ( getHelptextVar.obj.id ) {
          event.stopPropagation();  // Klick nicht weiterreichen (liedtexte: Musik springt an)
      ...
      
      1. problematische Seite

        Hallo Linuchs,

        die Propagation verläuft sequenziell. Javascript verarbeitet nichts parallel (von Worker-Threads abgesehen, aber die verarbeiten keine GUI Events).

        Das bedeutet: Wenn auf einem Element ein Event feuert – sei es durch direktes Auslösen oder dadurch, dass es dorthin geblubbert ist –, werden die auf diesem Element für dieses Event registrierten Handler nacheinander ausgeführt. Jeder Handler wird vollständig ausgeführt, bevor der nächste beginnt.

        Heißt also: es ist unerheblich, wo im Handler du stopPropagation oder preventDefault aufrufst. Beides, Propagation und Defaultverarbeitung, finden erst statt, nachdem deine Handlerfunktion zurückgekehrt ist.

        Ausnahme: Deine Handlerfunktion löst asynchrone Vorgänge aus (setTimeout oder Promises). Die asynchronen Schritte werden, wenn sie bereit zur Ausführung sind, in die Mikrotask-Queue gestellt und die wird erst abgearbeitet, wenn das aktuelle Event vollständig verarbeitet ist.

        Dein getHelptextXY ist asynchron; ich meine, ich hätte da Ajax in Erinnerung. Das bedeutet aber auch, dass in getHelptextXY nur der Ajax-Request angetriggert wird. Danach kehrt die Funktion zurück und stopPropagation wird aufgerufen. Du dürftest stopPropagation nicht in dem Eventhandler aufrufen, der die Ajax-Antwort entgegennimmt - DAS würde die Propagation des click-Events nicht verhindern können.

        Wenn das bei Dir nicht so ist, muss ich mir das nochmal auf deiner Seite live und in leuchtenden Farben anschauen.

        Rolf

        --
        sumpsi - posui - obstruxi