4 * based on jquery fullcalendar
10 * @class Roo.bootstrap.Calendar
11 * @extends Roo.bootstrap.Component
12 * Bootstrap Calendar class
15 * Create a new Container
16 * @param {Object} config The config object
19 Roo.bootstrap.Calendar = function(config){
20 Roo.bootstrap.Calendar.superclass.constructor.call(this, config);
24 * Fires when a date is selected
25 * @param {DatePicker} this
26 * @param {Date} date The selected date
31 * Fires when the displayed month changes
32 * @param {DatePicker} this
33 * @param {Date} date The selected month
40 Roo.extend(Roo.bootstrap.Calendar, Roo.bootstrap.Component, {
43 * @cfg {Number} startDay
44 * Day index at which the week should begin, 0-based (defaults to 0, which is Sunday)
48 getAutoCreate : function(){
51 fc_button = function(name, corner, style, content ) {
54 cls : 'fc-button fc-button-'+name+' fc-state-default ' +
56 'fc-corner-' + corner.split(' ').join(' fc-corner-') :
59 html : '<SPAN class="fc-text-'+style+ '">'+content +'</SPAN>',
74 cls : 'fc-header-left',
76 fc_button('prev', 'left', 'arrow', '‹' ),
77 fc_button('next', 'right', 'arrow', '›' ),
78 { tag: 'span', cls: 'fc-header-space' },
79 fc_button('today', 'left right', '', 'today' ), // neds state disabled..
87 cls : 'fc-header-center',
91 cls: 'fc-header-title',
102 cls : 'fc-header-right',
104 fc_button('month', 'left', '', 'month' ),
105 fc_button('week', '', '', 'week' ),
106 fc_button('day', 'right', '', 'day' )
118 var cal_heads = function() {
120 // fixme - handle this.
122 for (var i =0; i < Date.dayNames.length; i++) {
123 var d = Date.dayNames[i];
126 cls : 'fc-day-header fc-' + d.substring(0,3).toLowerCase() + ' fc-widget-header',
127 html : d.substring(0,3)
131 ret[0].cls += ' fc-first';
132 ret[6].cls += ' fc-last';
135 var cal_cell = function(n) {
138 cls : 'fc-day fc-'+n + ' fc-widget-content', ///fc-other-month fc-past
143 cls: 'fc-day-number',
147 cls: 'fc-day-content',
151 style: 'position: relative;' // height: 17px;
163 var cal_rows = function() {
165 for (var r = 0; r < 6; r++) {
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()));
177 row.cn[0].cls+=' fc-first';
178 row.cn[0].cn[0].style = 'min-height:90px';
179 row.cn[6].cls+=' fc-last';
183 ret[0].cls += ' fc-first';
185 ret[5].cls += ' fc-last';
191 cls: 'fc-border-separate',
192 style : 'width:100%',
200 cls : 'fc-first fc-last',
219 style : "position: relative;",
222 cls : 'fc-view fc-view-month fc-grid',
223 style : 'position: relative',
227 cls : 'fc-event-container',
228 style : 'position:absolute;z-index:8;top:0;left:0;'
246 initEvents : function()
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');
259 resize : function() {
260 var sz = this.el.getSize();
262 this.el.select('.fc-day-header',true).setWidth(sz.width / 7);
263 this.el.select('.fc-day-content div',true).setHeight(34);
268 showPrevMonth : function(e){
269 this.update(this.activeDate.add("mo", -1));
271 showToday : function(e){
272 this.update(new Date().clearTime());
275 showNextMonth : function(e){
276 this.update(this.activeDate.add("mo", 1));
280 showPrevYear : function(){
281 this.update(this.activeDate.add("y", -1));
285 showNextYear : function(){
286 this.update(this.activeDate.add("y", 1));
291 update : function(date)
294 var vd = this.activeDate;
295 this.activeDate = date;
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){}
315 var days = date.getDaysInMonth();
316 var firstOfMonth = date.getFirstDateOfMonth();
317 var startingPos = firstOfMonth.getDay()-this.startDay;
319 if(startingPos <= this.startDay){
323 var pm = date.add("mo", -1);
324 var prevStart = pm.getDaysInMonth()-startingPos;
326 var cells = this.cells.elements;
327 var textEls = this.textNodes;
330 // convert everything to numbers so it's fast
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;
343 var setCellClass = function(cal, cell){
348 cell.className += " fc-today";
349 cell.title = cal.todayText;
352 cell.className += " fc-state-highlight";
353 //setTimeout(function(){
354 // try{cell.firstChild.focus();}catch(e){}
359 cell.className = " fc-state-disabled";
360 cell.title = cal.minText;
364 cell.className = " fc-state-disabled";
365 cell.title = cal.maxText;
369 if(ddays.indexOf(d.getDay()) != -1){
370 cell.title = ddaysText;
371 cell.className = " fc-state-disabled";
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";
381 if (!cell.initialClassName) {
382 cell.initialClassName = cell.dom.className;
384 cell.dom.className = cell.initialClassName + ' ' + cell.className;
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]);
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]);
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]);
409 this.el.select('.fc-header-title h2',true).update(Date.monthNames[date.getMonth()] + " " + date.getFullYear());
410 this.fireEvent('monthchange', this, date);
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]);