Saturday, October 29, 2011

DVWP (Data View Web Part) as a rotating banner : SharePoint 2010 & Jquery

Description: Data View Webpart modified to display images from the local image library, images are linked, url opens in the new window or parent window, Start Date and End Date are used to expire/activate banners, images are sorted by number specified in a custom column (Position).
Specs
: Public facing Publishing site on SharePoint 2010 Foundation, custom master page - I am using Heather Solomon's Publishing master, (simple) custom page layout with a webpart zone - check Randy Drisgill's branding post, custom css.



First thing to mention this set up will only work on the site where the image library list is located, very useful for home page banner.
There is no clip region in the banner rotator so make sure that your banner images are all the same size. 
Custom Image library does not have an approval workflow activated, you can add Versioning Settings in the library settings and then add additional filter in the Data View Webpart to display only Approved Items.


You will need SharePoint Designer and Nivo slider with default template (this is the first one that popped up in my search) download Free jquery plugin. 


  1. Create HomePageBannerImages image library with three custom columns:
    From Site Actions > More Options > Picture Library  > Create - Name it (HomePageBannerImages)
    From Settings in the image library select Create Column to create the following columns:
    LinkURL - Hyperlink or Picture, Require that this column contains information, Format Url as Hyperlink, Add to default view
    Position - Number, Require that this column contains information, Add to default view
    TargetWindow - Choice, Require that this column contains information, Type each choice ... :_parent _blankAdd to default view - you can always set choices as New Window, Same Window- easier for the end users- and then use conditional statements in xsl to render correct target for the url.
  2. Unzip Nivo Slider package and upload files to the folders, I've created CustomCss and js folders in Style Library/en-us/:
    js: jquery.nivo.slider.pack.js
    CustomCss: default.css (themes/default folder in nivo package) and nivo-slider.css
    Images folder: bullets.png, arrows.png and loading.gif (themes/default folder in nivo package)
    modify default.css file to point images to correct folder i.e: background:#fff url(/images/loading.gif) no-repeat 50% 50%;
  3. In Sharepoint Designer create new page layout copy/paste code below. What I have is very Simple Page Layout for the home Page:  Banner area (webpart zone), Content Editor and table with 3 webpart zones for various feeds.
    *Make sure you add link to jquery library in your master page
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js"></script>
     I am adding links to js slider and css files in the page layout simply because this will be the only page that will hold the banner
    <%@ Page language="C#"   Inherits="Microsoft.SharePoint.Publishing.PublishingLayoutPage,Microsoft.SharePoint.Publishing,Version=14.0.0.0,Culture=neutral,PublicKeyToken=71e9bce111e9429c" meta:progid="SharePoint.WebPartPage.Document" meta:webpartpageexpansion="full" %>
    <%@ Register Tagprefix="SharePointWebControls" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %> <%@ Register Tagprefix="WebPartPages" Namespace="Microsoft.SharePoint.WebPartPages" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %> <%@ Register Tagprefix="PublishingWebControls" Namespace="Microsoft.SharePoint.Publishing.WebControls" Assembly="Microsoft.SharePoint.Publishing, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %> <%@ Register Tagprefix="PublishingNavigation" Namespace="Microsoft.SharePoint.Publishing.Navigation" Assembly="Microsoft.SharePoint.Publishing, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
    <asp:Content ContentPlaceholderID="PlaceHolderAdditionalPageHead" runat="server">
    <script type="text/javascript" src="/Style Library/en-us/js/jquery.nivo.slider.pack.js"></script>
    <link rel="stylesheet" href="/Style Library/en-us/CustomCss/default.css" type="text/css" media="screen" />
    <link rel="stylesheet" href="/Style Library/en-us/CustomCss/nivo-slider.css" type="text/css" media="screen" />
    <style type="text/css">
    #slider a{
    display:block;
    }
    </style>
    <script type="text/javascript">
     $(window).load(function() {
            $('#slider').nivoSlider({
            effect: 'slideInLeft',
            animSpeed: 500,
            pauseTime: 5000,
            pauseOnHover: true
            });
        });
        </script>
    
    </asp:Content>
    
    <asp:Content ContentPlaceholderID="PlaceHolderPageTitle" runat="server">
     <SharePointWebControls:FieldValue id="PageTitle" FieldName="Title" runat="server"/>
    </asp:Content>
    
    <asp:Content ContentPlaceholderID="PlaceHolderMain" runat="server">
    <WebPartPages:SPProxyWebPartManager runat="server" id="spproxywebpartmanager"></WebPartPages:SPProxyWebPartManager>
    <div id="banner">
    <WebPartPages:WebPartZone id="g_C7F9DDBE501142A69EE4B39CF62A1A12" runat="server" title="Banner"><ZoneTemplate></ZoneTemplate></WebPartPages:WebPartZone>
    </div>
    <div id="Article">
    <PublishingWebControls:RichHtmlField FieldName="f55c4d88-1f2e-4ad9-aaa8-819af4ee7ee8" runat="server" AllowFontColorsMenu="False" AllowFontStandardColors="False" AllowFontThemeColors="False" AllowStandardFonts="False" AllowThemeFonts="False" MinimumEditHeight="400px"></PublishingWebControls:RichHtmlField>
    <table width="100%"> <tr><td valign="top" style="width:270px;">
    <WebPartPages:WebPartZone Title="left" runat="server" ID="left" CssClass="Blog"><ZoneTemplate></ZoneTemplate></WebPartPages:WebPartZone></td>
    <td valign="top" style="width:270px;">
    <WebPartPages:WebPartZone Title="center" runat="server" ID="center" CssClass="Events"><ZoneTemplate></ZoneTemplate></WebPartPages:WebPartZone></td>
    <td valign="top" style="width:270px;">
    <WebPartPages:WebPartZone Title="right" runat="server" ID="right" CssClass="Press"><ZoneTemplate></ZoneTemplate></WebPartPages:WebPartZone>
    </td></tr></table>
    </div>
    </asp:Content>
    

    Save page Layout, check in, publish and approve. Check the site settings and make sure the page layout is available in Page Layouts. Go to the page where you need your banner: Edit page and Apply newly created layout. Save the page.
  4. Open Site in Sharepoint Designer, Expand "All Files", expand "Pages" folder, I am modifying default.aspx file. Right click on the file and select "Detach From Page Layout", right click again and this time "Edit File in Advanced Mode"
  5. Click on "Split" to show Split view of the Design and Code (bottom of the editing area)
    in the design view locate Banner div and click inside the Banner div area.
  6. From the Ribbon > Insert Tab> In the Data Views & Forms Area > Select Data View > Empty Data View
  7. Select HomePageBannerImages from Document Libraries by clicking on "Select a data source"
  8. In the Data Source Details area select first item in the Rows, usually it is Name field and from the dropdown "Insert Selected Fields as" select "Multiple Items View".

    Now the fun stuff:
  9. From the Ribbon > Paging > All Items
  10. From the Ribbon > Sort & Group: add Position and Select Ascending
  11. From the Ribbon > Filter set filters as shown below (Less Than or Equal  AND  Greater Than or Equal to)
  12. In the WebPart Zone Tools Set Chrome Type to None
  13. In the WebPart Zone click on Properties and in the Data View Properties click on the XSL editor
  14. Replace all the fancy SP stuff with the following xsl:
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
        xmlns:ddwrt2="urn:frontpage:internal"
        xmlns:ddwrt="http://schemas.microsoft.com/WebParts/v2/DataView/runtime"
        exclude-result-prefixes="ddwrt2 ddwrt">
        <xsl:output method="html" indent="no"/>
        <xsl:param name="Today">CurrentDate</xsl:param>
        <xsl:template match="/">
            <div class="slider-wrapper theme-default">
                <div class="ribbon"></div>
                <div id="slider" class="nivoSlider">
                    <xsl:apply-templates select="*"/>
                </div>
                <div id="slideshow_btns"></div>
            </div>
        </xsl:template>
        <xsl:template match="Row">
            <a href="{@LinkURL}" target="{@TargetWindow}"><img border="0" src="{@FileRef}" alt="{@FileRef}"/></a>
        </xsl:template>
    </xsl:stylesheet>
    

