HTML event handler attributes: down the rabbit hole
datastation.multiprocess.io
datastation.multiprocess.io
Also. Onclick will simply execute the content as JavaScript. So if you’re not passing an argument, why would you expect an argument?
You can simply return false to prevent the defaults from happening.
The whole article has nothing to do with a rabbit hole. But more with a junior dev
[1] - https://developer.mozilla.org/en-US/docs/Web/API/FormData/Fo...
I mentioned in the post I switched to onsubmit.
> But more with a junior dev
Damn, anyone can be a junior dev these days! :)
I'm a big fan of the data attributes for the same reason, they bind onto the actual element they belong with, they're available in JS and CSS, and they add semantic meaning to your markup when you're reading the source.
(1) you should arguably disable eval to help prevent code injections vs CSP. Turning that on disables HTML event handler attributes as those are strings that are "eval"ed
https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP
(2) using event handler attributes or the JS equivalent (elem.onclick = somefunc) is not very forward thinking as only one handler can be assigned. Sure, you tell yourself "Well, I'm only using one handler" ... until you're not. For example you decide to add event tracking or similar functionality and, since you've followed your pattern of using event handler attributes, only the last one to assign its function wins.
(3) Its often much easier to add events in code
https://jsfiddle.net/jfkds5px/
Yes, you can assign by attribute (see 2) or you can create HTML text (see 1)
(4) this was mentioned in the article but in an event handler, this = the element the listener was assigned to, event.target = the element that was event was triggered on
https://jsfiddle.net/8efd4ghb/
(5) button in forms submit the form by default. If you don't want that behavior add type="button". No need for event.preventDefault();
Depending on CSP is a smell, just like any time you open a GUI program from the terminal and it spams a bunch of (clearly undesirable) stuff to stdout—or, for that matter, opening the browser console on a given Web page and seeing a bunch of exceptions or other kinds of printf-style debugging spew that shouldn't have gotten checked in.
Besides that, using CSP to disable injected content is user-hostile, which is annoying given that the only "justification" for CSP only comes down to Web publishers whose development practices are such a mess that they don't have control over their content (which, due to the normalization of deviance in the world of Web development, means most of them these days).
Nowadays, I open up the browser console on pages associated with big name properties (Google, GitHub...), and it's filled with CSP and CORS violations that never should have escaped into production. I think it was better when browsers had status bars and IE put a badge in the corner, e.g. indicating when the current page encountered an error during the execution of a script. It forced publishers to confront the shoddiness of their work and deal with it if for no other reason than out of sheer embarrassment.
> button in forms submit the form by default. If you don't want that behavior add type="button". No need for event.preventDefault()
That, too, would be user-hostile. Keep your markup semantic so agents can reason about the content on a page. Don't just target incidental behavior.
Do you think HTTPS is user hostile as well, not being able to read all the network traffic generated on my machines feels off for me. In the end I guess HTTPS is good for the user and so is CSP.
2. YAGNI, in my experience.
3. That's a lot more code than onsubmit="handler(event)", and you've lost the ability to see what the form is doing by reading the HTML.
5. type=submit is semantic and helps the browser provide default behavior like submitting the form when you press enter.
I‘m not sure why the author doesn‘t want to handle form/multipart. Does Go not have good ergonomics for this case?
The Event API is not deprecated: https://developer.mozilla.org/en-US/docs/Web/API/Event. In the posted examples the `event` object implements the Event interface.
https://developer.mozilla.org/en-US/docs/Web/API/Window/even...
It's been around since IE 4 and is the "current event being handled by the site's code" so it's event inside the scope of an event handler and undefined anywhere else. That's definitely an anti-feature lol, maybe IE 4 didn't pass the event object into an event handler's synthetic function as an argument and window.event was a bodge to allow for <div onclick="alert(event.button)"> ?
Actually, I bet back then the code in the event handler attribute was just wrapped in eval() and executed, so you would need to have the event object in the global scope to be usable in the eval'd code.
The name of the synthesized function is the attribute name itself. So `<button onclick="alert(arguments.callee.name)">` will alert "onclick" on click.
I wonder if the name also reflects capitalization given that HTML element and attribute names are generally case insensitive.
Oh, any by the way, HTML attributes work with event bubbling. Add "onsubmit" to some div tag and it will catch submit events originating from any of the div's children. This is why there is support for eg. "onlick" on stuff like h1.
Think of the actual function that gets called as residing in an internal slot on the element. Both the attribute and the property can set the slot's value, and setting and the DOM propertie's getter accesses the slot directly. Sort of, if i remember correctly.
element.addEventListener('submit', submit)
The second argument to `addEventListener` is a callback that takes the event as its argument. (`element` should be the form and the event should be `submit` for accessibility reasons.)Also, the author's example comparing `x === window.x` as evidence that it's insufficient to know if the in-scope variable is the same as the one on the window is wrong. The example uses a primitive value (`1`) which in JS are passed by value, so of course whenever you compare 1 with 1 it'll return true regardless of which variable the 1 is stored in. Objects, (that `event`s are an example of) are passed by reference. So you get
const x1 = {foo: 1}
const x2 = {foo: 1}
x1 == x1 // true
x1 == x2 // false
x1 == {foo: 1} // false
So a simple comparison between objects is enough to determine if they are the same instance. But it won't work to see if 2 different objects contain consist of the same property-values as each other.Why avoid something when you can instead learn how it works? :)
> Also, the author's example comparing `x === window.x` as evidence that it's insufficient to know if the in-scope variable is the same as the one on the window is wrong.
I think you misunderstood it.
When you pass an object as an argument to a function it's passed as a reference. It would have been clearer if I used an object (I was trying to simplify the example) but my code is still illustrating what I meant it to even if I substituted `window.x = {a:2}` for `window.x = 1`.
Your first example is enough to conclude that the locally scoped `event` is the same as the one on the window object, due to the pass-by-reference nature of JS objects. The fact that comparing the two returns true means they must be the same object.
window.event may be a deprecated api but the thing that sends the event to the string event handler isn't. It doesn't matter that they're the same object it's about apis.
document.addEventListener('submit', ev => {
if (ev.target is a kind of a form I want json submit on) {
ev.preventDefault();
handle_json_submit(ev.target)
}
}, true);
Instead of sprinkling onsubmit="..." everywhere.For myself, the biggest thing is locality. Coming into a large codebase that's been around for a while, it's a lot easier to understand if the event handlers are defined inline, right there with the form itself.
If they aren't, you first have to determine experimentally that it's not using the default form behavior. Then you end up having to hunt down where in the code someone put the `addEventListener` calls and then read them to decide which calls (and which conditional branches) apply to this form.
If the event handlers are instead defined on the forms themselves, the onsubmit behavior is immediately obvious just by looking at the form. It's a bit more code to write, but it's much easier to digest later.
Not really..., neither memory leaks, nor missing the addition of event handling to newly added DOM elements is a problem for the addEventListener solution.
If the codebase is using JSON submitted forms almost everywhere, it's easier to build that feature more declaratively, by adding support for a special enctype attribute value (using one global addEventListener that would handle it), for example:
<form enctype="application/json"> ...
That would be more in line with how other features of the <form> element work.addEventListener solution is also better if you decide to add CSP in the future.