Upgrade to ExtJS 4.0.2 - Released 06/09/2011
[extjs.git] / docs / app / controller / Classes.js
1 /**
2  * Listeners should be defined here instead of in the view classes
3  */
4 Ext.define('Docs.controller.Classes', {
5     extend: 'Ext.app.Controller',
6
7     requires: [
8         'Docs.History',
9         'Docs.Syntax',
10         'Docs.view.cls.Overview'
11     ],
12
13     stores: [
14         'Favorites',
15         'History',
16         'Settings'
17     ],
18
19     models: [
20         'Favorite',
21         'History',
22         'Setting'
23     ],
24
25     refs: [
26         {
27             ref: 'header',
28             selector: 'classheader'
29         },
30         {
31             ref: 'tabPanel',
32             selector: 'classtabpanel'
33         },
34         {
35             ref: 'tree',
36             selector: 'classtree'
37         }
38     ],
39
40     init: function() {
41         this.addEvents(
42             /**
43              * @event showClass
44              * Fired after class shown. Used for analytics event tracking.
45              * @param {String} cls  name of the class.
46              */
47             "showClass",
48             /**
49              * @event showMember
50              * Fired after class member scrolled to view. Used for analytics event tracking.
51              * @param {String} cls  name of the class.
52              * @param {String} anchor  name of the member in form type-name like "method-bind".
53              */
54             "showMember",
55             /**
56              * @event showGuide
57              * Fired after guide shown. Used for analytics event tracking.
58              * @param {String} guide  name of the guide.
59              */
60             "showGuide"
61         );
62
63         Ext.getBody().addListener('click', function(cmp, el) {
64             this.loadClass(el.rel);
65         }, this, {
66             preventDefault: true,
67             delegate: '.docClass'
68         });
69
70         this.control({
71             'classtree': {
72                 // Can't simply assign the loadClass function as event
73                 // handler, because an extra event options object is
74                 // appended to the event arguments, which we don't
75                 // want to give to the loadClass, as this would render
76                 // the noHistory parameter to true.
77                 classclick: function(cls) {
78                     this.loadClass(cls);
79                 }
80             },
81
82             'indexcontainer': {
83                 afterrender: function(cmp) {
84                     cmp.el.addListener('click', function(cmp, el) {
85                         this.showGuide(el.rel);
86                     }, this, {
87                         preventDefault: true,
88                         delegate: '.guide'
89                     });
90                 }
91             },
92
93             'classoverview': {
94                 afterrender: function(cmp) {
95                     // Expand member when clicked
96                     cmp.el.addListener('click', function(cmp, el) {
97                         Ext.get(Ext.get(el).up('.member')).toggleCls('open');
98                     }, this, {
99                         preventDefault: true,
100                         delegate: '.expandable'
101                     });
102
103                     // Do nothing when clicking on not-expandable items
104                     cmp.el.addListener('click', Ext.emptyFn, this, {
105                         preventDefault: true,
106                         delegate: '.not-expandable'
107                     });
108                 }
109             }
110         });
111     },
112
113     cache: {},
114
115     /**
116      * Loads class.
117      *
118      * @param {String} clsUrl  name of the class + optionally name of the method, separated with dash.
119      * @param {Boolean} noHistory  true to disable adding entry to browser history
120      */
121     loadClass: function(clsUrl, noHistory) {
122         var cls = clsUrl;
123         var member;
124
125         Ext.getCmp('container').layout.setActiveItem(1);
126
127         // separate class and member name
128         var matches = clsUrl.match(/^(.*?)(?:-(.*))?$/);
129         if (matches) {
130             cls = matches[1];
131             member = matches[2];
132         }
133
134         if (!noHistory) {
135             Docs.History.push("/api/" + clsUrl);
136         }
137
138         if (this.cache[cls]) {
139             this.showClass(this.cache[cls], member);
140         } else {
141             if (this.getTabPanel()) {
142                 this.getTabPanel().setLoading(true);
143             }
144
145             Ext.data.JsonP.request({
146                 url: this.getBaseUrl() + '/output/' + cls + '.js',
147                 callbackName: cls.replace(/\./g, '_'),
148                 success: function(json, opts) {
149                     this.cache[cls] = json;
150                     this.showClass(json, member);
151                 },
152                 failure : function(response, opts) {
153                     console.log('Fail');
154                 },
155                 scope: this
156             });
157         }
158     },
159
160     showClass: function(cls, anchor) {
161         var classOverview = this.getTabPanel().down('classoverview');
162
163         if (this.currentCls != cls) {
164             this.getHeader().load(cls);
165
166             // Init overview tab if not already available
167             if (!classOverview) {
168                 classOverview = Ext.create('Docs.view.cls.Overview');
169                 this.getTabPanel().add(classOverview);
170                 this.getTabPanel().setActiveTab(0);
171             }
172             classOverview.load(cls);
173
174             this.getTabPanel().setLoading(false);
175
176             this.getTree().selectClass(cls.name);
177             this.fireEvent('showClass', cls.name);
178         }
179
180         if (anchor) {
181             classOverview.scrollToEl("#" + anchor);
182             this.fireEvent('showMember', cls.name, anchor);
183         } else {
184             classOverview.getEl().down('.x-panel-body').scrollTo('top', 0);
185         }
186
187         this.currentCls = cls;
188     },
189
190     showGuide: function(name, noHistory) {
191         noHistory || Docs.History.push("/guide/" + name);
192
193         Ext.data.JsonP.request({
194             url: this.getBaseUrl() + "/guides/" + name + "/README.js",
195             callbackName: name,
196             success: function(json) {
197                 Ext.getCmp("guide").update(json.guide);
198                 Ext.getCmp('container').layout.setActiveItem(2);
199                 Docs.Syntax.highlight(Ext.get("guide"));
200                 this.fireEvent('showGuide', name);
201             },
202             scope: this
203         });
204     },
205
206     /**
207      * Returns base URL used for making AJAX requests.
208      * @return {String} URL
209      */
210     getBaseUrl: function() {
211         return document.location.href.replace(/#.*/, "").replace(/index.html/, "");
212     }
213
214 });