Nadeem Ahmad
Nadeem Ahmad

Reputation: 745

How to return "addEventListener()" from another function - Javascript

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

Answers (4)

Jens Törnell
Jens Törnell

Reputation: 24768

I looked into the previous answers as an inspiration and created my take on it.

Core

const $ = (selector, base = document) => {
  return base.querySelector(selector);
};

Node.prototype.on = function(type, listener) {
  return this.addEventListener(type, listener);
};
  • It supports a base value in case you have another element than document but it's optional.
  • I like $ and on so that's what I use, just like jQuery.

Call it like below

$('button').on('click', (e) => {
  console.log(e.currentTarget);
});

Upvotes: 0

Jonathan
Jonathan

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

Dread Boy
Dread Boy

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

Andy
Andy

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

Related Questions