Reputation: 81
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
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