source: sandbox/2.3-MailArchiver/calendar/js/dhtmlx/sources/ext/ext_matrix.js @ 6779

Revision 6779, 18.5 KB checked in by rafaelraymundo, 12 years ago (diff)

Ticket #2946 - Liberado Expresso(branch 2.3) integrado ao MailArchiver?.

Line 
1(function(){
2scheduler.matrix = {};
3scheduler._merge=function(a,b){
4        for (var c in b)
5                if (typeof a[c] == "undefined")
6                        a[c]=b[c];
7};
8scheduler.createTimelineView=function(obj){
9
10       
11        scheduler._merge(obj,{
12                section_autoheight: true,
13                name:"matrix",
14                x:"time",
15                y:"time",
16                x_step:1,
17                x_unit:"hour",
18                y_unit:"day",
19                y_step:1,
20                x_start:0,
21                x_size:24,
22                y_start:0,
23                y_size: 7,
24                render:"cell",
25                dx:200,
26                dy:50,
27                _logic: function(render_name, y_unit, timeline) {
28                        var res = {};
29                        if(scheduler.checkEvent("onBeforeViewRender")) {
30                                res = scheduler.callEvent("onBeforeViewRender", [render_name, y_unit, timeline]);
31                        }
32                        return res;
33                }
34        });
35       
36        if (scheduler.checkEvent("onTimelineCreated")) {
37                scheduler.callEvent("onTimelineCreated", [obj]);
38        }
39
40        //init custom wrappers
41        scheduler[obj.name+"_view"]=function(){
42                scheduler.renderMatrix.apply(obj, arguments);
43        };
44       
45        var old = scheduler.render_data;
46        scheduler.render_data=function(evs, mode){
47                if (this._mode == obj.name){
48                        if (mode)       //repaint single event, precision is not necessary
49                                for (var i=0; i < evs.length; i++) {
50                                        this.clear_event(evs[i]);
51                                        this.render_timeline_event.call(this.matrix[this._mode], evs[i], 0, true);
52                                }
53                        else
54                        set_full_view.call(obj,true);
55                } else
56                        return old.apply(this,arguments);
57        };
58       
59        scheduler.matrix[obj.name]=obj;
60        scheduler.templates[obj.name+"_cell_value"] = function(ar){ return ar?ar.length:""; };
61        scheduler.templates[obj.name+"_cell_class"] = function(ar){ return ""; };
62        scheduler.templates[obj.name+"_scalex_class"] = function(ar){ return ""; };
63       
64        scheduler.templates[obj.name+"_scaley_class"] = function(section_id, section_label, section_options){ return "class"; };
65        scheduler.templates[obj.name+"_scale_label"] = function(section_id, section_label, section_options){ return section_label; };
66       
67        scheduler.templates[obj.name+"_tooltip"] = function(a,b,e){ return e.text; };
68        scheduler.templates[obj.name+"_date"] = function(datea, dateb){
69                if (datea.getDay()==dateb.getDay() && datea-dateb<(24*60*60*1000))
70                        return scheduler.templates.day_date(datea);
71                return scheduler.templates.week_date(datea, dateb);
72        };
73       
74        scheduler.templates[obj.name+"_scale_date"] = scheduler.date.date_to_str(obj.x_date||scheduler.config.hour_date);
75               
76        scheduler.date["add_"+obj.name]=function(a,b,c){
77                return scheduler.date.add(a,(obj.x_length||obj.x_size)*b*obj.x_step,obj.x_unit);
78        };
79       
80        // note this is not correct start_date as it doesn't take into account x_start value (though scheduler._min_date is correct)
81        scheduler.date[obj.name+"_start"] = scheduler.date[obj.x_unit+"_start"] || scheduler.date.day_start;
82       
83        scheduler.attachEvent("onSchedulerResize",function(){
84                if (this._mode == obj.name){
85                        set_full_view.call(obj,true);
86                        return false;
87                }
88                return true;
89        });
90       
91        scheduler.attachEvent("onOptionsLoad",function(){
92                        obj.order = {};
93                        for(var i=0; i<obj.y_unit.length;i++)
94                                obj.order[obj.y_unit[i].key]=i;
95                        if(obj.name == scheduler._mode) {
96                                if (scheduler._date)
97                                        scheduler.setCurrentView(scheduler._date, scheduler._mode);
98                        }
99        });     
100        scheduler.callEvent("onOptionsLoad",[obj]);
101       
102        //enable drag for non-cell modes
103                if (obj.render != "cell"){
104                var temp_date = new Date();
105                var step_diff = (scheduler.date.add(temp_date, 1, obj.x_unit).valueOf() - temp_date.valueOf());
106                scheduler["mouse_"+obj.name]=function(pos){     //mouse_coord handler
107                        //get event object
108                        var ev = this._drag_event;
109                        if (this._drag_id){
110                                ev = this.getEvent(this._drag_id);
111                                this._drag_event._dhx_changed = true;
112                        }
113                        pos.x-=obj.dx;
114                        //scheduler.date.date_part(ev.start_date);
115                       
116                        var summ = 0, xind = 0, yind = 0; 
117                        for (xind; xind < this._cols.length-1; xind++) {
118                                summ+=this._cols[xind];
119                                if (summ>pos.x){ //index of section
120                                        break;
121                                }
122                        }
123                       
124                        summ = 0;
125                        for (yind; yind < this._colsS.heights.length; yind++) {
126                                summ+=this._colsS.heights[yind];
127                                if (summ>pos.y)
128                                        break;
129                        }
130                       
131                        pos.fields={};
132                        pos.fields[obj.y_property] = ev[obj.y_property] = obj.y_unit[yind].key;
133                       
134                        pos.x =  yind/10000000; //force rendering when section changes
135                       
136                        if (this._drag_mode == "new-size" && ev.start_date*1==this._drag_start*1) {
137                                xind++;
138                        }
139                               
140                       
141                        if(xind >= obj._trace_x.length) { // if our event is at the end of the view
142                                var end_date = scheduler.date.add(obj._trace_x[obj._trace_x.length-1], obj.x_step, obj.x_unit);
143                        } else {
144                                var end_date = obj._trace_x[xind];
145                        }
146
147                        pos.y = Math.round((end_date-this._min_date)/(1000*60*this.config.time_step));
148                        pos.custom = true;
149                        pos.shift = step_diff;
150
151                        return pos;
152                };
153        }
154};
155
156scheduler.render_timeline_event = function(ev, stack, attach){
157
158        var x_start = _getX(ev, false, this._step);
159        var x_end = _getX(ev, true, this._step);
160
161        var hb = scheduler.xy.bar_height;
162        var y = 2+stack*hb;
163                                       
164                               
165        var cs = scheduler.templates.event_class(ev.start_date,ev.end_date,ev);
166        cs = "dhx_cal_event_line "+(cs||"");
167               
168        var html='<div event_id="'+ev.id+'" class="'+cs+'" style="position:absolute; top:'+y+'px; left:'+x_start+'px; width:'+Math.max(0,x_end-x_start)+'px;'+(ev._text_style||"")+'">'+scheduler.templates.event_bar_text(ev.start_date,ev.end_date,ev)+'</div>';
169       
170        if (!attach)
171                return html;
172        else {
173                var d = document.createElement("DIV");
174                d.innerHTML = html;
175               
176                var ind = this.order[ev[this.y_property]];
177                var parent = scheduler._els["dhx_cal_data"][0].firstChild.rows[ind].cells[1].firstChild;
178               
179                scheduler._rendered.push(d.firstChild);
180                parent.appendChild(d.firstChild);
181        }
182
183};
184       
185function trace_events(){
186        //minimize event set
187        var evs = scheduler.getEvents(scheduler._min_date, scheduler._max_date);
188        var matrix =[];
189        for (var i=0; i < this.y_unit.length; i++)
190                matrix[i]=[];
191       
192               
193        //next code defines row for undefined key
194        //most possible it is an artifact of incorrect configuration
195        if (!matrix[y])
196                matrix[y]=[];
197       
198        for (var i=0; i < evs.length; i++) {
199                var y = this.order[evs[i][this.y_property]];
200                var x = 0;
201                while (this._trace_x[x+1] && evs[i].start_date>=this._trace_x[x+1]) x++;
202                while (this._trace_x[x] && evs[i].end_date>this._trace_x[x]) {
203                        if (!matrix[y][x]) matrix[y][x]=[];
204                        matrix[y][x].push(evs[i]);
205                        x++;
206                }
207        }
208        return matrix;
209}
210
211// function used to get X (both start and end) coordinates for timeline bar view
212function _getX(ev, isEndPoint, step) {
213        var x = 0;
214        var date = (isEndPoint) ? ev.end_date : ev.start_date;
215        if(date.valueOf()>scheduler._max_date.valueOf())
216                date = scheduler._max_date;
217        var delta = date - scheduler._min_date_timeline;
218        if (delta<0) {
219                column_offset = 0;
220        } else {
221                var index = Math.round( delta/(step*scheduler._cols[0]) ); // results varies ~0.9 - ~24.17, e.g. that way we get 1 and 24
222                if(index>scheduler._cols.length) // if columns really small it's possible to get incorrect index
223                        index = scheduler._cols.length;
224                for (var k=0; k<index; k++) {
225                        x += scheduler._cols[k];
226                }
227                var column_date = scheduler.date.add(scheduler._min_date_timeline, scheduler.matrix[scheduler._mode].x_step*index, scheduler.matrix[scheduler._mode].x_unit);
228                delta = date - column_date;
229                var column_offset = Math.floor(delta/step);
230        }
231        x += (isEndPoint) ? column_offset-14 : column_offset+1;
232        return x;
233}
234       
235
236function y_scale(d){
237
238        var html = "<table style='table-layout:fixed;' cellspacing='0' cellpadding='0'>";
239        var evs=[];
240        if (scheduler._load_mode && scheduler._load()) return;
241        if (this.render == "cell")
242                evs = trace_events.call(this);
243        else {
244                var tevs = scheduler.getEvents(scheduler._min_date, scheduler._max_date);
245                for (var j=0; j<tevs.length; j++){
246                        var ind =  this.order[ tevs[j][this.y_property] ];
247                        if (!evs[ind]) evs[ind] = [];
248                        evs[ind].push(tevs[j]);
249                }
250        }
251               
252        var summ = 0;
253        for (var i=0; i < scheduler._cols.length; i++)
254                summ+=scheduler._cols[i];
255               
256        var step = new Date();
257        step = (scheduler.date.add(step, this.x_step*this.x_size, this.x_unit)-step)/summ;
258       
259        this._step = step;
260        this._summ = summ;
261       
262        var heights = scheduler._colsS.heights=[];
263       
264       
265        for (var i=0; i<this.y_unit.length; i++){
266               
267                var stats = this._logic(this.render, this.y_unit[i], this); // obj with custom style
268               
269                scheduler._merge(stats, {
270                        height: this.dy
271                });
272               
273                //autosize height, if we have a free space
274                if(this.section_autoheight) {
275                        if (this.y_unit.length * stats.height < d.offsetHeight) {
276                                stats.height = Math.max(stats.height, Math.floor((d.offsetHeight - 1) / this.y_unit.length));
277                        }
278                }       
279                               
280                scheduler._merge(stats, {
281                        //section 1
282                        tr_className: "",
283                        style_height: "height:"+stats.height+"px;",
284                        style_width: "width:"+(this.dx-1)+"px;",
285                        td_className: "dhx_matrix_scell "+scheduler.templates[this.name+"_scaley_class"](this.y_unit[i].key, this.y_unit[i].label, this),
286                        td_content: scheduler.templates[this.name+'_scale_label'](this.y_unit[i].key, this.y_unit[i].label, this),
287                        //section 2
288                        summ_width: "width:"+summ+"px;",
289                        //section 3
290                        table_className: ''
291                });
292               
293                // section 1
294                html+="<tr class='"+stats.tr_className+"' style='"+stats.style_height+"'><td class='"+stats.td_className+"' style='"+stats.style_width+"'>"+stats.td_content+"</td>";   
295
296                if (this.render == "cell"){
297                        for (var j=0; j < scheduler._cols.length; j++) {
298                                        html+="<td class='dhx_matrix_cell "+scheduler.templates[this.name+"_cell_class"](evs[i][j],this._trace_x[j],this.y_unit[i])+"' style='width:"+(scheduler._cols[j]-1)+"px'><div style='width:"+(scheduler._cols[j]-1)+"px'>"+scheduler.templates[this.name+"_cell_value"](evs[i][j])+"<div></td>";
299                        }
300                } else {
301                        //section 2
302                        html+="<td><div style='"+stats.summ_width+" "+stats.style_height+" position:relative;' class='dhx_matrix_line'>";
303
304                        if (evs[i]){
305                                evs[i].sort(function(a,b){ return a.start_date>b.start_date?1:-1; });
306                                var stack=[];
307                                for (var j=0; j<evs[i].length; j++){
308                                        var ev = evs[i][j];
309
310                                        //get line in stack
311                                        var stack_pointer = 0;
312                                       
313                                        while (stack[stack_pointer] && stack[stack_pointer].end_date > ev.start_date)
314                                                stack_pointer++;
315                                        stack[stack_pointer]=ev;
316                                        //render line
317                                       
318                                        html+=scheduler.render_timeline_event.call(this, ev, stack_pointer);
319                                }
320                        }
321                        //section 3
322                                html+="<table class='"+stats.table_className+"' cellpadding='0' cellspacing='0' style='"+stats.summ_width+" "+stats.style_height+"' >";
323                        for (var j=0; j < scheduler._cols.length; j++)
324                                html+="<td class='dhx_matrix_cell "+scheduler.templates[this.name+"_cell_class"](evs[i],this._trace_x[j],this.y_unit[i])+"' style='width:"+(scheduler._cols[j]-1)+"px'><div style='width:"+(scheduler._cols[j]-1)+"px'><div></td>";
325                        html+="</table>";                       
326                        html+="</div></td>";   
327                }
328                html+="</tr>";
329        }
330        html += "</table>";
331        this._matrix = evs;
332        d.scrollTop = 0; //fix flickering in FF
333        d.innerHTML = html;
334       
335        scheduler._rendered = [];
336        var divs = document.getElementsByTagName("DIV");
337        for (var i=0; i < divs.length; i++)
338                if (divs[i].getAttribute("event_id"))
339                        scheduler._rendered.push(divs[i]);
340                       
341        for (var i=0; i < d.firstChild.rows.length; i++)
342                heights.push(d.firstChild.rows[i].offsetHeight);
343       
344}
345function x_scale(h){
346        h.innerHTML = "<div></div>"; h=h.firstChild;
347       
348        scheduler._cols=[];     //store for data section
349        scheduler._colsS={height:0};
350        this._trace_x =[];
351       
352        scheduler._min_date_timeline = scheduler._min_date;
353               
354        var start = scheduler._min_date;
355        var summ = scheduler._x-this.dx-18; //border delta
356
357        var left = this.dx;
358       
359        for (var i=0; i<this.x_size; i++){
360                scheduler._cols[i]=Math.floor(summ/(this.x_size-i));
361                this._trace_x[i]=new Date(start);
362               
363                scheduler._render_x_header(i, left, start, h);
364               
365                var cs = scheduler.templates[this.name+"_scalex_class"](start);
366                if (cs)
367                        h.lastChild.className += " "+cs;
368                       
369                start = scheduler.date.add(start, this.x_step, this.x_unit);
370               
371                summ-=scheduler._cols[i];
372                left+=scheduler._cols[i];
373        }
374       
375        var trace = this._trace_x;
376        h.onclick = function(e){
377                var pos = locate_hcell(e);
378                if (pos)
379                        scheduler.callEvent("onXScaleClick",[pos.x, trace[pos.x], e||event]);
380        };
381        h.ondblclick = function(e){
382                var pos = locate_hcell(e);
383                if (pos)
384                        scheduler.callEvent("onXScaleDblClick",[pos.x, trace[pos.x], e||event]);
385        };
386}
387function set_full_view(mode){
388        if (mode){     
389                scheduler.set_sizes();
390                _init_matrix_tooltip();
391                //we need to have day-rounded scales for navigation
392                //in same time, during rendering scales may be shifted
393                var temp = scheduler._min_date;
394                        x_scale.call(this,scheduler._els["dhx_cal_header"][0]);
395                        y_scale.call(this,scheduler._els["dhx_cal_data"][0]);
396                scheduler._min_date = temp;
397                scheduler._els["dhx_cal_date"][0].innerHTML=scheduler.templates[this.name+"_date"](scheduler._min_date, scheduler._max_date);
398                scheduler._table_view=true;
399        }
400}
401
402
403function hideToolTip(){
404        if (scheduler._tooltip){
405                scheduler._tooltip.style.display = "none";
406                scheduler._tooltip.date = "";
407        }
408}
409function showToolTip(obj,pos,offset){
410        if (obj.render != "cell") return;
411        var mark = pos.x+"_"+pos.y;             
412        var evs = obj._matrix[pos.y][pos.x];
413       
414        if (!evs) return hideToolTip();
415       
416        evs.sort(function(a,b){ return a.start_date>b.start_date?1:-1; });
417
418        if (scheduler._tooltip){
419                if (scheduler._tooltip.date == mark) return;
420                scheduler._tooltip.innerHTML="";
421        } else {
422                var t = scheduler._tooltip = document.createElement("DIV");
423                t.className = "dhx_tooltip";
424                document.body.appendChild(t);
425                t.onclick = scheduler._click.dhx_cal_data;
426        }
427       
428        var html = "";
429   
430        for (var i=0; i<evs.length; i++){
431                html+="<div class='dhx_tooltip_line' event_id='"+evs[i].id+"'>";
432                html+="<div class='dhx_tooltip_date'>"+(evs[i]._timed?scheduler.templates.event_date(evs[i].start_date):"")+"</div>";
433                html+="<div class='dhx_event_icon icon_details'>&nbsp;</div>";
434                html+=scheduler.templates[obj.name+"_tooltip"](evs[i].start_date, evs[i].end_date,evs[i])+"</div>";
435   }
436   
437        scheduler._tooltip.style.display="";   
438        scheduler._tooltip.style.top = "0px";
439   
440        if (document.body.offsetWidth-offset.left-scheduler._tooltip.offsetWidth < 0)
441                scheduler._tooltip.style.left = offset.left-scheduler._tooltip.offsetWidth+"px";
442        else
443                scheduler._tooltip.style.left = offset.left+pos.src.offsetWidth+"px";
444     
445        scheduler._tooltip.date = mark;
446        scheduler._tooltip.innerHTML = html;
447   
448        if (document.body.offsetHeight-offset.top-scheduler._tooltip.offsetHeight < 0)
449                scheduler._tooltip.style.top= offset.top-scheduler._tooltip.offsetHeight+pos.src.offsetHeight+"px";
450        else
451                scheduler._tooltip.style.top= offset.top+"px";
452}
453
454function _init_matrix_tooltip(){
455        dhtmlxEvent(scheduler._els["dhx_cal_data"][0], "mouseover", function(e){
456                var obj = scheduler.matrix[scheduler._mode];
457                if (obj){
458                        var pos = scheduler._locate_cell_timeline(e);
459                        var e = e || event;
460                        var src = e.target||e.srcElement;
461                        if (pos)
462                                return showToolTip(obj,pos,getOffset(pos.src));
463                }
464                hideToolTip();
465        });
466   _init_matrix_tooltip=function(){};
467}
468
469scheduler.renderMatrix = function(mode){
470        var start_date = scheduler.date[this.name+"_start"](scheduler._date);
471        scheduler._min_date = scheduler.date.add(start_date, this.x_start*this.x_step, this.x_unit);
472        scheduler._max_date = scheduler.date.add(scheduler._min_date, this.x_size*this.x_step, this.x_unit);
473        scheduler._table_view = true;
474        set_full_view.call(this,mode);
475};
476
477function html_index(el) {
478        var p = el.parentNode.childNodes;
479        for (var i=0; i < p.length; i++)
480                if (p[i] == el) return i;
481        return -1;
482}
483function locate_hcell(e){
484        e = e||event;
485        var trg = e.target?e.target:e.srcElement;
486        while (trg && trg.tagName != "DIV")
487                trg=trg.parentNode;
488        if (trg && trg.tagName == "DIV"){
489                var cs = trg.className.split(" ")[0];
490                if (cs == "dhx_scale_bar")
491                        return { x:html_index(trg), y:-1, src:trg, scale:true };
492        }
493}
494scheduler._locate_cell_timeline = function(e){
495        e = e||event;
496        var trg = e.target?e.target:e.srcElement;
497        while (trg && trg.tagName != "TD")
498                trg=trg.parentNode;
499        if (trg && trg.tagName == "TD"){
500                var cs = trg.className.split(" ")[0];
501                if (cs == "dhx_matrix_cell") {
502               
503                        if(scheduler._isRender("cell")) {
504                                return { x:trg.cellIndex-1, y:trg.parentNode.rowIndex, src:trg };
505                        } else { // probably desired path for all modes except cell
506                                var trscell = trg.parentNode; // moving out from current td
507                                while(trscell && trscell.tagName != "TD") {
508                                        trscell=trscell.parentNode;
509                                }
510                                return { x:trg.cellIndex, y:trscell.parentNode.rowIndex, src:trg };
511                        }
512                }
513                else if (cs == "dhx_matrix_scell")
514                        return { x:-1, y:trg.parentNode.rowIndex, src:trg, scale:true };
515        }
516        return false;
517};
518
519var old_click = scheduler._click.dhx_cal_data;
520scheduler._click.dhx_cal_data = function(e){
521        var ret = old_click.apply(this,arguments);
522        var obj = scheduler.matrix[scheduler._mode];
523        if (obj){
524                var pos = scheduler._locate_cell_timeline(e);
525                if (pos){
526                        if (pos.scale)
527                                scheduler.callEvent("onYScaleClick",[pos.y, obj.y_unit[pos.y], e||event]);
528                        else
529                                scheduler.callEvent("onCellClick",[pos.x, pos.y, obj._trace_x[pos.x], (((obj._matrix[pos.y]||{})[pos.x])||[]), e||event]);
530                }
531        }
532        return ret;
533};
534
535scheduler.dblclick_dhx_matrix_cell = function(e){
536        var obj = scheduler.matrix[scheduler._mode];
537        if (obj){
538                var pos = scheduler._locate_cell_timeline(e);
539                if (pos){
540                        if (pos.scale)
541                                scheduler.callEvent("onYScaleDblClick",[pos.y, obj.y_unit[pos.y], e||event]);
542                        else
543                                scheduler.callEvent("onCellDblClick",[pos.x, pos.y, obj._trace_x[pos.x], (((obj._matrix[pos.y]||{})[pos.x])||[]), e||event]);
544                }
545        }
546};
547scheduler.dblclick_dhx_matrix_scell = function(e){
548        return scheduler.dblclick_dhx_matrix_cell(e);
549};
550
551scheduler._isRender = function(mode){
552        return (scheduler.matrix[scheduler._mode] && scheduler.matrix[scheduler._mode].render == mode);
553};
554
555scheduler.attachEvent("onCellDblClick", function (x, y, a, b, event){
556        if (this.config.readonly|| (event.type == "dblclick" && !this.config.dblclick_create)) return;
557       
558        var obj = scheduler.matrix[scheduler._mode];
559        var event_options = {};
560        event_options['start_date'] = obj._trace_x[x];
561        event_options['end_date'] = (obj._trace_x[x+1]) ? obj._trace_x[x+1] : scheduler.date.add(obj._trace_x[x], obj.x_step, obj.x_unit);
562        event_options[scheduler.matrix[scheduler._mode].y_property] = obj.y_unit[y].key;
563        scheduler.addEventNow(event_options, null, event);
564});     
565
566scheduler.attachEvent("onBeforeDrag", function (event_id, mode, native_event_object){
567        if(scheduler._isRender("cell")) {
568                return false;
569        }
570        return true;
571});     
572
573})();
Note: See TracBrowser for help on using the repository browser.