#ProjectManagerTMPL0002
#title:Default Project Display
#menuTitle:Default Project Display
#url:default-pm-template-project-display
#namespace:ProjectManager_project
#create
<script type="text/javascript" src="<tmpl_var extras.base>/js/at/AjaxRequest.js"></script>
<script type="text/javascript" src="<tmpl_var extras.base>/js/modal/modal.js"></script>

<script src="<tmpl_var extras.base>/calendar/calendar.js" type="text/javascript"></script>
<script src="<tmpl_var extras.base>/contextMenu/contextMenu.js" type="text/javascript"></script>
<script src="<tmpl_var extras.base>/calendar/lang/calendar-en.js" type="text/javascript"></script>
<script src="<tmpl_var extras.base>/calendar/calendar-setup.js" type="text/javascript"></script>

<script type="text/javascript">
    var dayMS = 86400000;
	
	var popTitle = "Add/Edit Task";
	
	var dunits = "<tmpl_var project.durationUnits>";
	var hoursPerDay = <tmpl_var project.hoursPerDay>;
	var taskLength=<tmpl_var project.task.length>;
	
   //--------------------------------------------------------------------------------------	
	function doCalendar (fieldId) {
	   Calendar.setup({ 
                         inputField : fieldId, 
                         ifFormat : "%Y-%m-%d", 
                         showsTime : false, 
                         step : 1,
                         timeFormat : "12",
                         firstDay : false
                    }); 
    }
	
   //--------------------------------------------------------------------------------------	
	function closeImage() {
       return '<tmpl_var extras>/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.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.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("<tmpl_var form.name.error>");
		  return;
	   } else if(form.start.value == "") {
	      alert("<tmpl_var form.start.error>");
		  return;
	   } else if(form.milestone.checked==false && form.end.value == "") {
	      alert("<tmpl_var form.end.error>");
		  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, 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 predecessor hours to days
	   var taskDuration = duration.value;
	   if(dunits == "hrs") taskDuration = taskDuration / hoursPerDay;
	   var durationFloor = Math.floor(taskDuration);
	   
	   //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() + durationFloor);
			  
	   //set end date to this date
	   end.value = intlDate(toDate);
	   
	   //Set new duration in taskArray
	   taskArray[seqNum]["duration"] = duration.value;
	   //Adjust time based on new end date
	   adjustTaskTimeFromDate(start, end, duration, end, isTaskForm, predecessor, origStart, origEnd, seqNum);
	}
	
   //--------------------------------------------------------------------------------------	
	function adjustTaskTimeFromDate (start, end, duration, 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;
	   }
	   
	   if (end.value == "") end.value = start.value;
	   else 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("<tmpl_var form.greaterthan.error>");
		     if(element.name == "start") {
		        end.value = element.value;
		     } else {
		        start.value = element.value;
		     }
		     duration.value = (dunits == "hrs")?hoursPerDay:1;
		     return;
	      }
	   
	      var d = getDaysInterval(start.value,end.value);
		  if(d == 0) d = 1;
	      if(dunits == "hrs") {
	         d = d * hoursPerDay;
	      }
	      duration.value = d;
	   } else {
	      //Set start/end if duration has been saved
		  var d = duration.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("<tmpl_var form.invalidMove.error>");
			 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 durationInDays = parseFloat(task["duration"]);
		 if(dunits == "hrs") durationInDays = durationInDays / hoursPerDay;
		 var durationFloor = Math.floor(durationInDays);
		 //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
					 durationInDays += predDayPart;
					 durationFloor = Math.floor(durationInDays);
				  }
				  //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() + durationFloor);
				  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"] = (durationInDays - Math.floor(durationInDays));
	  }
   }
	
   //--------------------------------------------------------------------------------------	
	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,isTaskForm,origStart,origEnd) {
	   var pred = field.value;
	   var newTask = false;
	   if(pred != "") {
	      if(seqNum == "") seqNum = taskLenth+1;
		  if(pred < 1) {
	         alert("<tmpl_var form.noPredecessor.error>");
		     field.value=origField.value;
		     return;
	      }
	      if(pred == seqNum) {
	         alert("<tmpl_var form.samePredecessor.error>");
		     field.value=origField.value;
		     return;
	      }
	      if(pred > seqNum) {
	         alert("<tmpl_var form.previousPredecessor.error>");
		     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 taskDuration = duration.value;
			 if(dunits == "hrs") taskDuration = taskDuration / hoursPerDay;
			 var durationFloor = Math.floor(taskDuration);
			 
			 //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
			    taskDuration += predDayPart;
				durationFloor = Math.floor(durationInDays);
			 }
	         
			 //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,start,isTaskForm,field,origStart,origEnd,seqNum);
			 return;
		  }
	   }
	   
	   //Set new predecessor in taskArray
	   taskArray[seqNum]["predecessor"] = pred;
	   
	   //Repaint
	   if(!isTaskForm) {
	      paintGanttChart();
	   }
	}
   
    addEvent(window, "load", initPopUp);
</script>
<tmpl_var form.header>
<table cellpadding="0" cellspacing="0" border="0" class="project" id="mastertable" style="width:<tmpl_var project.table.width>px;">
<tr>
	<td style="width:20px;height:20px;">&nbsp;</td>
	<td style="width:300px;" align="center">Task Name</td>
	<td style="width:70px;" align="center">Duration</td>
	<td style="width:70px;" align="center">Start</td>
	<td style="width:70px;" align="center">Finish</td>
	<td style="width:30px;" align="center">Pred</td>
	<td rowspan="<tmpl_var project.gaant.rowspan>" valign="top" id="scrolltd" style="border-style:none;width:<tmpl_var project.scroll.percentWidth>%;">
		<div class="scroller" id="gantt">
			<tmpl_var project.ganttChart>
		</div>
	</td>
