Upgrade to ExtJS 3.3.1 - Released 11/30/2010
[extjs.git] / src / error-checking.js
1 /*!
2  * Ext JS Library 3.3.1
3  * Copyright(c) 2006-2010 Sencha Inc.
4  * licensing@sencha.com
5  * http://www.sencha.com/license
6  */
7 Ext.ns('Ext.debug');\r
8 Ext.debug.Assistant = function(){\r
9     var enabled = true;\r
10         \r
11     return {\r
12         enable: function(){\r
13             enabled = true;\r
14         },\r
15         \r
16         disable: function(){\r
17             enabled = false;\r
18         },\r
19         \r
20         init : function(classes){\r
21             var klass,\r
22                 intercept = false,\r
23                 fn,\r
24                 method;\r
25             Ext.each(classes, function(cls){\r
26                 if(this.namespaceExists(cls.name)){\r
27                     klass = this.getClass(cls.name);\r
28                     method = cls.instance ? this.addInstanceCheck : this.addPrototypeCheck;\r
29                     Ext.each(cls.checks, function(check){\r
30                         intercept = check.intercept == true;\r
31                         fn = method.call(this, klass, check.name, check.fn, check.intercept == true);\r
32                         if(check.after){\r
33                             check.after(fn);\r
34                         }\r
35                     }, this);\r
36                 }\r
37             }, this);  \r
38         },\r
39         \r
40         namespaceExists: function(name){\r
41             var parent = window,\r
42                 exists = true;\r
43                 \r
44             Ext.each(name.split('.'), function(n){\r
45                 if(!Ext.isDefined(parent[n])){\r
46                     exists = false;\r
47                     return false;\r
48                 }\r
49                 parent = parent[n];\r
50             });\r
51             return exists;\r
52         },\r
53         \r
54         getClass : function(name){\r
55             var parent = window;\r
56             Ext.each(name.split('.'), function(n){\r
57                 parent = parent[n];\r
58             });  \r
59             return parent;\r
60         },\r
61         \r
62         warn: function(){\r
63             if(enabled && window.console){\r
64                 console.warn.apply(console, arguments);\r
65             }\r
66         },\r
67         \r
68         error: function(){\r
69             if(enabled && window.console){\r
70                 console.error.apply(console, arguments);\r
71             }\r
72         },\r
73         \r
74         addPrototypeCheck : function(cls, method, fn, intercept){\r
75             return (cls.prototype[method] = cls.prototype[method][intercept ? 'createInterceptor' : 'createSequence'](fn));\r
76         },\r
77         \r
78         addInstanceCheck : function(cls, method, fn, intercept){\r
79             return (cls[method] = cls[method][intercept ? 'createInterceptor' : 'createSequence'](fn));\r
80         }\r
81     };\r
82 }();\r
83 \r
84 (function(){\r
85     var A = Ext.debug.Assistant,\r
86         cls = [];\r
87         \r
88     cls.push({\r
89         name: 'Ext.util.Observable',\r
90         checks: [{\r
91             name: 'addListener',\r
92             intercept: true,\r
93             fn: function(eventName, fn){\r
94                 if(typeof eventName == 'object'){\r
95                     var ev, o;\r
96                     for(ev in eventName){\r
97                         if(!this.filterOptRe.test(ev)){\r
98                             o = eventName[ev];\r
99                             o = o && o.fn ? o.fn : o;\r
100                             if(!Ext.isFunction(o)){\r
101                                 A.error('Non function passed to event listener', this, ev);\r
102                                 return false;\r
103                             }\r
104                         }\r
105                     }\r
106                 }else{\r
107                     if(!Ext.isFunction(fn)){\r
108                         A.error('Non function passed to event listener', this, eventName);\r
109                     }\r
110                 }\r
111             },\r
112             after: function(method){\r
113                 Ext.util.Observable.prototype.on = method;\r
114             }\r
115         }]\r
116     });\r
117     \r
118     cls.push({\r
119         name: 'Ext.Component',\r
120         checks: [{\r
121             name: 'render',\r
122             intercept: true,\r
123             fn: function(container, position){\r
124                 if(!container && !this.el){\r
125                     A.error('Unable to render to container', this, container);\r
126                 }\r
127             \r
128                 if(this.contentEl){\r
129                     var el = Ext.getDom(this.contentEl);\r
130                     if(!el){\r
131                         A.error('Specified contentEl does not exist', this, this.contentEl);\r
132                         return false;\r
133                     }\r
134                 }\r
135             }\r
136         }]\r
137     });\r
138     \r
139     cls.push({\r
140         name: 'Ext.Container',\r
141         checks: [{\r
142             name: 'onBeforeAdd',\r
143             intercept: true,\r
144             fn: function(c){\r
145                 if(c.isDestroyed){\r
146                     A.warn('Adding destroyed component to container', c, this);\r
147                 }\r
148                 if(c.renderTo){\r
149                     A.warn('Using renderTo while adding an item to a Container. You should use the add() method or put the item in the items configuration', c, this);\r
150                 }\r
151                 if(c.applyTo){\r
152                     A.warn('Using applyTo while adding an item to a Container. You should use the add() method or put the item in the items configuration', c, this);\r
153                 }\r
154                 \r
155                 var type = this.layout.type;\r
156                 if(type == 'container' || type == 'auto'){\r
157                     A.warn('A non sizing layout is being used in a container that has child components. This means the child components will not be sized.', this);\r
158                 }\r
159             }\r
160         },{\r
161             name: 'lookupComponent',\r
162             intercept: true,\r
163             fn: function(c){\r
164                 var valid = true;\r
165                 if(Ext.isEmpty(c)){\r
166                     valid = false;\r
167                 }\r
168                 if(Ext.isString(c)){\r
169                     c = Ext.ComponentMgr.get(comp);\r
170                     valid = !Ext.isEmpty(c);\r
171                 }\r
172                 if(!valid){\r
173                     A.error('Adding invalid component to container', this, c);\r
174                     return false;\r
175                 }\r
176             }\r
177         }]\r
178     });\r
179     \r
180     cls.push({\r
181         name: 'Ext.DataView',\r
182         checks: [{\r
183             name: 'initComponent',\r
184             fn: function(){\r
185                 if(!this.itemSelector){\r
186                     A.error('No itemSelector specified', this);\r
187                 }\r
188             }\r
189         },{\r
190             name: 'afterRender',\r
191             fn: function(){\r
192                 if(!this.store){\r
193                     A.error('No store attached to DataView', this);\r
194                 } \r
195             }\r
196         }]\r
197     });\r
198     \r
199     cls.push({\r
200         name: 'Ext.Window',\r
201         checks: [{\r
202             name: 'show',\r
203             intercept: true,\r
204             fn: function(){\r
205                 if(this.isDestroyed){\r
206                     A.error('Trying to show a destroyed window. If you want to reuse the window, look at the closeAction configuration.', this);\r
207                     return false;\r
208                 } \r
209             }\r
210         }]\r
211     });\r
212     \r
213     cls.push({\r
214         name: 'Ext.grid.GridPanel',\r
215         checks: [{\r
216             name: 'initComponent',\r
217             fn: function(){\r
218                 if(!this.colModel){\r
219                     A.error('No column model specified for grid', this);\r
220                 }\r
221                 if(!this.store){\r
222                     A.error('No store specified for grid', this);\r
223                 }\r
224             }\r
225         }]\r
226     });\r
227     \r
228     cls.push({\r
229         name: 'Ext.grid.GridView',\r
230         checks: [{\r
231             name: 'autoExpand',\r
232             intercept: true,\r
233             fn: function(){\r
234                 var g = this.grid, \r
235                 cm = this.cm;\r
236                 if(!this.userResized && g.autoExpandColumn){\r
237                     var tw = cm.getTotalWidth(false), \r
238                         aw = this.grid.getGridEl().getWidth(true) - this.getScrollOffset();\r
239                     if(tw != aw){\r
240                         var ci = cm.getIndexById(g.autoExpandColumn);\r
241                         if(ci == -1){\r
242                             A.error('The autoExpandColumn does not exist in the column model', g, g.autoExpandColumn);\r
243                             return false;\r
244                         }\r
245                     }\r
246                 }\r
247             }\r
248         }]\r
249     });\r
250     \r
251     cls.push({\r
252         name: 'Ext.chart.Chart',\r
253         checks: [{\r
254             name: 'initComponent',\r
255             fn: function(){\r
256                 if(!this.store){\r
257                     A.error('No store specified for chart', this);\r
258                 }\r
259             }\r
260         }]\r
261     });\r
262     \r
263     cls.push({\r
264         name: 'Ext.tree.TreePanel',\r
265         checks: [{\r
266             name: 'afterRender',\r
267             intercept: true,\r
268             fn: function(){\r
269                 if(!this.root){\r
270                     A.error('No root node specified for tree', this);\r
271                     return false;\r
272                 }\r
273             }\r
274         }]\r
275     });\r
276     \r
277     cls.push({\r
278         name: 'Ext',\r
279         instance: true,\r
280         checks: [{\r
281             name: 'extend',\r
282             intercept: true,\r
283             fn: function(){\r
284                 if(arguments.length == 2 && !arguments[0]){\r
285                     A.error('Invalid base class passed to extend', arguments[0]);\r
286                     return false;\r
287                 }    \r
288                 if(arguments.length == 3){\r
289                     if(!arguments[0]){\r
290                         A.error('Invalid class to extend', arguments[0]);\r
291                         return false;    \r
292                     }else if(!arguments[1]){\r
293                         A.error('Invalid base class passed to extend', arguments[1]);\r
294                         return false;\r
295                     }\r
296                 }\r
297             }\r
298         },{\r
299             name: 'override',\r
300             intercept: true,\r
301             fn: function(c){\r
302                 if(!c){\r
303                     A.error('Invalid class passed to override', c);\r
304                     return false;\r
305                 }\r
306             }\r
307         }]    \r
308     });\r
309     \r
310     cls.push({\r
311         name: 'Ext.ComponentMgr',\r
312         instance: true,\r
313         checks: [{\r
314             name: 'register',\r
315             intercept: true,\r
316             fn: function(c){\r
317                 if(this.all.indexOfKey(c.id) > -1){\r
318                     A.warn('A component with this id already exists', c, c.id);\r
319                 }\r
320             }\r
321         },{\r
322             name: 'create',\r
323             intercept: true,\r
324             fn: function(config, defaultType){\r
325                 var types = Ext.ComponentMgr.types;\r
326                 if(!config.render){\r
327                     if(config.xtype){\r
328                         if(!types[config.xtype]){\r
329                             A.error('Unknown xtype specified', config, config.xtype);\r
330                             return false;\r
331                         }\r
332                     }else{\r
333                         if(!types[defaultType]){\r
334                             A.error('Unknown defaultType specified', config, defaultType);\r
335                             return false;\r
336                         }\r
337                     }\r
338                 }\r
339             }\r
340         }]\r
341     });\r
342     \r
343     cls.push({\r
344         name: 'Ext.layout.FitLayout',\r
345         checks: [{\r
346             name: 'onLayout',\r
347             intercept: true,\r
348             fn: function(){\r
349                 var ct = this.container;\r
350                 if(ct.items.getCount() > 1){\r
351                     A.warn('More than 1 item in the container. A fit layout will only display a single item.', ct);\r
352                 }\r
353             }\r
354         }]\r
355     });\r
356     \r
357     if(Ext.BLANK_IMAGE_URL == 'http:/' + '/www.extjs.com/s.gif'){\r
358         A.warn('You should set the Ext.BLANK_IMAGE_URL to reference a local copy.');\r
359     }\r
360     \r
361     A.init(cls);\r
362     \r
363         \r
364 })();