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