Overview
In one of the previous post we have started the discussion of customizing Slideshow web part, in particular it was demonstrated how to provide additional filtering for picture items. This time we’re going to go further and consider different scenarios of using SharePoint SlideShow capabilities. We deliberately do not consider the use of third party libraries for Slideshow or creating custom web parts, but try to build new experience using existing tools only.
1. Customize the display for Slideshow control: display additional picture properties
Suppose in addition to standard properties, custom properties should be displayed from Picture Library in Slideshow web part.
The following fields are retrieved from Picture Library for Slideshow:
- Title – picture title that is displayed in the PictureLibrarySlideshowWebPart, see SPPictureLibrarySlideshowDisplayStyle property for layout configuration
- Description – picture description that is displayed in the PictureLibrarySlideshowWebPart, see SPPictureLibrarySlideshowDisplayStyle property for layout configuration
- EncodedAbsWebImgUrl – Url of web image is used for displaying picture
- EncodedAbsUrl – Url of original image is used for picture link
- ImageWidth – picture width
- ImageHeight – picture height
So, our goal is to display slideshow using custom layout as shown below
Solution:
Solution consist of the following parts:
- load custom picture properties, see loadCarPicturesAdditionalInfo method for details
- Slideshow library (imglib.js) methods overriding for slideshow object initialization, picture changing and displaying
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function SlideshowObjectInitializer() { | |
ChangePic = (function(ChangePicOrig) { | |
return function() { | |
var ssObj = arguments[0]; //SlideShow object | |
if(typeof ssObj.additionalInfo != "undefined") | |
ChangePicOrig.apply(this, arguments); | |
}; | |
})(ChangePic); | |
ShowPic = (function(ShowPicOrig) { | |
return function() { | |
ShowPicOrig.apply(this, arguments); //call original ShowPic | |
var ssObj = arguments[0]; //SlideShow object | |
ShowAdditionalPicInfo(ssObj); | |
}; | |
})(ShowPic); | |
function ShowAdditionalPicInfo(ssObj) | |
{ | |
var curPicIdx=ssObj.index; //current picture index | |
if(ssObj.additionalInfo.length == 0) | |
return; | |
var picEntry = ssObj.additionalInfo[curPicIdx]; | |
var ssobj_ext_cell = '<td>'; | |
ssobj_ext_cell += '<div style="font-size:22px;"><span style="font-weight:bold">Car Model:</span>' + picEntry.CarModel + '</div>'; | |
ssobj_ext_cell += '<div style="font-size:22px;"><span style="font-weight:bold">Car Description:</span>' + picEntry.CarDesc + '</div>'; | |
ssobj_ext_cell += '</td>'; | |
var ssobj_row = jQuery(ssObj.cell).closest('tr'); | |
if(ssobj_row.find('td').length > 1) { | |
ssobj_row.find('td:nth-child(2)').replaceWith(ssobj_ext_cell); | |
} | |
else | |
ssobj_row.append(ssobj_ext_cell); | |
} | |
SlideshowObject = (function(SlideshowObjectOrig) { | |
return function() { | |
SlideshowObjectOrig.apply(this, arguments); | |
var ssobj = this; | |
ExecuteOrDelayUntilScriptLoaded(function(){ | |
loadCarPicturesAdditionalInfo(function(picEntries){ | |
ssobj.additionalInfo = picEntries; | |
ChangePic(ssobj); | |
}); | |
},'SP.js'); | |
}; | |
})(SlideshowObject); | |
} | |
function loadCarPicturesAdditionalInfo(cbPicsResults) { | |
var context = new SP.ClientContext.get_current(); | |
var web = context.get_web(); | |
var list = web.get_lists().getByTitle("Pictures"); | |
var viewXml = '<View></View>'; | |
var query = new SP.CamlQuery(); | |
query.set_viewXml(viewXml); | |
var items = list.getItems(query); | |
context.load(items,"Include(CarModel,CarDesc)"); | |
context.add_requestSucceeded(onLoaded); | |
context.add_requestFailed(onFailure); | |
context.executeQueryAsync(); | |
function onLoaded() { | |
var picEntries = []; | |
var itemsCount = items.get_count(); | |
for (i = 0; i < itemsCount; i++) { | |
var item = items.itemAt(i); | |
var picEntry = item.get_fieldValues(); | |
picEntries.push(picEntry); | |
} | |
cbPicsResults(picEntries); | |
} | |
function onFailure() { | |
cbPicsResults(null); | |
} | |
} |
Usage
Save JavaScript code to the file and embed it into the page with Slideshow web part as demonstrated below
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<script src="/_layouts/SE/imglibutils.js" type="text/javascript"></script> | |
<script type="text/javascript"> | |
ExecuteOrDelayUntilScriptLoaded(SlideshowObjectInitializer, 'imglib.js'); | |
</script> |
2. Customize the display for Slideshow control: display original pictures
In Slideshow web part, picture is initialized with field value that contains the Url of Web image (EncodedAbsWebImgUrl field). Unfortunately it is not supported to configure in web part what image type (original, web or thumbnail) should be displayed in Slideshow The solution that demonstrated below allows to display original images instead of web images in Slideshow web part.
Solution:
In order to specify original images, method overriding for picture initialization is used:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function SlideshowObjectInitializer() { | |
ShowPic = (function(ShowPicOrig) { | |
return function() { | |
var ssObj = arguments[0]; //SlideShow object | |
var curPicIdx=ssObj.index; //current picture index | |
ShowPicOrig.apply(this, arguments); //call original ShowPic | |
//apply some changes to display original picture in SlideShow control | |
ssObj.image.src = ssObj.linkArray[curPicIdx]; //display original image instead of web image | |
//change picture & container size to auto instead of fixed (by default web image size is used) | |
ssObj.image.setAttribute('height','100%'); | |
ssObj.image.setAttribute('width','100%'); | |
var cell = ssObj.cell; | |
cell.style.width = 'auto'; | |
cell.style.height = 'auto'; | |
cell.style.display = ''; | |
var pcell = ssObj.cell.parentNode; | |
pcell.style.width = 'auto'; | |
pcell.style.height = 'auto'; | |
}; | |
})(ShowPic); | |
} | |
ExecuteOrDelayUntilScriptLoaded(SlideshowObjectInitializer, 'imglib.js'); |
Usage
One of the most simple way to apply these changes is to embed specified JavaScript code via Content Editor web part (CEWP), for more details please follow this article.
- Save JavaScript code to the file, for example in SlideshowObjectInitializer.txt and upload it to SiteAssets Library
- Add CEWP on page where Slideshow web part is located and in the Content Editor tool pane, under Content Link property, type
/SiteAssets/SlideshowObjectInitializer.txt
3. Slideshow List View
Slideshow List View is only available for Pictures Library. It is pretty common scenario when another types of repositories are used for storing images, for example Assets Library. Let’s look at how to create a Slideshow List View for images stored in Assets Library.
Solution:
Slideshow List View
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<xsl:stylesheet xmlns:x="http://www.w3.org/2001/XMLSchema" | |
xmlns:d="http://schemas.microsoft.com/sharepoint/dsp" | |
version="1.0" exclude-result-prefixes="xsl msxsl ddwrt x d asp __designer SharePoint ddwrt2" | |
xmlns:ddwrt="http://schemas.microsoft.com/WebParts/v2/DataView/runtime" | |
xmlns:asp="http://schemas.microsoft.com/ASPNET/20" | |
xmlns:__designer="http://schemas.microsoft.com/WebParts/v2/DataView/designer" | |
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" | |
xmlns:msxsl="urn:schemas-microsoft-com:xslt" | |
xmlns:SharePoint="Microsoft.SharePoint.WebControls" | |
xmlns:ddwrt2="urn:frontpage:internal"> | |
<xsl:import href="/_layouts/xsl/main.xsl"/> | |
<xsl:output method="html" indent="no"/> | |
<xsl:template match="View" mode="full" ddwrt:ghost="always"> | |
<tr class="ms-viewheadertr"></tr> | |
<tr> | |
<td> | |
<!– Slideshow control –> | |
<table border="0" style="table-layout: fixed"> | |
<tbody> | |
<tr> | |
<td > | |
<div id="slidecontrol_cell" style="display: table-cell; vertical-align: middle; text-align: center;"> | |
<span style="vertical-align: middle; height: 100%; display: inline-block"></span> | |
<a id="slidecontrol_link" target="_blank"> | |
<img id="slidecontrol_curr" style="opacity: 0.9900000000000007; border: 0px; vertical-align: middle;" alt=""/> | |
</a> | |
</div> | |
</td> | |
</tr> | |
<tr> | |
<td style="height: 75px"> | |
<div style="height: 75px; opacity: 0.9900000000000007;" id="slidecontrol_text"> | |
<span id="slidecontrol_title" class="ms-slideshow-title"></span> | |
<br/> | |
</div> | |
</td> | |
</tr> | |
<tr> | |
<td style="text-align: center"> | |
<a id="btn_prev" > | |
<img border="0" style="position: relative; cursor: hand" onmouseover="HiliteButton()" onmouseout="DemoteButton()" src="/_layouts/images/plprev1.gif" alt="Previous Image"/> | |
</a> | |
<a id="btn_pp" > | |
<img border="0" style="position: relative; cursor: hand" onmouseover="HiliteButton()" onmouseout="DemoteButton()" src="/_layouts/images/plpause1.gif" id="slidecontrol_playpause" alt="Pause"/> | |
</a> | |
<a id="btn_next"> | |
<img border="0" style="position: relative; cursor: hand" onmouseover="HiliteButton()" onmouseout="DemoteButton()" src="/_layouts/images/plnext1.gif" alt="Next Image"/> | |
</a> | |
</td> | |
</tr> | |
</tbody> | |
</table> | |
<img id="slidecontrol_next" width="0" height="0" style="visibility: hidden" /> | |
<img id="slidecontrol_prev" width="0" height="0" style="visibility: hidden" /> | |
<img id="slidecontrol_pp" width="0" height="0" style="visibility: hidden" /> | |
</td> | |
</tr> | |
<script type="text/javascript"> | |
var slidecontrol_slideshowObject; | |
ExecuteOrDelayUntilScriptLoaded(function(){ | |
slidecontrol_slideshowObject = createSlideControl('slidecontrol_'); | |
},'SP.js'); | |
</script> | |
<xsl:apply-templates mode="footer" select="." /> | |
</xsl:template> | |
<xsl:template name="SlideshowViewOverride" mode="RootTemplate" match="View" ddwrt:dvt_mode="root"> | |
<script type='text/javascript' src="/_layouts/1033/imglib.js"></script> | |
<script type='text/javascript' src="/_layouts/yaspp/slideshow.js"></script> | |
<!–script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script–> | |
<script type="text/javascript"> | |
</script> | |
<xsl:call-template name="View_Default_RootTemplate"/> | |
</xsl:template> | |
</xsl:stylesheet> |
Slideshow control initialization and retrieving picture entries from Assets Library
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//initialize SlideshowObject control | |
function createSlideControl(slidecontrolId) | |
{ | |
loadPicturesInfo(function(picEntries) { | |
var slidecontrol_slideshowObject = new SlideshowObject(slidecontrolId, picEntries.src, picEntries.fullImageSrc, picEntries.title, picEntries.description, picEntries.height, picEntries.width, 15, 1.0); | |
ChangePic(slidecontrol_slideshowObject); | |
InitSlideControlNavButtons(slidecontrol_slideshowObject); | |
}); | |
} | |
// | |
function InitSlideControlNavButtons(slideshowObject) { | |
var btn_prev = document.getElementById("btn_prev"); | |
AddEvtHandler(btn_prev, "onclick", function() { NextPrevious(slideshowObject, false);}); | |
var btn_pp = document.getElementById("btn_pp"); | |
AddEvtHandler(btn_pp, "onclick", function() { PlayPause(slideshowObject);}); | |
var btn_next = document.getElementById("btn_next"); | |
AddEvtHandler(btn_next, "onclick", function() { NextPrevious(slideshowObject, true);}); | |
} | |
//retrieve picture entries for SlideObject control | |
function loadPicturesInfo(cbPicsResults) { | |
var context = new SP.ClientContext.get_current(); | |
var web = context.get_web(); | |
var list = web.get_lists().getByTitle(ctx.ListTitle); | |
var viewXml = '<View></View>'; | |
var query = new SP.CamlQuery(); | |
query.set_viewXml(viewXml); | |
var items = list.getItems(query); | |
context.load(items,"Include(Title,EncodedAbsWebImgUrl,EncodedAbsUrl,ImageWidth,ImageHeight)"); | |
context.add_requestSucceeded(onLoaded); | |
context.add_requestFailed(onFailure); | |
context.executeQueryAsync(); | |
function onLoaded() { | |
var widthArray = []; | |
var heightArray = []; | |
var pictureArray = []; | |
var linkArray = []; | |
var titleArray = []; | |
var descriptionArray = []; | |
var itemsCount = items.get_count(); | |
for (i = 0; i < itemsCount; i++) { | |
var item = items.itemAt(i); | |
var picEntry = item.get_fieldValues(); | |
titleArray.push(picEntry.Title); | |
pictureArray.push(picEntry.EncodedAbsWebImgUrl); | |
linkArray.push(picEntry.EncodedAbsUrl); | |
descriptionArray.push(''); | |
widthArray.push(picEntry.ImageWidth); | |
heightArray.push(picEntry.ImageHeight); | |
} | |
picEntries = {title:titleArray,description:descriptionArray,fullImageSrc: linkArray,src:pictureArray, width:widthArray,height:heightArray}; | |
cbPicsResults(picEntries); | |
} | |
function onFailure() { | |
cbPicsResults(null); | |
} | |
} |
4. Aggregate picture items and render as Slideshow
The last example demonstrates how to display slideshow for pictures aggregated from site collection. For aggregating pictures from site collection, Content Query web part is utilized.
Solution
OuterTemplate.SlideShowBody template is intended for rendering Slideshow control in CQWP
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<xsl:template name="OuterTemplate.SlideShowBody"> | |
<xsl:param name="Rows" /> | |
<xsl:param name="FirstRow" /> | |
<xsl:param name="LastRow" /> | |
<script type="text/javascript"> | |
function loadScript(url, callback) | |
{ | |
// adding the script tag to the head as suggested before | |
var head = document.getElementsByTagName('head')[0]; | |
var script = document.createElement('script'); | |
script.type = 'text/javascript'; | |
script.src = url; | |
// then bind the event to the callback function | |
// there are several events for cross browser compatibility | |
script.onreadystatechange = callback; | |
script.onload = callback; | |
// fire the loading | |
head.appendChild(script); | |
} | |
function InitSlideControlNavButtons(slideshowObject) { | |
var btn_prev = document.getElementById("btn_prev"); | |
AddEvtHandler(btn_prev, "onclick", function() { NextPrevious(slideshowObject, false);}); | |
var btn_pp = document.getElementById("btn_pp"); | |
AddEvtHandler(btn_pp, "onclick", function() { PlayPause(slideshowObject);}); | |
var btn_next = document.getElementById("btn_next"); | |
AddEvtHandler(btn_next, "onclick", function() { NextPrevious(slideshowObject, true);}); | |
} | |
<xsl:text>var widthArray = [</xsl:text> | |
<xsl:for-each select="$Rows"> | |
<xsl:value-of select="@ImageWidth" /> | |
<xsl:if test="position() != last()">, </xsl:if> | |
</xsl:for-each> | |
<xsl:text>];</xsl:text> | |
<xsl:text>var linkArray = [</xsl:text> | |
<xsl:for-each select="$Rows"> | |
<xsl:value-of select="concat('"',@LinkUrl,'"')" /> | |
<xsl:if test="position() != last()">, </xsl:if> | |
</xsl:for-each> | |
<xsl:text>];</xsl:text> | |
<xsl:text>var heightArray = [</xsl:text> | |
<xsl:for-each select="$Rows"> | |
<xsl:value-of select="@ImageHeight" /> | |
<xsl:if test="position() != last()">, </xsl:if> | |
</xsl:for-each> | |
<xsl:text>];</xsl:text> | |
<xsl:text>var pictureArray = [</xsl:text> | |
<xsl:for-each select="$Rows"> | |
<xsl:value-of select="concat('"',@LinkUrl,'"')" /> | |
<xsl:if test="position() != last()">, </xsl:if> | |
</xsl:for-each> | |
<xsl:text>];</xsl:text> | |
<xsl:text>var titleArray = [</xsl:text> | |
<xsl:for-each select="$Rows"> | |
<xsl:value-of select="concat('"',@Title,'"')" /> | |
<xsl:if test="position() != last()">, </xsl:if> | |
</xsl:for-each> | |
<xsl:text>];</xsl:text> | |
<xsl:text>var descriptionArray = [</xsl:text> | |
<xsl:for-each select="$Rows"> | |
<xsl:value-of select="concat('"',@Description,'"')" /> | |
<xsl:if test="position() != last()">, </xsl:if> | |
</xsl:for-each> | |
<xsl:text>];</xsl:text> | |
loadScript("/_layouts/1033/imglib.js", function() | |
{ | |
var slidecontrol = new SlideshowObject('slidecontrol_', pictureArray, linkArray, titleArray, descriptionArray, heightArray, widthArray, 15, 1.0); | |
ChangePic(slidecontrol); | |
InitSlideControlNavButtons(slidecontrol); | |
}); | |
</script> | |
<xsl:call-template name="SlideShowControl" > | |
</xsl:call-template> | |
</xsl:template> | |
<xsl:template name="SlideShowControl"> | |
<table border="0" style="table-layout: fixed"> | |
<tbody> | |
<tr> | |
<td > | |
<div id="slidecontrol_cell" style="display: table-cell; vertical-align: middle; text-align: center;"> | |
<span style="vertical-align: middle; height: 100%; display: inline-block"></span> | |
<a id="slidecontrol_link" target="_blank"> | |
<img id="slidecontrol_curr" style="opacity: 0.9900000000000007; border: 0px; vertical-align: middle;" alt=""/> | |
</a> | |
</div> | |
</td> | |
</tr> | |
<tr> | |
<td style="height: 75px"> | |
<div style="height: 75px; opacity: 0.9900000000000007;" id="slidecontrol_text"> | |
<span id="slidecontrol_title" class="ms-slideshow-title"></span> | |
<br/> | |
</div> | |
</td> | |
</tr> | |
<tr> | |
<td style="text-align: center"> | |
<a id="btn_prev" > | |
<img border="0" style="position: relative; cursor: hand" onmouseover="HiliteButton()" onmouseout="DemoteButton()" src="/_layouts/images/plprev1.gif" alt="Previous Image"/> | |
</a> | |
<a id="btn_pp" > | |
<img border="0" style="position: relative; cursor: hand" onmouseover="HiliteButton()" onmouseout="DemoteButton()" src="/_layouts/images/plpause1.gif" id="slidecontrol_playpause" alt="Pause"/> | |
</a> | |
<a id="btn_next"> | |
<img border="0" style="position: relative; cursor: hand" onmouseover="HiliteButton()" onmouseout="DemoteButton()" src="/_layouts/images/plnext1.gif" alt="Next Image"/> | |
</a> | |
</td> | |
</tr> | |
</tbody> | |
</table> | |
<img id="slidecontrol_next" width="0" height="0" style="visibility: hidden" /> | |
<img id="slidecontrol_prev" width="0" height="0" style="visibility: hidden" /> | |
<img id="slidecontrol_pp" width="0" height="0" style="visibility: hidden" /> | |
</xsl:template> |
Usage
- Specify additional fields for retrieving via CommonViewFields property. For more details how to display custom fields in a CQWP, follow this article
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<property name="CommonViewFields" type="string">Description,Text;ImageWidth,Integer;ImageHeight,Integer;Title,Text;</property> |
- Replace OuterTemplate.Body template with OuterTemplate.SlideShowBody in ContentQueryMain.xsl. For more details how to customize XSL for the Content Query Web Part follow this article
Conclusion
The main idea of this post was to demonstrate how to combine different components available in SharePoint 2010 in order to build new functionality without creating new one from scratch (i.e.: new web parts) or using third party components.