最近几周,公司为了管理项目,要做甘特图,甘特图的插件,要不是很烂,要不是不完善,要不就是收费的,昭来找去,也就dojo的甘特图比较好,但是还是文档奇少,官方文档,给了个
dataFilePath的使用,这里只是写了json的文件名,一句注释,连json数据的格式都没说,不过如果拿到demo后,可以通过函数getJSONData然后转为字符串alert出来,但是把得到字符串放到json文件保存后,还是无法显示json数据,于是继续调试,原来是 loadJSONData:function(filename){ var _this = this; _this.dataFilePath = filename ||_this.dataFilePath; request.get(_this.dataFilePath,{ sync: true }).then(function(response){ _this.loadJSONString( response);//此处原来是respons.text,但是get默认返回的就是text格式的字符串,所以去掉后,即可通过
然后,在原来功能的基础上,公司测试部的老外说,需要加一个审批的功能,即在甘特图中加入的任务,新增的未审批任务需要以红色显示,审批后,才能显示绿色,于是乎,硬着头皮去修改,感谢dojo是开源的,有未压缩的代码。
首先在ganttTaskItem.js中,扩展一个属性: this.isApproval = configuration.isApproval ||"";
然后在tabmenu.js中的buildcontent方法下,加入一句 var taskSucAdd = this.createTab(11, "Add Successor Task", "t",true, this); taskSucAdd.addItem(1, "Id", "id", true); taskSucAdd.addItem(2, "Name", "name"); taskSucAdd.addItem(3, "Start Time", "startTime"); taskSucAdd.addItem(4, "Duration (hours)", "duration"); taskSucAdd.addItem(5, "Percent Complete (%)","percentage"); taskSucAdd.addItem(6, "Task Assignee", "taskOwner"); taskSucAdd.addItem(7, "Is Approval","isApproval"); taskSucAdd.addAction("addSuccessorTaskAction");
得知taskSucAdd是一个contextMenuTab对象,所以需要找到它的addItem方法,并且我们需要的是一个选择框,所以找到dojit的 Select控件,new一个出来 addItem: function(id, name, key, required){ var inputControl; if(key == "startTime" || key == "startDate"){ inputControl = new DateTextBox({type:"text",constraints:{datePattern:"yyyy.M.d", strict:true}}); }else if(key == "percentage"){ inputControl = new NumberSpinner({ constraints:{ max:100,min:0 }}); }else if(key == "duration"){ inputControl = new NumberSpinner({ constraints:{ min:0}}); }else if(key =="isApproval"){ inputControl = new Select({name:"isApproval",options: [ { label: "Yes", value: "yes"}, { label: "No", value: "no", selected:true }]}); }else { inputControl = new TextBox(); } this.arrItems.push({ id: id, name: name, control: inputControl, tab: this, key: key, required: required }); },
在addItem后要执行,taskSucAdd.addAction("addSuccessorTaskAction");,所以还要找到addAction方法,此处没有修改,次方法只是把需要执行的方法名的到,即addSuccessorTaskAction,然后找到addSuccessorTaskAction, addSuccessorTaskAction: function(){ if(!this.preValueValidation(this.arrItems)){ return; } var pr = this.object.project, id = this.arrItems[0].control.textbox.value, name = this.arrItems[1].control.textbox.value, startTime =this.decodeDate(this.arrItems[2].control.textbox.value), duration = this.arrItems[3].control.textbox.value, pc = this.arrItems[4].control.textbox.value, owner = this.arrItems[5].control.textbox.value, isApproval =this.arrItems[6].control.get('value'); if(lang.trim(id).length <= 0){ return; } var parentTaskId = !this.object.parentTask ? "" :this.object.parentTask.taskItem.id; var predTaskId = this.object.taskItem.id; if(pr.insertTask(id, name, startTime,duration, pc, predTaskId, owner, parentTaskId,isApproval)){ this.hide(); }else{ alert("Please adjust your Customization"); return; } this.tabMenu.ganttChart.resource &&this.tabMenu.ganttChart.resource.reConstruct(); },
可以看到,如果要执行成功,还要修改 insertTask方法,在ganttProjectControl.js中找到insertTask方法, insertTask: function(id, name, startTime, duration,percentage, previousTaskId, taskOwner, parentTaskId,isApproval){ var task = null; var _task = null; if(this.project.getTaskById(id)){ return false; } if((!duration) || (duration <this.ganttChart.minWorkLength)){ duration = this.ganttChart.minWorkLength; } if((!name) || (name == "")){ name = id; } if((!percentage) || (percentage == "")){ percentage = 0; }else{ percentage = parseInt(percentage); if(percentage < 0 || percentage > 100){ return false; } } var sortRequired = false; if((parentTaskId) && (parentTaskId != "")){ var parentTask = this.project.getTaskById(parentTaskId); if(!parentTask){ return false; } startTime = startTime || parentTask.startTime; if(startTime < parentTask.startTime){ return false; } task = new GanttTaskItem({ id: id, name: name, startTime: startTime, duration: duration, percentage: percentage, previousTaskId: previousTaskId, taskOwner: taskOwner, isApproval: isApproval }); if(!this.ganttChart.checkPosParentTask(parentTask,task)){ return false; } task.parentTask = parentTask; var _parentTask = this.getTaskById(parentTask.id); var isHide = false; if(_parentTask.cTaskItem[0].style.display == "none"){ isHide = true; }else if(_parentTask.cTaskNameItem[2]){ if(!_parentTask.isExpanded){ isHide = true; } } if(isHide){ if(_parentTask.childTask.length == 0){ this.ganttChart.openTree(_parentTask.parentTask); }else{ this.ganttChart.openTree(_parentTask); } } if(previousTaskId != ""){ var predTask = this.project.getTaskById(previousTaskId); if(!predTask){ return false; } if(predTask.parentTask){ if(predTask.parentTask.id != task.parentTask.id){ return false; } }else{ return false; } if(!this.ganttChart.checkPosPreviousTask(predTask,task)){ this.ganttChart.correctPosPreviousTask(predTask, task); } task.previousTask = predTask; } var isAdd = false; if(sortRequired) for(var i = 0; i <parentTask.cldTasks.length; i++){ if(task.startTime <parentTask.cldTasks[i].startTime){ parentTask.cldTasks.splice(i, 0, task); if(i > 0){ parentTask.cldTasks[i - 1].nextChildTask =parentTask.cldTasks[i]; parentTask.cldTasks[i].previousChildTask =parentTask.cldTasks[i - 1]; } if(parentTask.cldTasks[i + 1]){ parentTask.cldTasks[i + 1].previousChildTask =parentTask.cldTasks[i]; parentTask.cldTasks[i].nextChildTask = parentTask.cldTasks[i +1]; } isAdd = true; break; } } if(!isAdd){ if(parentTask.cldTasks.length > 0){ parentTask.cldTasks[parentTask.cldTasks.length -1].nextChildTask = task; task.previousChildTask =parentTask.cldTasks[parentTask.cldTasks.length - 1]; } parentTask.cldTasks.push(task); } if(parentTask.cldTasks.length == 1){ _parentTask.cTaskNameItem[2] =_parentTask.createTreeImg(); } _task = new GanttTaskControl(task, this,this.ganttChart); _task.create(); if(task.nextChildTask) _task.nextChildTask =_task.project.getTaskById(task.nextChildTask.id); _task.adjustPanelTime(); var rowHeight = this.ganttChart.heightTaskItem +this.ganttChart.heightTaskItemExtra; _task.shiftCurrentTasks(_task, rowHeight);//23 }else{ startTime = startTime || this.project.startDate; task = new GanttTaskItem({ id: id, name: name, startTime: startTime, duration: duration, percentage: percentage, previousTaskId: previousTaskId, taskOwner: taskOwner, isApproval: isApproval }); if(task.startTime <= this.ganttChart.startDate){ return false; } if(previousTaskId != ""){ var predTask = this.project.getTaskById(previousTaskId); if(!predTask){ return false; } if(!this.ganttChart.checkPosPreviousTask(predTask,task)){ this.ganttChart.correctPosPreviousTask(predTask, task); } if(predTask.parentTask){ return false; } task.previousTask = predTask; } var isAdd = false; if(sortRequired){ for(var i = 0; i < this.project.parentTasks.length;i++){ var ppTask = this.project.parentTasks[i]; if(startTime < ppTask.startTime){ this.project.parentTasks.splice(i, 0, task); if(i > 0){ this.project.parentTasks[i - 1].nextParentTask = task; task.previousParentTask = this.project.parentTasks[i -1]; } if(this.project.parentTasks[i + 1]){ this.project.parentTasks[i + 1].previousParentTask =task; task.nextParentTask = this.project.parentTasks[i + 1]; } isAdd = true; break; } } } if(!isAdd){ if(this.project.parentTasks.length > 0){ this.project.parentTasks[this.project.parentTasks.length -1].nextParentTask = task; task.previousParentTask =this.project.parentTasks[this.project.parentTasks.length -1]; } this.project.parentTasks.push(task); } _task = new GanttTaskControl(task, this,this.ganttChart); _task.create(); if(task.nextParentTask) _task.nextParentTask =_task.project.getTaskById(task.nextParentTask.id); _task.adjustPanelTime(); this.arrTasks.push(_task); var rowHeight = this.ganttChart.heightTaskItem +this.ganttChart.heightTaskItemExtra; _task.shiftCurrentTasks(_task, rowHeight); this.projectItem[0].style.display = "inline"; this.setPercentCompleted(this.getPercentCompleted()); this.shiftProjectItem(); this.showDescrProject(); } this.ganttChart.checkHeighPanelTasks(); this.ganttChart.checkPosition(); return _task; },
乱七八糟的一大坨,基本看不懂,应该是一些验证的东西,好在我只是加个属性,不需要验证日期是否过期什么的,所以,加上标红的两句,ok了。在现实对话框的时候,又涉及到了一些赋值操作等一些地方需要小修小补的,代码不贴了,太多。 contextMenuTab.js中新增 reapprovalTaskAction函数,设置修改后的审批值 reapprovalTaskAction: function(){ var isApproval = this.arrItems[0].control.get('value'); //alert('isApproval---'+isApproval); this.object. setIsApproval(isApproval); this.hide(); }, 所以还要一个setIsApproval函数,在ganttTaskControl.js中新增次函数 setIsApproval: function(isApproval){// reapproval function byHu Wei this.taskItem.isApproval = isApproval; //get the percentage node rc0, consult the functionsetPercentCompleted :by Hu Wei var trow =this.cTaskItem[0].childNodes[0].firstChild.rows[0], rc0 = trow.cells[0], rc1 = trow.cells[1]; if(isApproval=='no'){ domClass.replace(rc0.firstChild,"ganttImageTaskProgressFi