SPTechCon Austin 2016 – The Videos!

In my last post, I promised those who attended my Content Search Web Part session (at SPTechCon Austin 2016) that I’d deliver videos of the demos I normally perform during that session. This post contains links to those demo videos as well as some additional commentary.

video playerAs I discussed in my last post titled “SPTechCon Austin 2016 And Death By Demo,” the demonstrations I intended to deliver at SPTechCon in Austin a week and a half ago didn’t go very well. In fact, they didn’t really go at all due to some extremely odd technical circumstances. To make up for the lack of demo content, I promised attendees that I would put together video walk-throughs for each of the demos I had intended to deliver at SPTechCon.

It took a little longer than initially anticipated, but the half-dozen links below represent the demo material I would normally walk through during a delivery of my “SharePoint’s New Swiss Army Knife: The Content Search Web Part” session. If there’s a silver lining to the fact that I’m doing the demos after the actual presentation, it’s that I was able to take more time than I normally have (within the context of a 75 minute session) to show some extra content and go off the beaten path a bit more.

So, for those of you who have been waiting … here are the goods!

These videos were recorded with Camtasia and rendered directly out to YouTube. I made every attempt to keep the quality high, but if something gets “lost in translation” or you have other issues, please let me know.

I enjoyed putting these videos together, and in the past I’ve tossed around the idea of doing more videos like this. If these CSWP videos were helpful to you and/or you’d like to see more, please let me know. If enough of you find value in these, I’d be willing to put together additional videos for some of the other presentations and workshops I deliver.

Enjoy, and as with everything else, I welcome your feedback!

References and Resources

  1. Blog Post: SPTechCon Austin 2016 And Death By Demo
  2. Resources: SharePoint’s New Swiss Army Knife: The Content Search Web Part (SPTechCon Austin 2016)
  3. Software: TechSmith’s Camtasia Studio
  4. Site: YouTube

SPTechCon Austin 2016 And Death By Demo

I just got back from SPTechCon Austin 2016, and I had some “trouble” (putting it mildly) with demos I gave during one of my sessions. This post is a note – and a promise – to those who attended my Content Search Web Part (CSWP) session during the conference.

This was me after my CSWP session yesterdayI used to write posts to sum-up the various conferences at which I’ve spoken. That was feasible when I was only speaking at a conference or event here or there, but writing about every event is somewhat time-consuming nowadays. And besides, most of the posts would look about the same: “great event,” “lots of fun,” “awesome attendees,” etc.

Well, I got back from SPTechCon Austin 2016 yesterday … and I felt compelled to write something today. Yes, it was a great conference, lots of fun, and filled with awesome attendees. But there was something more to this conference that motivated me – no, compelled me – to write this post.

Compelled By What?

That “thing” that compelled me was this: death by demo.

I delivered two sessions during the event: a new one on performance troubleshooting with SharePoint Online, and one of my “standards” that is an introduction to the Content Search Web Part (CSWP). I delivered the troubleshooting session on Tuesday, and although it went long (I still need to tune it up), it went pretty well – no real issues. I can’t claim the same about the CSWP session yesterday (Wednesday) morning.

Simply put, the demos for my CSWP session were a disaster. I’d gotten everything ready to go on the Tuesday night before the session; despite that, things went off-the-rails almost immediately. I was RDP’ing back to my home desktop system where I had VMware Workstation running, and all of that (i.e., the RDP and VWware Workstation parts) seemed fine. The fashion in which things blew up was not something I’d ever seen before.

Kerplunk? Kerplooey!

What went wrong? Well, it’s hard to describe. The best way to describe it is that left-clicking didn’t work properly in the development VM I was using. Sometimes my clicks would visibly register (e.g., on a window close button) – but nothing would happen. Other times, my left-clicks seemed to register somewhere else on the screen (other than where the mouse pointer was located). And at other times still, a left-click would highlight some weird section in the web browser window.

Because of this aberrant mouse behavior, I couldn’t show the demo material. I certainly tried enough times, and I even hobbled through one demo with the audience members helping me by shouting out keyboard shortcuts when I asked … but it was a total wreck.

Attendees for my CSWP session at SPTechConIf you were in attendance for this session (and there were quite a few folks, as shown in the picture on the right – taken a handful of minutes before I started), I truly apologize. An apology alone, though, isn’t enough (in my opinion).

My Attempt to Make Up

As the demos were slamming into walls and catching on fire, I commented a couple of times that I’d find some way to share the demo materials with the audience at a later time. I was initially thinking I’d try to do a webcast – kind of a do-over – but I thought about it some more on the plane ride home last night and decided on something else.

Here’s what I’m going to do: rather than do the whole session over again, I’m going to work through each of the demos I intended to show and record those as a Camtasia/video that can be viewed whenever someone has the time to do so. Doing this sort of video cuts straight to the chase and is ultimately more flexible than trying to round everyone up for a webcast. It can also be re-watched as desired.

“When is this video going to be ready,” you might ask? I need to do some catching-up after having been out of town for a while, but I’m hoping to find the time this coming weekend to put it together. If I can do that, then the video will be available sometime early next week.

How Will We Know?

Once everything is ready to go, I’ll put together another blog post to announce the availability and provide a link. I’ve also been in contact with David Rubinstein at BZ Media about this, and he said that he’d blast the information out to attendees and newsletter subscribers, as well.

Summary

So, once again: my sincere apologies to those who attended my CSWP session at SPTechCon. It’ll be a few days after the actual session, but hopefully the video will make up for the demos that went nowhere during the session.

Advanced Paging with SharePoint Content Search Web Part Display Templates

In this post, I cover the topic of exposing paging controls within the display templates used by SharePoint 2013’s Content Search Web Part (CSWP). In addition to looking at the underlying paging mechanisms used by the CSWP, I make available a couple of display templates that I created which include advanced paging support.

Click here to download associated ZIP file with display templatesPages in a BookI’ve had an opportunity to play with SharePoint 2013’s Content Search Web Part (CSWP) on a number of occasions in the last couple of years, and I have to say that I like it a lot. The CSWP can be employed to address a whole host of different use cases; in fact, in many situations I’ve found that it can be used to solve problems that were previously addressable only through custom code.

Search-driven content in SharePoint isn’t anything new, of course, but the display templates that are used to format search results in SharePoint 2013 are a large part of the CSWP’s “special sauce.” Through the use of a Control display template and an Item display template, it is possible to select, arrange, and style the search results that are returned and shown to users in a highly customizable fashion. With some knowledge of HTML and the help of SharePoint 2013’s Design Manager, it’s possible to produce some pretty impressive looking content. And if you know JavaScript, well … the sky is the limit on what you can produce.

Control And Item Display Templates

DisplayAndPropertyMappingsBefore I dive into paging and how I’ve tried to stretch what can be done with the CSWP, I want to briefly examine some display template basics. Although this post isn’t intended to be a primer on the CSWP and its associated display templates, there are a few items worth reviewing.

On the right is a snippet of a ToolPart containing some configuration data for a particular CSWP displaying some very basic data. The examples that follow (i.e., the two images shown below) use the configuration shown in the ToolPart, so refer to it if needed.

The first example below is how a CSWP showing three results might appear to an end user when the List with Paging Control template and Two lines Item template are applied. The second example (to the right of the first) differentiates which content regions on the CSWP are being driven by the List with Paging Control template (shown with green highlighting) and which are being driven by the Two lines Item template (shown in red).

Content Search Web Part Example as Seen by End User Content Search Web Part with Template Regions Highlighted

Through these images, I’m trying to convey a very simple point: the Control template dictates how the search results’ “container” appears, and the Item template determines how each individual search result within the container is displayed. The contents of any CSWP are rendered by the output of a single Control display template and zero or more Item display templates (again, one for each search result/item shown).

Nothing To See Here

As you might have guessed from the title of this post, one functional area that seems relatively unexplored and underdeveloped (in my experience) is that of paging and how paging controls are made available to end users of the CSWP. This is unfortunate, because whenever more results are returned than can be displayed at once – a very common scenario – some form of paging is needed.

