Omar Masri
Omar Masri

Reputation: 81

Famo.us - How to delete view with surfaces on it

Issue:

my famo.us app allows a user to add many "card" views on a work area. These cards are draggable, added directly to a ContainerSurface, and not in any particular layout.

The cards have a delete button, which when pressed deletes the card.

Currently I "delete" the view using

theCardView.render = function(){ return null; }

This works in removing the view and the surfaces on it from the work area;however, it has a strange side-effect. When I add another card the delete button surface is under the header surface that it normally sits on.

If I add a 2nd card, then the delete button on this 2nd card is displayed properly.

When I look at the DOM after the delete I see that divs for the surfaces on my view are still there, but empty

Is there a better/cleaner way to "delete" a view? Or is there something else I need to do to ensure the DOM is cleaned up?

I can get around this issue by setting the z-index of the button to 1; however this causes a problem when you drag the cards around over each other - The button is always on top of all the other cards.

Code of how I add the CardViews

this._eventInput.on('add-cards', function() {
 for (var i=0; i < that.cardPicker.selected.length ;i++){
            var x = new CardView({data:that.cardPicker.selected[i]});
            that.subscribe(x);
            that.cards.push(x);
            that.contentContainer.add(x);   
        }
  });

Code of how I delete the view

this._eventInput.on('delete-card',function(e){
        // e is the CardView object that has the button that was clicked
        removeFromArray(that.cards,e);
        e.render = function(){ return null; }
    });

Code for the view constructor

function CardView(data) {
    View.apply(this, arguments);
    that = this;

    this.dbdata = data.data;

    this.layout = new HeaderFooterLayout({
        headerSize: 43,
        footerSize: 0
    });

    // Header
    var oname = this.dbdata.dbname+"."+this.dbdata.table.name;
    this.headerSurface = new Surface({size: [275, 43],
               content: oname
              ,properties: {
                     backgroundColor:'rgb(51, 51, 51)'
                    ,color:'white'
                    ,paddingTop:'10px'
                    ,paddingLeft:'10px'
                }
            });
    this.draggable = new Draggable();
    this.headerSurface.pipe(this.draggable);
    this.draggable.activate();
    this.layout.header.add(this.headerSurface);


    // Header delete button
    this.deletebtn = new Surface({size: [55, 40],
               content: '<button type="button" class="btn btn-default">del</button>'
              ,properties:{
              } 
            });
    this.mod = new Modifier({
                transform: Transform.translate(215, 0, 0)
            });     
    this.layout.header.add(this.mod).add(this.deletebtn);
    this.deletebtn.pp = this;
    this.deletebtn.on('click', function() {
      that._eventOutput.emit('delete-card',this.pp);
    });


    this.layout.content.add(new Surface({size: [275, 300],
                                      properties: {
                                            backgroundColor:'rgb(236, 236, 236)'
                                        }
                                    }));

    // a modifier that centers the surface
    this.centerModifier = new Modifier({
      origin : [0.5, 0.5],
      align: [0.5, 0.5]
    });

    this.add(this.draggable).add(this.centerModifier).add(this.layout);
}

Upvotes: 1

Views: 90

Answers (1)

Joseph
Joseph

Reputation: 539

So a couple of things:

Deleting surfaces from the context
When calling context.add() a RenderNode is created and returned, all subsquent views/modifiers/etc added to this RenderNode create additional nodes. The render node is responsible for reporting to the context what elements it contains (each surface/modifier/etc is responsible for reporting what it represents).

To clear all of the elements from a render node do something like the following

var myView = new View();
var context = Engine.createContext();
myView.node = context.add(myView); // Now the context knows about your view
myView.node.set({}); // Now the context doesn't

Now the problem remains that the parent node/context will maintain a reference to the original node even though it doesn't contain anything. This is something that is known and are working towards a solution.

Dealing with z-index
If you wanted to set the z-index of the button so that it is above the surface itself, you can also modify the z-index of the focused view. This can be accomplished by maintaining a reference to the modifier of the specific view and increasing the z-index. You will have to ensure the the change in z-index flows down into each element.

I would go for the first solution and delete the elements from the render node.

Upvotes: 1

Related Questions