Ext.define('Ext.ux.DataView.Animated', {
defaults: {
duration : 750,
idProperty: 'id'
},
constructor: function(config) {
Ext.apply(this, config || {}, this.defaults);
},
init: function(dataview) {
this.dataview = dataview;
var idProperty = this.idProperty,
store = dataview.store;
dataview.blockRefresh = true;
dataview.updateIndexes = Ext.Function.createSequence(dataview.updateIndexes, function() {
this.getTargetEl().select(this.itemSelector).each(function(element, composite, index) {
element.id = element.dom.id = Ext.util.Format.format("{0}-{1}", dataview.id, store.getAt(index).internalId);
}, this);
}, dataview);
this.dataviewID = dataview.id;
this.cachedStoreData = {};
this.cacheStoreData(store.data || store.snapshot);
dataview.on('resize', function() {
var store = dataview.store;
if (store.getCount() > 0) {
}
}, this);
dataview.store.on('datachanged', reDraw, this);
function reDraw(store) {
var parentEl = dataview.getTargetEl(),
calcItem = store.getAt(0),
added = this.getAdded(store),
removed = this.getRemoved(store),
previous = this.getRemaining(store),
existing = Ext.apply({}, previous, added);
Ext.each(removed, function(item) {
var id = this.dataviewID + '-' + item.internalId;
Ext.fly(id).animate({
remove : false,
duration: duration,
opacity : 0,
useDisplay: true,
callback: function() {
Ext.fly(id).setDisplayed(false);
}
});
}, this);
if (calcItem == undefined) {
this.cacheStoreData(store);
return;
}
this.cacheStoreData(store);
var el = Ext.get(this.dataviewID + "-" + calcItem.internalId);
if (!el) {
dataview.refresh();
return true;
}
var itemCount = store.getCount(),
itemWidth = el.getMargin('lr') + el.getWidth(),
itemHeight = el.getMargin('bt') + el.getHeight(),
dvWidth = parentEl.getWidth(),
columns = Math.floor(dvWidth / itemWidth),
rows = Math.ceil(itemCount / columns),
currentRows = Math.ceil(this.getExistingCount() / columns);
var oldPositions = {},
newPositions = {},
elCache = {};
Ext.iterate(previous, function(id, item) {
var id = item.internalId,
el = elCache[id] = Ext.get(this.dataviewID + '-' + id);
oldPositions[id] = {
top : el.getTop() - parentEl.getTop() - el.getMargin('t') - parentEl.getPadding('t'),
left: el.getLeft() - parentEl.getLeft() - el.getMargin('l') - parentEl.getPadding('l')
};
}, this);
parentEl.applyStyles({
display : 'block',
position: 'relative'
});
Ext.iterate(previous, function(id, item) {
var oldPos = oldPositions[id],
el = elCache[id];
if (el.getStyle('position') != 'absolute') {
elCache[id].applyStyles({
position: 'absolute',
left : oldPos.left + "px",
top : oldPos.top + "px"
});
}
});
var index = 0;
Ext.iterate(store.data.items, function(item) {
var id = item.internalId,
el = elCache[id];
var column = index % columns,
row = Math.floor(index / columns),
top = row * itemHeight,
left = column * itemWidth;
newPositions[id] = {
top : top,
left: left
};
index ++;
}, this);
var startTime = new Date(),
duration = this.duration,
dataviewID = this.dataviewID;
var doAnimate = function() {
var elapsed = new Date() - startTime,
fraction = elapsed / duration,
id;
if (fraction >= 1) {
for (id in newPositions) {
Ext.fly(dataviewID + '-' + id).applyStyles({
top : newPositions[id].top + "px",
left: newPositions[id].left + "px"
});
}
Ext.TaskManager.stop(task);
} else {
for (id in newPositions) {
if (!previous[id]) {
continue;
}
var oldPos = oldPositions[id],
newPos = newPositions[id],
oldTop = oldPos.top,
newTop = newPos.top,
oldLeft = oldPos.left,
newLeft = newPos.left,
diffTop = fraction * Math.abs(oldTop - newTop),
diffLeft= fraction * Math.abs(oldLeft - newLeft),
midTop = oldTop > newTop ? oldTop - diffTop : oldTop + diffTop,
midLeft = oldLeft > newLeft ? oldLeft - diffLeft : oldLeft + diffLeft;
Ext.fly(dataviewID + '-' + id).applyStyles({
top : midTop + "px",
left: midLeft + "px"
}).setDisplayed(true);
}
}
};
var task = {
run : doAnimate,
interval: 20,
scope : this
};
Ext.TaskManager.start(task);
Ext.iterate(added, function(id, item) {
Ext.fly(this.dataviewID + '-' + item.internalId).applyStyles({
top : newPositions[item.internalId].top + "px",
left : newPositions[item.internalId].left + "px"
}).setDisplayed(true);
Ext.fly(this.dataviewID + '-' + item.internalId).animate({
remove : false,
duration: duration,
opacity : 1
});
}, this);
this.cacheStoreData(store);
}
},
cacheStoreData: function(store) {
this.cachedStoreData = {};
store.each(function(record) {
this.cachedStoreData[record.internalId] = record;
}, this);
},
getExisting: function() {
return this.cachedStoreData;
},
getExistingCount: function() {
var count = 0,
items = this.getExisting();
for (var k in items) {
count++;
}
return count;
},
getAdded: function(store) {
var added = {};
store.each(function(record) {
if (this.cachedStoreData[record.internalId] == undefined) {
added[record.internalId] = record;
}
}, this);
return added;
},
getRemoved: function(store) {
var removed = [],
id;
for (id in this.cachedStoreData) {
if (store.findBy(function(record) {return record.internalId == id;}) == -1) {
removed.push(this.cachedStoreData[id]);
}
}
return removed;
},
getRemaining: function(store) {
var remaining = {};
store.each(function(record) {
if (this.cachedStoreData[record.internalId] != undefined) {
remaining[record.internalId] = record;
}
}, this);
return remaining;
}
});