Tuesday, October 30, 2012

A Tiny cute SharePoint calendar

(Part I)



Have you noticed these cute month calendars that people sometimes put on the homepage of their Website?
Now, have you tried to drop a SharePoint month calendar on the home page of your SharePoint site? The result… not so cute: the calendar eats up half of the screen.
In this post I am going to show how with the help of CSS you can shrink your SharePoint calendar and make it fit in the right column of a SharePoint page. The picture shows you the expected result.
So let’s start by dropping on our right column a monthly view of the calendar and a hidden Content Editor Web Part.

 

In the source editor of the CEWP, paste the code below:
<style type="text/css">
/* Tiny Calendar */
/* Christophe@PathToSharePoint.com */
/* Remove week blocks */
.ms-cal-weekempty {display:none;}
.ms-cal-week {display:none;}
.ms-cal-weekB {display:none;}
.ms-cal-weekB {display:none;}
/* Shrink cells */
.ms-cal-workitem2B {display:none;}
.ms-cal-noworkitem2B {display:none;}
.ms-cal-nodataBtm2 {display:none;}
.ms-cal-todayitem2B {display:none;}
.ms-cal-workitem {font-size:0px;}
.ms-cal-muworkitem {font-size:0px;}
.ms-cal-noworkitem {font-size:0px;}
.ms-cal-nodataMid {font-size:0px;}
.ms-cal-todayitem {font-size:0px;}
/* thin out header */
.ms-cal-nav {display:none;}
.ms-cal-nav-buttonsltr {display:none;}
.ms-cal-navheader {padding:0px;spacing:0px;}
.ms-calheader IMG {width:15px;}
/* Abbreviate weekdays */
.ms-cal-weekday {letter-spacing:6px; width:22px; overflow: hidden;}
</style>
What this CSS does:

height:
- Reduce the height of the calendar cells
- Reduce the height of the header

width:
- Only keep the first letter of the weekday names
- Simplify the header options to just keep previous and next month
- Reduce the “bone” that forces the width of the header
- Remove the week boxes to the left of the calendar

Note that if you click on a day, SharePoint will open a full size day view of your calendar – I have chosen to keep this as the expected behavior. If you don’t like it you can simply deactivate the JavaScript that triggers the day view.
We now have our cute calendar that tells us that today is October 6 and that October 28th is a Tuesday.
The next step is to display the list items, so that I know for example that Halloween is on October 31st. This will be the object of part II. Of course, we’ll have to accept some constraints because of the reduced size of the calendar.
Update [Feb 6, 2009]: several people asked about the bottom border. To get it, in the Web Part settings select:
Appearance | Chrome type | border only.
Update [Jan 22, 2009]: the above stylesheet is for SharePoint 2007. For SharePoint 2003, you can try this:
<style type="text/css">
/* Tiny Calendar - SharePoint 2003 */
/* Christophe@PathToSharePoint.com */
.ms-calMid {height:0px;}
.ms-CalSpacer {height:0px;}
.ms-calhead {padding:0px;spacing:0px;}
</style>

(Part II)

October 11, 2008 in Content Editor Web Part, SharePoint 2007, Styles/CSS