Out of the box (OOTB), SharePoint 2013 comes with only a handful of Control and Item display templates that can be used with the CSWP to format your search results. Of these display templates, only one contains paging controls: the List with Paging Control template. If all you require is the basic forward/backward paging offered by the two buttons it contains, then the List with Paging display template may be adequate for your needs.

Personally, I think the List with Paging template is bland and kind of … ugly. It works, sure, but it doesn’t display several pieces of information that I find important; for example, the total number of search results and the result page that the user is currently on. Worse is the fact that it doesn’t provide any sort of mechanism to jump to a specific page. The best that an end-user can do is page forward or backward one page at a time.

Better Paging Support

CSWP With Advanced Paging SupportOne of the talks I’ve been giving recently at various SharePoint events and conferences is titled SharePoint’s New Swiss Army Knife: The Content Search Web Part. During that talk, I demonstrate a set of CSWP display templates that I put together to generate something decidedly “non-search” in appearance – like a directory of files to which the current user has access within the current site collection. An image of that CSWP example appears on the left.

This file directory CSWP instance was generated with three simple files: two custom display templates (one for the Control, and one for each Item shown) and a cascading style sheet. The actual result data isn’t particularly remarkable, but the manner in which the paging is implemented is what tends to catch people’s attention. With the Control template I created, end-users can:

  • See the total number of documents (i.e., search results) to which they have access
  • Clearly see which page of search results they’re on through the boxed page number and the “Page xx of yy” label
  • Identify which items/results they’re viewing through the “Items xxx to yyy of zzz” label
  • Jump directly to a page of results by clicking the specified page number

Finding all of this information and displaying it through the CSWP Control template took some research and tinkering. Some of the information was available directly within the search results that were passed to the CSWP, but some of it wasn’t. In the case where some desired information wasn’t available, it was computed with some basic math.

Overview Of The CSWP HTML

By default, the CSWP implements a client-side processing and paging model. Search results that are displayed are controlled by JavaScript functions contained within the Control and Item display templates that have been assigned to the CSWP. When a set of search results is being processed for display within the client browser, the Control template (which is the results container) gets called first to render the HTML that will frame or house the search items/results. For each search result or item that is passed to the CSWP, the Item display template then gets called to create a snippet of HTML for the result/item that can be inserted into the “frame” (commonly a <div>) created by Control display template.

An example of the rendered HTML for the search results shown in the previous “Better Paging Support” section appears below.

