Como disparar um evento em JavaScript?

523

Anexei um evento a uma caixa de texto usando addEventListener. Funciona bem. Meu problema surgiu quando eu queria disparar o evento programaticamente a partir de outra função.

Como eu posso fazer isso?

KoolKabin
fonte
11
O Mozilla tem um artigo muito bom explicando a criação e o acionamento de eventos em Javascript . Espero que ajude!
Ricky Stam
1
Altere a resposta aceita para isso , é mais atualizado.
Michał Perłakowski 02/04
1
@RickyStam Parece que o artigo MDN mudou-se para aqui
styfle

Respostas:

454

Você pode usar o fireEvent no IE 8 ou inferior e o dispatchEvent do W3C na maioria dos outros navegadores. Para criar o evento que você deseja disparar, você pode usar um createEventou outro, createEventObjectdependendo do navegador.

Aqui está um trecho de código auto-explicativo (do protótipo) que dispara um evento dataavailableem um element:

var event; // The custom event that will be created
if(document.createEvent){
    event = document.createEvent("HTMLEvents");
    event.initEvent("dataavailable", true, true);
    event.eventName = "dataavailable";
    element.dispatchEvent(event);
} else {
    event = document.createEventObject();
    event.eventName = "dataavailable";
    event.eventType = "dataavailable";
    element.fireEvent("on" + event.eventType, event);
}
Alsciende
fonte
6
Dont't esquecer que apenas a versão IE tem o 'on' na frente (que eu perdi na primeira)
hugomg
45
O que a variável eventNamecontém aqui?
NeDark 15/09
1
Sim, os dados disponíveis devem estar em eventName e o memorando também deve ser definido (definir para {} está ok).
Charles
4
O Internet Explorer 9+ manipula createEvent e dispatchEvent, portanto, não há necessidade dessas instruções if.
Blake
5
Este exemplo nem funciona, veja a minha resposta: stackoverflow.com/a/20548330/407213 #
Dorian
334

Um exemplo de trabalho:

// Add an event listener
document.addEventListener("name-of-event", function(e) {
  console.log(e.detail); // Prints "Example of an event"
});

// Create the event
var event = new CustomEvent("name-of-event", { "detail": "Example of an event" });

// Dispatch/Trigger/Fire the event
document.dispatchEvent(event);

Para polyfill de navegadores mais antigos e exemplos mais complexos, consulte a documentação do MDN .

Veja as tabelas de suporte para EventTarget.dispatchEvente CustomEvent.

