| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356 | <!DOCTYPE html><html><head>  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />  <title>The source code</title>  <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />  <script type="text/javascript" src="../resources/prettify/prettify.js"></script>  <style type="text/css">    .highlight { display: block; background-color: #ddd; }  </style>  <script type="text/javascript">    function highlight() {      document.getElementById(location.hash.replace(/#/, "")).className = "highlight";    }  </script></head><body onload="prettyPrint(); highlight();">  <pre class="prettyprint lang-js"><span id='Ext-ux-DataView-Animated'>/**</span> * @author Ed Spencer (http://sencha.com) * Transition plugin for DataViews */Ext.define('Ext.ux.DataView.Animated', {<span id='Ext-ux-DataView-Animated-property-defaults'>    /**</span>     * @property defaults     * @type Object     * Default configuration options for all DataViewTransition instances     */    defaults: {        duration  : 750,        idProperty: 'id'    },    <span id='Ext-ux-DataView-Animated-method-constructor'>    /**</span>     * Creates the plugin instance, applies defaults     * @constructor     * @param {Object} config Optional config object     */    constructor: function(config) {        Ext.apply(this, config || {}, this.defaults);    },<span id='Ext-ux-DataView-Animated-method-init'>    /**</span>     * Initializes the transition plugin. Overrides the dataview's default refresh function     * @param {Ext.view.View} dataview The dataview     */    init: function(dataview) {<span id='Ext-ux-DataView-Animated-property-dataview'>        /**</span>         * @property dataview         * @type Ext.view.View         * Reference to the DataView this instance is bound to         */        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);        <span id='Ext-ux-DataView-Animated-property-dataviewID'>        /**</span>         * @property dataviewID         * @type String         * The string ID of the DataView component. This is used internally when animating child objects         */        this.dataviewID = dataview.id;        <span id='Ext-ux-DataView-Animated-property-cachedStoreData'>        /**</span>         * @property cachedStoreData         * @type Object         * A cache of existing store data, keyed by id. This is used to determine         * whether any items were added or removed from the store on data change         */        this.cachedStoreData = {};                //catch the store data with the snapshot immediately        this.cacheStoreData(store.data || store.snapshot);        dataview.on('resize', function() {            var store = dataview.store;            if (store.getCount() > 0) {                // reDraw.call(this, store);            }        }, 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);                        //hide old items            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);                        //store is empty            if (calcItem == undefined) {                this.cacheStoreData(store);                return;            }                        this.cacheStoreData(store);                        var el = Ext.get(this.dataviewID + "-" + calcItem.internalId);                        //if there is nothing rendered, force a refresh and return. This happens when loading asynchronously (was not            //covered correctly in previous versions, which only accepted local data)            if (!el) {                dataview.refresh();                return true;            }                        //calculate the number of rows and columns we have            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);                        //stores the current top and left values for each element (discovered below)            var oldPositions = {},                newPositions = {},                elCache      = {};                        //find current positions of each element and save a reference in the 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);                        //make sure the correct styles are applied to the parent element            parentEl.applyStyles({                display : 'block',                position: 'relative'            });                        //set absolute positioning on all DataView items. We need to set position, left and             //top at the same time to avoid any flickering            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"                    });                }            });                        //get new positions            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);                        //do the movements            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 {                    //move each item                    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);                        //show new items            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);        }    },    <span id='Ext-ux-DataView-Animated-method-cacheStoreData'>    /**</span>     * Caches the records from a store locally for comparison later     * @param {Ext.data.Store} store The store to cache data from     */    cacheStoreData: function(store) {        this.cachedStoreData = {};                store.each(function(record) {             this.cachedStoreData[record.internalId] = record;        }, this);    },    <span id='Ext-ux-DataView-Animated-method-getExisting'>    /**</span>     * Returns all records that were already in the DataView     * @return {Object} All existing records     */    getExisting: function() {        return this.cachedStoreData;    },    <span id='Ext-ux-DataView-Animated-method-getExistingCount'>    /**</span>     * Returns the total number of items that are currently visible in the DataView     * @return {Number} The number of existing items     */    getExistingCount: function() {        var count = 0,            items = this.getExisting();                for (var k in items) {            count++;        }                return count;    },    <span id='Ext-ux-DataView-Animated-method-getAdded'>    /**</span>     * Returns all records in the given store that were not already present     * @param {Ext.data.Store} store The updated store instance     * @return {Object} Object of records not already present in the dataview in format {id: record}     */    getAdded: function(store) {        var added = {};                store.each(function(record) {            if (this.cachedStoreData[record.internalId] == undefined) {                added[record.internalId] = record;            }        }, this);                return added;    },    <span id='Ext-ux-DataView-Animated-method-getRemoved'>    /**</span>     * Returns all records that are present in the DataView but not the new store     * @param {Ext.data.Store} store The updated store instance     * @return {Array} Array of records that used to be present     */    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;    },    <span id='Ext-ux-DataView-Animated-method-getRemaining'>    /**</span>     * Returns all records that are already present and are still present in the new store     * @param {Ext.data.Store} store The updated store instance     * @return {Object} Object of records that are still present from last time in format {id: record}     */    getRemaining: function(store) {        var remaining = {};        store.each(function(record) {            if (this.cachedStoreData[record.internalId] != undefined) {                remaining[record.internalId] = record;            }        }, this);                return remaining;    }});</pre></body></html>
 |