jQuery Find number of items per row in floated li's
Asked Answered
T

7

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 :)

Thinner answered 18/7, 2012 at 10:16 Comment(5)
did you try $("ul li").length?Cacciatore
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)Excurvate
@Furqan i clearly mentioned number of li in per row not the whole ulThinner
@ElRonnoco May be the edited question will clear of any doubts :)Thinner
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_rowStrangeness
O
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

Overblouse answered 18/7, 2012 at 10:40 Comment(7)
i see no way to do this for subsequent rows. Only the first rowThinner
The count will be same for all rows except maybe the last. Number of LIs in the last row can easily be found out by doing: $('ul li').length % lisInRowOverblouse
He's got you there :) This is a very elegant solutionSimplicidentate
Updated the demo above to show the number of LIs in last row as well.Overblouse
Updated your JSFiddle to allow for rows with different numbers of elements (i.e. non-uniform sizes). Try hovering over elements here: jsfiddle.net/KgBpx/107Theocritus
Just curious if anyone would know how to detect when the number of rows has changed during a window resize? Thanks for this awesome solution!Whittaker
When we resize the window or zoom out why the results becomes 0Harilda
U
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;
Uncanonical answered 27/7, 2015 at 1:53 Comment(0)
S
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;

    }
Stibine answered 18/7, 2012 at 10:36 Comment(1)
I think you'd need to take margin into account too.Simplicidentate
B
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

Busra answered 18/7, 2012 at 10:37 Comment(0)
C
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) );
Clave answered 18/7, 2012 at 10:40 Comment(2)
@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 :DClave
@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. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…Krumm
K
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);
Krumm answered 16/6, 2013 at 17:1 Comment(0)
D
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();
}
Disintegration answered 3/6, 2014 at 14:41 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.