In part I, we saw how to adjust the size of an empty SharePoint month calendar to fit in the right column of our home page. Now our next step is to display the events.
As you can expect, the default display will be too big for our tiny calendar. So here are two tricks to work around this issue.
Method 1: no title display
In SharePoint 2007, you can choose which column to display in the month view. So let’s create an additional column:
- name: “Display”
- required: yes
- default value: “*”
In the view settings, choose [Display] as month view title. The result: for each event, SharePoint will display a simple “*” that will fit into the day cell.
This works fine, but the user has to click on the item to actually see the event. This may be an issue, especially if several events happen on the same day.
Method 2: shrink the title
So another option is to keep the title and use some CSS magic. Here is the deal: a title will be displayed in small fonts by default (unreadable), but will get back to normal size when the user hovers over it (see the screenshot at the beginning of this post).
To achieve this we’ll just add a few rules to the CSS from part I:
<style type="text/css">
/* Tiny Calendar */
/* Christophe@PathToSharePoint.com */
/* Remove week blocks */
.ms-cal-weekempty {display:none;}
.ms-cal-week {display:none;}
.ms-cal-weekB {display:none;}
.ms-cal-weekB {display:none;}
/* Shrink cells */
.ms-cal-workitem2B {display:none;}
.ms-cal-noworkitem2B {display:none;}
.ms-cal-nodataBtm2 {display:none;}
.ms-cal-todayitem2B {display:none;}
.ms-cal-workitem {font-size:0px;}
.ms-cal-muworkitem {font-size:0px;}
.ms-cal-noworkitem {font-size:0px;}
.ms-cal-nodataMid {font-size:0px;}
.ms-cal-todayitem {font-size:0px;}
/* thin out header */
.ms-cal-nav {display:none;}
.ms-cal-nav-buttonsltr {display:none;}
.ms-cal-navheader {padding:0px;spacing:0px;}
.ms-calheader IMG {width:15px;}
/* Abbreviate weekdays */
.ms-cal-weekday {letter-spacing:6px; width:22px; overflow: hidden;}
/* events display */
.ms-cal-defaultbgcolor {padding:0;}
.ms-cal-defaultbgcolor a {font-size:3px;}
.ms-cal-monthitem a {font-size:3px;}
.ms-cal-monthitem a:hover {font-size:10px;}
</style>
This second method is more user-friendly, if your titles are not too long.
There are of course many variations around these two methods, here are for example some other text adjustments you can use:
http://www.w3schools.com/Css/css_text.asp
And remember: all of this was done using CSS only, no harm was done to the structure itself. The SharePoint calendar remains fully operational (recurring events, alerts, filters, etc.).

Friday, October 26, 2012

Apply colour coding to your SharePoint lists

Color coding is very useful to highlight key items in a list. For example in an issues list, you may want to draw the users’ attention on items with high priority.
In the picture below, I have aggregated 4 different ways to do it:


This customization was entirely done through the SharePoint UI. Let’s see how.


The method
I am simply going to apply my post about using calculated columns to write HTML. For each example, we need to figure out the formula that will create the HTML string. Then the script, included in a CEWP, will make it behave as real HTML.

The formulas
In my example, I am applying color coding based on the priority of each issue: red for high, yellow for normal and green for low. Note that the formulas below were built for an issues list, formulas for other lists or libraries may be slightly different.
So here we go, please refer to the above picture to see the result:
- Traffic light (actually a big bullet!):
=”<DIV style=’font-weight:bold; font-size:24px; color:”&CHOOSE(RIGHT(LEFT(Priority,2),1),”red”,”orange”,”green”)&”;’>•</DIV>”
ALSO, instead of CHOOSE you can use IF statements. For example:
IF( [status]=”open”, “red”, IF([status]=”in progress”, “orange”, “green”))
- Indicator (reusing the default SharePoint KPI images):
=”<DIV><IMG src=’/_layouts/images/KPIDefault-”&(3-RIGHT(LEFT(Priority,2),1))&”.gif’ /></DIV>”
- Font color:
=”<DIV style=’font-weight:bold; font-size:12px; color:”&CHOOSE(RIGHT(LEFT(Priority,2),1),”red”,”orange”,”green”)&”;’>”&Priority&”</DIV>”
- Background color:
=”<DIV style=’font-size:12px; background-color:”&CHOOSE(RIGHT(LEFT(Priority,2),1),”red”,”orange”,”green”)&”;’>”&Priority&”</DIV>”
Simply paste your preferred formula in a calculated column, add the script on the Web page as explained here, and voila!

Tuesday, October 16, 2012

SharePoint Calculated Columns :: Using calculated columns to write HTML.. by Christophe (Reposted)

Updates
I am now expanding the scope of this method:
- list views (flat views and expanded grouping): this article
- list views (collapsed grouping): this article
- display forms (DispForm.aspx): published on 10/01/2008
- calendar views: published on 11/15/2008
- using calculated columns to write scripts: published on 2/26/2009
- preview panes: not published yet
- filters: not published yet
Also note the troubleshooting section.
Update [09/10/2008]


