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