动态宽度的元素的动态数量,直到两行被填充

时间:2017-06-13 12:28:26

标签: javascript jquery css knockout.js

我在页面底部显示多个div元素。

这些元素的数量及其宽度未知 - 这意味着我事先并不知道它们,因为它们是根据其他一些规则动态加载的。

我想要实现的是,只显示这些元素的两行,并且一旦另一个元素在第三行中断开,只需显示一些指示符,表示有更多元素可以展开。

我不想在那里有任何滚动条。

article

我正在使用jquery和knockout.js。

当屏幕尺寸发生变化时,应重新组织元素。

JS

// all the elements representing the divs
self.tags = ko.observableArray();
// disaplayed elements
self.tagsPreview = ko.observableArray()

HTML

<div id="tagsContainer">
    <!-- ko foreach: { data: tagsPreview, as: 'tag' } -->
        <div data-bind="text: tag.title" class="tag"></div>            
    <!-- /ko -->
</div>

CSS

#tagsContainer .tag {
    box-sizing: border-box;
    display: inline-block;     
    height: 30px;    
    margin-top: 4px;
    margin-right: 1px;
    padding: 5px;        
}

我不知道如何计算或找出应分配给tagsPreview observable的元素。有什么建议?我不认为这可以通过css来完成

1 个答案:

答案 0 :(得分:1)

只需使用flexbox进行布局,就可以到达中途。

显示溢出指标是计算有多少行的问题,也就是说这些项目中有多少个不同的值。

除了在setMoreTags中使用afterRender之外,您还需要将其设置为在容器调整大小时运行。

const names = ['one', 'two', 'three', 'four', 'five golden rings', 'six', 'seven', 'eight', 'nine', 'ten',
  'eleven', 'twelve', 'thirteen', 'fourteen', 'fifteen'
];
const vm = {
  // all the elements representing the divs
  tags: ko.observableArray([]),
  moreTags: ko.observable(false),
  setMoreTags: function () {
    // Count how many different tops there are among the tags
    // If more than two, moreTags is true
    const tags = document.querySelectorAll('#tagsContainer .tag');
    const tops = {};
    
    for (const t of tags) {
      tops[t.getBoundingClientRect().top] = true;
    }
    vm.moreTags(Object.keys(tops).length > 2);
  }
};

ko.applyBindings(vm);

const i = setInterval(() => {
  if (names.length) {
    vm.tags.push({
      title: names.shift()
    });
  } else {
    clearInterval(i);
  }
}, 500);
#tagsContainer {
  background-color: #eee;
  display: flex;
  flex-flow: row wrap;
  max-height: 68px;
  overflow: hidden;
  position: relative;
  width: 300px;
}

#tagsContainer .tag {
  border: thin solid blue;
  box-sizing: border-box;
  height: 30px;
  margin-top: 4px;
  margin-right: 1px;
  padding: 5px;
}

#tagsContainer .more-indicator {
  background-color: red;
  color: white;
  font-size: 18px;
  position: absolute;
  bottom: 0;
  right: 0;
  padding: 5px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<div id="tagsContainer">
  <!-- ko foreach: { data: tags, as: 'tag', afterRender: setMoreTags } -->
  <div data-bind="text: tag.title" class="tag"></div>
  <!-- /ko -->
  <!-- ko if: moreTags -->
  <div class="more-indicator">...</div>
  <!-- /ko -->
</div>