Ronan
Ronan

Reputation: 177

Apply a function to several elements at once

When I apply the same function to several elements, I usually do the following:

var func = function(elem) {
  elem.style.color = 'red';
};

var p = document.querySelector('p');
var div = document.querySelector('div');

func(p);
func(div);

I was wondering if there is an easy way to apply this function to two (or more) elements at once ? Eg :

func(p, div); // Apply my function to both elements at once

Upvotes: 1

Views: 385

Answers (6)

laruiss
laruiss

Reputation: 3816

You could combine some of the great answers here to come up with a functionnal programming code easily reusable :

var f = function (applyTo) {
    var makeArray = function(arrayLike) {
        return Array.prototype.slice.call(arrayLike);
    };
    return function () {
        var args = makeArray(arguments),
            elements = [];
        args.forEach(function (selector) {
            var newElements = makeArray(document.querySelectorAll(selector));
            console.log(newElements);
            elements = elements.concat(newElements);
        });
        elements.forEach(applyTo);
    }
};

var redify = function (elem) {
    elem.style.color = '#F00';
}

var underline = function (elem) {
    elem.style.textDecoration = 'underline';
}

var overline = function (elem) {
    elem.style.textDecoration = 'overline';
}

f(redify)('div', 'p');

f(underline)('div.test2');

f(overline)('p.test2');

JSFiddle

Upvotes: 1

user663031
user663031

Reputation:

Transforming the function so it returns itself

By transforming the function so it returns itself, you can use the syntax

func(p)(div)

To make this work, you'll need to arrange for func to return itself.

function selfify(fn) {
    return function self() {
        fn.apply(this, arguments);
        return self;
    };
}

Then

funcx = selfify(func);
funcx(p)(div);

Transforming the function so it is called on each argument

If you would prefer the func(p, div) syntax, write the following kind of transformer, which creates a function which calls an underlying function on each of its arguments:

function repeatify(fn) {
    return function() {
        Array.prototype.forEach.call(arguments, fn, this);
    };
}

Then

funcy = repeatify(func);
funcy(p, div);

This obviously won't work well if the underlying function takes two or more parameters.

In ES6, using rest parameters, the above can be written somewhat more simply as

function repeatify(fn) {
    return function(...args) {
        [...args].forEach(fn, this);
    };
}

Real simple solution

If all the above functional-style programming is too much to wrap your head around, all you really need to do is:

[p, div].forEach(func);

Upvotes: 2

Olga Filipova
Olga Filipova

Reputation: 1

Consider combining a basic loop from the previous answers and the use of classes instead of querySelector.

Thus you could assign the needed classed to all your element that you'll need to pass through the function and then just call the function with them:

var func = function (elem) {
    for (var i = 0; i < elem.length; i++) {
        elem[i].style.color = 'red';
    }
};

func(document.getElementsByClassName("yourClass"));

Upvotes: 0

Endless
Endless

Reputation: 37825

var forEach = Array.prototype.forEach;
var elms = document.querySelectorAll('p, div'); // css selector to match both p & div
var func = function(elem) {
    elem.style.color = 'red';
};

forEach.call(elms, func);

Upvotes: 0

STT
STT

Reputation: 668

You can make use of arguments:

var func = function() {
    var args = [].slice.apply(arguments);

    args.forEach(function (elem) {
        elem.style.color = 'red';
    });
};

Call it like you wanted:

func(p, div);

On a side note, there is a functionality called "rest parameter" planned in ECMAScript 6 that allows for just what you had in mind, take a look here.

Upvotes: 4

Abdul Jabbar
Abdul Jabbar

Reputation: 2573

The right way to do is through the use of classes.

<p class="myClass"></p>
<div class="myClass"></div>

Then in your javascript when you wish to change the color of these two elements, simply do:

var elems = document.getElementsByClassName("myClass");

for(var i=0; i<elems.length; i++){
    func(elem[i]);
}

It'll be useful for long run when you have large number of elements, organizing them in classes based on your needs is the way to go.

Upvotes: -1

Related Questions