Upgrade to ExtJS 4.0.2 - Released 06/09/2011
[extjs.git] / docs / app / view / cls / Overview.js
1 /**
2  * Renders the whole class-documentation page.
3  */
4 Ext.define('Docs.view.cls.Overview', {
5     extend: 'Ext.panel.Panel',
6     alias: 'widget.classoverview',
7     requires: [
8         'Docs.view.cls.Toolbar',
9         'Docs.Syntax',
10         'Docs.Settings'
11     ],
12
13     cls: 'class-overview iScroll',
14     title: 'Overview',
15     autoScroll: true,
16     bodyPadding: '20',
17
18     /**
19      * Scrolls the specified element into view
20      *
21      * @param {String} query  DomQuery selector string.
22      */
23     scrollToEl: function(query) {
24         var el = Ext.get(Ext.query(query)[0]);
25         if (el) {
26             var isMember = el.hasCls("member");
27             var scrollOffset = el.getY() - (isMember ? 145 : 135);
28             var docContent = this.getEl().down('.x-panel-body');
29             var currentScroll = docContent.getScroll()['top'];
30             docContent.scrollTo('top', currentScroll + scrollOffset, true);
31
32             if (isMember && el.down(".expandable")) {
33                 el.addCls('open');
34             }
35             el.highlight();
36         }
37     },
38
39     /**
40      * Renders class documentation in this panel.
41      *
42      * @param {Object} docClass
43      */
44     load: function(docClass) {
45         this.docClass = docClass;
46
47         if (this.toolbar) {
48             this.removeDocked(this.toolbar, true);
49         }
50         this.toolbar = Ext.create('Docs.view.cls.Toolbar', {
51             docClass: this.docClass
52         });
53         this.addDocked(this.toolbar);
54
55         this.update(this.renderClass(docClass));
56         Docs.Syntax.highlight(this.getEl());
57
58         if (Docs.Settings.get("hideInherited")) {
59             this.toolbar.hideInherited(true);
60         }
61     },
62
63     renderClass: function(cls) {
64         this.classTpl = this.classTpl || new Ext.XTemplate(
65             '<div>',
66                 '{hierarchy}',
67                 '{doc}',
68                 '<div class="members">',
69                     '{members}',
70                 '</div>',
71             '</div>'
72         );
73
74         return this.classTpl.apply({
75             doc: cls.doc,
76             hierarchy: this.renderHierarchy(cls),
77             members: this.renderMembers(cls)
78         });
79     },
80
81     renderHierarchy: function(cls) {
82         if (cls.superclasses.length === 0 && cls.allMixins.length === 0 && cls.alternateClassNames.length === 0) {
83             return "";
84         }
85
86         this.hierarchyTpl = this.hierarchyTpl || new Ext.XTemplate(
87             '<pre class="hierarchy">',
88             '<tpl if="alternateClassNames.length &gt; 0">',
89                 '<h4>Alternate names</h4>',
90                 '<tpl for="alternateClassNames">',
91                     '<div class="alternate-class-name">{.}</div>',
92                 '</tpl>',
93             '</tpl>',
94             '<tpl if="tree">',
95                 '<h4>Hierarchy</h4>',
96                 '{tree}',
97             '</tpl>',
98             '<tpl if="mixins.length &gt; 0">',
99                 '<h4>Mixins</h4>',
100                 '<tpl for="mixins">',
101                     '<div class="mixin">{.}</div>',
102                 '</tpl>',
103             '</tpl>',
104             '</pre>'
105         );
106
107         return this.hierarchyTpl.apply({
108             tree: cls.superclasses.length ? this.renderClassTree(cls.superclasses.concat(cls.name), true) : "",
109             mixins: Ext.Array.map(cls.allMixins, this.renderLink, this),
110             alternateClassNames: cls.alternateClassNames
111         });
112     },
113
114     renderClassTree: function(superclasses, firstChild) {
115         if (superclasses.length === 0) {
116             return "";
117         }
118
119         this.classTreeTpl = this.classTreeTpl || new Ext.XTemplate(
120             '<div class="subclass {firstChild}">',
121               '{link}',
122               '{subtree}',
123             '</div>'
124         );
125
126         var name = superclasses[0];
127         return this.classTreeTpl.apply({
128             firstChild: firstChild ? 'first-child' : '',
129             link: superclasses.length > 1 ? this.renderLink(name) : '<strong>'+name+'</strong>',
130             subtree: this.renderClassTree(superclasses.slice(1))
131         });
132     },
133
134     renderLink: function(className) {
135         return Ext.String.format('<a href="#/api/{0}" rel="{0}" class="docClass">{0}</a>', className);
136     },
137
138     renderMembers: function(cls) {
139         var typeTitles = {
140             cfg: "Config options",
141             property: "Properties",
142             method: "Methods",
143             event: "Events"
144         };
145
146         // Skip rendering empty sections
147         var html = [];
148         for (var type in typeTitles) {
149             if (cls.members[type].length > 0) {
150                 html.push(this.renderSection(cls.members[type], type, typeTitles[type]));
151             }
152         }
153         return html.join("");
154     },
155
156     renderSection: function(members, type, title) {
157         this.sectionTpl = this.sectionTpl || new Ext.XTemplate(
158             '<div id="m-{type}">',
159                 '<div class="definedBy">Defined By</div>',
160                 '<h3 class="members-title">{title}</h3>',
161                 '{members}',
162             '</div>'
163         );
164
165         return this.sectionTpl.apply({
166             type: type,
167             title: title,
168             members: Ext.Array.map(members, this.renderMemberDiv, this).join("")
169         });
170     },
171
172     renderMemberDiv: function(member, index) {
173         this.memberTpl = this.memberTpl || new Ext.XTemplate(
174             '<div id="{tagname}-{name}" class="member {firstChild} {inherited}">',
175                 // leftmost column: expand button
176                 '<a href="#" class="side {expandable}">',
177                     '<span>&nbsp;</span>',
178                 '</a>',
179                 // member name and type + link to owner class and source
180                 '<div class="title">',
181                     '<div class="meta">',
182                         '<a href="#/api/{owner}" rel="{owner}" class="definedIn docClass">{owner}</a><br/>',
183                         '<a href="source/{href}" target="_blank" class="viewSource">view source</a>',
184                     '</div>',
185                     '{signature}',
186                 '</div>',
187                 // short and long descriptions
188                 '<div class="description">',
189                     '<div class="short">{[this.shortDoc(values)]}</div>',
190                     '<div class="long">{longDoc}</div>',
191                 '</div>',
192             '</div>',
193             {
194                 // Returns contents for short documentation
195                 shortDoc: function(cfg) {
196                     return cfg.shortDoc ? cfg.shortDoc : cfg.doc;
197                 }
198             }
199         );
200
201         return this.memberTpl.apply(Ext.apply({
202             // use classname "first-child" when it's first member in its category
203             firstChild: (index === 0) ? "first-child" : "",
204             // use classname "expandable" when member has shortened description
205             expandable: member.shortDoc ? "expandable" : "not-expandable",
206             // use classname "inherited" when member is not defined in this class
207             inherited: member.owner === this.docClass.name ? "not-inherited" : "inherited",
208             // method params signature or property type signature
209             signature: this.renderSignature(member),
210             // full documentation together with optional parameters and return value
211             longDoc: this.renderLongDoc(member)
212         }, member));
213     },
214
215     renderSignature: function(member) {
216         this.signatureTpl = this.signatureTpl || new Ext.XTemplate(
217             '{before}<a href="#/api/{member}-{tagname}-{name}" class="name {expandable}">{name}</a>{params}{after}'
218         );
219
220         var cfg = Ext.apply({}, member);
221         cfg.expandable = member.shortDoc ? "expandable" : "not-expandable";
222
223         if (member.tagname === "method" && member.name === member.owner.replace(/^.*\./, "")) {
224             cfg.before = "<strong class='constructor-signature'>new</strong>";
225         }
226
227         if (member.tagname === "cfg" || member.tagname === "property") {
228             cfg.params = "<span> : " + member.type + "</span>";
229         }
230         else {
231             var ps = Ext.Array.map(member.params, this.renderShortParam, this).join(", ");
232             cfg.params = '( <span class="pre">' + ps + "</span> )";
233             if (member.tagname === "method") {
234                 cfg.params += " : " + member["return"].type;
235             }
236         }
237
238         if (member.protected) {
239             cfg.after = "<strong class='protected-signature'>protected</strong>";
240         }
241         if (member.static) {
242             cfg.after = "<strong class='static-signature'>static</strong>";
243         }
244         if (member.deprecated) {
245             cfg.after = "<strong class='deprecated-signature'>deprecated</strong>";
246         }
247
248         return this.signatureTpl.apply(cfg);
249     },
250
251     renderShortParam: function(param) {
252         var p = param.type + " " + param.name;
253         return param.optional ? "["+p+"]" : p;
254     },
255
256     renderLongDoc: function(member) {
257         var doc = member.doc;
258
259         if (member.deprecated) {
260             var v = member.deprecated.version ? "since " + member.deprecated.version : "";
261             doc += '<div class="deprecated">';
262             doc += Ext.String.format('<p>This {0} has been <strong>deprecated</strong> {1}</p>', member.tagname, v);
263             doc += member.deprecated.text;
264             doc += '</div>';
265         }
266
267         if (member.params && member.params.length > 0) {
268             doc += '<h3 class="pa">Parameters</h3>';
269             var ps = Ext.Array.map(member.params, this.renderLongParam, this).join("");
270             doc += "<ul>" + ps + "</ul>";
271         }
272
273         if (member["return"]) {
274             doc += this.renderReturn(member["return"]);
275         }
276
277         return doc;
278     },
279
280     renderLongParam: function(param) {
281         this.paramTpl = this.paramTpl || new Ext.XTemplate(
282             '<li>',
283                 '<span class="pre">{name}</span> : {type}',
284                 '<div class="sub-desc">',
285                     '{doc}',
286                 '</div>',
287             '</li>'
288         );
289
290         return this.paramTpl.apply(param);
291     },
292
293     renderReturn: function(returnDoc) {
294         this.returnTpl = this.returnTpl || new Ext.XTemplate(
295             '<h3 class="pa">Returns</h3>',
296             '<ul>',
297                 '<li>',
298                     '<span class="pre">{type}</span>',
299                     '<div class="sub-desc">',
300                         '{doc}',
301                     '</div>',
302                 '</li>',
303             '</ul>'
304         );
305
306         return this.returnTpl.apply(returnDoc);
307     }
308 });