0

I am trying to create a function like the function of jQuery which changes the style of an HTMLElement, probably you have seen it somewhere:

$("button").css("color", "red");

which is pretty handy, so here is what I've tried:

function $(selector, parent=document){
return parent.querySelector(selector);
}

so the above code is the code of the function $ which grabs an HTMLElement from the DOM,this seems to work perfectly.

Now, the next step for me is to define the $ function methods and properties, so the method I want to create is the css method as seen in the previous example:

$.css = function(style, value){
this[style] = value;
}

now after testing the css method it's not working (and of course it will never work, but I'm just trying to deliver my question idea for you). I know a lot about object-oriented programming in JavaScript, I am comfortable with it, so I have no problem if you posted any answer, I will try my best to understand it. I've tried a lot to understand what's the magic that the jQuery developers made to create this method.

What do you think the best approach to make it? what about mixins, what if I wanted other functions and not just "$" to inherit this "css" method?

Mohammad
  • 111
  • 6
  • what about making a class called $ ? please suggest I need your help – Mohammad Sep 17 '20 at 19:42
  • 2
    `[...document.querySelectorAll()].forEach(element => element.style.color = 'red')` – Taplar Sep 17 '20 at 19:43
  • because that is not how creating instances of an object work. – epascarello Sep 17 '20 at 19:44
  • You mentioned `mixins` though. Are you using Vue or something? – Taplar Sep 17 '20 at 19:44
  • @Taplar, no, I am using only Vanilla JavaScript, I learned the term "mixins" from the course of Mosh Hamedani of JavaScript Object-orianted programming – Mohammad Sep 17 '20 at 19:45
  • 1
    https://www.freecodecamp.org/news/how-to-write-a-jquery-like-library-in-71-lines-of-code-learn-about-the-dom-e9fb99dbc8d2/ – epascarello Sep 17 '20 at 19:47
  • 2
    I think you also need to step back a bit. jQuery has been a very popular, very successful library, in part because of the design of its API. But if you're writing your own code for your own purposes, you should think about what style API you might want. Consider, for instance, `const elements = select('button'); css(elements, 'color', 'red')`. Is this better? Worse? I don't know. It's your API. But if your're going to build it up, think it through before reusing the jQuery version. – Scott Sauyet Sep 17 '20 at 19:53
  • 1
    @ScottSauyet, Oh thank you very much, I really appreciate your comment! this is a very good Idea, (always think out of the box) – Mohammad Sep 17 '20 at 19:58
  • Does this answer your question? [How to change CSS property using JavaScript](https://stackoverflow.com/questions/15241915/how-to-change-css-property-using-javascript) – Heretic Monkey Jan 19 '23 at 15:04

2 Answers2

4

To modify styles, you need to set a CSS property of the style declaration object of an element. For example:

elm.style.color = 'red';

You need to modify your $.css to access the current element(s) in the collection, and access their .style[propertyName] property.

You can put the collection onto a property of the instance, and make sure to put the css method as a prototype of the class:

function collection (selector, parent = document) {
  this.elms = parent.querySelectorAll(selector);
}
collection.prototype.css = function(prop, value) {
  for (const elm of this.elms) {
    elm.style[prop] = value;
  }
}
const $ = (...args) => new collection(...args);

$("button").css("color", "red");
<button>a button</button>
<button>a button</button>

Because your $ doesn't use new, you'll either need it to return an instance of a different class (as in the code above), or always use new when calling it, or have $ return its instance created via Object.create, or something like that. There are various methods.

CertainPerformance
  • 356,069
  • 52
  • 309
  • 320
  • Sorry, there is one problem with this code, which is the main reason I asked the question, thanks for your help, the problem is: when you do in the console console.log($("button")) you'll see the following output collection {elms: NodeList(1)} which is a problem because now you can't access the HTMLElement inherited methods which is a big problem, this code is not completed, I mean: try to make for example: $("button").parentNode you'll see the output is undefined – Mohammad Sep 17 '20 at 20:56
  • If you want to access a particular selected element itself, rather than the collection, then access one of the `elms`. eg `$('button')[0].classList.add('selected');` – CertainPerformance Sep 18 '20 at 01:11
  • 1
    You can't *both* have new methods (like `.css`) *and* the built-in DOM methods (like `parentNode`) easily, unless you manually repeat all the built-in DOM methods on the prototype. – CertainPerformance Sep 18 '20 at 01:12
  • "unless you manually repeat all the built-in DOM methods on the prototype" Okay? how to do it? it's impossible – Mohammad Sep 18 '20 at 15:32
  • Like: `collection.prototype.parentNode = function() { return this.elms[0].parentNode; }`, or make it a getter, and so on for all such methods – CertainPerformance Sep 18 '20 at 15:37
-1

Not sure if this is what you're after, but you could just apply the style inline?

var elem = document.querySelector('#some-element');

//set color to red
elem.style.color = 'red';

//set the background color to a light gray
elem.style.backgroundColor = '#e5e5e5';

//set the height to 225px
elem.style.height = '225px';
dotnetdev
  • 61
  • 3
  • 8