d3.js force layout namespace in a backbone view

425 views Asked by At

I'm working on a medium-complex app using backbone.js to handle wordpress data, and i can't figure out how to get the force working in a backbone layout.

basically, i'm trying to instantiate a force layout within a backbone boilerplate layout, like this:

myLayout = Backbone.Layout.extend({
    initialize: function() {
        var f = this; // i.e. the layout instance
        f.force = d3.layout.force()
            .nodes(myModels)
            .on("tick", f.tick)
            .gravity(0)
            .friction(0.9)
            .start();

        console.log(f.force);
    },
    tick: function() {
        // stuff to do when the force ticks
    }
});

The problem is that the force is being defined with all blank functions, like gravity: function(x) { //lots of null things here }. i'm pretty sure it's a namespacing issue, but nothing i try works - i've tried doing $(window).force, var force, $this.force...

in my example tick is the only namespaced function, but i've tried doing that with all the others too (gravity, friction, etc.) to no avail (even though they should just be chaining onto the force object).

anyone have any ideas? i can't really post a .jsfiddle because the app is too complicated, so sorry in advance about that. The current version is up here

edit: here's how d3 can access the models successfully:

this works:

myLayout.nodes = myLayout.d3_wrapper.selectAll(".node")
    .data(myModels)
    .enter().append("g").attr("class", "node")
    .attr("x",10)
    .attr("y",10);

    myLayout.nodes.append("clipPath")
        .attr("id", function(d) { return d.get("slug"); })

as does this: myLayout.nodes.append("clipPath") .attr("id", function(d) { return d.attributes.slug });

edit: in the interest of clarity, here's the non-nicknamed code:

setforce: function() { // this gets called from the layout's initialize fn
    console.log("setting force");
    var f = this; // the layout
    f.force = d3.layout.force()
        .nodes(Cartofolio.elders.models) // Cartofolio is the module, elders is a Backbone Collection
        .gravity(0)
        .friction(0.9)
        .start();

    console.log(f.force);
}
1

There are 1 answers

4
Ben On

I would try using toJSON() on your collection before passing it to d3:

myLayout = Backbone.Layout.extend({
    initialize: function() {
        var f = this; // i.e. the layout instance
        f.force = d3.layout.force()
            .nodes(myModels.toJSON())
            .on("tick", f.tick)
            .gravity(0)
            .friction(0.9)
            .start();

        console.log(f.force);
    },
    tick: function() {
        // stuff to do when the force ticks
    }
});