13 March 2015

Display Templates: Slider

In this blogpost I will explain how to create a slider in SharePoint using Display Templates. The slider will cover the entire screen width. To do this, I will use the Revolution Slider in Unify. It is a beautiful, responsive slider, which makes it suitable for mobile devices without any extra effort. Unify is based on Bootstrap, which is a widely used, responsive platform. I would definitely recommend it.

We will base the slider on the Search Results Web Part. Because we want the slider to cover the entire width of our screen, we have to create a custom Page Layout for it as well. The slider will eventually look like this:



Start

The first step is downloading the Starter Display Templates, which you can find in my other blogpost. Save the files and give them a representative name. In case of our slider it could be something like 'SliderControl' and 'SliderItem'.

Upload the Display Templates (via the browser) to Display Templates -> Search, inside the Masterpage Gallery (Site Settings -> Web Designer Galleries -> Master pages and page layouts). When you uploaded the files, you will see JS files being generated with the same name. If not, something went wrong.

You could also use the 'New' button in the Display Templates folder to create new Display Templates. You should see the options 'Control Display Template' and 'Item Display Template' in the dropdown menu.

Now is a good time to map the Masterpage Library (if you have not done that already, read here how to do that). You can now use Explorer to open the Display Templates and directly edit them in Notepad++ or any other editor.

Next step is to create a Pictures Library in SharePoint. Give it a name without spaces! This is very important, because SharePoint does not like spaces, so if it finds spaces in the url, it will not work. Upload some images to the library. Keep in mind that the slider will have a fixed height, but a flexible width. The size of the images should be small in height and very very wide in width. Do also fill in the Title and Description fields, we will also use those in the slider.

Page Layout

The slider will be flexible in width, but always the same width as your screen. To achieve that, we have to adjust the markup (HTML) on the page. We are going to create an 80% width page, but the slider will cover full width.

First, create a new Page Layout. You can do that by copying an existing one, but you can also navigate to the Masterpage Library using the browser (~/_catalogs/masterpage/Forms/AllItems.aspx) and select the arrow next to New Document. A list will appear, which contains a Page Layout option.
Another option is to navigate to the Design Manager and create a Page Layout in there. I usually do the latter myself.

Add the code below to the <!--MS:<asp:ContentPLaceHolder id="PlaceHolderAdditionalPageHead" runat="server">--> of the Page Layout (all the way on the bottom, right before the closing tag): <!--MS:<style type="text/css">-->
/* The default contentBOx has margins. We don't want that, because our slider should cover the entire width of the page. So... We remove the margins here. */
#contentBox {
margin: 0;
}

/* The sidenav is now on top of the slider. We would like to push it below the slider, next to the rest of the content. If we don't, the sidenav will push the slider down which is not very pretty. */
#sideNavBox {
position:relative;
top:500px;
}

/* Because of the slider being flexible, it will shrink when your screen resolution gets smaller. We use mediaqueries to adjust the relative distance between the sidenav and the slider when it shrinks. In case of IE, this will only work in version 9 and up. */
@media screen and (max-width: 1024px) {
#sideNavBox {
top:450px;
}
}

@media screen and (max-width: 880px) {
#sideNavBox {
top:450px;
}
}

@media screen and (max-width: 730px) {
#sideNavBox {
top:450px;
}
}

/* It is quite likely that you want to add more content to the page than just the slider. The contentPositioner positions a <div> on a distance of 220px (sidenav width) from the left and 15px from the top. */
.contentPositioner {
margin: 0 auto 0 220px;
padding-top: 15px;
}

/* Below are three Web Part zones, two narrower and a wider one. */
.wpzLeft {
float: left;
width:25%;
margin:0 2% 0 0;
}

.wpzCenter {
float: left;
width: 46%;
}

.wpzRight {
float: left;
width: 25%;
margin: 0 0 0 2%;
}
<!--ME:</style>-->

It is 'best practise' not to use inline CSS code, so usually you should put the styling of Page Layouts inside the your common custom CSS file which you call in the of a custom MasterPage or in the Additional CSS settings. Right now, I put the CSS in like this, because I want to focus on this specific page, without considering the hassle around it. Inside the CSS file I used comments to describe what every sentence does, in case you would be interested ☺

The next step is to add the HTML to the page layout. You can download it here.
Replace all code inside the <!--MS:<asp:ContentPlaceHolder id="PlaceHolderMain" runat="server">--> tag, except the Title snippet. In this code the Web Part zones are present already. All Web Part zones have their own ID. It might cause problems on your SharePoint site. If it does, you should generate your own IDs using the Snippet Tool (Design Manager) or SharePoint Designer.

