4 * base class for bootstrap elements.
8 Roo.bootstrap = Roo.bootstrap || {};
10 * @class Roo.bootstrap.Component
11 * @extends Roo.Component
13 * @children Roo.bootstrap.Component
14 * Bootstrap Component base class
15 * @cfg {String} cls css class
16 * @cfg {String} style any extra css
17 * @cfg {Object} xattr extra attributes to add to 'element' (used by builder to store stuff.)
18 * @cfg {Boolean} can_build_overlaid True if element can be rebuild from a HTML page
19 * @cfg {string} dataId cutomer id
20 * @cfg {string} name Specifies name attribute
21 * @cfg {string} tooltip Text for the tooltip
22 * @cfg {string} container_method method to fetch parents container element (used by NavHeaderbar - getHeaderChildContainer)
23 * @cfg {string|object} visibilityEl (el|parent) What element to use for visibility (@see getVisibilityEl())
26 * Do not use directly - it does not do anything..
27 * @param {Object} config The config object
32 Roo.bootstrap.Component = function(config){
33 Roo.bootstrap.Component.superclass.constructor.call(this, config);
37 * @event childrenrendered
38 * Fires when the children have been rendered..
39 * @param {Roo.bootstrap.Component} this
41 "childrenrendered" : true
50 Roo.extend(Roo.bootstrap.Component, Roo.BoxComponent, {
53 allowDomMove : false, // to stop relocations in parent onRender...
63 * Initialize Events for the element
65 initEvents : function() { },
71 can_build_overlaid : true,
73 container_method : false,
80 // returns the parent component..
81 return Roo.ComponentMgr.get(this.parentId)
87 onRender : function(ct, position)
89 // Roo.log("Call onRender: " + this.xtype);
91 Roo.bootstrap.Component.superclass.onRender.call(this, ct, position);
94 if (this.el.attr('xtype')) {
95 this.el.attr('xtypex', this.el.attr('xtype'));
96 this.el.dom.removeAttribute('xtype');
106 var cfg = Roo.apply({}, this.getAutoCreate());
108 cfg.id = this.id || Roo.id();
110 // fill in the extra attributes
111 if (this.xattr && typeof(this.xattr) =='object') {
112 for (var i in this.xattr) {
113 cfg[i] = this.xattr[i];
118 cfg.dataId = this.dataId;
122 cfg.cls = (typeof(cfg.cls) == 'undefined' ? this.cls : cfg.cls) + ' ' + this.cls;
125 if (this.style) { // fixme needs to support more complex style data.
126 cfg.style = (typeof(cfg.style) == 'undefined' ? this.style : cfg.style) + '; ' + this.style;
130 cfg.name = this.name;
133 this.el = ct.createChild(cfg, position);
136 this.tooltipEl().attr('tooltip', this.tooltip);
139 if(this.tabIndex !== undefined){
140 this.el.dom.setAttribute('tabIndex', this.tabIndex);
147 * Fetch the element to add children to
148 * @return {Roo.Element} defaults to this.el
150 getChildContainer : function()
154 getDocumentBody : function() // used by menus - as they are attached to the body so zIndexes work
156 return Roo.get(document.body);
160 * Fetch the element to display the tooltip on.
161 * @return {Roo.Element} defaults to this.el
163 tooltipEl : function()
168 addxtype : function(tree,cntr)
173 cn = Roo.factory(tree);
174 //Roo.log(['addxtype', cn]);
176 cn.parentType = this.xtype; //??
177 cn.parentId = this.id;
181 cntr = (typeof(cntr) == 'undefined' ) ? 'getChildContainer' : cntr;
182 if (typeof(cn.container_method) == 'string') {
183 cntr = cn.container_method;
187 var has_flexy_each = (typeof(tree['flexy:foreach']) != 'undefined');
189 var has_flexy_if = (typeof(tree['flexy:if']) != 'undefined');
191 var build_from_html = Roo.XComponent.build_from_html;
193 var is_body = (tree.xtype == 'Body') ;
195 var page_has_body = (Roo.get(document.body).attr('xtype') == 'Roo.bootstrap.Body');
197 var self_cntr_el = Roo.get(this[cntr](false));
199 // do not try and build conditional elements
200 if ((has_flexy_each || has_flexy_if || this.can_build_overlaid == false ) && build_from_html) {
204 if (!has_flexy_each || !build_from_html || is_body || !page_has_body) {
205 if(!has_flexy_if || typeof(tree.name) == 'undefined' || !build_from_html || is_body || !page_has_body){
206 return this.addxtypeChild(tree,cntr, is_body);
209 var echild =self_cntr_el ? self_cntr_el.child('>*[name=' + tree.name + ']') : false;
212 return this.addxtypeChild(Roo.apply({}, tree),cntr);
215 Roo.log('skipping render');
221 if (!build_from_html) {
225 // this i think handles overlaying multiple children of the same type
226 // with the sam eelement.. - which might be buggy..
228 var echild =self_cntr_el ? self_cntr_el.child('>*[xtype]') : false;
234 if (echild && echild.attr('xtype').split('.').pop() != cn.xtype) {
238 ret = this.addxtypeChild(Roo.apply({}, tree),cntr);
245 addxtypeChild : function (tree, cntr, is_body)
247 Roo.debug && Roo.log('addxtypeChild:' + cntr);
248 Roo.log('ADDXTYPECHILD');
250 cntr = (typeof(cntr) == 'undefined' ) ? 'getChildContainer' : cntr;
253 var has_flexy = (typeof(tree['flexy:if']) != 'undefined') ||
254 (typeof(tree['flexy:foreach']) != 'undefined');
258 skip_children = false;
259 // render the element if it's not BODY.
262 // if parent was disabled, then do not try and create the children..
263 if(!this[cntr](true)){
268 cn = Roo.factory(tree);
271 cn.parentType = this.xtype; //??
272 cn.parentId = this.id;
274 var build_from_html = Roo.XComponent.build_from_html;
277 // does the container contain child eleemnts with 'xtype' attributes.
278 // that match this xtype..
279 // note - when we render we create these as well..
280 // so we should check to see if body has xtype set.
281 if (build_from_html && Roo.get(document.body).attr('xtype') == 'Roo.bootstrap.Body') {
283 var self_cntr_el = Roo.get(this[cntr](false));
284 var echild =self_cntr_el ? self_cntr_el.child('>*[xtype]') : false;
286 //Roo.log(Roo.XComponent.build_from_html);
287 //Roo.log("got echild:");
290 // there is a scenario where some of the child elements are flexy:if (and all of the same type)
291 // and are not displayed -this causes this to use up the wrong element when matching.
292 // at present the only work around for this is to nest flexy:if elements in another element that is always rendered.
297 if (echild && echild.attr('xtype').split('.').pop() == cn.xtype) {
298 // Roo.log("found child for " + this.xtype +": " + echild.attr('xtype') );
305 //echild.dom.removeAttribute('xtype');
307 Roo.debug && Roo.log("MISSING " + cn.xtype + " on child of " + (this.el ? this.el.attr('xbuilderid') : 'no parent'));
308 Roo.debug && Roo.log(self_cntr_el);
309 Roo.debug && Roo.log(echild);
310 Roo.debug && Roo.log(cn);
316 // if object has flexy:if - then it may or may not be rendered.
317 if (build_from_html && has_flexy && !cn.el && cn.can_build_overlaid) {
318 // skip a flexy if element.
319 Roo.debug && Roo.log('skipping render');
320 Roo.debug && Roo.log(tree);
322 Roo.debug && Roo.log('skipping all children');
323 skip_children = true;
328 // actually if flexy:foreach is found, we really want to create
329 // multiple copies here...
331 //Roo.log(this[cntr]());
332 // some elements do not have render methods.. like the layouts...
334 if(this[cntr](true) === false){
339 cn.render && cn.render(this[cntr](true));
342 // then add the element..
349 if (typeof (tree.menu) != 'undefined') {
350 tree.menu.parentType = cn.xtype;
351 tree.menu.triggerEl = cn.el;
352 nitems.push(cn.addxtype(Roo.apply({}, tree.menu)));
356 if (!tree.items || !tree.items.length) {
358 //Roo.log(["no children", this]);
363 var items = tree.items;
366 //Roo.log(items.length);
368 if (!skip_children) {
369 for(var i =0;i < items.length;i++) {
370 // Roo.log(['add child', items[i]]);
371 nitems.push(cn.addxtype(Roo.apply({}, items[i])));
377 //Roo.log("fire childrenrendered");
379 cn.fireEvent('childrenrendered', this);
385 * Set the element that will be used to show or hide
387 setVisibilityEl : function(el)
389 this.visibilityEl = el;
393 * Get the element that will be used to show or hide
395 getVisibilityEl : function()
397 if (typeof(this.visibilityEl) == 'object') {
398 return this.visibilityEl;
401 if (typeof(this.visibilityEl) == 'string') {
402 return this.visibilityEl == 'parent' ? this.parent().getEl() : this.getEl();
409 * Show a component - removes 'hidden' class
413 if(!this.getVisibilityEl()){
417 this.getVisibilityEl().removeClass(['hidden','d-none']);
419 this.fireEvent('show', this);
424 * Hide a component - adds 'hidden' class
428 if(!this.getVisibilityEl()){
432 this.getVisibilityEl().addClass(['hidden','d-none']);
434 this.fireEvent('hide', this);