4. Highlight Weekends in List View

Update: July 18th, 2010

This article the first of The Power of Content Editor WebPart series. Other parts:

 

Some time ago we’ve had an interesting project and part of that project was to expose weekends in a list view. This meant that the list had a Date and Time column. When all items were listed, the rows containing dates with weekends would need to be with red text instead of default black. A sample of what needed to be done is in a screenshot below:

Result

Do we program an extra webpart for coloring rows of data? No. JavaScript to the rescue.

Let’s get busy!

After we’ve created our list with the date and time column, before going the standard way of inserting the CEWP and linking the JS, let’s turn attention to SharePoint first. We need a way to tell if the date represented is a weekend day. For that we’ll use the calculated column.

In our list Let’s Create a new Calculated column:

In Settings menu select Create Column Choose the Calculated type

How to calculate the day of the week? We’ll use the powerful "TEXT" function. In the Formula field enter the following formula:

=TEXT([Date],"ddd")

Important note: if you use comma as a decimal separator, replace the comma in the formula above with the semicolon. (=TEXT([Date];"ddd")). If you named your Date column different, then also insert your column name instead of "Date".

The return value should be one lline of text and we need to add the column to the default view. If you’re working in other than default view, please add the new column to that view also.

The Day of week formula

Now we have days of week in our view.

Days of week column added

 

Can I do the CEWP/JavaScript now?

Sure. Now let’s do the same magic as in previous articles of series. After inserting CEWP and simple "Hello world" alert script we should have the following result:

Hello world JavaScript  Hello world result

Let’s review what we’ll do: we’ll select the table that contains rows with dates. Then we’ll iterate through all the rows and check if they contain text Sat or Sun (because we’ve created and added a column with name of the day). If the row contains the text, we’ll add a special CSS class that we’ll define to the row. The CSS class will define red color of text and links in it. So now let’s get down to business.

First we need to get a hold of the table that contains the rows. A quick inspection with Developer tools in IE can help us there:

image

Even though the table has an ID that is pretty sure unique it is not universal enough (for example if we’d want to use the same script on another view or another list, the unique ID of the table wouldn’t suffice. But as we’ve already learned from previous articles, the class ms-listviewtable is unique enough (it appears only once in the page) and universal enough (it appears on all list views).

So we start by inserting the GetElementsByCssClass function from previous article in this series. Thanks to MJM I’ve updated this function a bit to take into consideration also the elements that have multiple CSS classes (for more details you can read comments to the previous article.

<script type="text/javascript">
function getElementsByCssClass(sTagName, sClassName) {
    var results = new Array();
    var allTagElements = document.getElementsByTagName(sTagName);
    for (i = 0; i < allTagElements.length; i++) {
        if(allTagElements[i].className.indexOf(sClassName) > -1) results.push(allTagElements[i]);
    }
    return results;
}
</script>


Because we’ll be adding a CSS class to the weekend rows we could just simply do object.className += " nameOfOurClass". But that may leave some trouble on objects that have no CSS class defined. That’s why we’ll construct a simple JavaScript function for adding CSS classes to HTML elements:

function addClass(obj, sClassName) {
	var classes;
	if(obj.className == undefined) classes = new Array();
	else classes = obj.className.split(" ");
	classes.push(sClassName);
	obj.className = classes.join(" ");
}

OK. We still can’t see any changes in the HTML but we have all the support functions we need. And now for the main function that does the trick. To not overexplain I’ve added comments in the function itself:

function highlightWeekends() {
	//Get the list view table
	var lvTable = getElementsByCssClass("table", "ms-listviewtable")[0];
	//get its rows
	var lvTableRows = lvTable.getElementsByTagName("tr");
	//iterate through rows (you can ignore first (header) row
	for (var i = 1; i < lvTableRows.length; i++) {
		//If the row's HTML contains "Sat" or "Sun"
		if(lvTableRows[i].innerHTML.indexOf("Sat") > -1 || lvTableRows[i].innerHTML.indexOf("Sun") > -1) {
			//add a class to the row
			addClass(lvTableRows[i], "redWeekendColor");
		}
	}
}

If we save the file we should be getting something by now, right? No. Because we’ve encapsulated the entire functionality in a function we need to call this function. So just after the last line of the function add

highlightWeekends();

This may come in handy if you need to manually call this script. (Say from URL for debugging purposes).

So now… Results? Still nothing. That’s because we’ve added a class called redWeekendColor, but we haven’t defined it anywhere. After the script block add the following code:

<style type="text/css">
	tr.redWeekendColor td,
	tr.redWeekendColor td a {
		color: red;
	}
</style>

Now we should see the result:

End result

The entire code for this solution is as follows:

<script type="text/javascript">
function getElementsByCssClass(sTagName, sClassName) {
    var results = new Array();
    var allTagElements = document.getElementsByTagName(sTagName);
    for (i = 0; i < allTagElements.length; i++) {
        if(allTagElements[i].className.indexOf(sClassName) > -1) results.push(allTagElements[i]);
    }
    return results;
}

function addClass(obj, sClassName) {
	var classes;
	if(obj.className == undefined) classes = new Array();
	else classes = obj.className.split(" ");
	classes.push(sClassName);
	obj.className = classes.join(" ");
}

function highlightWeekends() {
	//Get the list view table
	var lvTable = getElementsByCssClass("table", "ms-listviewtable")[0];
	//get its rows
	var lvTableRows = lvTable.getElementsByTagName("tr");
	//iterate through rows (you can ignore first (header) row
	for (var i = 1; i < lvTableRows.length; i++) {
		//If the row's HTML contains "Sat" or "Sun"
		if(lvTableRows[i].innerHTML.indexOf("Sat") > -1 || lvTableRows[i].innerHTML.indexOf("Sun") > -1) {
			//add a class to the row
			addClass(lvTableRows[i], "redWeekendColor");
		}
	}
}

highlightWeekends();
</script>
<style type="text/css">
	tr.redWeekendColor td,
	tr.redWeekendColor td a {
		color: red;
	}
</style>

At this point I’d just like to point out two important considerations: 1. we have to keep the day-of-week column name in the view and 2. we have to have scripts and css code embeded in any view we want this to work.

Hope your name doesn’t get highlighted too many times :)

Other articles from this series:

TOP