Roo/bootstrap/TabGroup.js
[roojs1] / Roo / bootstrap / TabGroup.js
1 /*
2  * - LGPL
3  *
4  * column
5  * 
6  */
7
8 /**
9  * @class Roo.bootstrap.TabGroup
10  * @extends Roo.bootstrap.Column
11  * Bootstrap Column class
12  * @cfg {String} navId the navigation id (for use with navbars) - will be auto generated if it does not exist..
13  * @cfg {Boolean} carousel true to make the group behave like a carousel
14  * @cfg {Boolean} bullets show bullets for the panels
15  * @cfg {Boolean} autoslide (true|false) auto slide .. default false
16  * @cfg {Boolean} slideOnTouch (true|false) slide on touch .. default false
17  * @cfg {Number} timer auto slide timer .. default 0 millisecond
18  * @cfg {Boolean} showarrow (true|false) show arrow default true
19  * 
20  * @constructor
21  * Create a new TabGroup
22  * @param {Object} config The config object
23  */
24
25 Roo.bootstrap.TabGroup = function(config){
26     Roo.bootstrap.TabGroup.superclass.constructor.call(this, config);
27     if (!this.navId) {
28         this.navId = Roo.id();
29     }
30     this.tabs = [];
31     Roo.bootstrap.TabGroup.register(this);
32     
33 };
34
35 Roo.extend(Roo.bootstrap.TabGroup, Roo.bootstrap.Column,  {
36     
37     carousel : false,
38     transition : false,
39     bullets : 0,
40     timer : 0,
41     autoslide : false,
42     slideFn : false,
43     slideOnTouch : false,
44     showarrow : true,
45     
46     getAutoCreate : function()
47     {
48         Roo.isTouch = false;
49         
50         var cfg = Roo.apply({}, Roo.bootstrap.TabGroup.superclass.getAutoCreate.call(this));
51         
52         Roo.log(cfg);
53         
54         cfg.cls += ' tab-content';
55         
56         if (this.carousel) {
57             cfg.cls += ' carousel slide';
58             
59             cfg.cn = [{
60                cls : 'carousel-inner',
61                cn : []
62             }];
63         
64             if(this.bullets  && !Roo.isTouch){
65                 
66                 var bullets = {
67                     cls : 'carousel-bullets',
68                     cn : []
69                 };
70                
71                 if(this.bullets_cls){
72                     bullets.cls = bullets.cls + ' ' + this.bullets_cls;
73                 }
74                  /*
75                 for (var i = 0; i < this.bullets; i++){
76                     bullets.cn.push({
77                         cls : 'bullet bullet-' + i
78                     });
79                 }
80                 */
81                 bullets.cn.push({
82                     cls : 'clear'
83                 });
84                 
85                 cfg.cn[0].cn.push(bullets);
86             }
87             
88             if(this.showarrow){
89                 cfg.cn[0].cn.push({
90                     tag : 'div',
91                     class : 'carousel-arrow',
92                     cn : [
93                         {
94                             tag : 'div',
95                             class : 'carousel-prev',
96                             cn : [
97                                 {
98                                     tag : 'i',
99                                     class : 'fa fa-chevron-left'
100                                 }
101                             ]
102                         },
103                         {
104                             tag : 'div',
105                             class : 'carousel-next',
106                             cn : [
107                                 {
108                                     tag : 'i',
109                                     class : 'fa fa-chevron-right'
110                                 }
111                             ]
112                         }
113                     ]
114                 });
115             }
116             
117         }
118         
119         return cfg;
120     },
121     
122     initEvents:  function()
123     {
124         if(Roo.isTouch && this.slideOnTouch && !this.showarrow){
125             this.el.on("touchstart", this.onTouchStart, this);
126         }
127         
128         if(this.autoslide){
129             var _this = this;
130             
131             this.slideFn = window.setInterval(function() {
132                 _this.showPanelNext();
133             }, this.timer);
134         }
135         
136         if(this.showarrow){
137             this.el.select('.carousel-prev', true).first().on('click', this.showPanelNext(), this);
138         }
139         
140         
141     },
142     
143     onTouchStart : function(e, el, o)
144     {
145         if(!this.slideOnTouch || !Roo.isTouch || Roo.get(e.getTarget()).hasClass('roo-button-text')){
146             return;
147         }
148         
149         this.showPanelNext();
150     },
151     
152     getChildContainer : function()
153     {
154         return this.carousel ? this.el.select('.carousel-inner', true).first() : this.el;
155     },
156     
157     /**
158     * register a Navigation item
159     * @param {Roo.bootstrap.NavItem} the navitem to add
160     */
161     register : function(item)
162     {
163         this.tabs.push( item);
164         item.navId = this.navId; // not really needed..
165         this.addBullet();
166     
167     },
168     
169     getActivePanel : function()
170     {
171         var r = false;
172         Roo.each(this.tabs, function(t) {
173             if (t.active) {
174                 r = t;
175                 return false;
176             }
177             return null;
178         });
179         return r;
180         
181     },
182     getPanelByName : function(n)
183     {
184         var r = false;
185         Roo.each(this.tabs, function(t) {
186             if (t.tabId == n) {
187                 r = t;
188                 return false;
189             }
190             return null;
191         });
192         return r;
193     },
194     indexOfPanel : function(p)
195     {
196         var r = false;
197         Roo.each(this.tabs, function(t,i) {
198             if (t.tabId == p.tabId) {
199                 r = i;
200                 return false;
201             }
202             return null;
203         });
204         return r;
205     },
206     /**
207      * show a specific panel
208      * @param {Roo.bootstrap.TabPanel|number|string} panel to change to (use the tabId to specify a specific one)
209      * @return {boolean} false if panel was not shown (invalid entry or beforedeactivate fails.)
210      */
211     showPanel : function (pan)
212     {
213         if(this.transition || typeof(pan) == 'undefined'){
214             Roo.log("waiting for the transitionend");
215             return;
216         }
217         
218         if (typeof(pan) == 'number') {
219             pan = this.tabs[pan];
220         }
221         
222         if (typeof(pan) == 'string') {
223             pan = this.getPanelByName(pan);
224         }
225         
226         var cur = this.getActivePanel();
227         
228         if(!pan || !cur){
229             Roo.log('pan or acitve pan is undefined');
230             return false;
231         }
232         
233         if (pan.tabId == this.getActivePanel().tabId) {
234             return true;
235         }
236         
237         if (false === cur.fireEvent('beforedeactivate')) {
238             return false;
239         }
240         
241         if(this.bullets > 0 && !Roo.isTouch){
242             this.setActiveBullet(this.indexOfPanel(pan));
243         }
244         
245         if (this.carousel && typeof(Roo.get(document.body).dom.style.transition) != 'undefined') {
246             
247             this.transition = true;
248             var dir = this.indexOfPanel(pan) > this.indexOfPanel(cur)  ? 'next' : 'prev';
249             var lr = dir == 'next' ? 'left' : 'right';
250             pan.el.addClass(dir); // or prev
251             pan.el.dom.offsetWidth; // find the offset with - causing a reflow?
252             cur.el.addClass(lr); // or right
253             pan.el.addClass(lr);
254             
255             var _this = this;
256             cur.el.on('transitionend', function() {
257                 Roo.log("trans end?");
258                 
259                 pan.el.removeClass([lr,dir]);
260                 pan.setActive(true);
261                 
262                 cur.el.removeClass([lr]);
263                 cur.setActive(false);
264                 
265                 _this.transition = false;
266                 
267             }, this, { single:  true } );
268             
269             return true;
270         }
271         
272         cur.setActive(false);
273         pan.setActive(true);
274         
275         return true;
276         
277     },
278     showPanelNext : function()
279     {
280         var i = this.indexOfPanel(this.getActivePanel());
281         
282         if (i >= this.tabs.length - 1 && !this.autoslide) {
283             return;
284         }
285         
286         if (i >= this.tabs.length - 1 && this.autoslide) {
287             i = -1;
288         }
289         
290         this.showPanel(this.tabs[i+1]);
291     },
292     
293     showPanelPrev : function()
294     {
295         var i = this.indexOfPanel(this.getActivePanel());
296         
297         if (i  < 1 && !this.autoslide) {
298             return;
299         }
300         
301         if (i < 1 && this.autoslide) {
302             i = this.tabs.length;
303         }
304         
305         this.showPanel(this.tabs[i-1]);
306     },
307     
308     
309     addBullet: function()
310     {
311         if(!this.bullets || Roo.isTouch){
312             return;
313         }
314         var ctr = this.el.select('.carousel-bullets',true).first();
315         var i = this.el.select('.carousel-bullets .bullet',true).getCount() ;
316         var bullet = ctr.createChild({
317             cls : 'bullet bullet-' + i
318         },ctr.dom.lastChild);
319         
320         
321         var _this = this;
322         
323         bullet.on('click', (function(e, el, o, ii, t){
324
325             e.preventDefault();
326
327             this.showPanel(ii);
328
329             if(this.autoslide && this.slideFn){
330                 clearInterval(this.slideFn);
331                 this.slideFn = window.setInterval(function() {
332                     _this.showPanelNext();
333                 }, this.timer);
334             }
335
336         }).createDelegate(this, [i, bullet], true));
337                 
338         
339     },
340      
341     setActiveBullet : function(i)
342     {
343         if(Roo.isTouch){
344             return;
345         }
346         
347         Roo.each(this.el.select('.bullet', true).elements, function(el){
348             el.removeClass('selected');
349         });
350
351         var bullet = this.el.select('.bullet-' + i, true).first();
352         
353         if(!bullet){
354             return;
355         }
356         
357         bullet.addClass('selected');
358     }
359     
360     
361   
362 });
363
364  
365
366  
367  
368 Roo.apply(Roo.bootstrap.TabGroup, {
369     
370     groups: {},
371      /**
372     * register a Navigation Group
373     * @param {Roo.bootstrap.NavGroup} the navgroup to add
374     */
375     register : function(navgrp)
376     {
377         this.groups[navgrp.navId] = navgrp;
378         
379     },
380     /**
381     * fetch a Navigation Group based on the navigation ID
382     * if one does not exist , it will get created.
383     * @param {string} the navgroup to add
384     * @returns {Roo.bootstrap.NavGroup} the navgroup 
385     */
386     get: function(navId) {
387         if (typeof(this.groups[navId]) == 'undefined') {
388             this.register(new Roo.bootstrap.TabGroup({ navId : navId }));
389         }
390         return this.groups[navId] ;
391     }
392     
393     
394     
395 });
396
397