Dorian
fonte
11
Esta resposta é mais atual agora. Uma coisa a acrescentar: se houver um evento de tipo conhecido (como TransitionEvent , ClipboardEvent , etc), o construtor apropriado poderá ser chamado.
Kiril
6
@AngelPolitis: Porque ele foi escrito após a anterior já foi aceita e que a pessoa que escreveu a questão (@KoolKabin) provavelmente não voltar a ler as respostas
Dorian
4
E porque foi solicitado em 2010 #
DarkNeuron
Não funcionará com nenhuma versão do IE ( caniuse.com/#feat=customevent ). Veja minha resposta para uma correção.
Yarin
A observação para futuros leitores detailé uma propriedade do Event, portanto, atribua todos os dados que você deseja acessar na outra extremidade e com os quais acessa event.detail. +1
daka
71

Se você não quiser usar o jQuery e não estiver especialmente preocupado com a compatibilidade com versões anteriores, use:

let element = document.getElementById(id);
element.dispatchEvent(new Event("change")); // or whatever the event type might be

Veja a documentação aqui e aqui .

EDIT: Dependendo da sua configuração, você pode querer adicionar bubbles: true:

let element = document.getElementById(id);
element.dispatchEvent(new Event('change', { 'bubbles': true }));
e18r
fonte
4
Esta deve ser a resposta aceita como ele não usa métodos obsoletas como initEvent ()
user2912903
2
Solução agradável, mas saiba que isso não funcionará no IE11. Você deve usar CustomEvente o polyfill correspondente.
Fabian von Ellerts 19/03/19
2
Melhor que a resposta selecionada
WitnessTruth 18/04/19
42

se você usa jQuery, você pode fazer

$('#yourElement').trigger('customEventName', [arg0, arg1, ..., argN]);

e lidar com isso com

$('#yourElement').on('customEventName',
   function (objectEvent, [arg0, arg1, ..., argN]){
       alert ("customEventName");
});

onde "[arg0, arg1, ..., argN]" significa que esses argumentos são opcionais.

Hilder Vitor Lima Pereira
fonte
4
A sintaxe correta é $ ('# yourElement'). Trigger ('customEventName', [arg0, arg1, ..., argN]); Você esqueceu o [] no segundo parâmetro
harry
25

Se você estiver suportando o IE9 +, poderá usar o seguinte. O mesmo conceito está incorporado em Você pode não precisar do jQuery .

function addEventListener(el, eventName, handler) {
  if (el.addEventListener) {
    el.addEventListener(eventName, handler);
  } else {
    el.attachEvent('on' + eventName, function() {
      handler.call(el);
    });
  }
}

function triggerEvent(el, eventName, options) {
  var event;
  if (window.CustomEvent) {
    event = new CustomEvent(eventName, options);
  } else {
    event = document.createEvent('CustomEvent');
    event.initCustomEvent(eventName, true, true, options);
  }
  el.dispatchEvent(event);
}

// Add an event listener.
addEventListener(document, 'customChangeEvent', function(e) {
  document.body.innerHTML = e.detail;
});

// Trigger the event.
triggerEvent(document, 'customChangeEvent', {
  detail: 'Display on trigger...'
});


Se você já está usando jQuery, aqui está a versão jQuery do código acima.

$(function() {
  // Add an event listener.
  $(document).on('customChangeEvent', function(e, opts) {
    $('body').html(opts.detail);
  });

  // Trigger the event.
  $(document).trigger('customChangeEvent', {
    detail: 'Display on trigger...'
  });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

Mr. Polywhirl
fonte
Isso não vai funcionar para qualquer versão do IE, como window.CustomEventexiste, mas não pode ser chamado como um construtor: caniuse.com/#search=CustomEvent ;)
SidOfc
13

Pesquisei eventos de clique, mouse e mouseup na ativação do mouse usando JavaScript. Encontrei uma resposta fornecida por Juan Mendes . Para a resposta, clique aqui .

Clique aqui e a demonstração ao vivo e abaixo está o código:

function fireEvent(node, eventName) {
    // Make sure we use the ownerDocument from the provided node to avoid cross-window problems
    var doc;
    if (node.ownerDocument) {
        doc = node.ownerDocument;
    } else if (node.nodeType == 9) {
        // the node may be the document itself, nodeType 9 = DOCUMENT_NODE
        doc = node;
    } else {
        throw new Error("Invalid node passed to fireEvent: " + node.id);
    }

    if (node.dispatchEvent) {
        // Gecko-style approach (now the standard) takes more work
        var eventClass = "";

        // Different events have different event classes.
        // If this switch statement can't map an eventName to an eventClass,
        // the event firing is going to fail.
        switch (eventName) {
        case "click": // Dispatching of 'click' appears to not work correctly in Safari. Use 'mousedown' or 'mouseup' instead.
        case "mousedown":
        case "mouseup":
            eventClass = "MouseEvents";
            break;

        case "focus":
        case "change":
        case "blur":
        case "select":
            eventClass = "HTMLEvents";
            break;

        default:
            throw "fireEvent: Couldn't find an event class for event '" + eventName + "'.";
            break;
        }
        var event = doc.createEvent(eventClass);

        var bubbles = eventName == "change" ? false : true;
        event.initEvent(eventName, bubbles, true); // All events created as bubbling and cancelable.

        event.synthetic = true; // allow detection of synthetic events
        // The second parameter says go ahead with the default action
        node.dispatchEvent(event, true);
    } else if (node.fireEvent) {
        // IE-old school style
        var event = doc.createEventObject();
        event.synthetic = true; // allow detection of synthetic events
        node.fireEvent("on" + eventName, event);
    }
};
S.Mishra
fonte
8

Apenas para sugerir uma alternativa que não envolva a necessidade de chamar manualmente um evento de ouvinte:

O que quer que seu ouvinte de evento faça, mova-o para uma função e chame essa função do ouvinte de evento.

Em seguida, você também pode chamar essa função em qualquer outro lugar para realizar a mesma coisa que o evento quando é acionado.

Acho isso menos "intensivo em código" e mais fácil de ler.

Kirby L. Wallace
fonte
1
E se você quiser fazer várias coisas diferentes para o mesmo evento (ou bem, função de retorno de chamada no seu caso) dependendo do contexto? :) É uma boa alternativa, mas isso parece mais um comentário do que uma resposta, já que o OP quer saber como acionar programaticamente um evento, em vez de usar um retorno de chamada :) #
236 SidOfc
Você está certo de que isso deveria ter sido um comentário e não uma resposta. Por quê? Porque, uhm, bem, .... não responde à pergunta que realmente foi feita. Boa decisão. Quanto à sua própria pergunta, eu diria que essa seria uma grande oportunidade para construtores em JavaScript! ;-) Mas sem eles, eu diria, envie um argumento com sua chamada de função e deixe que isso seja usado para determinar o que a função deve fazer.
22817 Kirby L. Wallace
5