I have added a few lines to the initial script to address the case of collapsed views. Also, see my note at the end of this post.
Your feedback is important to me. Big thanks to Fernando, Jeff and the others who reported the limitations of the initial version!
A technical note: considering that 1/ the script is generic and 2/ it may still evolve in the future, a good practice is to store it in a separate text file on your site. You can then link to it from any Content Editor Web Part by using the “Content link” box.
I have already introduced calculated columns in a previous post.
One of their limitations is that the output is just text. Sometimes your browser will be smart enough to interpret the text as a hyperlink – when you calculate an e-mail address or a URL for example. Nevertheless in this case the display is usually not user-friendly. This will never allow you to get what a “Hyperlink or Picture” column does, for example.
To extend the possibilities of calculated columns, my idea is to use them to write HTML instead of just text, thus allowing some additional formatting. In this post I am going to show how to achieve this result through a generic method, combining calculated columns and the Content Editor Web Part.
Let’s start with a simple example based on a contacts list (I’ll provide more advanced examples in my next posts). For each team member, I store the first name, last name and job title. On my site home page, I want to display the list of contacts as “First name Last name”, and display the managers’ name in bold. It would look like the first column below:

A calculated column will easily give me the display name:
=CONCATENATE([First Name],” “,[Last Name])
But I have no option in the SharePoint UI to highlight the managers’ name.
So let’s apply my idea, and use calculated columns to write HTML instead of simple text.
The initial formula becomes:
=CONCATENATE(”<DIV>”,[First Name],” “,[Last Name],”</DIV>”)
I can now add my condition: if the job title contains the word “manager”, add bold style. In SharePoint, this translates as:
IF(ISERROR(SEARCH(”manager”,[Job Title],1)),”style=’font-weight:bold;’”,” “)
So here is my complete formula:
=CONCATENATE(”<DIV”,IF(ISERROR(SEARCH(”manager”,[Job Title],1)),” “,” style=’font-weight:bold;’”),”>”,[First Name],” “,[Last Name],”</DIV>”)
Let’s take a look at our list:

We now have the correct HTML…except that SharePoint is displaying it as simple text. We need to add a short script to change it into HTML.
So let’s add a CEWP to the bottom of our Web Page (how?), and paste the following script in the source editor:
view plaincopy to clipboardprint?

<script type="text/javascript">  

// 

// Text to HTML 

// Feedback and questions: Christophe@PathToSharePoint.com 

// 

var theTDs = document.getElementsByTagName("TD");  

var i=0;  

var TDContent = " ";  

while (i < theTDs.length) {  

try {  

TDContent = theTDs[i].innerText || theTDs[i].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[j].innerText || theTBODYTDs[j].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);  

}  

</script> 

<script type="text/javascript">
//
// Text to HTML
// Feedback and questions: Christophe@PathToSharePoint.com
//
var theTDs = document.getElementsByTagName("TD");
var i=0;
var TDContent = " ";
while (i < theTDs.length) {
try {
TDContent = theTDs[i].innerText || theTDs[i].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[j].innerText || theTBODYTDs[j].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);
}
</script>


Now the browser displays the strings as HTML, and my list looks like the initial screenshot at the top of the page!
A couple notes:
- The script identifies the to-be HTML by the opening tag <DIV and the closing tag </DIV>.
- I have tested the script in Internet Explorer and Firefox.
- Remember to drop the CEWP after all the views you want to change. You can for example put it at the bottom of the page.
In my next posts, I’ll show various examples involving styles, pictures and links. If you have a specific issue, feel free to submit it!
How about the Data View Web Part?
Of course such customizations could also be done through the DVWP. I am not going to detail this here, feel free to contact me for specific questions.
As I already mentioned, if I can reach the same result with either the CEWP or the DVWP, I’ll favor the CEWP as 1/it is a safer approach 2/the changes can easierly be undone and 3/it doesn’t require SharePoint Designer.
A note for the SharePoint experts
On SharePoint pages, scripts can be called by a function named “_spBodyOnLoadFunctionNames”. This allows for a timely execution of the script, on page load.
In this case, I am not using it, as we want the script to run before the page can be viewed by the users. Are there any side effects of not using _spBodyOnLoadFunctionNames? Advice on this is welcome!
For more examples using this method, see the “Calculated Columns” category.
I would be especially interested in your feedback if you have tested the script in one of the following situations:
- browser other than IE or Firefox on Windows
- non-Windows environment
- scalability (long lists, use across multiple lists)
- specific use cases, with formulas you have written yourself
- coexistence with other code or customizations (DVWP, etc.)
Feel free to leave a comment or contact me: Christophe@PathToSharePoint.com

