var dayMS = 86400000; var popTitle = "Add/Edit Task"; // To be set by template vars var dunits, hoursPerDay, taskLength; var extrasPath, errorMsgs; var taskArray; function doCalendar (fieldId) { Calendar.setup({ inputField : fieldId, ifFormat : "%Y-%m-%d", showsTime : false, step : 1, timeFormat : "12", firstDay : false }); } //-------------------------------------------------------------------------------------- function buildMenuUrl (urltype,taskId) { if(urltype == "edit") { alert("edit task: "+taskId); } else if(urltype == "insertAbove") { alert("insert task above: "+taskId); } else if(urltype == "insertBelow") { alert("insert task below: "+taskId); } else if(urltype == "delete") { alert("delete task: "+taskId); } } //-------------------------------------------------------------------------------------- function closeImage() { return extrasPath + '/close.gif'; } //-------------------------------------------------------------------------------------- function configureMilestone(box) { var form = box.form; if(box.checked==true) { form.end.value=form.start.value; form.duration.value=0; form.duration.disabled=true; form.lagTime.value=0; form.lagTime.disabled=true; form.end.disabled=true; form.dependants.disabled=true; form.resource.disabled=true; form.percentComplete.disabled=true; form.percentComplete.value=0; } else { form.end.disabled=false; form.duration.disabled=false; form.lagTime.disabled=false; form.dependants.disabled=false; form.resource.disabled=false; form.percentComplete.disabled=false; form.duration.value = (dunits == "hrs")?hoursPerDay:1; } } //-------------------------------------------------------------------------------------- function checkEditTaskForm (form) { if(form.name.value == "") { alert(errorMsgs.name); return; } else if(form.start.value == "") { alert(errorMsgs.start); return; } else if(form.milestone.checked==false && form.end.value == "") { alert(errorMsgs.end); return; } form.submit(); } //-------------------------------------------------------------------------------------- function intlDate(dateObj) { return dateObj.getFullYear()+"-"+pad((dateObj.getMonth()+1))+"-"+pad(dateObj.getDate()); } //-------------------------------------------------------------------------------------- function toDateObj(date) { var to = date.split("-"); var dateObj = new Date(to[0],(to[1]-1),to[2],0,0,1,0); return dateObj; } //-------------------------------------------------------------------------------------- function adjustTaskTimeFromDuration(start, end, duration, lagTime, isTaskForm, predecessor, origStart, origEnd, seqNum) { //set the form element var form = duration.form; //get today's date var today = new Date(); var todayIntl = intlDate(today); //set start and end date if not already set if(start.value == "") start.value = todayIntl; if(end.value == "") end.value = todayIntl; //Convert hours to days var taskDuration = parseFloat(duration.value); var taskTotalDuration = taskDuration + parseFloat(lagTime.value); if(dunits == "hrs") taskTotalDuration = taskTotalDuration / hoursPerDay; var totalDurationFloor = Math.floor(taskTotalDuration); //Handle task form and main form seperately due to differences in the forms if(isTaskForm && taskDuration <= 0) { //Convert to milestone if task is less or equal to zero if(confirm("Zero duration tasks are considered Milestones. Do you wish to change this task to a milestone?")) { form.milestone.checked = true; configureMilestone(form.milestone); } else { duration.value = form.orig_duration.value; } return; } else if (taskDuration <= 0){ //Do not let users zero out tasks alert("Zero duration tasks are considered Milestones. Please edit the task by clicking the link if you wish to change this task to a milestone"); return; } //create the start date var aTo = start.value.split("-"); var toDate = new Date(aTo[0],(aTo[1]-1),aTo[2],0,0,1,0); //add new duration days to the start date toDate.setDate(toDate.getDate() + totalDurationFloor); //set end date to this date end.value = intlDate(toDate); //Set new duration in taskArray taskArray[seqNum]["duration"] = taskDuration; //Adjust time based on new end date adjustTaskTimeFromDate(start, end, duration, lagTime, end, isTaskForm, predecessor, origStart, origEnd, seqNum); } //-------------------------------------------------------------------------------------- function adjustTaskTimeFromDate (start, end, duration, lagTime, element, isTaskForm, predecessor, origStart, origEnd, seqNum) { //set the form element var form = element.form; //set original duration from task form to determine whether or not to continue to set duration var orig_duration; if(isTaskForm) { if(form.milestone.checked == true) return; orig_duration = form.orig_duration.value; } //Handle case where both start and end are empty if(start.value == "" && end.value == "") { //get today's date var today = new Date(); var todayIntl = intlDate(today); //set start and end date if not already set start.value = todayIntl; end.value = todayIntl; } //Handle case where one is set and the other isn't if (end.value == "") end.value = start.value; if(start.value == "") start.value = end.value; if(isTaskForm && orig_duration == "") { //Set duration if this is a new record //Check to make sure start date comes before end date var startcomp = start.value.replace(/-/g,""); var endcomp = end.value.replace(/-/g,""); if(startcomp > endcomp) { alert(errorMsgs.greaterthan); if(element.name == "start") { end.value = element.value; } else { start.value = element.value; } duration.value = (dunits == "hrs")?hoursPerDay:1; lagTime.value = 0; return; } var d = getDaysInterval(start.value,end.value); if(d == 0) d = 1; if(dunits == "hrs") { d = d * hoursPerDay; } duration.value = d - lagTime.value; } else { //Set start/end if duration has been saved var d = parseFloat(duration.value) + parseFloat(lagTime.value); if(dunits == "hrs") { //Convert to days d = d / hoursPerDay; } //Round off duration or set it to zero if less than 1; //alert("d = " + d + " floor = " + Math.floor(d)); if(d < 1) d = 0; else d = Math.floor(d); if(element.name.indexOf("start") > -1) { //create the date var aTo = start.value.split("-"); var toDate = new Date(aTo[0],(aTo[1]-1),aTo[2],0,0,1,0); //add duration days to the start date toDate.setDate(toDate.getDate() + d); //set end date to this date end.value = intlDate(toDate); } else if(element.name.indexOf("end") > -1) { //create the date var aFrom = end.value.split("-"); var fromDate = new Date(aFrom[0],(aFrom[1]-1),aFrom[2],0,0,1,0); //subtract duration days from the end date fromDate.setDate(fromDate.getDate() - d); //set start date to this date start.value = intlDate(fromDate); } } //Check Predecessors before moving stuff var pred = predecessor.value; if(pred != "") { //Check to make sure that the dependency requirement for this task is still valid //Get the predecessor end date var taskStart = toDateObj(start.value); var predTaskEnd; if(isTaskForm) { predTaskEnd = toDateObj(taskArray[pred]["end"]); } else { var predTaskEndId = "end_"+taskArray[pred]["id"]+"_formId" predTaskEnd = toDateObj(document.getElementById(predTaskEndId).value); } if(taskStart.getTime() < predTaskEnd.getTime()) { alert(errorMsgs.invalidMove); start.value = origStart.value; end.value = origEnd.value; return; } } //Check all tasks past this one and move them forward if necessary (this only needs to happen on the main form) if(!isTaskForm) { arrangePredecessors(element,seqNum); } //reset orig start and end values origStart.value = start.value; origEnd.value = end.value; if(!isTaskForm) { //Adjust task form for paintGanttChart(); } } //-------------------------------------------------------------------------------------- function trim(str) { return str.replace(/^\s+|\s+$/, ''); } //-------------------------------------------------------------------------------------- function arrangePredecessors (element,seqNum) { for (var i = 1; i <= taskLength; i++) { var seq = i; var task = taskArray[seq]; var taskId = task["id"]; //Calculate duration and duraiton floor var totalDurationInDays = parseFloat(task["duration"]) + parseFloat(task["lagTime"]); if(dunits == "hrs") totalDurationInDays = totalDurationInDays / hoursPerDay; var totalDurationFloor = Math.floor(totalDurationInDays); //alert("Duration Floor is: "+durationFloor); //Get the current elements var currElementStart = document.getElementById("start_"+taskId+"_formId"); var currElementEnd = document.getElementById("end_"+taskId+"_formId"); //alert("Current Start Date: "+currElementStart.value+" Current End Date: "+currElementEnd.value); //Skip the first record as it is the record that was changed if(seq > 1) { var predecessor = task["predecessor"]; //alert("predecessor for "+i+" is "+predecessor); if(predecessor != "") { var pred = taskArray[predecessor]; var predEndDate = toDateObj(pred["end"]); var startDate = toDateObj(task["start"]); //alert ("Pred End Date: "+intlDate(predEndDate)); //Make sure start date of this task is greater than the end date of the predecessor if(startDate.getTime() <= predEndDate.getTime()) { //Change the start and end dates of the task //Get the day part of the predecessor var predDayPart = parseFloat(pred["dayPart"]); //alert("predDayPart: "+predDayPart); if(predDayPart > 0) { //The previous task took up part of a day. Add the additional day part to the duration totalDurationInDays += predDayPart; totalDurationFloor = Math.floor(totalDurationInDays); } //alert("Duration in Days: "+durationInDays+" Duration Floor: "+durationFloor); //Set the start date of this task to the end date of the predecessor currElementStart.value = pred["end"]; //Adjust end date for change in start date and update the object - start date is actually predEndDate now, so use the existing date object predEndDate.setDate(predEndDate.getDate() + totalDurationFloor); currElementEnd.value = intlDate(predEndDate); //alert("Set seq "+i+" to start: "+pred["end"]+" end: "+intlDate(predEndDate)); } } } //Update task array with new start/end values taskArray[seq]["start"] = currElementStart.value; taskArray[seq]["end"] = currElementEnd.value; taskArray[seq]["dayPart"] = (totalDurationInDays - Math.floor(totalDurationInDays)); } } //-------------------------------------------------------------------------------------- function getDaysInterval(from,to) { var aFrom = from.split("-"); var aTo = to.split("-"); var fromDate = new Date(aFrom[0],(aFrom[1]-1),aFrom[2],0,0,1,0); var toDate = new Date(aTo[0],(aTo[1]-1),aTo[2],0,0,1,0); var fromEpoch = fromDate.getTime(); var toEpoch = toDate.getTime(); var seconds = toEpoch - fromEpoch; if(seconds == 0) return 0; return (seconds/dayMS); } //-------------------------------------------------------------------------------------- function pad(date) { var str = ""+date; if(str.length == 1) { str = "0"+str; } return str; } //-------------------------------------------------------------------------------------- function paintGanttChart () { var status = AjaxRequest.submit(document.forms['editAll'],{ 'onSuccess':function(req){ document.getElementById('gantt').innerHTML = req.responseText; } }); var mwidth = document.getElementById("projectTableWidth").name + "px"; var swidth = document.getElementById("projectScrollPercentWidth").name + "%"; document.getElementById("mastertable").style.width=mwidth; document.getElementById("scrolltd").style.width=swidth; } //-------------------------------------------------------------------------------------- function validateDependant(field,origField,seqNum,start,end,duration,lagTime,isTaskForm,origStart,origEnd) { var pred = field.value; var newTask = false; if(pred != "") { if(seqNum == "") seqNum = taskLength+1; if(pred < 1) { alert(errorMsgs.noPredecessor); field.value=origField.value; return; } if(pred == seqNum) { alert(errorMsgs.samePredecessor); field.value=origField.value; return; } if(pred > seqNum) { alert(errorMsgs.previousPredecessor); field.value = origField.value; return; } //Set defaults if it's a new record and one of the other options hasn't been checked. if(start.value == "" || end.value == "") { //get today's date newTask = true; duration.value = (dunits == "hrs")?hoursPerDay:1; } //Get the predecessor end date and decide where the new start date belongs var taskStart = start.value; var taskStartObj = toDateObj(taskStart); var predTaskEnd = taskArray[pred]["end"]; var predTaskEndObj = toDateObj(predTaskEnd); //Change start date if it comes before predecessor end date if(newTask || (taskStartObj.getTime() < predTaskEndObj.getTime())) { //Convert predecessor hours to days var taskTotalDuration = parseFloat(duration.value) + parseFloat(lagTime.value); if(dunits == "hrs") taskTotalDuration = taskTotalDuration / hoursPerDay; var totalDurationFloor = Math.floor(taskTotalDuration); //Get the predecessor dayPart var predDayPart = parseFloat(pred["dayPart"]); if(predDayPart > 0) { //The previous task took up part of a day. Add the additional day part to the duration taskTotalDuration += predDayPart; totalDurationFloor = Math.floor(totalDurationInDays); } //Set the start date of this task to the end date of the predecessor start.value = predTaskEnd; //Adjust end date for change in start date adjustTaskTimeFromDate(start,end,duration,lagTime,start,isTaskForm,field,origStart,origEnd,seqNum); return; } } //Repaint if(!isTaskForm) { //Set new predecessor in taskArray taskArray[seqNum]["predecessor"] = pred; paintGanttChart(); } }