How to apply a function with "foreach", using a set of pre-selected items by the Jquery style selector?

Asked

Viewed 40 times

2

I do not know if I could be clear in the title, and so I will illustrate. In jQuery, we could do something like this to make all H2 green:

$('h2').css('color','green')

I’m trying to get rid of jQuery by creating generic function based on what else I do on my website. So I was turning that code above into something like:

// $$ is my selector, to avoid conflicts with jQuery, and is set to

function $$(selector){
    return document.querySelectorAll(selector);
}

// setStyle would be a function that would use a foreach to go through all the items the selector found (foreach as it is in the function does not work because it needs to be "called" by the array)

function setStyle(styleName, value){
    forEach(function(x){
        x.style[styleName] = value;
    })
}

// This is how I would like to make the change on my site, but I don’t see how to pass the selector items so that foreach can use

$$('h2').setStyle('color','green')

*** Remembering that if I pass the selector as a parameter of the setStyle function, I already solve this, as an example below. But it’s not the way I want to apply.

function setStyle(elements, styleName, value){
    elements.forEach(function(x){
        x.style[styleName] = value;
    })
}

setStyle($$('h2'),'color','green')

I hope I have been able to exemplify clearly, and I am open to any suggested change in the code that will help me to carry out the action as the example I mentioned above.

2 answers

2

If you want to create this without using classes, you can also use a more dependent approach Factory functions:

There’s nothing wrong with classes. It’s just another example of using to show that you’re not required to use classes if you want to do something like this.

// API PÚBLICA
// ===========

function $$(selector) {
  const els = document.querySelectorAll(selector);
  return create$$Object(Array.from(els));
}

// API PRIVADA
// ===========

function create$$Object(els) {
  return {
    getAll: () => els,
    get: (i) => els[i],
    css: $$css(els)
  };
}

function $$css(els) {
  return function css(prop, value) {
    for (const el of els) {
      el.style.setProperty(prop, value);
    }
    return create$$Object(els);
  };
}

Note that the function $$ creates an object $$Object (arbitrary name) through function create$$Object. This object has all the functions that this "clone" of jQuery should support. In addition to the function $$, other functions, such as $$css also return a new object of the same type, to allow the chaining of functions.

Example of use:

// Exemplo:
$$('li').css('color', 'red').css('background-color', 'black');

// API PÚBLICA
// ===========

function $$(selector) {
  const els = document.querySelectorAll(selector);
  return create$$Object(Array.from(els));
}

// API PRIVADA
// ===========

function create$$Object(els) {
  return {
    getAll: () => els,
    get: (i) => els[i],
    css: $$css(els)
  };
}

function $$css(els) {
  return function css(prop, value) {
    for (const el of els) {
      el.style.setProperty(prop, value);
    }
    return create$$Object(els);
  };
}
<ul>
  <li>Foo</li>
  <li>Bar</li>
  <li>Baz</li>
  <li>Qux</li>
</ul>

A bit more complete example:

// Exemplo:
$$('li')
  .filter((li) => parseInt(li.textContent, 10) % 2 === 0)
  .append(' (par)')
  .css('color', 'red');

// API PÚBLICA
// ===========

function $$(selector) {
  const els = document.querySelectorAll(selector);
  return create$$Object(Array.from(els));
}

// API PRIVADA
// ===========

function create$$Object(els) {
  return {
    getAll: () => els,
    get: (i) => els[i],
    
    // Manipulação e outros:
    css: $$css(els),
    append: $$append(els),
    filter: $$filter(els)
  };
}

function $$css(els) {
  return function css(prop, value) {
    for (const el of els) {
      el.style.setProperty(prop, value);
    }
    return create$$Object(els);
  };
}

function $$append(els) {
  return function append(html) {
    for (const el of els) {
      el.innerHTML += html;
    }
    return create$$Object(els);
  };
}

function $$filter(els) {
  return function filter(predicate) {
    return create$$Object(els.filter(predicate));
  };
}
<ul>
  <li>1</li>
  <li>2</li>
  <li>3</li>
  <li>4</li>
  <li>5</li>
</ul>

0

If you want to use this function setStyle as a method, you will need to use the same approach as jQuery: create a class containing all these methods.

Example:

class Selector extends Array {
    constructor(query) {
        super()
        var nodos = document.querySelectorAll(query)
        Object.assign(this, nodos)
    }

    css(propriedade, valor) {
        for (var i = 0; i < this.length; i++) this[i].style[propriedade] = valor
        return this
    }
}

function $$(query) {
    return new Selector(query)
}

In the created class, it will store all nodes found by the function querySelectorAll as properties, and with the method css, i iterate on these properties and apply the style passed as parameter. The function $$ is just a "shortcut" to create a new instance of this class.


The other alternative would be to add these methods directly into the class NodeList

Object.defineProperty(NodeList.prototype, 'css', {
    value(propriedade, valor) {
        for (var i = 0; i < this.length; i++) this[i].style[propriedade] = valor
        return this
    }
})

You will need to create and handle all methods of this class manually. This is actually more interesting than using a library like jQuery?

Anyway, here are examples working:

class Selector extends Array {
    constructor(query) {
        super()
        var nodos = document.querySelectorAll(query)
        Object.assign(this, nodos)
    }

    css(propriedade, valor) {
        for (var i = 0; i < this.length; i++) this[i].style[propriedade] = valor
        return this
    }
}

function $$(query) {
    return new Selector(query)
}

function trocarCor() {
    $$('span').css('color', 'red')
}
<span>Exemplo</span>
<button onclick="trocarCor()">Clique aqui para alterar a cor</button>

Object.defineProperty(NodeList.prototype, 'css', {
    value(propriedade, valor) {
        for (var i = 0; i < this.length; i++) this[i].style[propriedade] = valor
        return this
    }
})

function $$(query) {
    return document.querySelectorAll(query)
}

function trocarCor() {
    $$('span').css('color', 'red')
}
<span>Exemplo</span>
<button onclick="trocarCor()">Clique aqui para alterar a cor</button>

  • 1

    I really think advising to use the modification of a prototype in Sopt is not a good idea. At least a warning. "Proton pollution" is not a good practice and should almost always be avoided, since it can bring some problems.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.