3 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
4 <title>The source code</title>
5 <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
6 <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
8 <body onload="prettyPrint();">
9 <pre class="prettyprint lang-js">/*!
10 * Ext JS Library 3.3.1
11 * Copyright(c) 2006-2010 Sencha Inc.
12 * licensing@sencha.com
13 * http://www.sencha.com/license
15 <div id="cls-Ext.ux.DataViewTransition"></div>/**
16 * @class Ext.ux.DataViewTransition
18 * @author Ed Spencer (http://extjs.com)
19 * Transition plugin for DataViews
21 Ext.ux.DataViewTransition = Ext.extend(Object, {
23 <div id="prop-Ext.ux.DataViewTransition-defaults"></div>/**
26 * Default configuration options for all DataViewTransition instances
33 <div id="method-Ext.ux.DataViewTransition-constructor"></div>/**
34 * Creates the plugin instance, applies defaults
36 * @param {Object} config Optional config object
38 constructor: function(config) {
39 Ext.apply(this, config || {}, this.defaults);
42 <div id="method-Ext.ux.DataViewTransition-init"></div>/**
43 * Initializes the transition plugin. Overrides the dataview's default refresh function
44 * @param {Ext.DataView} dataview The dataview
46 init: function(dataview) {
47 <div id="prop-Ext.ux.DataViewTransition-dataview"></div>/**
50 * Reference to the DataView this instance is bound to
52 this.dataview = dataview;
54 var idProperty = this.idProperty;
55 dataview.blockRefresh = true;
56 dataview.updateIndexes = dataview.updateIndexes.createSequence(function() {
57 this.getTemplateTarget().select(this.itemSelector).each(function(element, composite, index) {
58 element.id = element.dom.id = String.format("{0}-{1}", dataview.id, store.getAt(index).get(idProperty));
62 <div id="prop-Ext.ux.DataViewTransition-dataviewID"></div>/**
63 * @property dataviewID
65 * The string ID of the DataView component. This is used internally when animating child objects
67 this.dataviewID = dataview.id;
69 <div id="prop-Ext.ux.DataViewTransition-cachedStoreData"></div>/**
70 * @property cachedStoreData
72 * A cache of existing store data, keyed by id. This is used to determine
73 * whether any items were added or removed from the store on data change
75 this.cachedStoreData = {};
77 var store = dataview.store;
79 //cache the data immediately, and again on any load operation
80 this.cacheStoreData(store);
81 store.on('load', this.cacheStoreData, this);
83 store.on('datachanged', function(store) {
84 var parentEl = dataview.getTemplateTarget(),
85 calcItem = store.getAt(0),
86 added = this.getAdded(store),
87 removed = this.getRemoved(store),
88 previous = this.getRemaining(store),
89 existing = Ext.apply({}, previous, added);
92 Ext.each(removed, function(item) {
93 Ext.fly(this.dataviewID + '-' + item.get(this.idProperty)).fadeOut({
95 duration: duration / 1000,
101 if (calcItem == undefined) {
102 this.cacheStoreData(store);
106 var el = parentEl.child("#" + this.dataviewID + "-" + calcItem.get(this.idProperty));
108 //calculate the number of rows and columns we have
109 var itemCount = store.getCount(),
110 itemWidth = el.getMargins('lr') + el.getWidth(),
111 itemHeight = el.getMargins('bt') + el.getHeight(),
112 dvWidth = parentEl.getWidth(),
113 columns = Math.floor(dvWidth / itemWidth),
114 rows = Math.ceil(itemCount / columns),
115 currentRows = Math.ceil(this.getExistingCount() / columns);
117 //make sure the correct styles are applied to the parent element
118 parentEl.applyStyles({
122 // height : Ext.max([rows, currentRows]) * itemHeight,
123 // width : columns * itemWidth
126 //stores the current top and left values for each element (discovered below)
127 var oldPositions = {},
131 //find current positions of each element and save a reference in the elCache
132 Ext.iterate(previous, function(id, item) {
133 var id = item.get(this.idProperty),
134 el = elCache[id] = parentEl.child('#' + this.dataviewID + '-' + id);
137 top : el.getTop() - parentEl.getTop() - el.getMargins('t') - parentEl.getPadding('t'),
138 left: el.getLeft() - parentEl.getLeft() - el.getMargins('l') - parentEl.getPadding('l')
142 //set absolute positioning on all DataView items. We need to set position, left and
143 //top at the same time to avoid any flickering
144 Ext.iterate(previous, function(id, item) {
145 var oldPos = oldPositions[id],
148 if (el.getStyle('position') != 'absolute') {
149 elCache[id].applyStyles({
150 position: 'absolute',
151 left : oldPos.left + "px",
152 top : oldPos.top + "px",
154 //we set the width here to make ListViews work correctly. This is not needed for DataViews
155 width : el.getWidth(!Ext.isIE || Ext.isStrict),
156 height : el.getHeight(!Ext.isIE || Ext.isStrict)
163 Ext.iterate(store.data.items, function(item) {
164 var id = item.get(idProperty),
167 var column = index % columns,
168 row = Math.floor(index / columns),
169 top = row * itemHeight,
170 left = column * itemWidth;
181 var startTime = new Date(),
182 duration = this.duration,
183 dataviewID = this.dataviewID;
185 var doAnimate = function() {
186 var elapsed = new Date() - startTime,
187 fraction = elapsed / duration;
190 for (var id in newPositions) {
191 Ext.fly(dataviewID + '-' + id).applyStyles({
192 top : newPositions[id].top + "px",
193 left: newPositions[id].left + "px"
197 Ext.TaskMgr.stop(task);
200 for (var id in newPositions) {
201 if (!previous[id]) continue;
203 var oldPos = oldPositions[id],
204 newPos = newPositions[id],
207 oldLeft = oldPos.left,
208 newLeft = newPos.left,
209 diffTop = fraction * Math.abs(oldTop - newTop),
210 diffLeft= fraction * Math.abs(oldLeft - newLeft),
211 midTop = oldTop > newTop ? oldTop - diffTop : oldTop + diffTop,
212 midLeft = oldLeft > newLeft ? oldLeft - diffLeft : oldLeft + diffLeft;
214 Ext.fly(dataviewID + '-' + id).applyStyles({
228 Ext.TaskMgr.start(task);
231 Ext.iterate(added, function(id, item) {
232 Ext.fly(this.dataviewID + '-' + item.get(this.idProperty)).applyStyles({
233 top : newPositions[id].top + "px",
234 left: newPositions[id].left + "px"
237 duration: duration / 1000
241 this.cacheStoreData(store);
245 <div id="method-Ext.ux.DataViewTransition-cacheStoreData"></div>/**
246 * Caches the records from a store locally for comparison later
247 * @param {Ext.data.Store} store The store to cache data from
249 cacheStoreData: function(store) {
250 this.cachedStoreData = {};
252 store.each(function(record) {
253 this.cachedStoreData[record.get(this.idProperty)] = record;
257 <div id="method-Ext.ux.DataViewTransition-getExisting"></div>/**
258 * Returns all records that were already in the DataView
259 * @return {Object} All existing records
261 getExisting: function() {
262 return this.cachedStoreData;
265 <div id="method-Ext.ux.DataViewTransition-getExistingCount"></div>/**
266 * Returns the total number of items that are currently visible in the DataView
267 * @return {Number} The number of existing items
269 getExistingCount: function() {
271 items = this.getExisting();
273 for (var k in items) count++;
278 <div id="method-Ext.ux.DataViewTransition-getAdded"></div>/**
279 * Returns all records in the given store that were not already present
280 * @param {Ext.data.Store} store The updated store instance
281 * @return {Object} Object of records not already present in the dataview in format {id: record}
283 getAdded: function(store) {
286 store.each(function(record) {
287 if (this.cachedStoreData[record.get(this.idProperty)] == undefined) {
288 added[record.get(this.idProperty)] = record;
295 <div id="method-Ext.ux.DataViewTransition-getRemoved"></div>/**
296 * Returns all records that are present in the DataView but not the new store
297 * @param {Ext.data.Store} store The updated store instance
298 * @return {Array} Array of records that used to be present
300 getRemoved: function(store) {
303 for (var id in this.cachedStoreData) {
304 if (store.findExact(this.idProperty, Number(id)) == -1) removed.push(this.cachedStoreData[id]);
310 <div id="method-Ext.ux.DataViewTransition-getRemaining"></div>/**
311 * Returns all records that are already present and are still present in the new store
312 * @param {Ext.data.Store} store The updated store instance
313 * @return {Object} Object of records that are still present from last time in format {id: record}
315 getRemaining: function(store) {
318 store.each(function(record) {
319 if (this.cachedStoreData[record.get(this.idProperty)] != undefined) {
320 remaining[record.get(this.idProperty)] = record;