<div id="sas-lib-listing">
	<div>Documents To Which I Have Access</div>
	<ul class="sas-table">
		<li class="sas-tablerow">
			<span class="sas-tableheader">Title of Document</span>
		</li>
		<li class="sas-tablerow">
			<div class="sas-tablecell" id="ctl00_ctl39_g_85d5f2f9_fbe4_4e9b_9d51_647e179b87f9_csr1_SAS_Item_Template_container" data-displaytemplate="SAS_Item_Template">
				<div id="ctl00_ctl39_g_85d5f2f9_fbe4_4e9b_9d51_647e179b87f9_csr1_SAS_Item_Template_dataContainer">
					<a title="3. Optimus Prime Part - Button" id="ctl00_ctl39_g_85d5f2f9_fbe4_4e9b_9d51_647e179b87f9_csr1_SAS_Item_Template_displayTextLink"
					href="http://sp2013-dev:18480/SiteAssets/Forms/DispForm.aspx?ID=4">3. Optimus Prime Part - Button</a>
				</div>
			</div>
		</li>
		<li class="sas-tablerow">
			<div class="sas-tablecell" id="ctl00_ctl39_g_85d5f2f9_fbe4_4e9b_9d51_647e179b87f9_csr2_SAS_Item_Template_container" data-displaytemplate="SAS_Item_Template">
				<div id="ctl00_ctl39_g_85d5f2f9_fbe4_4e9b_9d51_647e179b87f9_csr2_SAS_Item_Template_dataContainer">
					<a title="4. Weather Right Now (Not Really) - Button" id="ctl00_ctl39_g_85d5f2f9_fbe4_4e9b_9d51_647e179b87f9_csr2_SAS_Item_Template_displayTextLink"
					href="http://sp2013-dev:18480/SiteAssets/Forms/DispForm.aspx?ID=5">4. Weather Right Now (Not Really) - Button</a>
				</div>
			</div>
		</li>
		<li class="sas-tablerow">
			<div class="sas-tablecell" id="ctl00_ctl39_g_85d5f2f9_fbe4_4e9b_9d51_647e179b87f9_csr3_SAS_Item_Template_container" data-displaytemplate="SAS_Item_Template">
				<div id="ctl00_ctl39_g_85d5f2f9_fbe4_4e9b_9d51_647e179b87f9_csr3_SAS_Item_Template_dataContainer">
					<a title="5. Weather Right Now Page - Button" id="ctl00_ctl39_g_85d5f2f9_fbe4_4e9b_9d51_647e179b87f9_csr3_SAS_Item_Template_displayTextLink"
					href="http://sp2013-dev:18480/SiteAssets/Forms/DispForm.aspx?ID=6">5. Weather Right Now Page - Button</a>
				</div>
			</div>
		</li>
		<li class="sas-tablerow">
			<div class="sas-tablecell" id="ctl00_ctl39_g_85d5f2f9_fbe4_4e9b_9d51_647e179b87f9_csr4_SAS_Item_Template_container" data-displaytemplate="SAS_Item_Template">
				<div id="ctl00_ctl39_g_85d5f2f9_fbe4_4e9b_9d51_647e179b87f9_csr4_SAS_Item_Template_dataContainer">
					<a title="6. Weather Right Now Provisioned - Button" id="ctl00_ctl39_g_85d5f2f9_fbe4_4e9b_9d51_647e179b87f9_csr4_SAS_Item_Template_displayTextLink"
					href="http://sp2013-dev:18480/SiteAssets/Forms/DispForm.aspx?ID=8">6. Weather Right Now Provisioned - Button</a>
				</div>
			</div>
		</li>
		<li class="sas-tablerow">
			<div class="sas-tablecell" id="ctl00_ctl39_g_85d5f2f9_fbe4_4e9b_9d51_647e179b87f9_csr5_SAS_Item_Template_container" data-displaytemplate="SAS_Item_Template">
				<div id="ctl00_ctl39_g_85d5f2f9_fbe4_4e9b_9d51_647e179b87f9_csr5_SAS_Item_Template_dataContainer">
					<a title="8. Donuts And Drinks Pub - Button" id="ctl00_ctl39_g_85d5f2f9_fbe4_4e9b_9d51_647e179b87f9_csr5_SAS_Item_Template_displayTextLink"
					href="http://sp2013-dev:18480/SiteAssets/Forms/DispForm.aspx?ID=9">8. Donuts And Drinks Pub - Button</a>
				</div>
			</div>
		</li>
		<li class="sas-tablerow">
			<div class="sas-tablecell" id="ctl00_ctl39_g_85d5f2f9_fbe4_4e9b_9d51_647e179b87f9_csr6_SAS_Item_Template_container" data-displaytemplate="SAS_Item_Template">
				<div id="ctl00_ctl39_g_85d5f2f9_fbe4_4e9b_9d51_647e179b87f9_csr6_SAS_Item_Template_dataContainer">
					<a title="WeatherRightNowScraper" id="ctl00_ctl39_g_85d5f2f9_fbe4_4e9b_9d51_647e179b87f9_csr6_SAS_Item_Template_displayTextLink"
					href="http://sp2013-dev:18480/SitePages/WeatherRightNowScraper.aspx">WeatherRightNowScraper</a>
				</div>
			</div>
		</li>
		<li class="sas-tablerow">
			<div class="sas-tablecell" id="ctl00_ctl39_g_85d5f2f9_fbe4_4e9b_9d51_647e179b87f9_csr7_SAS_Item_Template_container" data-displaytemplate="SAS_Item_Template">
				<div id="ctl00_ctl39_g_85d5f2f9_fbe4_4e9b_9d51_647e179b87f9_csr7_SAS_Item_Template_dataContainer">
					<a title="DonutsAndDrinksPub" id="ctl00_ctl39_g_85d5f2f9_fbe4_4e9b_9d51_647e179b87f9_csr7_SAS_Item_Template_displayTextLink"
					href="http://sp2013-dev:18480/Pages/DonutsAndDrinksPub.aspx">DonutsAndDrinksPub</a>
				</div>
			</div>
		</li>
		<li class="sas-tablerow">
			<div class="sas-tablecell" id="ctl00_ctl39_g_85d5f2f9_fbe4_4e9b_9d51_647e179b87f9_csr8_SAS_Item_Template_container" data-displaytemplate="SAS_Item_Template">
				<div id="ctl00_ctl39_g_85d5f2f9_fbe4_4e9b_9d51_647e179b87f9_csr8_SAS_Item_Template_dataContainer">
					<a title="DonutsAndDrinks" id="ctl00_ctl39_g_85d5f2f9_fbe4_4e9b_9d51_647e179b87f9_csr8_SAS_Item_Template_displayTextLink"
					href="http://sp2013-dev:18480/SitePages/DonutsAndDrinks.aspx">DonutsAndDrinks</a>
				</div>
			</div>
		</li>
		<li class="sas-tablerow">
			<div class="sas-tablecell" id="ctl00_ctl39_g_85d5f2f9_fbe4_4e9b_9d51_647e179b87f9_csr9_SAS_Item_Template_container" data-displaytemplate="SAS_Item_Template">
				<div id="ctl00_ctl39_g_85d5f2f9_fbe4_4e9b_9d51_647e179b87f9_csr9_SAS_Item_Template_dataContainer">
					<a title="MakingPiTakesEffort" id="ctl00_ctl39_g_85d5f2f9_fbe4_4e9b_9d51_647e179b87f9_csr9_SAS_Item_Template_displayTextLink"
					href="http://sp2013-dev:18480/SitePages/MakingPiTakesEffort.aspx">MakingPiTakesEffort</a>
				</div>
			</div>
		</li>
		<li class="sas-tablerow">
			<div class="sas-tablecell" id="ctl00_ctl39_g_85d5f2f9_fbe4_4e9b_9d51_647e179b87f9_csr10_SAS_Item_Template_container" data-displaytemplate="SAS_Item_Template">
				<div id="ctl00_ctl39_g_85d5f2f9_fbe4_4e9b_9d51_647e179b87f9_csr10_SAS_Item_Template_dataContainer">
					<a title="OptimusPrimePart" id="ctl00_ctl39_g_85d5f2f9_fbe4_4e9b_9d51_647e179b87f9_csr10_SAS_Item_Template_displayTextLink"
					href="http://sp2013-dev:18480/SitePages/OptimusPrimePart.aspx">OptimusPrimePart</a>
				</div>
			</div>
		</li>
	</ul>
	<div class="sas-paging-table">
		<div class="sas-paging-tablerow">
			<div class="sas-paging-tablecell">
				<a onclick="$getClientControl(this).page(1);return Srch.U.cancelEvent(event);" href="#">1</a>
			</div>
			<div class="sas-paging-tablecell">
				<a onclick="$getClientControl(this).page(11);return Srch.U.cancelEvent(event);" href="#">2</a>
			</div>
			<div class="sas-paging-tablecell">
				<a onclick="$getClientControl(this).page(21);return Srch.U.cancelEvent(event);" href="#">3</a>
			</div>
			<div class="sas-paging-tablecell">
				<a onclick="$getClientControl(this).page(31);return Srch.U.cancelEvent(event);" href="#">4</a>
			</div>
			<div class="sas-paging-tablecell">
				<a onclick="$getClientControl(this).page(41);return Srch.U.cancelEvent(event);" href="#">5</a>
			</div>
			<div class="sas-paging-tablecell">
				<a onclick="$getClientControl(this).page(51);return Srch.U.cancelEvent(event);" href="#">6</a>
			</div>
			<div class="sas-paging-tablecell">
				<a onclick="$getClientControl(this).page(61);return Srch.U.cancelEvent(event);" href="#">7</a>
			</div>
			<div class="sas-paging-tablecell">
				<a onclick="$getClientControl(this).page(71);return Srch.U.cancelEvent(event);" href="#">8</a>
			</div>
			<div class="sas-paging-tablecell">
				<a onclick="$getClientControl(this).page(81);return Srch.U.cancelEvent(event);" href="#">9</a>
			</div>
			<div class="sas-paging-tablecell">
				<a onclick="$getClientControl(this).page(91);return Srch.U.cancelEvent(event);" href="#">10</a>
			</div>
			<div class="sas-paging-tablecell">
				<a onclick="$getClientControl(this).page(101);return Srch.U.cancelEvent(event);" href="#">11</a>
			</div>
			<div class="sas-paging-tablecell">
				<a onclick="$getClientControl(this).page(111);return Srch.U.cancelEvent(event);" href="#">12</a>
			</div>
			<div class="sas-paging-tablecell">
				<a onclick="$getClientControl(this).page(121);return Srch.U.cancelEvent(event);" href="#">13</a>
			</div>
			<div class="sas-paging-tablecell sas-paging-currentpage">14</div>
			<div class="sas-paging-tablecell">
				<a onclick="$getClientControl(this).page(141);return Srch.U.cancelEvent(event);" href="#">15</a>
			</div>
			<div class="sas-paging-tablecell">
				<a onclick="$getClientControl(this).page(151);return Srch.U.cancelEvent(event);" href="#">16</a>
			</div>
			<div class="sas-paging-tablecell">
				<a onclick="$getClientControl(this).page(161);return Srch.U.cancelEvent(event);" href="#">17</a>
			</div>
			<div class="sas-paging-tablecell">
				<a onclick="$getClientControl(this).page(171);return Srch.U.cancelEvent(event);" href="#">18</a>
			</div>
			<div class="sas-paging-tablecell sas-paging-summary">Page
				<span>14</span>of
				<span>18</span>, items
				<span>131</span>to
				<span>140</span>of
				<span>179</span>.</div>
		</div>
	</div>
</div>

The Control template (SwissArmy_Control_Template.js) creates the top level <div> and a child <ul> element (with a CSS class of “sas-table”) for the overall HTML structure, as well as the individual <li> elements used to contain each search/result item. For each search result/item, the Item template (SwissArmy_Item_Template.js) creates a <div> block that is inserted as a child within an <li> element. Each of the individual item <div> blocks created by the Item template has a CSS class of “sas-tablecell” for easier styling.

Below the <ul> block housing the search results is another <div> with a CSS class of “sas-paging-table.” As suggested by the class name, the <div> is used to house the clickable page numbers and additional paging information seen at the bottom of the CSWP control. And like the rest of the container information, this HTML is generated within the Control template.

Fetching Search Results

Each time a set of search results is needed, either on initial page rendering or when the user moves to a new page, the CSWP calls back to its SharePoint site collection for the data it needs. By default, this call occurs asynchronously; however, the CSWP can be configured to make such calls synchronously within the normal page processing sequence.

For example, if I had a page containing a CSWP at the following URL

http://sp2013-dev:18580/DisplayTemplateStyling

… the CSWP on that page would request search results for display by posting a request to the following endpoint:

http://sp2013-dev:18580/_vti_bin/client.svc/ProcessQuery

As part of its request, the CSWP passes an XML structure to the client.svc web service that looks something like the XML that appears below. This structure contains all of the information the ProcessQuery method needs to determine which search results should be sent back:

