Upgrade to ExtJS 4.0.7 - Released 10/19/2011
[extjs.git] / examples / 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         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         return this.view;
92     },
93
94     onViewReady: function(){
95         this.view.getSelectionModel().select(this.view.store.first());
96     },
97
98     /**
99      * Creates the toolbar to be used for controlling feeds.
100      * @private
101      * @return {Ext.toolbar.Toolbar}
102      */
103     createToolbar: function(){
104         this.createActions();
105         this.toolbar = Ext.create('widget.toolbar', {
106             items: [this.addAction, this.removeAction]
107         });
108         return this.toolbar;
109     },
110
111     /**
112      * Create actions to share between toolbar and menu
113      * @private
114      */
115     createActions: function(){
116         this.addAction = Ext.create('Ext.Action', {
117             scope: this,
118             handler: this.onAddFeedClick,
119             text: 'Add feed',
120             iconCls: 'feed-add'
121         });
122
123         this.removeAction = Ext.create('Ext.Action', {
124             itemId: 'remove',
125             scope: this,
126             handler: this.onRemoveFeedClick,
127             text: 'Remove feed',
128             iconCls: 'feed-remove'
129         });
130     },
131
132     /**
133      * Create the context menu
134      * @private
135      */
136     createMenu: function(){
137         this.menu = Ext.create('widget.menu', {
138             items: [{
139                 scope: this,
140                 handler: this.onLoadClick,
141                 text: 'Load feed',
142                 iconCls: 'feed-load'
143             }, this.removeAction, '-', this.addAction],
144             listeners: {
145                 hide: function(c){
146                     c.activeFeed = null;
147                 }
148             }
149         });
150     },
151
152     /**
153      * Used when view selection changes so we can disable toolbar buttons.
154      * @private
155      */
156     onSelectionChange: function(){
157         var selected = this.getSelectedItem();
158         this.toolbar.getComponent('remove').setDisabled(!selected);
159         this.loadFeed(selected);
160     },
161
162     /**
163      * React to the load feed menu click.
164      * @private
165      */
166     onLoadClick: function(){
167         this.loadFeed(this.menu.activeFeed);
168     },
169
170     /**
171      * Loads a feed.
172      * @private
173      * @param {Ext.data.Model} rec The feed
174      */
175     loadFeed: function(rec){
176         if (rec) {
177             this.fireEvent('feedselect', this, rec.get('title'), rec.get('url'));
178         }
179     },
180
181     /**
182      * Gets the currently selected record in the view.
183      * @private
184      * @return {Ext.data.Model} Returns the selected model. false if nothing is selected.
185      */
186     getSelectedItem: function(){
187         return this.view.getSelectionModel().getSelection()[0] || false;
188     },
189
190     /**
191      * Listens for the context menu event on the view
192      * @private
193      */
194     onContextMenu: function(view, index, el, event){
195         var menu = this.menu;
196
197         event.stopEvent();
198         menu.activeFeed = view.store.getAt(index);
199         menu.showAt(event.getXY());
200     },
201
202     /**
203      * React to a feed being removed
204      * @private
205      */
206     onRemoveFeedClick: function(){
207         var active = this.menu.activeFeed || this.getSelectedItem();
208
209
210         this.animateNode(this.view.getNode(active), 1, 0, {
211             scope: this,
212             afteranimate: function(){
213                 this.view.store.remove(active);
214             }
215         });
216         this.fireEvent('feedremove', this, active.get('title'), active.get('url'));
217
218     },
219
220     /**
221      * React to a feed attempting to be added
222      * @private
223      */
224     onAddFeedClick: function(){
225         var win = Ext.create('widget.feedwindow', {
226             listeners: {
227                 scope: this,
228                 feedvalid: this.onFeedValid
229             }
230         });
231         win.show();
232     },
233
234     /**
235      * React to a validation on a feed passing
236      * @private
237      * @param {FeedViewer.FeedWindow} win
238      * @param {String} title The title of the feed
239      * @param {String} url The url of the feed
240      */
241     onFeedValid: function(win, title, url){
242         var view = this.view,
243             store = view.store,
244             rec;
245
246         rec = store.add({
247             url: url,
248             title: title
249         })[0];
250         this.animateNode(view.getNode(rec), 0, 1);
251     },
252
253     /**
254      * Animate a node in the view when it is added/removed
255      * @private
256      * @param {Mixed} el The element to animate
257      * @param {Number} start The start opacity
258      * @param {Number} end The end opacity
259      * @param {Object} listeners (optional) Any listeners
260      */
261     animateNode: function(el, start, end, listeners){
262         Ext.create('Ext.fx.Anim', {
263             target: Ext.get(el),
264             duration: 500,
265             from: {
266                 opacity: start
267             },
268             to: {
269                 opacity: end
270             },
271             listeners: listeners
272          });
273     },
274
275     // Inherit docs
276     onDestroy: function(){
277         this.callParent(arguments);
278         this.menu.destroy();
279     }
280 });
281