Wie kann ich ein onclick () -Ereignis programmgesteuert von einem Ankertag aus aufrufen, während die 'this'-Referenz in der onclick-Funktion erhalten bleibt?

83

Folgendes funktioniert nicht ... (zumindest nicht in Firefox: document.getElementById('linkid').click()ist keine Funktion)

<script type="text/javascript">
    function doOnClick() {
        document.getElementById('linkid').click();
        //Should alert('/testlocation');
    }
</script>
<a id="linkid" href="/testlocation" onclick="alert(this.href);">Testlink</a>
Ropstah
quelle

Antworten:

110

Sie benötigen applyden Ereignishandler im Kontext dieses Elements:

var elem = document.getElementById("linkid");
if (typeof elem.onclick == "function") {
    elem.onclick.apply(elem);
}

Andernfalls thiswürde auf den Kontext verwiesen, in dem der obige Code ausgeführt wird.

Gumbo
quelle
3
Ich denke, Sie sind der einzige, der mich nicht als Dummkopf sieht (weil Sie die Klammer-Notation / die Inkompatibilität des Onclick | Click-Browsers nicht erwähnt haben). Genau richtig!
Ropstah
3
Beachten Sie Folgendes : howtocreate.co.uk/tutorials/javascript/domevents - Ruft der Aufruf der Funktion onclick alle registrierten Ereignishandler auf? Wenn Sie ein Ereignis fälschlicherweise aufrufen, wird nicht die mit diesem Ereignis verknüpfte Standardaktion erzeugt (z. B. das Senden eines Formulars).
Jrharshath
Gumbo, da dieser Code unterschiedliche Ergebnisse liefert, funktioniert er immer noch nicht mit den Bibliotheken Microsoft.Ajax und Microsoft.AjaxMvc ....
Ropstah
1
Warum apply()hier verwenden? Sie können es einfach tun elem.onclick();und elemwerden die 'this'-Referenz in der Funktion sein - einfach!
Doin
18

Der beste Weg, dies zu lösen, ist die Verwendung von Vanilla JS. Wenn Sie jedoch bereits jQuery verwenden, gibt es eine sehr einfache Lösung:

<script type="text/javascript">
    function doOnClick() {
        $('#linkid').click();
    }
</script>
<a id="linkid" href="/testlocation" onclick="alert(this.href);">Testlink</a>

Getestet in IE8-10, Chrome, Firefox.

luschn
quelle
3
Warum die Ablehnung? Bitte kommentieren Sie einen Grund, damit ich meine Frage verbessern kann, wenn Sie glauben, dass etwas nicht stimmt.
Luschn
1
Im Stackoverflow heißt es, dass Sie keine Antworten geben sollten, die von einer externen Ressource abhängen (z. B. einer Bibliothek wie jQuery), wenn das OP dies nicht explizit erwähnt hat. Ich denke, das hat die Abwertung motiviert
vhoyer
2013 benutzten alle jquery - aber heutzutage würde ich zustimmen :) - ich werde die Antwort für zukünftige Referenz behalten.
Luschn
15

Um ein Ereignis auszulösen, rufen Sie einfach den Ereignishandler für dieses Element auf. Leichte Änderung von Ihrem Code.

var a = document.getElementById("element");
var evnt = a["onclick"];

if (typeof(evnt) == "function") {
    evnt.call(a);
}
einfach hart
quelle
1
+1. Ein bisschen googeln zeigt auch, dass foo.click () nur IE ist, natürlich könnte ich mich irren ...
karim79
1
Sie sollten die Punktnotation (.onclick) anstelle der Klammernotation (["onclick"]) verwenden.
Rudd Zwolinski
.onclick () oder .click () funktionieren beide nicht wie erwartet. In Firefox .click (oder in Klammern ['click']) ist es "NOT A FUNCTION". Aber wenn Sie .onclick () aufrufen, verlieren Sie die Referenz "this" (ich benötige diese in ASP.NET MVC, da Informationen vom <a> -Tag in der ausführenden Funktion benötigt werden)
Ropstah
5
$("#linkid").trigger("click");
Gast
quelle
2
Willkommen bei SO. Können Sie näher erläutern, warum dies funktioniert (was genau es tut usw.) und was dies von den anderen Lösungen unterscheidet?
m00am
2
Warum diese Antwort notieren? Dies ist die beste Lösung auf dieser Seite, wenn Sie jquery verwenden ... ein Liner - das kann man nicht übertreffen!
PodTech.io
Für die Antwort sollte jQuery
Greg Perham
5

Zugegeben, OP erklärte sehr ähnlich, dass dies nicht funktionierte, aber für mich. Basierend auf den Notizen in meiner Quelle scheint es, dass es zu der Zeit oder nach dem Post von OP implementiert wurde. Vielleicht ist es jetzt mehr Standard.

document.getElementsByName('MyElementsName')[0].click();

In meinem Fall hatte mein Button keine ID. Wenn Ihr Element eine ID hat, verwenden Sie vorzugsweise die folgende (nicht getestete).

document.getElementById('MyElementsId').click();

