/* _ ___ _ _ _____ _ (_)___ / _ \__ _ _ __ | |_| |_ \_ \_ __ ___ _ __ _ __ _____ _____ __| | | / __| / /_\/ _` | '_ \| __| __| / /\/ '_ ` _ \| '_ \| '__/ _ \ \ / / _ \/ _` | | \__ \/ /_\\ (_| | | | | |_| |_/\/ /_ | | | | | | |_) | | | (_) \ V / __/ (_| | _/ |___/\____/\__,_|_| |_|\__|\__\____/ |_| |_| |_| .__/|_| \___/ \_/ \___|\__,_| |__/ |_| jsGanttImproved 1.7.5.4 The current version of this code can be found at https://github.com/jsGanttImproved/jsgantt-improved/ * Copyright (c) 2013-2017, Paul Geldart, Eduardo Rodrigues and Ricardo Cardoso. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of Paul Geldart, Eduardo Rodrigues and Ricardo Cardoso nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY PAUL GELDART, EDUARDO RODRIGUES AND RICARDO CARDOSO ''AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL PAUL GELDART, EDUARDO RODRIGUES AND RICARDO CARDOSO BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. This project is based on jsGantt 1.2, (which can be obtained from https://code.google.com/p/jsgantt/) and remains under the original BSD license. The original project license follows: Copyright (c) 2009, Shlomy Gantz BlueBrick Inc. All rights reserved. * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of Shlomy Gantz or BlueBrick Inc. nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY SHLOMY GANTZ/BLUEBRICK INC. ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL SHLOMY GANTZ/BLUEBRICK INC. BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ var JSGantt; if (!JSGantt) JSGantt={}; var vBenchTime=new Date().getTime(); JSGantt.isIE=function () { if(typeof document.all!='undefined') { if ('pageXOffset' in window) return false; // give IE9 and above the benefit of the doubt! else return true; } else return false; }; JSGantt.TaskItem=function(pID, pName, pStart, pEnd, pClass, pLink, pMile, pRes, pComp, pGroup, pParent, pOpen, pDepend, pCaption, pNotes, pGantt) { var vID=parseInt(document.createTextNode(pID).data); var vName=document.createTextNode(pName).data; var vStart=new Date(0); var vEnd=new Date(0); var vGroupMinStart=null; var vGroupMinEnd=null; var vClass=document.createTextNode(pClass).data; var vLink=document.createTextNode(pLink).data; var vMile=parseInt(document.createTextNode(pMile).data); var vRes=document.createTextNode(pRes).data; var vComp=parseFloat(document.createTextNode(pComp).data); var vGroup=parseInt(document.createTextNode(pGroup).data); var vParent=document.createTextNode(pParent).data; var vOpen=(vGroup==2)?1:parseInt(document.createTextNode(pOpen).data); var vDepend=new Array(); var vDependType=new Array(); var vCaption=document.createTextNode(pCaption).data; var vDuration=''; var vLevel=0; var vNumKid=0; var vWeight=0; var vVisible=1; var vSortIdx=0; var vToDelete=false; var x1, y1, x2, y2; var vNotes; var vParItem=null; var vCellDiv=null; var vGantt=(pGantt instanceof JSGantt.GanttChart)? pGantt : g; //hack for backwards compatibility var vBarDiv=null; var vTaskDiv=null; var vListChildRow=null; var vChildRow=null; var vGroupSpan=null; vNotes=document.createElement('span'); vNotes.className='gTaskNotes'; if (pNotes!=null) { vNotes.innerHTML=pNotes; JSGantt.stripUnwanted(vNotes); } if (pStart!=null && pStart!='') { vStart=(pStart instanceof Date)?pStart:JSGantt.parseDateStr(document.createTextNode(pStart).data,vGantt.getDateInputFormat()); vGroupMinStart=vStart; } if (pEnd!=null && pEnd!='') { vEnd =(pEnd instanceof Date)?pEnd:JSGantt.parseDateStr(document.createTextNode(pEnd).data,vGantt.getDateInputFormat()); vGroupMinEnd=vEnd; } if (pDepend!=null) { var vDependStr=pDepend+''; var vDepList=vDependStr.split(','); var n=vDepList.length; for(var k=0;k1) { vFormatArr[j++]=arguments[i].toLowerCase(); var vRegExp=new RegExp('(?:^|\s)'+arguments[i]+'(?!\S)', 'g'); vValidFormats=vValidFormats.replace(vRegExp, ''); } } }; this.setShowRes=function(pVal){vShowRes=pVal;}; this.setShowDur=function(pVal){vShowDur=pVal;}; this.setShowComp=function(pVal){vShowComp=pVal;}; this.setShowStartDate=function(pVal){vShowStartDate=pVal;}; this.setShowEndDate=function(pVal){vShowEndDate=pVal;}; this.setShowTaskInfoRes=function(pVal){vShowTaskInfoRes=pVal;}; this.setShowTaskInfoDur=function(pVal){vShowTaskInfoDur=pVal;}; this.setShowTaskInfoComp=function(pVal){vShowTaskInfoComp=pVal;}; this.setShowTaskInfoStartDate=function(pVal){vShowTaskInfoStartDate=pVal;}; this.setShowTaskInfoEndDate=function(pVal){vShowTaskInfoEndDate=pVal;}; this.setShowTaskInfoNotes=function(pVal){vShowTaskInfoNotes=pVal;}; this.setShowTaskInfoLink=function(pVal){vShowTaskInfoLink=pVal;}; this.setShowEndWeekDate=function(pVal){vShowEndWeekDate=pVal;}; this.setShowSelector=function() { var vValidSelectors='top bottom'; vShowSelector=new Array(); for(var i=0, j=0; i1) { vShowSelector[j++]=arguments[i].toLowerCase(); var vRegExp=new RegExp('(?:^|\s)'+arguments[i]+'(?!\S)', 'g'); vValidSelectors=vValidSelectors.replace(vRegExp, ''); } } }; this.setShowDeps=function(pVal){vShowDeps=pVal;}; this.setDateInputFormat=function(pVal){vDateInputFormat=pVal;}; this.setDateTaskTableDisplayFormat=function(pVal){vDateTaskTableDisplayFormat=JSGantt.parseDateFormatStr(pVal);}; this.setDateTaskDisplayFormat=function(pVal){vDateTaskDisplayFormat=JSGantt.parseDateFormatStr(pVal);}; this.setHourMajorDateDisplayFormat=function(pVal){vHourMajorDateDisplayFormat=JSGantt.parseDateFormatStr(pVal);}; this.setHourMinorDateDisplayFormat=function(pVal){vHourMinorDateDisplayFormat=JSGantt.parseDateFormatStr(pVal);}; this.setDayMajorDateDisplayFormat=function(pVal){vDayMajorDateDisplayFormat=JSGantt.parseDateFormatStr(pVal);}; this.setDayMinorDateDisplayFormat=function(pVal){vDayMinorDateDisplayFormat=JSGantt.parseDateFormatStr(pVal);}; this.setWeekMajorDateDisplayFormat=function(pVal){vWeekMajorDateDisplayFormat=JSGantt.parseDateFormatStr(pVal);}; this.setWeekMinorDateDisplayFormat=function(pVal){vWeekMinorDateDisplayFormat=JSGantt.parseDateFormatStr(pVal);}; this.setMonthMajorDateDisplayFormat=function(pVal){vMonthMajorDateDisplayFormat=JSGantt.parseDateFormatStr(pVal);}; this.setMonthMinorDateDisplayFormat=function(pVal){vMonthMinorDateDisplayFormat=JSGantt.parseDateFormatStr(pVal);}; this.setQuarterMajorDateDisplayFormat=function(pVal){vQuarterMajorDateDisplayFormat=JSGantt.parseDateFormatStr(pVal);}; this.setQuarterMinorDateDisplayFormat=function(pVal){vQuarterMinorDateDisplayFormat=JSGantt.parseDateFormatStr(pVal);}; this.setCaptionType=function(pType){vCaptionType=pType;}; this.setFormat=function(pFormat) { vFormat=pFormat; this.Draw(); }; this.setMinGpLen=function(pMinGpLen){vMinGpLen=pMinGpLen;}; this.setScrollTo=function(pDate){vScrollTo=pDate;}; this.setHourColWidth=function(pWidth){vHourColWidth=pWidth;}; this.setDayColWidth=function(pWidth){vDayColWidth=pWidth;}; this.setWeekColWidth=function(pWidth){vWeekColWidth=pWidth;}; this.setMonthColWidth=function(pWidth){vMonthColWidth=pWidth;}; this.setQuarterColWidth=function(pWidth){vQuarterColWidth=pWidth;}; this.setRowHeight=function(pHeight){vRowHeight=pHeight;}; this.setLang=function(pLang){if(vLangs[pLang])vLang=pLang;}; this.setChartBody=function(pDiv){if(typeof HTMLDivElement !== 'function' || pDiv instanceof HTMLDivElement)vChartBody=pDiv;}; this.setChartHead=function(pDiv){if(typeof HTMLDivElement !== 'function' || pDiv instanceof HTMLDivElement)vChartHead=pDiv;}; this.setListBody=function(pDiv){if(typeof HTMLDivElement !== 'function' || pDiv instanceof HTMLDivElement)vListBody=pDiv;}; this.setChartTable=function(pTable){if(typeof HTMLTableElement !== 'function' || pTable instanceof HTMLTableElement)vChartTable=pTable;}; this.setLines=function(pDiv){if(typeof HTMLDivElement !== 'function' || pDiv instanceof HTMLDivElement)vLines=pDiv;}; this.setTimer=function(pVal){vTimer=pVal*1;}; this.addLang=function(pLang, pVals){ if(!vLangs[pLang]) { vLangs[pLang]=new Object(); for(var vKey in vLangs['en'])vLangs[pLang][vKey]=(pVals[vKey])?document.createTextNode(pVals[vKey]).data:vLangs['en'][vKey]; } }; this.getDivId=function(){return vDivId;}; this.getUseFade=function(){return vUseFade;}; this.getUseMove=function(){return vUseMove;}; this.getUseRowHlt=function(){return vUseRowHlt;}; this.getUseToolTip=function(){return vUseToolTip;}; this.getUseSort=function(){return vUseSort;}; this.getUseSingleCell=function(){return vUseSingleCell;}; this.getFormatArr=function(){return vFormatArr;}; this.getShowRes=function(){return vShowRes;}; this.getShowDur=function(){return vShowDur;}; this.getShowComp=function(){return vShowComp;}; this.getShowStartDate=function(){return vShowStartDate;}; this.getShowEndDate=function(){return vShowEndDate;}; this.getShowTaskInfoRes=function(){return vShowTaskInfoRes;}; this.getShowTaskInfoDur=function(){return vShowTaskInfoDur;}; this.getShowTaskInfoComp=function(){return vShowTaskInfoComp;}; this.getShowTaskInfoStartDate=function(){return vShowTaskInfoStartDate;}; this.getShowTaskInfoEndDate=function(){return vShowTaskInfoEndDate;}; this.getShowTaskInfoNotes=function(){return vShowTaskInfoNotes;}; this.getShowTaskInfoLink=function(){return vShowTaskInfoLink;}; this.getShowEndWeekDate=function(){return vShowEndWeekDate;}; this.getShowSelector=function(){return vShowSelector;}; this.getShowDeps=function(){return vShowDeps;}; this.getDateInputFormat=function(){return vDateInputFormat;}; this.getDateTaskTableDisplayFormat=function(){return vDateTaskTableDisplayFormat;}; this.getDateTaskDisplayFormat=function(){return vDateTaskDisplayFormat;}; this.getHourMajorDateDisplayFormat=function(){return vHourMajorDateDisplayFormat;}; this.getHourMinorDateDisplayFormat=function(){return vHourMinorDateDisplayFormat;}; this.getDayMajorDateDisplayFormat=function(){return vDayMajorDateDisplayFormat;}; this.getDayMinorDateDisplayFormat=function(){return vDayMinorDateDisplayFormat;}; this.getWeekMajorDateDisplayFormat=function(){return vWeekMajorDateDisplayFormat;}; this.getWeekMinorDateDisplayFormat=function(){return vWeekMinorDateDisplayFormat;}; this.getMonthMajorDateDisplayFormat=function(){return vMonthMajorDateDisplayFormat;}; this.getMonthMinorDateDisplayFormat=function(){return vMonthMinorDateDisplayFormat;}; this.getQuarterMajorDateDisplayFormat=function(){return vQuarterMajorDateDisplayFormat;}; this.getQuarterMinorDateDisplayFormat=function(){return vQuarterMinorDateDisplayFormat;}; this.getCaptionType=function(){return vCaptionType;}; this.getMinGpLen=function(){return vMinGpLen;}; this.getScrollTo=function(){return vScrollTo;}; this.getHourColWidth=function(){return vHourColWidth;}; this.getDayColWidth=function(){return vDayColWidth;}; this.getWeekColWidth=function(){return vWeekColWidth;}; this.getMonthColWidth=function(){return vMonthColWidth;}; this.getQuarterColWidth=function(){return vQuarterColWidth;}; this.getRowHeight=function(){return vRowHeight;}; this.getChartBody=function(){return vChartBody;}; this.getChartHead=function(){return vChartHead;}; this.getListBody=function(){return vListBody;}; this.getChartTable=function(){return vChartTable;}; this.getLines=function(){return vLines;}; this.getTimer=function(){return vTimer;}; this.CalcTaskXY=function() { var vID; var vList=this.getList(); var vBarDiv; var vTaskDiv; var vParDiv; var vLeft, vTop, vWidth; var vHeight=Math.floor((this.getRowHeight()/2)); for(var i=0; i=x2 && y1!=y2) vBend=true; break; } if (vBend) { this.sLine(x1,y1,x1+vShort,y1,pClass); this.sLine(x1+vShort,y1,x1+vShort,y2-vRow,pClass); this.sLine(x1+vShort,y2-vRow,x2-(vShort*2),y2-vRow,pClass); this.sLine(x2-(vShort*2),y2-vRow,x2-(vShort*2),y2,pClass); this.sLine(x2-(vShort*2),y2,x2-(1*vDir),y2,pClass); } else if (y1!=y2) { this.sLine(x1,y1,x1+vShort,y1,pClass); this.sLine(x1+vShort,y1,x1+vShort,y2,pClass); this.sLine(x1+vShort,y2,x2-(1*vDir),y2,pClass); } else this.sLine(x1,y1,x2-(1*vDir),y2,pClass); var vTmpDiv=this.sLine(x2,y2,x2-3-((vDir<0)?1:0),y2-3-((vDir<0)?1:0),pClass+"Arw"); vTmpDiv.style.width='0px'; vTmpDiv.style.height='0px'; }; this.DrawDependencies=function() { if (this.getShowDeps()==1) { //First recalculate the x,y this.CalcTaskXY(); this.clearDependencies(); var vList=this.getList(); for(var i=0; i0 && vList[i].getVisible()==1) { for(var k=0;k=0 && vList[vTask].getGroup()!=2) { if(vList[vTask].getVisible()==1) { if(vDependType[k]=='SS')this.drawDependency(vList[vTask].getStartX()-1,vList[vTask].getStartY(),vList[i].getStartX()-1,vList[i].getStartY(),'SS','gDepSS'); else if(vDependType[k]=='FF')this.drawDependency(vList[vTask].getEndX(),vList[vTask].getEndY(),vList[i].getEndX(),vList[i].getEndY(),'FF','gDepFF'); else if(vDependType[k]=='SF')this.drawDependency(vList[vTask].getStartX()-1,vList[vTask].getStartY(),vList[i].getEndX(),vList[i].getEndY(),'SF','gDepSF'); else if(vDependType[k]=='FS')this.drawDependency(vList[vTask].getEndX(),vList[vTask].getEndY(),vList[i].getStartX()-1,vList[i].getStartY(),'FS','gDepFS'); } } } } } } // draw the current date line if (vTodayPx>=0) this.sLine(vTodayPx, 0, vTodayPx, this.getChartTable().offsetHeight-1, 'gCurDate'); }; this.getArrayLocationByID=function(pId) { var vList=this.getList(); for(var i=0; i0) { // Process all tasks, reset parent date and completion % if task list has altered if (vProcessNeeded) JSGantt.processRows(vTaskList, 0, -1, 1, 1, this.getUseSort()); vProcessNeeded=false; // get overall min/max dates plus padding vMinDate=JSGantt.getMinDate(vTaskList, vFormat); vMaxDate=JSGantt.getMaxDate(vTaskList, vFormat); // Calculate chart width variables. if(vFormat=='day') vColWidth=vDayColWidth; else if(vFormat=='week') vColWidth=vWeekColWidth; else if(vFormat=='month') vColWidth=vMonthColWidth; else if(vFormat=='quarter') vColWidth=vQuarterColWidth; else if(vFormat=='hour') vColWidth=vHourColWidth; // DRAW the Left-side of the chart (names, resources, comp%) var vLeftHeader=document.createDocumentFragment(); var vTmpDiv=this.newNode(vLeftHeader, 'div', vDivId+'glisthead', 'glistlbl gcontainercol'); var vTmpTab=this.newNode(vTmpDiv, 'table', null, 'gtasktableh'); var vTmpTBody=this.newNode(vTmpTab, 'tbody'); var vTmpRow=this.newNode(vTmpTBody, 'tr'); this.newNode(vTmpRow, 'td', null, 'gtasklist', '\u00A0'); var vTmpCell=this.newNode(vTmpRow, 'td', null, 'gspanning gtaskname'); vTmpCell.appendChild(this.drawSelector('top')); if(vShowRes==1)this.newNode(vTmpRow, 'td', null, 'gspanning gresource', '\u00A0'); if(vShowDur==1)this.newNode(vTmpRow, 'td', null, 'gspanning gduration', '\u00A0'); if(vShowComp==1)this.newNode(vTmpRow, 'td', null, 'gspanning gpccomplete', '\u00A0'); if(vShowStartDate==1)this.newNode(vTmpRow, 'td', null, 'gspanning gstartdate', '\u00A0'); if(vShowEndDate==1)this.newNode(vTmpRow, 'td', null, 'gspanning genddate', '\u00A0'); vTmpRow=this.newNode(vTmpTBody, 'tr'); this.newNode(vTmpRow, 'td', null, 'gtasklist', '\u00A0'); this.newNode(vTmpRow, 'td', null, 'gtaskname', '\u00A0'); if(vShowRes==1)this.newNode(vTmpRow, 'td', null, 'gtaskheading gresource', vLangs[vLang]['resource']); if(vShowDur==1)this.newNode(vTmpRow, 'td', null, 'gtaskheading gduration', vLangs[vLang]['duration']); if(vShowComp==1)this.newNode(vTmpRow, 'td', null, 'gtaskheading gpccomplete', vLangs[vLang]['comp']); if(vShowStartDate==1)this.newNode(vTmpRow, 'td', null, 'gtaskheading gstartdate', vLangs[vLang]['startdate']); if(vShowEndDate==1)this.newNode(vTmpRow, 'td', null, 'gtaskheading genddate', vLangs[vLang]['enddate']); var vLeftTable=document.createDocumentFragment(); var vTmpDiv2=this.newNode(vLeftTable, 'div', vDivId+'glistbody', 'glistgrid gcontainercol'); this.setListBody(vTmpDiv2); vTmpTab=this.newNode(vTmpDiv2, 'table', null, 'gtasktable'); vTmpTBody=this.newNode(vTmpTab, 'tbody'); for(i=0; i1) { vTmpDate.setDate(vTmpDate.getDate()+1); } } else if(vFormat=='quarter') { if(vTmpDate<=vMaxDate) { vTmpCell=this.newNode(vTmpRow, 'td', null, vHeaderCellClass); this.newNode(vTmpCell, 'div', null, null, JSGantt.formatDateStr(vTmpDate,vQuarterMinorDateDisplayFormat,vLangs[vLang]), vColWidth); vNumCols++; } vTmpDate.setDate(vTmpDate.getDate()+81); while(vTmpDate.getDate()>1) vTmpDate.setDate(vTmpDate.getDate()+1); } else if(vFormat=='hour') { for(i=vTmpDate.getHours();i<24;i++) { vTmpDate.setHours(i);//works around daylight savings but may look a little odd on days where the clock goes forward if(vTmpDate<=vMaxDate) { vTmpCell=this.newNode(vTmpRow, 'td', null, vHeaderCellClass); this.newNode(vTmpCell, 'div', null, null, JSGantt.formatDateStr(vTmpDate,vHourMinorDateDisplayFormat,vLangs[vLang]), vColWidth); vNumCols++; } } vTmpDate.setHours(0); vTmpDate.setDate(vTmpDate.getDate()+1); } } vDateRow=vTmpRow; vTaskLeftPx=(vNumCols *(vColWidth+1))+1; if(vUseSingleCell!=0 && vUseSingleCell<(vNumCols*vNumRows))vSingleCell=true; this.newNode(vTmpDiv, 'div', null, 'rhscrpad', null, null, vTaskLeftPx+1); vTmpDiv=this.newNode(vRightHeader, 'div', null, 'glabelfooter'); var vRightTable=document.createDocumentFragment(); vTmpDiv=this.newNode(vRightTable, 'div', vDivId+'gchartbody', 'gchartgrid gcontainercol'); this.setChartBody(vTmpDiv); vTmpTab=this.newNode(vTmpDiv, 'table', vDivId+'chartTable', 'gcharttable', null, vTaskLeftPx); this.setChartTable(vTmpTab); this.newNode(vTmpDiv, 'div', null, 'rhscrpad', null, null, vTaskLeftPx+1); vTmpTBody=this.newNode(vTmpTab, 'tbody'); // Draw each row var i=0; var j=0; for(i=0; ivMinGpLen && vTaskWidth=vMinGpLen*2) this.newNode(vTmpDiv, 'div', null, vTaskList[i].getClass() +'endpointright'); vCaptClass='ggroupcaption'; } if(!vSingleCell && !vComb) { vCellFormat=''; for(j=0; j=(new Date()).getTime()) vTodayPx=JSGantt.getOffset(vMinDate, new Date(), vColWidth, vFormat); else vTodayPx=-1; this.DrawDependencies(); } }; //this.draw this.mouseOver=function(pObj1, pObj2) { if (this.getUseRowHlt()) { pObj1.className+=' gitemhighlight'; pObj2.className+=' gitemhighlight'; } }; this.mouseOut=function(pObj1, pObj2) { if (this.getUseRowHlt()) { pObj1.className=pObj1.className.replace(/(?:^|\s)gitemhighlight(?!\S)/g, ''); pObj2.className=pObj2.className.replace(/(?:^|\s)gitemhighlight(?!\S)/g, ''); } }; this.drawSelector=function(pPos) { var vOutput=document.createDocumentFragment(); var vDisplay=false; for (var i=0; i=0 && vIdx'; vTask+=''+vTaskList[vIdx].getName()+''; vTask+=''+JSGantt.formatDateStr(vTaskList[vIdx].getStart(),vOutFrmt,vLangs[vLang])+''; vTask+=''+JSGantt.formatDateStr(vTaskList[vIdx].getEnd(),vOutFrmt,vLangs[vLang])+''; vTask+=''+vTaskList[vIdx].getClass()+''; vTask+=''+vTaskList[vIdx].getLink()+''; vTask+=''+vTaskList[vIdx].getMile()+''; if(vTaskList[vIdx].getResource()!='\u00A0') vTask+=''+vTaskList[vIdx].getResource()+''; vTask+=''+vTaskList[vIdx].getCompVal()+''; vTask+=''+vTaskList[vIdx].getGroup()+''; vTask+=''+vTaskList[vIdx].getParent()+''; vTask+=''+vTaskList[vIdx].getOpen()+''; vTask+=''; var vDepList=vTaskList[vIdx].getDepend(); for (i=0;i0)vTask+=','; if(vDepList[i]>0)vTask+=vDepList[i]+vTaskList[vIdx].getDepType()[i]; } vTask+=''; vTask+=''+vTaskList[vIdx].getCaption()+''; var vTmpFrag=document.createDocumentFragment(); var vTmpDiv=this.newNode(vTmpFrag, 'div', null, null,vTaskList[vIdx].getNotes().innerHTML); vTask+=''+vTmpDiv.innerHTML+''; vTask+=''; } return vTask; }; if (vDiv && vDiv.nodeName.toLowerCase()=='div') vDivId=vDiv.id; }; //GanttChart JSGantt.updateFlyingObj=function (e, pGanttChartObj, pTimer) { var vCurTopBuf=3; var vCurLeftBuf=5; var vCurBotBuf=3; var vCurRightBuf=15; var vMouseX=(e)?e.clientX:window.event.clientX; var vMouseY=(e)?e.clientY:window.event.clientY; var vViewportX=document.documentElement.clientWidth||document.getElementsByTagName('body')[0].clientWidth; var vViewportY=document.documentElement.clientHeight||document.getElementsByTagName('body')[0].clientHeight; var vNewX=vMouseX; var vNewY=vMouseY; if (navigator.appName.toLowerCase ()=='microsoft internet explorer') { // the clientX and clientY properties include the left and top borders of the client area vMouseX-=document.documentElement.clientLeft; vMouseY-=document.documentElement.clientTop; var vZoomFactor=JSGantt.getZoomFactor (); if (vZoomFactor!=1) {// IE 7 at non-default zoom level vMouseX=Math.round (vMouseX / vZoomFactor); vMouseY=Math.round (vMouseY / vZoomFactor); } } var vScrollPos=JSGantt.getScrollPositions(); /* Code for positioned right of the mouse by default*/ /* if (vMouseX+vCurRightBuf+pGanttChartObj.vTool.offsetWidth>vViewportX) { if (vMouseX-vCurLeftBuf-pGanttChartObj.vTool.offsetWidth<0) vNewX=vScrollPos.x; else vNewX=vMouseX+vScrollPos.x-vCurLeftBuf-pGanttChartObj.vTool.offsetWidth; } else vNewX=vMouseX+vScrollPos.x+vCurRightBuf; */ /* Code for positioned left of the mouse by default */ if (vMouseX-vCurLeftBuf-pGanttChartObj.vTool.offsetWidth<0) { if (vMouseX+vCurRightBuf+pGanttChartObj.vTool.offsetWidth>vViewportX) vNewX=vScrollPos.x; else vNewX=vMouseX+vScrollPos.x+vCurRightBuf; } else vNewX=vMouseX+vScrollPos.x-vCurLeftBuf-pGanttChartObj.vTool.offsetWidth; /* Code for positioned below the mouse by default */ if (vMouseY+vCurBotBuf+pGanttChartObj.vTool.offsetHeight>vViewportY) { if (vMouseY-vCurTopBuf-pGanttChartObj.vTool.offsetHeight<0) vNewY=vScrollPos.y; else vNewY=vMouseY+vScrollPos.y-vCurTopBuf-pGanttChartObj.vTool.offsetHeight; } else vNewY=vMouseY+vScrollPos.y+vCurBotBuf; /* Code for positioned above the mouse by default */ /* if (vMouseY-vCurTopBuf-pGanttChartObj.vTool.offsetHeight<0) { if (vMouseY+vCurBotBuf+pGanttChartObj.vTool.offsetHeight>vViewportY) vNewY=vScrollPos.y; else vNewY=vMouseY+vScrollPos.y+vCurBotBuf; } else vNewY=vMouseY+vScrollPos.y-vCurTopBuf-pGanttChartObj.vTool.offsetHeight; */ if (pGanttChartObj.getUseMove()) { clearInterval(pGanttChartObj.vTool.moveInterval); pGanttChartObj.vTool.moveInterval=setInterval(function(){JSGantt.moveToolTip(vNewX, vNewY, pGanttChartObj.vTool, pTimer);},pTimer); } else { pGanttChartObj.vTool.style.left=vNewX +'px'; pGanttChartObj.vTool.style.top=vNewY +'px'; } }; JSGantt.showToolTip=function(pGanttChartObj, e, pContents, pWidth, pTimer){ var vTtDivId=pGanttChartObj.getDivId()+'JSGanttToolTip'; var vMaxW=500; var vMaxAlpha=100; var vShowing=pContents.id; if(pGanttChartObj.getUseToolTip()) { if(pGanttChartObj.vTool==null){ pGanttChartObj.vTool=document.createElement('div'); pGanttChartObj.vTool.id=vTtDivId; pGanttChartObj.vTool.className='JSGanttToolTip'; pGanttChartObj.vTool.vToolCont=document.createElement('div'); pGanttChartObj.vTool.vToolCont.id=vTtDivId+'cont'; pGanttChartObj.vTool.vToolCont.className='JSGanttToolTipcont'; pGanttChartObj.vTool.vToolCont.setAttribute('showing',''); pGanttChartObj.vTool.appendChild(pGanttChartObj.vTool.vToolCont); document.body.appendChild(pGanttChartObj.vTool); pGanttChartObj.vTool.style.opacity=0; pGanttChartObj.vTool.setAttribute('currentOpacity',0); pGanttChartObj.vTool.setAttribute('fadeIncrement',10); pGanttChartObj.vTool.setAttribute('moveSpeed',10); pGanttChartObj.vTool.style.filter='alpha(opacity=0)'; pGanttChartObj.vTool.style.visibility='hidden'; pGanttChartObj.vTool.style.left=Math.floor(((e)?e.clientX:window.event.clientX)/2)+'px'; pGanttChartObj.vTool.style.top=Math.floor(((e)?e.clientY:window.event.clientY)/2)+'px'; JSGantt.addListener('mouseover', function () {clearTimeout(pGanttChartObj.vTool.delayTimeout);}, pGanttChartObj.vTool); JSGantt.addListener('mouseout', function () {JSGantt.delayedHide(pGanttChartObj, pGanttChartObj.vTool, pTimer);}, pGanttChartObj.vTool); } clearTimeout(pGanttChartObj.vTool.delayTimeout); if(pGanttChartObj.vTool.vToolCont.getAttribute('showing')!=vShowing || pGanttChartObj.vTool.style.visibility!='visible') { if (pGanttChartObj.vTool.vToolCont.getAttribute('showing')!=vShowing) { pGanttChartObj.vTool.vToolCont.setAttribute('showing',vShowing); pGanttChartObj.vTool.vToolCont.innerHTML=pContents.innerHTML; // as we are allowing arbitrary HTML we should remove any tag ids to prevent duplication JSGantt.stripIds(pGanttChartObj.vTool.vToolCont); } pGanttChartObj.vTool.style.visibility='visible'; // Rather than follow the mouse just have it stay put JSGantt.updateFlyingObj(e, pGanttChartObj, pTimer); pGanttChartObj.vTool.style.width=(pWidth)? pWidth+'px' : 'auto'; if(!pWidth && JSGantt.isIE()){ pGanttChartObj.vTool.style.width=pGanttChartObj.vTool.offsetWidth; } if(pGanttChartObj.vTool.offsetWidth>vMaxW){pGanttChartObj.vTool.style.width=vMaxW+'px';} } if (pGanttChartObj.getUseFade()) { clearInterval(pGanttChartObj.vTool.fadeInterval); pGanttChartObj.vTool.fadeInterval=setInterval(function(){JSGantt.fadeToolTip(1, pGanttChartObj.vTool, vMaxAlpha);},pTimer); } else { pGanttChartObj.vTool.style.opacity=vMaxAlpha * 0.01; pGanttChartObj.vTool.style.filter='alpha(opacity='+vMaxAlpha+')'; } } }; JSGantt.stripIds=function(pNode){ for(var i=0; i=0 && pList[i].getID()==pID)vCurItem=pList[i]; } for(i=0; ivMaxDate) { vMaxDate=pList[i].getEnd(); vMaxSet=1; } vNumKid++; vWeight+=pList[i].getEnd()-pList[i].getStart()+1; vCompSum+=pList[i].getCompVal()*(pList[i].getEnd()-pList[i].getStart()+1); pList[i].setSortIdx(i*pList.length); } } if(pRow>=0) { if(pList[pRow].getGroupMinStart()!=null && pList[pRow].getGroupMinStart()vMaxDate) { vMaxDate=pList[pRow].getGroupMinEnd(); } pList[pRow].setStart(vMinDate); pList[pRow].setEnd(vMaxDate); pList[pRow].setNumKid(vNumKid); pList[pRow].setWeight(vWeight); pList[pRow].setCompVal(Math.ceil(vCompSum/vWeight)); } if (pID==0 && pUseSort==1) { JSGantt.sortTasks(pList, 0, 0); pList.sort(function(a,b){return a.getSortIdx()-b.getSortIdx();}); } if (pID==0 && pUseSort!=1) // Need to sort combined tasks regardless { for(i=0; i0) { sortArr.sort(function(a,b){ var i=a.getStart().getTime()-b.getStart().getTime(); if (i==0) i=a.getEnd().getTime()-b.getEnd().getTime(); if (i==0) return a.getID()-b.getID(); else return i; }); } for (var j=0; j1) vDate.setDate(vDate.getDate()-1); } else if (pFormat=='quarter') { vDate.setDate(vDate.getDate()-31); if(vDate.getMonth()==0 || vDate.getMonth()==1 || vDate.getMonth()==2) vDate.setFullYear(vDate.getFullYear(), 0, 1); else if(vDate.getMonth()==3 || vDate.getMonth()==4 || vDate.getMonth()==5) vDate.setFullYear(vDate.getFullYear(), 3, 1); else if(vDate.getMonth()==6 || vDate.getMonth()==7 || vDate.getMonth()==8) vDate.setFullYear(vDate.getFullYear(), 6, 1); else if(vDate.getMonth()==9 || vDate.getMonth()==10 || vDate.getMonth()==11) vDate.setFullYear(vDate.getFullYear(), 9, 1); } else if (pFormat=='hour') { vDate.setHours(vDate.getHours()-1); while(vDate.getHours()%6!=0) vDate.setHours(vDate.getHours()-1); } if(pFormat=='hour')vDate.setMinutes(0,0); else vDate.setHours(0,0,0); return(vDate); }; // Used to determine the maximum date of all tasks and set upper bound based on format JSGantt.getMaxDate=function (pList, pFormat) { var vDate=new Date(); vDate.setTime(pList[0].getEnd().getTime()); // Parse all Task End dates to find max for(var i=0; ivDate.getTime()) vDate.setTime(pList[i].getEnd().getTime()); } // Adjust max date to specific format boundaries (end of week or end of month) if (pFormat=='day') { vDate.setDate(vDate.getDate()+1); while(vDate.getDay()%7!=0) vDate.setDate(vDate.getDate()+1); } else if (pFormat=='week') { //For weeks, what is the last logical boundary? vDate.setDate(vDate.getDate()+1); while(vDate.getDay()%7!=0) vDate.setDate(vDate.getDate()+1); } else if (pFormat=='month') { // Set to last day of current Month while(vDate.getDate()>1) vDate.setDate(vDate.getDate()+1); vDate.setDate(vDate.getDate()-1); } else if (pFormat=='quarter') { // Set to last day of current Quarter if(vDate.getMonth()==0 || vDate.getMonth()==1 || vDate.getMonth()==2) vDate.setFullYear(vDate.getFullYear(), 2, 31); else if(vDate.getMonth()==3 || vDate.getMonth()==4 || vDate.getMonth()==5) vDate.setFullYear(vDate.getFullYear(), 5, 30); else if(vDate.getMonth()==6 || vDate.getMonth()==7 || vDate.getMonth()==8) vDate.setFullYear(vDate.getFullYear(), 8, 30); else if(vDate.getMonth()==9 || vDate.getMonth()==10 || vDate.getMonth()==11) vDate.setFullYear(vDate.getFullYear(), 11, 31); } else if (pFormat=='hour') { if(vDate.getHours()==0)vDate.setDate(vDate.getDate()+1); vDate.setHours(vDate.getHours()+1); while(vDate.getHours()%6!=5) vDate.setHours(vDate.getHours()+1); } return(vDate); }; // This function finds the document id of the specified object JSGantt.findObj=function (theObj, theDoc) { var p, i, foundObj; if(!theDoc) theDoc=document; if(document.getElementById) foundObj=document.getElementById(theObj); return foundObj; }; JSGantt.changeFormat=function(pFormat,ganttObj) { if(ganttObj) ganttObj.setFormat(pFormat); else alert('Chart undefined'); }; // Function to open/close and hide/show children of specified task JSGantt.folder=function (pID,ganttObj) { var vList=ganttObj.getList(); var vDivId=ganttObj.getDivId(); ganttObj.clearDependencies(); // clear these first so slow rendering doesn't look odd for(var i=0; i=52 && vMonthStr==1) vYear--; if (vWeekNum==1 && vMonthStr==12) vYear++; if (vWeekNum<10) vWeekNum='0'+vWeekNum; vDateStr+=vYear+'-W'+vWeekNum+'-'+vDayOfWeek; break; default: if (pL[pDateFormatArr[i].toLowerCase()]) vDateStr+=pL[pDateFormatArr[i].toLowerCase()]; else vDateStr+=pDateFormatArr[i]; break; } } return vDateStr; }; JSGantt.parseDateFormatStr=function(pFormatStr) { var vDateStr=''; var vComponantStr=''; var vCurrChar=''; var vSeparators=new RegExp('[\/\\ -.,\'":]'); var vDateFormatArray=new Array(); for (var i=0; i0) project=projNode[0].getAttribute('xmlns'); if(project=='http://schemas.microsoft.com/project') { vMSP=true; pGanttVar.setDateInputFormat('yyyy-mm-dd'); Task=JSGantt.findXMLNode(pXmlDoc,'Task'); if (typeof Task=='undefined')n=0; else n=Task.length; var resources=JSGantt.findXMLNode(pXmlDoc,'Resource'); if (typeof resources=='undefined'){n=0; m=0;} else m=resources.length; for(i=0;i0 && uid>0) res[uid]=resname; } var assignments=JSGantt.findXMLNode(pXmlDoc,'Assignment'); if (typeof assignments=='undefined') j=0; else j=assignments.length; for(i=0;i0) { if (resUID>0) assRes[uid]=res[resUID]; ass[uid]=assignments[i]; } } // Store information about parent UIDs in an easily searchable form for(i=0;i0) pars[vOutlineNumber]=uid; if (uid>maxPID)maxPID=uid; } for(i=0;i1) { vOutlineNumber=JSGantt.getXMLNodeValue(Task[i],'OutlineNumber',2,'0'); pParent=pars[vOutlineNumber.substr(0, vOutlineNumber.lastIndexOf('.'))]; } try {var pNotes=Task[i].getElementsByTagName('Notes')[0].childNodes[1].nodeValue; //this should be a CDATA node } catch (error) {pNotes ='';} if(typeof assRes[pID]!='undefined') var pRes=assRes[pID]; else pRes=''; var predecessors=JSGantt.findXMLNode(Task[i],'PredecessorLink'); if (typeof predecessors=='undefined') j=0; else j=predecessors.length; var pDepend=''; for(k=0;k0) { if (pDepend.length>0)pDepend+=','; switch(depType) { case 0: pDepend+=depUID+'FF'; break; case 1: pDepend+=depUID+'FS'; break; case 2: pDepend+=depUID+'SF'; break; case 3: pDepend+=depUID+'SS'; break; default: pDepend+=depUID+'FS'; break; } } } var pOpen=1; var pCaption=''; if(pGroup>0) var pClass ='ggroupblack'; else if(pMile>0) pClass ='gmilestone'; else pClass ='gtaskblue'; // check for split tasks var splits=JSGantt.findXMLNode(ass[pID],'TimephasedData'); if (typeof splits=='undefined') j=0; else j=splits.length; var vSplitStart=pStart; var vSplitEnd=pEnd; var vSubCreated=false; var vDepend=pDepend.replace(/,*[0-9]+[FS]F/g,''); for(k=0;k0) pClass ='ggroupblack'; else if(pMile>0) pClass ='gmilestone'; else pClass ='gtaskblue'; } // Finally add the task pGanttVar.AddTaskItem(new JSGantt.TaskItem(pID, pName, pStart, pEnd, pClass, pLink, pMile, pRes, pComp, pGroup, pParent, pOpen, pDepend, pCaption, pNotes, pGanttVar)); } } } }; JSGantt.benchMark=function(pItem) { var vEndTime=new Date().getTime(); alert(pItem+': Elapsed time: '+((vEndTime-vBenchTime)/1000)+' seconds.'); vBenchTime=new Date().getTime(); }; JSGantt.getIsoWeek=function(pDate){ // We have to compare against the monday of the first week of the year containing 04 jan *not* 01/01 // 60*60*24*1000=86400000 var dayMiliseconds=86400000; var keyDay=new Date(pDate.getFullYear(),0,4,0,0,0); var keyDayOfWeek=(keyDay.getDay()==0) ? 6 : keyDay.getDay()-1; // define monday as 0 var firstMondayYearTime=keyDay.getTime()-(keyDayOfWeek * dayMiliseconds); var thisDate=new Date(pDate.getFullYear(), pDate.getMonth(),pDate.getDate(),0,0,0); // This at 00:00:00 var thisTime=thisDate.getTime(); var daysFromFirstMonday=Math.round(((thisTime-firstMondayYearTime) / dayMiliseconds)); var lastWeek=99; var thisWeek=99; var firstMondayYear=new Date(firstMondayYearTime); thisWeek=Math.ceil((daysFromFirstMonday+1)/7); if (thisWeek<=0) thisWeek=JSGantt.getIsoWeek(new Date(pDate.getFullYear()-1,11,31,0,0,0)); else if (thisWeek==53 && (new Date(pDate.getFullYear(),0,1,0,0,0)).getDay()!=4 && (new Date(pDate.getFullYear(),11,31,0,0,0)).getDay()!=4) thisWeek=1; return thisWeek; }; JSGantt.addListener=function (eventName, handler, control) { // Check if control is a string if (control===String(control)) control=JSGantt.findObj(control); if(control.addEventListener) //Standard W3C { return control.addEventListener(eventName, handler, false); } else if (control.attachEvent) //IExplore { return control.attachEvent('on'+eventName, handler); } else { return false; } }; JSGantt.addTooltipListeners=function(pGanttChart, pObj1, pObj2) { JSGantt.addListener('mouseover', function (e) {JSGantt.showToolTip(pGanttChart, e, pObj2, null, pGanttChart.getTimer());}, pObj1); JSGantt.addListener('mouseout', function (e) {JSGantt.delayedHide(pGanttChart, pGanttChart.vTool, pGanttChart.getTimer());}, pObj1); }; JSGantt.addThisRowListeners=function(pGanttChart, pObj1, pObj2) { JSGantt.addListener('mouseover', function () {pGanttChart.mouseOver(pObj1, pObj2);}, pObj1); JSGantt.addListener('mouseover', function () {pGanttChart.mouseOver(pObj1, pObj2);}, pObj2); JSGantt.addListener('mouseout', function () {pGanttChart.mouseOut(pObj1, pObj2);}, pObj1); JSGantt.addListener('mouseout', function () {pGanttChart.mouseOut(pObj1, pObj2);}, pObj2); }; JSGantt.addFolderListeners=function(pGanttChart, pObj, pID) { JSGantt.addListener('click', function () {JSGantt.folder(pID, pGanttChart);}, pObj); }; JSGantt.addFormatListeners=function(pGanttChart, pFormat, pObj) { JSGantt.addListener('click', function () {JSGantt.changeFormat(pFormat, pGanttChart);}, pObj); }; JSGantt.addScrollListeners=function(pGanttChart) { JSGantt.addListener('scroll', function () {pGanttChart.getChartBody().scrollTop=pGanttChart.getListBody().scrollTop;}, pGanttChart.getListBody()); JSGantt.addListener('scroll', function () {pGanttChart.getListBody().scrollTop=pGanttChart.getChartBody().scrollTop;}, pGanttChart.getChartBody()); JSGantt.addListener('scroll', function () {pGanttChart.getChartHead().scrollLeft=pGanttChart.getChartBody().scrollLeft;}, pGanttChart.getChartBody()); JSGantt.addListener('scroll', function () {pGanttChart.getChartBody().scrollLeft=pGanttChart.getChartHead().scrollLeft;}, pGanttChart.getChartHead()); JSGantt.addListener('resize', function () {pGanttChart.getChartHead().scrollLeft=pGanttChart.getChartBody().scrollLeft;}, window); JSGantt.addListener('resize', function () {pGanttChart.getListBody().scrollTop=pGanttChart.getChartBody().scrollTop;}, window); };