Basic Backbone application using d3 I've started my first application using backbone and have something basic up and running, backbone seems to give a lot of freedom to application design and I don't know what I'm doing right and wrong in that regard. I'm just after some tips and criticism.

The first view is for the details which should be visible when the page loads:

var DetailsView = Backbone.View.extend({

    el: $(".details"),

    initialize: function(options) {
        // nothing here yet
    },

    render: function() {
        // nothing here yet
    },

    events: {
        "click .btn": "setDetails"
    },

    setDetails: function(e) {
        this.$el.hide();
        // will do validation here...
        this.options.dataEditorView.$el.show();
        this.options.finalView.render();

    }

});


Once a user has completed the details form for that view, the data edit view is displayed:

var DataEditorView = Backbone.View.extend({
    el: $(".data-editor"),

    initialize: function(options) {

    },

    events: {
        "keypress .point-x": "addSeriesPoint",
        "keypress .point-y": "addSeriesPoint"
    },

    addSeriesPoint: function(e) {
        if (e.keyCode != 13) return;
        //if (!this.input.val()) return;

        console.log('adding point');

        var point = [];
        point[0] = $("#input-point-x").val();
        point[1] = $("#input-point-y").val();

        Series.create({
            x: $("#input-point-x").val(),
            y: $("#input-point-y").val()
        });

        var points = this.options.seriesCollection.toJSON();
        this.options.summaryView.addPoint(points);

        $(".point-x").val("");
        $(".point-x").focus();

    }

});


And the summary view which is visible while the date editor view is visible:

var SummaryView = Backbone.View.extend({
    initialize: function() {

        console.log('initialising...');

        this.canvas = d3.select(this.el)
                        .append("svg")
                        .attr("width", 600)
                        .attr("height", 500);

    },

    className: "summary",

    render: function() {
        $("body").append(this.el);
    },

    addPoint: function(points) {
        console.log(points);
        this.canvas.selectAll("circle")
                    .data(points)
                    .enter()
                    .append("circle")
                    .attr("r", 42)
                    .attr("cx", function(d) { return d.x })
                    .attr("cy", function(d) { return d.y })
                    .transition().selectAll('circle')
                    .ease('bounce').duration(900)
                    .attr('r', function (d) {
                        console.log(d);
                        return 99; //ugh
                    });
    }

});
DetailsView

You should pass jquery selector to the el — Backbone will handle it. Also, note that you should pass DOM element to the el property.



Injecting one view into another is often a bad practice (if relation is not like parent and subview): is.options.dataEditorView.$el.show(); this.options.finalView.render();

Consider triggering event like validation-success from DetailsView. Subscriber to this event should be in the route or other main object.

DataEditorView

var point = {
    x: $("#input-point-x").val(),
        y: $("#input-point-y").val()
};

Series.create(point); 
// Probably you want to add new point to existing collection this.options.seriesCollection?




Another view injection: this.options.summaryView.addPoint(points);

Just add new point into collection and subscribe to event in the summaryView (see next block).



// Micro optimization
var pointX = $(".point-x");
pointX.val("");
pointX.focus();


SummaryView

Add view.listenTo(seriesCollection, 'add', addPoint) into initialize step. addPoint should accept parameters: model, collection, options, where model is a new point which was added to the collection.

In this function you should run collection.toJSON() to prepare points for D3.data().