gaffa-tape / gaffa

Model driven JavaScript application framework
Other
45 stars 6 forks source link

How to create Gaffa extensions? #27

Closed sholtomaud closed 10 years ago

sholtomaud commented 10 years ago

I'm an intermediate js user, still learning the Gaffa/Gel/Crel/Lang framework. Stylistically the framework has been changing throughout v0.-v1. I have a few different examples from the developers of Gaffa with different ways of achieving the same thing. For example:

var app = {},
    Gaffa = require('gaffa'),
    gaffa = new Gaffa(),
    views = gaffa.views.constructors = app.views = require('./views'),
    actions = gaffa.actions.constructors = app.actions = require('./actions'),
    behaviours = gaffa.behaviours.constructors = app.behaviours = require('./behaviours');

app.gaffa = gaffa;

module.exports = app;

verses

var gaffa = new Gaffa();
window.gaffa = gaffa;

require('./constructors')(gaffa);

constructors.js

var constructors = [
        require('gaffa-list'),
        require('gaffa-container'),
        require('gaffa-label'),
        require('gaffa-heading')
    ];

module.exports = function(gaffa){
    constructors.forEach(gaffa.registerConstructor.bind(gaffa));
}

It would be good to lock down the style so noobs like me can get a handle on things.

In particular I'd like to add gaffa extensions (see for example)[https://github.com/shotlom/gaffa-canvas/issues/1] for charts (e.g. D3.js, joint.js, dagre), drawings (canvas), and maps (e.g. leaflet.js) but not sure how to do so.

Any chance of an example 'how to' for Gaffa extensions, and lock down the "Gaffa style" at the same time?

KoryNunn commented 10 years ago

All of the above are acceptable, since gaffa is striving towards being a tool more than a framework.

There is no 'correct' way of architecting your application but gaffa-template aims to provide some guidance and convention around how gaffa can be used.

gaffa viewItems, whilst often seen in a gaffa-extensions folder, are not special when compared to viewItems such as gaffa-textbox or gaffa-container. the gaffaExtensions folder seen in some gaffa applications is just a place to put viewItems that are not their own modules (yet).

I do intent to create some documentation around creating viewItems, which should cover the question about D3. An (old) example of non-html views being used in gaffa can be seen here: https://github.com/KoryNunn/gaffa-three/tree/master/views. Here, three-js is being used with gaffa to render a 3D scene.

sholtomaud commented 10 years ago

Thanks @KoryNunn, library integration doesn't look like something I could do just yet.

Thinking out aloud - I'm wondering:

  1. What are the main benefits of this type of integration? I.e. Why would one do this rather than just use the libraries?
  2. Do the libraries need to be browserifiable before they can be integrated to Gaffa?
sholtomaud commented 10 years ago

Interesting blog Replacing d3.js with pure SVG + AngularJS raises issues which might be relevant to this thread.

Would Gaffa have the same situation?

KoryNunn commented 10 years ago

Both D3 and Angular are focused around control of a similar level of an application, manipulating DOM/SVG/etc.

Gaffa's focus is higher, around the data flow of the application and its abstract UI components. Rather than getting data in and out of the raw UI its self, gaffa defers to viewItems to interact with the raw UI.

This is actually a good thing in the case of using D3; Gaffa doesn't want to touch the DOM, but instead wants something else to do it, which it will keep informed of changes to the data being represented.

gaffa s stack position

So in terms of actual implementation: Lets say you wanted to make a graph of user over time..

var Gaffa = require('gaffa'),
    crel = require('crel');

function UserGraph(){}
UserGraph = Gaffa.createSpec(UserGraph, Gaffa.View);
UserGraph.prototype._type = 'userGraph';
UserGraph.prototype.render = function(){
    var renderedElement = crel('div');

    this.renderedElement = renderedElement;
}
UserGraph.prototype.data = new Gaffa.Property(function(view, data){

    // This will be called whenever the data that UserGraph.data is bound to changes.

    // Use D3 to manipulate the DOM within view.renderedElement

});

And then you just use the UserGraph in you application as you would any other view:

var UserGraph = require('./path/to/userGraph.js');

gaffa.registerConstructor(UserGraph);

var userGraph = new UserGraph();
userGraph.data.binding = '[/usersOverTime]';

gaffa.views.add(userGraph);
KoryNunn commented 10 years ago

Also, no, libraries do not need to be browserifyable to be able to use them within a Gaffa ViewItem, they can be on the global, and you can just call them from within the ViewItems code