e6c589b3d5704d4000526efa5858c2bb0efbb18e
[roojs1] / Roo / bootstrap / panel / Content.js
1 /*
2  * Based on:
3  * Ext JS Library 1.1.1
4  * Copyright(c) 2006-2007, Ext JS, LLC.
5  *
6  * Originally Released Under LGPL - original licence link has changed is not relivant.
7  *
8  * Fork - LGPL
9  * <script type="text/javascript">
10  */
11 /**
12  * @class Roo.ContentPanel
13  * @extends Roo.util.Observable
14  * A basic ContentPanel element.
15  * @cfg {Boolean}   fitToFrame    True for this panel to adjust its size to fit when the region resizes  (defaults to false)
16  * @cfg {Boolean}   fitContainer   When using {@link #fitToFrame} and {@link #resizeEl}, you can also fit the parent container  (defaults to false)
17  * @cfg {Boolean/Object} autoCreate True to auto generate the DOM element for this panel, or a {@link Roo.DomHelper} config of the element to create
18  * @cfg {Boolean}   closable      True if the panel can be closed/removed
19  * @cfg {Boolean}   background    True if the panel should not be activated when it is added (defaults to false)
20  * @cfg {String/HTMLElement/Element} resizeEl An element to resize if {@link #fitToFrame} is true (instead of this panel's element)
21  * @cfg {Toolbar}   toolbar       A toolbar for this panel
22  * @cfg {Boolean} autoScroll    True to scroll overflow in this panel (use with {@link #fitToFrame})
23  * @cfg {String} title          The title for this panel
24  * @cfg {Array} adjustments     Values to <b>add</b> to the width/height when doing a {@link #fitToFrame} (default is [0, 0])
25  * @cfg {String} url            Calls {@link #setUrl} with this value
26  * @cfg {String} region         (center|north|south|east|west) which region to put this panel on (when used with xtype constructors)
27  * @cfg {String/Object} params  When used with {@link #url}, calls {@link #setUrl} with this value
28  * @cfg {Boolean} loadOnce      When used with {@link #url}, calls {@link #setUrl} with this value
29  * @cfg {String}    content        Raw content to fill content panel with (uses setContent on construction.)
30  * @cfg {Boolean} badges render the badges
31  * @cfg {String} cls  extra classes to use  
32  * @cfg {String} background (primary|secondary|success|info|warning|danger|light|dark)
33
34  * @constructor
35  * Create a new ContentPanel.
36  * @param {String/HTMLElement/Roo.Element} el The container element for this panel
37  * @param {String/Object} config A string to set only the title or a config object
38  * @param {String} content (optional) Set the HTML content for this panel
39  * @param {String} region (optional) Used by xtype constructors to add to regions. (values center,east,west,south,north)
40  */
41 Roo.bootstrap.panel.Content = function( config){
42     
43     this.tpl = config.tpl || false;
44     
45     var el = config.el;
46     var content = config.content;
47
48     if(config.autoCreate){ // xtype is available if this is called from factory
49         el = Roo.id();
50     }
51     this.el = Roo.get(el);
52     if(!this.el && config && config.autoCreate){
53         if(typeof config.autoCreate == "object"){
54             if(!config.autoCreate.id){
55                 config.autoCreate.id = config.id||el;
56             }
57             this.el = Roo.DomHelper.append(document.body,
58                         config.autoCreate, true);
59         }else{
60             var elcfg =  {
61                 tag: "div",
62                 cls: (config.cls || '') +
63                     (config.background ? ' bg-' + config.background : '') +
64                     " roo-layout-inactive-content",
65                 id: config.id||el
66             };
67             if (config.html) {
68                 elcfg.html = config.html;
69                 
70             }
71                         
72             this.el = Roo.DomHelper.append(document.body, elcfg , true);
73         }
74     } 
75     this.closable = false;
76     this.loaded = false;
77     this.active = false;
78    
79       
80     if (config.toolbar && !config.toolbar.el && config.toolbar.xtype) {
81         
82         this.toolbar = new config.toolbar.xns[config.toolbar.xtype](config.toolbar);
83         
84         this.wrapEl = this.el; //this.el.wrap();
85         var ti = [];
86         if (config.toolbar.items) {
87             ti = config.toolbar.items ;
88             delete config.toolbar.items ;
89         }
90         
91         var nitems = [];
92         this.toolbar.render(this.wrapEl, 'before');
93         for(var i =0;i < ti.length;i++) {
94           //  Roo.log(['add child', items[i]]);
95             nitems.push(this.toolbar.addxtype(Roo.apply({}, ti[i])));
96         }
97         this.toolbar.items = nitems;
98         this.toolbar.el.insertBefore(this.wrapEl.dom.firstChild);
99         delete config.toolbar;
100         
101     }
102     /*
103     // xtype created footer. - not sure if will work as we normally have to render first..
104     if (this.footer && !this.footer.el && this.footer.xtype) {
105         if (!this.wrapEl) {
106             this.wrapEl = this.el.wrap();
107         }
108     
109         this.footer.container = this.wrapEl.createChild();
110          
111         this.footer = Roo.factory(this.footer, Roo);
112         
113     }
114     */
115     
116      if(typeof config == "string"){
117         this.title = config;
118     }else{
119         Roo.apply(this, config);
120     }
121     
122     if(this.resizeEl){
123         this.resizeEl = Roo.get(this.resizeEl, true);
124     }else{
125         this.resizeEl = this.el;
126     }
127     // handle view.xtype
128     
129  
130     
131     
132     this.addEvents({
133         /**
134          * @event activate
135          * Fires when this panel is activated. 
136          * @param {Roo.ContentPanel} this
137          */
138         "activate" : true,
139         /**
140          * @event deactivate
141          * Fires when this panel is activated. 
142          * @param {Roo.ContentPanel} this
143          */
144         "deactivate" : true,
145
146         /**
147          * @event resize
148          * Fires when this panel is resized if fitToFrame is true.
149          * @param {Roo.ContentPanel} this
150          * @param {Number} width The width after any component adjustments
151          * @param {Number} height The height after any component adjustments
152          */
153         "resize" : true,
154         
155          /**
156          * @event render
157          * Fires when this tab is created
158          * @param {Roo.ContentPanel} this
159          */
160         "render" : true
161         
162         
163         
164     });
165     
166
167     
168     
169     if(this.autoScroll){
170         this.resizeEl.setStyle("overflow", "auto");
171     } else {
172         // fix randome scrolling
173         //this.el.on('scroll', function() {
174         //    Roo.log('fix random scolling');
175         //    this.scrollTo('top',0); 
176         //});
177     }
178     content = content || this.content;
179     if(content){
180         this.setContent(content);
181     }
182     if(config && config.url){
183         this.setUrl(this.url, this.params, this.loadOnce);
184     }
185     
186     
187     
188     Roo.bootstrap.panel.Content.superclass.constructor.call(this);
189     
190     if (this.view && typeof(this.view.xtype) != 'undefined') {
191         this.view.el = this.el.appendChild(document.createElement("div"));
192         this.view = Roo.factory(this.view); 
193         this.view.render  &&  this.view.render(false, '');  
194     }
195     
196     
197     this.fireEvent('render', this);
198 };
199
200 Roo.extend(Roo.bootstrap.panel.Content, Roo.bootstrap.Component, {
201     
202     cls : '',
203     background : '',
204     
205     tabTip : '',
206     
207     setRegion : function(region){
208         this.region = region;
209         this.setActiveClass(region && !this.background);
210     },
211     
212     
213     setActiveClass: function(state)
214     {
215         if(state){
216            this.el.replaceClass("roo-layout-inactive-content", "roo-layout-active-content");
217            this.el.setStyle('position','relative');
218         }else{
219            this.el.replaceClass("roo-layout-active-content", "roo-layout-inactive-content");
220            this.el.setStyle('position', 'absolute');
221         } 
222     },
223     
224     /**
225      * Returns the toolbar for this Panel if one was configured. 
226      * @return {Roo.Toolbar} 
227      */
228     getToolbar : function(){
229         return this.toolbar;
230     },
231     
232     setActiveState : function(active)
233     {
234         this.active = active;
235         this.setActiveClass(active);
236         if(!active){
237             if(this.fireEvent("deactivate", this) === false){
238                 return false;
239             }
240             return true;
241         }
242         this.fireEvent("activate", this);
243         return true;
244     },
245     /**
246      * Updates this panel's element
247      * @param {String} content The new content
248      * @param {Boolean} loadScripts (optional) true to look for and process scripts
249     */
250     setContent : function(content, loadScripts){
251         this.el.update(content, loadScripts);
252     },
253
254     ignoreResize : function(w, h){
255         if(this.lastSize && this.lastSize.width == w && this.lastSize.height == h){
256             return true;
257         }else{
258             this.lastSize = {width: w, height: h};
259             return false;
260         }
261     },
262     /**
263      * Get the {@link Roo.UpdateManager} for this panel. Enables you to perform Ajax updates.
264      * @return {Roo.UpdateManager} The UpdateManager
265      */
266     getUpdateManager : function(){
267         return this.el.getUpdateManager();
268     },
269      /**
270      * Loads this content panel immediately with content from XHR. Note: to delay loading until the panel is activated, use {@link #setUrl}.
271      * @param {Object/String/Function} url The url for this request or a function to call to get the url or a config object containing any of the following options:
272 <pre><code>
273 panel.load({
274     url: "your-url.php",
275     params: {param1: "foo", param2: "bar"}, // or a URL encoded string
276     callback: yourFunction,
277     scope: yourObject, //(optional scope)
278     discardUrl: false,
279     nocache: false,
280     text: "Loading...",
281     timeout: 30,
282     scripts: false
283 });
284 </code></pre>
285      * The only required property is <i>url</i>. The optional properties <i>nocache</i>, <i>text</i> and <i>scripts</i>
286      * are shorthand for <i>disableCaching</i>, <i>indicatorText</i> and <i>loadScripts</i> and are used to set their associated property on this panel UpdateManager instance.
287      * @param {String/Object} params (optional) The parameters to pass as either a URL encoded string "param1=1&amp;param2=2" or an object {param1: 1, param2: 2}
288      * @param {Function} callback (optional) Callback when transaction is complete -- called with signature (oElement, bSuccess, oResponse)
289      * @param {Boolean} discardUrl (optional) By default when you execute an update the defaultUrl is changed to the last used URL. If true, it will not store the URL.
290      * @return {Roo.ContentPanel} this
291      */
292     load : function(){
293         var um = this.el.getUpdateManager();
294         um.update.apply(um, arguments);
295         return this;
296     },
297
298
299     /**
300      * Set a URL to be used to load the content for this panel. When this panel is activated, the content will be loaded from that URL.
301      * @param {String/Function} url The URL to load the content from or a function to call to get the URL
302      * @param {String/Object} params (optional) The string params for the update call or an object of the params. See {@link Roo.UpdateManager#update} for more details. (Defaults to null)
303      * @param {Boolean} loadOnce (optional) Whether to only load the content once. If this is false it makes the Ajax call every time this panel is activated. (Defaults to false)
304      * @return {Roo.UpdateManager} The UpdateManager
305      */
306     setUrl : function(url, params, loadOnce){
307         if(this.refreshDelegate){
308             this.removeListener("activate", this.refreshDelegate);
309         }
310         this.refreshDelegate = this._handleRefresh.createDelegate(this, [url, params, loadOnce]);
311         this.on("activate", this.refreshDelegate);
312         return this.el.getUpdateManager();
313     },
314     
315     _handleRefresh : function(url, params, loadOnce){
316         if(!loadOnce || !this.loaded){
317             var updater = this.el.getUpdateManager();
318             updater.update(url, params, this._setLoaded.createDelegate(this));
319         }
320     },
321     
322     _setLoaded : function(){
323         this.loaded = true;
324     }, 
325     
326     /**
327      * Returns this panel's id
328      * @return {String} 
329      */
330     getId : function(){
331         return this.el.id;
332     },
333     
334     /** 
335      * Returns this panel's element - used by regiosn to add.
336      * @return {Roo.Element} 
337      */
338     getEl : function(){
339         return this.wrapEl || this.el;
340     },
341     
342    
343     
344     adjustForComponents : function(width, height)
345     {
346         //Roo.log('adjustForComponents ');
347         if(this.resizeEl != this.el){
348             width -= this.el.getFrameWidth('lr');
349             height -= this.el.getFrameWidth('tb');
350         }
351         if(this.toolbar){
352             var te = this.toolbar.getEl();
353             te.setWidth(width);
354             height -= te.getHeight();
355         }
356         if(this.footer){
357             var te = this.footer.getEl();
358             te.setWidth(width);
359             height -= te.getHeight();
360         }
361         
362         
363         if(this.adjustments){
364             width += this.adjustments[0];
365             height += this.adjustments[1];
366         }
367         return {"width": width, "height": height};
368     },
369     
370     setSize : function(width, height){
371         if(this.fitToFrame && !this.ignoreResize(width, height)){
372             if(this.fitContainer && this.resizeEl != this.el){
373                 this.el.setSize(width, height);
374             }
375             var size = this.adjustForComponents(width, height);
376             this.resizeEl.setSize(this.autoWidth ? "auto" : size.width, this.autoHeight ? "auto" : size.height);
377             this.fireEvent('resize', this, size.width, size.height);
378         }
379     },
380     
381     /**
382      * Returns this panel's title
383      * @return {String} 
384      */
385     getTitle : function(){
386         
387         if (typeof(this.title) != 'object') {
388             return this.title;
389         }
390         
391         var t = '';
392         for (var k in this.title) {
393             if (!this.title.hasOwnProperty(k)) {
394                 continue;
395             }
396             
397             if (k.indexOf('-') >= 0) {
398                 var s = k.split('-');
399                 for (var i = 0; i<s.length; i++) {
400                     t += "<span class='visible-"+s[i]+"'>"+this.title[k]+"</span>";
401                 }
402             } else {
403                 t += "<span class='visible-"+k+"'>"+this.title[k]+"</span>";
404             }
405         }
406         return t;
407     },
408     
409     /**
410      * Set this panel's title
411      * @param {String} title
412      */
413     setTitle : function(title){
414         this.title = title;
415         if(this.region){
416             this.region.updatePanelTitle(this, title);
417         }
418     },
419     
420     /**
421      * Returns true is this panel was configured to be closable
422      * @return {Boolean} 
423      */
424     isClosable : function(){
425         return this.closable;
426     },
427     
428     beforeSlide : function(){
429         this.el.clip();
430         this.resizeEl.clip();
431     },
432     
433     afterSlide : function(){
434         this.el.unclip();
435         this.resizeEl.unclip();
436     },
437     
438     /**
439      *   Force a content refresh from the URL specified in the {@link #setUrl} method.
440      *   Will fail silently if the {@link #setUrl} method has not been called.
441      *   This does not activate the panel, just updates its content.
442      */
443     refresh : function(){
444         if(this.refreshDelegate){
445            this.loaded = false;
446            this.refreshDelegate();
447         }
448     },
449     
450     /**
451      * Destroys this panel
452      */
453     destroy : function(){
454         this.el.removeAllListeners();
455         var tempEl = document.createElement("span");
456         tempEl.appendChild(this.el.dom);
457         tempEl.innerHTML = "";
458         this.el.remove();
459         this.el = null;
460     },
461     
462     /**
463      * form - if the content panel contains a form - this is a reference to it.
464      * @type {Roo.form.Form}
465      */
466     form : false,
467     /**
468      * view - if the content panel contains a view (Roo.DatePicker / Roo.View / Roo.JsonView)
469      *    This contains a reference to it.
470      * @type {Roo.View}
471      */
472     view : false,
473     
474       /**
475      * Adds a xtype elements to the panel - currently only supports Forms, View, JsonView.
476      * <pre><code>
477
478 layout.addxtype({
479        xtype : 'Form',
480        items: [ .... ]
481    }
482 );
483
484 </code></pre>
485      * @param {Object} cfg Xtype definition of item to add.
486      */
487     
488     
489     getChildContainer: function () {
490         return this.getEl();
491     }
492     
493     
494     /*
495         var  ret = new Roo.factory(cfg);
496         return ret;
497         
498         
499         // add form..
500         if (cfg.xtype.match(/^Form$/)) {
501             
502             var el;
503             //if (this.footer) {
504             //    el = this.footer.container.insertSibling(false, 'before');
505             //} else {
506                 el = this.el.createChild();
507             //}
508
509             this.form = new  Roo.form.Form(cfg);
510             
511             
512             if ( this.form.allItems.length) {
513                 this.form.render(el.dom);
514             }
515             return this.form;
516         }
517         // should only have one of theses..
518         if ([ 'View', 'JsonView', 'DatePicker'].indexOf(cfg.xtype) > -1) {
519             // views.. should not be just added - used named prop 'view''
520             
521             cfg.el = this.el.appendChild(document.createElement("div"));
522             // factory?
523             
524             var ret = new Roo.factory(cfg);
525              
526              ret.render && ret.render(false, ''); // render blank..
527             this.view = ret;
528             return ret;
529         }
530         return false;
531     }
532     \*/
533 });
534