Eu apenas usei o seguinte (parece ser muito mais simples):

element.blur();
element.focus();

Nesse caso, o evento será acionado apenas se o valor for realmente alterado, da mesma forma que você o acionaria pelo lócus de foco normal perdido realizado pelo usuário.

Aleksander Lech
fonte
1
Isso não leva em conta que tipo de evento é. A desfocagem e a focagem podem desencadear o evento, mas também não. Isso está convidando bugs.
Mardok
1
Isso também se aplica a element.click().
AxeEffect
Isso corrigiu um problema estranho no meu aplicativo Angular / Cordova, no Android, onde a área de texto se recusava a se limpar. Então obrigado.
DarkNeuron
5

Resposta de @ Dorian modificada para trabalhar com o IE:

document.addEventListener("my_event", function(e) {
  console.log(e.detail);
});

var detail = 'Event fired';

try {

    // For modern browsers except IE:
    var event = new CustomEvent('my_event', {detail:detail});

} catch(err) {

  // If IE 11 (or 10 or 9...?) do it this way:

    // Create the event.
    var event = document.createEvent('Event');
    // Define that the event name is 'build'.
    event.initEvent('my_event', true, true);
    event.detail = detail;

}

// Dispatch/Trigger/Fire the event
document.dispatchEvent(event);

FIDDLE: https://jsfiddle.net/z6zom9d0/1/

VEJA TAMBÉM:
https://caniuse.com/#feat=customevent

Yarin
fonte
4

A resposta aceita não funcionou para mim, nenhuma das createEvent funcionou.

O que funcionou para mim no final foi:

targetElement.dispatchEvent(
    new MouseEvent('click', {
        bubbles: true,
        cancelable: true,
        view: window,
}));

Aqui está um trecho:

const clickBtn = document.querySelector('.clickme');
const viaBtn = document.querySelector('.viame');

viaBtn.addEventListener('click', function(event) {
    clickBtn.dispatchEvent(
        new MouseEvent('click', {
            bubbles: true,
            cancelable: true,
            view: window,
    }));
});

clickBtn.addEventListener('click', function(event) {
    console.warn(`I was accessed via the other button! A ${event.type} occurred!`);
});
<button class="clickme">Click me</button>

<button class="viame">Via me</button>

Da leitura: https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent

Ming
fonte
3
function fireMouseEvent(obj, evtName) {
    if (obj.dispatchEvent) {
        //var event = new Event(evtName);
        var event = document.createEvent("MouseEvents");
        event.initMouseEvent(evtName, true, true, window,
                0, 0, 0, 0, 0, false, false, false, false, 0, null);
        obj.dispatchEvent(event);
    } else if (obj.fireEvent) {
        event = document.createEventObject();
        event.button = 1;
        obj.fireEvent("on" + evtName, event);
        obj.fireEvent(evtName);
    } else {
        obj[evtName]();
    }
}