<Request xmlns="http://schemas.microsoft.com/sharepoint/clientquery/2009" SchemaVersion="15.0.0.0" LibraryVersion="15.0.0.0" ApplicationName="Javascript Library">
	<Actions>
		<ObjectPath Id="1" ObjectPathId="0" />
		<SetProperty Id="2" ObjectPathId="0" Name="QueryTemplate">
			<Parameter Type="String">(contentclass:STS_ListItem OR IsDocument:True)</Parameter>
		</SetProperty>
		<ObjectPath Id="4" ObjectPathId="3" />
		<Method Name="Add" Id="5" ObjectPathId="3">
			<Parameters>
				<Parameter Type="String">LastModifiedTime</Parameter>
				<Parameter Type="Number">1</Parameter>
			</Parameters>
		</Method>
		<SetProperty Id="6" ObjectPathId="0" Name="StartRow">
			<Parameter Type="Number">130</Parameter>
		</SetProperty>
		<SetProperty Id="7" ObjectPathId="0" Name="RowsPerPage">
			<Parameter Type="Number">10</Parameter>
		</SetProperty>
		<SetProperty Id="8" ObjectPathId="0" Name="RowLimit">
			<Parameter Type="Number">10</Parameter>
		</SetProperty>
		<SetProperty Id="9" ObjectPathId="0" Name="TotalRowsExactMinimum">
			<Parameter Type="Number">141</Parameter>
		</SetProperty>
		<SetProperty Id="10" ObjectPathId="0" Name="SourceId">
			<Parameter Type="Guid">{8413cd39-2156-4e00-b54d-11efd9abdb89}</Parameter>
		</SetProperty>
		<ObjectPath Id="12" ObjectPathId="11" />
		<Method Name="SetQueryPropertyValue" Id="13" ObjectPathId="11">
			<Parameters>
				<Parameter Type="String">SourceName</Parameter>
				<Parameter TypeId="{b25ba502-71d7-4ae4-a701-4ca2fb1223be}">
					<Property Name="BoolVal" Type="Boolean">false</Property>
					<Property Name="IntVal" Type="Number">0</Property>
					<Property Name="QueryPropertyValueTypeIndex" Type="Number">1</Property>
					<Property Name="StrArray" Type="Null" />
					<Property Name="StrVal" Type="String">Local SharePoint Results</Property>
				</Parameter>
			</Parameters>
		</Method>
		<Method Name="SetQueryPropertyValue" Id="14" ObjectPathId="11">
			<Parameters>
				<Parameter Type="String">SourceLevel</Parameter>
				<Parameter TypeId="{b25ba502-71d7-4ae4-a701-4ca2fb1223be}">
					<Property Name="BoolVal" Type="Boolean">false</Property>
					<Property Name="IntVal" Type="Number">0</Property>
					<Property Name="QueryPropertyValueTypeIndex" Type="Number">1</Property>
					<Property Name="StrArray" Type="Null" />
					<Property Name="StrVal" Type="String">Ssa</Property>
				</Parameter>
			</Parameters>
		</Method>
		<ObjectPath Id="16" ObjectPathId="15" />
		<Method Name="Add" Id="17" ObjectPathId="15">
			<Parameters>
				<Parameter Type="String">Path</Parameter>
			</Parameters>
		</Method>
		<Method Name="Add" Id="18" ObjectPathId="15">
			<Parameters>
				<Parameter Type="String">Title</Parameter>
			</Parameters>
		</Method>
		<Method Name="Add" Id="19" ObjectPathId="15">
			<Parameters>
				<Parameter Type="String">
 FileExtension</Parameter>
			</Parameters>
		</Method>
		<Method Name="Add" Id="20" ObjectPathId="15">
			<Parameters>
				<Parameter Type="String">
 SecondaryFileExtension
