0

Let me know if you can help me out somehow, i'm kind of struggling to get my head around.

Starting with some Marionette application logics:

app.js

//basic setup
this.Graph = new joint.dia.Graph;
this.Paper = new joint.dia.Paper({ width: 640, height: 480, model: this.Graph });

// [...] lots of code

//adding elements
app.Elements.add(element);

So far so good. Now the tricky part. I want a collection.

JointCollectionView.js

module.exports = Marionette.CollectionView.extend({
    tagName: 'div',
    className: 'row',
    childView: JointView,

    addChild: function(child, ChildView, index){
        //does that make sense?
        app.Graph.addCell(child);

        //should i add it to collection?
        if (child.shouldBeShown()) {
            return Marionette.CollectionView.prototype.addChild.call(this,   child, ChildView, index);
        }
    },

    getChildView: function(item) {
        return app.Graph.getCell(item);
    }

    //[...]
})

Now even more tricky. How do i handle the joint-view to make it work with collections and also display html elements?

JointView.js

module.exports = joint.dia.ElementView.extend({ /* ?!?!?! */ });

//OR ?

module.exports = Marionette.ItemView.extend({
    jointElementView: null, //this will be like above somewhere else...

    initialize: function(options){
        jointElementView = new JointElementView({ /* ... */ });
    }
})
Tom Siwik
  • 992
  • 9
  • 22
  • How did it work it for you? – seebiscuit Dec 23 '15 at 03:13
  • I have actually solved the problem. JointElementView is a bad idea since jointjs doesn't work that way. I will update my post so you can change your answer accordingly. Since you are the only one who invested some time looking at it your points are well deserved. Sorry for the delay tho. Busy before xmas :) – Tom Siwik Dec 23 '15 at 13:19
  • There you go. Edited. Fix your answer and i'll approve it :) – Tom Siwik Dec 23 '15 at 13:47

2 Answers2

1

I'm no JointJS expert, but your implementation looks perfect.

You want to use the second option:

JointView.js

module.exports = Marionette.ItemView.extend({
  template: _.template("");
  jointElementView: null, //this will be like above somewhere else...

  initialize: function(options){
      this.jointElementView = new JointElementView({ /* ... */ });
  }
});

since a Marionette.CollectionView expects a Marionette view (sp. a Marionette.ItemView or descendent [LayoutView/CompositeView]).

What I would add to JointView.js is a method to inject the result from this.jointElementView into the JointView.js html. So, add a property to it, like:

onRender: function () {
  this.$el.append(this.jointElementView.el); // Where this.jointElementView.el is the JointJS view html
}
seebiscuit
  • 4,905
  • 5
  • 31
  • 47
0

With the help of @seebiscuit i looked much deeper into jointjs and narrowed down how i should approach this problem (You didn't seem to be interested in the points though, so i'll answer myself)

The following files were edited:

app.js (changed, important!)

//this step is necessary to create these element before the paper is created.
//Make jointjs GLOBAL!!!!!!
joint.shapes.html = {};
joint.shapes.html.Element = require('views/Element');  //this dude im gonna use to create the elements 
joint.shapes.html.ElementView = require('views/ElementView');  //this badboy will fire when i create those elements. MAGIC!

//basic setup
this.Graph = new joint.dia.Graph;
this.Paper = new joint.dia.Paper({ width: 640, height: 480, model:     this.Graph });

// [...] lots of code

//adding elements
app.Elements.add(element);

JointCollectionView.js (beauti-/simplyfied)

module.exports = Marionette.CollectionView.extend({
    tagName: 'div',
    className: 'row',
    childView: JointView,

    onRender: function(){
      // jointjs' paper is added here long after jointjs custom element init.
      this.el.appendChild(app.Paper.el);
    },

    onDestroy: function(){
      // removal of the paper is done here
      this.el.removeChild(app.Paper.el);
    },

    buildChildView: function(child, JointView, childViewOptions){
      // add model, jointjs' paper and graph into JointView's options
      var options = _.extend({model: child}, childViewOptions);
          options = _.extend({paper: app.Paper, graph: app.Graph}, options);

      return new JointView(options);
    }    

    //[...]
})

JointView.js (magic here!)

module.exports = Marionette.ItemView.extend({
    tagName: 'div',
    className: 'html-element',
    template: "#agentTmpl",

    // store here just in case
    cell: null,

    // [...]

    initialize: function() {
      // initialize joinjs element-shape here
      Marionette.bindEntityEvents(this, this.model, this.modelEvents);

      if(this.cell == null){
        //notice `el: this.el` This will actually pass the option el to ElementView. Surprised? 
        //Yeah me too. From there i can do with the dom-element whatever i want
        this.cell = new joint.shapes.html.Element({ el: this.el, position: { x: 80, y: 80 }, size: { width: 250 } });
      }
    },

    onRender: function(){
          // after rendering add cell to graph
          this.options.graph.addCell(this.cell);
    },

    onDestroy: function(){
          // after removal remove cell from graph
          this.cell.remove();
    }
});

Element.js ElementView.js

For simplicity more or less like here: http://www.jointjs.com/tutorial/html-elements To summarize what actually happens is: whenever a new Element is created ElementView will fire all necessary event (initialize, render & whatnot). From there you can manipulate the drawn svg elements or overlap (similar to the tutorial) with my previously created JointView's html. I basically put my JointView dom-element over the SVG which is drawn by jointjs.

There you go. Fixed!

Tom Siwik
  • 992
  • 9
  • 22