]>
Commit | Line | Data |
---|---|---|
f0cfe83e AD |
1 | define("dijit/layout/ContentPane", [ |
2 | "dojo/_base/kernel", // kernel.deprecated | |
3 | "dojo/_base/lang", // lang.mixin lang.delegate lang.hitch lang.isFunction lang.isObject | |
4 | "../_Widget", | |
5 | "../_Container", | |
6 | "./_ContentPaneResizeMixin", | |
7 | "dojo/string", // string.substitute | |
8 | "dojo/html", // html._ContentSetter | |
9 | "dojo/i18n!../nls/loading", | |
10 | "dojo/_base/array", // array.forEach | |
11 | "dojo/_base/declare", // declare | |
12 | "dojo/_base/Deferred", // Deferred | |
13 | "dojo/dom", // dom.byId | |
14 | "dojo/dom-attr", // domAttr.attr | |
15 | "dojo/dom-construct", // empty() | |
16 | "dojo/_base/xhr", // xhr.get | |
17 | "dojo/i18n", // i18n.getLocalization | |
18 | "dojo/when" | |
19 | ], function(kernel, lang, _Widget, _Container, _ContentPaneResizeMixin, string, html, nlsLoading, | |
20 | array, declare, Deferred, dom, domAttr, domConstruct, xhr, i18n, when){ | |
21 | ||
22 | // module: | |
23 | // dijit/layout/ContentPane | |
24 | ||
25 | ||
26 | return declare("dijit.layout.ContentPane", [_Widget, _Container, _ContentPaneResizeMixin], { | |
27 | // summary: | |
28 | // A widget containing an HTML fragment, specified inline | |
29 | // or by uri. Fragment may include widgets. | |
30 | // | |
31 | // description: | |
32 | // This widget embeds a document fragment in the page, specified | |
33 | // either by uri, javascript generated markup or DOM reference. | |
34 | // Any widgets within this content are instantiated and managed, | |
35 | // but laid out according to the HTML structure. Unlike IFRAME, | |
36 | // ContentPane embeds a document fragment as would be found | |
37 | // inside the BODY tag of a full HTML document. It should not | |
38 | // contain the HTML, HEAD, or BODY tags. | |
39 | // For more advanced functionality with scripts and | |
40 | // stylesheets, see dojox/layout/ContentPane. This widget may be | |
41 | // used stand alone or as a base class for other widgets. | |
42 | // ContentPane is useful as a child of other layout containers | |
43 | // such as BorderContainer or TabContainer, but note that those | |
44 | // widgets can contain any widget as a child. | |
45 | // | |
46 | // example: | |
47 | // Some quick samples: | |
48 | // To change the innerHTML: | |
49 | // | cp.set('content', '<b>new content</b>')` | |
50 | // Or you can send it a NodeList: | |
51 | // | cp.set('content', dojo.query('div [class=selected]', userSelection)) | |
52 | // To do an ajax update: | |
53 | // | cp.set('href', url) | |
54 | ||
55 | // href: String | |
56 | // The href of the content that displays now. | |
57 | // Set this at construction if you want to load data externally when the | |
58 | // pane is shown. (Set preload=true to load it immediately.) | |
59 | // Changing href after creation doesn't have any effect; Use set('href', ...); | |
60 | href: "", | |
61 | ||
62 | // content: String|DomNode|NodeList|dijit/_Widget | |
63 | // The innerHTML of the ContentPane. | |
64 | // Note that the initialization parameter / argument to set("content", ...) | |
65 | // can be a String, DomNode, Nodelist, or _Widget. | |
66 | content: "", | |
67 | ||
68 | // extractContent: Boolean | |
69 | // Extract visible content from inside of `<body> .... </body>`. | |
70 | // I.e., strip `<html>` and `<head>` (and it's contents) from the href | |
71 | extractContent: false, | |
72 | ||
73 | // parseOnLoad: Boolean | |
74 | // Parse content and create the widgets, if any. | |
75 | parseOnLoad: true, | |
76 | ||
77 | // parserScope: String | |
78 | // Flag passed to parser. Root for attribute names to search for. If scopeName is dojo, | |
79 | // will search for data-dojo-type (or dojoType). For backwards compatibility | |
80 | // reasons defaults to dojo._scopeName (which is "dojo" except when | |
81 | // multi-version support is used, when it will be something like dojo16, dojo20, etc.) | |
82 | parserScope: kernel._scopeName, | |
83 | ||
84 | // preventCache: Boolean | |
85 | // Prevent caching of data from href's by appending a timestamp to the href. | |
86 | preventCache: false, | |
87 | ||
88 | // preload: Boolean | |
89 | // Force load of data on initialization even if pane is hidden. | |
90 | preload: false, | |
91 | ||
92 | // refreshOnShow: Boolean | |
93 | // Refresh (re-download) content when pane goes from hidden to shown | |
94 | refreshOnShow: false, | |
95 | ||
96 | // loadingMessage: String | |
97 | // Message that shows while downloading | |
98 | loadingMessage: "<span class='dijitContentPaneLoading'><span class='dijitInline dijitIconLoading'></span>${loadingState}</span>", | |
99 | ||
100 | // errorMessage: String | |
101 | // Message that shows if an error occurs | |
102 | errorMessage: "<span class='dijitContentPaneError'><span class='dijitInline dijitIconError'></span>${errorState}</span>", | |
103 | ||
104 | // isLoaded: [readonly] Boolean | |
105 | // True if the ContentPane has data in it, either specified | |
106 | // during initialization (via href or inline content), or set | |
107 | // via set('content', ...) / set('href', ...) | |
108 | // | |
109 | // False if it doesn't have any content, or if ContentPane is | |
110 | // still in the process of downloading href. | |
111 | isLoaded: false, | |
112 | ||
113 | baseClass: "dijitContentPane", | |
114 | ||
115 | /*====== | |
116 | // ioMethod: dojo/_base/xhr.get|dojo._base/xhr.post | |
117 | // Function that should grab the content specified via href. | |
118 | ioMethod: dojo.xhrGet, | |
119 | ======*/ | |
120 | ||
121 | // ioArgs: Object | |
122 | // Parameters to pass to xhrGet() request, for example: | |
123 | // | <div data-dojo-type="dijit/layout/ContentPane" data-dojo-props="href: './bar', ioArgs: {timeout: 500}"> | |
124 | ioArgs: {}, | |
125 | ||
126 | // onLoadDeferred: [readonly] dojo.Deferred | |
127 | // This is the `dojo.Deferred` returned by set('href', ...) and refresh(). | |
128 | // Calling onLoadDeferred.then() registers your | |
129 | // callback to be called only once, when the prior set('href', ...) call or | |
130 | // the initial href parameter to the constructor finishes loading. | |
131 | // | |
132 | // This is different than an onLoad() handler which gets called any time any href | |
133 | // or content is loaded. | |
134 | onLoadDeferred: null, | |
135 | ||
136 | // Cancel _WidgetBase's _setTitleAttr because we don't want the title attribute (used to specify | |
137 | // tab labels) to be copied to ContentPane.domNode... otherwise a tooltip shows up over the | |
138 | // entire pane. | |
139 | _setTitleAttr: null, | |
140 | ||
141 | // Flag to parser that I'll parse my contents, so it shouldn't. | |
142 | stopParser: true, | |
143 | ||
144 | // template: [private] Boolean | |
145 | // Flag from the parser that this ContentPane is inside a template | |
146 | // so the contents are pre-parsed. | |
147 | // TODO: this declaration can be commented out in 2.0 | |
148 | template: false, | |
149 | ||
150 | create: function(params, srcNodeRef){ | |
151 | // Convert a srcNodeRef argument into a content parameter, so that the original contents are | |
152 | // processed in the same way as contents set via set("content", ...), calling the parser etc. | |
153 | // Avoid modifying original params object since that breaks NodeList instantiation, see #11906. | |
154 | if((!params || !params.template) && srcNodeRef && !("href" in params) && !("content" in params)){ | |
155 | srcNodeRef = dom.byId(srcNodeRef); | |
156 | var df = srcNodeRef.ownerDocument.createDocumentFragment(); | |
157 | while(srcNodeRef.firstChild){ | |
158 | df.appendChild(srcNodeRef.firstChild); | |
159 | } | |
160 | params = lang.delegate(params, {content: df}); | |
161 | } | |
162 | this.inherited(arguments, [params, srcNodeRef]); | |
163 | }, | |
164 | ||
165 | postMixInProperties: function(){ | |
166 | this.inherited(arguments); | |
167 | var messages = i18n.getLocalization("dijit", "loading", this.lang); | |
168 | this.loadingMessage = string.substitute(this.loadingMessage, messages); | |
169 | this.errorMessage = string.substitute(this.errorMessage, messages); | |
170 | }, | |
171 | ||
172 | buildRendering: function(){ | |
173 | this.inherited(arguments); | |
174 | ||
175 | // Since we have no template we need to set this.containerNode ourselves, to make getChildren() work. | |
176 | // For subclasses of ContentPane that do have a template, does nothing. | |
177 | if(!this.containerNode){ | |
178 | this.containerNode = this.domNode; | |
179 | } | |
180 | ||
181 | // remove the title attribute so it doesn't show up when hovering | |
182 | // over a node (TODO: remove in 2.0, no longer needed after #11490) | |
183 | this.domNode.title = ""; | |
184 | ||
185 | if(!domAttr.get(this.domNode,"role")){ | |
186 | this.domNode.setAttribute("role", "group"); | |
187 | } | |
188 | }, | |
189 | ||
190 | startup: function(){ | |
191 | // summary: | |
192 | // Call startup() on all children including non _Widget ones like dojo/dnd/Source objects | |
193 | ||
194 | // This starts all the widgets | |
195 | this.inherited(arguments); | |
196 | ||
197 | // And this catches stuff like dojo/dnd/Source | |
198 | if(this._contentSetter){ | |
199 | array.forEach(this._contentSetter.parseResults, function(obj){ | |
200 | if(!obj._started && !obj._destroyed && lang.isFunction(obj.startup)){ | |
201 | obj.startup(); | |
202 | obj._started = true; | |
203 | } | |
204 | }, this); | |
205 | } | |
206 | }, | |
207 | ||
208 | _startChildren: function(){ | |
209 | // summary: | |
210 | // Called when content is loaded. Calls startup on each child widget. Similar to ContentPane.startup() | |
211 | // itself, but avoids marking the ContentPane itself as "restarted" (see #15581). | |
212 | ||
213 | // This starts all the widgets | |
214 | array.forEach(this.getChildren(), function(obj){ | |
215 | if(!obj._started && !obj._destroyed && lang.isFunction(obj.startup)){ | |
216 | obj.startup(); | |
217 | obj._started = true; | |
218 | } | |
219 | }); | |
220 | ||
221 | // And this catches stuff like dojo/dnd/Source | |
222 | if(this._contentSetter){ | |
223 | array.forEach(this._contentSetter.parseResults, function(obj){ | |
224 | if(!obj._started && !obj._destroyed && lang.isFunction(obj.startup)){ | |
225 | obj.startup(); | |
226 | obj._started = true; | |
227 | } | |
228 | }, this); | |
229 | } | |
230 | }, | |
231 | ||
232 | setHref: function(/*String|Uri*/ href){ | |
233 | // summary: | |
234 | // Deprecated. Use set('href', ...) instead. | |
235 | kernel.deprecated("dijit.layout.ContentPane.setHref() is deprecated. Use set('href', ...) instead.", "", "2.0"); | |
236 | return this.set("href", href); | |
237 | }, | |
238 | _setHrefAttr: function(/*String|Uri*/ href){ | |
239 | // summary: | |
240 | // Hook so set("href", ...) works. | |
241 | // description: | |
242 | // Reset the (external defined) content of this pane and replace with new url | |
243 | // Note: It delays the download until widget is shown if preload is false. | |
244 | // href: | |
245 | // url to the page you want to get, must be within the same domain as your mainpage | |
246 | ||
247 | // Cancel any in-flight requests (a set('href', ...) will cancel any in-flight set('href', ...)) | |
248 | this.cancel(); | |
249 | ||
250 | this.onLoadDeferred = new Deferred(lang.hitch(this, "cancel")); | |
251 | this.onLoadDeferred.then(lang.hitch(this, "onLoad")); | |
252 | ||
253 | this._set("href", href); | |
254 | ||
255 | // _setHrefAttr() is called during creation and by the user, after creation. | |
256 | // Assuming preload == false, only in the second case do we actually load the URL; | |
257 | // otherwise it's done in startup(), and only if this widget is shown. | |
258 | if(this.preload || (this._created && this._isShown())){ | |
259 | this._load(); | |
260 | }else{ | |
261 | // Set flag to indicate that href needs to be loaded the next time the | |
262 | // ContentPane is made visible | |
263 | this._hrefChanged = true; | |
264 | } | |
265 | ||
266 | return this.onLoadDeferred; // Deferred | |
267 | }, | |
268 | ||
269 | setContent: function(/*String|DomNode|Nodelist*/data){ | |
270 | // summary: | |
271 | // Deprecated. Use set('content', ...) instead. | |
272 | kernel.deprecated("dijit.layout.ContentPane.setContent() is deprecated. Use set('content', ...) instead.", "", "2.0"); | |
273 | this.set("content", data); | |
274 | }, | |
275 | _setContentAttr: function(/*String|DomNode|Nodelist*/data){ | |
276 | // summary: | |
277 | // Hook to make set("content", ...) work. | |
278 | // Replaces old content with data content, include style classes from old content | |
279 | // data: | |
280 | // the new Content may be String, DomNode or NodeList | |
281 | // | |
282 | // if data is a NodeList (or an array of nodes) nodes are copied | |
283 | // so you can import nodes from another document implicitly | |
284 | ||
285 | // clear href so we can't run refresh and clear content | |
286 | // refresh should only work if we downloaded the content | |
287 | this._set("href", ""); | |
288 | ||
289 | // Cancel any in-flight requests (a set('content', ...) will cancel any in-flight set('href', ...)) | |
290 | this.cancel(); | |
291 | ||
292 | // Even though user is just setting content directly, still need to define an onLoadDeferred | |
293 | // because the _onLoadHandler() handler is still getting called from setContent() | |
294 | this.onLoadDeferred = new Deferred(lang.hitch(this, "cancel")); | |
295 | if(this._created){ | |
296 | // For back-compat reasons, call onLoad() for set('content', ...) | |
297 | // calls but not for content specified in srcNodeRef (ie: <div data-dojo-type=ContentPane>...</div>) | |
298 | // or as initialization parameter (ie: new ContentPane({content: ...}) | |
299 | this.onLoadDeferred.then(lang.hitch(this, "onLoad")); | |
300 | } | |
301 | ||
302 | this._setContent(data || ""); | |
303 | ||
304 | this._isDownloaded = false; // mark that content is from a set('content') not a set('href') | |
305 | ||
306 | return this.onLoadDeferred; // Deferred | |
307 | }, | |
308 | _getContentAttr: function(){ | |
309 | // summary: | |
310 | // Hook to make get("content") work | |
311 | return this.containerNode.innerHTML; | |
312 | }, | |
313 | ||
314 | cancel: function(){ | |
315 | // summary: | |
316 | // Cancels an in-flight download of content | |
317 | if(this._xhrDfd && (this._xhrDfd.fired == -1)){ | |
318 | this._xhrDfd.cancel(); | |
319 | } | |
320 | delete this._xhrDfd; // garbage collect | |
321 | ||
322 | this.onLoadDeferred = null; | |
323 | }, | |
324 | ||
325 | destroy: function(){ | |
326 | this.cancel(); | |
327 | this.inherited(arguments); | |
328 | }, | |
329 | ||
330 | destroyRecursive: function(/*Boolean*/ preserveDom){ | |
331 | // summary: | |
332 | // Destroy the ContentPane and its contents | |
333 | ||
334 | // if we have multiple controllers destroying us, bail after the first | |
335 | if(this._beingDestroyed){ | |
336 | return; | |
337 | } | |
338 | this.inherited(arguments); | |
339 | }, | |
340 | ||
341 | _onShow: function(){ | |
342 | // summary: | |
343 | // Called when the ContentPane is made visible | |
344 | // description: | |
345 | // For a plain ContentPane, this is called on initialization, from startup(). | |
346 | // If the ContentPane is a hidden pane of a TabContainer etc., then it's | |
347 | // called whenever the pane is made visible. | |
348 | // | |
349 | // Does necessary processing, including href download and layout/resize of | |
350 | // child widget(s) | |
351 | ||
352 | this.inherited(arguments); | |
353 | ||
354 | if(this.href){ | |
355 | if(!this._xhrDfd && // if there's an href that isn't already being loaded | |
356 | (!this.isLoaded || this._hrefChanged || this.refreshOnShow) | |
357 | ){ | |
358 | return this.refresh(); // If child has an href, promise that fires when the load is complete | |
359 | } | |
360 | } | |
361 | }, | |
362 | ||
363 | refresh: function(){ | |
364 | // summary: | |
365 | // [Re]download contents of href and display | |
366 | // description: | |
367 | // 1. cancels any currently in-flight requests | |
368 | // 2. posts "loading..." message | |
369 | // 3. sends XHR to download new data | |
370 | ||
371 | // Cancel possible prior in-flight request | |
372 | this.cancel(); | |
373 | ||
374 | this.onLoadDeferred = new Deferred(lang.hitch(this, "cancel")); | |
375 | this.onLoadDeferred.then(lang.hitch(this, "onLoad")); | |
376 | this._load(); | |
377 | return this.onLoadDeferred; // If child has an href, promise that fires when refresh is complete | |
378 | }, | |
379 | ||
380 | _load: function(){ | |
381 | // summary: | |
382 | // Load/reload the href specified in this.href | |
383 | ||
384 | // display loading message | |
385 | this._setContent(this.onDownloadStart(), true); | |
386 | ||
387 | var self = this; | |
388 | var getArgs = { | |
389 | preventCache: (this.preventCache || this.refreshOnShow), | |
390 | url: this.href, | |
391 | handleAs: "text" | |
392 | }; | |
393 | if(lang.isObject(this.ioArgs)){ | |
394 | lang.mixin(getArgs, this.ioArgs); | |
395 | } | |
396 | ||
397 | var hand = (this._xhrDfd = (this.ioMethod || xhr.get)(getArgs)), | |
398 | returnedHtml; | |
399 | ||
400 | hand.then( | |
401 | function(html){ | |
402 | returnedHtml = html; | |
403 | try{ | |
404 | self._isDownloaded = true; | |
405 | return self._setContent(html, false); | |
406 | }catch(err){ | |
407 | self._onError('Content', err); // onContentError | |
408 | } | |
409 | }, | |
410 | function(err){ | |
411 | if(!hand.canceled){ | |
412 | // show error message in the pane | |
413 | self._onError('Download', err); // onDownloadError | |
414 | } | |
415 | delete self._xhrDfd; | |
416 | return err; | |
417 | } | |
418 | ).then(function(){ | |
419 | self.onDownloadEnd(); | |
420 | delete self._xhrDfd; | |
421 | return returnedHtml; | |
422 | }); | |
423 | ||
424 | // Remove flag saying that a load is needed | |
425 | delete this._hrefChanged; | |
426 | }, | |
427 | ||
428 | _onLoadHandler: function(data){ | |
429 | // summary: | |
430 | // This is called whenever new content is being loaded | |
431 | this._set("isLoaded", true); | |
432 | try{ | |
433 | this.onLoadDeferred.resolve(data); | |
434 | }catch(e){ | |
435 | console.error('Error '+this.widgetId+' running custom onLoad code: ' + e.message); | |
436 | } | |
437 | }, | |
438 | ||
439 | _onUnloadHandler: function(){ | |
440 | // summary: | |
441 | // This is called whenever the content is being unloaded | |
442 | this._set("isLoaded", false); | |
443 | try{ | |
444 | this.onUnload(); | |
445 | }catch(e){ | |
446 | console.error('Error '+this.widgetId+' running custom onUnload code: ' + e.message); | |
447 | } | |
448 | }, | |
449 | ||
450 | destroyDescendants: function(/*Boolean*/ preserveDom){ | |
451 | // summary: | |
452 | // Destroy all the widgets inside the ContentPane and empty containerNode | |
453 | ||
454 | // Make sure we call onUnload (but only when the ContentPane has real content) | |
455 | if(this.isLoaded){ | |
456 | this._onUnloadHandler(); | |
457 | } | |
458 | ||
459 | // Even if this.isLoaded == false there might still be a "Loading..." message | |
460 | // to erase, so continue... | |
461 | ||
462 | // For historical reasons we need to delete all widgets under this.containerNode, | |
463 | // even ones that the user has created manually. | |
464 | var setter = this._contentSetter; | |
465 | array.forEach(this.getChildren(), function(widget){ | |
466 | if(widget.destroyRecursive){ | |
467 | // All widgets will hit this branch | |
468 | widget.destroyRecursive(preserveDom); | |
469 | }else if(widget.destroy){ | |
470 | // Things like dojo/dnd/Source have destroy(), not destroyRecursive() | |
471 | widget.destroy(preserveDom); | |
472 | } | |
473 | widget._destroyed = true; | |
474 | }); | |
475 | if(setter){ | |
476 | // Most of the widgets in setter.parseResults have already been destroyed, but | |
477 | // things like Menu that have been moved to <body> haven't yet | |
478 | array.forEach(setter.parseResults, function(widget){ | |
479 | if(!widget._destroyed){ | |
480 | if(widget.destroyRecursive){ | |
481 | // All widgets will hit this branch | |
482 | widget.destroyRecursive(preserveDom); | |
483 | }else if(widget.destroy){ | |
484 | // Things like dojo/dnd/Source have destroy(), not destroyRecursive() | |
485 | widget.destroy(preserveDom); | |
486 | } | |
487 | widget._destroyed = true; | |
488 | } | |
489 | }); | |
490 | delete setter.parseResults; | |
491 | } | |
492 | ||
493 | // And then clear away all the DOM nodes | |
494 | if(!preserveDom){ | |
495 | domConstruct.empty(this.containerNode); | |
496 | } | |
497 | ||
498 | // Delete any state information we have about current contents | |
499 | delete this._singleChild; | |
500 | }, | |
501 | ||
502 | _setContent: function(/*String|DocumentFragment*/ cont, /*Boolean*/ isFakeContent){ | |
503 | // summary: | |
504 | // Insert the content into the container node | |
505 | // returns: | |
506 | // Returns a Deferred promise that is resolved when the content is parsed. | |
507 | ||
508 | // first get rid of child widgets | |
509 | this.destroyDescendants(); | |
510 | ||
511 | // html.set will take care of the rest of the details | |
512 | // we provide an override for the error handling to ensure the widget gets the errors | |
513 | // configure the setter instance with only the relevant widget instance properties | |
514 | // NOTE: unless we hook into attr, or provide property setters for each property, | |
515 | // we need to re-configure the ContentSetter with each use | |
516 | var setter = this._contentSetter; | |
517 | if(! (setter && setter instanceof html._ContentSetter)){ | |
518 | setter = this._contentSetter = new html._ContentSetter({ | |
519 | node: this.containerNode, | |
520 | _onError: lang.hitch(this, this._onError), | |
521 | onContentError: lang.hitch(this, function(e){ | |
522 | // fires if a domfault occurs when we are appending this.errorMessage | |
523 | // like for instance if domNode is a UL and we try append a DIV | |
524 | var errMess = this.onContentError(e); | |
525 | try{ | |
526 | this.containerNode.innerHTML = errMess; | |
527 | }catch(e){ | |
528 | console.error('Fatal '+this.id+' could not change content due to '+e.message, e); | |
529 | } | |
530 | })/*, | |
531 | _onError */ | |
532 | }); | |
533 | } | |
534 | ||
535 | var setterParams = lang.mixin({ | |
536 | cleanContent: this.cleanContent, | |
537 | extractContent: this.extractContent, | |
538 | parseContent: !cont.domNode && this.parseOnLoad, | |
539 | parserScope: this.parserScope, | |
540 | startup: false, | |
541 | dir: this.dir, | |
542 | lang: this.lang, | |
543 | textDir: this.textDir | |
544 | }, this._contentSetterParams || {}); | |
545 | ||
546 | var p = setter.set( (lang.isObject(cont) && cont.domNode) ? cont.domNode : cont, setterParams ); | |
547 | ||
548 | // dojox/layout/html/_base::_ContentSetter.set() returns a Promise that indicates when everything is completed. | |
549 | // dojo/html::_ContentSetter.set() currently returns the DOMNode, but that will be changed for 2.0. | |
550 | // So, if set() returns a promise then use it, otherwise fallback to waiting on setter.parseDeferred | |
551 | var self = this; | |
552 | return when(p && p.then ? p : setter.parseDeferred, function(){ | |
553 | // setter params must be pulled afresh from the ContentPane each time | |
554 | delete self._contentSetterParams; | |
555 | ||
556 | if(!isFakeContent){ | |
557 | if(self._started){ | |
558 | // Startup each top level child widget (and they will start their children, recursively) | |
559 | self._startChildren(); | |
560 | ||
561 | // Call resize() on each of my child layout widgets, | |
562 | // or resize() on my single child layout widget... | |
563 | // either now (if I'm currently visible) or when I become visible | |
564 | self._scheduleLayout(); | |
565 | } | |
566 | self._onLoadHandler(cont); | |
567 | } | |
568 | }); | |
569 | }, | |
570 | ||
571 | _onError: function(type, err, consoleText){ | |
572 | this.onLoadDeferred.reject(err); | |
573 | ||
574 | // shows user the string that is returned by on[type]Error | |
575 | // override on[type]Error and return your own string to customize | |
576 | var errText = this['on' + type + 'Error'].call(this, err); | |
577 | if(consoleText){ | |
578 | console.error(consoleText, err); | |
579 | }else if(errText){// a empty string won't change current content | |
580 | this._setContent(errText, true); | |
581 | } | |
582 | }, | |
583 | ||
584 | // EVENT's, should be overide-able | |
585 | onLoad: function(/*===== data =====*/){ | |
586 | // summary: | |
587 | // Event hook, is called after everything is loaded and widgetified | |
588 | // tags: | |
589 | // callback | |
590 | }, | |
591 | ||
592 | onUnload: function(){ | |
593 | // summary: | |
594 | // Event hook, is called before old content is cleared | |
595 | // tags: | |
596 | // callback | |
597 | }, | |
598 | ||
599 | onDownloadStart: function(){ | |
600 | // summary: | |
601 | // Called before download starts. | |
602 | // description: | |
603 | // The string returned by this function will be the html | |
604 | // that tells the user we are loading something. | |
605 | // Override with your own function if you want to change text. | |
606 | // tags: | |
607 | // extension | |
608 | return this.loadingMessage; | |
609 | }, | |
610 | ||
611 | onContentError: function(/*Error*/ /*===== error =====*/){ | |
612 | // summary: | |
613 | // Called on DOM faults, require faults etc. in content. | |
614 | // | |
615 | // In order to display an error message in the pane, return | |
616 | // the error message from this method, as an HTML string. | |
617 | // | |
618 | // By default (if this method is not overriden), it returns | |
619 | // nothing, so the error message is just printed to the console. | |
620 | // tags: | |
621 | // extension | |
622 | }, | |
623 | ||
624 | onDownloadError: function(/*Error*/ /*===== error =====*/){ | |
625 | // summary: | |
626 | // Called when download error occurs. | |
627 | // | |
628 | // In order to display an error message in the pane, return | |
629 | // the error message from this method, as an HTML string. | |
630 | // | |
631 | // Default behavior (if this method is not overriden) is to display | |
632 | // the error message inside the pane. | |
633 | // tags: | |
634 | // extension | |
635 | return this.errorMessage; | |
636 | }, | |
637 | ||
638 | onDownloadEnd: function(){ | |
639 | // summary: | |
640 | // Called when download is finished. | |
641 | // tags: | |
642 | // callback | |
643 | } | |
644 | }); | |
645 | ||
646 | }); |