source: branches/2.2.0.1/calendar/js/dhtmlx/sources/event.js @ 4001

Revision 4001, 17.6 KB checked in by rafaelraymundo, 13 years ago (diff)

Ticket #1615 - Componente novo para agenda......................................

Line 
1scheduler.uid=function(){
2        if (!this._seed) this._seed=(new Date).valueOf();
3        return this._seed++;
4};
5scheduler._events={};
6scheduler.clearAll=function(){
7        this._events={};
8        this._loaded={};
9        this.clear_view();
10};
11scheduler.addEvent=function(start_date,end_date,text,id,extra_data){
12        var ev=start_date;
13        if (arguments.length!=1){
14                ev=extra_data||{};
15                ev.start_date=start_date;
16                ev.end_date=end_date;
17                ev.text=text;
18                ev.id=id;
19        };
20        ev.id = ev.id||scheduler.uid();
21        ev.text = ev.text||"";
22       
23        if (typeof ev.start_date == "string")  ev.start_date=this.templates.api_date(ev.start_date);
24        if (typeof ev.end_date == "string")  ev.end_date=this.templates.api_date(ev.end_date);
25        ev._timed=this.is_one_day_event(ev);
26
27        var is_new=!this._events[ev.id];
28        this._events[ev.id]=ev;
29        this.event_updated(ev);
30        if (!this._loading)
31                this.callEvent(is_new?"onEventAdded":"onEventChanged",[ev.id,ev]);
32};
33scheduler.deleteEvent=function(id,silent){
34        var ev=this._events[id];
35        if (!silent && !this.callEvent("onBeforeEventDelete",[id,ev])) return;
36       
37        if (ev){
38                delete this._events[id];
39                this.unselect(id);
40                this.event_updated(ev);
41        }
42};
43scheduler.getEvent=function(id){
44        return this._events[id];
45};
46scheduler.setEvent=function(id,hash){
47        this._events[id]=hash;
48};
49scheduler.for_rendered=function(id,method){
50        for (var i=this._rendered.length-1; i>=0; i--)
51                if (this._rendered[i].getAttribute("event_id")==id)
52                        method(this._rendered[i],i);
53};
54scheduler.changeEventId=function(id,new_id){
55        if (id == new_id) return;
56        var ev=this._events[id];
57        if (ev){
58                ev.id=new_id;
59                this._events[new_id]=ev;
60                delete this._events[id];
61        }
62        this.for_rendered(id,function(r){
63                r.setAttribute("event_id",new_id);
64        });
65        if (this._select_id==id) this._select_id=new_id;
66        if (this._edit_id==id) this._edit_id=new_id;
67        this.callEvent("onEventIdChange",[id,new_id]);
68};
69
70(function(){
71        var attrs=["text","Text","start_date","StartDate","end_date","EndDate"];
72        var create_getter=function(name){
73                return function(id){ return (scheduler.getEvent(id))[name]; };
74        };
75        var create_setter=function(name){
76                return function(id,value){
77                        var ev=scheduler.getEvent(id); ev[name]=value;
78                        ev._changed=true;
79                        ev._timed=this.is_one_day_event(ev);
80                        scheduler.event_updated(ev,true);
81                };
82        };
83        for (var i=0; i<attrs.length; i+=2){
84                scheduler["getEvent"+attrs[i+1]]=create_getter(attrs[i]);
85                scheduler["setEvent"+attrs[i+1]]=create_setter(attrs[i]);
86        }
87})();
88
89scheduler.event_updated=function(ev,force){
90        if (this.is_visible_events(ev))
91                this.render_view_data();
92        else this.clear_event(ev.id);
93};
94scheduler.is_visible_events=function(ev){
95        if (ev.start_date<this._max_date && this._min_date<ev.end_date) return true;
96        return false;
97};
98scheduler.is_one_day_event=function(ev){
99        var delta = ev.end_date.getDate()-ev.start_date.getDate();
100       
101        if (!delta)
102                return ev.start_date.getMonth()==ev.end_date.getMonth() && ev.start_date.getFullYear()==ev.end_date.getFullYear();
103        else {
104                if (delta < 0)  delta = Math.ceil((ev.end_date.valueOf()-ev.start_date.valueOf())/(24*60*60*1000));
105                return (delta == 1 && !ev.end_date.getHours() && !ev.end_date.getMinutes() && (ev.start_date.getHours() || ev.start_date.getMinutes() ));
106        }
107               
108};
109scheduler.get_visible_events=function(){
110        //not the best strategy for sure
111        var stack=[];
112        var filter = this["filter_"+this._mode];
113       
114        for( var id in this._events)
115                if (this.is_visible_events(this._events[id]))
116                        if (this._table_view || this.config.multi_day || this._events[id]._timed)
117                                if (!filter || filter(id,this._events[id]))
118                                        stack.push(this._events[id]);
119                               
120        return stack;
121};
122scheduler.render_view_data=function(){
123        if (this._not_render) {
124                this._render_wait=true;
125                return;
126        }
127        this._render_wait=false;
128       
129        this.clear_view();
130        var evs=this.get_visible_events();
131       
132        if (this.config.multi_day && !this._table_view){
133                var tvs = [];
134                var tvd = [];
135                for (var i=0; i < evs.length; i++){
136                        if (evs[i]._timed)
137                                tvs.push(evs[i]);
138                        else
139                                tvd.push(evs[i]);
140                };
141                this._table_view=true;
142                this.render_data(tvd);
143                this._table_view=false;         
144                this.render_data(tvs);
145        } else
146                this.render_data(evs); 
147};
148scheduler.render_data=function(evs,hold){
149        evs=this._pre_render_events(evs,hold);
150        for (var i=0; i<evs.length; i++)
151                if (this._table_view)
152                        this.render_event_bar(evs[i]);
153                else
154                        this.render_event(evs[i]);
155};
156scheduler._pre_render_events=function(evs,hold){
157        var hb = this.xy.bar_height;
158        var h_old = this._colsS.heights;       
159        var h=this._colsS.heights=[0,0,0,0,0,0,0];
160       
161        if (!this._table_view) evs=this._pre_render_events_line(evs,hold); //ignore long events for now
162        else evs=this._pre_render_events_table(evs,hold);
163       
164        if (this._table_view){
165                if (hold)
166                        this._colsS.heights = h_old;
167                else {
168                        var evl = this._els["dhx_cal_data"][0].firstChild;
169                        if (evl.rows){
170                                for (var i=0; i<evl.rows.length; i++){
171                                        h[i]++;
172                                        if ((h[i])*hb > this._colsS.height-22){ // 22 - height of cell's header
173                                                //we have overflow, update heights
174                                                var cells = evl.rows[i].cells;
175                                                for (var j=0; j < cells.length; j++) {
176                                                        cells[j].childNodes[1].style.height = h[i]*hb+"px";
177                                                }
178                                                h[i]=(h[i-1]||0)+cells[0].offsetHeight;
179                                        }
180                                        h[i]=(h[i-1]||0)+evl.rows[i].cells[0].offsetHeight;
181                                }       
182                                h.unshift(0);
183                                if (evl.parentNode.offsetHeight<evl.parentNode.scrollHeight && !evl._h_fix){
184                                        //we have v-scroll, decrease last day cell
185                                        for (var i=0; i<evl.rows.length; i++){
186                                                var cell = evl.rows[i].cells[6].childNodes[0];
187                                                var w = cell.offsetWidth-scheduler.xy.scroll_width+"px";
188                                                cell.style.width = w;
189                                                cell.nextSibling.style.width = w;
190                                        }               
191                                        evl._h_fix=true;
192                                }
193                        } else{
194                               
195                                if (!evs.length && this._els["dhx_multi_day"][0].style.visibility == "visible")
196                                        h[0]=-1;
197                                if (evs.length || h[0]==-1){
198                                        //shift days to have space for multiday events
199                                        var childs = evl.parentNode.childNodes;
200                                        var dh = (h[0]+1)*hb+"px";
201                                        for (var i=0; i<childs.length; i++)
202                                                if (this._colsS[i])
203                                                        childs[i].style.top=dh;
204                                        var last = this._els["dhx_multi_day"][0];
205                                        last.style.top = "0px";
206                                        last.style.height=dh;
207                                        last.style.visibility=(h[0]==-1?"hidden":"visible");
208                                        last=this._els["dhx_multi_day"][1];
209                                        last.style.height=dh;
210                                        last.style.visibility=(h[0]==-1?"hidden":"visible");
211                                        last.className=h[0]?"dhx_multi_day_icon":"dhx_multi_day_icon_small";
212                                       
213                                        this._dy_shift=(h[0]+1)*hb;
214                                        h[0] = 0;
215                                }                               
216                               
217                        }
218                }
219        }
220       
221        return evs;
222};
223scheduler._get_event_sday=function(ev){
224        return Math.floor((ev.start_date.valueOf()-this._min_date.valueOf())/(24*60*60*1000));
225};
226scheduler._pre_render_events_line=function(evs,hold){
227        evs.sort(function(a,b){ return a.start_date>b.start_date?1:-1; });
228        var days=[]; //events by weeks
229        var evs_originals = [];
230        for (var i=0; i < evs.length; i++) {
231                var ev=evs[i];
232
233                //check scale overflow
234                var sh = ev.start_date.getHours();
235                var eh = ev.end_date.getHours();
236               
237                ev._sday=this._get_event_sday(ev);
238                if (!days[ev._sday]) days[ev._sday]=[];
239               
240                if (!hold){
241                        ev._inner=false;
242                        var stack=days[ev._sday];
243                        while (stack.length && stack[stack.length-1].end_date<=ev.start_date)
244                                stack.splice(stack.length-1,1);
245                        if (stack.length) stack[stack.length-1]._inner=true;
246                        ev._sorder=stack.length; stack.push(ev);
247                        if (stack.length>(stack.max_count||0)) stack.max_count=stack.length;
248                }
249               
250                if (sh < this.config.first_hour || eh >= this.config.last_hour){
251                        evs_originals.push(ev);
252                        evs[i]=ev=this._copy_event(ev);
253                        if (sh < this.config.first_hour){
254                                ev.start_date.setHours(this.config.first_hour);
255                                ev.start_date.setMinutes(0);
256                        }
257                        if (eh >= this.config.last_hour){
258                                ev.end_date.setMinutes(0);
259                                ev.end_date.setHours(this.config.last_hour);
260                        }
261                        if (ev.start_date>ev.end_date || sh==this.config.last_hour) {
262                                evs.splice(i,1); i--; continue;
263                        }
264                }
265                               
266        }
267        if (!hold){
268                for (var i=0; i < evs.length; i++)
269                        evs[i]._count=days[evs[i]._sday].max_count;
270                for (var i=0; i < evs_originals.length; i++)
271                        evs_originals[i]._count=days[evs_originals[i]._sday].max_count;
272        }
273       
274        return evs;
275};
276scheduler._time_order=function(evs){
277        evs.sort(function(a,b){
278                if (a.start_date.valueOf()==b.start_date.valueOf()){
279                        if (a._timed && !b._timed) return 1;
280                        if (!a._timed && b._timed) return -1;
281                        return 0;
282                }
283                return a.start_date>b.start_date?1:-1;
284        });
285};
286scheduler._pre_render_events_table=function(evs,hold){ // max - max height of week slot
287        this._time_order(evs);
288       
289        var out=[];
290        var weeks=[[],[],[],[],[],[],[]]; //events by weeks
291        var max = this._colsS.heights;
292        var start_date;
293        var cols = this._cols.length;
294       
295        for (var i=0; i < evs.length; i++) {
296                var ev=evs[i];
297                var sd = (start_date||ev.start_date);
298                var ed = ev.end_date;
299                //trim events which are crossing through current view
300                if (sd<this._min_date) sd=this._min_date;
301                if (ed>this._max_date) ed=this._max_date;
302               
303                var locate_s = this.locate_holder_day(sd,false,ev);
304                ev._sday=locate_s%cols;
305                var locate_e = this.locate_holder_day(ed,true,ev)||cols;
306                ev._eday=(locate_e%cols)||cols; //cols used to fill full week, when event end on monday
307                ev._length=locate_e-locate_s;
308               
309                //3600000 - compensate 1 hour during winter|summer time shift
310                ev._sweek=Math.floor((this._correct_shift(sd.valueOf(),1)-this._min_date.valueOf())/(60*60*1000*24*cols));     
311               
312                //current slot
313                var stack=weeks[ev._sweek];
314                //check order position
315                var stack_line;
316               
317                for (stack_line=0; stack_line<stack.length; stack_line++)
318                        if (stack[stack_line]._eday<=ev._sday)
319                                break;
320                ev._sorder=stack_line;
321               
322               
323                if (ev._sday+ev._length<=cols){
324                        start_date=null;
325                        out.push(ev);
326                        stack[stack_line]=ev;
327                        //get max height of slot
328                        max[ev._sweek]=stack.length-1;
329                } else{ // split long event in chunks
330                        var copy=this._copy_event(ev);
331                        copy._length=cols-ev._sday;
332                        copy._eday=cols; copy._sday=ev._sday;
333                        copy._sweek=ev._sweek; copy._sorder=ev._sorder;
334                        copy.end_date=this.date.add(sd,copy._length,"day");
335                       
336                        out.push(copy);
337                        stack[stack_line]=copy;
338                        start_date=copy.end_date;
339                        //get max height of slot
340                        max[ev._sweek]=stack.length-1;
341                        i--; continue;  //repeat same step
342                }
343        };
344       
345        return out;
346};
347scheduler._copy_dummy=function(){
348        this.start_date=new Date(this.start_date);
349        this.end_date=new Date(this.end_date);
350};
351scheduler._copy_event=function(ev){
352        this._copy_dummy.prototype = ev;
353        return new this._copy_dummy();
354        //return {start_date:ev.start_date, end_date:ev.end_date, text:ev.text, id:ev.id}
355};
356scheduler._rendered=[];
357scheduler.clear_view=function(){
358        for (var i=0; i<this._rendered.length; i++){
359                var obj=this._rendered[i];
360                if (obj.parentNode) obj.parentNode.removeChild(obj);           
361        }
362        this._rendered=[];
363};
364scheduler.updateEvent=function(id){
365        var ev=this.getEvent(id);
366        this.clear_event(id);
367        if (ev && this.is_visible_events(ev))
368                this.render_data([ev],true);
369};
370scheduler.clear_event=function(id){
371        this.for_rendered(id,function(node,i){
372                if (node.parentNode)
373                        node.parentNode.removeChild(node);
374                scheduler._rendered.splice(i,1);
375        });
376};
377scheduler.render_event=function(ev){
378        var menu = scheduler.xy.menu_width;
379        if (ev._sday<0) return; //can occur in case of recurring event during time shift
380        var parent=scheduler.locate_holder(ev._sday);   
381        if (!parent) return; //attempt to render non-visible event
382        var sm = ev.start_date.getHours()*60+ev.start_date.getMinutes();
383        var em = (ev.end_date.getHours()*60+ev.end_date.getMinutes())||(scheduler.config.last_hour*60);
384       
385        var top = (Math.round((sm*60*1000-this.config.first_hour*60*60*1000)*this.config.hour_size_px/(60*60*1000)))%(this.config.hour_size_px*24)+1; //42px/hour
386        var height = Math.max(scheduler.xy.min_event_height,(em-sm)*this.config.hour_size_px/60)+1; //42px/hour
387        //var height = Math.max(25,Math.round((ev.end_date.valueOf()-ev.start_date.valueOf())*(this.config.hour_size_px+(this._quirks?1:0))/(60*60*1000))); //42px/hour
388        var width=Math.floor((parent.clientWidth-menu)/ev._count);
389        var left=ev._sorder*width+1;
390        if (!ev._inner) width=width*(ev._count-ev._sorder);
391       
392       
393       
394        var d=this._render_v_bar(ev.id,menu+left,top,width,height,ev._text_style,scheduler.templates.event_header(ev.start_date,ev.end_date,ev),scheduler.templates.event_text(ev.start_date,ev.end_date,ev));
395               
396        this._rendered.push(d);
397        parent.appendChild(d);
398       
399        left=left+parseInt(parent.style.left,10)+menu;
400       
401        top+=this._dy_shift; //corrupt top, to include possible multi-day shift
402        if (this._edit_id==ev.id){
403                d.style.zIndex = 1; //fix overlapping issue
404                width=Math.max(width-4,scheduler.xy.editor_width);
405                var d=document.createElement("DIV");
406                d.setAttribute("event_id",ev.id);
407                this.set_xy(d,width,height-20,left,top+14);
408                d.className="dhx_cal_editor";
409                       
410                var d2=document.createElement("DIV");
411                this.set_xy(d2,width-6,height-26);
412                d2.style.cssText+=";margin:2px 2px 2px 2px;overflow:hidden;";
413               
414                d.appendChild(d2);
415                this._els["dhx_cal_data"][0].appendChild(d);
416                this._rendered.push(d);
417       
418                d2.innerHTML="<textarea class='dhx_cal_editor'>"+ev.text+"</textarea>";
419                if (this._quirks7) d2.firstChild.style.height=height-12+"px"; //IEFIX
420                this._editor=d2.firstChild;
421                this._editor.onkeypress=function(e){
422                        if ((e||event).shiftKey) return true;
423                        var code=(e||event).keyCode;
424                        if (code==scheduler.keys.edit_save) scheduler.editStop(true);
425                        if (code==scheduler.keys.edit_cancel) scheduler.editStop(false);
426                };
427                this._editor.onselectstart=function(e){ return (e||event).cancelBubble=true; };
428                d2.firstChild.focus();
429                //IE and opera can add x-scroll during focusing
430                this._els["dhx_cal_data"][0].scrollLeft=0;
431                d2.firstChild.select();
432        }
433       
434        if (this._select_id==ev.id){
435                //d.style.zIndex = 1; //fix overlapping issue
436                var icons=this.config["icons_"+((this._edit_id==ev.id)?"edit":"select")];
437                var icons_str="";
438                for (var i=0; i<icons.length; i++)
439                        icons_str+="<div class='dhx_menu_icon "+icons[i]+"' title='"+this.locale.labels[icons[i]]+"'></div>";
440                var obj = this._render_v_bar(ev.id,left-menu+1,top,menu,icons.length*20+26,"","<div class='dhx_menu_head'></div>",icons_str,true);
441                obj.style.left=left-menu+1;
442                this._els["dhx_cal_data"][0].appendChild(obj);
443                this._rendered.push(obj);
444        }
445};
446scheduler._render_v_bar=function(id,x,y,w,h,style,contentA,contentB,bottom){
447        var d=document.createElement("DIV");
448       
449        var ev = this.getEvent(id);
450        var cs = "dhx_cal_event";
451        var cse = scheduler.templates.event_class(ev.start_date,ev.end_date,ev);
452        if (cse) cs=cs+" "+cse;
453       
454        var html='<div event_id="'+id+'" class="'+cs+'" style="position:absolute; top:'+y+'px; left:'+x+'px; width:'+(w-4)+'px; height:'+h+'px;'+(style||"")+'">';
455        html+='<div class="dhx_header" style=" width:'+(w-6)+'px;" >&nbsp;</div>';
456        html+='<div class="dhx_title">'+contentA+'</div>';
457        html+='<div class="dhx_body" style=" width:'+(w-(this._quirks?4:14))+'px; height:'+(h-(this._quirks?20:30))+'px;">'+contentB+'</div>';
458        html+='<div class="dhx_footer" style=" width:'+(w-8)+'px;'+(bottom?' margin-top:-1px;':'')+'" ></div></div>';
459       
460        d.innerHTML=html;
461        return d.firstChild;
462};
463scheduler.locate_holder=function(day){
464        if (this._mode=="day") return this._els["dhx_cal_data"][0].firstChild; //dirty
465        return this._els["dhx_cal_data"][0].childNodes[day];
466};
467scheduler.locate_holder_day=function(date,past){
468        var day = Math.floor((this._correct_shift(date,1)-this._min_date)/(60*60*24*1000));
469        //when locating end data of event , we need to use next day if time part was defined
470        if (past && this.date.time_part(date)) day++;
471        return day;
472};
473scheduler.render_event_bar=function(ev){
474        var parent=this._els["dhx_cal_data"][0];
475
476        var x=this._colsS[ev._sday];
477        var x2=this._colsS[ev._eday];
478        if (x2==x) x2=this._colsS[ev._eday+1];
479        var hb = this.xy.bar_height;
480       
481        var y=this._colsS.heights[ev._sweek]+(this._colsS.height?(this.xy.month_scale_height+2):2)+ev._sorder*hb;
482                       
483        var d=document.createElement("DIV");
484        var cs = ev._timed?"dhx_cal_event_clear":"dhx_cal_event_line";
485        var cse = scheduler.templates.event_class(ev.start_date,ev.end_date,ev);
486        if (cse) cs=cs+" "+cse;
487       
488        var html='<div event_id="'+ev.id+'" class="'+cs+'" style="position:absolute; top:'+y+'px; left:'+x+'px; width:'+(x2-x-15)+'px;'+(ev._text_style||"")+'">';
489               
490        if (ev._timed)
491                html+=scheduler.templates.event_bar_date(ev.start_date,ev.end_date,ev);
492        html+=scheduler.templates.event_bar_text(ev.start_date,ev.end_date,ev)+'</div>';
493        html+='</div>';
494       
495        d.innerHTML=html;
496       
497        this._rendered.push(d.firstChild);
498        parent.appendChild(d.firstChild);
499};
500
501scheduler._locate_event=function(node){
502        var id=null;
503        while (node && !id && node.getAttribute){
504                id=node.getAttribute("event_id");
505                node=node.parentNode;
506        }
507        return id;
508};
509
510
511scheduler.edit=function(id){
512        if (this._edit_id==id) return;
513        this.editStop(false,id);
514        this._edit_id=id;
515        this.updateEvent(id);
516};
517scheduler.editStop=function(mode,id){
518        if (id && this._edit_id==id) return;
519        var ev=this.getEvent(this._edit_id);
520        if (ev){
521                if (mode) ev.text=this._editor.value;
522                this._edit_id=null;
523                this._editor=null;     
524                this.updateEvent(ev.id);
525                this._edit_stop_event(ev,mode);
526        }
527};
528scheduler._edit_stop_event=function(ev,mode){
529        if (this._new_event){
530                if (!mode) this.deleteEvent(ev.id,true);               
531                else this.callEvent("onEventAdded",[ev.id,ev]);
532                this._new_event=null;
533        } else
534                if (mode) this.callEvent("onEventChanged",[ev.id,ev]);
535};
536
537scheduler.getEvents = function(from,to){
538        var result = [];
539        for (var a in this._events){
540                var ev = this._events[a];
541                if (ev && ev.start_date<to && ev.end_date>from)
542                        result.push(ev);
543        }
544        return result;
545};
Note: See TracBrowser for help on using the repository browser.