当网格底部有空格时,Bootstrap + Masonry会添加空白div

时间:2015-10-15 06:55:44

标签: javascript jquery html css twitter-bootstrap

我使用砌砖+自举,并注意到当我有一个3列网格然后我有10个项目时,它会显示一个3x4网格,底部有2个空格。我怎么能在底部自动添加2个空div来填充它而没有那些空格?所以总div将变为12,其中2个div只是空白?

这不应该固定为3列,但每当检测到有N个空div可以填满时,应该动态添加空div。应适用于装载和调整大小。

.item尺寸没有问题,因为它们都具有相同的宽度和高度(方框/方形)

我制作了jsFiddle,现在可以在最后一行的空白处添加填充符。这也是通过使用layoutComplete事件来处理on resize。但问题是,每当我调整大小时,它都会不断添加新的填充物。

尝试重新调整大小以适应不同尺寸,并且您会注意到它会继续添加填充物。

以防这里也是代码。

HTML

<input type="hidden" name="hfTotalGridItems" id="hfTotalGridItems" value="10" />
<div class="grid">
    <div class="item">
        <div>lorem</div>
    </div>
    <div class="item">
        <div>lorem</div>
    </div>
    <div class="item">
        <div>lorem</div>
    </div>
    <div class="item">
        <div>lorem</div>
    </div>
    <div class="item">
        <div>lorem</div>
    </div>
    <div class="item">
        <div>lorem</div>
    </div>
    <div class="item">
        <div>lorem</div>
    </div>
    <div class="item">
        <div>lorem</div>
    </div>
    <div class="item">
        <div>lorem</div>
    </div>
    <div class="item">
        <div>lorem</div>
    </div>
</div>
<div class="result"></div>

CSS

.grid {
    margin: 0 auto;
}
.item {
    margin-bottom: 20px;
    border: 1px solid red;
    height: 80px;
    width: 80px;        
}
.filler {
    background-color: #999;
    border: 1px solid blue;
}

JQuery的

$(function () {
    function calculateRows() {
        var lisInRow = 0;
        var $item = $('.grid .item');
        var $grid = $('.grid');
        var itemWidth = $('.grid .item').width();
        var itemHeight = $('.grid .item').height();

        $item.each(function () {
            if ($(this).prev().length > 0) {
                if ($(this).position().top != $(this).prev().position().top) return false;
                lisInRow++;
            } else {
                lisInRow++;
            }
        });

        var lisInLastRow = $item.length % lisInRow;
        if (lisInLastRow == 0) lisInLastRow = lisInRow;

        $('.result').html('No: of lis in a row = ' + lisInRow + '<br>' + 'No: of lis in last row = ' + lisInLastRow);

        if (lisInLastRow < lisInRow) {
            var $clonedItem = $('.grid .item:last-child').clone().empty().css({
                width: itemWidth,
                height: itemHeight
            }).addClass('filler');
            $grid.append($clonedItem).masonry('appended', $clonedItem);

        } else {
            if (newTotal > $('#hfTotalGridItems').val()) {
                $grid.masonry('remove', $('.grid .item.filler'));
                $grid.masonry();
            }
        }
    }

    var $grid = $('.grid');

    $grid.masonry({
        itemSelector: '.item',
        isFitWidth: true,
        gutter: 20
    });

    $grid.masonry('on', 'layoutComplete', function (event) {
        calculateRows(event.length);
    });

    $grid.masonry();
});

2 个答案:

答案 0 :(得分:5)

您需要检查两件事

  1. 如果原始方框的数量可以被第一行(originalBoxs % lisInRow === 0)中的方框数整除。
  2. 如果框数大于允许的最大框数。您可以计算允许的最大框,如下所示

    var totalAllowed = lisInRow;
    while (totalAllowed < originalBoxs) {
       totalAllowed += lisInRow;
    }
    
  3. 如果这是真的,那么你应该删除所有多余的盒子。否则添加填充框。这是更新的jsFiddle

    我在下面添加了更新的jQuery代码

    $(function () {
    
        // remember the original box lenth. 
        var $item = $('.grid .item');
        var originalBoxs = $item.length;
    
        function calculateRows() {
    
            var lisInRow = 0;
            var $item = $('.grid .item');
            var $grid = $('.grid');
            var itemWidth = $('.grid .item').width();
            var itemHeight = $('.grid .item').height();
    
            // calculate how many boxes are in the first row. 
            $item.each(function () {
                if ($(this).prev().length > 0) {
                    if ($(this).position().top != $(this).prev().position().top) return false;
                    lisInRow++;
                } else {
                    lisInRow++;
                }
            });
    
            // calculate how many boxes are in the last row. 
            var lisInLastRow = $item.length % lisInRow;
    
            $('.result').html('No: of lis in a row = ' + lisInRow + '<br>' + 'No: of lis in last row = ' + lisInLastRow);
    
            // the total allowed boxes on the page. 
            var totalAllowed = lisInRow;
            while (totalAllowed < originalBoxs) {
                totalAllowed += lisInRow;
            }
    
            if (($item.length > originalBoxs && originalBoxs % lisInRow === 0) || ($item.length > totalAllowed)) {
                // if the number of original boxes evenly divides into the number of boxes in a row.
                // or the number of boxes on the page is past the max allowed. 
                // remove any filler boxes. 
                var boxesToDelete = $('.grid .item.filler');
                var deleteBoxes = $item.length - totalAllowed;
                for (var i = 0; i < deleteBoxes; i++) {
                    // delete unnesecary boxes. 
                    $grid.masonry('remove', boxesToDelete[boxesToDelete.length - i - 1]);
                }
            } else if (lisInLastRow !== 0) {
                // if the last row does not equal 0 and the number of boxes is less then the original + the first row
                // then fill it in with new boxes. 
                var $clonedItem = $('.grid .item:last-child').clone().empty().css({
                    width: itemWidth,
                    height: itemHeight
                }).addClass('filler');
                $grid.append($clonedItem).masonry('appended', $clonedItem);    
            }
    
        }
    
        var $grid = $('.grid');
    
        $grid.masonry({
            itemSelector: '.item',
            isFitWidth: true,
            gutter: 20
        });
    
        $grid.masonry('on', 'layoutComplete', function (event) {
            calculateRows(event.length);
        });
    
        $grid.masonry();
    });
    

