Tuve un problema. Aquí está el código muy simplificado:
<!DOCTYPE html> <html> <head> <script> function ended(e) { alert("Ended"); } function paused(e) { alert("Paused"); } function played(e) { alert("Played"); } </script> </head> <body> <div> <video src="videoFile.mp4" controls onended="ended(event)" onpause="paused()" onplay="played(event)" > </video> </div> </body> </html>Cada vez que pausaba, reproducía o finalizaba el video, recibía el error:
Uncaught TypeError: played is not a function at HTMLVideoElement.onplay o lo mismo pero con paused o ended en lugar de played , y en onpause y onended en lugar de en onplay .
Ya lo resolví, así que pongo la respuesta a continuación, para aquellos que se encuentren con un problema similar.
Resulta que HTMLMediaElement , que es el elemento <video> , contiene algunas propiedades booleanas: ended , paused y played .
Y resulta que cuando el navegador (Chrome, tal vez otros) llama al evento, obtiene el valor de esas propiedades (que es true o false ), en lugar de usar mis funciones ya definidas. Entonces intenta llamar true(event) o false(event) , y dado que true y false no son funciones, da el error de que played is not a function .
Entonces, la respuesta es, asegúrese de que los nombres de las funciones que usa para los eventos no coincidan con las propiedades dentro del HTMLElement relevante que activa el evento, y entonces no debería tener ningún problema. (No lo he comprobado, pero parece probable que esto ocurra con otros HTMLElements)
En mi caso, los cambié a doMyEnded , doMyPaused y doMyPlayed y todo estuvo bien.
NOTA: Recomiendo encarecidamente a cualquiera que quiera saber más sobre esto que lea la respuesta de TJ Crowder
Esta es una de las muchas razones para no usar controladores de eventos de estilo onxyz . No solo pueden llamar a funciones globales (que no son las mejores prácticas), sino que se ejecutan en un entorno de alcance complicado que incluye no solo las propiedades del elemento actual (el problema que tenía), sino también en algunos casos las propiedades de otros elementos ( como el form en el que se encuentra una input ). (Más abajo).
En su lugar, use el manejo de eventos moderno (y módulos cuando sea posible [todos los navegadores modernos los admiten]).
Por ejemplo:
<!DOCTYPE html> <html> <head> </head> <body> <div> <video src="videoFile.mp4" controls></video> </div> <script type="module"> function ended(e) { console.log("Ended"); } function paused(e) { console.log("Paused"); } function played(e) { console.log("Played"); } const videoElement = document.querySelector(`video[src="videoFile.mp4"]`); videoElement.addEventListener("ended", ended); videoElement.addEventListener("pause", paused); videoElement.addEventListener("play", played); </script> </body> </html> Acerca del "entorno de alcance complicado": el código en un controlador de eventos de estilo de onxyz se ejecuta en un alcance que se crea de manera efectiva como este (para su ejemplo):
with (document) { with (theTargetVideoElement) { // ...your code here... } } (Así es, la temida (y obsoleta) declaración with ).
Para un elemento en un form , es aún peor:
with (document) { with (theForm) { with (theTargetElementInTheForm) { // ...your code here... } } }Aquí hay un ejemplo de eso:
<form method="POST"> <input type="button" onclick=" console.log(documentElement.tagName); // 'HTML' console.log(method); // 'post' console.log(type); // 'button' " value="Click Me"> </form>documentElement proviene de documentmethod proviene del elemento de form .type proviene del elemento de inputSolo di no. 😃