Ich habe diese Methode ursprünglich ausprobiert und sie hat nicht funktioniert. Nach dem Googeln kam ich zurück und stellte fest, dass mein Element namentlich war und keinen Ausweis hatte. Stellen Sie sicher, dass Sie das richtige Attribut aufrufen.

Quelle: https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/click

Tyler Montney
quelle
1

Schauen Sie sich die handleEvent-Methode
https://developer.mozilla.org/en-US/docs/Web/API/EventListener an

"Rohes" Javascript:

function MyObj() {
   this.abc = "ABC";
}
MyObj.prototype.handleEvent = function(e) {
   console.log("caught event: "+e.type);
   console.log(this.abc);
}

var myObj = new MyObj();

document.querySelector("#myElement").addEventListener('click', myObj);

Klicken Sie nun auf Ihr Element (mit der ID "myElement") und es sollte Folgendes in der Konsole drucken:

gefangenes Ereignis: Klicken Sie auf
ABC

Auf diese Weise können Sie eine Objektmethode als Ereignishandler verwenden und auf alle Objekteigenschaften in dieser Methode zugreifen.

Sie können nicht einfach eine Methode eines Objekts direkt an addEventListener übergeben (so :) element.addEventListener('click',myObj.myMethod);und erwarten myMethod, dass Sie so tun , als ob ich normalerweise für das Objekt aufgerufen worden wäre. Ich vermute, dass jede an addEventListener übergebene Funktion irgendwie kopiert wird, anstatt referenziert zu werden. Wenn Sie beispielsweise eine Ereignis-Listener-Funktionsreferenz an addEventListener übergeben (in Form einer Variablen) und diese Referenz deaktivieren, wird der Ereignis-Listener weiterhin ausgeführt, wenn Ereignisse abgefangen werden.

Eine andere (weniger elegante) Problemumgehung, um eine Methode als Ereignis-Listener und -Stil zu übergeben thisund dennoch Zugriff auf Objekteigenschaften innerhalb des Ereignis-Listeners zu haben, wäre ungefähr so:

// see above for definition of MyObj

var myObj = new MyObj();

document.querySelector("#myElement").addEventListener('click', myObj.handleEvent.bind(myObj));
Rolf
quelle
1

Alter Thread, aber die Frage ist immer noch relevant, also ...

(1) Das Beispiel in Ihrer Frage funktioniert jetzt in Firefox. Zusätzlich zum Aufrufen des Ereignishandlers (der eine Warnung anzeigt) klickt er AUCH auf den Link und verursacht eine Navigation (sobald die Warnung geschlossen wird).

(2) Um NUR den Ereignishandler aufzurufen (ohne die Navigation auszulösen), ersetzen Sie einfach:

document.getElementById('linkid').click();

mit

document.getElementById('linkid').onclick();
Doin
quelle
0

Wenn Sie dies nur verwenden, um auf die Funktion im onclick-Attribut zu verweisen, scheint dies eine sehr schlechte Idee zu sein. Inline-Events sind im Allgemeinen eine schlechte Idee.

Ich würde folgendes vorschlagen:

function addEvent(elm, evType, fn, useCapture) {
    if (elm.addEventListener) {
        elm.addEventListener(evType, fn, useCapture);
        return true;
    }
    else if (elm.attachEvent) {
        var r = elm.attachEvent('on' + evType, fn);
        return r;
    }
    else {
        elm['on' + evType] = fn;
    }
}

handler = function(){
   showHref(el);
}

showHref = function(el) {
   alert(el.href);
}

var el = document.getElementById('linkid');

addEvent(el, 'click', handler);

Wenn Sie dieselbe Funktion aus einem anderen Javascript-Code aufrufen möchten, ist die Simulation eines Klicks zum Aufrufen der Funktion nicht der beste Weg. Erwägen:

function doOnClick() {
   showHref(document.getElementById('linkid'));
}
David Snabel-Caunt
quelle
Es geht darum, den Verweis auf "dies" beizubehalten. Ich kann nicht nur den Onclick-Teil im Anker (.NET MVC) generieren. Ich muss ein vollständiges Ankertag generieren. Dieses Tag wird vollständig von der onclick-Funktion benötigt (z. B. verwendet es das href-Attribut).
Ropstah
-1

Im Allgemeinen würde ich davon abraten, die Ereignishandler "manuell" aufzurufen.

  • Es ist unklar, was aufgrund mehrerer registrierter Listener ausgeführt wird
  • Gefahr, in eine rekursive und unendliche Ereignisschleife zu geraten (Klick A, Auslöser Klick B, Auslöser Klick A usw.)
  • Redundante Aktualisierungen des DOM
  • Es ist schwierig, vom Benutzer verursachte tatsächliche Änderungen in der Ansicht von Änderungen zu unterscheiden, die als Initialisierungscode vorgenommen wurden (der nur einmal ausgeführt werden sollte).

Besser ist es, herauszufinden, was genau geschehen soll, dies in eine Funktion einzufügen und manuell aufzurufen UND als Ereignis-Listener zu registrieren.

hvdd
quelle
OP fragte, wie man etwas macht, nicht wie man etwas am besten macht. Dies ist nicht CodeReview. Wenn Sie seine Frage beantwortet und dann den Haftungsausschluss gestellt hätten, wäre das anders.
Tyler Montney