Upgrade to ExtJS 4.0.7 - Released 10/19/2011
[extjs.git] / examples / key-feed-viewer / viewer / FeedPanel.js
1 /*
2
3 This file is part of Ext JS 4
4
5 Copyright (c) 2011 Sencha Inc
6
7 Contact:  http://www.sencha.com/contact
8
9 GNU General Public License Usage
10 This file may be used under the terms of the GNU General Public License version 3.0 as published by the Free Software Foundation and appearing in the file LICENSE included in the packaging of this file.  Please review the following information to ensure the GNU General Public License version 3.0 requirements will be met: http://www.gnu.org/copyleft/gpl.html.
11
12 If you are unsure which license is appropriate for your use, please contact the sales department at http://www.sencha.com/contact.
13
14 */
15 /**
16  * @class FeedViewer.FeedPanel
17  * @extends Ext.panel.Panel
18  *
19  * Shows a list of available feeds. Also has the ability to add/remove and load feeds.
20  *
21  * @constructor
22  * Create a new Feed Panel
23  * @param {Object} config The config object
24  */
25
26 Ext.define('FeedViewer.FeedPanel', {
27     extend: 'Ext.panel.Panel',
28
29     alias: 'widget.feedpanel',
30
31     animCollapse: true,
32     layout: 'fit',
33     title: 'Feeds',
34
35     initComponent: function(){
36         Ext.apply(this, {
37             items: this.createView(),
38             dockedItems: [this.createToolbar()]
39         });
40         this.createMenu();
41         this.addEvents(
42             /**
43              * @event feedremove Fired when a feed is removed
44              * @param {FeedPanel} this
45              * @param {String} title The title of the feed
46              * @param {String} url The url of the feed
47              */
48             'feedremove',
49
50             /**
51              * @event feedselect Fired when a feed is selected
52              * @param {FeedPanel} this
53              * @param {String} title The title of the feed
54              * @param {String} url The url of the feed
55              */
56             'feedselect'
57         );
58
59         this.callParent(arguments);
60     },
61
62     /**
63      * Create the DataView to be used for the feed list.
64      * @private
65      * @return {Ext.view.View}
66      */
67     createView: function(){
68         var view = this.view = Ext.create('widget.dataview', {
69             store: Ext.create('Ext.data.Store', {
70                 model: 'Feed',
71                 data: this.feeds
72             }),
73             selModel: {
74                 mode: 'SINGLE',
75                 listeners: {
76                     scope: this,
77                     selectionchange: this.onSelectionChange
78                 }
79             },
80             listeners: {
81                 scope: this,
82                 contextmenu: this.onContextMenu,
83                 viewready: this.onViewReady
84             },
85             trackOver: true,
86             cls: 'feed-list',
87             itemSelector: '.feed-list-item',
88             overItemCls: 'feed-list-item-hover',
89             tpl: '<tpl for="."><div class="feed-list-item">{title}</div></tpl>'
90         });
91
92         view.on('render', function() {
93
94         }, this);
95         return this.view;
96     },
97
98     onViewReady: function(){
99         this.view.getSelectionModel().select(this.view.store.first());
100     },
101
102     /**
103      * Creates the toolbar to be used for controlling feeds.
104      * @private
105      * @return {Ext.toolbar.Toolbar}
106      */
107     createToolbar: function(){
108         this.createActions();
109         this.toolbar = Ext.create('widget.toolbar', {
110             items: [this.addAction, this.removeAction]
111         });
112         return this.toolbar;
113     },
114
115     /**
116      * Create actions to share between toolbar and menu
117      * @private
118      */
119     createActions: function(){
120         this.addAction = Ext.create('Ext.Action', {
121             scope: this,
122             handler: this.onAddFeedClick,
123             text: 'Add feed',
124             iconCls: 'feed-add'
125         });
126
127         this.removeAction = Ext.create('Ext.Action', {
128             itemId: 'remove',
129             scope: this,
130             handler: this.onRemoveFeedClick,
131             text: 'Remove feed',
132             iconCls: 'feed-remove'
133         });
134     },
135
136     /**
137      * Create the context menu
138      * @private
139      */
140     createMenu: function(){
141         this.menu = Ext.create('widget.menu', {
142             items: [{
143                 scope: this,
144                 handler: this.onLoadClick,
145                 text: 'Load feed',
146                 iconCls: 'feed-load'
147             }, this.removeAction, '-', this.addAction],
148             listeners: {
149                 hide: function(c){
150                     c.activeFeed = null;
151                 }
152             }
153         });
154     },
155
156     /**
157      * Used when view selection changes so we can disable toolbar buttons.
158      * @private
159      */
160     onSelectionChange: function(){
161         var selected = this.getSelectedItem();
162         this.toolbar.getComponent('remove').setDisabled(!selected);
163         this.loadFeed(selected);
164     },
165
166     /**
167      * React to the load feed menu click.
168      * @private
169      */
170     onLoadClick: function(){
171         this.loadFeed(this.menu.activeFeed);
172     },
173
174     /**
175      * Loads a feed.
176      * @private
177      * @param {Ext.data.Model} rec The feed
178      */
179     loadFeed: function(rec){
180         if (rec) {
181             this.fireEvent('feedselect', this, rec.get('title'), rec.get('url'));
182         }
183     },
184
185     /**
186      * Gets the currently selected record in the view.
187      * @private
188      * @return {Ext.data.Model} Returns the selected model. false if nothing is selected.
189      */
190     getSelectedItem: function(){
191         return this.view.getSelectionModel().getSelection()[0] || false;
192     },
193
194     /**
195      * Listens for the context menu event on the view
196      * @private
197      */
198     onContextMenu: function(view, index, el, event){
199         var menu = this.menu;
200
201         event.stopEvent();
202         menu.activeFeed = view.store.getAt(index);
203         menu.showAt(event.getXY());
204     },
205
206     /**
207      * React to a feed being removed
208      * @private
209      */
210     onRemoveFeedClick: function(){
211         var active = this.menu.activeFeed || this.getSelectedItem();
212
213
214         this.animateNode(this.view.getNode(active), 1, 0, {
215             scope: this,
216             afteranimate: function(){
217                 this.view.store.remove(active);
218             }
219         });
220         this.fireEvent('feedremove', this, active.get('title'), active.get('url'));
221
222     },
223
224     /**
225      * React to a feed attempting to be added
226      * @private
227      */
228     onAddFeedClick: function(){
229         var win = Ext.create('widget.feedwindow', {
230             listeners: {
231                 scope: this,
232                 feedvalid: this.onFeedValid
233             }
234         });
235         win.show();
236     },
237
238     /**
239      * React to a validation on a feed passing
240      * @private
241      * @param {FeedViewer.FeedWindow} win
242      * @param {String} title The title of the feed
243      * @param {String} url The url of the feed
244      */
245     onFeedValid: function(win, title, url){
246         var view = this.view,
247             store = view.store,
248             rec;
249
250         rec = store.add({
251             url: url,
252             title: title
253         })[0];
254         this.animateNode(view.getNode(rec), 0, 1);
255     },
256
257     /**
258      * Animate a node in the view when it is added/removed
259      * @private
260      * @param {Mixed} el The element to animate
261      * @param {Number} start The start opacity
262      * @param {Number} end The end opacity
263      * @param {Object} listeners (optional) Any listeners
264      */
265     animateNode: function(el, start, end, listeners){
266         Ext.create('Ext.fx.Anim', {
267             target: Ext.get(el),
268             duration: 500,
269             from: {
270                 opacity: start
271             },
272             to: {
273                 opacity: end
274             },
275             listeners: listeners
276          });
277     },
278
279     // Inherit docs
280     onDestroy: function(){
281         Ext.destroy(
282             this.viewNav,
283             this.menu
284         );
285         this.callParent(arguments);
286     }
287 });
288