Quick fix: countdown + HTML calculated column

Some readers have tried to combine in a same list the “HTML calculated column” and the countdown proposed by Alexander Bautz.

Unfortunately just putting the two scripts side by side in a CEWP doesn’t work for collapsed views: the scripts overwrite each other, as Alexander reused my method for his script.

So here is a quick fix – I have combined both scripts in one and removed the overlapping parts:

<script type="text/javascript">
<!--                                                                                      -->
<!-- COUNTDOWN + HTML CALCULATED COLUMN                                                   -->
<!--                                                                                      -->
<!-- The first part of this script was created by Alexander Bautz                         -->
<!-- Inspired by Christophe@PathToSharePoint.com                                          -->
<!-- This script searches for calculated fields that are "marked" vith "Due:" and         -->
<!-- select them if they are less than today's date, or less than the "offset" as         -->
<!-- specified in the configuration in the top of the script                              -->

<!-- Create a calculated field in the list with the following formula:                    -->
<!-- =IF(DueDate="","N/A","Due: "&MONTH(DueDate)&"/"&DAY(DueDate)&"/"&YEAR(DueDate))      -->

<!-- The data type returned from this formula is: Date and Time                           -->
<!-- The reason for returning Date and Time is that the date fields                       -->
<!-- displays in <nobr> tags and therefore easier to search for because                   -->
<!-- there are fewer <nobr> tags than <td> tags                                           -->

<!-- ************************************************** -->
<!-- ***************  Change these ******************** -->
<!-- ***  yDaysOffset are the offset "Yellow Light" *** -->
<!-- ***  rDaysOffset are the offset "Red Light"    *** -->
<!-- ************************************************** -->

var yDaysOffset = 5;
var rDaysOffset = 0; 

<!-- plus or minus on todaysDate:                     -->
<!-- minus marks the date x days after                -->
<!-- plus marks the date x days before                -->

<!-- ************************************************ -->
<!-- **** Do not change anything below this line **** -->
<!-- ************************************************ -->

function findDatefields() {
// Find today's date
var todaysDate = new Date();

var arr = document.getElementsByTagName('nobr');
	for (var i=0;i < arr.length; i++ ) {
	// Check if it is "our field"
		if(arr&#91;i&#93;.innerHTML.indexOf("Due:") == 0) {

		var sepDate = arr&#91;i&#93;.innerHTML.substring(5).split("/",3);
		var m = sepDate&#91;0&#93;;
		var d = sepDate&#91;1&#93;;
		var y = sepDate&#91;2&#93;;

		// build the datestring
		var fieldDate = new Date(y,m-1,d,00,00,00);

		var frendlyFieldDate = m + "/" + d + "/" + y; 

		// Round overdueDays with one decimal
		var overDueByDays = (Math.round(((todaysDate.getTime() - fieldDate.getTime())/86400000)*10)/10);

		// OffsetDate - Create the traffic lights
		var date = new Date();
		var yDay = date.getDate() + yDaysOffset;
		var rDay = date.getDate() + rDaysOffset;
		var Month = date.getMonth();
		var Year = date.getFullYear();
		var redOffsetDate = new Date(Year,Month,rDay,00,00,00);
		var yellowOffsetDate = new Date(Year,Month,yDay,00,00,00);

			if(yellowOffsetDate.getTime() < fieldDate.getTime() && redOffsetDate.getTime() < fieldDate.getTime()){
			//alert("green");
			arr&#91;i&#93;.innerHTML = "<DIV title='Due " + frendlyFieldDate + "' style='font-weight:bold; font-size:24px; color:green'>&bull;</DIV>";
			}
			else if(yellowOffsetDate.getTime() >= fieldDate.getTime() && redOffsetDate.getTime() < fieldDate.getTime()){
			//alert("yellow");
			arr&#91;i&#93;.innerHTML = "<DIV title='Due " + frendlyFieldDate + "' style='font-weight:bold; font-size:24px; color:yellow'>&bull;</DIV>";
			}
			else if(redOffsetDate.getTime() == fieldDate.getTime()){
			//alert("red");
			arr[i].innerHTML = "<DIV title='Due today!' style='font-weight:bold; font-size:24px; color:red'>&bull;</DIV>";
			}
			else if(redOffsetDate.getTime() > fieldDate.getTime()){
			//alert("red");
			arr[i].innerHTML = "<DIV title='Overdue by " + overDueByDays + " day(s)" + "' style='font-weight:bold; font-size:24px; color:red'>&bull;</DIV>";
			}

		}
	}
}

