Reputation: 745
I am trying to make my code shorter and more optimized, and want to make it look clearer.
So far I did this :
function id(a) {
return document.getElementById(a);
}
function cl(a) {
return document.getElementsByClassName(a);
}
function tg(a) {
return document.getElementsByTagName(a);
}
function qs(a) {
return document.querySelector(a);
}
function qa(a) {
return document.querySelectorAll(a);
}
Now I have the possibility to call qs("#myElement")
. Now I want to attach a event to the specified element just like qs("#myElement").addEventListener("click", callBack)
. It works great for me. But when I try to make this :
function ev(e, call) {
return addEventListener(e, callback);
}
And then try to call qs("#init-scrap").ev("click", someFunction)
then it pops up the following error :
Uncaught (in promise) TypeError: qs(...).ev is not a function.
. I don't know what is the problem, do I have to try method chaining ? or any other way I can resolve this problem.
Note : I don't want to use any libraries or frameworks liek Jquery etc.
Upvotes: 1
Views: 1365
Reputation: 24768
I looked into the previous answers as an inspiration and created my take on it.
const $ = (selector, base = document) => {
return base.querySelector(selector);
};
Node.prototype.on = function(type, listener) {
return this.addEventListener(type, listener);
};
document
but it's optional.$
and on
so that's what I use, just like jQuery.$('button').on('click', (e) => {
console.log(e.currentTarget);
});
Upvotes: 0
Reputation: 9151
There is an error in your ev
method. It should be
const ev = document.addEventListener.bind(document);
So instead of creating new functions that wrap the original, you can alias the actual function itself.
You should do the same for your other aliases if you want to go with this approach.
const qs = document.querySelector.bind(document);
const qa = document.querySelectorAll.bind(document);
My final word of advise would be to not alias these methods at all. The abbreviated method names hurt the readability of your code. Readability almost always trumps brevity as it comes to code.
Upvotes: 0
Reputation: 722
If you wish to use syntax qs("#init-scrap").ev("click", someFunction)
, you need to wrap object returned by querySelector
into another object that has ev
function.
class jQueryLite {
constructor(el) {
this.el = el;
}
ev(e, callback) {
this.el.addEventListener(e, callback);
return this;
}
}
qs(a) {
return new jQueryLite(document.querySelector(a));
}
It's called Fluent interface, if you wish to look it up.
Upvotes: 2
Reputation: 63524
Just pass the element/nodelist in as the first argument and attached the listener to it.
function ev(el, e, call) {
return el.addEventListener(e, callback);
}
As an alternative, but not something I would recommend, you could add ev
as a new Node
prototype function:
function qs(selector) {
return document.querySelector(selector);
}
if (!Node.prototype.ev) {
Node.prototype.ev = function(e, cb) {
return this.addEventListener(e, cb);
};
}
qs('button').ev('click', handleClick);
let count = 0;
function handleClick() {
console.log(count++);
}
<button>Count+=1</button>
Note I've only tested this with document.querySelector
. You might have to alter the code to work with document.querySelectorAll
etc as they don't return single elements.
Upvotes: 2