4

Consider the following example which should color every second row: (live demo here)

JS:

$(function() {
    var wrapper = $("<div></div>")

    for (i = 0; i < 100; i++) {
        wrapper.append("<span></span>");
    }

    $("body").append(wrapper);

    color_rows();
});

function color_rows() {
    $("span").each(function(i) {
        if (i % 10 >= 5) {
            $(this).css("background-color", "red");
        }
    });
}

CSS:

div {
    width: 450px;
    height: 400px;
    background-color: #ccc;
    overflow: auto;
}
span {
    display: inline-block;
    width: 50px;
    height: 50px;
    background-color: #777;
    margin: 0 30px 30px 0;
}

The output is:

enter image description here

As you can see, color_rows() function assumes that there are 5 elements per row. If, for example, I change the width of the div to be 350px, the color_rows() function will not work properly (i.e. will not color every second row).

How could I fix color_rows() so that it will work for every width of the div ?

Misha Moroshko
  • 166,356
  • 226
  • 505
  • 746
  • Should tr:nth-child(odd) not work here? EDIT: Ah! I assumed there was a table! – Jawad Jul 19 '11 at 06:11
  • It doesn't matter whether it's a table or not. CSS3 nth-child works on any element, but it's not supported by Internet Explorer. – Jezen Thomas Apr 23 '12 at 06:28

6 Answers6

4

this is my solution:

this works based on the top offset of each element and by comparing the it to the top offset of last element in the loop it detects if new row is seen or not, and then based on the number of row colors rows.

function color_rows() {
    var lastTop = -1;
    var rowCount = 0;
    $("span").each(function(i) {
        var top = $(this).position().top;
        if (top != lastTop) {
            rowCount++;
            lastTop = top;
        }
        if(rowCount % 2 == 0)
        {
            $(this).css("background-color", "red");
        }
    });
}

jsFiddle: http://jsfiddle.net/Ug6wD/4/

Mo Valipour
  • 13,286
  • 12
  • 61
  • 87
  • +1 this is kinda how I'd have done it too - the browser will know when it has moved elements to the next line, so ask it! – Alnitak Jul 19 '11 at 06:38
  • Nice! you could just compare `$(this).position().top` with `$(this).prev().position().top` – Salman A Jul 19 '11 at 06:58
  • @Salman it's more efficient to just remember it each pass through the loop - your way makes five jQuery calls vs the original's two. – Alnitak Jul 19 '11 at 07:14
2

Look at my fixes http://jsfiddle.net/Ug6wD/5/

I am getting Container width, itemWidth + margin. And calculating how many items per row. Get margin-right from span item.

Then minus 20 to the container width, coz of overflow scrollbar.

function color_rows() {
var containerWidth = $('div').width()-20;
var itemWidth = $('span:first').width() + parseInt($('span:first').css('margin-right'));
var itemsPerRow = parseInt(containerWidth / itemWidth);

$("span").each(function(i) {
    if (i % (itemsPerRow *2) >= itemsPerRow ) {
        $(this).css("background-color", "red");
    }
});

} UPDATE with dynamic margin-right value from CSS AND Right scrollbar fix causing breakage : http://jsfiddle.net/Ug6wD/5/

Marc Uberstein
  • 12,501
  • 3
  • 44
  • 72
0

There is a simpler way:

$('tr:even').css("background-color", "red");
dingo_d
  • 11,160
  • 11
  • 73
  • 132
akallali
  • 29
  • 5
0

Edit: This only works on some div-widths.. -.- Nevermind, then..

This should do it:

function color_rows() {
    var divW = $('div').width();
    var spanW = $('span').outerWidth(true);   //Get margin too
    var cnt = parseInt(divW/spanW, 10);   //Remove decimals
    $("span").each(function(i) {
        if (i % (cnt*2) >= cnt) {
            $(this).css("background-color", "red");
        }
    });
}
Thor Jacobsen
  • 8,621
  • 2
  • 27
  • 26
  • This wont work correct coz you have forgotten about the '% 10'. The ten value should be itemsPerRow * 2, 10 will only work for itemsPerRow = 5. ;) [and the margin value] – Marc Uberstein Jul 19 '11 at 06:22
0

fiddle: http://jsfiddle.net/gn5QW/1/

html

<div id="container">
    <div class="box"></div>
    <div class="box"></div>
    <div class="box"></div>
    <div class="box"></div>
</div>

js

$(document).ready(function(){
    var box = $(".box");
    var con = $("#container");
    var box_per_line = Math.floor(parseInt($("#container").width())/ (parseInt( $(".box").width()) +10*2/*px*/));
    var style = "black";
    $(".box").each(function(i){
        if(i % box_per_line == 0){ style = (style == "black") ? "grey" : "black"; }
        $(this).css("background-color",style);
    });
});

css

.box {
    width: 100px;
    height: 100px;
    float: left;
    margin: 10px;
}

#conainer {
    background-color: grey;
    display: inline-block;
}
Ilia Choly
  • 18,070
  • 14
  • 92
  • 160
0

I've fixed your code, but please PLEASE don't do this. The internet the in pain,

$(function() {
    var wrapper = $("<div></div>")

    for (i = 0; i < 100; i++) {
        wrapper.append("<span></span>");
    }

    $("body").append(wrapper);

    color_rows();
});

function color_rows() {
        var rowWidth = Number( $('div:first').css('width').slice(0,-2) );
        var itemWidth = Number( $('span:first').css('width').slice(0,-2) ) + Number( $('span:first').css('margin-right').slice(0,-2) );
        var perRow =  Math.floor( rowWidth/itemWidth );

    $("span").each(function(i) {
        if (i % 10 >= perRow ) {
            $(this).css("background-color", "red");
        }
    });
}
Sinetheta
  • 9,189
  • 5
  • 31
  • 52