I have planned to get a rid of jQuery, just to learn more plain javascript to build my own libraries. I have created function __ similar to jQuery's $. First prototype method I choose to be _addClass which actually add a class to DOM element(s);
Html code is simple:
(() => {
function __(arg) {
if (!(this instanceof __))
return new __(arg);
this.element = null;
this.elements = null;
this.singleElement = false;
switch (arg.substring(0, 1)) {
case ".":
this.elements = document.getElementsByClassName(arg.substring(1));
break;
case "#":
this.element = document.getElementById(arg.substring(1));
this.singleElement = true;
break;
case "&":
this.elements = document.getElementsByName(arg.substring(1));
break;
default:
this.elements = document.querySelectorAll(arg);
break;
}
return this;
}
__.prototype._addClass = (a) => {
if (this.singleElement) {
this.element.classList.add(a);
return this.element;
} else {
this.elements.forEach((element) => element.classList.add(a));
return this.elements;
}
}
document.getElementById("btn").addEventListener("click", () => {
__("#test")._addClass("new-class-style");
})
})();
<div id="test">Div content</div>
<button id="btn">Button</button>
However, I'm getting error:
Uncaught TypeError: Cannot read properties of undefined (reading 'classList')
pointing to this.element
or this.elements
or this.singleElement
are undefined and I just can't figure why?
Edit:
Concept was actually OK, but I often use arrow function instead of regular javascript function since in classes in callback with function, this
is not working, so I use arrow function in which this
is working in callback. And I just haven't realized that in declaring prototype I cannot use arrow functions. And calling window.__ = __;
is needed to use out of this scope.
Final working version, with all suggested changes will be:
(() => {
function __(selector) {
if (!(this instanceof __))
return new __(selector);
this.elements = null;
if (selector !== undefined)
this.elements = document.querySelectorAll(selector);
return this;
}
__.prototype.addClass = function (...a) {
this.elements.forEach((element) => {
a.forEach((className) => element.classList.add(className));
});
return this;
}
__.prototype.removeClass = function (...a) {
this.elements.forEach((element) => {
a.forEach((className) => element. classList.remove(className));
});
return this;
}
__.prototype.html = function (a) {
if (a === undefined) {
let out = "";
this.elements.forEach((element) => out = element.innerHTML);
return out;
}
this.elements.forEach((element) => element.innerHTML = a);
return this;
}
__.prototype.text = function (a) {
if (a === undefined) {
let out = "";
this.elements.forEach((element) => out = element.innerText);
return out;
}
this.elements.forEach((element) => element.innerText = a);
return this;
}
__.prototype.on = function (type, callback) {
this.elements.forEach((element) => {
element.addEventListener(type, callback);
});
return this;
}
window.__ = __;
})();
__("#btn").on("click", () => {
__("#test").addClass("some-class").text("Div content chaged");
})
<div id="test">Div content</div>
<button id="btn">Button</button>