And it works well, but I know it's not a good practice.
If having #logInButton
on the page is optional, that's perfectly good practice — other than using onclick
rather than addEventListener
(but that's probably a matter of style). Naturally, you'd have this code in a script linked at the end of the document, just prior to the </body>
tag (or trigger it via a DOMContentLoaded
callback).
But if you want the equivalent of the jQuery, you need to think in jQuery's "set-based" mindset and use querySelectorAll
:
// Not very efficient
document.querySelectorAll("#logInButton").forEach(function() {
// Set up the handler here using `this`
});
Except that jQuery optimizes queries using #id
format to a getElementById
call (which is dramatically faster) and then uses an if
(like yours) to build the set with either one element or zero.
Perhaps in your quest to not use jQuery, you might give yourself a couple of helper functions to take its place, as the DOM API is quite verbose. If you like jQuery's set-based nature, you might even make them set-based:
function MyQuery(selector) {
if (!selector) {
this.data = [];
} else if (typeof selector === "string") {
// (jQuery takes it further than this, search in an unminified version for `rquickExpr`)
var id = /#([\w-]+)/.match(selector);
if (id) {
var e = document.getElementById(id[0]);
this.data = e ? [e] : [];
} else {
this.data = Array.from(document.querySelector(selector));
}
} else {
/* ...handle other things, such as DOM elements or arrays of them...? */
this.data = /*...*/;
}
}
MyQuery.prototype = {
constructor: MyQuery,
on: function(eventName, handler) {
this.data.forEach(function(element) {
element.addEventListener(eventName, handler);
});
return this;
}
// ...etc...
};
function qset(selector) {
return new MyQuery(selector);
}
Then
qset("#logInButton").on("click", /*...*/);
Of course, you might find yourself basically recreating jQuery. But if you keep it lean...
Side note: Using forEach
on the return value of querySelectorAll
requires an up-to-date browser, or that you polyfill it:
if (typeof NodeList !== "undefined" &&
NodeList.prototype &&
!NodeList.prototype.forEach) {
Object.defineProperty(NodeList.prototype, "forEach", {
value: Array.prototype.forEach
});
}
For truly obsolete browsers (like IE8), you'd have to polyfill Array.prototype.forEach
first.