</Parameter>
			</Parameters>
		</Method>
		<ObjectPath Id="22" ObjectPathId="21" />
		<Method Name="Add" Id="23" ObjectPathId="21">
			<Parameters>
				<Parameter Type="String">Title</Parameter>
			</Parameters>
		</Method>
		<Method Name="Add" Id="24" ObjectPathId="21">
			<Parameters>
				<Parameter Type="String">Path</Parameter>
			</Parameters>
		</Method>
		<Method Name="Add" Id="25" ObjectPathId="21">
			<Parameters>
				<Parameter Type="String">Author</Parameter>
			</Parameters>
		</Method>
		<Method Name="Add" Id="26" ObjectPathId="21">
			<Parameters>
				<Parameter Type="String">SectionNames</Parameter>
			</Parameters>
		</Method>
		<Method Name="Add" Id="27" ObjectPathId="21">
			<Parameters>
				<Parameter Type="String">SiteDescription</Parameter>
			</Parameters>
		</Method>
		<SetProperty Id="28" ObjectPathId="0" Name="TrimDuplicates">
			<Parameter Type="Boolean">false</Parameter>
		</SetProperty>
		<Method Name="SetQueryPropertyValue" Id="29" ObjectPathId="11">
			<Parameters>
				<Parameter Type="String">TryCache</Parameter>
				<Parameter TypeId="{b25ba502-71d7-4ae4-a701-4ca2fb1223be}">
					<Property Name="BoolVal" Type="Boolean">true</Property>
					<Property Name="IntVal" Type="Number">0</Property>
					<Property Name="QueryPropertyValueTypeIndex" Type="Number">3</Property>
					<Property Name="StrArray" Type="Null" />
					<Property Name="StrVal" Type="Null" />
				</Parameter>
			</Parameters>
		</Method>
		<Method Name="SetQueryPropertyValue" Id="30" ObjectPathId="11">
			<Parameters>
				<Parameter Type="String">Scope</Parameter>
				<Parameter TypeId="{b25ba502-71d7-4ae4-a701-4ca2fb1223be}">
					<Property Name="BoolVal" Type="Boolean">false</Property>
					<Property Name="IntVal" Type="Number">0</Property>
					<Property Name="QueryPropertyValueTypeIndex" Type="Number">1</Property>
					<Property Name="StrArray" Type="Null" />
					<Property Name="StrVal" Type="String">{Site.URL}</Property>
				</Parameter>
			</Parameters>
		</Method>
		<Method Name="SetQueryPropertyValue" Id="31" ObjectPathId="11">
			<Parameters>
				<Parameter Type="String">UpdateLinksForCatalogItems</Parameter>
				<Parameter TypeId="{b25ba502-71d7-4ae4-a701-4ca2fb1223be}">
					<Property Name="BoolVal" Type="Boolean">true</Property>
					<Property Name="IntVal" Type="Number">0</Property>
					<Property Name="QueryPropertyValueTypeIndex" Type="Number">3</Property>
					<Property Name="StrArray" Type="Null" />
					<Property Name="StrVal" Type="Null" />
				</Parameter>
			</Parameters>
		</Method>
		<Method Name="SetQueryPropertyValue" Id="32" ObjectPathId="11">
			<Parameters>
				<Parameter Type="String">EnableStacking</Parameter>
				<Parameter TypeId="{b25ba502-71d7-4ae4-a701-4ca2fb1223be}">
					<Property Name="BoolVal" Type="Boolean">true</Property>
					<Property Name="IntVal" Type="Number">0</Property>
					<Property Name="QueryPropertyValueTypeIndex" Type="Number">3</Property>
					<Property Name="StrArray" Type="Null" />
					<Property Name="StrVal" Type="Null" />
				</Parameter>
			</Parameters>
		</Method>
		<Method Name="SetQueryPropertyValue" Id="33" ObjectPathId="11">
			<Parameters>
				<Parameter Type="String">ListId</Parameter>
				<Parameter TypeId="{b25ba502-71d7-4ae4-a701-4ca2fb1223be}">
					<Property Name="BoolVal" Type="Boolean">false</Property>
					<Property Name="IntVal" Type="Number">0</Property>
					<Property Name="QueryPropertyValueTypeIndex" Type="Number">1</Property>
					<Property Name="StrArray" Type="Null" />
					<Property Name="StrVal" Type="String">fb9e18d3-1d80-4ab1-8e76-bc36b0a8e22d</Property>
				</Parameter>
			</Parameters>
		</Method>
		<Method Name="SetQueryPropertyValue" Id="34" ObjectPathId="11">
			<Parameters>
				<Parameter Type="String">ListItemId</Parameter>
				<Parameter TypeId="{b25ba502-71d7-4ae4-a701-4ca2fb1223be}">
					<Property Name="BoolVal" Type="Boolean">false</Property>
					<Property Name="IntVal" Type="Number">6</Property>
					<Property Name="QueryPropertyValueTypeIndex" Type="Number">2</Property>
					<Property Name="StrArray" Type="Null" />
					<Property Name="StrVal" Type="Null" />
				</Parameter>
			</Parameters>
		</Method>
		<Method Name="SetQueryPropertyValue" Id="35" ObjectPathId="11">
			<Parameters>
				<Parameter Type="String">TermId</Parameter>
				<Parameter TypeId="{b25ba502-71d7-4ae4-a701-4ca2fb1223be}">
					<Property Name="BoolVal" Type="Boolean">false</Property>
					<Property Name="IntVal" Type="Number">0</Property>
					<Property Name="QueryPropertyValueTypeIndex" Type="Number">1</Property>
					<Property Name="StrArray" Type="Null" />
					<Property Name="StrVal" Type="String">0bfc89ed-1741-4925-9d25-828eaf74b2c8</Property>
				</Parameter>
			</Parameters>
		</Method>
		<Method Name="SetQueryPropertyValue" Id="36" ObjectPathId="11">
			<Parameters>
				<Parameter Type="String">TermSetId</Parameter>
				<Parameter TypeId="{b25ba502-71d7-4ae4-a701-4ca2fb1223be}">
					<Property Name="BoolVal" Type="Boolean">false</Property>
					<Property Name="IntVal" Type="Number">0</Property>
					<Property Name="QueryPropertyValueTypeIndex" Type="Number">1</Property>
					<Property Name="StrArray" Type="Null" />
					<Property Name="StrVal" Type="String">0f14334e-b929-42bf-ad10-ed6a93d16a4f</Property>
				</Parameter>
			</Parameters>
		</Method>
		<Method Name="SetQueryPropertyValue" Id="37" ObjectPathId="11">
			<Parameters>
				<Parameter Type="String">TermStoreId</Parameter>
				<Parameter TypeId="{b25ba502-71d7-4ae4-a701-4ca2fb1223be}">
					<Property Name="BoolVal" Type="Boolean">false</Property>
					<Property Name="IntVal" Type="Number">0</Property>
					<Property Name="QueryPropertyValueTypeIndex" Type="Number">1</Property>
					<Property Name="StrArray" Type="Null" />
					<Property Name="StrVal" Type="String">c4c58328-0e88-4937-91e9-cf7526b9b0db</Property>
				</Parameter>
			</Parameters>
		</Method>
		<SetProperty Id="38" ObjectPathId="0" Name="ResultsUrl">
			<Parameter Type="String">http://sp2013-dev:18580/DisplayTemplateStyling#k=#s=131</Parameter>
		</SetProperty>
		<SetProperty Id="39" ObjectPathId="0" Name="BypassResultTypes">
			<Parameter Type="Boolean">true</Parameter>
		</SetProperty>
		<SetProperty Id="40" ObjectPathId="0" Name="ClientType">
			<Parameter Type="String">ContentSearchRegular</Parameter>
		</SetProperty>
		<SetProperty Id="41" ObjectPathId="0" Name="EnableInterleaving">
			<Parameter Type="Boolean">false</Parameter>
		</SetProperty>
		<SetProperty Id="42" ObjectPathId="0" Name="ProcessBestBets">
			<Parameter Type="Boolean">false</Parameter>
		</SetProperty>
		<Method Name="SetQueryPropertyValue" Id="43" ObjectPathId="11">
			<Parameters>
				<Parameter Type="String">QuerySession</Parameter>
				<Parameter TypeId="{b25ba502-71d7-4ae4-a701-4ca2fb1223be}">
					<Property Name="BoolVal" Type="Boolean">false</Property>
					<Property Name="IntVal" Type="Number">0</Property>
					<Property Name="QueryPropertyValueTypeIndex" Type="Number">1</Property>
					<Property Name="StrArray" Type="Null" />
					<Property Name="StrVal" Type="String">a4e0e9b5-6dd9-4aea-b38b-26f325c67fdf</Property>
				</Parameter>
			</Parameters>
		</Method>
		<SetProperty Id="44" ObjectPathId="0" Name="ProcessPersonalFavorites">
			<Parameter Type="Boolean">false</Parameter>
		</SetProperty>
		<SetProperty Id="45" ObjectPathId="0" Name="SafeQueryPropertiesTemplateUrl">
			<Parameter Type="String">querygroup://webroot/Pages/DisplayTemplateStyling.aspx?groupname=Default</Parameter>
		</SetProperty>
		<SetProperty Id="46" ObjectPathId="0" Name="IgnoreSafeQueryPropertiesTemplateUrl">
			<Parameter Type="Boolean">false</Parameter>
		</SetProperty>
		<ObjectPath Id="48" ObjectPathId="47" />
		<ExceptionHandlingScope Id="49">
			<TryScope Id="51">
				<Method Name="ExecuteQueries" Id="53" ObjectPathId="47">
					<Parameters>
						<Parameter Type="Array">
							<Object Type="String">26103082-0e16-4ab0-a12c-bded636a7fb8Default</Object>
						</Parameter>
						<Parameter Type="Array">
							<Object ObjectPathId="0" />
						</Parameter>
						<Parameter Type="Boolean">true</Parameter>
					</Parameters>
				</Method>
			</TryScope>
			<CatchScope Id="55" />
		</ExceptionHandlingScope>
	</Actions>
	<ObjectPaths>
		<Constructor Id="0" TypeId="{80173281-fffd-47b6-9a49-312e06ff8428}" />
		<Property Id="3" ParentId="0" Name="SortList" />
		<Property Id="11" ParentId="0" Name="Properties" />
		<Property Id="15" ParentId="0" Name="SelectProperties" />
		<Property Id="21" ParentId="0" Name="HitHighlightedProperties" />
		<Constructor Id="47" TypeId="{8d2ac302-db2f-46fe-9015-872b35f15098}" />
	</ObjectPaths>
</Request>				 				 			 			 		 	 	 		 		 		 		 		 		 	  

Once the server finds the desired search results and processes them, it packages them up as a JSON object and returns that object to the browser for further action. The following is an example of a JSON structure (containing ten results) that was returned for the Swiss Army Knife CSWP as it was shown earlier in the “Better Paging Support” section:

