hawkmaster1: onClick 2 returns?

Hallo zusammen, bei einem Button Klick sollen zwei Funktionen aufgerufen werden (mit return)

Ich habe es so versucht:

onclick="return checkbutton(); return notemsgbefore();"

Wenn die erste Funktion jedoch ok ist bzw. kein "false" zurückbringt, wird die zweite "notemshbefore()" erst gar nicht aufgerufen. Jetzt habe ich bei stackoverflow etwas gelesen das man dies mit einem logischen UND verbinden kann, also:

onclick="return checkbutton() && notemsgbefore();"

Das klappt bei mir aber nicht. Bleibt hier nur die Lösung das man eine Dummy Funktion macht und hier dann die beiden anderen reinpackt?

Danke Gruss hawk

  1. Moin!

    Spielzeug:

    <html>
    <script>
    function checkbutton(v) {
        alert ('checkbutton');
        return v;
    }
    
    function notemsgbefore() {
        alert ('notemsgbefore');
        return 1;
    }
    
    </script>
    <button onclick="checkbutton(true)  && notemsgbefore();">true and</button>
    <button onclick="checkbutton(false) && notemsgbefore();">false and</button>
    <button onclick="checkbutton(true)  || notemsgbefore();">true or</button>
    <button onclick="checkbutton(false) || notemsgbefore();">false or</button>
    </html>
    

    Abgesehen davon, dass button onclick dermaßen aus der Mode ist...

    Jörg Reinholz

    1. Moin, danke für den Vorschlag. Du meinst vermutlich man soll jetzt eher mit eventHandler arbeiten oder?

      Gruss hawk

      1. Moin!

        Moin, danke für den Vorschlag. Du meinst vermutlich man soll jetzt eher mit eventHandler arbeiten oder?

        Ja. Also diesen mit JS hinzufügen.

        Jörg Reinholz

  2. Hallo

    bei einem Button Klick sollen zwei Funktionen aufgerufen werden (mit return)

    Ich habe es so versucht:

    onclick="return checkbutton(); return notemsgbefore();"
    

    Wenn die erste Funktion jedoch ok ist bzw. kein "false" zurückbringt, wird die zweite "notemshbefore()" erst gar nicht aufgerufen.

    Die zweite Funktion wird hier niemals aufgerufen. Der String, den du dem Handlerattribut als Wert zuweist wird automatisch zu einer anonymen Funktion geparst, das heißt, was du oben geschrieben hast liest sich in Wirklichkeit etwa so:

    button.onclick = function (event) {
      return checkbutton( );
      return notemsgbefore( );
    };
    

    Wird der Eventhandler durch einen Klick auf den Button ausgelöst wird einfach nur checkbutton aufgerufen und deren Wert zurückgegeben. Die zweite return-Anweisung wird nie erreicht.

    Jetzt habe ich bei stackoverflow etwas gelesen das man dies mit einem logischen UND verbinden kann, also:

    onclick="return checkbutton() && notemsgbefore();"
    

    Das klappt bei mir aber nicht.

    Daraus wird wie oben gesehen folgendes:

    button.onclick = function (event) {
      return checkbutton( ) && notemsgbefore( );
    };
    

    Hier wird zunächst checkbutton aufgerufen und wenn deren Rückgabewert ein falsy value ist, dann wird dieser Wert zurückgegeben. Die Funktion notemsgbefore wird in diesem Fall nicht aufgerufen.

    Ist der Rückgabewert von checkbutton hingegen kein falsy value, sprich, ergibt die Auswertung von checkbutton() ein positives Ergebnis, dann wird notemsgbefore aufgerufen und deren Wert zurückgegeben.

    Wenn du möchtest, dass die zweite Funktion, also notemsgbefore nur aufgerufen wird, wenn checkbutton ein bestimmtes Ergebnis zurückgibt, dann kannst du das natürlich mit den entsprechenden Operatoren oder auch einfach über eine bedingte Anweisung implementieren.

    Je nach dem was du vorhast, könnte das so aussehen, unter der Voraussetzung, dass du deinem Button eine ID gegeben hast, über die er referenziert werden kann:

    document.getElementById('name').addEventListener('click', function ( ) {
      // wenn checkbutton ein positives Ergebnis zurückgibt, rufe notemsgbefore auf
      checkbutton( ) && notemsgbefore( );
    });
    
    // oder
    
    document.getElementById('name').addEventListener('click', function ( ) {
      // wenn checkbutton ein negatives Ergebnis zurückgibt, rufe notemsgbefore auf
      checkbutton( ) || notemsgbefore( );
    });
    

    Eventhandler sollten nicht im HTML sondern mittels der Methode addEventListener registriert werden.

    Im Gegensatz zu deinem Code enthält die als Event Listener registrierte anonyme Funktion hier im Beispiel keine return-Anweisung, eine solche wäre nämlich unabhängig von der Art der Notation ziemlich nutzlos, es sei denn, du wolltest eine Defaultaktion unterbinden. Aber dies sollte wenn dann ohnehin mittels event.preventDefault() umgesetzt werden…

    Gruß,

    Orlok

    --
    „Das Wesentliche einer Kerze ist nicht das Wachs, das seine Spuren hinterlässt, sondern das Licht.“ Antoine de Saint-Exupéry
    1. @@Orlok

      Je nach dem was du vorhast […]

      Wenn immer beide aufgerufen werden sollen:

      document.getElementById('name').addEventListener('click', function () {
        checkbutton();
        notemsgbefore();
      });
      

      oder

      document.getElementById('name').addEventListener('click', function () {
        checkbutton();
      });
      
      document.getElementById('name').addEventListener('click', function () {
        notemsgbefore();
      });
      

      Wobei in dem Fall das Element nur einmal im DOM gesucht werden sollte:

      var myButtonElement = document.getElementById('name');
      
      myButtonElement.addEventListener('click', function () {
        checkbutton();
      });
      
      myButtonElement.addEventListener('click', function () {
        notemsgbefore();
      });
      

      LLAP 🖖

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

        Ich habe mit meiner Antwort mal etwas gewartet, da ich mir nicht sicher war, ob du deinen Beitrag nicht vielleicht selbst nochmal korrigieren willst… ;-)

        Wenn immer beide aufgerufen werden sollen:

        document.getElementById('name').addEventListener('click', function () {
          checkbutton();
          notemsgbefore();
        });
        

        Das könnte man so machen, ja. – Aber…

        document.getElementById('name').addEventListener('click', function () {
          checkbutton();
        });
        
        document.getElementById('name').addEventListener('click', function () {
          notemsgbefore();
        });
        

        …ist in der Form natürlich Quatsch.

        Wenn beim Ereigniseintritt beide Funktionen aufgerufen werden sollen und die Aufrufe nicht wie in deinem ersten Beispiel zusammengefasst werden sollen, dann sollten auch beide Funktionen direkt als Handler registriert werden, und nicht gekapselt in einer anonymen Funktion.

        Wobei in dem Fall das Element nur einmal im DOM gesucht werden sollte […]

        Richtig, ergo:

        var button = document.getElementById('name');
        
        button.addEventListener('click', checkbutton);
        button.addEventListener('click', notemsgbefore);
        

        Weiterhin lassen die vom TO verwendeten Bezeichner vermuten, dass der entsprechende Button nicht irgendwo isoliert sein Dasein fristet, sondern Teil eines Formulars ist.

        Das heißt, semantisches Markup vorausgesetzt, könnte der Button auch über das form.elements API referenziert werden, was den Vorteil hätte, dass überhaupt nicht das gesamte DOM abgesucht werden müsste…

        var button = document.forms['myForm'].elements['myButton'];
        

        …was sowohl mittels der ID als auch mittels des hier zulässigen name-Attributes als auch über den jeweiligen Index funktionieren würde.

        Sollte die angelegte – eventuell sogar globale – Variable darüber hinaus keine Verwendung finden, könnte man den Job auch von einem IIFE (Immediately-Invoked Function Expression) erledigen lassen:

        (function (button) {
          button.addEventListener('click', checkbutton);
          button.addEventListener('click', notemsgbefore);
        }(document.forms['myForm'].elements['myButton']));
        

        Dieser könnte der Lesbarkeit des Codes zuliebe auch einen passenden Bezeichner bekommen, da ein solcher nur innerhalb des Ausdrucks Gültigkeit besäße.

        Aber für welche Variante sich der TO auch entscheiden mag, haben wir beide ein für ihn gegebenenfalls relevantes Thema bislang ausgespart, nämlich die Frage, wo die Registrierung vorzunehmen ist.

        Der TO hatte seine Handler bislang ja unglücklicherweise im HTML notiert, was zwar grundsätzlich abzulehnen ist, aber immerhin den Vorteil bietet, dass das Objekt, für welches der Handler registriert werden soll, zum Zeitpunkt der Registrierung auf jeden Fall existiert.

        Würde der TO sein script ohne weitere Angaben im Kopf des Dokuments notieren, würde natürlich ein Type Error geworfen, da das DOM-Objekt das den Button repräsentiert zum Zeitpunkt der Scriptausführung und mithin der Handler-Registrierung noch gar nicht erzeugt wurde.

        Wird ein externes Script eingebunden, wäre hier die Notierung des defer-Attributes eine Möglichkeit, das die Ausführung des Scripts verzögert bis das Dokument fertig geparst wurde:

        <script src="script.js" defer></script>
        

        Besser wäre es wahrscheinlich jedoch, auf das Ereignis DOMContentLoaded zu warten und die Handler dann nach dessen Eintritt zu registrieren:

        document.addEventListener('DOMContentLoaded', function ( ) {
          var button = document.forms['myForm'].elements['myButton'];
          button.addEventListener('click', checkbutton);
          button.addEventListener('click', notemsgbefore);
        });
        

        Viele Grüße,

        Orlok

        --
        „Das Wesentliche einer Kerze ist nicht das Wachs, das seine Spuren hinterlässt, sondern das Licht.“ Antoine de Saint-Exupéry
        1. Das könnte man so machen, ja. – Aber…

          document.getElementById('name').addEventListener('click', function () {
            checkbutton();
          });
          

          …ist in der Form natürlich Quatsch.

          Wenn beim Ereigniseintritt beide Funktionen aufgerufen werden sollen und die Aufrufe nicht wie in deinem ersten Beispiel zusammengefasst werden sollen, dann sollten auch beide Funktionen direkt als Handler registriert werden, und nicht gekapselt in einer anonymen Funktion.

          var button = document.getElementById('name');
          
          button.addEventListener('click', checkbutton);
          

          Zur Erklärung: Zum einen ist die Variante ohne Closure kürzer und besser lesbar. Zum anderen verkörpern die Varianten aber auch semantische Unterschiede: Die Version mit Closure vergisst den this-Kontext und den Event-Parameter. Die direkte Variante von Orlok entspricht foglich mehr dieser Semantik:

          document.getElementById('name').addEventListener('click', function (event) {
            checkbutton.call(this, event);
          });
          

          Damit hat man dann im Eventhandler checkbutton mehr Informationen über das eingetretene Eregignis zur Verfügung.

          Wobei in dem Fall das Element nur einmal im DOM gesucht werden sollte […]

          Das heißt, semantisches Markup vorausgesetzt, könnte der Button auch über das form.elements API referenziert werden, was den Vorteil hätte, dass überhaupt nicht das gesamte DOM abgesucht werden müsste…

          Diese Gedankenspiele hinsichtlich Performance sind recht naiv. Man kann heute davon ausgehen, dass kein Browser eine gewöhnliche Baumsuche benutzt um Elemente im DOM zu finden. Stattdessen werden unter der Haube wohl eine Reihe von Optimierungsstrategien implementiert sein, bspw. auf Basis von zusätzlichen Indexstrukturen und Caching. Im Zweifelsfall würde ich immer die am besten lesbare Variante vorziehen und erst im Anschluss die Performance messen und ggf. optimieren. Das wäre für mich in dem Fall dann die Variante von Gunnar.

    2. Hallo vielen Dank für die tolle und ausführliche Erklärung.

      Gruss hawk