2d1798e445f7b64e428e2c06f08e214d09a0af70
[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.
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().clearTime());
252         this.el.select('.fc-button-prev',true).on('click', this.showPrevMonth, this);
253         this.el.select('.fc-button-next',true).on('click', this.showNextMonth, this);
254         this.el.select('.fc-button-today',true).on('click', this.showToday, this);
255         this.el.select('.fc-button',true).addClassOnOver('fc-state-hover');
256         this.cells.addClassOnOver('fc-state-hover');
257         
258     },
259     resize : function() {
260         var sz  = this.el.getSize();
261         
262         this.el.select('.fc-day-header',true).setWidth(sz.width / 7);
263         this.el.select('.fc-day-content div',true).setHeight(34);
264     },
265     
266     
267     // private
268     showPrevMonth : function(e){
269         this.update(this.activeDate.add("mo", -1));
270     },
271     showToday : function(e){
272         this.update(new Date().clearTime());
273     },
274     // private
275     showNextMonth : function(e){
276         this.update(this.activeDate.add("mo", 1));
277     },
278
279     // private
280     showPrevYear : function(){
281         this.update(this.activeDate.add("y", -1));
282     },
283
284     // private
285     showNextYear : function(){
286         this.update(this.activeDate.add("y", 1));
287     },
288
289     
290    // private
291     update : function(date)
292     {
293        
294         var vd = this.activeDate;
295         this.activeDate = date;
296         if(vd && this.el){
297             var t = date.getTime();
298             if(vd.getMonth() == date.getMonth() && vd.getFullYear() == date.getFullYear()){
299                 Roo.log('using add remove');
300                 this.cells.removeClass("fc-state-highlight");
301                 this.cells.each(function(c){
302                    if(c.dateValue == t){
303                        c.addClass("fc-state-highlight");
304                        setTimeout(function(){
305                             try{c.dom.firstChild.focus();}catch(e){}
306                        }, 50);
307                        return false;
308                    }
309                    return true;
310                 });
311                 return;
312             }
313         }
314         
315         var days = date.getDaysInMonth();
316         var firstOfMonth = date.getFirstDateOfMonth();
317         var startingPos = firstOfMonth.getDay()-this.startDay;
318
319         if(startingPos <= this.startDay){
320             startingPos += 7;
321         }
322
323         var pm = date.add("mo", -1);
324         var prevStart = pm.getDaysInMonth()-startingPos;
325
326         var cells = this.cells.elements;
327         var textEls = this.textNodes;
328         days += startingPos;
329
330         // convert everything to numbers so it's fast
331         var day = 86400000;
332         var d = (new Date(pm.getFullYear(), pm.getMonth(), prevStart)).clearTime();
333         var today = new Date().clearTime().getTime();
334         var sel = date.clearTime().getTime();
335         var min = this.minDate ? this.minDate.clearTime() : Number.NEGATIVE_INFINITY;
336         var max = this.maxDate ? this.maxDate.clearTime() : Number.POSITIVE_INFINITY;
337         var ddMatch = this.disabledDatesRE;
338         var ddText = this.disabledDatesText;
339         var ddays = this.disabledDays ? this.disabledDays.join("") : false;
340         var ddaysText = this.disabledDaysText;
341         var format = this.format;
342
343         var setCellClass = function(cal, cell){
344             cell.title = "";
345             var t = d.getTime();
346             cell.dateValue = t;
347             if(t == today){
348                 cell.className += " fc-today";
349                 cell.title = cal.todayText;
350             }
351             if(t == sel){
352                 cell.className += " fc-state-highlight";
353                 //setTimeout(function(){
354                 //    try{cell.firstChild.focus();}catch(e){}
355                 //}, 50);
356             }
357             // disabling
358             if(t < min) {
359                 cell.className = " fc-state-disabled";
360                 cell.title = cal.minText;
361                 return;
362             }
363             if(t > max) {
364                 cell.className = " fc-state-disabled";
365                 cell.title = cal.maxText;
366                 return;
367             }
368             if(ddays){
369                 if(ddays.indexOf(d.getDay()) != -1){
370                     cell.title = ddaysText;
371                     cell.className = " fc-state-disabled";
372                 }
373             }
374             if(ddMatch && format){
375                 var fvalue = d.dateFormat(format);
376                 if(ddMatch.test(fvalue)){
377                     cell.title = ddText.replace("%0", fvalue);
378                     cell.className = " fc-state-disabled";
379                 }
380             }
381             if (!cell.initialClassName) {
382                 cell.initialClassName = cell.dom.className;
383             }
384             cell.dom.className = cell.initialClassName  + ' ' +  cell.className;
385         };
386
387         var i = 0;
388         for(; i < startingPos; i++) {
389             textEls[i].innerHTML = (++prevStart);
390             d.setDate(d.getDate()+1);
391             cells[i].className = "fc-past fc-other-month";
392             setCellClass(this, cells[i]);
393         }
394         for(; i < days; i++){
395             intDay = i - startingPos + 1;
396             textEls[i].innerHTML = (intDay);
397             d.setDate(d.getDate()+1);
398             cells[i].className = ''; // "x-date-active";
399             setCellClass(this, cells[i]);
400         }
401         var extraDays = 0;
402         for(; i < 42; i++) {
403              textEls[i].innerHTML = (++extraDays);
404              d.setDate(d.getDate()+1);
405              cells[i].className = "fc-future fc-other-month";
406              setCellClass(this, cells[i]);
407         }
408
409         this.el.select('.fc-header-title h2',true).update(Date.monthNames[date.getMonth()] + " " + date.getFullYear());
410         this.fireEvent('monthchange', this, date);
411         
412         
413         /*
414         if(!this.internalRender){
415             var main = this.el.dom.firstChild;
416             var w = main.offsetWidth;
417             this.el.setWidth(w + this.el.getBorderWidth("lr"));
418             Roo.fly(main).setWidth(w);
419             this.internalRender = true;
420             // opera does not respect the auto grow header center column
421             // then, after it gets a width opera refuses to recalculate
422             // without a second pass
423             if(Roo.isOpera && !this.secondPass){
424                 main.rows[0].cells[1].style.width = (w - (main.rows[0].cells[0].offsetWidth+main.rows[0].cells[2].offsetWidth)) + "px";
425                 this.secondPass = true;
426                 this.update.defer(10, this, [date]);
427             }
428         }
429         */
430         
431     }
432 });
433
434