[  
   {  
      "SchemaVersion":"15.0.0.0",
      "LibraryVersion":"15.0.4569.1501",
      "ErrorInfo":null,
      "TraceCorrelationId":"36d5029d-dcee-709e-a995-81ad013126e0"
   },
   119,
   {  
      "IsNull":false
   },
   122,
   {  
      "IsNull":false
   },
   130,
   {  
      "IsNull":false
   },
   134,
   {  
      "IsNull":false
   },
   140,
   {  
      "IsNull":false
   },
   166,
   {  
      "IsNull":false
   },
   171,
   {  
      "418e02d2-9bc5-46fd-ada2-83762ed79256Default":{  
         "_ObjectType_":"Microsoft.SharePoint.Client.Search.Query.ResultTableCollection",
         "ElapsedTime":31,
         "Properties":{  
            "RowLimit":10,
            "SourceId":"\/Guid(8413cd39-2156-4e00-b54d-11efd9abdb89)\/",
            "EnableStacking":true,
            "SerializedQuery":"<Query Culture=\"en-US\" EnableStemming=\"True\" EnablePhonetic=\"False\" EnableNicknames=\"False\" IgnoreAllNoiseQuery=\"True\" SummaryLength=\"180\" MaxSnippetLength=\"180\" DesiredSnippetLength=\"90\" KeywordInclusion=\"0\" QueryText=\"\" QueryTemplate=\"(contentclass:STS_ListItem OR IsDocument:True)\" TrimDuplicates=\"False\" Site=\"e964e9f4-d726-4c46-bda6-00367a81bb29\" Web=\"1b739834-de53-4968-b4cc-04a559306668\" KeywordType=\"True\" HiddenConstraints=\"\" \u002f>"
         },
         "QueryErrors":null,
         "QueryId":"e12d2e7f-598c-4db7-ae6e-fbf021d0b230",
         "SpellingSuggestion":"",
         "TriggeredRules":[  

         ],
         "ResultTables":[  
            {  
               "_ObjectType_":"Microsoft.SharePoint.Client.Search.Query.ResultTable",
               "GroupTemplateId":null,
               "ItemTemplateId":null,
               "Properties":{  
                  "GenerationId":9223372036854775806,
                  "ExecutionTimeMs":16,
                  "QueryModification":"(contentclass:STS_ListItem OR IsDocument:True) -ContentClass=urn:content-class:SPSPeople",
                  "RenderTemplateId":"~sitecollection\u002f_catalogs\u002fmasterpage\u002fDisplay Templates\u002fSearch\u002fGroup_Default.js",
                  "StartRecord":0
               },
               "QueryId":"e12d2e7f-598c-4db7-ae6e-fbf021d0b230",
               "QueryRuleId":"00000000-0000-0000-0000-000000000000",
               "ResultRows":[  
                  {  
                     "Rank":0,
                     "DocId":114,
                     "Path":"http:\u002f\u002fsp2013-dev:18480\u002fSiteAssets\u002fForms\u002fDispForm.aspx?ID=4",
                     "Title":"3. Optimus Prime Part - Button",
                     "OriginalPath":"http:\u002f\u002fsp2013-dev:18480\u002fSiteAssets\u002fForms\u002fDispForm.aspx?ID=4",
                     "PartitionId":"\/Guid(0c37852b-34d0-418e-91c6-2ac25af4be5b)\/",
                     "UrlZone":0,
                     "AAMEnabledManagedProperties":"AttachmentURI;deeplinks;DefaultEncodingURL;ExternalMediaURL;HierarchyUrl;OrgParentUrls;OrgUrls;OriginalPath;ParentLink;Path;PictureThumbnailURL;PictureURL;PublishingImage;recommendedfor;ServerRedirectedEmbedURL;ServerRedirectedPreviewURL;ServerRedirectedURL;SiteLogo;SitePath;SPSiteURL;UserEncodingURL",
                     "RenderTemplateId":"~sitecollection\u002f_catalogs\u002fmasterpage\u002fDisplay Templates\u002fSearch\u002fItem_Default.js",
                     "QueryRuleId":"\/Guid(00000000-0000-0000-0000-000000000000)\/"
                  },
                  {  
                     "Rank":0,
                     "DocId":115,
                     "Path":"http:\u002f\u002fsp2013-dev:18480\u002fSiteAssets\u002fForms\u002fDispForm.aspx?ID=5",
                     "Title":"4. Weather Right Now (Not Really) - Button",
                     "OriginalPath":"http:\u002f\u002fsp2013-dev:18480\u002fSiteAssets\u002fForms\u002fDispForm.aspx?ID=5",
                     "PartitionId":"\/Guid(0c37852b-34d0-418e-91c6-2ac25af4be5b)\/",
                     "UrlZone":0,
                     "AAMEnabledManagedProperties":"AttachmentURI;deeplinks;DefaultEncodingURL;ExternalMediaURL;HierarchyUrl;OrgParentUrls;OrgUrls;OriginalPath;ParentLink;Path;PictureThumbnailURL;PictureURL;PublishingImage;recommendedfor;ServerRedirectedEmbedURL;ServerRedirectedPreviewURL;ServerRedirectedURL;SiteLogo;SitePath;SPSiteURL;UserEncodingURL",
                     "RenderTemplateId":"~sitecollection\u002f_catalogs\u002fmasterpage\u002fDisplay Templates\u002fSearch\u002fItem_Default.js",
                     "QueryRuleId":"\/Guid(00000000-0000-0000-0000-000000000000)\/"
                  },
                  {  
                     "Rank":0,
                     "DocId":116,
                     "Path":"http:\u002f\u002fsp2013-dev:18480\u002fSiteAssets\u002fForms\u002fDispForm.aspx?ID=6",
                     "Title":"5. Weather Right Now Page - Button",
                     "OriginalPath":"http:\u002f\u002fsp2013-dev:18480\u002fSiteAssets\u002fForms\u002fDispForm.aspx?ID=6",
                     "PartitionId":"\/Guid(0c37852b-34d0-418e-91c6-2ac25af4be5b)\/",
                     "UrlZone":0,
                     "AAMEnabledManagedProperties":"AttachmentURI;deeplinks;DefaultEncodingURL;ExternalMediaURL;HierarchyUrl;OrgParentUrls;OrgUrls;OriginalPath;ParentLink;Path;PictureThumbnailURL;PictureURL;PublishingImage;recommendedfor;ServerRedirectedEmbedURL;ServerRedirectedPreviewURL;ServerRedirectedURL;SiteLogo;SitePath;SPSiteURL;UserEncodingURL",
                     "RenderTemplateId":"~sitecollection\u002f_catalogs\u002fmasterpage\u002fDisplay Templates\u002fSearch\u002fItem_Default.js",
                     "QueryRuleId":"\/Guid(00000000-0000-0000-0000-000000000000)\/"
                  },
                  {  
                     "Rank":0,
                     "DocId":117,
                     "Path":"http:\u002f\u002fsp2013-dev:18480\u002fSiteAssets\u002fForms\u002fDispForm.aspx?ID=8",
                     "Title":"6. Weather Right Now Provisioned - Button",
                     "OriginalPath":"http:\u002f\u002fsp2013-dev:18480\u002fSiteAssets\u002fForms\u002fDispForm.aspx?ID=8",
                     "PartitionId":"\/Guid(0c37852b-34d0-418e-91c6-2ac25af4be5b)\/",
                     "UrlZone":0,
                     "AAMEnabledManagedProperties":"AttachmentURI;deeplinks;DefaultEncodingURL;ExternalMediaURL;HierarchyUrl;OrgParentUrls;OrgUrls;OriginalPath;ParentLink;Path;PictureThumbnailURL;PictureURL;PublishingImage;recommendedfor;ServerRedirectedEmbedURL;ServerRedirectedPreviewURL;ServerRedirectedURL;SiteLogo;SitePath;SPSiteURL;UserEncodingURL",
                     "RenderTemplateId":"~sitecollection\u002f_catalogs\u002fmasterpage\u002fDisplay Templates\u002fSearch\u002fItem_Default.js",
                     "QueryRuleId":"\/Guid(00000000-0000-0000-0000-000000000000)\/"
                  },
                  {  
                     "Rank":0,
                     "DocId":119,
                     "Path":"http:\u002f\u002fsp2013-dev:18480\u002fSiteAssets\u002fForms\u002fDispForm.aspx?ID=9",
                     "Title":"8. Donuts And Drinks Pub - Button",
                     "OriginalPath":"http:\u002f\u002fsp2013-dev:18480\u002fSiteAssets\u002fForms\u002fDispForm.aspx?ID=9",
                     "PartitionId":"\/Guid(0c37852b-34d0-418e-91c6-2ac25af4be5b)\/",
                     "UrlZone":0,
                     "AAMEnabledManagedProperties":"AttachmentURI;deeplinks;DefaultEncodingURL;ExternalMediaURL;HierarchyUrl;OrgParentUrls;OrgUrls;OriginalPath;ParentLink;Path;PictureThumbnailURL;PictureURL;PublishingImage;recommendedfor;ServerRedirectedEmbedURL;ServerRedirectedPreviewURL;ServerRedirectedURL;SiteLogo;SitePath;SPSiteURL;UserEncodingURL",
                     "RenderTemplateId":"~sitecollection\u002f_catalogs\u002fmasterpage\u002fDisplay Templates\u002fSearch\u002fItem_Default.js",
                     "QueryRuleId":"\/Guid(00000000-0000-0000-0000-000000000000)\/"
                  },
                  {  
                     "Rank":0,
                     "DocId":688,
                     "Path":"http:\u002f\u002fsp2013-dev:18480\u002fSitePages\u002fWeatherRightNowScraper.aspx",
                     "Title":"WeatherRightNowScraper",
                     "OriginalPath":"http:\u002f\u002fsp2013-dev:18480\u002fSitePages\u002fWeatherRightNowScraper.aspx",
                     "PartitionId":"\/Guid(0c37852b-34d0-418e-91c6-2ac25af4be5b)\/",
                     "UrlZone":0,
                     "AAMEnabledManagedProperties":"AttachmentURI;deeplinks;DefaultEncodingURL;ExternalMediaURL;HierarchyUrl;OrgParentUrls;OrgUrls;OriginalPath;ParentLink;Path;PictureThumbnailURL;PictureURL;PublishingImage;recommendedfor;ServerRedirectedEmbedURL;ServerRedirectedPreviewURL;ServerRedirectedURL;SiteLogo;SitePath;SPSiteURL;UserEncodingURL",
                     "RenderTemplateId":"~sitecollection\u002f_catalogs\u002fmasterpage\u002fDisplay Templates\u002fSearch\u002fItem_Default.js",
                     "QueryRuleId":"\/Guid(00000000-0000-0000-0000-000000000000)\/"
                  },
                  {  
                     "Rank":0,
                     "DocId":683,
                     "Path":"http:\u002f\u002fsp2013-dev:18480\u002fPages\u002fDonutsAndDrinksPub.aspx",
                     "Title":"DonutsAndDrinksPub",
                     "OriginalPath":"http:\u002f\u002fsp2013-dev:18480\u002fPages\u002fDonutsAndDrinksPub.aspx",
                     "PartitionId":"\/Guid(0c37852b-34d0-418e-91c6-2ac25af4be5b)\/",
                     "UrlZone":0,
                     "AAMEnabledManagedProperties":"AttachmentURI;deeplinks;DefaultEncodingURL;ExternalMediaURL;HierarchyUrl;OrgParentUrls;OrgUrls;OriginalPath;ParentLink;Path;PictureThumbnailURL;PictureURL;PublishingImage;recommendedfor;ServerRedirectedEmbedURL;ServerRedirectedPreviewURL;ServerRedirectedURL;SiteLogo;SitePath;SPSiteURL;UserEncodingURL",
                     "RenderTemplateId":"~sitecollection\u002f_catalogs\u002fmasterpage\u002fDisplay Templates\u002fSearch\u002fItem_Default.js",
                     "QueryRuleId":"\/Guid(00000000-0000-0000-0000-000000000000)\/"
                  },
                  {  
                     "Rank":0,
                     "DocId":685,
                     "Path":"http:\u002f\u002fsp2013-dev:18480\u002fSitePages\u002fDonutsAndDrinks.aspx",
                     "Title":"DonutsAndDrinks",
                     "OriginalPath":"http:\u002f\u002fsp2013-dev:18480\u002fSitePages\u002fDonutsAndDrinks.aspx",
                     "PartitionId":"\/Guid(0c37852b-34d0-418e-91c6-2ac25af4be5b)\/",
                     "UrlZone":0,
                     "AAMEnabledManagedProperties":"AttachmentURI;deeplinks;DefaultEncodingURL;ExternalMediaURL;HierarchyUrl;OrgParentUrls;OrgUrls;OriginalPath;ParentLink;Path;PictureThumbnailURL;PictureURL;PublishingImage;recommendedfor;ServerRedirectedEmbedURL;ServerRedirectedPreviewURL;ServerRedirectedURL;SiteLogo;SitePath;SPSiteURL;UserEncodingURL",
                     "RenderTemplateId":"~sitecollection\u002f_catalogs\u002fmasterpage\u002fDisplay Templates\u002fSearch\u002fItem_Default.js",
                     "QueryRuleId":"\/Guid(00000000-0000-0000-0000-000000000000)\/"
                  },
                  {  
                     "Rank":0,
                     "DocId":686,
                     "Path":"http:\u002f\u002fsp2013-dev:18480\u002fSitePages\u002fMakingPiTakesEffort.aspx",
                     "Title":"MakingPiTakesEffort",
                     "OriginalPath":"http:\u002f\u002fsp2013-dev:18480\u002fSitePages\u002fMakingPiTakesEffort.aspx",
                     "PartitionId":"\/Guid(0c37852b-34d0-418e-91c6-2ac25af4be5b)\/",
                     "UrlZone":0,
                     "AAMEnabledManagedProperties":"AttachmentURI;deeplinks;DefaultEncodingURL;ExternalMediaURL;HierarchyUrl;OrgParentUrls;OrgUrls;OriginalPath;ParentLink;Path;PictureThumbnailURL;PictureURL;PublishingImage;recommendedfor;ServerRedirectedEmbedURL;ServerRedirectedPreviewURL;ServerRedirectedURL;SiteLogo;SitePath;SPSiteURL;UserEncodingURL",
                     "RenderTemplateId":"~sitecollection\u002f_catalogs\u002fmasterpage\u002fDisplay Templates\u002fSearch\u002fItem_Default.js",
                     "QueryRuleId":"\/Guid(00000000-0000-0000-0000-000000000000)\/"
                  },
                  {  
                     "Rank":0,
                     "DocId":139,
                     "Path":"http:\u002f\u002fsp2013-dev:18480\u002fSitePages\u002fOptimusPrimePart.aspx",
                     "Title":"OptimusPrimePart",
                     "OriginalPath":"http:\u002f\u002fsp2013-dev:18480\u002fSitePages\u002fOptimusPrimePart.aspx",
                     "PartitionId":"\/Guid(0c37852b-34d0-418e-91c6-2ac25af4be5b)\/",
                     "UrlZone":0,
                     "AAMEnabledManagedProperties":"AttachmentURI;deeplinks;DefaultEncodingURL;ExternalMediaURL;HierarchyUrl;OrgParentUrls;OrgUrls;OriginalPath;ParentLink;Path;PictureThumbnailURL;PictureURL;PublishingImage;recommendedfor;ServerRedirectedEmbedURL;ServerRedirectedPreviewURL;ServerRedirectedURL;SiteLogo;SitePath;SPSiteURL;UserEncodingURL",
                     "RenderTemplateId":"~sitecollection\u002f_catalogs\u002fmasterpage\u002fDisplay Templates\u002fSearch\u002fItem_Default.js",
                     "QueryRuleId":"\/Guid(00000000-0000-0000-0000-000000000000)\/"
                  }
               ],
               "ResultTitle":null,
               "ResultTitleUrl":null,
               "RowCount":10,
               "TableType":"RelevantResults",
               "TotalRows":179,
               "TotalRowsIncludingDuplicates":179
            }
         ]
      }
   },
   167,
   {  
      "HasException":false,
      "ErrorInfo":null
   }
]

