Marionette - 用空数据填充集合大小的集合
Marionette - populating a set size collection with empty data
我正在尝试填充一组列表,仅使用指定数量的元素来指定需要将它们添加到哪一行。
示例:
每个节点项都有一个对应于特定 UL 的编号以及要添加到的位置,但是元素的 "total" 数量是已知的。
简化示例数据(假设pre-determined数组大小为5):
nodes = new Entities.NodeCollection([
{ listID: 1, position: 2, name: "node2" },
{ listID: 1, position: 5, name: "node5" },
{ listID: 2, position: 4, name: "node4" }
]);
预期输出:
每个节点都插入到正确的位置,其余位置填充空 LI。
<ul id="list1">
<li></li>
<li><div class="template-class" id="node2"></div></li>
<li></li>
<li></li>
<li><div class="template-class" id="node5"></div></li>
</ul>
<ul id="list2">
<li></li>
<li></li>
<li></li>
<li><div class="template-class" id="node4"></div></li>
<li></li>
</ul>
预期输出:
如何创建一个模板,让我可以将数据插入正确的位置并 auto-fills 缺失的部分?
我可以用 jQuery 轻松做到这一点,(pre-fill 正确的长度和 select child #)但我需要使用 Marionette/Backbone,构建应用程序的事件管理和数据库查询端。
最坏的情况,能够循环遍历已知的元素数量并检查是否有应该去那里的数据点,必要时填写正确的 html(或空的),但是看起来不像是常见的 Marionette/Backbone 范例。
我想我的实际行模板是正确的;
<script type="text/template" id="node-list-item">
<div class="template-class" id="<%- name %></div>
</script>
和观点:
RowView = Backbone.Marionette.ItemView.extend({
tagName: "li",
template: "#node-list-item"
//something goes here to correctly handle empty pieces?
});
ListView = Backbone.Marionette.CompositeView.extend({
itemView: RowView,
itemViewContainer: "ul",
//I don't think template implementation isn't important for this example
template: "#list-layout"
});
我是不是做错了,我应该在添加到集合之前修改数据集以包含空部分吗? (如果是这样,我将需要根据源数组项是否为空来切换模板,但这似乎是另一种蠕虫病毒,具有过多的空数据点。)
最终,输出类似于 table,但数据是以面向列的方式构建的,我在尝试构建它时发现有点迷失方向。空行确保所有项目都排成一行,并有望在开发过程中进一步简化 jQuery 调用。
完整的预期输出示例片段:
#main-content {
background: #ccc;
position: relative;
}
#iconrow {
border-bottom: solid 1px #999
}
.col-xs-0 {
width: 55px;
padding: 0px;
position: relative;
float: left;
min-height: 1px;
}
.icon {
width: 100%;
height: 0;
padding-bottom: 99%;
margin: 15px 0px;
border-radius: 100%;
border: 1px solid #999;
background: white
}
.timeline {
padding: 30px 0px;
position: relative;
}
.timeline ul {
padding: 0px;
list-style: none;
margin: 0px;
position: relative;
}
.timeline li {
position: relative;
width: 100%;
height: 50px;
display: block;
}
.timeline li:before {
width: 6px;
height: 100%;
margin-left: -3px;
position: absolute;
top: 0;
left: 50%;
display: block;
background: #cc7264;
content: ' ';
}
.timeline .node2 {
width: 24px;
height: 24px;
margin-left: -12px;
margin-top: 0px;
z-index: 2;
background: #eee;
border: 4px solid #cc7264;
position: absolute;
left: 50%;
top: -1px;
border-radius: 100%;
}
.timeline .node2:hover {
width: 48px;
height: 48px;
margin-left: -24px;
margin-top: -12px;
border-width: 6px;
}
.timeline .node2:active {
width: 36px;
height: 36px;
margin-left: -18px;
margin-top: -6px;
background: #eebaa9;
border-width: 6px;
}
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"></script>
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css" rel="stylesheet"/>
<div class="container" id="main-content">
<div class="row clearfix">
<div class="col-xs-0"></div>
<div class="col-xs-2 timeline">
<ul class="year y2014">
<li> <div class="node2"></div></li>
<li> </li>
<li> </li>
<li> <div class="node2"></div></li>
<li> <div class="node2"></div></li>
<li> </li>
<li> <div class="node2"></div></li>
<li> </li>
<li> </li>
<li> </li>
<li> </li>
<li> <div class="node2"></div></li>
</ul>
<ul class="year y2015">
<li> <div class="node2"></div></li>
<li> </li>
<li> </li>
<li> <div class="node2"></div></li>
<li> <div class="node2"></div></li>
<li> </li>
<li> <div class="node2"></div></li>
<li> </li>
<li> </li>
<li> </li>
<li> </li>
<li> <div class="node2"></div></li>
</ul>
</div>
<div class="col-xs-2 timeline">
<ul>
<li> </li>
<li> <div class="node2"></div></li>
<li> <div class="node2"></div></li>
<li> </li>
<li> <div class="node2"></div></li>
<li> </li>
<li> </li>
<li> </li>
<li> <div class="node2"></div></li>
<li> <div class="node2"></div></li>
<li> </li>
<li> </li>
</ul>
</div>
<div class="col-xs-2 timeline">
<ul>
<li> </li>
<li class="disabled"> <div class="node2"></div></li>
<li class="disabled"> </li>
<li class="disabled"> </li>
<li class="disabled"> </li>
<li class="disabled"> </li>
<li class="disabled"> </li>
<li class="disabled"> </li>
<li class="disabled"> </li>
<li class="disabled"> </li>
<li class="disabled"> <div class="node2"></div></li>
<li class="disabled"> </li>
</ul>
</div>
<div class="col-xs-2 timeline">
<ul>
<li class="disabled"> <div class="node2"></div></li>
<li class="disabled"> </li>
<li class="disabled"> </li>
<li class="disabled"> <div class="node2"></div></li>
<li class="disabled"> <div class="node2"></div></li>
<li class="disabled"> <div class="node2"></div></li>
<li class="disabled"> <div class="node2"></div></li>
<li class="disabled"> </li>
<li class="disabled"> </li>
<li class="disabled"> <div class="node2"></div></li>
<li class="disabled"> </li>
<li class="disabled"> <div class="node2"></div></li>
</ul>
</div>
</div>
</div>
谢谢!
我的解决方案最终是创建辅助函数来填充数据,并简化新模型的制作。
我首先制作节点模型的主集合,因此每个节点都获得 backbone cID 和单个处理程序,然后我使用集合的 "where" 功能(来自 underscore.js) 以获取与组匹配的节点数组。 nodeCollection.where({listID:1})
使用这个特定于列表的数组,然后我可以创建一个大小为 N 的空数组,var emptyArray = Array(N)
,并在特定于列表的节点上进行简单的 foreach 循环,以用节点替换数组中的位置目的。 (注意:这个数组填充了"undefined"个对象)
for(node in nodeSublist){
i=node.get("position")-1;//subtract 1 for 0-based array position
emptyArray[i]=node;
}
有了这个填充的节点数组,我可以然后将该数组放入一个新的集合对象中。 new Entities.NodesCollection(paddedArray)
。 Backbone 不会创建新的 Node 对象,因为它们已经被实例化了。
我将这个新填充的 nodeCollection 设置为新 "list" 模型中的一个属性,用于每个列表。然后在列表的 CollectionView 中,我只是在 initialize:
传递上将视图的集合设置为模型中的节点列表。
initialize: function(){
this.collection = this.model.get("nodes");
}
我可以创建这些列表模型的集合,现在我拥有了我需要的所有对象。列表数组的简单 CollectionView,将输出一个容器并呈现每个 NodeList 视图。每个Nodelist都会输出UL,并在Node ItemView和Empty ItemView之间切换。
var NodeList = Marionette.CollectionView.extend({
tagName: "ul",
getChildView: function(node){
//this is a real node
if(node.get("name")){
return List.NodeView;
}
//otherwise this node is empty, dont render anything
else{
return List.EmptyNodeView;
}
},
initialize: function(){
this.collection = this.model.get("nodes");
//you cannot set the class on initialize,
//because the DOM object is created before the initialize function,
//so use jquery.
this.$el.addClass("list"+this.model.get("listID"));
}
}
我们很好!
谢谢@Seebiscuit 让我开始!
我正在尝试填充一组列表,仅使用指定数量的元素来指定需要将它们添加到哪一行。
示例: 每个节点项都有一个对应于特定 UL 的编号以及要添加到的位置,但是元素的 "total" 数量是已知的。
简化示例数据(假设pre-determined数组大小为5):
nodes = new Entities.NodeCollection([
{ listID: 1, position: 2, name: "node2" },
{ listID: 1, position: 5, name: "node5" },
{ listID: 2, position: 4, name: "node4" }
]);
预期输出: 每个节点都插入到正确的位置,其余位置填充空 LI。
<ul id="list1">
<li></li>
<li><div class="template-class" id="node2"></div></li>
<li></li>
<li></li>
<li><div class="template-class" id="node5"></div></li>
</ul>
<ul id="list2">
<li></li>
<li></li>
<li></li>
<li><div class="template-class" id="node4"></div></li>
<li></li>
</ul>
预期输出:
如何创建一个模板,让我可以将数据插入正确的位置并 auto-fills 缺失的部分?
我可以用 jQuery 轻松做到这一点,(pre-fill 正确的长度和 select child #)但我需要使用 Marionette/Backbone,构建应用程序的事件管理和数据库查询端。
最坏的情况,能够循环遍历已知的元素数量并检查是否有应该去那里的数据点,必要时填写正确的 html(或空的),但是看起来不像是常见的 Marionette/Backbone 范例。
我想我的实际行模板是正确的;
<script type="text/template" id="node-list-item">
<div class="template-class" id="<%- name %></div>
</script>
和观点:
RowView = Backbone.Marionette.ItemView.extend({
tagName: "li",
template: "#node-list-item"
//something goes here to correctly handle empty pieces?
});
ListView = Backbone.Marionette.CompositeView.extend({
itemView: RowView,
itemViewContainer: "ul",
//I don't think template implementation isn't important for this example
template: "#list-layout"
});
我是不是做错了,我应该在添加到集合之前修改数据集以包含空部分吗? (如果是这样,我将需要根据源数组项是否为空来切换模板,但这似乎是另一种蠕虫病毒,具有过多的空数据点。)
最终,输出类似于 table,但数据是以面向列的方式构建的,我在尝试构建它时发现有点迷失方向。空行确保所有项目都排成一行,并有望在开发过程中进一步简化 jQuery 调用。
完整的预期输出示例片段:
#main-content {
background: #ccc;
position: relative;
}
#iconrow {
border-bottom: solid 1px #999
}
.col-xs-0 {
width: 55px;
padding: 0px;
position: relative;
float: left;
min-height: 1px;
}
.icon {
width: 100%;
height: 0;
padding-bottom: 99%;
margin: 15px 0px;
border-radius: 100%;
border: 1px solid #999;
background: white
}
.timeline {
padding: 30px 0px;
position: relative;
}
.timeline ul {
padding: 0px;
list-style: none;
margin: 0px;
position: relative;
}
.timeline li {
position: relative;
width: 100%;
height: 50px;
display: block;
}
.timeline li:before {
width: 6px;
height: 100%;
margin-left: -3px;
position: absolute;
top: 0;
left: 50%;
display: block;
background: #cc7264;
content: ' ';
}
.timeline .node2 {
width: 24px;
height: 24px;
margin-left: -12px;
margin-top: 0px;
z-index: 2;
background: #eee;
border: 4px solid #cc7264;
position: absolute;
left: 50%;
top: -1px;
border-radius: 100%;
}
.timeline .node2:hover {
width: 48px;
height: 48px;
margin-left: -24px;
margin-top: -12px;
border-width: 6px;
}
.timeline .node2:active {
width: 36px;
height: 36px;
margin-left: -18px;
margin-top: -6px;
background: #eebaa9;
border-width: 6px;
}
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"></script>
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css" rel="stylesheet"/>
<div class="container" id="main-content">
<div class="row clearfix">
<div class="col-xs-0"></div>
<div class="col-xs-2 timeline">
<ul class="year y2014">
<li> <div class="node2"></div></li>
<li> </li>
<li> </li>
<li> <div class="node2"></div></li>
<li> <div class="node2"></div></li>
<li> </li>
<li> <div class="node2"></div></li>
<li> </li>
<li> </li>
<li> </li>
<li> </li>
<li> <div class="node2"></div></li>
</ul>
<ul class="year y2015">
<li> <div class="node2"></div></li>
<li> </li>
<li> </li>
<li> <div class="node2"></div></li>
<li> <div class="node2"></div></li>
<li> </li>
<li> <div class="node2"></div></li>
<li> </li>
<li> </li>
<li> </li>
<li> </li>
<li> <div class="node2"></div></li>
</ul>
</div>
<div class="col-xs-2 timeline">
<ul>
<li> </li>
<li> <div class="node2"></div></li>
<li> <div class="node2"></div></li>
<li> </li>
<li> <div class="node2"></div></li>
<li> </li>
<li> </li>
<li> </li>
<li> <div class="node2"></div></li>
<li> <div class="node2"></div></li>
<li> </li>
<li> </li>
</ul>
</div>
<div class="col-xs-2 timeline">
<ul>
<li> </li>
<li class="disabled"> <div class="node2"></div></li>
<li class="disabled"> </li>
<li class="disabled"> </li>
<li class="disabled"> </li>
<li class="disabled"> </li>
<li class="disabled"> </li>
<li class="disabled"> </li>
<li class="disabled"> </li>
<li class="disabled"> </li>
<li class="disabled"> <div class="node2"></div></li>
<li class="disabled"> </li>
</ul>
</div>
<div class="col-xs-2 timeline">
<ul>
<li class="disabled"> <div class="node2"></div></li>
<li class="disabled"> </li>
<li class="disabled"> </li>
<li class="disabled"> <div class="node2"></div></li>
<li class="disabled"> <div class="node2"></div></li>
<li class="disabled"> <div class="node2"></div></li>
<li class="disabled"> <div class="node2"></div></li>
<li class="disabled"> </li>
<li class="disabled"> </li>
<li class="disabled"> <div class="node2"></div></li>
<li class="disabled"> </li>
<li class="disabled"> <div class="node2"></div></li>
</ul>
</div>
</div>
</div>
谢谢!
我的解决方案最终是创建辅助函数来填充数据,并简化新模型的制作。
我首先制作节点模型的主集合,因此每个节点都获得 backbone cID 和单个处理程序,然后我使用集合的 "where" 功能(来自 underscore.js) 以获取与组匹配的节点数组。 nodeCollection.where({listID:1})
使用这个特定于列表的数组,然后我可以创建一个大小为 N 的空数组,var emptyArray = Array(N)
,并在特定于列表的节点上进行简单的 foreach 循环,以用节点替换数组中的位置目的。 (注意:这个数组填充了"undefined"个对象)
for(node in nodeSublist){
i=node.get("position")-1;//subtract 1 for 0-based array position
emptyArray[i]=node;
}
有了这个填充的节点数组,我可以然后将该数组放入一个新的集合对象中。 new Entities.NodesCollection(paddedArray)
。 Backbone 不会创建新的 Node 对象,因为它们已经被实例化了。
我将这个新填充的 nodeCollection 设置为新 "list" 模型中的一个属性,用于每个列表。然后在列表的 CollectionView 中,我只是在 initialize:
传递上将视图的集合设置为模型中的节点列表。
initialize: function(){
this.collection = this.model.get("nodes");
}
我可以创建这些列表模型的集合,现在我拥有了我需要的所有对象。列表数组的简单 CollectionView,将输出一个容器并呈现每个 NodeList 视图。每个Nodelist都会输出UL,并在Node ItemView和Empty ItemView之间切换。
var NodeList = Marionette.CollectionView.extend({
tagName: "ul",
getChildView: function(node){
//this is a real node
if(node.get("name")){
return List.NodeView;
}
//otherwise this node is empty, dont render anything
else{
return List.EmptyNodeView;
}
},
initialize: function(){
this.collection = this.model.get("nodes");
//you cannot set the class on initialize,
//because the DOM object is created before the initialize function,
//so use jquery.
this.$el.addClass("list"+this.model.get("listID"));
}
}
我们很好!
谢谢@Seebiscuit 让我开始!