Commander: addEventListener(xxx, funktion("wert"), xxx) ?????

Hallo Leute,

sorry mir ist kein anderes Thema eingefallen. ;-)

Wie kann ich an mit addEventListener() oder attachEvent() aufgerufene Funktionen einen Wert weitergeben?

addEventListener(mouseover, funktion("bla"), true)

Das mit den Klammern bei funktion("bla") geht ja nicht.

  1. Moin,

    Wie kann ich an mit addEventListener() oder attachEvent() aufgerufene Funktionen einen Wert weitergeben?

    So direkt gar nicht, die Funktion bekommt ja schon das Event-Objekt als ersten und einzigen Parameter übergeben. Wenn du das nicht willst, musst du einen Wrapper drum schreiben. Also etwa

    function blawrapper(e)
    { funktion("bla"); }

    addEventListener(mouseover, blawrapper, true);

    --
    Henryk Plötz
    Grüße aus Berlin

    1. function blawrapper(e)
      { funktion("bla"); }

      addEventListener(mouseover, blawrapper, true);

      ich versteh jetzt nicht was das bringt, also ich mach das so:

      function auf(div){
      ...
      }

      function machEvent(objekt, Eventtyp, Funktion){
        objekt = eval(document.getElementById(objekt));
        if (objekt.addEventListener){
          objekt.addEventListener(Eventtyp, Funktion, true);
          return true;
        } else if (objekt.attachEvent){
          var r = objekt.attachEvent("on"+Eventtyp, Funktion, true);
          return r;
        }
      }

      machEvent("ID eins Divs", "mouseover", auf(ID eins Divs));

      1. Moin,

        ich versteh jetzt nicht was das bringt, also ich mach das so:

        Ah ok, wiedermal sieht man dass es leichter ist zu helfen, wenn man die ganze Geschichte kennt. Ich hatte bisher gedacht, du hättest nur irgendeine Funktion (meinetwegen alert()) und möchtest die, wenn ein bestimmtes Ereignis auftritt, mit einem bestimmten Parameter aufrufen.

        machEvent("ID eins Divs", "mouseover", auf(ID eins Divs));

        Du denkst hier viel zu kompliziert, mach dich mal mit dem DOM ein bisschen vertrauter und fange an, objektorientierter zu denken. Also soweit ich das sehe, willst du eine Funktion aufrufen und ihr als Parameter das div übergeben das ge-mouseover-t wurde. Dafür hat es im DOM-Event die unheimlich praktische Eigenschaft currentTarget die immer das DOM-Objekt enthält zu dem der aktuell laufende Event-Listener gehört.

        Ich hab deinen Code mal modifiziert

        function auf(ev){
        if(!ev) ev = window.event; // Kann es zwar grad nicht testen, aber iirc braucht IE das
        div = ev.currentTarget; // DOM-Kompatibel
        // Ich bin mir nicht sicher, ob das beim IE nicht auch wieder anders heisst

        // In div liegt jetzt das div-Objekt auf das das Ereignis ausgeführt wurde
        }

        function machEvent(objekt, Eventtyp, Funktion){
          objekt = eval(document.getElementById(objekt));
          if (objekt.addEventListener){
            objekt.addEventListener(Eventtyp, Funktion, true);
            return true;
          } else if (objekt.attachEvent){
            var r = objekt.attachEvent("on"+Eventtyp, Funktion, true);
            return r;
          }
        }

        machEvent("ID eins Divs", "mouseover", auf);

        und schwupps kannst du dir das explizite Übermitteln der div-ID sparen.

        --
        Henryk Plötz
        Grüße aus Berlin

        1. Mit NN7 geht es, sogar gut, obwohl ich es nicht ganz verstehe.
          Mit IE kommt nichts.

          Selfhtml kann mir aber nichts über currentTarget sagen, das mit dem addEventListener hab ich auch wo anders her.

          Aber ich möchte auch ein paar mal fremde divs damit ansprechen.

          Ich habe Scripts gesehen wo das geht, aber die sind so kompliziert, das ich da nichts rauslesen kann.

          z.B.
          http://www.scope.gmd.de/info/hierMenu/webreference.com/dhtml/hiermenus/latest/listing.html

          1. Moin,

            Mit NN7 geht es, sogar gut, obwohl ich es nicht ganz verstehe.

            Wie gesagt, das ist reines, wunderschönes DOM.

            Mit IE kommt nichts.

            Ja, der kann DOM nicht vernünftig, zumindest nicht den Event-Teil aus DOM2. Prinzipiell geht vieles von den DOM-Events auch mit dem IE, bloß heissen die Eigenschaften da (scheinbar konsequent) anders. Da ich keinen IE zum Testen habe, kann ich auch kein Erfolgsrezept geben. (Das letzte mal als ich ein schönes DOM-kompatibles Skript so verbiegen musste, dass es auch im IE klappt, habe ich auch schon genug geflucht.)

            Selfhtml kann mir aber nichts über currentTarget sagen, das mit dem addEventListener hab ich auch wo anders her.

            In Selfhtml sind DOM-Events glaube ich auch noch gar nicht drin. Das steht aber alles in der W3C-Spezifikation unter http://www.w3.org/TR/DOM-Level-2-Events/

            Aber ich möchte auch ein paar mal fremde divs damit ansprechen.

            "fremde divs"?

            Ich habe Scripts gesehen wo das geht, aber die sind so kompliziert, das ich da nichts rauslesen kann.

            Ja, das berücksichtigt gleich mehrere Browser. Ich habe vor einiger Zeit ein komplexeres Skript für DOM, NN4, IE4 und IE 5/6 (die wollen alle extra berücksichtigt werden) aufgebohrt und wollte dazu eigentlich auch einen Feature-Artikel schreiben (zu 20% fertig), hatte dann aber keine Zeit mehr.

            Ich habe eben noch mal gegooglet und einen Vergleich gefunden: http://www.javascriptkit.com/dhtmltutors/domeventp2-1.shtml. Da steht, dass IE gar kein Äquivalent zu currentTarget kennt, also ist wohl mal wieder die Zeit der dreckigen Workarounds gekommen.

            Also (tieflufthohl): Der IE kennt srcElement (das Äquivalent zu target) und das enthält eine Referenz auf das Element an das das Event eigentlich gerichtet ist. Das ist leider nicht notwendigerweise das Element, dass du haben willst (falls doch kannst du jetzt aufhören diesen Absatz zu lesen ;). Wenn du also deinen Event-Handler bei <div><img>bla</div> auf das div ansetzt und jemand auf das Bild (statt auf den Text daneben) klickt, dann ist eine Referenz auf das img-Objekt in srcElement bzw. target. Glücklicherweise kennt der IE die Eigenschaft parentElement die jedes HTML-Element-Objekt hat (die korrespondierende DOM-Eigenschaft heisst übrigens parentNode) und die das jeweilige Elternelement enthält. Du musst dann nur noch die Objektkette bis nach oben durchklettern und schauen ob da ein Objekt bei ist, dass dir gefällt. Das entscheidest du entweder, indem du irgendwo eine Liste mit den IDs der interessanten Elemente hast oder indem du bei der Benennung irgendein Schema benutzt, also <div id="hallo1"> .. <div id="hallo2"> .. und dann mit indexOf() auf die id-Eigenschaft der jeweiligen Kandidaten losgehst (alternativ kannst du auch einen festen Wert für das name-Attribut verwenden, der darf bei mehreren Elementen gleich sein).

            (BTW: Wenn du dieses Schema gleich anwendest, brauchst du unter Umständen nur einen Event-Listener bzw. Handler für das body-Element zu definieren und kannst dann das Skript ohne Änderung am JS-Code auf mehreren Seiten einsetzen. Das ist das Prinzip das du bei den meisten Beispielen finden wirst, deswegen sind die häufig auch übermäßig kompliziert.)

            So, um die trockene Theorie mal etwas aufzulockern hier noch ein einfaches Beispiel in Form einer modifizierten function auf(). Der Rest müsste gleich bleiben können:

            function auf(ev){
            if(!ev) ev = window.event; // Ja, der IE braucht das definitiv
            div = ev.currentTarget; // DOM-Kompatibel
            if(!div) { // Spaß
             div = ev.srcElement; // Das ursprüngliche Ziel des Events
             while( div.id.indexOf("aufmachbar") != -1  // Abbruch, wenn die ID "aufmachbar" enthält ...
                    && div.parentElement) // ... oder es keine weiteren Eltern gibt
              div = div.parentElement;
             if(div.id.indexOf("aufmachbar") != -1) return; // Nix gefunden
            }

            // In div liegt jetzt das div-Objekt auf das das Ereignis ausgeführt wurde
            }

            (Der Code ist mangels IE ungetestet, sollte aber selbst wenn er nicht funktioniert das Prinzip illustrieren.)

            Und in deiner Seite hast du dann
            <div id="aufmachbar1"> bla </div> <div id="aufmachbar2"> blu </div>
            oder ähnliches.

            HTH

            --
            Henryk Plötz
            Grüße aus Berlin

            1. Ich sag mal zu allem *Schluck*.

              Ich probier das gleich mal.

              Ehm ich probier das mal, aber wie ich seh hast du Ahnung, hast du ICQ, da könnte ich dir denn ganzen Code sehen, und verstehen was ich überhaubt machen will.
              Meiner Nummer lautet 164175210.

      2. Hallo,

        function auf(div){
        ...
        }

        function machEvent(objekt, Eventtyp, Funktion){
          objekt = eval(document.getElementById(objekt));
          if (objekt.addEventListener){
            objekt.addEventListener(Eventtyp, Funktion, true);
            return true;
          } else if (objekt.attachEvent){
            var r = objekt.attachEvent("on"+Eventtyp, Funktion, true);
            return r;
          }
        }

        machEvent("ID eins Divs", "mouseover", auf(ID eins Divs));

        Also ich glaube, was du brauchst, ist dies:

        document.getElementById('id').onmouseover = function() { auf(this) };

        Im Unterschied zu addEventListener() und attachEvent() kann man so zwar nicht mehrere onmouseover-Events für das selbe Objekt definieren, aber ich nehme mal an, dass das für dich ziemlich unwichtig ist. Die Funktion auf() bekommt das auslösende Objekt direkt übergeben:

        function auf(obj) { obj.style.backgroundColor = 'red'; }

        Grüße, Stefan

        1. document.getElementById('id').onmouseover = function() { auf(this) };

          function auf(obj) { obj.style.backgroundColor = 'red'; }

          Ich habe das am Anfang ähnlich gemacht.

          div = document.createElement("div");
           div.onmouseover = new Function('auf("'+id+'")');
           document.body.appendChild(div);

          Das lief mit IE gut, aber bei NN lief das onmouseout nicht immer was unschöne Fehler machte.

          Als ich es so machte:

          function auf(ev){
          if(!ev) ev = window.event;
          div = ev.currentTarget;

          div.style.backgroundColor = "#006699";
          }

          machEvent(id, "mouseover", auf);

          lief es mit NN perfekt, mit IE aber nicht.
          Als ich es so ergänzte:

          function auf(ev){
          if(!ev) ev = window.event;
          div = ev.currentTarget;
          if(!div) {
           div = ev.srcElement;
           while( div.id.indexOf("aufmachbar") != -1 && v.parentElement)
           div = div.parentElement;
           if(div.id.indexOf("aufmachbar") != -1) return;
          }

          div.style.backgroundColor = "#006699";
          }
          Lief es mit IE und mit NN, aber mit NN genau so wie am Anfang, so das onmouseout bei NN nicht immer läuft.

          1. Hi,

            document.getElementById('id').onmouseover = function() { auf(this) };

            function auf(obj) { obj.style.backgroundColor = 'red'; }

            Ich habe das am Anfang ähnlich gemacht.

            div = document.createElement("div");
            div.onmouseover = new Function('auf("'+id+'")');
            document.body.appendChild(div);

            Rein gefühlsmäßig würde ich den Handler erst setzen, nachdem ich das Div ins Dokument eingefügt hätte. Wie ist 'id' definiert?

            Das lief mit IE gut, aber bei NN lief das onmouseout nicht immer was unschöne Fehler machte.

            Wie ist onmouseout definiert?

            Als ich es so machte:

            function auf(ev){
            if(!ev) ev = window.event;
            div = ev.currentTarget;

            div.style.backgroundColor = "#006699";
            }

            machEvent(id, "mouseover", auf);

            lief es mit NN perfekt, mit IE aber nicht.

            IE kennt kein 'currentTarget'. Aber warum 'if(!ev)'? Wenn 'ev' nicht definiert ist, solltest du der Frage erst mal nachgehen, warum das so ist. Hast du denn schon probiert, 'this' zu übergeben? Was passiert denn dabei?

            Ansonsten solltest du vielleicht mal zusammenhängenden Code oder eine URL posten.

            Grüße, Stefan

            1. Rein gefühlsmäßig würde ich den Handler erst setzen, nachdem ich das Div ins Dokument eingefügt hätte. Wie ist 'id' definiert?

              id ist immer anders mal JS mal so mal so, ab und zu ist es auch das div selbst

              Wie ist onmouseout definiert?

              genauso, ich habe bloß vergessen hier zu schreiben

              IE kennt kein 'currentTarget'. Aber warum 'if(!ev)'? Wenn 'ev' nicht definiert ist, solltest du der Frage erst mal nachgehen, warum das so ist. Hast du denn schon probiert, 'this' zu übergeben? Was passiert denn dabei?

              Das mit dem if(!ev) hat mir Henryk Plötz gestern gegeben.(weiter unten)
              Mit this kenn ich mich garnicht aus, ich hab es probier und es funktionierte nicht, ind SelfHtml ist this nicht gut beschrieben.

              Ansonsten solltest du vielleicht mal zusammenhängenden Code oder eine URL posten.

              Hier hab ich mal alles überarbeitet:
              http://duell.host.sk/menue/erster.html
              http://duell.host.sk/menue/zweiter.html
              http://duell.host.sk/menue/dritter.html

              1. Hallo,

                http://duell.host.sk/menue/erster.html
                http://duell.host.sk/menue/zweiter.html

                Das hab' ich mir mal mit Mozilla angesehen. Also es hat auf jeden Fall was damit zu tun, dass mehrere Divs übereinander liegen, die jeweils eigene Events haben. Wenn man das onmouseout der Hauptebene herausnimmt, ist die Macke nicht mehr da, nur wird das Menü natürlich dann nicht wieder ausgeblendet. Mir ist allerdings nicht klar, wieso der onmouseout der Hauptebene ständig ausgelöst wird.

                Events werden ja normalerweise durch alle Dokument-Ebenen 'durchgereicht', können aber auch abgefangen werden. Eigentlich wird dieses Verhalten mit dem dritten Parameter von addEventListener() gesteuert (true = Bubbling wird angehalten), und deshalb lief dein zweites Beispiel zwischendurch auch wohl mal, weil es addEventListener(*,*,true) benutzt, aber offenbar spielt noch was anderes eine Rolle, was jetzt dazu führt, dass sich die Events gegenseitig stören.

                Wenn das zweite Beispiel gestern noch lief, überleg' doch mal genau, was du inzwischen geändert hast. Das dann für IE anzupassen, ist sicher nicht schwierig.

                Grüße, Stefan

                1. An das überblenden hab ich noch garnicht gedacht und was das true oder false bedeutetet stand in der Referenz wo ich das weg hab auch nicht.
                  Ich setze mich später mal dran, aber falls nichts mehr geht las ich das HaubtTeil einfach weg.

                  1. Moin,

                    An das überblenden hab ich noch garnicht gedacht und was das true oder false bedeutetet stand in der Referenz wo ich das weg hab auch nicht.

                    Da das leider auch falsch in Selfhtml steht, hier nochmal die richtige Erklärung dazu (Teilweise aus der W3C-Recommendation, teilweise aus einem anderen Tutorial dazu):
                    Es gibt grob gesagt zwei Typen um Events zu verteilen:
                    Bubbling: Das Ereignis landet zuerst bei dem Objekt an das es gerichtet war (also das was im Element-Baum ganz unten hängt) und steigt dann langsam an alle Elternelemente hoch (wie eine Luftblase unter Wasser, daher der Name). Das ist die Methode die der Internet Explorer benutzt (benutzte?).
                    Capture: Das Ereignis landet zuerst bei dem obersten Objekt (das müsste window sein) und hangelt sich dann stückweise bis zum Ziel nach unten herab. Dabei können Event-Handler definiert werden, die das Ereignis zwischendurch abfangen (capturen, daher der Name). Das ist die Methode die NN4 benutzt.

                    Um das ganze möglichst universell zu machen, sieht das DOM beide Methoden vor: Zuerst geht das Event-Objekt in die capture-Phase und steigt von oben im Baum bis zum Zielelement herab. Dann kommt es dort an und fängt anschließend mit der bubble-Phase an, wobei es es vom Zielelement wieder bis zur Wurzel aufsteigt.

                    Mit dem 3. Parameter von addEventListener kannst du nun festlegen, ob du möchtest, dass dein EventListener capturing macht - d.h. er kriegt das Event vor dem Zielelement zu fassen (wenn er selbst an das Zielelement gebunden ist, feuert er übrigens nicht) - oder aber dein Listener das Event erst beim bubbling bekommt - also nach allen capturing-Listenern und dem Zielelement selbst (Vorsicht: nicht alle Events bubblen).

                    Jeder der Event-Listener kann übrigens einige Eigenschaften des Event-Objektes verändern. Die Listener die nach ihm aufgerufen werden, kriegen dann das veränderte Event vorgesetzt (alle Listener die an das selbe Element gebunden sind, bekommen noch das unmodifizierte Objekt).

                    --
                    Henryk Plötz
                    Grüße aus Berlin

            2. Moin,

              IE kennt kein 'currentTarget'. Aber warum 'if(!ev)'?

              Das ist ein Quasi-Trick um die selbe Funktion als Event-Listener für DOM-kompatible (die Funktion bekommt das Event-Objekt als ersten Parameter übergeben) und IE-Browser (das Event-Objekt befindet sich in der globalen Variablen window.event) zu verwenden.

              --
              Henryk Plötz
              Grüße aus Berlin