Linuchs: onclick funktioniert nicht auf Smartphone

problematische Seite

Hallo,

bisher habe ich geschaut, ob gewisse Webseiten auf dem Smartphone ordentlich aussehen. Aber noch nie habe ich mit dem Smartphone Ajax-Verbindungen getestet. Und prompt funktioniert es auch nicht.

Auf einem Formular sind Namen anzuklicken. Jeder Klick bewirkt per Ajax einen Eintrag in die Datenbank. Bei nochmaligem click wird der Eintrag wieder gelöscht.

Ein bestehender Eintrag wird durch gelbe Hintergrund-Farbe angezeigt.

Klappt vorzüglich auf dem PC unter Firefox, aber nicht mit meinem Android-Browser.

Ich vermute, ein Smartphone versteht die Anweisung onclick nicht. Oder was kann das sein?

Und ja - ich habe vor einer Woche eine Lektion in Event-Handling bekommen, aber nicht verstanden, wie ich den "Absender" des onclick-Events erkenne. Das feuert ja in allen übergeordneten Tags.

Bitte diese Seite mal mit dem Smartphone aufrufen. Ich kann keinen Namen akivieren.

Linuchs

  1. problematische Seite

    Hallo Linuchs,

    Wenn das so aussehen soll, wie im Anhang, scheint es bei mir auf Android 5 mit mBrowser, Firefox und Chrome (jeweils die aktuellsten Versionen) keine Probleme zu geben.Alternativ-Text

    Gruß
    Julius

    1. problematische Seite

      Hallo Julius,

      Wenn das so aussehen soll, wie im Anhang, scheint es bei mir auf Android 5 mit mBrowser, Firefox und Chrome (jeweils die aktuellsten Versionen) keine Probleme zu geben.Alternativ-Text

      Ja, so soll es aussehen. Du hast mit dem Finger auf einen Namen getippt und der wurde sofort gelb unterlegt?

      Ich habe nochmal auf meinem Smartphone getestet. Die Namen werden gewählt, was ich mit dem PC überprüft habe, aber nicht gelb hinterlegt. Beim nächsten Klick wird die Wahl wieder storniert. Die Rückmeldung klappt also nicht.

      Also empfängt mein Smartphone die Ajax-Rückmeldung nicht oder zeigt die Hintergrund-Farbe nicht an.

      Gruß, Linuchs

      1. problematische Seite

        Hallo Linuchs, Alternativ-Text

        Ja, so soll es aussehen. Du hast mit dem Finger auf einen Namen getippt und der wurde sofort gelb unterlegt?

        Ja, unverzüglich.

        Gruß
        Julius

        1. problematische Seite

          @@Julius

          Ja, unverzüglich

          Auf’m iPhone auch.

          LLAP 🖖

          --
          „Wir haben deinen numidischen Schreiber aufgegriffen, o Syndicus.“
          „Hat auf dem Forum herumgelungert …“
          (Wachen in Asterix 36: Der Papyrus des Cäsar)
  2. Hallo Linuchs

    Und ja - ich habe vor einer Woche eine Lektion in Event-Handling bekommen, aber nicht verstanden, wie ich den "Absender" des onclick-Events erkenne. Das feuert ja in allen übergeordneten Tags.

    Ich weiß, dass ich nicht besonders gut im Erklären bin, der von dir angesprochene Thread ist dafür ein trauriges Beispiel. In dieser Hinsicht wäre es aber auch für mich hilfreich gewesen, wenn du nochmals nachgefragt und dabei die einzelnen Stellen angesprochen hättest, die du nicht verstanden hast.

    Mit „Absender“ des Ereignisses meinst du wohl das Element, bei dem das Ereignis eingetreten ist:

    Das ist das Ziel (Target) des Ereignisses.

    Wenn du das Objekt referenzieren willst, welches das Ziel eines Ereignisses ist, dann kannst du dies über die Eigenschaft target des Event-Objektes machen:

    <body>
      <ul id="list">
        <li>A</li>
        <li>B</li>
        <li>C</li>
      </ul>
      <script>
    
    
    document.getElementById('list').addEventListener('click', function (event) {
      if (event.target !== this) {
        console.log(event.target.textContent); // A oder B oder C
      }
    });
    
    
      </script>
    </body>
    

    Hier ist ein Eventhandler für das Objekt registriert, welches das ul-Element mit der ID list repräsentiert, und zwar für das Ereignis click. Dieser Eventhandler wird nun immer dann aufgerufen wenn entweder auf das Listenelement selbst, oder aber auf eines seiner Kindelemente geklickt wird.

    Für die anonyme Funktion die wir der Methode addEventListener hier als zweites Argument übergeben ist ein Parameter event deklariert. Wenn nun die Funktion bei einem Klick innerhalb der Liste aufgerufen wird, dann wird bei diesem Aufruf das Event-Objekt als Argument übergeben, sodass dieses innerhalb der Funktion über event referenziert werden kann.

    Der Wert der Eigenschaft target des Event-Objektes ist nun wie gesagt immer eine Referenz auf das Objekt, bei dem das Ereignis eingetreten ist. Das bedeutet, hier im Beispiel verweist event.target entweder auf das Listenelement selbst, für das wir den Eventhandler registriert haben, oder aber auf eines der Kindelemente der Liste, eben abhängig davon, auf welches der Elemente tatsächlich geklickt wurde.

    Die Variable this hingegen, ebenso wie die Eigenschaft event.currentTarget enthält immer eine Referenz auf das Objekt für welches der aufgerufene Eventhandler registriert wurde. Wenn wir also prüfen

    if (event.target !== this)
    

    dann heißt das soviel wie: „Wenn das Element auf das geklickt wurde nicht das Element ist, für das dieser Eventhander registriert wurde, dann führe die folgende Anweisung aus.“

    Wir hätten an dieser Stelle also ebenso gut schreiben können

    if (event.target !== event.currentTarget)
    

    oder auch

    if (event.target !== document.getElementById('list'))
    

    Da wir das Element ul, für welches wir den Handler registriert haben, durch diese bedingte Anweisung ausgeschlossen haben, wird also nur dann der textuelle Inhalt des Zielobjektes in die Konsole geschrieben, wenn auf eines der li-Elemente geklickt wurde. Sonst passiert nichts.

    console.log(event.target.textContent); // A oder B oder C
    

    Das meinte ich im Übrigen mit „in der Handlerfunktion selektieren“: Den Wert der Eigenschaft target des Event-Objektes lesen und dann abhängig von dem dort referenzierten Zielobjekt die verschiedenen Anweisungen ausführen.

    Drehen wir unser Beispiel einmal um und nehmen an, wir wollten nur dann etwas machen, wenn das Ereignis tatsächlich bei dem ul-Element aufgetreten ist, nicht aber bei einem seiner Kindelemente:

    <body>
      <ul id="list">
        <li>A</li>
        <li>B</li>
        <li>C</li>
      </ul>
      <script>
    
    
    document.getElementById('list').addEventListener('click', function (event) {
      if (event.target.parentElement === document.body) {
        console.log(event.target.tagName); // UL
      }
    });
    
    
      </script>
    </body>
    

    Auch hier ist wieder ein Eventhandler für das ul-Element mit der ID list registriert, und auch hier verwenden wir event.target, um das Element zu identifizieren, auf das tatsächlich geklickt wurde.

    if (event.target.parentElement === document.body) {
      console.log(event.target.tagName); // UL
    }
    

    Hier prüfen wir, ob das Elternelement des Elementes auf das geklickt wurde das body-Element ist. Da das Elternelement der li-Elemente hier natürlich nicht body sondern ul ist, wird die nachfolgende Anweisung nur ausgeführt, wenn auf das Listenelement selbst geklickt wurde.

    Wobei wir bezogen auf dieses konkrete Beispiel freilich besser so geprüft hätten (siehe oben):

    if (event.target === this)
    
    // oder
    
    if (event.target === event.currentTarget)
    

    Wandeln wir das Beispiel nochmals etwas ab, sodass es dem Code recht ähnlich ist, den du im ersten Beitrag des eingangs verlinkten Threads gepostet hattest:

    <body>
      <ul id="list">
        <li>A</li>
        <li>B</li>
        <li>
          <ul class="sub">
            <li>C</li>
            <li>D</li>
          </ul>
        </li>
      </ul>
      <script>
    
    
    document.getElementById('list').addEventListener('click', function (event) {
      var target = event.target, parent = target.parentElement;
      if (parent === this && !target.children[0]) {
        console.log('click on list level one item');
      }
      else if (parent.className === 'sub') {
        console.log('click on list level two item');
      }
    });
    
    
      </script>
    </body>
    

    Auch hier wird wieder über event.target selektiert:

    Die erste bedingte Anweisung wird nur dann ausgeführt, wenn auf ein Kindelement von list geklickt wurde, das nicht selbst über ein Kindelement verfügt. Hier also die ersten beiden li-Elemente mit dem Inhalt A und B. Die zweite bedingte Anweisung wird entsprechend nur dann ausgeführt, wenn auf eines der beiden Kindelemente des zweiten ul-Elementes mit der Klasse sub geklickt wurde.

    Hierbei sei übrigens besonderes Augenmerk auf den zweiten Teil der ersten Bedingung gerichtet:

    Im Gegensatz zu deinem Beispielcode habe ich hier nicht die Eigenschaft childNodes gelesen sondern die Eigenschaft children. In childNodes sind nämlich anders als in children nicht nur Elementknoten enthalten sondern ebenfalls Textknoten, und das hätte uns hier natürlich nicht weitergeholfen.

    Das wäre nun jedenfalls ein Beispiel für das Prinzip der Event Delegation, denn die Behandlung von Ereignissen, die bei verschiedenen Elementen eintreten, wird hier an eine einzige Handlerfunktion delegiert, welche für ein gemeinsames Elternelement registriert wurde.

    Ich hoffe ich konnte dir nun zumindest diesen Punkt verständlich machen. Wenn nicht, wirst du dir wohl jemanden suchen müssen der das besser erklären kann als ich. :-/

    Viele Grüße,

    Orlok

    1. Hallo Orlok,

      Ich weiß, dass ich nicht besonders gut im Erklären bin, der von dir angesprochene Thread ist dafür ein trauriges Beispiel.

      Das finde ich ganz und gar nicht.

      In dieser Hinsicht wäre es aber auch für mich hilfreich gewesen, wenn du nochmals nachgefragt und dabei die einzelnen Stellen angesprochen hättest, die du nicht verstanden hast.

      Dem stimme ich allerdings voll und ganz zu. Manchmal ist in solchen Fragen ein Forum allerdings auch schlichtweg das falsche Medium.

      Bis demnächst
      Matthias

      --
      Das Geheimnis des Könnens liegt im Wollen. (Giuseppe Mazzini)
    2. Hallo Orlok,

      gute Fachleute müssen nicht automatisch gute Lehrer sein. Dieses kleine Beispiel von dir finde ich prima, werde es einsetzen und ausbauen:

      <body>
        <ul id="list">
          <li>A</li>
          <li>B</li>
          <li>C</li>
        </ul>
        <script>
      
      
      document.getElementById('list').addEventListener('click', function (event) {
        if (event.target !== this) {
          console.log(event.target.textContent); // A oder B oder C
        }
      });
      
      
        </script>
      </body>
      

      Und dann nach und nach deinen Roman verstehen. Danke dir.

      Linuchs

  3. problematische Seite

    @@Linuchs

    Klappt vorzüglich auf dem PC unter Firefox

    Nein, das tut es nicht.

    Bitte diese Seite mal mit dem Smartphone aufrufen. Ich kann keinen Namen akivieren.

    Bitte diese Seite mal mit beliebigem Gerät aufrufen. Ich kann keinen Namen akivieren. Nicht per Tastatur. Deine Auswahl ist nicht funktionstüchtig.

    Bevor du jetzt rangehst und die Tastaturbedienbarkeit mühsam mit JavaScript und ARIA nachrüstest: das ist nicht der Weg, du du gehen solltest. Sondern: die richtigen HTML-Elemente verwenden: Du willst eine Ja/nein-Auswahl von mehreren Items – also Checkboxen.

    Nicht

    <div id="K13778-14649" onclick="toggleWunsch( '14649', this)" class="border_transparent prio1 haken1 fleet" title="4Fleet Group 50733 Köln &nbsp; Kontakt 13778-14649">
      <p class="bezeichnung">4Fleet Group</p>
    </div>
    

    sondern

    <div>
      <input type="checkbox" id="K13778-14649" name="K13778-14649"/>
      <label for="K13778-14649" title="4Fleet Group 50733 Köln &nbsp; Kontakt 13778-14649">4Fleet Group</label>
    </div>
    

    oder auch

    <label>
      <input type="checkbox" name="K13778-14649"/>
      <span title="4Fleet Group 50733 Köln &nbsp; Kontakt 13778-14649">4Fleet Group</span>
    </label>
    

    Damit ist die Tastaturbedienbarkeit gegeben. Und die Auswahl funktioniert auch ohne JavaScript. Du kannst natürlich Funktionalität als progressive enhancement hinzufügen.

    Und du kannst die Auswahl wie gewünscht stylen: ausgewählte Items gelb hinterlegt:

    :checked + label { background: yellow }
    

    bzw.

    :checked + span { background: yellow }
    

    LLAP 🖖

    --
    „Wir haben deinen numidischen Schreiber aufgegriffen, o Syndicus.“
    „Hat auf dem Forum herumgelungert …“
    (Wachen in Asterix 36: Der Papyrus des Cäsar)