JSFiddle - React, Tailwind, and code Playground
HTML
<script src="//canjs.com/release/2.0.3/can.jquery.js"></script>
<script src="https://rawgithub.com/ai/transition-events/master/lib/transition-events.js"></script>
<script type="text/mustache" id="something">
<button name="add" can-click="addItem">Add</button>
<hr/>
{{#each items}}
<div class="something {{animationState}}" data-token="{{token}}">
<h1>{{title}}</h1>
<button name="close" can-click="removeItem">Close</button>
</div>
{{/each}}
</script>
CSS
.something
{
border-bottom: 1px solid silver;
padding-bottom: 1em;
}
.something.removing
{
opacity: 0;
transition: 2s opacity;
-moz-transition: 2s opacity;
-webkit-transition: 2s opacity;
}
JavaScript
can.Component.extend(
{
tag: "something",
template: can.view("#something"),
init: function(element, options)
{
this.scope.attr( "element", can.$(element) );
can.batch.start();
this.scope.addItem();
this.scope.addItem();
can.batch.stop();
},
scope:
{
count: 0,
element: null,
items: [],
addItem: function()
{
this.items.push(
{
title: "Item " + (++this.count),
token: (new Date().getTime() * Math.random()).toString().replace(".",""),
animationState: ""
});
},
getItemInfo: function(token)
{
var info = null;
this.items.forEach( function(listElement, listIndex, list)
{
if (listElement.token === token)
{
info = {
domElement: this.element.find("[data-token="+token+"]"),
listElement: listElement,
listIndex: listIndex,
list: list
};
// Kill loop
return false;
}
}, this);
return info;
},
removeItem: function(token)
{
// If called with a declarative can-event
if (typeof token !== "string")
{
token = token.attr("token");
}
var item = this.getItemInfo(token);
var proxy = this;
item.listElement.attr("animationState", "removing");
item.domElement.afterTransition(function(event)
{
proxy.items.splice( proxy.getItemInfo(token).listIndex, 1 );
});
}
},
events:{}
});
$("body").append( can.view.mustache("<something/>") );