27

Is there a way to find number of items (li tag) inside a ul which has it's float: set to left. Assume i got loads of folders which are visually represented by li tags. Due to floating behavior as soon as the li does not fit in single row they will be pushed down giving it Rows and columns look.my questions is

Using jQuery ..etc Is there a way to determine the number of li for each row

Code

<ul>
 <li>A</li>
 <li>B</li>
 <li>C</li>
 <li>D</li>
 <li>E</li>
 <li>F</li>
 <li>G</li>
 <li>H</li>
 <li>I</li>
 <li>J</li>
</ul>

Style

ul,li{margin:0 0;padding:0 0;}
ul li{display:inline;float:left}

For my resolution li's upto F makes one row and the rest makes another like below. I would like a jquery way to get number of elements ( which is 6 in my case ) in row 1.

A B C D E F
G H I J

Context

I am adding keyboard events to navigate to each folder(li) using left,right,top,down. Left right is as simple as highlighting next and previous li's. Top and down keys need to go to next row and above row. Now you will get it :)

Deeptechtons
  • 10,945
  • 27
  • 96
  • 178
  • 1
    did you try `$("ul li").length`? – Furqan Hameedi Jul 18 '12 at 10:18
  • 1
    This could be tricky as you are relying on a browser layout engine to produce the layout logic you require - I would suggest adopting a different method. Doing this with jQuery could be very tricky indeed as the standard jQuery DOM functions will look *at the markup* rather than the layout. You could do something with .position but I would recommend rethinking your strategy (from what I undestand of it) – El Ronnoco Jul 18 '12 at 10:19
  • 2
    @Furqan i clearly mentioned **number of li in per row** not the whole ul – Deeptechtons Jul 18 '12 at 10:20
  • @ElRonnoco May be the edited question will clear of any doubts :) – Deeptechtons Jul 18 '12 at 10:25
  • Interesting! Are li's of fixed width? in that case you can calculate the number of li's per row by dividing the width of ul with with of li. This way you can determine how many li's will appear in a single row. You can also take $("li").lenght and use it to determine how many li's are in the last row i.e. total_li%li_per_row – U.P Jul 18 '12 at 10:31

7 Answers7

47

We can do this by checking the number of LIs with their top (y-axis) positions matching that of their previous siblings.

Demo: http://jsfiddle.net/KgBpx/1/

Updated demo: http://jsfiddle.net/KgBpx/2/

Note: recalculation done on window resize as well to fully demonstrate the logic.

Code:

function calculateLIsInRow() {
    var lisInRow = 0;
    $('ul li').each(function() {
        if($(this).prev().length > 0) {
            if($(this).position().top != $(this).prev().position().top) return false;
            lisInRow++;
        }
        else {
            lisInRow++;   
        }
    });
    console.log('No: of lis in a row = ' + lisInRow);
}

calculateLIsInRow();

$(window).resize(calculateLIsInRow);

NOTE

The count of LIs will be same for all rows except maybe the last if the total number of LIs is not a multiple of lisInRow. The number of LIs in the last row can easily be found out by doing: $('ul li').length % lisInRow

isherwood
  • 58,414
  • 16
  • 114
  • 157
techfoobar
  • 65,616
  • 14
  • 114
  • 135
3

Using filter() makes for smaller amount of code.

function filterByTop(top) {
  return function(i) { return $(this).offset().top == top; };
}
var el = $('li:first');
var rowSz = $('li').filter(filterByTop(el.offset().top)).length;
stt
  • 342
  • 2
  • 7
0

You can use the following function to get an array which will have the number of Li items per each row. If you want only the li items with float left, you can easily add that condition.

function computeItemsPerRow() {
        var itemsInRows = new Array();

        var countLi = $('ul li');
        var rowWidth = $('#rowContainer').width(); // TODO: Replace with the proper row container selector.
        var curRowWidth = 0;
        var itemsInCurRow = 0;

        for (var i = 0; i < countLi; i++) {
            var itemWidth = $('li:eq(' + i + ')').width();
            if (curRowWidth + itemWidth > rowWidth || i == countLi - 1) {

                itemsInRows[itemsInRows.length] = itemsInCurRow;
                itemsInCurRow = 1;
                curRowWidth = itemWidth;
            }
            else {
                itemsInCurRow++;
                curRowWidth = curRowWidth + itemWidth;
            }
        }

        return itemsInRows;

    }
dotcoder
  • 2,828
  • 10
  • 34
  • 50
0

You can do it by top position:

var arr = [];

$('ul li').each(function(i){
    arr[i] = $(this).position().top;
});

Then you count matching values in resulting array - How to count Matching values in Array of Javascript

Community
  • 1
  • 1
Jānis
  • 328
  • 2
  • 5
0

Try this (really out of it, might need some debugging)

var numberPerRow = [];
var offsets =      [];
$("li").each(function(){
    var thisOffset = $(this).offset().top; 
    var index = $.inArray(thisOffset, offsets);
    if(index >=0){
        numberPerRow[index]++;
    }else{
        offsets.push(thisOffset);
        numberPerRow.push(1);
    }
});

Update

To get the highest row-value in an array, you can use something this:

console.log( Math.max.apply(null, numberPerRow) );
yckart
  • 32,460
  • 9
  • 122
  • 129
vvMINOvv
  • 1,768
  • 4
  • 22
  • 45
  • @yckart I tested it and it works. but why does it work... apply (as far as I know) just calls that function in this case `Math.max`, and the first parameter is the scope, so you pass in `Math` but I don't see any looping mechanism here :s . please explain your wizardry :D – vvMINOvv Jun 18 '13 at 12:50
  • @wMINOw This function uses apply to find the maximum element in a numeric array. `getMaxOfArray([1,2,3])` is equivalent to `Math.max(1, 2, 3)`, but you can use `getMaxOfArray` on programmatically constructed arrays of any size. Clever usage of apply allows you to use built-ins functions for some tasks that otherwise probably would have been written by looping over the array values. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply#apply_and_built-in_functions – yckart Jun 18 '13 at 14:32
0
var rows = 0;
$('li').each(function() {
    var $this = $(this);
    var $prev = $this.prev();
    if ($prev.length && $this.position().top === $prev.position().top) rows++;
});

console.log(rows);
yckart
  • 32,460
  • 9
  • 122
  • 129
0

An small update of @techfoobar script:

You can hide last row when its items count is different of the common items count

http://jsfiddle.net/cavico/KgBpx/222/

if(lisInLastRow != lisInRow) {
    $('ul li').slice( -lisInLastRow ).hide();
}