Living a SharePoint life

Thursday, August 22, 2013

Adding a calendar icon to a Content Query Web Part

I was working on a project the other day, when I stumbled upon this webpage with a nice little calendar done completely in CSS. So I was wondering if it would be possible to create an events list from this:



to this:




Before we start, you must be sure, that you are able to add CSS to your master page. If you don’t know what I’m talking about, you can check out a blog post of mine (In German). This step is mandatory, otherwise it will not work. You can also crawl the web for blog posts on this subject.

In the first step we need a calendar list somewhere in our Site collection. It really doesn’t matter where you create it, because we can use the Content Query Web Part (CQWP) to collect all events in event lists in the entire Site collection. For development purpose and to keep it simple, I recommend you create the list in the same site where the CQWP will be located later.

The second step will be to create the CQWP itself. You will need the publishing features in the site and site collection turned on. Otherwise the CQWP will be not available in the selection. Beside of that, I assume you have knowledge on how to configure the CQWP. Therefor I will not cover this subject here.

The new Content Query Web Part Style


After adding the CQWP to your page, we’ll start to modify the settings. Go to the following list and download the ItemStyle.xsl file:
http://<SiteCollection>/Style%20Library/XSL%20Style%20Sheets/ItemStyle.xsl
When you’re finished with downloading, open the XSL file and look for the following section:
<xsl:template name=”HiddenSlots” match=”Row[@Style=’HiddenSlots’]” />
Above that section you copy & paste the following piece of XSL:
<xsl:template name="EventsCalender" match="Row[@Style='EventsCalender']" mode="itemstyle">
    <xsl:variable name="dateTime" select="ddwrt:FormatDate(string(@EventDate), 1033, 3)" />
    <xsl:variable name="dateTimeCondensed" select="ddwrt:FormatDate(string(@EventDate), 1033, 2)" />
    <xsl:variable name="date"  select="substring-before(substring-after($dateTime, ', '), ', ')" />
    <xsl:variable name="month" select="substring-before($date, ' ')" />
    <xsl:variable name="shortMonth" select="substring($month, 1, 3)" />
 <xsl:variable name="day"   select="substring-after($date, ' ')" />
    <xsl:variable name="time"  select="substring-after($dateTimeCondensed, ' ')" />
 <xsl:variable name="SafeLinkUrl">
      <xsl:call-template name="OuterTemplate.GetSafeLink">
        <xsl:with-param name="UrlColumnName" select="'LinkUrl'"/>
      </xsl:call-template>
    </xsl:variable>
 <xsl:variable name="DisplayTitle">
  <xsl:call-template name="OuterTemplate.GetTitle">
   <xsl:with-param name="Title" select="@Title"/>
   <xsl:with-param name="UrlColumnName" select="'LinkUrl'"/>
  </xsl:call-template>
    </xsl:variable>
    <div class="item link-item">
  <div class="description calendar">
   <div class="calendarIcon">
    <xsl:value-of select="$day" />
    <em>
     <xsl:value-of select="$shortMonth" />
    </em>
   </div>
   <div class="Information">
    <xsl:call-template name="OuterTemplate.CallPresenceStatusIconTemplate"/>
    <div class="title">
     <a href="{$SafeLinkUrl}" title="{@LinkToolTip}">
      <xsl:if test="$ItemsHaveStreams = 'True'">
       <xsl:attribute name="onclick">
        <xsl:value-of select="@OnClickForWebRendering"/>
       </xsl:attribute>
      </xsl:if>
      <xsl:if test="$ItemsHaveStreams != 'True' and @OpenInNewWindow = 'True'">
       <xsl:attribute name="onclick">
        <xsl:value-of disable-output-escaping="yes" select="$OnClickTargetAttribute"/>
       </xsl:attribute>
      </xsl:if>
      <xsl:value-of select="$DisplayTitle"/>
     </a>
    </div>
    <div class="location">
     <xsl:value-of select="@Location" />
    </div>
    <div class="time">
     <xsl:value-of select="$time" />
    </div>
   </div>
  </div>
 </div>
  </xsl:template>
You must be sure to add the following style sheet to your ItemStyle.xsl file. If you don’t, the modification will brick your CQWP.
xmlns:ddwrt=”http://schemas.microsoft.com/WebParts/v2/DataView/runtime”

Making the calendar standout


