714a92af36cf4982b7bb7aeddd0b8eb4e981c14c
[roojs1] / Roo / bootstrap / Calendar.js
1 /*
2  * - LGPL
3  *
4  * based on jquery fullcalendar
5  * 
6  */
7
8
9 /**
10  * @class Roo.bootstrap.Calendar
11  * @extends Roo.bootstrap.Component
12  * Bootstrap Calendar class
13     
14  * @constructor
15  * Create a new Container
16  * @param {Object} config The config object
17  */
18
19 Roo.bootstrap.Calendar = function(config){
20     Roo.bootstrap.Calendar.superclass.constructor.call(this, config);
21 };
22
23 Roo.extend(Roo.bootstrap.Calendar, Roo.bootstrap.Component,  {
24     
25      
26       
27     getAutoCreate : function(){
28         
29         
30         fc_button = function(name, corner, style, content ) {
31             return Roo.apply({},{
32                 tag : 'span',
33                 cls : 'fc-button fc-button-'+name+' fc-state-default ' + 
34                          (corner.length ?
35                             'fc-corner-' + corner.split(' ').join(' fc-corner-') :
36                             ''
37                         ),
38                 html : '<SPAN class="fc-text-'+style+ '">'+content +'</SPAN>',
39                 unselectable: 'on'
40             });
41         };
42         
43         var header = {
44             tag : 'table',
45             cls : 'fc-header',
46             style : 'width:100%',
47             cn : [
48                 {
49                     tag: 'tr',
50                     cn : [
51                         {
52                             tag : 'td',
53                             cls : 'fc-header-left',
54                             cn : [
55                                 fc_button('prev', 'left', 'arrow', '&#8249;' ),
56                                 fc_button('next', 'right', 'arrow', '&#8250;' ),
57                                 { tag: 'span', cls: 'fc-header-space' },
58                                 fc_button('today', 'left right', '', 'today' ), // neds state disabled..
59                                 
60                                 
61                             ]
62                         },
63                         
64                         {
65                             tag : 'td',
66                             cls : 'fc-header-center',
67                             cn : [
68                                 {
69                                     tag: 'span',
70                                     cls: 'fc-header-title',
71                                     cn : {
72                                         tag: 'H2',
73                                         html : 'month / year'
74                                     }
75                                 }
76                                 
77                             ]
78                         },
79                         {
80                             tag : 'td',
81                             cls : 'fc-header-right',
82                             cn : [
83                                 fc_button('month', 'left', '', 'month' ),
84                                 fc_button('week', '', '', 'week' ),
85                                 fc_button('day', 'right', '', 'day' )
86                                 
87                                 
88                             ]
89                         },
90                         
91                     ]
92                 }
93             ]
94         };
95         
96        
97         var cal_heads = function() {
98             var ret = [];
99             for (var i =0; i < Date.dayNames.length; i++) {
100                 var d = Date.dayNames[i];
101                 ret.push({
102                     tag: 'th',
103                     cls : 'fc-day-header fc-' + d.substring(0,3).toLowerCase() + ' fc-widget-header',
104                     html : d.substring(0,3)
105                 });
106                 
107             }
108             ret[0].cls += ' fc-first';
109             ret[6].cls += ' fc-last';
110             return ret;
111         };
112         var cal_cell = function(n) {
113             return  {
114                 tag: 'td',
115                 cls : 'fc-day fc-'+n + ' fc-widget-content', ///fc-other-month fc-past
116                 cn : [
117                     {
118                         cn : [
119                             {
120                                 cls: 'fc-day-number',
121                                 html: 'D'
122                             },
123                             {
124                                 cls: 'fc-day-content',
125                              
126                                 cn : [
127                                      {
128                                         style: 'position: relative;' // height: 17px;
129                                     }
130                                 ]
131                             }
132                             
133                             
134                         ]
135                     }
136                 ]
137                 
138             }
139         };
140         var cal_rows = function() {
141             var ret = []
142             for (var r = 0; r < 6; r++) {
143                 var row= {
144                     tag : 'tr',
145                     cls : 'fc-week',
146                     cn : []
147                 };
148                 
149                 for (var i =0; i < Date.dayNames.length; i++) {
150                     var d = Date.dayNames[i];
151                     row.cn.push(cal_cell(d.substring(0,3).toLowerCase()));
152
153                 }
154                 row.cn[0].cls+=' fc-first';
155                 row.cn[0].cn[0].style = 'min-height:90px';
156                 row.cn[6].cls+=' fc-last';
157                 ret.push(row);
158                 
159             }
160             ret[0].cls += ' fc-first';
161            
162             ret[5].cls += ' fc-last';
163             return ret;
164             
165         };
166         var cal_table = {
167             tag: 'table',
168             cls: 'fc-border-separate',
169             style : 'width:100%',
170             cellspacing  : 0,
171             cn : [
172                 { 
173                     tag: 'thead',
174                     cn : [
175                         { 
176                             tag: 'tr',
177                             cls : 'fc-first fc-last',
178                             cn : cal_heads()
179                         }
180                     ]
181                 },
182                 { 
183                     tag: 'tbody',
184                     cn : cal_rows()
185                 }
186                   
187             ]
188         };
189          
190          var cfg = {
191             cls : 'fc fc-ltr',
192             cn : [
193                 header,
194                 {
195                     cls : 'fc-content',
196                     style : "position: relative;",
197                     cn : [
198                         {
199                             cls : 'fc-view fc-view-month fc-grid',
200                             style : 'position: relative',
201                             unselectable : 'on',
202                             cn : [
203                                 {
204                                     cls : 'fc-event-container',
205                                     style : 'position:absolute;z-index:8;top:0;left:0;'
206                                 },
207                                 cal_table
208                             ]
209                         }
210                     ]
211     
212                 }
213            ] 
214             
215         };
216         
217          
218         
219         return cfg;
220     },
221     
222     
223     initEvents : function()
224     {
225         this.resize();
226         this.cells = this.el.query('.fc-day');
227         this.textNodes = this.el.query('.fc-day-number');
228         try { 
229             this.update(new Date());
230         catch(e) {
231             Roo.log(e);
232         }
233         
234         
235     },
236     resize : function() {
237         var sz  = this.el.getSize();
238         
239         this.el.select('.fc-day-header',true).setWidth(sz.width / 7);
240         this.el.select('.fc-day-content div',true).setHeight(34);
241     },
242    // private
243     update : function(date)
244     {
245         var vd = this.activeDate;
246         this.activeDate = date;
247         if(vd && this.el){
248             var t = date.getTime();
249             if(vd.getMonth() == date.getMonth() && vd.getFullYear() == date.getFullYear()){
250                 this.cells.removeClass("fc-state-highlight");
251                 this.cells.each(function(c){
252                    if(c.dom.firstChild.dateValue == t){
253                        c.addClass("fc-state-highlight");
254                        setTimeout(function(){
255                             try{c.dom.firstChild.focus();}catch(e){}
256                        }, 50);
257                        return false;
258                    }
259                    return true;
260                 });
261                 return;
262             }
263         }
264         
265         var days = date.getDaysInMonth();
266         var firstOfMonth = date.getFirstDateOfMonth();
267         var startingPos = firstOfMonth.getDay()-this.startDay;
268
269         if(startingPos <= this.startDay){
270             startingPos += 7;
271         }
272
273         var pm = date.add("mo", -1);
274         var prevStart = pm.getDaysInMonth()-startingPos;
275
276         var cells = this.cells.elements;
277         var textEls = this.textNodes;
278         days += startingPos;
279
280         // convert everything to numbers so it's fast
281         var day = 86400000;
282         var d = (new Date(pm.getFullYear(), pm.getMonth(), prevStart)).clearTime();
283         var today = new Date().clearTime().getTime();
284         var sel = date.clearTime().getTime();
285         var min = this.minDate ? this.minDate.clearTime() : Number.NEGATIVE_INFINITY;
286         var max = this.maxDate ? this.maxDate.clearTime() : Number.POSITIVE_INFINITY;
287         var ddMatch = this.disabledDatesRE;
288         var ddText = this.disabledDatesText;
289         var ddays = this.disabledDays ? this.disabledDays.join("") : false;
290         var ddaysText = this.disabledDaysText;
291         var format = this.format;
292
293         var setCellClass = function(cal, cell){
294             cell.title = "";
295             var t = d.getTime();
296             cell.firstChild.dateValue = t;
297             if(t == today){
298                 cell.className += " fc-today";
299                 cell.title = cal.todayText;
300             }
301             if(t == sel){
302                 cell.className += " fc-state-highlight";
303                 setTimeout(function(){
304                     try{cell.firstChild.focus();}catch(e){}
305                 }, 50);
306             }
307             // disabling
308             if(t < min) {
309                 cell.className = " fc-state-disabled";
310                 cell.title = cal.minText;
311                 return;
312             }
313             if(t > max) {
314                 cell.className = " fc-state-disabled";
315                 cell.title = cal.maxText;
316                 return;
317             }
318             if(ddays){
319                 if(ddays.indexOf(d.getDay()) != -1){
320                     cell.title = ddaysText;
321                     cell.className = " fc-state-disabled";
322                 }
323             }
324             if(ddMatch && format){
325                 var fvalue = d.dateFormat(format);
326                 if(ddMatch.test(fvalue)){
327                     cell.title = ddText.replace("%0", fvalue);
328                     cell.className = " fc-state-disabled";
329                 }
330             }
331         };
332
333         var i = 0;
334         for(; i < startingPos; i++) {
335             textEls[i].innerHTML = (++prevStart);
336             d.setDate(d.getDate()+1);
337             cells[i].className = "x-date-prevday";
338             setCellClass(this, cells[i]);
339         }
340         for(; i < days; i++){
341             intDay = i - startingPos + 1;
342             textEls[i].innerHTML = (intDay);
343             d.setDate(d.getDate()+1);
344             cells[i].className = "x-date-active";
345             setCellClass(this, cells[i]);
346         }
347         var extraDays = 0;
348         for(; i < 42; i++) {
349              textEls[i].innerHTML = (++extraDays);
350              d.setDate(d.getDate()+1);
351              cells[i].className = "x-date-nextday";
352              setCellClass(this, cells[i]);
353         }
354
355         this.mbtn.setText(this.monthNames[date.getMonth()] + " " + date.getFullYear());
356         this.fireEvent('monthchange', this, date);
357         
358         if(!this.internalRender){
359             var main = this.el.dom.firstChild;
360             var w = main.offsetWidth;
361             this.el.setWidth(w + this.el.getBorderWidth("lr"));
362             Roo.fly(main).setWidth(w);
363             this.internalRender = true;
364             // opera does not respect the auto grow header center column
365             // then, after it gets a width opera refuses to recalculate
366             // without a second pass
367             if(Roo.isOpera && !this.secondPass){
368                 main.rows[0].cells[1].style.width = (w - (main.rows[0].cells[0].offsetWidth+main.rows[0].cells[2].offsetWidth)) + "px";
369                 this.secondPass = true;
370                 this.update.defer(10, this, [date]);
371             }
372         }
373         
374         
375     }
376 });
377
378