This JSON structure contains a lot of information – certainly more information than is being displayed by the CSWP. The trick, of course, is in figuring out exactly “what” is “where” for purposes of building a paging system.

Page-Related Processing Within The Control Template

Thankfully, the CSWP provides us with a relatively easy mechanism for getting at the search result data we care about within the JSON object that is returned from the call to client.svc. When a Control display template is invoked by the CSWP, it is passed a context object as follows:

function DisplayTemplate_2aa45a743fd94e75a3e53c940628e2ec(ctx) { ... } 

ctx Content ObjectThe ctx context object contains a number of useful methods, properties, and subordinate objects we can leverage in our attempts to manipulate search results and calculate paging information. We can use ctx to interact directly with the CSWP (which is accessible through the ClientControl property), as well as obtain the search results themselves (and information about them) through the ListData property.

Note: Even though Microsoft’s List with Paging Control template doesn’t provide anything more than relative paging forward and backward, the CSWP does appear to support some form of more advanced paging scheme through its get_pagingInfo() method. When this method is called, it returns an object that contains expanded paging information that includes information about the current page, as well as a subset of pages before and after the current page. The object does not, however, contain all of the information needed to determine the total number of items in the search result set, how to access those pages, etc.

Fortunately for us, though, the ctx.ListData object contains everything we need to implement an end-to-end paging system. Here’s how each of the critical paging information pieces is located or computed within the Control template so that the portion of the control seen below can be rendered:

