Можете ли вы упростить и обобщить эту полезную функцию jQuery, пожалуйста? - PullRequest
1 голос
/ 15 апреля 2010

Я делаю интернет-магазин с товарами, отображаемыми в виде «плиток» в сетке, как обычно. Я просто хочу использовать плитки разного размера и убедиться, что (через jQuery) нет свободных мест.

В базовой ситуации у меня есть оболочка размером 960 пикселей, и я хочу использовать плитки размером 240x180 пикселей (класс .grid_4) и 480x360 пикселей (класс .grid_8). См. Изображение (представьте, что нет полей / отступов):

альтернативный текст http://img580.imageshack.us/img580/2828/screenshot2010041508h52.png

Проблемы без jQuery:

  • когда CMS предоставляет большую плитку как 6-ю, под 5-ой будет свободное пространство
  • когда CMS предоставляет большой тайл как 7-й, будет свободное пространство под 5-м и 6-м
  • когда CMS предоставляет большой тайл как 8-й, он перемещается на следующую строку, оставляя позицию № 8 свободной

Мое решение пока выглядит так:

$(".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;

        }

    }); 

Из комментариев должно быть очевидно, как это работает - обычно всегда следит за тем, чтобы большая плитка находилась в нечетном положении (количество предшествующих маленьких плиток является четным), сдвигая одну позицию назад, если это необходимо. Также маленькие плитки слева от большого нужно обернуть в другой элемент div, чтобы они отображались в столбце, а не в строке.

Теперь наконец вопросы:

  • как обобщить функцию, чтобы я мог использовать еще больше размеров плитки, таких как 720x360 (3x2), 480x540 (2x3) и т. Д .?
  • есть ли способ упростить функцию?
  • Мне нужно убедиться, что большие плитки учитываются как кратные маленьких плиток при проверке фактической позиции. Поскольку использование index () для плитки в позиции 12 (последняя плитка в 3-м ряду) теперь вернет 7 (позицию 8), потому что плитки в позициях 5 и 9 обернуты вместе в один столбец, а большая плитка также является просто одним div, но охватывает 2х2 позиции. Есть ли какой-нибудь чистый способ обеспечить это?

Большое спасибо за любые подсказки. Не стесняйтесь повторно использовать код, я думаю, что он может быть полезен.

Йозеф

Ответы [ 2 ]

3 голосов
/ 15 апреля 2010

Похоже, вам нужно использовать плагин jQuery, называемый masonry.

Вы можете найти его здесь

0 голосов
/ 09 ноября 2012

Это достаточно упрощенно для вас?

$(".grid_8")
.each(function () {
switch (($(this)
    .index() + 1) % 4) {
    case 1:
        break;
    case 2:
        $(this)
            .insertAfter($(this)
            .next()), $(this)
            .prevAll(":nth(0), :nth(1)")
            .wrapAll('<div class="grid_4" />');
        break;
    case 3:
        $(this)
            .prevAll(":nth(0), :nth(1)")
            .wrapAll('<div class="grid_4" />'), $(this)
            .nextAll(":nth(0), :nth(1)")
            .wrapAll('<div class="grid_4" />'), $(this)
            .insertAfter($(this)
            .next());
        break;
    case 0:
        $(this)
            .insertAfter($(this)
            .next())
}
})
...