Martin Velchevski
Martin Velchevski

Reputation: 904

Set dynamic css width to children of a container using jQuery

I am trying to set the width of a number of child elements dynamically using jQuery. What I am trying to do is the following

  1. Get the count of the desired containers (as I'll be having multiple instances of the .steps-container class in the DOM)
  2. Iterate through their children
  3. Set the width of their children by applying the following formula: width = 100 / number of children

I have this:

$(document).ready(function() {

    var setStepsWidth = function(stepsContainer) {

        var el = stepsContainer,
            count = stepsContainer.length,
            childrenCount = 0;

        for( var i = 0; i < count; i++ ) {

            childrenCount = el[i].children.length;

            var containerChildren = el[i].children;
            console.log(containerChildren);


            for(var j = 0; j < childrenCount; j++) {

                //test to see if it's working
                childrenCount[j].css('background-color', 'red');

            }


        }
    };

    setStepsWidth($('.steps-container'));

});

The code returns an error: "Uncaught TypeError: Cannot read property 'css' of undefined "

What am I missing?

Upvotes: 3

Views: 1077

Answers (2)

Roamer-1888
Roamer-1888

Reputation: 19288

You are making heavy weather of something very simple.

  • to iterate over the containers, use jQuery's .each()
  • to set the child widths, exploit on jQuery's inate ability to operate on all elements in a collection, without writing the iteration yourself.
$(document).ready(function() {
    function setStepsWidth($containers) {
        $containers.each(function(i, el) {//iterate through the containers
            var $children = $(el).children();//find steps in current iteration's container.
            $children.width(100 / $children.length);//calculate width and apply it to all steps in current iteration's container.
        });
    }
    setStepsWidth($('.steps-container'));
});

Alternatively, if the steps are dynamic, you might choose to attach a 'setStepsWidth' event handller that can be fired whenever a step is added or removed.

For example :

$(document).ready(function() {
    $(document).on('setStepsWidth', '.steps-container', function() {
        var $children = $(this).children();
        $children.width(100 / $children.length);
    });
});

DEMO

Upvotes: 2

Lawrence Johnson
Lawrence Johnson

Reputation: 4043

The children property is incorrect. The children are retrieved via function "children()". See below:

$(document).ready(function() {
var setStepsWidth = function(stepsContainer) {

    var el = stepsContainer,
        count = stepsContainer.length,
        childrenCount = 0;

    for( var i = 0; i < count; i++ ) {

        childrenCount = el[i].children().length;

        var containerChildren = el[i].children();
        console.log(containerChildren);


        for(var j = 0; j < childrenCount; j++) {

            //test to see if it's working
            childrenCount[j].css('background-color', 'red');

        }


    }
};

setStepsWidth($('.steps-container'));

});

Alternatively, you may want to consider writing it like this as opposed to using array elements. Not sure if this is a performance gain or decrease, but it's how I'd write it:

jQuery(document).ready(function() {
    function _stepsWidth(__stepsContainer) {
        jQuery.each(__stepsContainer.children(), function() {
            jQuery(this).css('background-color', 'red');
        });
    }
    _stepsWidth(jQuery('.steps-container'));
});

If you want recursion (not sure if that's what you're after), this is what you want:

jQuery(document).ready(function() {
    function _stepsWidth(__stepsContainer) {
        jQuery.each(__stepsContainer.children(), function() {
            jQuery(this).css('background-color', 'red');
            _stepsWidth(jQuery(this));
        });
    }
    _stepsWidth(jQuery('.steps-container'));
});

I also just realized that you're not using a single container, so if your width commands are specific to each container, you'd want to do this:

jQuery(document).ready(function() {
    function _stepsWidth(__stepsContainer) {
        jQuery.each(__stepsContainer.children(), function() {
            jQuery(this).css('background-color', 'red');
        });
    }
    jQuery.each(jQuery('.steps-container'), function() {
        _stepsWidth(jQuery(this));
    });
});

Try it. :)

Upvotes: 2

Related Questions