Paging Line

  • ctx.ListData InspectionTotal number of all search results available. The totalRowCount variable is used within the Control display template scripting to store this value. And the value itself is readily available through the ctx.ListData.ResultTables[0].TotalRows property.
  • Maximum number of items to display per page. This value (represented within the Control display template scripting as rowsPerPageCount) is easily obtained through the ctx.ListData.Properties.RowLimit property. It identifies the maximum number of rows that may be returned in the search results table (through ctx.ListData.ResultTables[0]), and it is the value which should be used to determine the number of individual search results shown in the CSWP.
  • Number of items to display on the current page. In most cases, this value (defined through the rowsOnCurrentPageCount variable within the Control display template scripting) will be the same as the maximum number of items per page. On the last page of results, though, it isn’t uncommon for there to be fewer results available than the maximum number possible. To determine how many items should be shown on the current page of search results, the script simply determines how many rows are present in the current search results table (ctx.ListData.ResultTables[0].RowCount).
  • First page number for the result set. As my kids would say, “Easy peasy lemon squeezy.” This variable (firstPageNumber) always has the intuitive value of 1. This variable should not be confused with the firstPage variable that commonly appears in the OOTB display template scripting. The reference which is assigned to the firstPage variable is a PagingLink object that is meaningful within the context of the pagingInfo object returned from the call to the ctx.ClientControl.get_pagingInfo() – not the page calculations in the display templates associated with this post.
  • Last page number for the result set. This value (represented by the lastPageNumber variable) isn’t readily available in a way that can be “plucked” out of the search data, so the display template scripting simply does a little math to calculate it: Math.ceil(totalRowCount /rowsPerPageCount). In non-code terms: the last page of the total search results set is the total number of results in the set divided by the number of results displayed per page, rounded-down. As with the firstPageNumber and firstPage variables, don’t confuse lastPageNumber with the OOTB lastPage object reference.

In addition to the values described above, a series of calculations are performed to determine the currentPageStartItem and currentPageEndItem variables that represent the first and last item numbers on the current page. Once these values are known and assigned to their respective variables, it becomes a relatively straightforward exercise to display the paging information as is done within the SwissArmy_Control_Template.js Control template. The (not-so-heavy) lifting is accomplished with the following Javascript:

// Figure out the current page information
for (var i = 0; i< pagingInfo.length; i++)
{
	var pl = pagingInfo[i];
	if (!$isNull(pl))
	{
		if (pl.startItem == -1)
		{
			currentPage = pl;
			currentPageNumber = pl.pageNumber;
			currentPageStartItem = ((currentPageNumber - 1) * rowsPerPageCount) + 1;
			if (currentPageNumber == lastPageNumber) {
				currentPageEndItem = totalRowCount;
			} else {
				currentPageEndItem = currentPageNumber * rowsPerPageCount;
			}
		}
	}
}

// Generate page divs and their links
var getPageNumberDivs = function() {
	var currentDiv, divBlocks, pageStartItem;
	divBlocks = '';
	for (var i = firstPageNumber; i <= lastPageNumber; i++) {
		cellStyle = 'sas-paging-tablecell';
		if (i == currentPageNumber) {
			currentDiv = '<div class="sas-paging-tablecell sas-paging-currentpage">';
			currentDiv += i;
			currentDiv += '</div>';
		} else {
			pageStartItem = ((i - 1) * rowsPerPageCount) + 1;
			currentDiv = '<div class="sas-paging-tablecell">';
			currentDiv += '<a href="#" onclick="$getClientControl(this).page(' + $htmlEncode(pageStartItem) + ');return Srch.U.cancelEvent(event);">';
			currentDiv += i;
			currentDiv += '</a></div>';
		}
		divBlocks += currentDiv;
	}
	return divBlocks;
}

// Generate the block that indicates current page, item counts, etc.
var getPageSummary = function() {
	var currentDiv;
	var pageInfo = 'Page {1} of {2}, items {3} to {4} of {5}.';
	pageInfo = pageInfo.replace('{1}', '<span>' + currentPageNumber + '</span>');
	pageInfo = pageInfo.replace('{2}', '<span>' + lastPageNumber + '</span>');
	pageInfo = pageInfo.replace('{3}', '<span>' + currentPageStartItem + '</span>');
	pageInfo = pageInfo.replace('{4}', '<span>' + currentPageEndItem + '</span>');
	pageInfo = pageInfo.replace('{5}', '<span>' + totalRowCount + '</span>');
	currentDiv = '<div class="sas-paging-tablecell sas-paging-summary">' + '</span>';
	currentDiv += pageInfo + '</div>';
	return currentDiv;
}

ms_outHtml.push(''
,''
,'			</ul>'
,''
,'			<div class="sas-paging-table">'
,'				<div class="sas-paging-tablerow">'
,'					', getPageNumberDivs() ,''
,'					', getPageSummary() ,''
,'				</div>'
,'			</div>'
,'		</div>'
,'		'
);

Creating The Page Links

One area does warrant a little more explanation, though, and that is how the hyperlinks are created for each of the clickable page numbers at the bottom of the CSWP. There really isn’t a whole lot of magic behind the creation of the hyperlinks themselves; the results are achieved on line 101 of the SwissArmy_Control_Template.js file:

 
currentDiv += '<a href="#" onclick="$getClientControl(this).page(' + $htmlEncode(pageStartItem) + ');return Srch.U.cancelEvent(event);">';

The pageStartItem variable value is computed as follows …

 
pageStartItem = ((i - 1) * rowsPerPageCount) + 1; 

… where i is the value of the new result page being clicked by the user. For example, if the user clicks on “17” (to indicate a desire to move to page 17 of the search results), the value of i will be 161 when there are 10 items per page.

http://sp2013-dev:18580/DisplayTemplateStyling#k=#s=161

On the server side, SharePoint translates the request for 161 (which can also be reached directly via re-post by attaching a #s=161 to the query string portion of the URL as shown above) to package-up and send down a search results table containing all of the page 17 result items.

How Do I Use The Sample (Downloadable) Files?

Once you’ve downloaded the SwissArmyTemplates.zip file and opened it up, you’ll find that it contains five files:

  • SwissArmy_Control_Template.html
  • SwissArmy_Control_Template.js
  • SwissArmy_Item_Template.html
  • SwissArmy_Item_Template.js
  • SwissArmy_Styles.css

The two HTML files are each of the display templates in their HTML form. These HTML files can be processed through SharePoint 2013’s Design Manager to generate the corresponding JavaScript files that are actually used by the CSWP. Alternatively, the JS files that are included in the ZIP file can be used as-is and dropped directly into the Master Page Gallery > Display Templates > Content Web Parts folder within a site collection to make them available to the CSWP.

The remaining file is a CSS style sheet, and it provides the look and feel that is employed by the display templates. The style sheet itself is referenced from with the Control template files (SwissArmy_Control_Template.html and SwissArmy_Control_Template.js), and the Control template files assume that the style sheet will be available in the following location within the site collection:

~sitecollection/Style Library/en-us/SwissArmyStyles/SwissArmy_Styles.css

If you place the style sheet somewhere else in the site collection, ensure that the $includeCSS() calls in the SwissArmy_Control_Template.html file (line 25) and the SwissArmy_Control_Template.js file (line 164) are updated accordingly.

Final Request

Thanks for citing appropriatelyAs with all of the resources I make available, please feel free to use the display templates and style sheet I’ve provided within your own projects, either as-is or in a form that you’ve modified to suit your needs.

If you do share or redistribute what I’ve provided in some form, whether or not you’ve made modifications, I simply ask that you reference the original source (i.e., me and/or this blog post) in what you’re sharing. I do believe in citing sources where appropriate.

Thanks, and have fun paging through search results!

References and Resources

  1. SharePoint Interface: Files for the Swiss Army Knife CSWP example
  2. MSDN: Content Search Web Part in SharePoint 2013
  3. MSDN: SharePoint 2013 Design Manager display templates
  4. MSDN: Overview of Design Manager in SharePoint 2013
  5. SharePoint Interface: Presentation for SharePoint’s New Swiss Army Knife: The Content Search Web Part
  6. MSDN: 3.1.4.1 ProcessQuery
  7. JSON.org: Introducing JSON