var obj = document.getElementById("......");
fireMouseEvent(obj, "click");
toto
fonte
1
Isso está obsoleto. Útil apenas para polyfills. developer.mozilla.org/pt-BR/docs/Web/API/MouseEvent/…
hipkiss
1

Você poderia usar esta função que eu compilei juntos.

if (!Element.prototype.trigger)
  {
    Element.prototype.trigger = function(event)
    {
        var ev;

        try
        {
            if (this.dispatchEvent && CustomEvent)
            {
                ev = new CustomEvent(event, {detail : event + ' fired!'});
                this.dispatchEvent(ev);
            }
            else
            {
                throw "CustomEvent Not supported";
            }
        }
        catch(e)
        {
            if (document.createEvent)
            {
                ev = document.createEvent('HTMLEvents');
                ev.initEvent(event, true, true);

                this.dispatchEvent(event);
            }
            else
            {
                ev = document.createEventObject();
                ev.eventType = event;
                this.fireEvent('on'+event.eventType, event);
            }
        }
    }
  }

Acione um evento abaixo:

var dest = document.querySelector('#mapbox-directions-destination-input');
dest.trigger('focus');

Assista ao evento:

dest.addEventListener('focus', function(e){
   console.log(e);
});

Espero que isto ajude!

Ifeanyi Amadi
fonte
1

Você pode usar o código abaixo para disparar um evento usando o método Element:

if (!Element.prototype.triggerEvent) {
    Element.prototype.triggerEvent = function (eventName) {
        var event;

        if (document.createEvent) {
            event = document.createEvent("HTMLEvents");
            event.initEvent(eventName, true, true);
        } else {
            event = document.createEventObject();
            event.eventType = eventName;
        }

        event.eventName = eventName;

        if (document.createEvent) {
            this.dispatchEvent(event);
        } else {
            this.fireEvent("on" + event.eventType, event);
        }
    };
}

iProDev
fonte
0

A maneira mais eficiente é chamar a mesma função que foi registrada addEventListenerdiretamente.

Você também pode acionar um evento falso com CustomEvente co.

Finalmente, alguns elementos, como <input type="file">suporte a um .click()método.

Walle Cyril
fonte
0
var btn = document.getElementById('btn-test');
var event = new Event(null);

event.initEvent('beforeinstallprompt', true, true);
btn.addEventListener('beforeinstallprompt', null, false);
btn.dispatchEvent(event);

isso acionará imediatamente um evento 'beforeinstallprompt'

Dan Alboteanu
fonte
-2

Use a chamada de evento jquery. Escreva a linha abaixo onde deseja acionar o onChange de qualquer elemento.

$("#element_id").change();

element_id é o ID do elemento cujo onChange você deseja acionar.

Evite o uso de

 element.fireEvent("onchange");

Porque tem muito menos suporte. Consulte este documento para obter suporte .

Bhuvan Arora
fonte
-2

HTML

<a href="demoLink" id="myLink"> myLink </a>
<button onclick="fireLink(event)"> Call My Link </button>

JS

// click event listener of the link element --------------  
document.getElementById('myLink').addEventListener("click", callLink);
function callLink(e) {
    // code to fire
}

// function invoked by the button element ----------------
function fireLink(event) {                   
    document.getElementById('myLink').click();      // script calls the "click" event of the link element 
}
Pall Arpad
fonte
-9

O que você quer é algo como isto:

document.getElementByClassName("example").click();

Usando jQuery, seria algo como isto:

$(".example").trigger("click");
Osiris RD
fonte
método de gatilho não é errado, mas é um método jQuery
Kamuran Sönecek
2
1. document.getElementByClassNamenão existe. 2. document.getElementsByClassNameexiste, mas retorna uma lista. 3. isso funciona apenas para alguns poucos eventos nativos. 4. O último exemplo aciona um evento jQuery onde não existe nenhum evento nativo subjacente.
Glenn Jorde