Wednesday, October 10, 2012

SharePoint Calendar Colourification

One of the ways we use SharePoint is to track events and their status, "Completed", "Pending", or "Rescheduled". It's a pretty common use of SharePoint and depending on how it's put into practice you can simply filter out events that you don't want to see. For example, if you wanted to see only the events that were "Pending" displayed on a calendar, you simply had to filter out events that "do not contain" = "Pending" and presto!


Here's where it gets (got) challenging: The users of this system wanted to display all events, regardless of status, but wanted them colour coded based on their status. Sounds easy enough, but SharePoint doesn't provide a way to do it so I had to figure it out.
After pounding on Google for about an hour and following links to pages that were asking me to pay for a solution that "might" be what I was looking for, I was about to call it quits and tell them that we'll just have to have separate calendars for each status. Then I found that tiny gold nugget I was looking for!
This site described how to include dynamic HTML code into a calculated column. In itself that's not a challenging task, the problem is that SharePoint displays the HTML in the calculated column as text and doesn't execute it as a part of the page. Thankfully, that same page described how to translate displayed HTML into executed HTML using a bit of JavaScript called "innerText" and "innerHTML".


This was a great breakthrough, except that it only applied to the list view, not the calendar view. I decided that it was time to dust off my old dev skills and hack the code up to make it do what I wanted it to do and here's what I came up with.


Calculated Column code: (cleaned up on 14 November 2008)
=CONCATENATE(" <nobr title='",[Status],": ",[Short Description],"' style='font-weight:lighter;color:",IF(ISERROR(SEARCH("Completed",Status,1)),(IF(ISERROR(SEARCH("Pending",Status,1)),(IF(ISERROR(SEARCH("Rescheduled",Status,1)),,"blue")),"red")),"green"),"'> #",[Title],"</nobr><tag>")
Yes, I know it looks like a lot of garble-dy-gook and I'm sorry for that.


Everything you see that is between the square brackets is a column from my list that I want to use in building the HTML. You'll need to change these to match your list.
The most confusing part of this is easily the "IF(ISERROR(..." block. I'll try to clear that up here using standard code formatting instead of the single line of text. The core functionality revolves around this line:

IF(ISERROR(SEARCH("variable", [Column],1)), false, true)

The "variable" - the value you're trying to find. [Column] - the column that you're looking in. false - what to do if the "variable" isn't found in the [Column]. This can be an output string or more code. true - what to do if the "variable" is found.
If you're like me, you may need a bit of a visual clue to help understand this:

 


SharePoint makes you put it all in one line like Excel. It basically creates the HTML that needs to get translated from displayed code to executed code.
This part is where the magic happens. The original JavaScript code was designed to work on the List view in SharePoint, but I needed it to work on the Calendar view. Here's the code I used: (updated 14 November 2008)
<script type="text/javascript">
var theTags = document.getElementsByTagName("A");
var i=0;
while (i < theTags.length)
{
try
{
TagContent = theTags[i].innerText || theTags[i].textContent;
if (TagContent.indexOf("<tag>") >= 0)
{
theTags[i].innerHTML = TagContent;
}
}
catch(err){}
i=i+1;
}
</script>
This bit of JavaScript is placed into a Content Editor Web Part and placed below the Calendar.
Freely I have received this code, and freely I give it away. If you'd like help hacking this up to make it work on your SharePoint site just drop me an email and I'll help where I can.