Dietrich: TOUCH Eventlistener lässt sich nicht löschen

Moin Moin,

...hab da mal ne Frage:

Ich habe einen Touch-EventListener den ich registrieren und wieder löschen möchte. Registrieren klappt, das Löschen weniger.

Das ist mein Script:

let Objekt1 = document.getElementById("Objekt1");

let functionTouch = (o, e) => {
	e.preventDefault();
	o.style.top = `${o.getBoundingClientRect().top + 10}px`;

};

let functionTouchEnd = (o, e) => {
	e.preventDefault();
	o.removeEventListener("touchstart", functionTouch);
	/*
	
	Nun sollte "touchstart" nicht mehr aktiv sein!
	
	*/
};

Objekt1.addEventListener("touchstart", functionTouch.bind(this, Objekt1));
Objekt1.addEventListener("touchend", functionTouchEnd.bind(this, Objekt1));

Der Touchend Listener löst offensichtlich nich so aus wie erwartet, da der Touchstart Listener aktiv bleibt - ich kann das Element nicht nur einmal, sondern beliebig oft über den Bildschirm schieben.

Funktioniert übrigens auch nicht mit einem Touchmove dazwischen.

Warum?

Besten Gruß dem sonnigen Norden, Dietrich

  1. Hallo Dietrich,

    functionTouch.bind(this, Objekt1) ist nicht das gleiche wie functionTouch

    deswegen entfernt der removeEventListener das nicht. Speichere die gebundene Funktion in einer Variablen, dann kannst Du sie zum Registrieren und Deregistrieren nutzen. Aber musst Du überhaupt binden?

    Ohne bind bekommst Du nur das TouchEvent Objekt, und darin sollte das currentTarget Property auf dein Objekt1 verweisen.

    Alternativ könntest Du auch mal schauen, ob Du mit einem Once-Listener klarkommst. Der entfernt sich nach dem ersten Auslösen selbst.

    Objekt1.addEventListener("touchstart", functionTouch, { once:true });
    

    Das funktioniert zwar nicht im IE, aber der kennt auch kein touchstart.

    Rolf

    --
    sumpsi - posui - obstruxi
  2. Lieber Dietrich,

    ich löse das weniger umständlich.

    let Objekt1 = document.getElementById("Objekt1");
    
    let functionTouch = (e) => {
    	e.preventDefault();
    	Objekt1.style.top = `${Objekt1.getBoundingClientRect().top + 10}px`;
    
    };
    
    let functionTouchEnd = (e) => {
    	e.preventDefault();
    	Objekt1.removeEventListener("touchstart", functionTouch);
    	/*
    	
    	Nun sollte "touchstart" nicht mehr aktiv sein!
    	
    	*/
    };
    
    Objekt1.addEventListener("touchstart", functionTouch);
    Objekt1.addEventListener("touchend", functionTouchEnd);
    

    Liebe Grüße

    Felix Riesterer

    1. Hallo Felix,

      ok, das war jetzt zu einfach um drauf zu kommen 😂

      Vorausgesetzt natürlich, es gibt nur ein Element das auf touch reagieren soll.

      Rolf

      --
      sumpsi - posui - obstruxi
      1. Lieber Rolf,

        Vorausgesetzt natürlich, es gibt nur ein Element das auf touch reagieren soll.

        event.target.removeEventListener("touchstart", functionTouch);
        

        Liebe Grüße

        Felix Riesterer

        1. Ne, gibt mehrere Elemente.

          Kommt es da zu Konflikten, wenn ich einem Array von Elementen mit einem forEach() die EventListener anfüge/entferne? In eure Lösungen werden die Elemente ja nicht jeweils den Funktionen übergeben, sondern die Funktionen greifen auf ein außerhalb definiertes Objekt1 zu.

          Touch kann aber anders als Click mehrere Objekte gleichzeitig betreffen, ==> Konflikte was Objekt1 in den Funktionen angeht?

          1. Lieber Dietrich,

            Deine Handler-Funktion (functionTouchEnd) bekommt ein Event-Objekt übermittelt. Dieses kennt eine Eigenschaft target. Dabei handelt es sich um eine Referenz auf das HTML-Element, welches das Event ausgelöst hat. Daher mein Einzeiler, der sich an den Daten des Event-Objektes das "richtige" Element nimmt, um ihm den EventListener wieder wegzunehmen.

            Kommt es da zu Konflikten, wenn ich einem Array von Elementen mit einem forEach() die EventListener anfüge/entferne?

            Nö.

            In eure Lösungen werden die Elemente ja nicht jeweils den Funktionen übergeben, sondern die Funktionen greifen auf ein außerhalb definiertes Objekt1 zu.

            Das war für "nur ein Element". Du willst mehrere. Daher dieser Code:

            let functionTouch = (e) => {
            	e.preventDefault();
            	e.target.style.top = `${Objekt1.getBoundingClientRect().top + 10}px`;
            
            };
            
            let functionTouchEnd = (e) => {
            	e.preventDefault();
            	e.target.removeEventListener("touchstart", functionTouch);
            	/*
            	
            	Nun sollte "touchstart" nicht mehr aktiv sein!
            	
            	*/
            };
            

            Touch kann aber anders als Click mehrere Objekte gleichzeitig betreffen, ==> Konflikte was Objekt1 in den Funktionen angeht?

            Na natürlich! Die Variable solltest Du in den Handlerfunktionen nicht verwenden, sondern abhängig vom auslösenden HTML-Elementobjekt arbeiten. Siehe event.target.

            Liebe Grüße

            Felix Riesterer

            1. Hallo Felix,

              <button id="touchable1">
                 <span>touch me</span>
              </button>
              

              Wenn der touch-Handler auf dem Button registriert ist, der Anwender aber seinen Finger auf das span legt, dann wird dort das touchstart Event ausgelöst und blubbert zum Button hoch.

              Kommt es dort vorbei, wird der Handler aufgerufen. Aber dann bezeichnet event.target das span. Der Buutton ist event.currentTarget (also das Element, an dem das Event gerade vorbei blubbert).

              Wenn das touchable Element kein inneres HTML enthält, ist's egal.

              Rolf

              --
              sumpsi - posui - obstruxi
            2. Dufte, danke Jungs!

              1. Hallo Dietrich,

                und zum Schluss noch ein Tipp:

                Pointerevents reagieren auf Touch- und auf Mausaktionen.

                Gruß
                Jürgen