答案 1 :(得分:3)

这是一个有点不同的版本。请检查传统的JSFiddle进行测试。

简而言之,我采取了非侵入式修改的方式,以最佳的方式实现预期的行为。

$(function() {

  var fillerHtml = '<div></div>',
    fillerClassName = 'filler',
    initialItemCount = null;

  function toggleFillers() {
    var masonry = $grid.data('masonry'),
      currentItemCount = masonry.items.length,
      items = masonry.items,
      cols = masonry.cols,
      expectedItemCount = 0,
      lastRowItemCount = 0,
      lastRowFillerCount = 0,
      fillersToRemove = [],
      fillersToAddCount = 0,
      fillersToAdd = [];

    if (initialItemCount === null) {
      initialItemCount = currentItemCount;
    }

    lastRowItemCount = initialItemCount % cols;
    lastRowFillerCount = (lastRowItemCount !== 0) ? cols - lastRowItemCount : 0;
    expectedItemCount = initialItemCount + lastRowFillerCount;
    
    $('.result').html('No: of lis in a row = ' + cols + '<br>' + 'No: of lis in last row = ' + lastRowItemCount);

    if (expectedItemCount !== currentItemCount) {
      if (currentItemCount > expectedItemCount) {
        var itemsToRemove = items.slice(initialItemCount + lastRowFillerCount);

        $.each(itemsToRemove, function(index, item) {
          fillersToRemove.push(item.element);
        });

        masonry.remove(fillersToRemove);
        masonry.layout();
      } else {
        fillersToAddCount = expectedItemCount - currentItemCount;
        fillerClassName = masonry.options.itemSelector.replace('.', '') + ' ' + fillerClassName;

        while (fillersToAddCount) {
          $el = $(fillerHtml).addClass(fillerClassName);
          $grid.append($el);
          fillersToAddCount = fillersToAddCount - 1;
        }

        masonry.reloadItems();
        masonry.layout();
      }
    }
  }

  var $grid = $('.grid');

  $grid.masonry({
    itemSelector: '.item',
    isFitWidth: true,
    gutter: 20
  });
  $grid.masonry('on', 'layoutComplete', toggleFillers);
  $grid.masonry('layout');
});
.grid {
  margin: 0 auto;
}
.item,
.filler {
  margin-bottom: 20px;
  border: 1px solid red;
  height: 80px;
  width: 80px;
}
.filler {
  background-color: #999;
  border: 1px solid blue;
}
<script type="text/javascript" src="//code.jquery.com/jquery-2.1.3.js"></script>
<link rel="stylesheet" type="text/css" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
<script type="text/javascript" src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
<script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/masonry/3.3.2/masonry.pkgd.min.js"></script>
<input type="hidden" name="hfTotalGridItems" id="hfTotalGridItems" value="10" />

<div class="grid">
  <div class="item">
    <div>lorem</div>
  </div>
  <div class="item">
    <div>lorem</div>
  </div>
  <div class="item">
    <div>lorem</div>
  </div>
  <div class="item">
    <div>lorem</div>
  </div>
  <div class="item">
    <div>lorem</div>
  </div>
  <div class="item">
    <div>lorem</div>
  </div>
  <div class="item">
    <div>lorem</div>
  </div>
  <div class="item">
    <div>lorem</div>
  </div>
  <div class="item">
    <div>lorem</div>
  </div>
  <div class="item">
    <div>lorem</div>
  </div>
</div>
<div class="result"></div>

我已经和Masonry玩了一段时间,所以我决定将它打包为插件,如果你需要玩具在别处使用它。

您可以使用bower安装它,或者只是从GitHub

获取源代码
bower install jquery-masonry-autofill

以下是带插件的演示的JSFiddle