6

I've been looking all over the web for how to do this. I am trying to make Jquerys .html() function in vanilla JavaScript. I want to recreate so I can understand it better. I've tried the following but nothing seems to work, I just don't understand what I am doing wrong.

let $ = function(ele) {
    if (ele.charAt(0) == '.' || ele.charAt(0) == '#') {
    let newEle = cut(ele,0);
    if (ele.charAt(0) == '#')
        get(newEle);
    else
        return document.getElementsByClassName(newEle);
  } else
    return document.getElementById(ele);
}

$.prototype.html = function(html) {
    this.innerHTML = html;
}

$('test').html('hey');
$('.hey')[0].html('hey');
function cut(string,num) {
    let a = string.slice(0,num);
  let b = string.slice(num + 1,string.length);
  return a + b;
}

It doesn't work, the console log reports this error:

Uncaught TypeError: $(...).html is not a function

Please help and thanks in advance.

2 Answers 2

1

The problem here is what you are returning from the $ function. Think about this: document.getElementsByClassName and document.getElementById return dom elements and dom elements don't have a .html function. That is why you are getting the error.

What you need is to return is an object, a wrapper, with a .html function, and a closure over the dom elements that you want to modify.

Sign up to request clarification or add additional context in comments.

Comments

1

Because you're returning an object from $, you're overriding the default behavior of new $; instead of resulting in the newly-created object, it results in the object you returned out of $.

Instead, you'd want to remember the results of those getElementsByClassName/getElementById calls in an array or Set you store on this (the newly-created object), and then use that array or Set within html (since you want to loop over all matching elements in the case where you're setting the new HTML).


Side note: Since you're using ES2015+ features anyway (let), you might want to use the simpler class syntax instead of a separate function declaration and assigning to $.prototype:

class $ {
    constructor(ele) {
        // ...
    }

    html(html) {
        // ..
    }
}

8 Comments

So going off of your class thing, I'm still a little confused on what I would put inside of the html(html) { }. Would I put this.innerHTML = html? Sorry, I'm still learning a lot.
@JoeTheHobo - No, as I said above, since you want to loop over all matching elements in the case where you're setting the new HTML, you'd use a loop on the array/Set that you saved in the constructor. When html receives an argument (so you're making it a setter), you'd set innerHTML on the elements in that array/Set, in the loop.
@JoeTheHobo - Re your deleted answer: No, very much not that. :-) Never add to Object.prototype. (And if you add to other built-in prototypes, be sure to use defineProperty so you're creating a non-enumerable property.) Re Johnny Zabala's answer: No, there's no need to abandon your prototype-based solution (class is also prototype-based). While returning an object that closes over the elements is one option, it's not necessary.
Kay thanks for the help. I just need to look into classes a little bit more to get a better understanding. Thanks again.
@T.J.Crowder my answer don't abandon prototype-based solution. But if you are trying to replicate JQuery you cannot use a class base-solution as your main api. If you use a class you will need to use the new keyword and JQuery don't work like that. You still can have a class underneath and use prototype but if you are mimicking JQuery, a class can't be your api entry point.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.