source: Dev/trunk/src/client/dojox/gantt/GanttChart.js @ 529

Last change on this file since 529 was 483, checked in by hendrikvanantwerpen, 11 years ago

Added Dojo 1.9.3 release.

File size: 45.0 KB
Line 
1// FIXME: documentation
2define([
3    "./GanttProjectItem",
4    "./GanttResourceItem",
5    "./GanttProjectControl",
6    "./GanttTaskControl",
7    "./GanttTaskItem",
8    "./TabMenu",
9    "dijit/Tooltip",
10    "dojo/_base/declare",
11        "dojo/_base/array",
12        "dojo/_base/lang",
13    "dojo/date/locale",
14        "dojo/request",
15        "dojo/request/util",
16        "dojo/on",
17        "dojo/dom",
18        "dojo/dom-class",
19        "dojo/dom-construct",
20        "dojo/dom-style",
21        "dojo/dom-attr",
22        "dojo/dom-geometry",
23        "dojo/keys",
24        "dojo/has",
25        "dojo/_base/window",
26        "dojo/json",
27        "dojo/domReady!"
28], function(GanttProjectItem, GanttResourceItem, GanttProjectControl,
29                GanttTaskControl, GanttTaskItem, TabMenu,
30                Tooltip,
31                declare, arrayUtil, lang, locale, request, util, on,
32                dom, domClass, domConstruct, domStyle, domAttr, domGeometry, keys, has, win, JSON){
33        return declare("dojox.gantt.GanttChart", [], {
34                constructor: function(configuration, node){
35                        this.resourceChartHeight = configuration.resourceChartHeight !== undefined ? configuration.resourceChartHeight : false;
36                        this.withResource = configuration.withResource !== undefined ? configuration.withResource : true;
37                        this.correctError = configuration.autoCorrectError !== undefined ? configuration.autoCorrectError : false;
38                        this.isShowConMenu = this.isContentEditable = !configuration.readOnly;
39                        this.withTaskId = configuration.withTaskId !== undefined ? configuration.withTaskId : !configuration.readOnly;
40                        this.animation = configuration.animation !== undefined ? configuration.animation : true;
41                        this.saveProgramPath = configuration.saveProgramPath  || "saveGanttData.php";
42                        this.dataFilePath = configuration.dataFilePath  || "gantt_default.json";
43                        this.contentHeight = configuration.height || 400;
44                        this.contentWidth = configuration.width || 600;
45                        this.content = dom.byId(node);
46                        this.scrollBarWidth = 18;
47                        this.panelTimeHeight = 102;
48                        this.maxWidthPanelNames = 150;
49                        this.maxWidthTaskNames = 150;
50                        this.minWorkLength = 8;
51                        this.heightTaskItem = 12;
52                        this.heightTaskItemExtra = 11;
53                        this.pixelsPerDay = 24;//px
54                        this.hsPerDay = 8;
55                        this.pixelsPerWorkHour = this.pixelsPerDay / this.hsPerDay;//px
56                        this.pixelsPerHour = this.pixelsPerDay / 24;//px
57                        this.countDays = 0;
58                        this.totalDays = 0;
59                        this.startDate = null;
60                        this.initialPos = 0;
61                       
62                        this.contentDataHeight = 0;
63                        this.panelTimeExpandDelta = 20;
64                       
65                        this.divTimeInfo = null;
66                        this.panelNames = null;
67                        this.panelTime = null;
68                        this.contentData = null;
69                        this.tabMenu = null;
70                       
71                        this.project = [];
72                        this.arrProjects = [];
73                       
74                        this.xmlLoader = null;
75                        this.isMoving = false;
76                        this.isResizing = false;
77                        this.animationNodes = [];
78                        this.scale = 1;
79                        this.tempDayInPixels = 0;
80                        this.resource = null;
81                        this.months = locale.getNames("months", "wide");
82                        this._events = [];
83                },
84                getProject: function(id){
85                        return arrayUtil.filter(this.arrProjects, function(proj){
86                                return proj.project.id == id;
87                        }, this)[0];
88                },
89                checkPosPreviousTask: function(predTask, task){
90                        var widthPred = this.getWidthOnDuration(predTask.duration);
91                        var posPred = this.getPosOnDate(predTask.startTime);
92                        var posChild = this.getPosOnDate(task.startTime);
93                        return (widthPred + posPred) <= posChild;
94
95                },
96                correctPosPreviousTask: function(predTask, ctask, ctaskObj){
97                        var newDate = new Date(predTask.startTime);
98                        newDate.setHours(newDate.getHours() + (predTask.duration / this.hsPerDay * 24));
99                        if(newDate.getHours() > 0){
100                                newDate.setHours(0);
101                                newDate.setDate(newDate.getDate() + 1);
102                        }
103                        ctaskObj ? (ctaskObj.setStartTime(newDate, true)) : (ctask.startTime = newDate);
104                        if(ctask.parentTask){
105                                if(!this.checkPosParentTask(ctask.parentTask, ctask)){
106                                        var newDate2 = new Date(ctask.parentTask.startTime);
107                                        newDate2.setHours(newDate2.getHours() + (ctask.parentTask.duration / this.hsPerDay * 24));
108                                        ctask.duration = parseInt((parseInt((newDate2 - ctask.startTime) / (1000 * 60 * 60))) * this.hsPerDay / 24);
109                                }
110                        }
111                },
112                correctPosParentTask: function(parentTask, ctask){
113                        if(!ctask.previousTask){
114                                if(parentTask.startTime > ctask.startTime){
115                                        ctask.startTime = new Date(parentTask.startTime);
116                                }
117                                if(!this.checkPosParentTask(parentTask, ctask)){
118                                        ctask.duration = parentTask.duration;
119                                }
120                        }else{
121                                this.correctPosPreviousTask(ctask.previousTask, ctask);
122                        }
123                },
124                checkPosParentTaskInTree: function(parentTask){
125                        var exception = false;
126                        for(var i = 0; i < parentTask.cldTasks.length; i++){
127                                var pcTask = parentTask.cldTasks[i];
128                                if(!this.checkPosParentTask(parentTask, pcTask)){
129                                        if(!this.correctError){
130                                                return true;
131                                        }else{
132                                                this.correctPosParentTask(parentTask, pcTask);
133                                        }
134                                }
135                                if(parentTask.startTime > pcTask.startTime){
136                                        if(!this.correctError){
137                                                return true;
138                                        }else{
139                                                this.correctPosParentTask(parentTask, pcTask);
140                                        }
141                                }
142                                if(pcTask.cldTasks.length > 0){
143                                        exception = this.checkPosParentTaskInTree(pcTask);
144                                }
145                        }
146                        return exception;
147                },
148                setPreviousTask: function(project){
149                        var exception = false;
150                        for(var i = 0; i < project.parentTasks.length; i++){
151                                var ppTask = project.parentTasks[i];
152                                if(ppTask.previousTaskId){
153                                        ppTask.previousTask = project.getTaskById(ppTask.previousTaskId);
154                                        if(!ppTask.previousTask){
155                                                if(!this.correctError){
156                                                        return true;
157                                                }
158                                        }
159                                        ppTask.previousTask.cldPreTasks.push(ppTask);
160                                }
161                                if(ppTask.previousTask){
162                                        if(!this.checkPosPreviousTask(ppTask.previousTask, ppTask)){
163                                                if(!this.correctError){
164                                                        return true;
165                                                }else{
166                                                        this.correctPosPreviousTask(ppTask.previousTask, ppTask);
167                                                }
168                                        }
169                                }
170                                exception = this.setPreviousTaskInTree(ppTask);
171                        }
172                        return exception;
173                },
174                setPreviousTaskInTree: function(parentTask){
175                        var exception = false;
176                        for(var i = 0; i < parentTask.cldTasks.length; i++){
177                                var pcTask = parentTask.cldTasks[i];
178                                if(pcTask.previousTaskId){
179                                        pcTask.previousTask = parentTask.project.getTaskById(pcTask.previousTaskId);
180                                        if(!pcTask.previousTask){
181                                                if(!this.correctError){
182                                                        return true;
183                                                }
184                                        }
185                                        if(!this.checkPosPreviousTask(pcTask.previousTask, pcTask)){
186                                                if(!this.correctError){
187                                                        return true;
188                                                }else{
189                                                        this.correctPosPreviousTask(pcTask.previousTask, pcTask);
190                                                }
191                                        }
192                                        pcTask.previousTask.cldPreTasks.push(pcTask);
193                                }
194                               
195                                if(pcTask.cldTasks.length > 0){
196                                        exception = this.setPreviousTaskInTree(pcTask);
197                                }
198                        }
199                        return exception;
200                },
201                checkPosParentTask: function(parentTask, task){
202                        var widthParent = this.getWidthOnDuration(parentTask.duration);
203                        var posParent = this.getPosOnDate(parentTask.startTime);
204                        var posChild = this.getPosOnDate(task.startTime);
205                        var widthChild = this.getWidthOnDuration(task.duration);
206                        return (widthParent + posParent) >= (posChild + widthChild);
207                },
208                addProject: function(projectItem){
209                        this.project.push(projectItem);
210                },
211                deleteProject: function(id){
212                        var project = this.getProject(id);
213                        if(project){
214                                if(project.arrTasks.length > 0){
215                                        while(project.arrTasks.length > 0){
216                                                project.deleteChildTask(project.arrTasks[0]);
217                                        }
218                                }
219                                var rowHeight = this.heightTaskItemExtra + this.heightTaskItem;
220                                project.nextProject && project.shiftNextProject(project, -rowHeight); //rowHeight: 23
221                                this.project = arrayUtil.filter(this.project, function(proj){
222                                        return proj.id != project.project.id;
223                                }, this);
224                                if((project.previousProject) && (project.nextProject)){
225                                        var previousProject = project.previousProject;
226                                        previousProject.nextProject = project.nextProject;
227                                }
228                                if((project.previousProject) && !(project.nextProject)){
229                                        var previousProject = project.previousProject;
230                                        previousProject.nextProject = null;
231                                }
232                                if(!(project.previousProject) && (project.nextProject)){
233                                        var nextProject = project.nextProject;
234                                        nextProject.previousProject = null;
235                                }
236                                for(var i = 0; i < this.arrProjects.length; i++){
237                                        if(this.arrProjects[i].project.id == id){
238                                                this.arrProjects.splice(i, 1);
239                                        }
240                                }
241                                project.projectItem[0].parentNode.removeChild(project.projectItem[0]);
242                                project.descrProject.parentNode.removeChild(project.descrProject);
243                                project.projectNameItem.parentNode.removeChild(project.projectNameItem);
244                                this.contentDataHeight -= this.heightTaskItemExtra + this.heightTaskItem;
245                                if(this.project.length == 0){
246                                        var d = new Date(this.startDate);
247                                        var t = new Date(d.setDate(d.getDate() + 1));
248                                        var pi = new GanttProjectItem({
249                                                id: 1,
250                                                name: "New Project",
251                                                startDate: t
252                                        });
253                                        this.project.push(pi);
254                                        var project = new GanttProjectControl(this, pi);
255                                        project.create();
256                                        this.arrProjects.push(project);
257                                        this.contentDataHeight += this.heightTaskItemExtra + this.heightTaskItem;
258                                }
259                                this.checkPosition();
260                        }
261                },
262                insertProject: function(id, name, startDate){
263                        if(this.startDate >= startDate){
264                                return false;
265                        }
266                        if(this.getProject(id)){
267                                return false;
268                        }
269                        this.checkHeighPanelTasks();
270                        var project = new GanttProjectItem({
271                                id: id,
272                                name: name,
273                                startDate: startDate
274                        });
275                        this.project.push(project);
276                        var _project = new GanttProjectControl(this, project);
277                        for(var i = 0; i < this.arrProjects.length; i++){
278                                var curProject = this.arrProjects[i],
279                                        preProject = this.arrProjects[i-1],
280                                        nextProject = this.arrProjects[i+1];
281                                if(startDate < curProject.project.startDate){
282                                        this.arrProjects.splice(i, 0, _project);
283                                        if(i > 0){
284                                                _project.previousProject = preProject;
285                                                preProject.nextProject = _project;
286                                        }
287                                        if(i + 1 <= this.arrProjects.length){
288                                                _project.nextProject = nextProject;
289                                                nextProject.previousProject = _project;
290                                                var rowHeight = this.heightTaskItem + this.heightTaskItemExtra;
291                                                _project.shiftNextProject(_project, rowHeight);
292                                        }
293                                        _project.create();
294                                        _project.hideDescrProject();
295                                        this.checkPosition();
296                                        return _project;
297                                }
298                        }
299                        if(this.arrProjects.length > 0){
300                                this.arrProjects[this.arrProjects.length - 1].nextProject = _project;
301                                _project.previousProject = this.arrProjects[this.arrProjects.length - 1];
302                        }
303                        this.arrProjects.push(_project);
304                        _project.create();
305                        _project.hideDescrProject();
306                        this.checkPosition();
307                        return _project;
308                },
309                openTree: function(parentTask){
310                        var lastParentTask = this.getLastCloseParent(parentTask);
311                        this.openNode(lastParentTask);
312                        parentTask.taskItem.id != lastParentTask.taskItem.id && this.openTree(parentTask);
313                },
314                openNode: function(parentTask){
315                        if(!parentTask.isExpanded){
316                                domClass.remove(parentTask.cTaskNameItem[2], "ganttImageTreeExpand");
317                                domClass.add(parentTask.cTaskNameItem[2], "ganttImageTreeCollapse");
318                                parentTask.isExpanded = true;
319                                parentTask.shiftCurrentTasks(parentTask, parentTask.hideTasksHeight);
320                                parentTask.showChildTasks(parentTask, parentTask.isExpanded);
321                                parentTask.hideTasksHeight = 0;
322                        }
323                },
324                getLastCloseParent: function(task){
325                        if(task.parentTask){
326                                if((!task.parentTask.isExpanded) ||
327                                (task.parentTask.cTaskNameItem[2].style.display == "none")){
328                                        return this.getLastCloseParent(task.parentTask);
329                                }else{
330                                        return task;
331                                }
332                        }else{
333                                return task;
334                        }
335                },
336                getProjectItemById: function(id){
337                        return arrayUtil.filter(this.project, function(proj){
338                                return proj.id == id;
339                        }, this)[0];
340                },
341                clearAll: function(){
342                        this.contentDataHeight = 0;
343                        this.startDate = null;
344                        this.clearData();
345                        this.clearItems();
346                        this.clearEvents();
347                },
348                clearEvents: function(){
349                        arrayUtil.forEach(this._events, function(e){
350                                e.remove();
351                        });
352                        this._events = [];
353                },
354                clearData: function(){
355                        this.project = [];
356                        this.arrProjects = [];
357                },
358                clearItems: function(){
359                        this.contentData.removeChild(this.contentData.firstChild);
360                        this.contentData.appendChild(this.createPanelTasks());
361                        this.panelNames.removeChild(this.panelNames.firstChild);
362                        this.panelNames.appendChild(this.createPanelNamesTasks());
363                        this.panelTime.removeChild(this.panelTime.firstChild);
364                },
365                buildUIContent: function(){
366                        this.project.sort(this.sortProjStartDate);
367                        this.startDate = this.getStartDate();
368                        this.panelTime.appendChild(this.createPanelTime());
369                        for(var i = 0; i < this.project.length; i++){
370                                var proj = this.project[i];
371                                for(var k = 0; k < proj.parentTasks.length; k++){
372                                        var ppTask = proj.parentTasks[k];
373                                        if(ppTask.startTime){
374                                                this.setStartTimeChild(ppTask);
375                                        }else{
376                                                return;
377                                        }
378                                        if(this.setPreviousTask(proj)){
379                                                return;
380                                        }
381                                }
382                                for(var k = 0; k < proj.parentTasks.length; k++){
383                                        var ppTask = proj.parentTasks[k];
384                                        if(ppTask.startTime < proj.startDate){
385                                                return;
386                                        }
387                                        if(this.checkPosParentTaskInTree(ppTask)) return;
388                                }
389                                this.sortTasksByStartTime(proj);
390                        }
391                       
392                        for(var i = 0; i < this.project.length; i++){
393                                var proj = this.project[i];
394                                var project = new GanttProjectControl(this, proj);
395                                if(this.arrProjects.length > 0){
396                                        var previousProject = this.arrProjects[this.arrProjects.length - 1];
397                                        project.previousProject = previousProject;
398                                        previousProject.nextProject = project;
399                                }
400                                project.create();
401                                this.checkHeighPanelTasks();
402                                this.arrProjects.push(project);
403                                this.createTasks(project);
404                        }
405                        this.resource && this.resource.reConstruct();
406                        this.postLoadData();
407                        this.postBindEvents();
408                },
409                loadJSONData: function(filename){
410                        var _this = this;
411                        _this.dataFilePath = filename || _this.dataFilePath;
412                        request.get(_this.dataFilePath, {
413                                sync: true
414                        }).then(function(response){
415                                _this.loadJSONString(response.text);
416                                _this.buildUIContent();
417                                console.log("Successfully! Loaded data from: " + _this.dataFilePath);
418                        }, function(){
419                                console.log("Failed! Load error: " + _this.dataFilePath);
420                        });
421                },
422                loadJSONString: function(content){
423                        //load data
424                        if(!content){ return; }
425                        this.clearAll();
426                        var jsonObj = JSON.parse(content);
427                       
428                        var items = jsonObj.items;
429                        arrayUtil.forEach(items, function(pItem){
430                                var startDate = pItem.startdate.split("-");
431                                var project = new GanttProjectItem({
432                                        id: pItem.id,
433                                        name: pItem.name,
434                                        startDate: new Date(startDate[0], (parseInt(startDate[1]) - 1), startDate[2])
435                                });
436                                var tItems = pItem.tasks;
437                                arrayUtil.forEach(tItems, function(tItem){
438                                        var id = tItem.id,
439                                                name = tItem.name,
440                                                starttime = tItem.starttime.split("-"),
441                                                duration = tItem.duration,
442                                                percentage = tItem.percentage,
443                                                previousTaskId = tItem.previousTaskId,
444                                                taskOwner = tItem.taskOwner;
445                                       
446                                        var task = new GanttTaskItem({
447                                                id: id,
448                                                name: name,
449                                                startTime: new Date(starttime[0], (parseInt(starttime[1]) - 1), starttime[2]),
450                                                duration: duration,
451                                                percentage: percentage,
452                                                previousTaskId: previousTaskId,
453                                                taskOwner: taskOwner
454                                        });
455                                        var ctItems = tItem.children;
456                                        if(ctItems.length != 0){
457                                                this.buildChildTasksData(task, ctItems);
458                                        }
459                                        project.addTask(task);
460                                }, this);
461                                this.addProject(project);
462                         }, this);
463                },
464                buildChildTasksData: function(parentTask, childTaskItems){
465                        childTaskItems && arrayUtil.forEach(childTaskItems, function(ctItem){
466                                var id = ctItem.id,
467                                        name = ctItem.name,
468                                        starttime = ctItem.starttime.split("-"),
469                                        duration = ctItem.duration,
470                                        percentage = ctItem.percentage,
471                                        previousTaskId = ctItem.previousTaskId,
472                                        taskOwner = ctItem.taskOwner;
473                               
474                                var task = new GanttTaskItem({
475                                        id: id,
476                                        name: name,
477                                        startTime: new Date(starttime[0], (parseInt(starttime[1]) - 1), starttime[2]),
478                                        duration: duration,
479                                        percentage: percentage,
480                                        previousTaskId: previousTaskId,
481                                        taskOwner: taskOwner
482                                });
483                                task.parentTask = parentTask;
484                                parentTask.addChildTask(task);
485                               
486                                var ctItems = ctItem.children;
487                                if(ctItems.length != 0){
488                                        this.buildChildTasksData(task, ctItems);
489                                }
490                        }, this);
491                },
492                getJSONData: function(){
493                        var jsonObj = {identifier: 'id', items: []};
494                        arrayUtil.forEach(this.project, function(proj){
495                                var project = {
496                                        id: proj.id,
497                                        name: proj.name,
498                                        startdate: proj.startDate.getFullYear() + '-' + (proj.startDate.getMonth() + 1) + '-' + proj.startDate.getDate(),
499                                        tasks: []
500                                };
501                                jsonObj.items.push(project);
502                                arrayUtil.forEach(proj.parentTasks, function(pTask){
503                                        var task = {
504                                                id: pTask.id,
505                                                name: pTask.name,
506                                                starttime: pTask.startTime.getFullYear() + '-' + (pTask.startTime.getMonth() + 1) + '-' + pTask.startTime.getDate(),
507                                                duration: pTask.duration,
508                                                percentage: pTask.percentage,
509                                                previousTaskId: (pTask.previousTaskId || ''),
510                                                taskOwner: (pTask.taskOwner || ''),
511                                                children: this.getChildTasksData(pTask.cldTasks)
512                                        };
513                                        project.tasks.push(task);
514                                }, this);
515                        }, this);
516                        return jsonObj;
517                },
518                getChildTasksData: function(childTasks){
519                        var cTaskObj = [];
520                        childTasks && childTasks.length > 0 && arrayUtil.forEach(childTasks, function(childTask){
521                                var ctask = {
522                                        id: childTask.id,
523                                        name: childTask.name,
524                                        starttime: childTask.startTime.getFullYear() + '-' + (childTask.startTime.getMonth() + 1) + '-' + childTask.startTime.getDate(),
525                                        duration: childTask.duration,
526                                        percentage: childTask.percentage,
527                                        previousTaskId: (childTask.previousTaskId || ''),
528                                        taskOwner: (childTask.taskOwner || ''),
529                                        children: this.getChildTasksData(childTask.cldTasks)
530                                };
531                                cTaskObj.push(ctask);
532                        }, this);
533                        return cTaskObj;
534                },
535                saveJSONData: function(fileName){
536                        var _this = this;
537                        _this.dataFilePath = (fileName && lang.trim(fileName).length > 0) ? fileName : this.dataFilePath;
538                        try {
539                                request.post(_this.saveProgramPath, {
540                                        query: {filename: _this.dataFilePath, data: JSON.stringify(_this.getJSONData())}
541                                }).response.then(function(response){
542                                        if((util.checkStatus(response.options.status))||
543                                                (response.options.status == 405)
544                                        ){
545                                                console.log("Successfully! Saved data to " + _this.dataFilePath);
546                                        }else{
547                                                console.log("Failed! Saved error");
548                                        }
549                                });
550                        } catch(e){
551                                console.log("exception: " + e.message);
552                        }
553                },
554                sortTaskStartTime: function(a, b){
555                        return a.startTime < b.startTime ? -1 : (a.startTime > b.startTime ? 1 : 0);
556                },
557                sortProjStartDate: function(a, b){
558                        return a.startDate < b.startDate ? -1 : (a.startDate > b.startDate ? 1 : 0);
559                },
560                setStartTimeChild: function(parentTask){
561                        arrayUtil.forEach(parentTask.cldTasks, function(pcTask){
562                                if(!pcTask.startTime){
563                                        pcTask.startTime = parentTask.startTime;
564                                }
565                                if(pcTask.cldTasks.length != 0){
566                                        this.setStartTimeChild(pcTask);
567                                }
568                        }, this);
569                },
570                createPanelTasks: function(){
571                        var panelTask = domConstruct.create("div", {
572                                className: "ganttTaskPanel"
573                        });
574                        domStyle.set(panelTask, {
575                                height: (this.contentHeight - this.panelTimeHeight - this.scrollBarWidth) + "px"
576                        });
577                        return panelTask;
578                },
579                refreshParams: function(pixelsPerDay){
580                        this.pixelsPerDay = pixelsPerDay;
581                        this.pixelsPerWorkHour = this.pixelsPerDay / this.hsPerDay;
582                        this.pixelsPerHour = this.pixelsPerDay / 24;
583                },
584                createPanelNamesTasksHeader: function(){
585                        var panelHeader = domConstruct.create("div", {className: "ganttPanelHeader"});
586                        var tblHeader = domConstruct.create("table", {
587                                cellPadding: "0px",
588                                border: "0px",
589                                cellSpacing: "0px",
590                                bgColor: "#FFFFFF",
591                                className: "ganttToolbar"
592                        }, panelHeader);
593                        var firstRow = tblHeader.insertRow(tblHeader.rows.length);
594                        var secondRow = tblHeader.insertRow(tblHeader.rows.length);
595                        var thirdRow = tblHeader.insertRow(tblHeader.rows.length);
596                        var forthRow = tblHeader.insertRow(tblHeader.rows.length);
597                        var zoomIn = domConstruct.create("td", {
598                                align: "center",
599                                vAlign: "middle",
600                                className: "ganttToolbarZoomIn"
601                        }, firstRow);
602                        var zoomInFn = lang.hitch(this, function(){
603                                if(this.scale * 2 > 5){return;}
604                                this.scale = this.scale * 2;
605                                this.switchTeleMicroView(this.pixelsPerDay * this.scale);
606                        });
607                        if(this.zoomInClickEvent){
608                                this.zoomInClickEvent.remove();
609                        }
610                        this.zoomInClickEvent = on(zoomIn, "click", lang.hitch(this, zoomInFn));
611                        //a11y support
612                        if(this.zoomInKeyEvent){
613                                this.zoomInKeyEvent.remove();
614                        }
615                        this.zoomInKeyEvent = on(zoomIn, "keydown", lang.hitch(this, function(e){
616                                if(e.keyCode != keys.ENTER){return;}
617                                zoomInFn();
618                        }));
619
620                        domAttr.set(zoomIn, "tabIndex", 0);
621                        var zoomOut = domConstruct.create("td", {
622                                align: "center",
623                                vAlign: "middle",
624                                className: "ganttToolbarZoomOut"
625                        }, firstRow);
626                        var zoomOutFn = lang.hitch(this, function(){
627                                if(this.scale * 0.5 < 0.2){return;}
628                                this.scale = this.scale * 0.5;
629                                this.switchTeleMicroView(this.pixelsPerDay * this.scale);
630                        });
631                        if(this.zoomOutClickEvent){
632                                this.zoomOutClickEvent.remove();
633                        }
634                        this.zoomOutClickEvent = on(zoomOut, "click", lang.hitch(this, zoomOutFn));
635
636                        //a11y support
637                        if(this.zoomOutKeyEvent){
638                                this.zoomOutKeyEvent.remove();
639                        }
640                        this.zoomOutKeyEvent = on(zoomOut, "keydown", lang.hitch(this, function(e){
641                                if(e.keyCode != keys.ENTER){return;}
642                                zoomOutFn();
643                        }));
644
645                        domAttr.set(zoomOut, "tabIndex", 0);
646                        var micro = domConstruct.create("td", {
647                                align: "center",
648                                vAlign: "middle",
649                                className: "ganttToolbarMicro"
650                        }, secondRow);
651                        if(this.microClickEvent){
652                                this.microClickEvent.remove();
653                        }
654                        this.microClickEvent = on(micro, "click", lang.hitch(this, this.refresh, this.animation?15:1, 0, 2));
655
656                        //a11y support
657                        if(this.microKeyEvent){
658                                this.microKeyEvent.remove();
659                        }
660                        this.microKeyEvent = on(micro, "keydown", lang.hitch(this, function(e){
661                                if(e.keyCode != keys.ENTER){return;}
662                                micro.blur();
663                                this.refresh(this.animation?15:1, 0, 2);
664                        }));
665
666                        domAttr.set(micro, "tabIndex", 0);
667                        var tele = domConstruct.create("td", {
668                                align: "center",
669                                vAlign: "middle",
670                                className: "ganttToolbarTele"
671                        }, secondRow);
672                        if(this.teleClickEvent){
673                                this.teleClickEvent.remove();
674                        }
675                        this.teleClickEvent = on(tele, "click", lang.hitch(this, this.refresh, this.animation?15:1, 0, 0.5));
676                        //a11y support
677                        if(this.teleKeyEvent){
678                                this.teleKeyEvent.remove();
679                        }
680                        this.teleKeyEvent = on(tele, "keydown", lang.hitch(this, function(e){
681                                if(e.keyCode != keys.ENTER){return;}
682                                tele.blur();
683                                this.refresh(this.animation?15:1, 0, 0.5);
684                        }));
685                        domAttr.set(tele, "tabIndex", 0);
686                        var save = domConstruct.create("td", {
687                                align: "center",
688                                vAlign: "middle",
689                                className: "ganttToolbarSave"
690                        }, thirdRow);
691                        if(this.saveClickEvent){
692                                this.saveClickEvent.remove();
693                        }
694                        this.saveClickEvent = on(save, "click", lang.hitch(this, this.saveJSONData, ""));
695                        //a11y support
696                        if(this.saveKeyEvent){
697                                this.saveKeyEvent.remove();
698                        }
699                        this.saveKeyEvent = on(save, "keydown", lang.hitch(this, function(e){
700                                if(e.keyCode != keys.ENTER){return;}
701                                this.saveJSONData("");
702                        }));
703                        domAttr.set(save, "tabIndex", 0);
704                        var load = domConstruct.create("td", {
705                                align: "center",
706                                vAlign: "middle",
707                                className: "ganttToolbarLoad"
708                        }, thirdRow);
709                        if(this.loadClickEvent){
710                                this.loadClickEvent.remove();
711                        }
712                        this.loadClickEvent = on(load, "click", lang.hitch(this, this.loadJSONData, ""));
713                        //a11y support
714                        if(this.loadKeyEvent){
715                                this.loadKeyEvent.remove();
716                        }
717                        this.loadKeyEvent = on(load, "keydown", lang.hitch(this, function(e){
718                                if(e.keyCode != keys.ENTER){return;}
719                                this.loadJSONData("");
720                        }));
721
722                        domAttr.set(load, "tabIndex", 0);
723                        //action popup description
724                        var actions = [zoomIn, zoomOut, micro, tele, save, load],
725                                titles = ["Enlarge timeline", "Shrink timeline", "Zoom in time zone(microscope view)", "Zoom out time zone(telescope view)",
726                                                        "Save gantt data to json file", "Load gantt data from json file"];
727                        arrayUtil.forEach(actions, function(action, i){
728                                var title = titles[i];
729                                var tooltipShow = function(){
730                                        domClass.add(action, "ganttToolbarActionHover");
731                                        // FIXME: including dijit/Tooltip moves showTooltip and hideTooltip into the dijit namespace
732                                        dijit.showTooltip(title, action, ["above", "below"]);
733                                };
734                                action.onmouseover = tooltipShow;
735                                //a11y support
736                                action.onfocus = tooltipShow;
737                                var tooltipHide = function(){
738                                        domClass.remove(action, "ganttToolbarActionHover");
739                                        action && dijit.hideTooltip(action);
740                                };
741                                action.onmouseout = tooltipHide;
742                                action.onblur = tooltipHide;
743                        }, this);
744                        return panelHeader;
745                },
746                createPanelNamesTasks: function(){
747                        var panelNameTask = domConstruct.create("div", {
748                                innerHTML: "&nbsp;",
749                                className: "ganttPanelNames"
750                        });
751                        domStyle.set(panelNameTask, {
752                                height: (this.contentHeight - this.panelTimeHeight - this.scrollBarWidth) + "px",
753                                width: this.maxWidthPanelNames + "px"
754                        });
755                        return panelNameTask;
756                },
757                createPanelTime: function(){
758                        var panelTime = domConstruct.create("div", {className: "ganttPanelTime"});
759                        var tblTime = domConstruct.create("table", {
760                                cellPadding: "0px",
761                                border: "0px",
762                                cellSpacing: "0px",
763                                bgColor: "#FFFFFF",
764                                className: "ganttTblTime"
765                        }, panelTime);
766                        this.totalDays = this.countDays;
767                        //year
768                        var newYearRow = tblTime.insertRow(tblTime.rows.length), oldYear, newYear, ycount = 0;
769                        newYear = oldYear = new Date(this.startDate).getFullYear();
770                        for(var i = 0; i < this.countDays; i++, ycount++){
771                                var date = new Date(this.startDate);
772                                date.setDate(date.getDate() + i);
773                                newYear = date.getFullYear();
774                                if(newYear != oldYear){
775                                        this.addYearInPanelTime(newYearRow, ycount, oldYear);
776                                        ycount = 0;
777                                        oldYear = newYear;
778                                }
779                        }
780                        this.addYearInPanelTime(newYearRow, ycount, newYear);
781                        domStyle.set(newYearRow, "display", "none");
782                        //month
783                        var newMonthRow = tblTime.insertRow(tblTime.rows.length), oldMonth, newMonth, mcount = 0, lastYear = 1970;
784                        newMonth = oldMonth = new Date(this.startDate).getMonth();
785                        for(var i = 0; i < this.countDays; i++, mcount++){
786                                var date = new Date(this.startDate);
787                                date.setDate(date.getDate() + i);
788                                newMonth = date.getMonth();
789                                lastYear = date.getFullYear();
790                                if(newMonth != oldMonth){
791                                        this.addMonthInPanelTime(newMonthRow, mcount, oldMonth, lastYear);
792                                        mcount = 0;
793                                        oldMonth = newMonth;
794                                }
795                        }
796                        this.addMonthInPanelTime(newMonthRow, mcount, newMonth, lastYear);
797                        //week
798                        var newWeekRow = tblTime.insertRow(tblTime.rows.length), oldWeek, newWeek, mcount = 0;
799                        newWeek = oldWeek = locale._getWeekOfYear(new Date(this.startDate));
800                        for(var i = 0; i < this.countDays; i++, mcount++){
801                                var date = new Date(this.startDate);
802                                date.setDate(date.getDate() + i);
803                                newWeek = locale._getWeekOfYear(date);
804                                if(newWeek != oldWeek){
805                                        this.addWeekInPanelTime(newWeekRow, mcount, oldWeek);
806                                        mcount = 0;
807                                        oldWeek = newWeek;
808                                }
809                        }
810                        this.addWeekInPanelTime(newWeekRow, mcount, newWeek);
811                        //day
812                        var newDayRow = tblTime.insertRow(tblTime.rows.length);
813                        for(var i = 0; i < this.countDays; i++){
814                                this.addDayInPanelTime(newDayRow);
815                        }
816                        //hour
817                        var newHourRow = tblTime.insertRow(tblTime.rows.length);
818                        for(var i = 0; i < this.countDays; i++){
819                                this.addHourInPanelTime(newHourRow);
820                        }
821                        domStyle.set(newHourRow, "display", "none");
822                        return panelTime;
823                },
824                adjustPanelTime: function(){
825                        var maxEndPos = arrayUtil.map(this.arrProjects, function(project){
826                                return (parseInt(project.projectItem[0].style.left) + parseInt(project.projectItem[0].firstChild.style.width)
827                                        + project.descrProject.offsetWidth + this.panelTimeExpandDelta);
828                        }, this).sort(function(a,b){return b-a})[0];
829                        if(this.maxTaskEndPos != maxEndPos){
830                                //reset panel time
831                                var prows = this.panelTime.firstChild.firstChild.rows;
832                                for(var i = 0; i <= 4; i++){//prows.length
833                                        this.removeCell(prows[i]);
834                                }
835                                var countDays = Math.round((maxEndPos+this.panelTimeExpandDelta) / this.pixelsPerDay);
836                                this.totalDays = countDays;
837                                //year
838                                var oldYear, newYear, ycount = 0;
839                                newYear = oldYear = new Date(this.startDate).getFullYear();
840                                for(var i = 0; i < countDays; i++, ycount++){
841                                        var date = new Date(this.startDate);
842                                        date.setDate(date.getDate() + i);
843                                        newYear = date.getFullYear();
844                                        if(newYear != oldYear){
845                                                this.addYearInPanelTime(prows[0], ycount, oldYear);
846                                                ycount = 0;
847                                                oldYear = newYear;
848                                        }
849                                }
850                                this.addYearInPanelTime(prows[0], ycount, newYear);
851                                //month
852                                var oldMonth, newMonth, mcount = 0, lastYear = 1970;
853                                newMonth = oldMonth = new Date(this.startDate).getMonth();
854                                for(var i = 0; i < countDays; i++, mcount++){
855                                        var date = new Date(this.startDate);
856                                        date.setDate(date.getDate() + i);
857                                        newMonth = date.getMonth();
858                                        lastYear = date.getFullYear();
859                                        if(newMonth != oldMonth){
860                                                this.addMonthInPanelTime(prows[1], mcount, oldMonth, lastYear);
861                                                mcount = 0;
862                                                oldMonth = newMonth;
863                                        }
864                                }
865                                this.addMonthInPanelTime(prows[1], mcount, newMonth, lastYear);
866                                //week
867                                var oldWeek, newWeek, mcount = 0;
868                                newWeek = oldWeek = locale._getWeekOfYear(new Date(this.startDate));
869                                for(var i = 0; i < countDays; i++, mcount++){
870                                        var date = new Date(this.startDate);
871                                        date.setDate(date.getDate() + i);
872                                        newWeek = locale._getWeekOfYear(date);
873                                        if(newWeek != oldWeek){
874                                                this.addWeekInPanelTime(prows[2], mcount, oldWeek);
875                                                mcount = 0;
876                                                oldWeek = newWeek;
877                                        }
878                                }
879                                this.addWeekInPanelTime(prows[2], mcount, newWeek);
880                                //day
881                                for(var i = 0; i < countDays; i++){
882                                        this.addDayInPanelTime(prows[3]);
883                                }
884                                //hour
885                                for(var i = 0; i < countDays; i++){
886                                        this.addHourInPanelTime(prows[4]);
887                                }
888                                this.panelTime.firstChild.firstChild.style.width = this.pixelsPerDay * (prows[3].cells.length) + "px";
889                                this.contentData.firstChild.style.width = this.pixelsPerDay * (prows[3].cells.length) + "px";
890                                this.maxTaskEndPos = maxEndPos;
891                        }
892                },
893                addYearInPanelTime: function(row, count, year){
894                        var data = "Year   " + year;
895                        var newCell = domConstruct.create("td", {
896                                colSpan: count,
897                                align: "center",
898                                vAlign: "middle",
899                                className: "ganttYearNumber",
900                                innerHTML: this.pixelsPerDay * count > 20 ? data : "",
901                                innerHTMLData: data
902                        }, row);
903                        domStyle.set(newCell, "width", (this.pixelsPerDay * count) + "px");
904                },
905                addMonthInPanelTime: function(row, count, month, year){
906                        var data = this.months[month] + (year ? " of " + year : "");
907                        var newCell = domConstruct.create("td", {
908                                colSpan: count,
909                                align: "center",
910                                vAlign: "middle",
911                                className: "ganttMonthNumber",
912                                innerHTML: this.pixelsPerDay * count > 30 ? data : "",
913                                innerHTMLData: data
914                        }, row);
915                        domStyle.set(newCell, "width", (this.pixelsPerDay * count) + "px");
916                },
917                addWeekInPanelTime: function(row, count, week){
918                        var data = "Week   " + week;
919                        var newCell = domConstruct.create("td", {
920                                colSpan: count,
921                                align: "center",
922                                vAlign: "middle",
923                                className: "ganttWeekNumber",
924                                innerHTML: this.pixelsPerDay * count > 20 ? data : "",
925                                innerHTMLData: data
926                        }, row);
927                        domStyle.set(newCell, "width", (this.pixelsPerDay * count) + "px");
928                },
929                addDayInPanelTime: function(row){
930                        var date = new Date(this.startDate);
931                        date.setDate(date.getDate() + parseInt(row.cells.length));
932                        var newCell = domConstruct.create("td", {
933                                align: "center",
934                                vAlign: "middle",
935                                className: "ganttDayNumber",
936                                innerHTML: this.pixelsPerDay > 20 ? date.getDate() : "",
937                                innerHTMLData: String(date.getDate()),
938                                data: row.cells.length
939                        }, row);
940                        domStyle.set(newCell, "width", this.pixelsPerDay + "px");
941                        (date.getDay() >= 5) && domClass.add(newCell, "ganttDayNumberWeekend");
942                        this._events.push(
943                                on(newCell, "mouseover", lang.hitch(this, function(event){
944                                        var dayTime = event.target || event.srcElement;
945                                        var date = new Date(this.startDate.getTime());
946                                        date.setDate(date.getDate() + parseInt(domAttr.get(dayTime, "data")));
947                                        dijit.showTooltip(date.getFullYear() + "." + (date.getMonth() + 1) + "." + date.getDate(), newCell, ["above", "below"]);
948                                }))
949                        );
950                        this._events.push(
951                                on(newCell, "mouseout", lang.hitch(this, function(event){
952                                        var dayTime = event.target || event.srcElement;
953                                        dayTime && dijit.hideTooltip(dayTime);
954                                }))
955                        );
956                },
957                addHourInPanelTime: function(row){
958                        var newCell = domConstruct.create("td", {
959                                align: "center",
960                                vAlign: "middle",
961                                className: "ganttHourNumber",
962                                data: row.cells.length
963                        }, row);
964                        domStyle.set(newCell, "width", this.pixelsPerDay + "px");
965                       
966                        var hourTable = domConstruct.create("table", {
967                                cellPadding: "0",
968                                cellSpacing: "0"
969                        }, newCell);
970                        var newRow = hourTable.insertRow(hourTable.rows.length);
971                        for(var i = 0; i < this.hsPerDay; i++){
972                                var hourTD = domConstruct.create("td", {
973                                        className: "ganttHourClass"
974                                }, newRow);
975                                domStyle.set(hourTD, "width", (this.pixelsPerDay / this.hsPerDay) + "px");
976                                domAttr.set(hourTD, "innerHTMLData", String(9 + i));
977                                if(this.pixelsPerDay / this.hsPerDay > 5){
978                                        domAttr.set(hourTD, "innerHTML", String(9 + i));
979                                }
980                                domClass.add(hourTD, i <= 3?"ganttHourNumberAM":"ganttHourNumberPM");
981                        }
982                },
983                incHeightPanelTasks: function(height){
984                        var containerTasks = this.contentData.firstChild;
985                        containerTasks.style.height = parseInt(containerTasks.style.height) + height + "px";
986                },
987                incHeightPanelNames: function(height){
988                        var containerNames = this.panelNames.firstChild;
989                        containerNames.style.height = parseInt(containerNames.style.height) + height + "px";
990                },
991                checkPosition: function(){
992                        arrayUtil.forEach(this.arrProjects, function(project){
993                                arrayUtil.forEach(project.arrTasks, function(task){
994                                        task.checkPosition();
995                                }, this);
996                        }, this);
997                },
998                checkHeighPanelTasks: function(){
999                        this.contentDataHeight += this.heightTaskItemExtra + this.heightTaskItem;
1000                        if((parseInt(this.contentData.firstChild.style.height) <= this.contentDataHeight)){
1001                                this.incHeightPanelTasks(this.heightTaskItem + this.heightTaskItemExtra);
1002                                this.incHeightPanelNames(this.heightTaskItem + this.heightTaskItemExtra);
1003                        }
1004                },
1005                sortTasksByStartTime: function(project){
1006                        project.parentTasks.sort(this.sortTaskStartTime);
1007                        for(var i = 0; i < project.parentTasks.length; i++){
1008                                project.parentTasks[i] = this.sortChildTasks(project.parentTasks[i]);
1009                        }
1010                },
1011                sortChildTasks: function(parenttask){
1012                        parenttask.cldTasks.sort(this.sortTaskStartTime);
1013                        for(var i = 0; i < parenttask.cldTasks.length; i++){
1014                                if(parenttask.cldTasks[i].cldTasks.length > 0) this.sortChildTasks(parenttask.cldTasks[i]);
1015                        }
1016                        return parenttask;
1017                },
1018                refresh: function(count, current, multi){
1019                        //return if no task items
1020                        if(this.arrProjects.length <= 0){return;}
1021                        if(this.arrProjects[0].arrTasks.length <= 0){return;}
1022                        //Show panel of names
1023                        if(!count || current > count){
1024                                this.refreshController();
1025                                if(this.resource){
1026                                        this.resource.refresh();
1027                                }
1028                                this.tempDayInPixels = 0;
1029                                this.panelNameHeadersCover && domStyle.set(this.panelNameHeadersCover, "display", "none");
1030                                return;
1031                        }
1032                        if(this.tempDayInPixels == 0){
1033                                this.tempDayInPixels = this.pixelsPerDay;
1034                        }
1035                        this.panelNameHeadersCover && domStyle.set(this.panelNameHeadersCover, "display", "");
1036                        var dip = this.tempDayInPixels + this.tempDayInPixels * (multi - 1) * Math.pow((current / count), 2);
1037                        this.refreshParams(dip);
1038                        arrayUtil.forEach(this.arrProjects, function(project){
1039                                arrayUtil.forEach(project.arrTasks, function(task){
1040                                        task.refresh();
1041                                }, this);
1042                                project.refresh();
1043                        }, this);
1044                        setTimeout(lang.hitch(this, function(){
1045                                this.refresh(count, ++current, multi);
1046                        }), 15);
1047                },
1048                switchTeleMicroView: function(dip){
1049                        var plChild = this.panelTime.firstChild.firstChild;
1050                        for(var i = 0; i < 5; i++){//0:Y 1:M 2:W 3:D 4:H
1051                                if(dip > 40){
1052                                        domStyle.set(plChild.rows[i], "display", (i==0||i==1)?"none":"");
1053                                }else if(dip < 20){
1054                                        domStyle.set(plChild.rows[i], "display", (i==2||i==4)?"none":"");
1055                                }else{
1056                                        domStyle.set(plChild.rows[i], "display", (i==0||i==4)?"none":"");
1057                                }
1058                        }
1059                },
1060                refreshController: function(){
1061                        this.contentData.firstChild.style.width = Math.max(1200, this.pixelsPerDay * this.totalDays) + "px";
1062                        this.panelTime.firstChild.style.width = this.pixelsPerDay * this.totalDays + "px";
1063                        this.panelTime.firstChild.firstChild.style.width = this.pixelsPerDay * this.totalDays + "px";
1064                        this.switchTeleMicroView(this.pixelsPerDay);
1065                        arrayUtil.forEach(this.panelTime.firstChild.firstChild.rows, function(row){
1066                                arrayUtil.forEach(row.childNodes, function(td){
1067                                        var cs = parseInt(domAttr.get(td, "colSpan") || 1);
1068                                        var idata = lang.trim(domAttr.get(td, "innerHTMLData")||"");
1069                                        if(idata.length > 0){
1070                                                domAttr.set(td, "innerHTML", this.pixelsPerDay * cs < 20 ? "" : idata);
1071                                        }else{
1072                                                arrayUtil.forEach(td.firstChild.rows[0].childNodes, function(td){
1073                                                        var sdata = lang.trim(domAttr.get(td, "innerHTMLData")||"");
1074                                                        domAttr.set(td, "innerHTML", this.pixelsPerDay / this.hsPerDay > 10 ? sdata : "");
1075                                                }, this);
1076                                        }
1077                                        if(cs == 1){
1078                                                domStyle.set(td, "width", (this.pixelsPerDay*cs) + "px");
1079                                                if(idata.length <= 0){
1080                                                        arrayUtil.forEach(td.firstChild.rows[0].childNodes, function(td){
1081                                                                domStyle.set(td, "width", (this.pixelsPerDay*cs / this.hsPerDay) + "px");
1082                                                        }, this);
1083                                                }
1084                                        }
1085                                }, this);
1086                        }, this);
1087                },
1088                init: function(){
1089                        this.startDate = this.getStartDate();
1090                        domStyle.set(this.content, {
1091                                width: this.contentWidth + "px",
1092                                height: this.contentHeight + "px"
1093                        });
1094                        //create Table
1095                        this.tableControl = domConstruct.create("table", {
1096                                cellPadding: "0",
1097                                cellSpacing: "0",
1098                                className: "ganttTabelControl"
1099                        });
1100                        var newRowTblControl = this.tableControl.insertRow(this.tableControl.rows.length);
1101                        //Add to content Table
1102                        this.content.appendChild(this.tableControl);
1103                        this.countDays = this.getCountDays();
1104                        //Creation panel of time
1105                        this.panelTime = domConstruct.create("div", {className: "ganttPanelTimeContainer"});
1106                        domStyle.set(this.panelTime, "height", this.panelTimeHeight + "px");
1107                        this.panelTime.appendChild(this.createPanelTime());
1108                        //Creation panel contentData
1109                        this.contentData = domConstruct.create("div", {className: "ganttContentDataContainer"});
1110                        domStyle.set(this.contentData, "height", (this.contentHeight - this.panelTimeHeight) + "px");
1111                        this.contentData.appendChild(this.createPanelTasks());
1112                        //Creation panel of names
1113                        var newCellTblControl = domConstruct.create("td", {
1114                                vAlign: "top"
1115                        });
1116                        //Creation panel of task header
1117                        this.panelNameHeaders = domConstruct.create("div", {className: "ganttPanelNameHeaders"}, newCellTblControl);
1118                        domStyle.set(this.panelNameHeaders, {
1119                                height: this.panelTimeHeight + "px",
1120                                width: this.maxWidthPanelNames + "px"
1121                        });
1122                        this.panelNameHeaders.appendChild(this.createPanelNamesTasksHeader());
1123                        this.panelNames = domConstruct.create("div", {className: "ganttPanelNamesContainer"}, newCellTblControl);
1124                        this.panelNames.appendChild(this.createPanelNamesTasks());
1125                        newRowTblControl.appendChild(newCellTblControl);
1126                        //add to control contentData and dataTime
1127                        newCellTblControl = domConstruct.create("td", {
1128                                vAlign: "top"
1129                        });
1130                        var divCell = domConstruct.create("div", {className: "ganttDivCell"});
1131                        divCell.appendChild(this.panelTime);
1132                        divCell.appendChild(this.contentData);
1133                        newCellTblControl.appendChild(divCell);
1134                        newRowTblControl.appendChild(newCellTblControl);
1135                        //Show panel of names
1136                        domStyle.set(this.panelNames, "height", (this.contentHeight - this.panelTimeHeight - this.scrollBarWidth) + "px");
1137                        domStyle.set(this.panelNames, "width", this.maxWidthPanelNames + "px");
1138                        domStyle.set(this.contentData, "width", (this.contentWidth - this.maxWidthPanelNames) + "px");
1139                        domStyle.set(this.contentData.firstChild, "width", this.pixelsPerDay * this.countDays + "px");
1140                        domStyle.set(this.panelTime, "width", (this.contentWidth - this.maxWidthPanelNames - this.scrollBarWidth) + "px");
1141                        domStyle.set(this.panelTime.firstChild, "width", this.pixelsPerDay * this.countDays + "px");
1142                        if(this.isShowConMenu){
1143                                this.tabMenu = new TabMenu(this);
1144                        }
1145                        var _this = this;
1146                        this.contentData.onscroll = function(){
1147                                _this.panelTime.scrollLeft = this.scrollLeft;
1148                                if(_this.panelNames){
1149                                        _this.panelNames.scrollTop = this.scrollTop;
1150                                        if(_this.isShowConMenu){
1151                                                _this.tabMenu.hide();
1152                                        }
1153                                }
1154                                if(_this.resource){
1155                                        _this.resource.contentData.scrollLeft = this.scrollLeft;
1156                                }
1157                        };
1158                        this.project.sort(this.sortProjStartDate);
1159                        for(var i = 0; i < this.project.length; i++){
1160                                var proj = this.project[i];
1161                                for(var k = 0; k < proj.parentTasks.length; k++){
1162                                        var ppTask = proj.parentTasks[k];
1163                                        if(!ppTask.startTime){
1164                                                ppTask.startTime = proj.startDate;
1165                                        }
1166                                        this.setStartTimeChild(ppTask);
1167                                        if(this.setPreviousTask(proj)){
1168                                                return;
1169                                        }
1170                                }
1171                                for(var k = 0; k < proj.parentTasks.length; k++){
1172                                        var ppTask = proj.parentTasks[k];
1173                                        if(ppTask.startTime < proj.startDate){
1174                                                if(!this.correctError){
1175                                                        return;
1176                                                }else{
1177                                                        ppTask.startTime = proj.startDate;
1178                                                }
1179                                        }
1180                                        if(this.checkPosParentTaskInTree(ppTask)){
1181                                                return;
1182                                        }
1183                                }
1184                                this.sortTasksByStartTime(proj);
1185                        }
1186                        for(var i = 0; i < this.project.length; i++){
1187                                //creation project
1188                                var proj = this.project[i];
1189                                var project = new GanttProjectControl(this, proj);
1190                                if(this.arrProjects.length > 0){
1191                                        var previousProject = this.arrProjects[this.arrProjects.length - 1];
1192                                        project.previousProject = previousProject;
1193                                        previousProject.nextProject = project;
1194                                }
1195                                project.create();
1196                                this.checkHeighPanelTasks();
1197                                this.arrProjects.push(project);
1198                                this.createTasks(project);
1199                        }
1200                        if(this.withResource){
1201                                this.resource = new GanttResourceItem(this);
1202                                this.resource.create();
1203                        }
1204                        this.postLoadData();
1205                        this.postBindEvents();
1206                        return this;
1207                },
1208                postLoadData: function(){
1209                        arrayUtil.forEach(this.arrProjects, function(project){
1210                                arrayUtil.forEach(project.arrTasks, function(task){
1211                                        task.postLoadData();
1212                                }, this);
1213                                project.postLoadData();
1214                        }, this);
1215                        //toolbar cover div
1216                        var cpos = domGeometry.getMarginBox(this.panelNameHeaders);
1217                        if(!this.panelNameHeadersCover){
1218                                this.panelNameHeadersCover = domConstruct.create("div", {className: "ganttHeaderCover"}, this.panelNameHeaders.parentNode);
1219                                domStyle.set(this.panelNameHeadersCover, {
1220                                        left: cpos.l+"px",
1221                                        top: cpos.t+"px",
1222                                        height: cpos.h+"px",
1223                                        width: cpos.w+"px",
1224                                        display: "none"
1225                                });
1226                        }
1227                },
1228                postBindEvents: function(){
1229                        //highlight row
1230                        var pos = domGeometry.position(this.tableControl, true);
1231                        has("dom-addeventlistener") && this._events.push(
1232                                on(this.tableControl, "mousemove", lang.hitch(this, function(event){
1233                                        var elem = event.srcElement || event.target;
1234                                        if(elem == this.panelNames.firstChild || elem == this.contentData.firstChild){
1235                                                //23: this.heightTaskItem + this.heightTaskItemExtra
1236                                                var rowHeight = this.heightTaskItem + this.heightTaskItemExtra;
1237                                                var hlTop = parseInt(event.layerY / rowHeight) * rowHeight + this.panelTimeHeight - this.contentData.scrollTop;
1238                                                if(hlTop != this.oldHLTop && hlTop < (pos.h - 50)){
1239                                                        if(this.highLightDiv){
1240                                                                domStyle.set(this.highLightDiv, "top", (pos.y + hlTop) + "px");
1241                                                        }else{
1242                                                                this.highLightDiv = domConstruct.create("div", {
1243                                                                        className: "ganttRowHighlight"
1244                                                                }, win.body());
1245                                                                domStyle.set(this.highLightDiv, {
1246                                                                        top: (pos.y + hlTop) + "px",
1247                                                                        left: pos.x + "px",
1248                                                                        width: (pos.w - 20) + "px",
1249                                                                        height: rowHeight + "px"
1250                                                                });
1251                                                        }
1252                                                }
1253                                                this.oldHLTop = hlTop;
1254                                        }
1255                                }))
1256                        );
1257                },
1258                getStartDate: function(){
1259                        arrayUtil.forEach(this.project, function(proj){
1260                                if(this.startDate){
1261                                        if(proj.startDate < this.startDate){
1262                                                this.startDate = new Date(proj.startDate);
1263                                        }
1264                                }else{
1265                                        this.startDate = new Date(proj.startDate);
1266                                }
1267                        }, this);
1268                        this.initialPos = 24 * this.pixelsPerHour;
1269                        return this.startDate ? new Date(this.startDate.setHours(this.startDate.getHours() - 24)) : new Date();
1270                },
1271                getCountDays: function(){
1272                        return parseInt((this.contentWidth - this.maxWidthPanelNames) / (this.pixelsPerHour * 24));
1273                },
1274                createTasks: function(project){
1275                        arrayUtil.forEach(project.project.parentTasks, function(pppTask, i){
1276                                if(i > 0){
1277                                        project.project.parentTasks[i - 1].nextParentTask = pppTask;
1278                                        pppTask.previousParentTask = project.project.parentTasks[i - 1];
1279                                }
1280                                var task = new GanttTaskControl(pppTask, project, this);
1281                                project.arrTasks.push(task);
1282                                task.create();
1283                                this.checkHeighPanelTasks();
1284                                if(pppTask.cldTasks.length > 0){
1285                                        this.createChildItemControls(pppTask.cldTasks, project);
1286                                }
1287                        }, this);
1288                },
1289                createChildItemControls: function(arrChildTasks, project){
1290                        arrChildTasks && arrayUtil.forEach(arrChildTasks, function(cTask, i){
1291                                if(i > 0){
1292                                        cTask.previousChildTask = arrChildTasks[i - 1];
1293                                        arrChildTasks[i - 1].nextChildTask = cTask;
1294                                }
1295                                var task = new GanttTaskControl(cTask, project, this);
1296                                task.create();
1297                                this.checkHeighPanelTasks();
1298                                if(cTask.cldTasks.length > 0){
1299                                        this.createChildItemControls(cTask.cldTasks, project);
1300                                }
1301                        }, this);
1302                },
1303                getPosOnDate: function(startTime){
1304                        return (startTime - this.startDate) / (60 * 60 * 1000) * this.pixelsPerHour;
1305                },
1306                getWidthOnDuration: function(duration){
1307                        return Math.round(this.pixelsPerWorkHour * duration);
1308                },
1309                getLastChildTask: function(task){
1310                        return task.childTask.length > 0 ? this.getLastChildTask(task.childTask[task.childTask.length - 1]) : task;
1311                },
1312                removeCell: function(row){
1313                        while(row.cells[0]){
1314                                row.deleteCell(row.cells[0]);
1315                        }
1316                }
1317        });
1318});
Note: See TracBrowser for help on using the repository browser.