"Isotope" with KO

Boxes are animated when added or removed

by ScottRippey

HTML

<script src="//cdnjs.cloudflare.com/ajax/libs/mootools/1.4.5/mootools-core-full-compat-yc.js"></script>
<button data-bind="click: addItem">Add Item</button>
<div data-bind="foreach: {data: items, beforeMove: storePosition, afterMove: movePosition }"><div class="box" data-bind="text: text, click: function() { $parent.items.remove($data)}"></div></div>

CSS

.box {
    width: 100px; height: 100px; 
    float: left;
    margin: 0 10px 10px 0;
    border: 1px solid hsl(200,100%,50%);
    background-color: hsl(200,100%,90%);
}

JavaScript

Fx.implement({
    options: {
        duration: 500
        ,transition: 'quad:out'
    }
});

var randomItems = [ 'scott','william','rippey' ], i = 0;

window.viewModel = {
    items: ko.observableArray( )
    ,addItem: function() {
        var text = randomItems[i++ % randomItems.length] + " " + i;
        this.items.splice(2, 0, {
            text: text
        });
    }
};

for (var x = 0; x < 5; x++) {
    viewModel.addItem();
}


window.storePosition = function(element, i, data) {
    var p =element.getPosition();
    element.store('position', p);
};
window.movePosition = function(element, i, data) {
    var oldP = element.retrieve('position');
    var newP = element.getPosition();
    element.setStyles({
        position: 'relative'
        ,top: -(newP.y - oldP.y)
        ,left: -(newP.x - oldP.x)
    });
    element.morph({
        top: 0, left: 0
    });
}
window.fadeThisGuyOut = function(element, i, data) {
    element.morph({ opacity: 0, height: 0, width: 0, margin: 0 });
    element.get('morph').chain(function() {
        element.destroy();
    });
}
window.fadeThisGuyIn = function(element, i, data) {
    element.setStyles({ opacity: 0 }).morph({ opacity: 1 });
}


ko.applyBindings(viewModel);