FeedPanel.js 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. /**
  2. * @class FeedViewer.FeedPanel
  3. * @extends Ext.panel.Panel
  4. *
  5. * Shows a list of available feeds. Also has the ability to add/remove and load feeds.
  6. *
  7. * @constructor
  8. * Create a new Feed Panel
  9. * @param {Object} config The config object
  10. */
  11. Ext.define('FeedViewer.FeedPanel', {
  12. extend: 'Ext.panel.Panel',
  13. alias: 'widget.feedpanel',
  14. animCollapse: true,
  15. layout: 'fit',
  16. title: 'Feeds',
  17. initComponent: function(){
  18. Ext.apply(this, {
  19. items: this.createView(),
  20. dockedItems: this.createToolbar()
  21. });
  22. this.createMenu();
  23. this.addEvents(
  24. /**
  25. * @event feedremove Fired when a feed is removed
  26. * @param {FeedPanel} this
  27. * @param {String} title The title of the feed
  28. * @param {String} url The url of the feed
  29. */
  30. 'feedremove',
  31. /**
  32. * @event feedselect Fired when a feed is selected
  33. * @param {FeedPanel} this
  34. * @param {String} title The title of the feed
  35. * @param {String} url The url of the feed
  36. */
  37. 'feedselect'
  38. );
  39. this.callParent(arguments);
  40. },
  41. /**
  42. * Create the DataView to be used for the feed list.
  43. * @private
  44. * @return {Ext.view.View}
  45. */
  46. createView: function(){
  47. this.view = Ext.create('widget.dataview', {
  48. store: Ext.create('Ext.data.Store', {
  49. model: 'Feed',
  50. data: this.feeds
  51. }),
  52. selModel: {
  53. mode: 'SINGLE',
  54. listeners: {
  55. scope: this,
  56. selectionchange: this.onSelectionChange
  57. }
  58. },
  59. listeners: {
  60. scope: this,
  61. contextmenu: this.onContextMenu,
  62. viewready: this.onViewReady
  63. },
  64. trackOver: true,
  65. cls: 'feed-list',
  66. itemSelector: '.feed-list-item',
  67. overItemCls: 'feed-list-item-hover',
  68. tpl: '<tpl for="."><div class="feed-list-item">{title}</div></tpl>'
  69. });
  70. return this.view;
  71. },
  72. onViewReady: function(){
  73. this.view.getSelectionModel().select(this.view.store.first());
  74. },
  75. /**
  76. * Creates the toolbar to be used for controlling feeds.
  77. * @private
  78. * @return {Ext.toolbar.Toolbar}
  79. */
  80. createToolbar: function(){
  81. this.createActions();
  82. this.toolbar = Ext.create('widget.toolbar', {
  83. items: [this.addAction, this.removeAction]
  84. });
  85. return this.toolbar;
  86. },
  87. /**
  88. * Create actions to share between toolbar and menu
  89. * @private
  90. */
  91. createActions: function(){
  92. this.addAction = Ext.create('Ext.Action', {
  93. scope: this,
  94. handler: this.onAddFeedClick,
  95. text: 'Add feed',
  96. iconCls: 'feed-add'
  97. });
  98. this.removeAction = Ext.create('Ext.Action', {
  99. itemId: 'remove',
  100. scope: this,
  101. handler: this.onRemoveFeedClick,
  102. text: 'Remove feed',
  103. iconCls: 'feed-remove'
  104. });
  105. },
  106. /**
  107. * Create the context menu
  108. * @private
  109. */
  110. createMenu: function(){
  111. this.menu = Ext.create('widget.menu', {
  112. items: [{
  113. scope: this,
  114. handler: this.onLoadClick,
  115. text: 'Load feed',
  116. iconCls: 'feed-load'
  117. }, this.removeAction, '-', this.addAction],
  118. listeners: {
  119. hide: function(c){
  120. c.activeFeed = null;
  121. }
  122. }
  123. });
  124. },
  125. /**
  126. * Used when view selection changes so we can disable toolbar buttons.
  127. * @private
  128. */
  129. onSelectionChange: function(){
  130. var selected = this.getSelectedItem();
  131. this.toolbar.getComponent('remove').setDisabled(!selected);
  132. this.loadFeed(selected);
  133. },
  134. /**
  135. * React to the load feed menu click.
  136. * @private
  137. */
  138. onLoadClick: function(){
  139. this.loadFeed(this.menu.activeFeed);
  140. },
  141. /**
  142. * Loads a feed.
  143. * @private
  144. * @param {Ext.data.Model} rec The feed
  145. */
  146. loadFeed: function(rec){
  147. if (rec) {
  148. this.fireEvent('feedselect', this, rec.get('title'), rec.get('url'));
  149. }
  150. },
  151. /**
  152. * Gets the currently selected record in the view.
  153. * @private
  154. * @return {Ext.data.Model} Returns the selected model. false if nothing is selected.
  155. */
  156. getSelectedItem: function(){
  157. return this.view.getSelectionModel().getSelection()[0] || false;
  158. },
  159. /**
  160. * Listens for the context menu event on the view
  161. * @private
  162. */
  163. onContextMenu: function(view, index, el, event){
  164. var menu = this.menu;
  165. event.stopEvent();
  166. menu.activeFeed = view.store.getAt(index);
  167. menu.showAt(event.getXY());
  168. },
  169. /**
  170. * React to a feed being removed
  171. * @private
  172. */
  173. onRemoveFeedClick: function(){
  174. var active = this.menu.activeFeed || this.getSelectedItem();
  175. this.animateNode(this.view.getNode(active), 1, 0, {
  176. scope: this,
  177. afteranimate: function(){
  178. this.view.store.remove(active);
  179. }
  180. });
  181. this.fireEvent('feedremove', this, active.get('title'), active.get('url'));
  182. },
  183. /**
  184. * React to a feed attempting to be added
  185. * @private
  186. */
  187. onAddFeedClick: function(){
  188. var win = this.addFeedWindow || (this.addFeedWindow = Ext.create('widget.feedwindow', {
  189. listeners: {
  190. scope: this,
  191. feedvalid: this.onFeedValid
  192. }
  193. }));
  194. win.form.getForm().reset();
  195. win.show();
  196. },
  197. /**
  198. * React to a validation on a feed passing
  199. * @private
  200. * @param {FeedViewer.FeedWindow} win
  201. * @param {String} title The title of the feed
  202. * @param {String} url The url of the feed
  203. */
  204. onFeedValid: function(win, title, url){
  205. var view = this.view,
  206. store = view.store,
  207. rec;
  208. rec = store.add({
  209. url: url,
  210. title: title
  211. })[0];
  212. this.animateNode(view.getNode(rec), 0, 1);
  213. },
  214. /**
  215. * Animate a node in the view when it is added/removed
  216. * @private
  217. * @param {Mixed} el The element to animate
  218. * @param {Number} start The start opacity
  219. * @param {Number} end The end opacity
  220. * @param {Object} listeners (optional) Any listeners
  221. */
  222. animateNode: function(el, start, end, listeners){
  223. Ext.create('Ext.fx.Anim', {
  224. target: Ext.get(el),
  225. duration: 500,
  226. from: {
  227. opacity: start
  228. },
  229. to: {
  230. opacity: end
  231. },
  232. listeners: listeners
  233. });
  234. },
  235. // Inherit docs
  236. onDestroy: function(){
  237. this.callParent(arguments);
  238. this.menu.destroy();
  239. }
  240. });