Now that we have a new style in place, we must make it look more like a calendar. Therefor we’ll add some CSS to our page. Open your CSS file and paste these styles to it:
.calendarIcon{
 margin:.25em 10px 10px 0;
 padding-top:5px;
 float:left;
 width:50px;
 background:#ededef;
 background: -webkit-gradient(linear, left top, left bottom, from(#ededef), to(#ccc)); 
 background: -moz-linear-gradient(top,  #ededef,  #ccc); 
 font:bold 20px/40px Arial Black, Arial, Helvetica, sans-serif;
 text-align:center;
 color:#000;
 text-shadow:#fff 0 1px 0; 
 -moz-border-radius:3px;
 -webkit-border-radius:3px;
 border-radius:3px; 
 position:relative;
 -moz-box-shadow:0 2px 2px #888;
 -webkit-box-shadow:0 2px 2px #888;
 box-shadow:0 2px 2px #888;
 }
.calendarIcon em{
 display:block;
 font:normal bold 10px/20px Arial, Helvetica, sans-serif;
 text-transform:uppercase;
 color:#fff;
 text-shadow:#00365a 0 -1px 0; 
 background:#04599a;
 background:-webkit-gradient(linear, left top, left bottom, from(#145866), to(#2190a6)); 
 background:-moz-linear-gradient(top,  #145866,  #2190a6); 
 -moz-border-radius-bottomright:3px;
 -webkit-border-bottom-right-radius:3px; 
 border-bottom-right-radius:3px;
 -moz-border-radius-bottomleft:3px;
 -webkit-border-bottom-left-radius:3px; 
 border-bottom-left-radius:3px; 
 border-top:1px solid #00365a;
 } 
.calendarIcon:before, .calendarIcon:after{
 content:'';
 float:left;
 position:absolute;
 top:4px; 
 width:6px;
 height:6px;
 background:#111;
 z-index:1;
 -moz-border-radius:10px;
 -webkit-border-radius:10px;
 border-radius:10px;
 -moz-box-shadow:0 1px 1px #fff;
 -webkit-box-shadow:0 1px 1px #fff;
 box-shadow:0 1px 1px #fff;
 }
.calendarIcon:before{left:7px;} 
.calendarIcon:after{right:7px;} 
.calendarIcon em:before, .calendarIcon em:after{
 content:'';
 float:left;
 position:absolute;
 top:-3px; 
 width:2px;
 height:10px;
 background:#dadada;
 background:-webkit-gradient(linear, left top, left bottom, from(#f1f1f1), to(#aaa)); 
 background:-moz-linear-gradient(top,  #f1f1f1,  #aaa); 
 z-index:2;
 -moz-border-radius:2px;
 -webkit-border-radius:2px;
 border-radius:2px;
 }
.calendarIcon em:before{left:9px;} 
.calendarIcon em:after{right:9px;}
Save all our files back to SharePoint and don’t forget to publish them, too. If you’ve done everything right, you can select the new created style in the CQWP settings and admire your new good looking calendar list on your page.


7 comments:

  1. Hi,

    Wonderful post! Thanks for Sharing.

    I am trying to display the time according to their local but by the above code it is displaying the time based on the server.

    I have tried searching for a solution but nothing has worked so far…..can you help me?

    Thanks in Advance,
    Sadana

    ReplyDelete
  2. That isn't so easy. The CQWP is rendering the html on the server before the content is submitted to the browser. Therefor you would need some kind of JS to calc the delta of your users timezone (What I consider kind of messy). Maybe you'l find some more information here:
    https://autosponge.wordpress.com/2008/05/09/ddwrt-formatdate-and-formatdatetime/
    Good luck

    ReplyDelete
  3. Thanks .....this worked perfectly for me on my project!!!

    ReplyDelete
    Replies
    1. Your welcome. Nice to hear that the calendar is used on other SharePoint sites.

      Delete
  4. Hi Hagen

    I followed all your steps but, I get a "Unable to display this Web Part" error.

    Any advise?

    ReplyDelete
    Replies
    1. Unfortunately the description of the error does give a hint about the problem. The CQWP can be tricky when the XML isn't correct. My best guess would be to double check the XML. When redoing the steps, upload the changes after every step. That way you can see when it breaks.

      Delete
    2. Btw if you are already on Office 365 consider to use the modern pages and Office PnP

      Delete

Featured Post

The Retro Powershell - Looking good in 8-Bit | Part 1

I wrote a little script that, when placed in your PowerShell Profile, will print a message similar to the old boot message you got from you...