</tr>
<tr>
	<td colspan="6">&nbsp;</td>
</tr>
<tmpl_loop task.loop>
   <tr>
	   <td align="center" style="height:20px"><tmpl_var task.number></td>
	   <td align="left" style="height:20px">
	      <tmpl_if task.canAdd>
		     <a href="<tmpl_var task.edit.url>" class="submodal"><tmpl_var task.name></a>
		  <tmpl_else>
		     <tmpl_var task.name>
		  </tmpl_if>
	   </td>
	   <td align="center" style="height:20px"><tmpl_var task.duration> <tmpl_var task.duration.units></td>
	   <td align="center" style="height:20px"><tmpl_var task.start></td>
	   <td align="center" style="height:20px"><tmpl_var task.end></td>
	   <td align="center" style="height:20px"><tmpl_var task.dependants></td>	
   </tr>
</tmpl_loop>
<tr>
	<td colspan="6" style="border-style:none;">&nbsp;</td>
</tr>
<tr>
	<td colspan="6" style="border-style:none;">&nbsp;</td>
</tr>
</table>
<tmpl_var form.footer>

<div id="links">
<!-- 	<tmpl_if project.canEdit><a href="<tmpl_var task.resources.url>"><tmpl_var task.resources.label></a>&nbsp;|&nbsp;</tmpl_if> -->
	<tmpl_if task.canAdd><a href="<tmpl_var task.add.url>" class="submodal"><tmpl_var task.add.label></a>&nbsp;|&nbsp;</tmpl_if>
	<a href="<tmpl_var task.back.url>"><tmpl_var task.back.label></a>
</div>

~~~
<style type="text/css">
	body, html {
		margin:0px;
		padding:0px;
	}
	.project {
		position:relative;
		margin-top:5px;
		margin-left:5px;
	}
	.project td {
		border:solid silver 1px;
		border-bottom:solid gray 1px;
		font-size:9pt;
		font-family:arial;		
	}
	.project a {
	    color:#000000;
		font-weight: normal;
		font-size: 9pt;
		text-decoration: none;
	}
	
	.project a:hover {
	    color:#7AB7E9;
		font-weight: normal;
		font-size: 9pt;
		text-decoration: none;
	}
	
	.taskname {
	   font-family: verdana;
	   font-size: 10px;
	   font-weight: normal;
	   color: black;
	   width: 295px;
    }
	.taskduration {
	   font-family: verdana;
	   font-size: 10px;
	   font-weight: normal;
	   color: black;
	   width: 25px;
	}
	.taskdate {
	   font-family: verdana;
	   font-size: 10px;
	   font-weight: normal;
	   color: black;
	   width: 68px;
	}
	.taskdependant {
	   font-family: verdana;
	   font-size: 10px;
	   font-weight: normal;
	   color: black;
	   width: 20px;
	}
	tr.monthNames td {		
		text-align:center;		
	}
	tr.dates td {
		width:16px;
	}
	div.scroller {		
		overflow:scroll;		
		position:relative;
		width:400px;		
	}
	
	* html div.scroller {
		overflow-x:scroll;
	}
	
	td.empty {
		background-color:transparent;
		border-style:none;
		height:20px;
	}
	
	div.barPositions {
		position:relative;
	}
	div.projectBar {
		background-color:#7AB7E9;
		position:absolute;
		height:10px;
		z-index:2;
		padding:0px;
		margin:0px;
		font-size:1pt;
	}
	div.statusBar {	
		background-color:#000;
		position:absolute;	
		height:5px;
		z-index:3;
		padding:0px;
		top:2px;
		margin:0px;		
		font-size:1pt;		
	}
	
	div.projectLineH {		
		background: url('images/dot.gif') top repeat-x;		
		font-size:1pt;
		text-align:right;
		position:absolute;
	}		
	div.projectLineV {
		width:1px;
		background-color:black;
		position:relative;
		font-size:1pt;	
		height:100%;
		float:right;
	}
	
	div.projectLabel {
		position:absolute;
		margin-top:-3px;
		white-space:nowrap;
		font-family: verdana;
		font-size:8px;
	}
	
	div.milestone {
		color:#000000;
		position:absolute;
		z-index:4;
		margin:0px;
		padding:0px;		
		margin-top:-3px;
		font-size: 10px;
		font-family: times;
	}
	
	#links {
		margin-top:7px;
		margin-left:5px;
		font-family:arial;
		font-size:9pt;
	}
	
	#links a {
		color:#7AB7E9;
	}
</style>

<style>
.popUp {
			width:100%;
			border:solid black 0px;
			background-color:#F5F5F5;
		}
		.popUp td {
			font-size:9pt;	
			font-family:arial;
			border-top:solid #E0E0E0 1px;
		}	
		.popUp tr.clear td {
			border-style:none;
			background-color:#F0F0F0;
		}
		.popUp tr.clearNoBG td {
			border-style:none;
		}
		.popUp td.header {
			font-weight:bold;
		}
		a.saveBtn {
			width:40px;
			height:15px;
			background-color:silver;
			padding:1px;
			padding-left:5px;
			padding-right:5px;
			color:white;
			border:solid gray 1px;
			text-decoration:none;
			font-weight:bold;
			display:block;
			float:right;
			text-align:center;
		}
		a.saveBtn:hover {
			background-color:#F0F0F0;
			color:gray;
		}		
</style>