source: Dev/trunk/src/client/dojox/gantt/GanttResourceItem.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: 17.9 KB
Line 
1define([
2    "dojo/_base/declare",
3        "dojo/_base/array",
4        "dojo/_base/lang",
5    "dojo/date/locale",
6        "dojo/request",
7        "dojo/on",
8        "dojo/dom",
9        "dojo/dom-class",
10        "dojo/dom-construct",
11        "dojo/dom-style",
12        "dojo/dom-attr",
13        "dojo/dom-geometry",
14        "dojo/keys",
15        "dojo/domReady!"
16], function(declare, arrayUtil, lang, locale, request, on,
17                dom, domClass, domConstruct, domStyle, domAttr, domGeometry, keys){
18        return declare("dojox.gantt.GanttResourceItem", [], {
19                constructor: function(ganttchart){
20                        this.ganttChart = ganttchart;
21                        this.ownerItem = [];
22                        this.ownerNameItem = [];
23                        this.ownerTaskNodeMapping = {};
24                        this.ownerTaskNodeMapping_time = {};
25                        this.resourceInfo = {};
26                        this.ownerTimeConsume = {};
27                },
28                clearAll: function(){
29                        this.clearData();
30                        this.clearItems();
31                },
32                clearData: function(){
33                        this.ownerItem = [];
34                        this.ownerNameItem = [];
35                        this.ownerTaskNodeMapping = {};
36                        this.ownerTaskNodeMapping_time = {};
37                        this.resourceInfo = {};
38                        this.ownerTimeConsume = {};
39                },
40                clearItems: function(){
41                        if(this.content.firstChild){
42                            domConstruct.destroy(this.content.firstChild);
43                        }
44                },
45                buildResource: function(){
46                        var resourceInfo = {};
47                        arrayUtil.forEach(this.ganttChart.arrProjects, function(project){
48                                arrayUtil.forEach(project.arrTasks, function(task){
49                                        task.buildResourceInfo(resourceInfo);
50                                }, this);
51                        }, this);
52                        return resourceInfo;
53                },
54                buildOwnerTimeConsume: function(){
55                        var ownerTimeConsume = {};
56                        for(var owner in this.resourceInfo){
57                                var tasks = this.resourceInfo[owner];
58                                //combine time zone  (startTime - this.startDate) / (60 * 60 * 1000) * this.pixelsPerHour;
59                                var timeZoom = {};
60                                for(var i = 0; i < tasks.length; i++){
61                                        var task = tasks[i];
62                                        var startTime = task.taskItem.startTime.getTime(), dur = task.taskItem.duration * 24 * 60 * 60 * 1000 / this.ganttChart.hsPerDay;
63                                        timeZoom.min = timeZoom.min ? Math.min(timeZoom.min, startTime) : startTime;
64                                        timeZoom.max = timeZoom.max ? Math.max(timeZoom.max, (startTime + dur)) : (startTime + dur);
65                                }
66                                timeZoom.dur = (timeZoom.max - timeZoom.min) * this.ganttChart.hsPerDay / (24 * 60 * 60 * 1000);
67                                timeZoom.min = new Date(timeZoom.min);
68                                timeZoom.max = new Date(timeZoom.max);
69                                ownerTimeConsume[owner] = timeZoom;
70                        }
71                        return ownerTimeConsume;
72                },
73                refresh: function(){
74                        this.ownerTimeConsume = this.buildOwnerTimeConsume();
75                        //resize outer div
76                        this.contentData.firstChild.style.width = Math.max(1200, this.ganttChart.pixelsPerDay * this.ganttChart.totalDays) + "px";
77                        for(var owner in this.resourceInfo){
78                                this.refreshOwnerEntry(owner);
79                        }
80                },
81                reConstruct: function(){
82                        this.clearAll();
83                        this.resourceInfo = this.buildResource();
84                        this.ownerTimeConsume = this.buildOwnerTimeConsume();
85                        this.tableControl = domConstruct.create("table", {
86                                cellPadding: "0",
87                                cellSpacing: "0",
88                                className: "ganttResourceTableControl"
89                        });
90                        var newRowTblControl = this.tableControl.insertRow(this.tableControl.rows.length);
91                        //Add to content Table
92                        this.contentHeight = this.content.offsetHeight;
93                        this.contentWidth = this.content.offsetWidth;
94                        this.content.appendChild(this.tableControl);
95                        //Creation panel contentData
96                        this.contentData = domConstruct.create("div", {className: "ganttResourceContentDataContainer"});
97                        this.contentData.appendChild(this.createPanelOwners());
98                        domStyle.set(this.contentData, "height", (this.contentHeight - this.ganttChart.panelTimeHeight) + "px");
99                        //Creation panel of names
100                        var newCellTblControl = domConstruct.create("td", {
101                                vAlign: "top"
102                        });
103                        this.panelNames = domConstruct.create("div", {className: "ganttResourcePanelNames"});
104                        this.panelNames.appendChild(this.createPanelNamesOwners());
105                        newCellTblControl.appendChild(this.panelNames);
106                        newRowTblControl.appendChild(newCellTblControl);
107                        //add to control contentData and contentDataTime
108                        newCellTblControl = domConstruct.create("td", {
109                                vAlign: "top"
110                        });
111                        var divCell = domConstruct.create("div", {className: "ganttResourceDivCell"});
112                        divCell.appendChild(this.contentData);
113                        newCellTblControl.appendChild(divCell);
114                        newRowTblControl.appendChild(newCellTblControl);
115                        //Show panel of names
116                        domStyle.set(this.panelNames, {
117                                height: (this.contentHeight - this.ganttChart.panelTimeHeight - this.ganttChart.scrollBarWidth) + "px",
118                                width: this.ganttChart.maxWidthPanelNames + "px"
119                        });
120                        this.contentData.style.width = (this.contentWidth - this.ganttChart.maxWidthPanelNames) + "px";
121                        this.contentData.firstChild.style.width = this.ganttChart.pixelsPerDay * (this.ganttChart.panelTime.firstChild.firstChild.rows[3].cells.length) + "px";
122                        var _this = this;
123                        this.contentData.onscroll = function(){
124                                if(_this.panelNames){
125                                        _this.panelNames.scrollTop = this.scrollTop;
126                                }
127                        };
128                        this.contentData.scrollLeft = this.ganttChart.contentData.scrollLeft;
129                        for(var owner in this.resourceInfo){
130                                this.createOwnerEntry(owner);
131                        }
132                        this.postAdjustment();
133                },
134                create: function(){
135                        var resourceHeader = domConstruct.create("div", {
136                                innerHTML: "Resource Chart:",
137                                className: "ganttResourceHeader"
138                        }, this.ganttChart.content, "after");
139                        domStyle.set(resourceHeader, "width", this.ganttChart.contentWidth + "px");
140                        var content = domConstruct.create("div", {className: "ganttResourceContent"}, resourceHeader, "after");
141                        domStyle.set(content, {
142                                width: this.ganttChart.contentWidth + "px",
143                                height: (this.ganttChart.resourceChartHeight || (this.ganttChart.contentHeight * 0.8)) + "px"
144                        });
145                        this.content = content || this.content;
146                        //create Table
147                        this.reConstruct();
148                },
149                postAdjustment: function(){
150                        //contentData height
151                        this.contentData.firstChild.style.height = (this.ownerItem.length * 23) + "px";
152                        this.panelNames.firstChild.style.height = (this.ownerItem.length * 23) + "px";
153                },
154       
155                refreshOwnerEntry: function(owner){
156                        this.refreshOwnerItem(owner);
157                        arrayUtil.forEach(this.resourceInfo[owner], function(task, i){
158                                var item = this.ownerTaskNodeMapping[owner].tasks[i][0];
159                                this.refreshDetailedTaskEntry(owner, item, task);
160                        }, this);
161                },
162                createOwnerEntry: function(owner){
163                        var containerOwner = this.contentData.firstChild;
164                        var previousOwner = this.ownerItem[this.ownerItem.length - 1];
165                        this.ownerTaskNodeMapping[owner] = {};
166                        this.ownerTaskNodeMapping[owner][owner] = [];
167                        //creation arrTasks
168                        var posY = (previousOwner ? parseInt(previousOwner.style.top) : (6 - 23)) + this.ganttChart.heightTaskItem + 11;
169                        //creation task item
170                        var oItem = this.createOwnerItem(owner, posY);
171                        containerOwner.appendChild(oItem);
172                        this.ownerItem.push(oItem);
173                        this.ownerTaskNodeMapping[owner][owner].push(oItem);
174                        if(this.panelNames){
175                                var oNameItem = this.createOwnerNameItem(owner, posY);
176                                this.panelNames.firstChild.appendChild(oNameItem);
177                                this.ownerNameItem.push(oNameItem);
178                                this.ownerTaskNodeMapping[owner][owner].push(oNameItem);
179                        }
180                        var currentOwnerNameNode = this.ownerNameItem[this.ownerNameItem.length - 1];
181                        //adjust nodes
182                        if(this.panelNames){
183                                this.checkWidthTaskNameItem(currentOwnerNameNode);
184                                var treeImg = this.createTreeImg(currentOwnerNameNode);
185                                this.panelNames.firstChild.appendChild(treeImg);
186                                this.ownerTaskNodeMapping[owner][owner].push(treeImg);
187                        }
188                        this.ownerTaskNodeMapping[owner]["taskCount"] = this.resourceInfo[owner].length;
189                        this.ownerTaskNodeMapping[owner]["isOpen"] = false;
190                        this.ownerTaskNodeMapping[owner]["tasks"] = [];
191                        arrayUtil.forEach(this.resourceInfo[owner], function(task){
192                                this.ownerTaskNodeMapping[owner]["tasks"].push(this.createDetailedTaskEntry(owner, currentOwnerNameNode, task));
193                        }, this);
194                        return this;
195                },
196                createOwnerNameItem: function(owner, posY){
197                        var ownerName = domConstruct.create("div", {
198                                id: owner,
199                                title: owner,
200                                innerHTML: owner,
201                                className: "ganttOwnerNameItem"
202                        });
203                        domStyle.set(ownerName, "top", posY + "px");
204                        return ownerName;
205                },
206                refreshOwnerItem: function(owner){
207                        var item = this.ownerTaskNodeMapping[owner][owner][0],
208                                start = this.ownerTimeConsume[owner].min, dur = this.ownerTimeConsume[owner].dur,
209                                posX = this.ganttChart.getPosOnDate(start); // should be task start date
210                        item.style.left = posX + "px";
211                        item.style.width = dur * this.ganttChart.pixelsPerWorkHour + "px";
212                        arrayUtil.forEach(this.resourceInfo[owner], function(task, i){
213                                var tposX = this.ganttChart.getPosOnDate(task.taskItem.startTime); // should be task start date
214                                domStyle.set(item.childNodes[i], {
215                                        left: (tposX - posX) + "px",
216                                        width: task.taskItem.duration * this.ganttChart.pixelsPerWorkHour + "px"
217                                });
218                        }, this);
219                },
220                createOwnerItem: function(owner, posY){
221                        var start = this.ownerTimeConsume[owner].min, dur = this.ownerTimeConsume[owner].dur;
222                        var posX = this.ganttChart.getPosOnDate(start); // should be task start date
223                        var ownerControl = domConstruct.create("div", {
224                                id: owner,
225                                owner: true,
226                                className: "ganttOwnerBar"
227                        });
228                        domStyle.set(ownerControl, {
229                                left: posX + "px",
230                                top: posY + "px",
231                                width: dur * this.ganttChart.pixelsPerWorkHour + "px",
232                                height: this.ganttChart.heightTaskItem + "px"
233                        });
234                        arrayUtil.forEach(this.resourceInfo[owner], function(task){
235                                var ownerTaskItem = domConstruct.create("div", {
236                                        id: owner,
237                                        className: "ganttOwnerTaskBar"
238                                }, ownerControl);
239                                var tposX = this.ganttChart.getPosOnDate(task.taskItem.startTime); // should be task start date
240                                domStyle.set(ownerTaskItem, {
241                                        left: (tposX - posX) + "px",
242                                        width: task.taskItem.duration * this.ganttChart.pixelsPerWorkHour + "px", // should be task duration
243                                        height: this.ganttChart.heightTaskItem + "px"
244                                });
245                        }, this);
246                        return ownerControl;
247                },
248                refreshDetailedTaskEntry: function(owner, item, task){
249                        this.refreshTaskItem(item, task);
250                },
251                createDetailedTaskEntry: function(owner, parentNode, task){
252                        var taskItems = [];
253                        var containerTasks = this.contentData.firstChild;
254                        var posY = parseInt(parentNode.style.top);
255               
256                        //creation task item
257                        var taskItem = this.createTaskItem(task, posY);
258                        taskItem.style.display = "none";
259                        containerTasks.appendChild(taskItem);
260                        this.ownerItem.push(taskItem);
261                        taskItems.push(taskItem);
262                        if(this.panelNames){
263                                var taskNameItem = this.createTaskNameItem(task.taskItem.name, posY);
264                                this.panelNames.firstChild.appendChild(taskNameItem);
265                                taskNameItem.style.display = "none";
266                                this.ownerNameItem.push(taskNameItem);
267                                taskItems.push(taskNameItem);
268                        }
269                        if(this.panelNames){
270                                this.ownerNameItem[this.ownerNameItem.length - 1].style.left = domStyle.get(parentNode, "left") + 15 + "px";
271                                var arrConnectingLinesNames = this.createConnectingLinesPN(parentNode, this.ownerNameItem[this.ownerNameItem.length - 1]);
272                                arrayUtil.forEach(arrConnectingLinesNames, function(lineName){
273                                        lineName.style.display = "none";
274                                }, this);
275                                taskItems.push({
276                                        "v": arrConnectingLinesNames[0],
277                                        "h": arrConnectingLinesNames[1]
278                                });
279                                this.checkWidthTaskNameItem(this.ownerNameItem[this.ownerNameItem.length - 1]);
280                        }
281                        return taskItems;
282                },
283                createTaskNameItem: function(owner, posY){
284                        var taskNameItem = domConstruct.create("div", {
285                                id: owner,
286                                className: "ganttTaskNameItem",
287                                title: owner,
288                                innerHTML: owner
289                        });
290                        domStyle.set(taskNameItem, "top", posY + "px");
291                        return taskNameItem;
292                },
293                refreshTaskItem: function(item, task){
294                        var posX = this.ganttChart.getPosOnDate(task.taskItem.startTime); // should be task start date
295                        domStyle.set(item, {
296                                left: posX + "px",
297                                width: task.taskItem.duration * this.ganttChart.pixelsPerWorkHour + "px"
298                        });
299                },
300                createTaskItem: function(task, posY){
301                        var posX = this.ganttChart.getPosOnDate(task.taskItem.startTime); // should be task start date
302                        var itemControl = domConstruct.create("div", {
303                                id: task.taskItem.name,
304                                className: "ganttTaskBar"
305                        });
306                        domStyle.set(itemControl, {
307                                left: posX + "px",
308                                top: posY + "px",
309                                width: task.taskItem.duration * this.ganttChart.pixelsPerWorkHour + "px",
310                                height: this.ganttChart.heightTaskItem + "px"
311                        });
312                        return itemControl;
313                },
314                createConnectingLinesPN: function(parentNode, currentNode){
315                        var arrConnectingLinesNames = [];
316                        var lineVerticalLeft = domConstruct.create("div", {
317                                innerHTML: "&nbsp;",
318                                className: "ganttResourceLineVerticalLeft"
319                        }, this.panelNames.firstChild);
320                        lineVerticalLeft.cNode = currentNode;
321                        lineVerticalLeft.pNode = parentNode;
322                        var LineHorizontalLeft = domConstruct.create("div", {
323                                noShade: true,
324                                color: "#000",
325                                className: "ganttResourceLineHorizontalLeft"
326                        }, this.panelNames.firstChild);
327                        LineHorizontalLeft.cNode = currentNode;
328                        LineHorizontalLeft.pNode = parentNode;
329                        this.panelNames.firstChild.appendChild(LineHorizontalLeft);
330                        arrConnectingLinesNames.push(lineVerticalLeft);
331                        arrConnectingLinesNames.push(LineHorizontalLeft);
332                        return arrConnectingLinesNames;
333                },
334                createTreeImg: function(ownerNameItem){
335                        var treeImg = domConstruct.create("div", {
336                                id: ownerNameItem.id,
337                                className: "ganttImageTreeExpand"
338                        });
339                        domAttr.set(treeImg, "tabIndex", 0);
340                        var currentItem = this.ownerTaskNodeMapping[ownerNameItem.id];
341                        arrayUtil.forEach(["click", "keydown"], function(e){
342                                this.ganttChart._events.push(
343                                        on(treeImg, e, lang.hitch(this, function(evt){
344                                                var reachTarget = false, owner, ownerItem;
345                                                if(e == "keydown" && evt.keyCode != keys.ENTER){ return; }
346                                                //TODO: perhaps the following conditional can be collapsed?  Duplicate code.
347                                                if(currentItem.isOpen){
348                                                        domClass.remove(treeImg, "ganttImageTreeCollapse");
349                                                        domClass.add(treeImg, "ganttImageTreeExpand");
350                                                        currentItem.isOpen = false;
351                                                        //collapse
352                                                        for(owner in this.ownerTaskNodeMapping){
353                                                                ownerItem = this.ownerTaskNodeMapping[owner];
354                                                                if(reachTarget){
355                                                                        arrayUtil.forEach(ownerItem[owner], function(tItem){
356                                                                                domStyle.set(tItem, "top", domStyle.get(tItem, "top") - currentItem.taskCount * 23 + "px");
357                                                                        });
358                                                                        arrayUtil.forEach(ownerItem.tasks, function(tItems){
359                                                                                arrayUtil.forEach(tItems, function(tItem){
360                                                                                        var item = !tItem.v && !tItem.h ? [tItem] : [tItem.v, tItem.h];
361                                                                                        arrayUtil.forEach(item, function(t){
362                                                                                                domStyle.set(t, "top", domStyle.get(t, "top") - currentItem.taskCount * 23 + "px");
363                                                                                        });
364                                                                                });
365                                                                        });
366                                                                }else{
367                                                                        if(owner == ownerNameItem.id){
368                                                                                reachTarget = true;
369                                                                                arrayUtil.forEach(ownerItem.tasks, function(tItems){
370                                                                                        arrayUtil.forEach(tItems, function(tItem){
371                                                                                                this.styleOwnerItem(tItem, ownerItem[owner][0], "none", 0);
372                                                                                        }, this);
373                                                                                }, this);
374                                                                        }
375                                                                }
376                                                        }
377                                                }else{
378                                                        domClass.remove(treeImg, "ganttImageTreeExpand");
379                                                        domClass.add(treeImg, "ganttImageTreeCollapse");
380                                                        currentItem.isOpen = true;
381                                                        //expand
382                                                        for(owner in this.ownerTaskNodeMapping){
383                                                                ownerItem = this.ownerTaskNodeMapping[owner];
384                                                                if(reachTarget){
385                                                                        arrayUtil.forEach(ownerItem[owner], function(tItem){
386                                                                                domStyle.set(tItem, "top", domStyle.get(tItem, "top") + currentItem.taskCount * 23 + "px");
387                                                                        });
388                                                                        arrayUtil.forEach(ownerItem.tasks, function(tItems){
389                                                                                arrayUtil.forEach(tItems, function(tItem){
390                                                                                        var item = !tItem.v && !tItem.h ? [tItem] : [tItem.v, tItem.h];
391                                                                                        arrayUtil.forEach(item, function(t){
392                                                                                                domStyle.set(t, "top", domStyle.get(t, "top") + currentItem.taskCount * 23 + "px");
393                                                                                        });
394                                                                                });
395                                                                        });
396                                                                }else{
397                                                                        if(owner == ownerNameItem.id){
398                                                                                reachTarget = true;
399                                                                                arrayUtil.forEach(ownerItem.tasks, function(tItems, i){
400                                                                                        arrayUtil.forEach(tItems, function(tItem){
401                                                                                                this.styleOwnerItem(tItem, ownerItem[owner][0], "inline", (i + 1) * 23);
402                                                                                        }, this);
403                                                                                }, this);
404                                                                        }
405                                                                }
406                                                        }
407                                                }
408                                        }))
409                                );
410                        }, this);
411                        domClass.add(treeImg, "ganttResourceTreeImage");
412                        domStyle.set(treeImg, {
413                                left: (domStyle.get(ownerNameItem, "left") - 12) + "px",
414                                top: (domStyle.get(ownerNameItem, "top") + 3) + "px"
415                        });
416                        return treeImg;
417                },
418                styleOwnerItem: function(tItem, owner, displayType, topOffset){
419                        if(tItem.v || tItem.h){
420                                domStyle.set(tItem.v, {
421                                        height: Math.max(1, (tItem.v.cNode.offsetTop - tItem.v.pNode.offsetTop)) + "px",
422                                        top: (tItem.v.pNode.offsetTop + 5) + "px",
423                                        left: (tItem.v.pNode.offsetLeft - 9) + "px",
424                                        display: displayType
425                                });
426                                domStyle.set(tItem.h, {
427                                        width: Math.max(1, (tItem.h.cNode.offsetLeft - tItem.h.pNode.offsetLeft + 4)) + "px",
428                                        top: (tItem.h.cNode.offsetTop + 5) + "px",
429                                        left: (tItem.h.pNode.offsetLeft - 9) + "px",
430                                        display: displayType
431                                });
432                        }else{
433                                domStyle.set(tItem, {
434                                        display: displayType,
435                                        top: parseInt(owner.style.top) + topOffset + "px"
436                                });
437                        }
438                },
439                checkWidthTaskNameItem: function(taskNameItem){
440                        if(taskNameItem && taskNameItem.offsetWidth + taskNameItem.offsetLeft > this.ganttChart.maxWidthPanelNames){
441                                var width = taskNameItem.offsetWidth + taskNameItem.offsetLeft - this.ganttChart.maxWidthPanelNames,
442                                        countChar = Math.round(width / (taskNameItem.offsetWidth / taskNameItem.firstChild.length)),
443                                        tName = taskNameItem.id.substring(0, taskNameItem.firstChild.length - countChar - 3);
444                                taskNameItem.innerHTML = tName + "...";
445                        }
446                },
447                createPanelOwners: function(){
448                        var panelOwner = domConstruct.create("div", {
449                                className: "ganttOwnerPanel"
450                        });
451                        domStyle.set(panelOwner, {
452                                height: (this.contentHeight - this.ganttChart.panelTimeHeight - this.ganttChart.scrollBarWidth) + "px"
453                        });
454                        return panelOwner;
455                },
456                createPanelNamesOwners: function(){
457                        var panelNameOwner = domConstruct.create("div", {
458                                innerHTML: "&nbsp;",
459                                className: "ganttResourcePanelNamesOwners"
460                        });
461                        domStyle.set(panelNameOwner, {
462                                height: (this.contentHeight - this.ganttChart.panelTimeHeight - this.ganttChart.scrollBarWidth) + "px",
463                                width: this.ganttChart.maxWidthPanelNames + "px"
464                        });
465                        return panelNameOwner;
466                }
467        });
468});
Note: See TracBrowser for help on using the repository browser.