Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add View Tree #32

Open
jasonLaster opened this issue Jan 23, 2015 · 7 comments
Open

Add View Tree #32

jasonLaster opened this issue Jan 23, 2015 · 7 comments

Comments

@jasonLaster
Copy link

The Marionette Inspector's view tree, which shows nested views, is one of the most appreciated features of the inspector. It serves two purposes: 1) makes it easy to find a view on the page, 2) offers context for how the app is built.

While Backbone doesn't have a native idea of regions, which lend themselves to layouts and lists, we could infer the view tree pretty easily by looking at the attached views and comparing their elements. A basic algorithm would go like this: given two views a and b, is A contained by B or vice versa, does A precede B or vice versa... Anyways, while it's more work to reverse engineer the view tree only given dom elements, I think it's absolutely possible for the motivated person.

View Tree

@Maluen
Copy link
Owner

Maluen commented Jan 23, 2015

We have just to make sure to spot subviews addition and removal on the fly.

This could be done by monitoring the DOM for element additions and removals, checking what is the first encountered view by going up the DOM, since it will likely be the parent view.

We should also take performance into consideration, probably we can create some data structure / annotate DOM (even if I don't like that much) to fastly retrieve parent / child views.

@jridgewell
Copy link

This could be done by monitoring the DOM for element additions and removals, checking what is the first encountered view by going up the DOM, since it will likely be the parent view.

That's going to be a major performance hit, and wouldn't be compatible with detached views and Minionette's Regions, which swap views in and out of the DOM without removing them. Even when detached, I still consider these "subviews" of the view.

Wrapping #remove seems like a definitive way to determine when the view is no longer a subview. Both Marionette and Minionette call it.

Determining when a subview is added to a view is a more difficult problem. I imagine an adaptor would be able to handle this: Some #_onAddSubview can be called when adding. We could extend that to removing a subview (ie. #_onRemoveSubview). It should be very easy to write adaptors to handle both cases.

We should also take performance into consideration, probably we can create some data structure / annotate DOM (even if I don't like that much) to fastly retrieve parent / child views.

Off hand, I know Thorax places data-cid onto all view's elements. It's not too difficult to traverse up parentNodes, checking if data-cid is an attribute.

@Maluen
Copy link
Owner

Maluen commented Jan 23, 2015

and wouldn't be compatible with detached views and Minionette's Regions, which swap views in and out of the DOM without removing them. Even when detached, I still consider these "subviews" of the view.

I get your point, however considering them no longer subviews only on remove basically means that once a subview is added it remains a subview of the same view forever, since remove is the last thing you do.

BUT, we could, in case an existing subview is appended under some other view, change the parent view. Thus this could actually work!

As for the performance on monitoring the DOM, we still need to pay it to find added views, if we don't have some other super clever (general) way to find subviews (adaptors? see below).

Determining when a subview is added to a view is a more difficult problem. I imagine an adaptor would be able to handle this: Some #_onAddSubview can be called when adding. We could extend that to removing a subview (ie. #_onRemoveSubview). It should be very easy to write adaptors to handle both cases.

How this adaptors would work? Are you suggesting changing Backbone itself? (we still have to be retro-compatible / work in most situations).

@jridgewell
Copy link

BUT, we could, in case an existing subview is appended under some other view, change the parent view.

That's what I had in mind.

How this adaptors would work? Are you suggesting changing Backbone itself?

Only changing minimally, to provide the necessary hooks (like the jQuery hooks refactor). Something along these lines:

// Backbone Debugger setup
var Backbone.View = Backbone.View.extend({
    remove: function() {
        this._removeFromParentView();
        Backbone.View.__super__.remove.apply(this, arguments);
    },
    _removeFromParentView: function() {
        // Code to remove references in BB-D
    },
    _addAsSubView: function(parent = null) {
        // Parent would be optional, find it through DOM if not given
        // Code to setup references in BB-D
    }
});

// EG. Minionette Adapter
// Regions trigger an "attach" event when attaching a new subview
// Use this to hook into BB-D
Minionette.Region = Minonette.Region.extend({
    constructor: function() {
        Minionette.Region.__super__.constructor.apply(this, arguments);
        this.on('attach', function(view, region) {
             view._addAsSubview(region._parent);
        });
    }
});

@Maluen
Copy link
Owner

Maluen commented Jan 26, 2015

We can't ask any user to change their Backbone applications, so that's just not feasible, we'll have to monitor the DOM to find additions like we'll have to do to find parents.

@jridgewell
Copy link

We can't ask any user to change their Backbone applications...

I'm not asking anyone to change their code. What I'm proposing is just providing the hooks so an adaptor could be written.

In my example above, the Minionette adaptor wouldn't be written by the end user. It'd be like a plugin to Backbone-Debugger: just include it on the page and it'll handle the synchronizing debugger's subview tree. No code modifications necessary.

@Maluen
Copy link
Owner

Maluen commented Jan 26, 2015

I see, the main project philosophy however is to strive to make it work everywhere with no modifications at all (yes that's not written anywhere), so what you are proposing could be good for things like offering Framework-specific customizations, e.g. customizing View panel with whatever custom Minionette specific content, in case the current app is using it.

For the rest, it should try to provide a general Backbone layer that works everywhere.

But I like your idea of a plugin system, even if intended for other things ;)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants