can you simlify and generalize this useful jQuery function?

Posted by user199368 on Stack Overflow See other posts from Stack Overflow or by user199368
Published on 2010-04-15T07:20:58Z Indexed on 2010/04/15 7:23 UTC
Read the original article Hit count: 323

Hi,

I'm doing an eshop with goods displayed as "tiles" in grid as usual. I just want to use various sizes of tiles and make sure (via jQuery) there are no free spaces.

In basic situation, I have a 960px wrapper and want to use 240x180px (class .grid_4) tiles and 480x360px (class .grid_8) tiles. See image (imagine no margins/paddings there):

alt text

Problems without jQuery: - when the CMS provides the big tile as 6th, there would be a free space under the 5th one - when the CMS provides the big tile as 7th, there would be a free space under 5th and 6th - when the CMS provides the big tile as 8th, it would shift to next line, leaving position no.8 free

My solution so far looks like this:

$(".grid_8").each(function(){
        //console.log("BIG on position "+($(this).index()+1)+" which is "+(($(this).index()+1)%2?"ODD":"EVEN"));

        switch (($(this).index()+1)%4) {

            case 1:
                // nothing needed
                //console.log("case 1");
                break;

            case 2:
                //need to shift one position and wrap into 240px div
                //console.log("case 2");
                $(this).insertAfter($(this).next()); //swaps this with next
                $(this).prevAll(":nth(0), :nth(1)").wrapAll("<div class=\"grid_4\" />");

                break;

            case 3:
                //need to shift two positions and wrap into 480px div
                //console.log("case 3");
                $(this).prevAll(":nth(0), :nth(1)").wrapAll("<div class=\"grid_4\" />"); //wraps previous two - forcing them into column 
                $(this).nextAll(":nth(0), :nth(1)").wrapAll("<div class=\"grid_4\" />"); //wraps next two - forcing them into column
                $(this).insertAfter($(this).next()); //moves behind the second column
                break;

            case 0:
                //need to shift one position
                //console.log("case 4");
                $(this).insertAfter($(this).next());
                //console.log("shifted to next line");
                break;

        }

    }); 

It should be obvious from the comments how it works - generally always makes sure that the big tile is on odd position (count of preceding small tiles is even) by shifting one position back if needed. Also small tiles to the left from the big one need to be wrapped in another div so that they appear in column rather than row.

Now finally the questions:

  • how to generalize the function so that I can use even more tile dimensions like 720x360 (3x2), 480x540 (2x3), etc.?
  • is there a way to simplify the function?
  • I need to make sure that big tile counts as a multiple of small tiles when checking the actual position. Because using index() on the tile on position 12 (last tile in 3rd row) would now return 7 (position 8) because tiles on positions 5 and 9 are wrapped together in one culumn and the big tile is also just a single div, but spans 2x2 positions. any clean way to ensure this?

Thank you very much for any hints. Feel free to reuse the code, I think it can be useful.

Josef

© Stack Overflow or respective owner

Related posts about jQuery

Related posts about JavaScript