| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267 | /** * @class FeedViewer.FeedPanel * @extends Ext.panel.Panel * * Shows a list of available feeds. Also has the ability to add/remove and load feeds. * * @constructor * Create a new Feed Panel * @param {Object} config The config object */Ext.define('FeedViewer.FeedPanel', {    extend: 'Ext.panel.Panel',    alias: 'widget.feedpanel',    animCollapse: true,    layout: 'fit',    title: 'Feeds',    initComponent: function(){        Ext.apply(this, {            items: this.createView(),            dockedItems: this.createToolbar()        });        this.createMenu();        this.addEvents(            /**             * @event feedremove Fired when a feed is removed             * @param {FeedPanel} this             * @param {String} title The title of the feed             * @param {String} url The url of the feed             */            'feedremove',            /**             * @event feedselect Fired when a feed is selected             * @param {FeedPanel} this             * @param {String} title The title of the feed             * @param {String} url The url of the feed             */            'feedselect'        );        this.callParent(arguments);    },    /**     * Create the DataView to be used for the feed list.     * @private     * @return {Ext.view.View}     */    createView: function(){        this.view = Ext.create('widget.dataview', {            store: Ext.create('Ext.data.Store', {                model: 'Feed',                data: this.feeds            }),            selModel: {                mode: 'SINGLE',                listeners: {                    scope: this,                    selectionchange: this.onSelectionChange                }            },            listeners: {                scope: this,                contextmenu: this.onContextMenu,                viewready: this.onViewReady            },            trackOver: true,            cls: 'feed-list',            itemSelector: '.feed-list-item',            overItemCls: 'feed-list-item-hover',            tpl: '<tpl for="."><div class="feed-list-item">{title}</div></tpl>'        });        return this.view;    },    onViewReady: function(){        this.view.getSelectionModel().select(this.view.store.first());    },    /**     * Creates the toolbar to be used for controlling feeds.     * @private     * @return {Ext.toolbar.Toolbar}     */    createToolbar: function(){        this.createActions();        this.toolbar = Ext.create('widget.toolbar', {            items: [this.addAction, this.removeAction]        });        return this.toolbar;    },    /**     * Create actions to share between toolbar and menu     * @private     */    createActions: function(){        this.addAction = Ext.create('Ext.Action', {            scope: this,            handler: this.onAddFeedClick,            text: 'Add feed',            iconCls: 'feed-add'        });        this.removeAction = Ext.create('Ext.Action', {            itemId: 'remove',            scope: this,            handler: this.onRemoveFeedClick,            text: 'Remove feed',            iconCls: 'feed-remove'        });    },    /**     * Create the context menu     * @private     */    createMenu: function(){        this.menu = Ext.create('widget.menu', {            items: [{                scope: this,                handler: this.onLoadClick,                text: 'Load feed',                iconCls: 'feed-load'            }, this.removeAction, '-', this.addAction],            listeners: {                hide: function(c){                    c.activeFeed = null;                }            }        });    },    /**     * Used when view selection changes so we can disable toolbar buttons.     * @private     */    onSelectionChange: function(){        var selected = this.getSelectedItem();        this.toolbar.getComponent('remove').setDisabled(!selected);        this.loadFeed(selected);    },    /**     * React to the load feed menu click.     * @private     */    onLoadClick: function(){        this.loadFeed(this.menu.activeFeed);    },    /**     * Loads a feed.     * @private     * @param {Ext.data.Model} rec The feed     */    loadFeed: function(rec){        if (rec) {            this.fireEvent('feedselect', this, rec.get('title'), rec.get('url'));        }    },    /**     * Gets the currently selected record in the view.     * @private     * @return {Ext.data.Model} Returns the selected model. false if nothing is selected.     */    getSelectedItem: function(){        return this.view.getSelectionModel().getSelection()[0] || false;    },    /**     * Listens for the context menu event on the view     * @private     */    onContextMenu: function(view, index, el, event){        var menu = this.menu;        event.stopEvent();        menu.activeFeed = view.store.getAt(index);        menu.showAt(event.getXY());    },    /**     * React to a feed being removed     * @private     */    onRemoveFeedClick: function(){        var active = this.menu.activeFeed || this.getSelectedItem();        this.animateNode(this.view.getNode(active), 1, 0, {            scope: this,            afteranimate: function(){                this.view.store.remove(active);            }        });        this.fireEvent('feedremove', this, active.get('title'), active.get('url'));    },    /**     * React to a feed attempting to be added     * @private     */    onAddFeedClick: function(){        var win = this.addFeedWindow || (this.addFeedWindow = Ext.create('widget.feedwindow', {            listeners: {                scope: this,                feedvalid: this.onFeedValid            }        }));        win.form.getForm().reset();        win.show();    },    /**     * React to a validation on a feed passing     * @private     * @param {FeedViewer.FeedWindow} win     * @param {String} title The title of the feed     * @param {String} url The url of the feed     */    onFeedValid: function(win, title, url){        var view = this.view,            store = view.store,            rec;        rec = store.add({            url: url,            title: title        })[0];        this.animateNode(view.getNode(rec), 0, 1);    },    /**     * Animate a node in the view when it is added/removed     * @private     * @param {Mixed} el The element to animate     * @param {Number} start The start opacity     * @param {Number} end The end opacity     * @param {Object} listeners (optional) Any listeners     */    animateNode: function(el, start, end, listeners){        Ext.create('Ext.fx.Anim', {            target: Ext.get(el),            duration: 500,            from: {                opacity: start            },            to: {                opacity: end            },            listeners: listeners         });    },    // Inherit docs    onDestroy: function(){        this.callParent(arguments);        this.menu.destroy();    }});
 |