Turcia
Turcia

Reputation: 711

Adding .class to <li> elements according to their width, but their width also changes after adding .class

You can see the problem on http://jsfiddle.net/6gnAF/1/

I've little problem with my list elements.

I'm using very simple unordered list like;

<div>
  <ul>
    <li class='button'>Element 1</li>
    ...
    <li class='button'>Element N</li>
  </ul>
</div>

(Number of list elements, N, varies on every page.)

The div which contains the ul is 696 px width. List elements, li, are horizontally aligned, and when they reach end of div's width, they contiues on new line.

What I wanted to adding class .left the first li of every line, and class .right to the last one.

    $('li').each(function() {
        var liWidthOut = $(this).width();
        totalWidth += liWidthOut;
        if (totalWidth >= divWidth) {
            $(this).addClass("left");
            $(this).prev().removeClass("middle").addClass("right");
            totalWidth = liWidthOut;
        }
        else {
            $(this).addClass("middle");
        }
     });

I managed that with Jquery, but I've a little problem.

You can see the problem on http://jsfiddle.net/6gnAF/1/

The problem is, .left and .right classes change the width of li elements which are added to, so some times they create new lines, and last li elements become first one which have .right class, instead of .left.

How can I fix this?

(Sorry for the grammatically errors)

Upvotes: 3

Views: 282

Answers (3)

Your code is mostly right, just two nitpicks which made it go wrong:

  1. Use var liWidthOut = this.offsetWidth; instead of var liWidthOut = $(this).width(); as the later is giving you the width of the inner text, instead of also adding the padding, as offsetWidth does.

  2. Apply the .button class before starting looping and calculating widths, as the .button style will affect the elements width, you have to apply it in the first place so your calculations don't fail later.

See working demo of your code with those two things corrected.

Upvotes: 4

Jan
Jan

Reputation: 5815

I changed the method to tracking the top position instead of calculating widths, seems to work ok. Using width() with paddings and borders and whatnot is less than reliable.

$('li')
    // Add classes first, so we calculate on the right styles
    .addClass("middle")
    .addClass("button")
    .each(function() {
        // Compare with last position
        if (lastPos != $(this).position().top) {
            $(this).removeClass("middle").addClass("left")
                .prev().removeClass("middle").addClass("right");
        }
        // Store last position
        lastPos = $(this).position().top;
    });

http://jsfiddle.net/2qydM/6/

Upvotes: 5

Ian Jamieson
Ian Jamieson

Reputation: 4816

Would it be possible to separate these lists into seperate lists?

If so you could use :nth-child or :last-child

Upvotes: 0

Related Questions