Last but not least, you have to set the Page Layout to the desired page. You can do that by navigating to the page, click the PAGE tab in the ribbon and click the Page Layout button. You should be able to select your custom Page Layout here, but only if you published it first.

Web Part

To be able to see the results of the changes we will make in de the Display Templates, we will first have to create the Web Part itself. As I previously mentioned, we will use the Search Results Web Part.

  1. Navigate to the page where you want to place the slider.
  2. Add a Web Part to the Slider Zone.
  3. Choose the Search Results Web Part and click Add.
  4. The next step is to build a query to load the right data into the Web Part.
  5. Navigate to the Edit Web Part menu (see the arrow on the top right of the web part).
  6. Click the Change Query button.
  7. In the Basics tab (make sure Quick mode is activated, you can verify by the link on the top right of the tab-page Switch to Advanced Mode/Switch to Quick Mode) you see Select a query, choose Pictures (System).
  8. Next, you see Restrict by app, choose Specify a URL and provide the url to the Pictures library you created earlier.
  9. Restrict by tag should remain to Don't restrict by any tag.
  10. Click OK.
  11. Click Apply in the Web Part menu (do not click OK yet!).
  12. What you see now, probably does not impress you very much yet, but you should be able to see some content of the Pictures library now. Do not close the Web Part edit menu yet, because we are going to set the right Display Templates now.
  13. Click the + next to Display Templates.
  14. First, you will see a dropdown menu Results Control Display Template. In the dropdown menu you should find your own Control Display Template now, which you created earlier. Select it. (Don't see it? Did you publish?)
  15. Next are two radiobuttons. Select the second one which says: Use a single template to display items.
  16. Below this radiobutton there is another dropdown menu. You should find your own Item Display Template here. Select it.
  17. Close the + next to Display Templates.
  18. The Display Templates are set now, but we have to change a few other settings as well. These settings display some settings for users (like sorting and other stuff like that) in the Web Part which we don't want to see in a slider. So, we will disable them.
  19. Click the + next to Settings.
  20. Uncheck all checkboxes, accept Show ranked results (if we'd turn that one off as well, there will be no data in the Web Part at all).
  21. The number you see below Number of results per page doesn't matter, jQuery is going to take care of that, so you can leave it as it is.
  22. Close the + next to Settings.
  23. By default, SharePoint shows a titlebar, which we naturally don't want to see in a slider. So let's turn that off as well.
  24. Click the + next to Appearance.
  25. At the bottom you can see the Chrome Type setting, with (again) a dropdown menu. Select None in the dropdown.
  26. For the elegance, you can set the title to give your slider a name. The name will not be visible, because we just turned the titlebar off.

Well, that's all concerning the Web Part itself and its settings. It still does not look like a slider at all, so let's quickly start working on the Display Templates.

Display Templates

Like I mentioned in my previous blogpost, Display Templates work in sets, one as a wrapper for the whole thing (Control Display Template) and the second as a wrapper for individual items (Item Display Template). Let's start with the first one.

Control Display Template

The Control Display Template doesn't only hold the markup (HTML) for the Web Part, it also holds the references to all necessary CSS and JavaScript files. The latter is what we start with. You can download the necessary files below (upload them to the desired place in SharePoint):

First, we will limit the slider to a maximum height of 400px, everywhere below that amount, it will remain flexible. Open the file 'plugins.css'. On line 76 you will find the selector '.revolution-mch-1:after'. Add the line 'max-height:400px;' to it and save.

Open your Control Display Template in Notepad++ (or any other editor) en replace everything in between the <script> tags by the code below:
$includeScript(this.url, "~sitecollection/[Path to file]/jquery.min.js");
$includeCSS(this.url, "~sitecollection/[Path to file]/style.css");
$includeCSS(this.url, "~sitecollection/[Path to file]/settings.css");

There is also a fallback for older IE browsers, you should add that after the </script> tag:
<!--[if lt IE 9]>
<script>
$includeCSS(this.url, "~sitecollection/[Path to file]/settings-ie8.css");
</script>
<![endif]-->

There is a catch here though. Inside 'style.css' a few other CSS files are called through the @import method. Those CSS files are inside the same folder, so the path is just the filename. Somehow, SharePoint sometimes interprets the paths relative to the site root instead of the folder they are actually in. Therefore you might have to specify the full url in the @import links.
Beside this, I have another problem on one of my SPO environments. When I navigate around the site and return to the slider page (look at it as refreshing the page without a server refresh, F5 instead of CTRL + F5), the additional CSS files, which should be loaded through the @import method, are not loaded at all. If you run into this problem as well, you can solve it by calling the plugins.css the same way as style.css.
Personally I experienced this problam randomly, have no clue why it sometimes occurs... So if you happen to know, please tell me!

The next step is loading and using the Javascript for the slider itself. You should add the code below in between the <!--#_ and _#--> tags and after the line var siteURL = SP.PageContextInfo.get_siteAbsoluteUrl();:
AddPostRenderCallback(ctx, function() {
$.getScript(siteURL + "/[Path to file]/jquery.themepunch.revolution.min.js", function(){
$.getScript(siteURL + "/[Path to file]/jquery.themepunch.tools.min.js", function(){
$.getScript(siteURL + "/[Path to file]/revolution-slider.js", function(){
jQuery(document).ready(function() {
RevolutionSlider.initRSfullWidth();
});
});
});
});
});

To make sure our slider works correctly, we have to load the JavaScript files in a certain order. By default, files are loaded asynchronously inside the Display Templates. If you use jQuery however, jQuery itself must be loaded before any JS files which depend on jQuery, elseways you will get a 'jQuery is undefined' error. Also, by navigating your site without a server refresh, some JS files may not be loaded, which makes the slider break.
In the code above, we nest functions which forces the JS files to load in a specific order.

Now we've loaded and activates everything we need in order to make the slider work. Now we have to build the slider itself, the markup (HTML) that is. First, add a class 'RevolutionSlider' to the first <div> (it is right above the code with which we just loaded the external files). Next, replace all HTML from the <div> with CSS class 'container' by the code below:
<div class="tp-banner-container">
<div class="tp-banner">
<ul>

</ul>
<div class="tp-bannertimer tp-bottom"></div>
</div>
</div>

Note: Don not remove the most outer div! It will no longer work if you do.

The final step is a small line of code which tells the Cotrol Display Template where to render the Item Display Template. Add this line of code in between the <ul> tags:
_#= ctx.RenderItems(ctx) =#_

To top it all off you should give the Control Display Template a name, add it inside the <title> tag. That's all for the Control Display Template. Let's now move on to the Item Display Template.

Item Display Template

The first thing to do in the Item Display Template is to tell it which SharePoint columns we want to get. That's what the <mso:ManagedPropertyMapping msdt:dt="string"> tag does. You can see that it already contains some values, but we need to add one more: The Image. Add the code below to the ManagedPropertyMapping tag:
‘PictureURL’:’ PictureURL’ Make sure that each set is separated by a comma.

Next we have to connect the 'PictureURL' column to a JavaScript variable. You can do that by adding the code below in between the <!--#_ and _#--> tags and after the line 'var siteURL = SP.PageContextInfo.get_siteAbsoluteUrl();':
var pictureURL = $getItemValue(ctx, "PictureURL");

Finally we have to add the HTML that we want to render in every item. Replace all HTML from the <div> with CSS class 'item' with the code below:

<li class="revolution-mch-1" data-transition="fade" data-slotamount="5" data-masterspeed="1000" data-title="_#= $htmlEncode(title) =#_">
<img src="_#= pictureURL =#_" alt="_#= $htmlEncode(title) =#_" data-bgfit="cover" data-bgposition="left top" data-bgrepeat="no-repeat">
<div class="tp-caption revolution-ch1 sft start"
data-x="center"
data-hoffset="0"
data-y="100"
data-speed="1500"
data-start="500"
data-easing="Back.easeInOut"
data-endeasing="Power1.easeIn"
data-endspeed="300">
_#= $htmlEncode(title) =#_
</div>

<div class="tp-caption revolution-ch2 sft" style="z-index: 6"
data-x="center"
data-hoffset="0"
data-y="190"
data-speed="1400"
data-start="2000"
data-easing="Power4.easeOut"
data-endspeed="300"
data-endeasing="Power1.easeIn"
data-captionhidden="off">
_#= $htmlEncode(description) =#_
</div>

<div class="tp-caption sft" style="z-index: 6"
data-x="center"
data-hoffset="0"
data-y="310"
data-speed="1600"
data-start="2800"
data-easing="Power4.easeOut"
data-endspeed="300"
data-endeasing="Power1.easeIn"
data-captionhidden="off">
<a href="_#= linkURL =#_" class="btn-u btn-brd btn-brd-hover btn-u-light">Read More</a>
</div>
</li>

Note: Don not remove the most outer div! It will no longer work if you do.

Notice here again all pieces of code starting with '_#='. These sentences use the JavaScript variables to call the SharePoint columns.

That's it! If you refresh the page on which you've placed the slider, you should be able to see it in all its glory ☺

To make it easy, you can download the examples of the finished files right here:

2 comments:

  1. Hi Chantal, thank you very much for taking the time to write this blog post. I have been looking for something like this.
    One thing though, the link to the HTML file for the page layout no longer works. Could you please help update it. Thanks a lot.

    ReplyDelete
    Replies
    1. Sorry for the very late response!
      I can't seem to find any broken links in my blogpost...

      Delete