// call script
findDatefields();
//
//
// Text to HTML - List views
// Feedback and questions: Christophe@PathToSharePoint.com
//
var theTDs = document.getElementsByTagName("TD");
var i=0;
var TDContent = " ";
while (i < theTDs.length) {
try {
TDContent = theTDs&#91;i&#93;.innerText || theTDs&#91;i&#93;.textContent;
if ((TDContent.indexOf("<DIV") == 0) && (TDContent.indexOf("</DIV>") >= 0)) {
theTDs[i].innerHTML = TDContent;
}
}
catch(err){}
i=i+1;
}
//
// ExpGroupRenderData overwrites the default SharePoint function
// This part is needed for collapsed groupings
//
function ExpGroupRenderData(htmlToRender, groupName, isLoaded) {
var tbody=document.getElementById("tbod"+groupName+"_");
var wrapDiv=document.createElement("DIV");
wrapDiv.innerHTML="<TABLE><TBODY id=\"tbod"+ groupName+"_\" isLoaded=\""+isLoaded+ "\">"+htmlToRender+"</TBODY></TABLE>";
var theTBODYTDs = wrapDiv.getElementsByTagName("TD"); var j=0; var TDContent = " ";
while (j < theTBODYTDs.length) {
try {
TDContent = theTBODYTDs&#91;j&#93;.innerText || theTBODYTDs&#91;j&#93;.textContent;
if ((TDContent.indexOf("<DIV") == 0) && (TDContent.indexOf("</DIV>") >= 0)) {
theTBODYTDs[j].innerHTML = TDContent;
}
}
catch(err){}
j=j+1;
}
tbody.parentNode.replaceChild(wrapDiv.firstChild.firstChild,tbody);
findDatefields();
}
</script>

Hope this helps!

14 thoughts on “Quick fix: countdown + HTML calculated column

  1. K, I am back to harass you. I usually try a script so I understand it works, then put it away unless I have an immeadiate need. So I am almost sure I got this script working. Today I am trying to duplicate it and I can not get it to work. So I am pulling out what hair I have left. . . Reading this and the other posts here over and over again. Finally I group the view and BINGO! Now I see that this works perfect if the view is grouped. I am almost sure that with some modifications we can get the same result without grouping, right?

  2. Is there any chance you could show a way to just display the days remaining? I’ve had a play trying to achieve this myself but am struggling.

  3. Hello

    I’ve got the script working perfect, and I have to say its a great script! Just wondering if someone can help with adding an extra piece. My knowledge of scripts/coding is pretty limited and I just can’t figure out how to add this part…I’m working with these columns Due date, traffic light, task completed. The due date column being the column used in the calculated column forumla (formula column I am calling traffic light), and the task completed column is a basic choice list. I’ve managed to add a part to the formula that says if task completed marked “completed” then no traffic light, this is working fine. Ideally what I would like is for the traffic light to turn green when this task completed column is marked completed. I have a feeling this has to be added to the script part but I wouldn’t even know where to begin to try and add this. Any ideas, I’ll really appreciate the help! Thank-you

  4. This is great, but I am from the UK and need the version of the code that enables me to to use DD/MM/YYYY not just MM/DD/YYYY, could this code be updated to include this functionality please?

  5. With regards to the ExpGroupRenderData override, you may want to consider using this method, to avoid having to copy MS’s rendering code:

    var oldFunc = ExpGroupRenderData;
    ExpGroupRenderData = overrideExpGroupRenderData;

    function overrideExpGroupRenderData(htmlToRender, groupName, isLoaded) {
    oldFunc(htmlToRender, groupName, isLoaded);

    }

    • Stuart, that’s actually what I do. This is a (very) old post with a quick fix, but since 2009 the Text to HTML script has been using the override method you describe (current version is 2.1.1).

    • I should add that the most recent version uses setTimeout instead, as running the script at regular intervals is the only way to cover all situations (grouping, calendars, AJAX, etc.).

  6. anyone know how to convert my countdown to double digits instead of single?

    Heres my code:
    // USER CONFIG SETTINGS
    var countdownYear:Number = 2011; // 20xx
    var countdownMonth:Number = 8; // 1-12
    var countdownDay:Number = 12; // 1-31
    date_txt.text = countdownMonth+”/”+countdownDay+”/”+countdownYear; // date formatting
    // USER CONFIG SETTINGS

    // EVENTS AND TIME CALCULATIONS
    var static_date:Date = new Date(countdownYear, countdownMonth-1, countdownDay, 00, 00, 00, 00);
    addEventListener(Event.ENTER_FRAME, fl_updateCountdown);
    function fl_updateCountdown(evt:Event):void
    {
    var now_date:Date = new Date();
    var nowCountdown:Number = static_date.time – now_date.time;

    var dayTill = ((((nowCountdown/1000)/60)/60)/24);
    var hoursTill = (((((nowCountdown/1000)/60)/60)/24) – Math.floor(dayTill))*24;
    var minTill = ((((((nowCountdown/1000)/60)/60)/24) – Math.floor(dayTill))*24 – Math.floor(hoursTill))*60;
    var secTill = (((((((nowCountdown/1000)/60)/60)/24) – Math.floor(dayTill))*24 – Math.floor(hoursTill))*60 – Math.floor(minTill))*60;

    countdown_txt.text = Math.floor(dayTill)+”:”+Math.floor(hoursTill)+”:”+Math.floor(minTill)+”:”+Math.floor(secTill)+””;
    }
    // END

Comments are closed.