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