javascript - ¿Cómo hacer que la función onclick se ejecute solo una vez?
html dom-events (7)
Tengo este código para Google Analytics en un botón. Necesito que se ejecute solo una vez, para que el usuario no pueda cambiar las estadísticas presionando el botón muchas veces. Intenté soluciones de temas similares, pero no funcionan. Por favor ayuda. Este es mi codigo.
<script>
function klikaj(i) {
gtag(''event'', ''first-4'', {
''event_category'' : ''cat-4'',
''event_label'' : ''site''
});
}
document.body.addEventListener("click", klikaj(i), {once:true})
</script>
<div id="thumb0" class="thumbs" onclick="klikaj(''rad1'')">My button</div>
Manejadores de eventos y oyentes
Hay tres formas * de registrar un evento en un elemento.
Los siguientes ejemplos muestran cómo registrar el evento click en un enlace con la clase
.once
** que llama a la función
test()
cuando se activa.
-
Oyente de eventos (recomendado)
-
document.querySelector(''.once'')
.addEventListener (''clic'', prueba); ``
-
-
Atributo en evento (
no
recomendado)
-
<a href=''#/'' class=''once''
onclick=''test()''>>Click</a>
-
-
Propiedad en el evento
-
document.querySelector(''.once'')
.onclick = prueba; ``
-
*
Consulte los
controladores DOM en el evento para más detalles
**. Una
.once
clase no es relevante para # 2
Cuestiones
El
OP
(
O
riginal
P
ost) tiene un detector de eventos (ver # 1 arriba) registrando un evento click en la etiqueta
<body>
y un atributo en el evento (ver # 2 arriba) registrando el evento click en un
<div>
.
Cada uno llama a una función (también conocida como función de devolución de llamada) llamada
klikaj()
que es redundante.
Hacer clic en el cuerpo (que normalmente está en todas partes) no es útil cuando pretendes que el usuario haga clic en un div.
Si el usuario hace clic en cualquier lugar que
no sea div
, se
klikaj()
.
Si el usuario hace clic en el div, se
klikaj()
dos veces.
Sugiero que elimine ambos controladores de eventos y los reemplace con esto:
A.
document.getElementById(''thumb0'').addEventListener("click", klikaj);
Tenga en cuenta que
klikaj
no tiene paréntesis
()
porque el navegador interpreta
()
como ejecutar la función ahora en lugar de cuando el usuario desencadena el evento registrado (ver # 1 y # 3 arriba).
Si un controlador de eventos tiene sentencias adicionales y / o funciones de devolución de llamada, se debe incluir una función anónima y se aplica la sintaxis normal:
SEGUNDO.
document.getElementById(''thumb0'').addEventListener("click", function(event) {
klikaj();
console.log(''clicked'');
});
Una alternativa más limpia es agregar líneas adicionales en la definición de la función de devolución de llamada y registrar eventos como #A.
Solución
Simplemente agregue la siguiente declaración como la última línea de
klikaj()
:
this.style.pointerEvents = "none";
Eso hará que la etiqueta cliqueada no se pueda hacer clic. Aplicado al código OP, debería ser así:
<div id="thumb0" class="thumbs">Thumb 0</div>
<script>
function klikaj(event) {
gtag(''event'', ''first-4'', {
''event_category'' : ''cat-4'',
''event_label'' : ''site''
});
this.style.pointerEvents = "none";
}
document.getElementById(''thumb0'').addEventListener("click", klikaj);
</script>
Manifestación
La siguiente demostración tiene dos enlaces:
-
.default
: un enlace normal registrado en el evento de clic que, cuando se activa,test()
llamadastest()
-
.once
: un enlace registrado en el evento click que, cuando se activa, llama atest()
y hace que el enlace no se pueda hacer clic.
function test() {
console.log(''test'');
}
document.querySelector(''.default'').onclick = function(e) {
test();
}
document.querySelector(''.once'').onclick = function(e) {
test();
this.style.pointerEvents = ''none'';
}
<a href=''#/'' class=''default''>Default</a><br>
<a href=''#/'' class=''once''>Once</a>
Elimine el atributo
onclick
en su botón y registre el oyente a través de JavaScript, como intentó hacer:
<div id="thumb0" class="thumbs"
style="border: 1px solid; cursor: pointer; float: left">
My button
</div>
<script>
function klikaj(i) {
console.log(i);
}
document.getElementById(''thumb0'')
.addEventListener("click", function(event) {
klikaj(''rad1'');
}, {once: true});
</script>
Si su navegador no admite la opción
{ once: true }
, puede eliminar el detector de eventos manualmente:
<div id="thumb0" class="thumbs"
style="border: 1px solid;cursor: pointer;float:left">
My button
</div>
<script>
function klikaj(i) {
console.log(i);
}
function onClick(event) {
klikaj(''rad1'');
document
.getElementById(''thumb0'')
.removeEventListener("click", onClick);
}
document
.getElementById(''thumb0'')
.addEventListener("click", onClick);
</script>
Hay un problema con la forma en que intenta adjuntar la función del controlador.
La función
klikaj(i)
regresa
undefined
por lo que está adjuntando indefinida al botón.
Si desea ejecutar
klikaj(i)
cuando se hace clic en el botón,
klikaj(i)
dentro de un cierre como este:
const button = document.querySelector(''button'')
const i = 10
function klikaj(i) {console.log(''clicked once'')}
button.addEventListener(''click'', () => { klikaj(i) }, {once: true})
<button>Hello world</button>
Si el navegador no admite
{once: true}
, puede simularlo usando:
const button = document.querySelector(''button'')
const i = 10
function klikaj(i) {console.log("clicked once")}
function clickOnceHandler(event) {
klikaj(i)
event.currentTarget.removeEventListener(''click'', clickOnceHandler)
}
button.addEventListener(''click'', clickOnceHandler)
<button>Hello world</button>
Recomendaría establecer una variable y verificar su valor.
<script>
var clicked = false;
function klikaj(i) {
if (clicked === false) {
gtag(''event'', ''first-4'', {
''event_category'' : ''cat-4'',
''event_label'' : ''site''
});
}
clicked = true;
}
...
</script>
O eliminar el evento onclick según lo sugerido por otros,
<script>
function klikaj(i) {
gtag(''event'', ''first-4'', {
''event_category'' : ''cat-4'',
''event_label'' : ''site''
});
document.getElementById(''thumb0).onclick = undefined;
}
...
</script>
Tenga en cuenta que,
once: true
desafortunadamente no es compatible con IE y Edge.
Ver
MDN
Si desea que se invoque la función solo cuando el usuario hace clic en el botón, deberá eliminar el detector de eventos de clic del cuerpo.
Para activar su función gtag solo una vez, puede cambiar la definición de la función de klikaj dentro del cuerpo de la función. Después de la primera llamada, nunca se llamará a gtag.
El siguiente código funciona bien.
<script>
function klikaj(i) {
gtag(''event'', ''first-4'', {
''event_category'' : ''cat-4'',
''event_label'' : ''site''
});
klikaj = function() {};
}
</script>
<div id="thumb0" class="thumbs" onclick="klikaj(''rad1'')">
My button
</div>
Simplemente use una variable de bandera y configúrela en la primera ejecución:
var handlerExecuted = false;
function clickHandler() {
if (!handlerExecuted) {
console.log("call gtag() here");
handlerExecuted = true;
} else {
console.log("not calling gtag() function");
}
}
document
.getElementById("thumb0")
.addEventListener("click", clickHandler);
<div id="thumb0" class="thumbs">My button</div>
Una variación avanzada que usa cierres y podría usarse en varios botones:
function clickHandlerFactory() {
var handlerExecuted = false;
return function() {
if (!handlerExecuted) {
console.log("call gtag() here");
handlerExecuted = true;
} else {
console.log("not calling gtag() function");
}
}
}
[...document.querySelectorAll(".thumbs")].forEach(function(el) {
el.addEventListener("click", clickHandlerFactory());
});
<div id="thumb0" class="thumbs">Button 1</div>
<div id="thumb1" class="thumbs">Button 2</div>
puede usar
removeAttribute()
esta manera:
document.getElementById(''thumb0'').removeAttribute("onclick");
o puede dejar que la función devuelva falso de esta manera:
document.getElementById(''thumb0'').onclick = ()=> false