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             cfg.cn[0].cn.push({
89                 tag : 'div',
90                 class : 'carousel-arrow',
91                 cn : [
92                     {
93                         tag : 'div',
94                         class : 'carousel-prev',
95                         cn : [
96                             {
97                                 tag : 'i',
98                                 class : 'fa fa-chevron-left'
99                             }
100                         ]
101                     },
102                     {
103                         tag : 'div',
104                         class : 'carousel-next',
105                         cn : [
106                             {
107                                 tag : 'i',
108                                 class : 'fa fa-chevron-right'
109                             }
110                         ]
111                     }
112                 ]
113             });
114         }
115         
116         return cfg;
117     },
118     
119     initEvents:  function()
120     {
121         if(Roo.isTouch && this.slideOnTouch){
122             this.el.on("touchstart", this.onTouchStart, this);
123         }
124         
125         if(this.autoslide){
126             var _this = this;
127             
128             this.slideFn = window.setInterval(function() {
129                 _this.showPanelNext();
130             }, this.timer);
131         }
132         
133         
134         
135     },
136     
137     onTouchStart : function(e, el, o)
138     {
139         if(!this.slideOnTouch || !Roo.isTouch || Roo.get(e.getTarget()).hasClass('roo-button-text')){
140             return;
141         }
142         
143         this.showPanelNext();
144     },
145     
146     getChildContainer : function()
147     {
148         return this.carousel ? this.el.select('.carousel-inner', true).first() : this.el;
149     },
150     
151     /**
152     * register a Navigation item
153     * @param {Roo.bootstrap.NavItem} the navitem to add
154     */
155     register : function(item)
156     {
157         this.tabs.push( item);
158         item.navId = this.navId; // not really needed..
159         this.addBullet();
160     
161     },
162     
163     getActivePanel : function()
164     {
165         var r = false;
166         Roo.each(this.tabs, function(t) {
167             if (t.active) {
168                 r = t;
169                 return false;
170             }
171             return null;
172         });
173         return r;
174         
175     },
176     getPanelByName : function(n)
177     {
178         var r = false;
179         Roo.each(this.tabs, function(t) {
180             if (t.tabId == n) {
181                 r = t;
182                 return false;
183             }
184             return null;
185         });
186         return r;
187     },
188     indexOfPanel : function(p)
189     {
190         var r = false;
191         Roo.each(this.tabs, function(t,i) {
192             if (t.tabId == p.tabId) {
193                 r = i;
194                 return false;
195             }
196             return null;
197         });
198         return r;
199     },
200     /**
201      * show a specific panel
202      * @param {Roo.bootstrap.TabPanel|number|string} panel to change to (use the tabId to specify a specific one)
203      * @return {boolean} false if panel was not shown (invalid entry or beforedeactivate fails.)
204      */
205     showPanel : function (pan)
206     {
207         if(this.transition || typeof(pan) == 'undefined'){
208             Roo.log("waiting for the transitionend");
209             return;
210         }
211         
212         if (typeof(pan) == 'number') {
213             pan = this.tabs[pan];
214         }
215         
216         if (typeof(pan) == 'string') {
217             pan = this.getPanelByName(pan);
218         }
219         
220         var cur = this.getActivePanel();
221         
222         if(!pan || !cur){
223             Roo.log('pan or acitve pan is undefined');
224             return false;
225         }
226         
227         if (pan.tabId == this.getActivePanel().tabId) {
228             return true;
229         }
230         
231         if (false === cur.fireEvent('beforedeactivate')) {
232             return false;
233         }
234         
235         if(this.bullets > 0 && !Roo.isTouch){
236             this.setActiveBullet(this.indexOfPanel(pan));
237         }
238         
239         if (this.carousel && typeof(Roo.get(document.body).dom.style.transition) != 'undefined') {
240             
241             this.transition = true;
242             var dir = this.indexOfPanel(pan) > this.indexOfPanel(cur)  ? 'next' : 'prev';
243             var lr = dir == 'next' ? 'left' : 'right';
244             pan.el.addClass(dir); // or prev
245             pan.el.dom.offsetWidth; // find the offset with - causing a reflow?
246             cur.el.addClass(lr); // or right
247             pan.el.addClass(lr);
248             
249             var _this = this;
250             cur.el.on('transitionend', function() {
251                 Roo.log("trans end?");
252                 
253                 pan.el.removeClass([lr,dir]);
254                 pan.setActive(true);
255                 
256                 cur.el.removeClass([lr]);
257                 cur.setActive(false);
258                 
259                 _this.transition = false;
260                 
261             }, this, { single:  true } );
262             
263             return true;
264         }
265         
266         cur.setActive(false);
267         pan.setActive(true);
268         
269         return true;
270         
271     },
272     showPanelNext : function()
273     {
274         var i = this.indexOfPanel(this.getActivePanel());
275         
276         if (i >= this.tabs.length - 1 && !this.autoslide) {
277             return;
278         }
279         
280         if (i >= this.tabs.length - 1 && this.autoslide) {
281             i = -1;
282         }
283         
284         this.showPanel(this.tabs[i+1]);
285     },
286     
287     showPanelPrev : function()
288     {
289         var i = this.indexOfPanel(this.getActivePanel());
290         
291         if (i  < 1 && !this.autoslide) {
292             return;
293         }
294         
295         if (i < 1 && this.autoslide) {
296             i = this.tabs.length;
297         }
298         
299         this.showPanel(this.tabs[i-1]);
300     },
301     
302     
303     addBullet: function()
304     {
305         if(!this.bullets || Roo.isTouch){
306             return;
307         }
308         var ctr = this.el.select('.carousel-bullets',true).first();
309         var i = this.el.select('.carousel-bullets .bullet',true).getCount() ;
310         var bullet = ctr.createChild({
311             cls : 'bullet bullet-' + i
312         },ctr.dom.lastChild);
313         
314         
315         var _this = this;
316         
317         bullet.on('click', (function(e, el, o, ii, t){
318
319             e.preventDefault();
320
321             this.showPanel(ii);
322
323             if(this.autoslide && this.slideFn){
324                 clearInterval(this.slideFn);
325                 this.slideFn = window.setInterval(function() {
326                     _this.showPanelNext();
327                 }, this.timer);
328             }
329
330         }).createDelegate(this, [i, bullet], true));
331                 
332         
333     },
334      
335     setActiveBullet : function(i)
336     {
337         if(Roo.isTouch){
338             return;
339         }
340         
341         Roo.each(this.el.select('.bullet', true).elements, function(el){
342             el.removeClass('selected');
343         });
344
345         var bullet = this.el.select('.bullet-' + i, true).first();
346         
347         if(!bullet){
348             return;
349         }
350         
351         bullet.addClass('selected');
352     }
353     
354     
355   
356 });
357
358  
359
360  
361  
362 Roo.apply(Roo.bootstrap.TabGroup, {
363     
364     groups: {},
365      /**
366     * register a Navigation Group
367     * @param {Roo.bootstrap.NavGroup} the navgroup to add
368     */
369     register : function(navgrp)
370     {
371         this.groups[navgrp.navId] = navgrp;
372         
373     },
374     /**
375     * fetch a Navigation Group based on the navigation ID
376     * if one does not exist , it will get created.
377     * @param {string} the navgroup to add
378     * @returns {Roo.bootstrap.NavGroup} the navgroup 
379     */
380     get: function(navId) {
381         if (typeof(this.groups[navId]) == 'undefined') {
382             this.register(new Roo.bootstrap.TabGroup({ navId : navId }));
383         }
384         return this.groups[navId] ;
385     }
386     
387     
388     
389 });
390
391