Save the page, right click on the page name in Pages and reattach it to the page layout. check in and that's pretty much it.
now Add images to your image library and watch them rotate ... mesmerizing....
you can add more options to nivo slider add fancy transitions and tooltips (check documentation on their site) obviously you can do a lot more with Data View display but this is just simple and quick way to make a banner rotator.

Let me know if there are any issues with this or something is not clear/missing.

Replace default navigation indicators with image thumbnails



You will need to make 3 adjustments to your slider: add css classes for the images and css class to the slider, modify options for your script and edit xsl template to include rel attribute containing path to the thumbnail

  1. Add the following css to your default.css style sheet

    .theme-default.controlnav-thumbs .nivoSlider {
        margin-bottom:100px; /* Tweak this to push content down */
    }
    .theme-default.controlnav-thumbs .nivo-controlNav {
        position:absolute;
        left:0px;
        bottom:-80px; /* Tweak this to push thumbnails down */
        margin:0;
    }
    .theme-default.controlnav-thumbs .nivo-controlNav a {
        display:inline;
        background:none;
        text-indent:0px;
        border:0;
        margin-right:10px;
        float:none;
    }
    .theme-default.controlnav-thumbs .nivo-controlNav a.active img {
        -webkit-box-shadow: 0px 1px 5px 0px #4a4a4a;
        -moz-box-shadow: 0px 1px 5px 0px #4a4a4a;
        box-shadow: 0px 1px 5px 0px #4a4a4a;
    }
    .theme-default.controlnav-thumbs .nivo-controlNav img {
        display:inline;
        position:relative;
        margin-right:10px;
    }
  2. add Use thumbnails Control Nav and Use image rel for thumbs options to your script (last two options)

    <script type="text/javascript">
        $(window).load(function() {
            $('#slider').nivoSlider({
            effect: 'slideInLeft',
            animSpeed: 500,
            pauseTime: 5000,
            pauseOnHover: true,
            controlNavThumbs:true,
         controlNavThumbsFromRel:true
            });
        });
        </script>
    
  3. Add rel attribute to the banner image

    There are two options to pull in thumbnails for the slider:
    • Set up separate Picture library in the same subsite just for thumbnails, upload thumbs into this library, add extra column (Picture) to your Banner Picture library, add thumbs to your newly created column and add the field to the rel="{@ThumbnailImageRef}" in your xsl template.
    • Use Thumbnails auto-created by Sharepoint 

      I like the second option because SharePoint created everything I need:
      if your banner image in HomePageBannerImages library is ForeverGreen.jpg with /HomePageBannerImages/ForeverGreen.jpg path,  the path to thumbnail for this image will be /HomePageBannerImages/_t/ForeverGreen_jpg.jpg and it is pretty easy to construct xsl string to render the path, XPath Expression Builder helps a lot  - final result:

      rel="{concat(@FileDirRef,'/_t/', substring-before(@FileLeafRef,'.'),'_',substring-after(@FileLeafRef,'.'),'.',@FileType)}"
      now add the above to your image tag after alt="{@FileRef}"
      remove<div id="slideshow_btns"></div> this is no longer needed add controlnav-thumbs class to the slider-wrapper div
      your final xsl


      <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
          xmlns:ddwrt2="urn:frontpage:internal"
          xmlns:ddwrt="http://schemas.microsoft.com/WebParts/v2/DataView/runtime"
          exclude-result-prefixes="ddwrt2 ddwrt">
          <xsl:output method="html" indent="no"/>
       <xsl:param name="Today">CurrentDate</xsl:param>
          <xsl:template match="/">
              <div class="slider-wrapper theme-default controlnav-thumbs">
         <div class="ribbon"></div>
                  <div id="slider" class="nivoSlider">
          <xsl:apply-templates select="*"/>
         </div>
         
        </div>
              
          </xsl:template>
          
          <xsl:template match="Row">
              
                  <a href="{@LinkURL}" target="{@TargetWindow}"><img border="0" src="{@FileRef}" alt="{@FileRef}" rel="{concat(@FileDirRef,'/_t/', substring-before(@FileLeafRef,'.'),'_',substring-after(@FileLeafRef,'.'),'.',@FileType)}"/></a>
      
          </xsl:template>
      </xsl:stylesheet>