Backbone and jQuery UI

by wojtiku

HTML

<script src="http://documentcloud.github.com/underscore/underscore-min.js"></script>
<script src="http://documentcloud.github.com/backbone/backbone-min.js"></script>
<div class="container">
    
    <ul id='collection-view'></ul>

</div>

<div id='post-data'></div>

CSS

body {
    background: #eee;
    font-family: "Arial", sans-serif;
}

.container {
    width: 500px;
    padding: 30px;
    margin: 20px auto;
    -webkit-border-radius: 6px;
            border-radius: 6px;
    background: #fff;
    box-shadow: 0 3px 10px rgba(0,0,0,.3);
}

#post-data {
    text-align: center;
    color: #999;
}

.item-view {
    padding: 10px;
    border: solid 1px #ddd;
    margin: 5px;
    -webkit-border-radius: 5px;
            border-radius: 5px;
    -moz-background-clip: padding; -webkit-background-clip: padding-box; background-clip: padding-box;
    background-color: #eee;
    background-image: -webkit-gradient(linear, left top, left bottom, from(#ffffff), to(#eeeeee));
    background-image: -webkit-linear-gradient(top, #ffffff, #eeeeee);
    background-image:    -moz-linear-gradient(top, #ffffff, #eeeeee);
    background-image:      -o-linear-gradient(top, #ffffff, #eeeeee);
    background-image:         linear-gradient(to bottom, #ffffff, #eeeeee);
    color: #888;
}

.item-view:active,
.item-view:hover {
    background-color: #ddd;
    background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#ddd));
    background-image: -webkit-linear-gradient(top, #fff, #ddd);
    background-image:    -moz-linear-gradient(top, #fff, #ddd);
    background-image:      -o-linear-gradient(top, #fff, #ddd);
    background-image:         linear-gradient(to bottom, #fff, #ddd);
    color: #000;
}

JavaScript

Application = {};
Application.Collection = {};
Application.Model = {};
Application.View = {};


Application.Model.Item = Backbone.Model.extend();

Application.Collection.Items = Backbone.Collection.extend({
    model: Application.Model.Item,
    comparator: function(model) {
        return model.get('ordinal');
    },
});


Application.View.Item = Backbone.View.extend({
    tagName: 'li',
    className: 'item-view',
    events: {
        'drop' : 'drop'
    },
    drop: function(event, index) {
        this.$el.trigger('update-sort', [this.model, index]);
    },        
    render: function() {
        $(this.el).html(this.model.get('name') + ' (' + this.model.get('id') + ')');
        return this;
    }
});

Application.View.Items = Backbone.View.extend({
    events: {
        'update-sort': 'updateSort'
    },
    render: function() {
        this.$el.children().remove();
        this.collection.each(this.appendModelView, this);
        return this;
    },    
    appendModelView: function(model) {
        var el = new Application.View.Item({model: model}).render().el;
        this.$el.append(el);
    },
    updateSort: function(event, model, position) {            
        this.collection.remove(model);

        this.collection.each(function (model, index) {
            var ordinal = index;
            if (index >= position)
                ordinal += 1;
            model.set('ordinal', ordinal);
        });            
        
        model.set('ordinal', position);
        this.collection.add(model, {at: position});
        
        // to update ordinals on server:
        var ids = this.collection.pluck('id');
        $('#post-data').html("Post IDs to server: <strong>" + ids.join(', ') + "</strong>.");
        
        this.render();
    }
});    

var Instance = {};
Instance.collection = new Application.Collection.Items();

Instance.collection.add(new Application.Model.Item({
    id: 1,
    name: 'a',
    ordinal: 0
}));

Instance.collection.add(new...