Let s say I have the following html structure:
<ul>
<li>1</li>
<li>2</li>
<li>4</li>
</ul>
Is it possible (and how) to insert a new element <li>3</li>
in the correct order without detaching the elements and resorting? Reason being, I believe if you .detach() and .append() the elements, you will cause a page reflow (which I suppose would happen anyways if the elements move around). But for some reason, it seems much cleaner to insert it in the right spot vs append/detach/sort/append.
I ve seen the nth-child selector in jQuery and I m working with the underscore.js framework too (which provides _.sortedIndex
which tells me the correct position of the element), but I can t seem to figure out the right way to put it in there.
Some background: I m working with backbone.js and I have a collection of items. Then I assume I need a View of the collection (or view per item in the collection?). When I add an element to the collection, I have the comparator set so the collection is sorted properly, but the View on the page is not sorted.
For those getting here via google, here s what I eventually came up with in backbone.js:
Item = Backbone.Model.extend({});
ItemList = Backbone.Collection.extend({
model: Item,
comparator: function(item) {
return item.get( id );
}
});
ItemView = Backbone.View.extend({
tagName: li ,
className: item ,
initialize: function() {
_.bindAll(this, render );
this.model.bind( change , this.render);
this.model.view = this;
},
render: function() {
$(this.el).text(this.model.get( name ));
return this;
}
});
App = Backbone.View.extend({
el: $( #mylist ),
initialize: function() {
_.bindAll(this, add_one , add_all , render );
this.items = new ItemList();
this.items.bind( add , this.add_one);
this.items.bind( refresh , this.add_all);
this.items.bind( all , this.render);
this.items.add(new Item({id: 2, name: two }));
this.items.add(new Item({id: 5, name: five }));
this.items.add(new Item({id: 1, name: one }));
this.items.add(new Item({id: 4, name: four }));
this.items.add(new Item({id: 3, name: three }));
this.items.add(new Item({id: 6, name: six }));
this.items.add(new Item({id: 5.5, name: five.five }));
},
add_one: function(item) {
var view = new ItemView({model: item});
var visible = this.$(view.tagName+ . +view.className);
var newel = view.render().el;
var idx = this.items.indexOf(item);
if (visible.length == idx) {
$(this.el).append(newel);
}
else {
visible.eq(idx).before(newel);
}
},
add_all: function() {
this.items.each(this.add_one);
}
});
app = new App();
Run it here: http://jsfiddle.net/dlamotte/L4j3b/