English 中文(简体)
jQuery Inserting elements in the correct order vs detach().sort()?
原标题:

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/

最佳回答

you can use a jQuery

$( li ).eq(1).after( <li>3</li> );

fiddle page: http://jsfiddle.net/Hrjks/

Better yet:

var myindex = 3;
var insertPoint = myindex -2;
$( li ).eq(insertPoint).after( <li>  + myindex + </li> );

fiddle for this:http://jsfiddle.net/Hrjks/1/

问题回答

I had the same problem recently and I fixed with the following function.

function sortInsert(parent, element, fnc) {
    var stack = parent.children().filter(function() {
        return fnc($(this), element) > 0;
    });       
    if (stack.length == 0) {
        parent.append(element);
    } else {
        stack.first().before(element);
    }
}

sortInsert($( ul ), $( <li>1</li> ), function(e, a) { 
    return parseInt(e.html()) - parseInt(a.html()); 
} );​

It is basically getting all the child of parent, then doing a filter. If you only need to compare its values you can do it simple by avoiding the callback but in my case it was needed as I was sorting by several criteria.

If you want to sort with a descending order just replace append by prepend, before by last and first for last and it should be working.

Feel free to play in my playground: http://jsfiddle.net/crodas/FMEkb/5/





相关问题
selected text in iframe

How to get a selected text inside a iframe. I my page i m having a iframe which is editable true. So how can i get the selected text in that iframe.

How to fire event handlers on the link using javascript

I would like to click a link in my page using javascript. I would like to Fire event handlers on the link without navigating. How can this be done? This has to work both in firefox and Internet ...

How to Add script codes before the </body> tag ASP.NET

Heres the problem, In Masterpage, the google analytics code were pasted before the end of body tag. In ASPX page, I need to generate a script (google addItem tracker) using codebehind ClientScript ...

Clipboard access using Javascript - sans Flash?

Is there a reliable way to access the client machine s clipboard using Javascript? I continue to run into permissions issues when attempting to do this. How does Google Docs do this? Do they use ...

javascript debugging question

I have a large javascript which I didn t write but I need to use it and I m slowely going trough it trying to figure out what does it do and how, I m using alert to print out what it does but now I ...

Parsing date like twitter

I ve made a little forum and I want parse the date on newest posts like twitter, you know "posted 40 minutes ago ","posted 1 hour ago"... What s the best way ? Thanx.

热门标签