Roo/bootstrap/Calendar.js
[roojs1] / Roo / bootstrap / Calendar.js
1 /*
2  * - LGPL
3  *
4  * based on jquery fullcalendar
5  * 
6  */
7
8 Roo.bootstrap = Roo.bootstrap || {};
9 /**
10  * @class Roo.bootstrap.Calendar
11  * @extends Roo.bootstrap.Component
12  * Bootstrap Calendar class
13  * @cfg {Boolean} loadMask (true|false) default false
14  * @cfg {Object} header generate the user specific header of the calendar, default false
15
16  * @constructor
17  * Create a new Container
18  * @param {Object} config The config object
19  */
20
21
22
23 Roo.bootstrap.Calendar = function(config){
24     Roo.bootstrap.Calendar.superclass.constructor.call(this, config);
25      this.addEvents({
26         /**
27              * @event select
28              * Fires when a date is selected
29              * @param {DatePicker} this
30              * @param {Date} date The selected date
31              */
32         'select': true,
33         /**
34              * @event monthchange
35              * Fires when the displayed month changes 
36              * @param {DatePicker} this
37              * @param {Date} date The selected month
38              */
39         'monthchange': true,
40         /**
41              * @event evententer
42              * Fires when mouse over an event
43              * @param {Calendar} this
44              * @param {event} Event
45              */
46         'evententer': true,
47         /**
48              * @event eventleave
49              * Fires when the mouse leaves an
50              * @param {Calendar} this
51              * @param {event}
52              */
53         'eventleave': true,
54         /**
55              * @event eventclick
56              * Fires when the mouse click an
57              * @param {Calendar} this
58              * @param {event}
59              */
60         'eventclick': true
61         
62     });
63
64 };
65
66 Roo.extend(Roo.bootstrap.Calendar, Roo.bootstrap.Component,  {
67     
68      /**
69      * @cfg {Number} startDay
70      * Day index at which the week should begin, 0-based (defaults to 0, which is Sunday)
71      */
72     startDay : 0,
73     
74     loadMask : false,
75     
76     header : false,
77       
78     getAutoCreate : function(){
79         
80         
81         var fc_button = function(name, corner, style, content ) {
82             return Roo.apply({},{
83                 tag : 'span',
84                 cls : 'fc-button fc-button-'+name+' fc-state-default ' + 
85                          (corner.length ?
86                             'fc-corner-' + corner.split(' ').join(' fc-corner-') :
87                             ''
88                         ),
89                 html : '<SPAN class="fc-text-'+style+ '">'+content +'</SPAN>',
90                 unselectable: 'on'
91             });
92         };
93         
94         var header = {};
95         
96         if(!this.header){
97             header = {
98                 tag : 'table',
99                 cls : 'fc-header',
100                 style : 'width:100%',
101                 cn : [
102                     {
103                         tag: 'tr',
104                         cn : [
105                             {
106                                 tag : 'td',
107                                 cls : 'fc-header-left',
108                                 cn : [
109                                     fc_button('prev', 'left', 'arrow', '&#8249;' ),
110                                     fc_button('next', 'right', 'arrow', '&#8250;' ),
111                                     { tag: 'span', cls: 'fc-header-space' },
112                                     fc_button('today', 'left right', '', 'today' )  // neds state disabled..
113
114
115                                 ]
116                             },
117
118                             {
119                                 tag : 'td',
120                                 cls : 'fc-header-center',
121                                 cn : [
122                                     {
123                                         tag: 'span',
124                                         cls: 'fc-header-title',
125                                         cn : {
126                                             tag: 'H2',
127                                             html : 'month / year'
128                                         }
129                                     }
130
131                                 ]
132                             },
133                             {
134                                 tag : 'td',
135                                 cls : 'fc-header-right',
136                                 cn : [
137                               /*      fc_button('month', 'left', '', 'month' ),
138                                     fc_button('week', '', '', 'week' ),
139                                     fc_button('day', 'right', '', 'day' )
140                                 */    
141
142                                 ]
143                             }
144
145                         ]
146                     }
147                 ]
148             };
149         }
150         
151         header = this.header;
152         
153        
154         var cal_heads = function() {
155             var ret = [];
156             // fixme - handle this.
157             
158             for (var i =0; i < Date.dayNames.length; i++) {
159                 var d = Date.dayNames[i];
160                 ret.push({
161                     tag: 'th',
162                     cls : 'fc-day-header fc-' + d.substring(0,3).toLowerCase() + ' fc-widget-header',
163                     html : d.substring(0,3)
164                 });
165                 
166             }
167             ret[0].cls += ' fc-first';
168             ret[6].cls += ' fc-last';
169             return ret;
170         };
171         var cal_cell = function(n) {
172             return  {
173                 tag: 'td',
174                 cls : 'fc-day fc-'+n + ' fc-widget-content', ///fc-other-month fc-past
175                 cn : [
176                     {
177                         cn : [
178                             {
179                                 cls: 'fc-day-number',
180                                 html: 'D'
181                             },
182                             {
183                                 cls: 'fc-day-content',
184                              
185                                 cn : [
186                                      {
187                                         style: 'position: relative;' // height: 17px;
188                                     }
189                                 ]
190                             }
191                             
192                             
193                         ]
194                     }
195                 ]
196                 
197             }
198         };
199         var cal_rows = function() {
200             
201             var ret = []
202             for (var r = 0; r < 6; r++) {
203                 var row= {
204                     tag : 'tr',
205                     cls : 'fc-week',
206                     cn : []
207                 };
208                 
209                 for (var i =0; i < Date.dayNames.length; i++) {
210                     var d = Date.dayNames[i];
211                     row.cn.push(cal_cell(d.substring(0,3).toLowerCase()));
212
213                 }
214                 row.cn[0].cls+=' fc-first';
215                 row.cn[0].cn[0].style = 'min-height:90px';
216                 row.cn[6].cls+=' fc-last';
217                 ret.push(row);
218                 
219             }
220             ret[0].cls += ' fc-first';
221             ret[4].cls += ' fc-prev-last';
222             ret[5].cls += ' fc-last';
223             return ret;
224             
225         };
226         
227         var cal_table = {
228             tag: 'table',
229             cls: 'fc-border-separate',
230             style : 'width:100%',
231             cellspacing  : 0,
232             cn : [
233                 { 
234                     tag: 'thead',
235                     cn : [
236                         { 
237                             tag: 'tr',
238                             cls : 'fc-first fc-last',
239                             cn : cal_heads()
240                         }
241                     ]
242                 },
243                 { 
244                     tag: 'tbody',
245                     cn : cal_rows()
246                 }
247                   
248             ]
249         };
250          
251          var cfg = {
252             cls : 'fc fc-ltr',
253             cn : [
254                 header,
255                 {
256                     cls : 'fc-content',
257                     style : "position: relative;",
258                     cn : [
259                         {
260                             cls : 'fc-view fc-view-month fc-grid',
261                             style : 'position: relative',
262                             unselectable : 'on',
263                             cn : [
264                                 {
265                                     cls : 'fc-event-container',
266                                     style : 'position:absolute;z-index:8;top:0;left:0;'
267                                 },
268                                 cal_table
269                             ]
270                         }
271                     ]
272     
273                 }
274            ] 
275             
276         };
277         
278          
279         
280         return cfg;
281     },
282     
283     
284     initEvents : function()
285     {
286         if(!this.store){
287             throw "can not find store for calendar";
288         }
289         
290         var mark = {
291             tag: "div",
292             cls:"x-dlg-mask",
293             style: "text-align:center",
294             cn: [
295                 {
296                     tag: "div",
297                     style: "background-color:white;width:50%;margin:250 auto",
298                     cn: [
299                         {
300                             tag: "img",
301                             src: rootURL + '/roojs1/images/ux/lightbox/loading.gif'
302                         },
303                         {
304                             tag: "span",
305                             html: "Loading"
306                         }
307                         
308                     ]
309                 }
310             ]
311         }
312         this.maskEl = Roo.DomHelper.append(this.el.select('.fc-content', true).first(), mark, true);
313         
314         var size = this.el.select('.fc-content', true).first().getSize();
315         this.maskEl.setSize(size.width, size.height);
316         this.maskEl.enableDisplayMode("block");
317         if(!this.loadMask){
318             this.maskEl.hide();
319         }
320         
321         this.store = Roo.factory(this.store, Roo.data);
322         this.store.on('load', this.onLoad, this);
323         this.store.on('beforeload', this.onBeforeLoad, this);
324         
325         this.resize();
326         
327         this.cells = this.el.select('.fc-day',true);
328         //Roo.log(this.cells);
329         this.textNodes = this.el.query('.fc-day-number');
330         this.cells.addClassOnOver('fc-state-hover');
331         
332         this.el.select('.fc-button-prev',true).on('click', this.showPrevMonth, this);
333         this.el.select('.fc-button-next',true).on('click', this.showNextMonth, this);
334         this.el.select('.fc-button-today',true).on('click', this.showToday, this);
335         this.el.select('.fc-button',true).addClassOnOver('fc-state-hover');
336         
337         this.on('monthchange', this.onMonthChange, this);
338         
339         this.update(new Date().clearTime());
340     },
341     
342     resize : function() {
343         var sz  = this.el.getSize();
344         
345         this.el.select('.fc-day-header',true).setWidth(sz.width / 7);
346         this.el.select('.fc-day-content div',true).setHeight(34);
347     },
348     
349     
350     // private
351     showPrevMonth : function(e){
352         this.update(this.activeDate.add("mo", -1));
353     },
354     showToday : function(e){
355         this.update(new Date().clearTime());
356     },
357     // private
358     showNextMonth : function(e){
359         this.update(this.activeDate.add("mo", 1));
360     },
361
362     // private
363     showPrevYear : function(){
364         this.update(this.activeDate.add("y", -1));
365     },
366
367     // private
368     showNextYear : function(){
369         this.update(this.activeDate.add("y", 1));
370     },
371
372     
373    // private
374     update : function(date)
375     {
376         var vd = this.activeDate;
377         this.activeDate = date;
378 //        if(vd && this.el){
379 //            var t = date.getTime();
380 //            if(vd.getMonth() == date.getMonth() && vd.getFullYear() == date.getFullYear()){
381 //                Roo.log('using add remove');
382 //                
383 //                this.fireEvent('monthchange', this, date);
384 //                
385 //                this.cells.removeClass("fc-state-highlight");
386 //                this.cells.each(function(c){
387 //                   if(c.dateValue == t){
388 //                       c.addClass("fc-state-highlight");
389 //                       setTimeout(function(){
390 //                            try{c.dom.firstChild.focus();}catch(e){}
391 //                       }, 50);
392 //                       return false;
393 //                   }
394 //                   return true;
395 //                });
396 //                return;
397 //            }
398 //        }
399         
400         var days = date.getDaysInMonth();
401         
402         var firstOfMonth = date.getFirstDateOfMonth();
403         var startingPos = firstOfMonth.getDay()-this.startDay;
404         
405         if(startingPos < this.startDay){
406             startingPos += 7;
407         }
408         
409         var pm = date.add(Date.MONTH, -1);
410         var prevStart = pm.getDaysInMonth()-startingPos;
411 //        
412         this.cells = this.el.select('.fc-day',true);
413         this.textNodes = this.el.query('.fc-day-number');
414         this.cells.addClassOnOver('fc-state-hover');
415         
416         var cells = this.cells.elements;
417         var textEls = this.textNodes;
418         
419         Roo.each(cells, function(cell){
420             cell.removeClass([ 'fc-past', 'fc-other-month', 'fc-future', 'fc-state-highlight', 'fc-state-disabled']);
421         });
422         
423         days += startingPos;
424
425         // convert everything to numbers so it's fast
426         var day = 86400000;
427         var d = (new Date(pm.getFullYear(), pm.getMonth(), prevStart)).clearTime();
428         //Roo.log(d);
429         //Roo.log(pm);
430         //Roo.log(prevStart);
431         
432         var today = new Date().clearTime().getTime();
433         var sel = date.clearTime().getTime();
434         var min = this.minDate ? this.minDate.clearTime() : Number.NEGATIVE_INFINITY;
435         var max = this.maxDate ? this.maxDate.clearTime() : Number.POSITIVE_INFINITY;
436         var ddMatch = this.disabledDatesRE;
437         var ddText = this.disabledDatesText;
438         var ddays = this.disabledDays ? this.disabledDays.join("") : false;
439         var ddaysText = this.disabledDaysText;
440         var format = this.format;
441         
442         var setCellClass = function(cal, cell){
443             cell.row = 0;
444             cell.events = [];
445             cell.more = [];
446             cell.inhertance = 0;
447             //Roo.log('set Cell Class');
448             cell.title = "";
449             var t = d.getTime();
450             
451             //Roo.log(d);
452             
453             cell.dateValue = t;
454             if(t == today){
455                 cell.className += " fc-today";
456                 cell.className += " fc-state-highlight";
457                 cell.title = cal.todayText;
458             }
459             if(t == sel){
460                 // disable highlight in other month..
461                 //cell.className += " fc-state-highlight";
462                 
463             }
464             // disabling
465             if(t < min) {
466                 cell.className = " fc-state-disabled";
467                 cell.title = cal.minText;
468                 return;
469             }
470             if(t > max) {
471                 cell.className = " fc-state-disabled";
472                 cell.title = cal.maxText;
473                 return;
474             }
475             if(ddays){
476                 if(ddays.indexOf(d.getDay()) != -1){
477                     cell.title = ddaysText;
478                     cell.className = " fc-state-disabled";
479                 }
480             }
481             if(ddMatch && format){
482                 var fvalue = d.dateFormat(format);
483                 if(ddMatch.test(fvalue)){
484                     cell.title = ddText.replace("%0", fvalue);
485                     cell.className = " fc-state-disabled";
486                 }
487             }
488             
489             if (!cell.initialClassName) {
490                 cell.initialClassName = cell.dom.className;
491             }
492             
493             cell.dom.className = cell.initialClassName  + ' ' +  cell.className;
494         };
495
496         var i = 0;
497         
498         for(; i < startingPos; i++) {
499             textEls[i].innerHTML = (++prevStart);
500             d.setDate(d.getDate()+1);
501             
502             cells[i].className = "fc-past fc-other-month";
503             setCellClass(this, cells[i]);
504         }
505         
506         var intDay = 0;
507         
508         for(; i < days; i++){
509             intDay = i - startingPos + 1;
510             textEls[i].innerHTML = (intDay);
511             d.setDate(d.getDate()+1);
512             
513             cells[i].className = ''; // "x-date-active";
514             setCellClass(this, cells[i]);
515         }
516         var extraDays = 0;
517         
518         for(; i < 42; i++) {
519             textEls[i].innerHTML = (++extraDays);
520             d.setDate(d.getDate()+1);
521             
522             cells[i].className = "fc-future fc-other-month";
523             setCellClass(this, cells[i]);
524         }
525         
526         this.el.select('.fc-header-title h2',true).update(Date.monthNames[date.getMonth()] + " " + date.getFullYear());
527         
528         var totalRows = Math.ceil((date.getDaysInMonth() + date.getFirstDateOfMonth().getDay()) / 7);
529         
530         this.el.select('tr.fc-week.fc-prev-last',true).removeClass('fc-last');
531         this.el.select('tr.fc-week.fc-next-last',true).addClass('fc-last').show();
532         
533         if(totalRows != 6){
534             this.el.select('tr.fc-week.fc-last',true).removeClass('fc-last').addClass('fc-next-last').hide();
535             this.el.select('tr.fc-week.fc-prev-last',true).addClass('fc-last');
536         }
537         
538         this.fireEvent('monthchange', this, date);
539         
540         
541         /*
542         if(!this.internalRender){
543             var main = this.el.dom.firstChild;
544             var w = main.offsetWidth;
545             this.el.setWidth(w + this.el.getBorderWidth("lr"));
546             Roo.fly(main).setWidth(w);
547             this.internalRender = true;
548             // opera does not respect the auto grow header center column
549             // then, after it gets a width opera refuses to recalculate
550             // without a second pass
551             if(Roo.isOpera && !this.secondPass){
552                 main.rows[0].cells[1].style.width = (w - (main.rows[0].cells[0].offsetWidth+main.rows[0].cells[2].offsetWidth)) + "px";
553                 this.secondPass = true;
554                 this.update.defer(10, this, [date]);
555             }
556         }
557         */
558         
559     },
560     
561     findCell : function(dt) {
562         dt = dt.clearTime().getTime();
563         var ret = false;
564         this.cells.each(function(c){
565             //Roo.log("check " +c.dateValue + '?=' + dt);
566             if(c.dateValue == dt){
567                 ret = c;
568                 return false;
569             }
570             return true;
571         });
572         
573         return ret;
574     },
575     
576     findCells : function(ev) {
577         var s = ev.start.clone().clearTime().getTime();
578        // Roo.log(s);
579         var e= ev.end.clone().clearTime().getTime();
580        // Roo.log(e);
581         var ret = [];
582         this.cells.each(function(c){
583              ////Roo.log("check " +c.dateValue + '<' + e + ' > ' + s);
584             
585             if(c.dateValue > e){
586                 return ;
587             }
588             if(c.dateValue < s){
589                 return ;
590             }
591             ret.push(c);
592         });
593         
594         return ret;    
595     },
596     
597 //    findBestRow: function(cells)
598 //    {
599 //        var ret = 0;
600 //        
601 //        for (var i =0 ; i < cells.length;i++) {
602 //            ret  = Math.max(cells[i].rows || 0,ret);
603 //        }
604 //        return ret;
605 //        
606 //    },
607     
608     
609     addItem : function(ev)
610     {
611         // look for vertical location slot in
612         var cells = this.findCells(ev);
613         
614 //        ev.row = this.findBestRow(cells);
615         
616         // work out the location.
617         
618         var crow = false;
619         var rows = [];
620         for(var i =0; i < cells.length; i++) {
621             
622             cells[i].inhertance = cells[i].inhertance + 1;
623             
624             if(i == 0){
625                 cells[i].row = cells[i].row + 1;
626                 cells[i].inhertance = cells[i].inhertance - 1;
627             }
628             
629             if (!crow) {
630                 crow = {
631                     start : cells[i],
632                     end :  cells[i]
633                 };
634                 continue;
635             }
636             if (crow.start.getY() == cells[i].getY()) {
637                 // on same row.
638                 crow.end = cells[i];
639                 continue;
640             }
641             // different row.
642             rows.push(crow);
643             crow = {
644                 start: cells[i],
645                 end : cells[i]
646             };
647             
648         }
649         
650         rows.push(crow);
651         ev.els = [];
652         ev.rows = rows;
653         ev.cells = cells;
654         
655         cells[0].events.push(ev);
656         
657 //        if((typeof(cells[0].events) == 'undefined')){
658 //            cells[0].events = [];
659 //        }
660 //        
661 //        cells[0].events.push(ev);
662 //        ev.rendered = false;
663 //        for (var i = 0; i < cells.length;i++) {
664 //            cells[i].rows = Math.max(cells[i].rows || 0 , ev.row + 1 );
665 //            
666 //        }
667         
668         this.calevents.push(ev);
669     },
670     
671     clearEvents: function() {
672         
673         if(!this.calevents){
674             return;
675         }
676         
677         Roo.each(this.cells.elements, function(c){
678             c.row = 0;
679             c.events = [];
680             c.more = [];
681         });
682         
683         Roo.each(this.calevents, function(e) {
684             Roo.each(e.els, function(el) {
685                 el.un('mouseenter' ,this.onEventEnter, this);
686                 el.un('mouseleave' ,this.onEventLeave, this);
687                 el.remove();
688             },this);
689         },this);
690         
691         Roo.each(Roo.select('.fc-more-event', true).elements, function(e){
692             e.remove();
693         });
694         
695     },
696     
697     renderEvents: function()
698     {  
699 //        for (var e = 0; e < this.calevents.length; e++) {
700 //            
701 //            var ev = this.calevents[e];
702 //            var cells = ev.cells;
703 //            var rows = ev.rows;
704 //            
705 //            for (var j = 0; j < cells.length; j++){
706 //            
707 //                if(!cells[j].more.length){
708 //                    cells[j].row++;
709 //                }
710 //                if(cells[j].row > 3){
711 //                    cells[j].more.push(ev);
712 //                    continue;
713 //                }
714 //                
715 //                cells[j].events.push(ev);
716 //            }
717 //        }
718             
719 //            for (var i = 0; i < rows.length; i++){
720 //                // how many rows should it span..
721 //
722 //                var  cfg = {
723 //                    cls : 'roo-dynamic fc-event fc-event-hori fc-event-draggable ui-draggable',
724 //                    style : 'position: absolute', // left: 387px; width: 121px; top: 359px;
725 //
726 //                    unselectable : "on",
727 //                    cn : [
728 //                        {
729 //                            cls: 'fc-event-inner',
730 //                            cn : [
731 ////                                {
732 ////                                  tag:'span',
733 ////                                  cls: 'fc-event-time',
734 ////                                  html : cells.length > 1 ? '' : ev.time
735 ////                                },
736 //                                {
737 //                                  tag:'span',
738 //                                  cls: 'fc-event-title',
739 //                                  html : String.format('{0}', ev.title)
740 //                                }
741 //
742 //
743 //                            ]
744 //                        },
745 //                        {
746 //                            cls: 'ui-resizable-handle ui-resizable-e',
747 //                            html : '&nbsp;&nbsp;&nbsp'
748 //                        }
749 //
750 //                    ]
751 //                };
752 //
753 //                if (i == 0) {
754 //                    cfg.cls += ' fc-event-start';
755 //                }
756 //                if ((i+1) == rows.length) {
757 //                    cfg.cls += ' fc-event-end';
758 //                }
759 //
760 //                var ctr = this.el.select('.fc-event-container',true).first();
761 //                var cg = ctr.createChild(cfg);
762 //
763 //                var sbox = rows[i].start.select('.fc-day-content',true).first().getBox();
764 //                var ebox = rows[i].end.select('.fc-day-content',true).first().getBox();
765 //
766 //                cg.setXY([sbox.x +2, sbox.y +(e * 20)]);    
767 //                cg.setWidth(ebox.right - sbox.x -2);
768 //
769 //                cg.on('mouseenter' ,this.onEventEnter, this, ev);
770 //                cg.on('mouseleave' ,this.onEventLeave, this, ev);
771 //                cg.on('click', this.onEventClick, this, ev);
772 //
773 //                ev.els.push(cg);
774 //
775 //                
776 //            }
777 //        }
778         
779         var _this = this;
780         
781         this.cells.each(function(c) {
782             if(c.inhertance > 4){
783                 c.more = c.events;
784                 c.events = [];
785                 return;
786             }
787             
788             var totalRow = c.inhertance + c.row;
789             
790             if(totalRow < 5){
791                 return;
792             }
793             
794             var moreRow = 3 - c.inhertance;
795             
796             var ev = c.events;
797             
798             c.events = ev.slice(0, moreRow);
799             c.more = ev.slice(moreRow);
800             
801             c.row = c.events.length + 1;
802             
803             if(c.more.length && c.more.length == 1){
804                 c.events.push(c.more.pop());
805             }
806             
807         });
808             
809 //        for (var e = 0; e < this.calevents.length; e++) {
810 //            
811 //            var ev = this.calevents[e];
812 //            var cells = ev.cells;
813 //            var rows = ev.rows;
814 //            
815 //            for(var i = 0; i < cells.length; i++){
816 //                
817 //                var cbox = this.cells.item(this.cells.indexOf(cells[i]));
818 //                
819 //                if(cells.length < 2 && cbox.rows.length > 3){
820 //                    cbox.more.push(ev);
821 //                    continue;
822 //                }
823 //                
824 //                cbox.rows.push(ev);
825 //            }
826 //        }
827 //        
828         this.cells.each(function(c) {
829             
830             c.select('.fc-day-content div',true).first().setHeight(Math.max(34, (c.inhertance + c.row) * 20));
831             
832             
833             for (var e = 0; e < c.events.length; e++){
834                 var ev = c.events[e];
835                 
836                 var rows = ev.rows;
837                 
838                 for(var i = 0; i < rows.length; i++) {
839                 
840                     // how many rows should it span..
841
842                     var  cfg = {
843                         cls : 'roo-dynamic fc-event fc-event-hori fc-event-draggable ui-draggable',
844                         style : 'position: absolute', // left: 387px; width: 121px; top: 359px;
845
846                         unselectable : "on",
847                         cn : [
848                             {
849                                 cls: 'fc-event-inner',
850                                 cn : [
851     //                                {
852     //                                  tag:'span',
853     //                                  cls: 'fc-event-time',
854     //                                  html : cells.length > 1 ? '' : ev.time
855     //                                },
856                                     {
857                                       tag:'span',
858                                       cls: 'fc-event-title',
859                                       html : String.format('{0}', ev.title)
860                                     }
861
862
863                                 ]
864                             },
865                             {
866                                 cls: 'ui-resizable-handle ui-resizable-e',
867                                 html : '&nbsp;&nbsp;&nbsp'
868                             }
869
870                         ]
871                     };
872
873                     if (i == 0) {
874                         cfg.cls += ' fc-event-start';
875                     }
876                     if ((i+1) == rows.length) {
877                         cfg.cls += ' fc-event-end';
878                     }
879
880                     var ctr = _this.el.select('.fc-event-container',true).first();
881                     var cg = ctr.createChild(cfg);
882
883                     var sbox = rows[i].start.select('.fc-day-content',true).first().getBox();
884                     var ebox = rows[i].end.select('.fc-day-content',true).first().getBox();
885
886                     cg.setXY([sbox.x +2, sbox.y +((c.inhertance + e) * 20)]);    
887                     cg.setWidth(ebox.right - sbox.x -2);
888
889                     cg.on('mouseenter' ,_this.onEventEnter, _this, ev);
890                     cg.on('mouseleave' ,_this.onEventLeave, _this, ev);
891                     cg.on('click', _this.onEventClick, _this, ev);
892
893                     ev.els.push(cg);
894                     
895                 }
896                 
897             }
898             
899             
900             if(c.more.length){
901                 var  cfg = {
902                     cls : 'fc-more-event roo-dynamic fc-event fc-event-hori fc-event-draggable ui-draggable fc-event-start fc-event-end',
903                     style : 'position: absolute',
904                     unselectable : "on",
905                     cn : [
906                         {
907                             cls: 'fc-event-inner',
908                             cn : [
909                                 {
910                                   tag:'span',
911                                   cls: 'fc-event-title',
912                                   html : 'More'
913                                 }
914
915
916                             ]
917                         },
918                         {
919                             cls: 'ui-resizable-handle ui-resizable-e',
920                             html : '&nbsp;&nbsp;&nbsp'
921                         }
922
923                     ]
924                 };
925
926                 var ctr = _this.el.select('.fc-event-container',true).first();
927                 var cg = ctr.createChild(cfg);
928
929                 var sbox = c.select('.fc-day-content',true).first().getBox();
930                 var ebox = c.select('.fc-day-content',true).first().getBox();
931                 //Roo.log(cg);
932                 cg.setXY([sbox.x +2, sbox.y +((c.inhertance + c.row) * 20)]);    
933                 cg.setWidth(ebox.right - sbox.x -2);
934
935                 cg.on('click', _this.onMoreEventClick, _this, c.more);
936                 
937             }
938             
939         });
940         
941         
942         
943     },
944     
945     onEventEnter: function (e, el,event,d) {
946         this.fireEvent('evententer', this, el, event);
947     },
948     
949     onEventLeave: function (e, el,event,d) {
950         this.fireEvent('eventleave', this, el, event);
951     },
952     
953     onEventClick: function (e, el,event,d) {
954         this.fireEvent('eventclick', this, el, event);
955     },
956     
957     onMonthChange: function () {
958         this.store.load();
959     },
960     
961     onMoreEventClick: function(e, el, more)
962     {
963         var _this = this;
964         
965         this.calpopover.placement = 'right';
966         this.calpopover.setTitle('More');
967         
968         this.calpopover.setContent('');
969         
970         var ctr = this.calpopover.el.select('.popover-content', true).first();
971         
972         Roo.each(more, function(m){
973             var cfg = {
974                 cls : 'fc-event-hori fc-event-draggable',
975                 html : m.title
976             }
977             var cg = ctr.createChild(cfg);
978             
979             cg.on('click', _this.onEventClick, _this, m);
980         });
981         
982         this.calpopover.show(el);
983         
984         
985     },
986     
987     onLoad: function () 
988     {   
989         this.calevents = [];
990         var cal = this;
991         
992         if(this.store.getCount() > 0){
993             this.store.data.each(function(d){
994                cal.addItem({
995                     id : d.data.id,
996                     start: (typeof(d.data.start_dt) === 'string') ? new Date.parseDate(d.data.start_dt, 'Y-m-d H:i:s') : d.data.start_dt,
997                     end : (typeof(d.data.end_dt) === 'string') ? new Date.parseDate(d.data.end_dt, 'Y-m-d H:i:s') : d.data.end_dt,
998                     time : d.data.start_time,
999                     title : d.data.title,
1000                     description : d.data.description,
1001                     venue : d.data.venue
1002                 });
1003             });
1004         }
1005         
1006         this.renderEvents();
1007         
1008         if(this.calevents.length && this.loadMask){
1009             this.maskEl.hide();
1010         }
1011     },
1012     
1013     onBeforeLoad: function()
1014     {
1015         this.clearEvents();
1016         if(this.loadMask){
1017             this.maskEl.show();
1018         }
1019     }
1020 });
1021
1022  
1023