Me & My SharePoint [FrontEnd]

© Christian Stahl – All about SharePoint branding & customizations

Most visited sites in SharePoint 2013 — April 30, 2015

Most visited sites in SharePoint 2013

Hi! Here come’s just a short blog post about how to Query the REST search api in SharePoint 2013, Online or On prem to display most visited sites that could look something like the image below. Take not that you should be able to get something similar with a content search web part with help of a custom display template as well. But if you need to display this in an app part or a script web part I hope this could be in any help.

TopSite

Let’s try this!

Download my experimental code from here, and please if you found something that can be written better or if you have any other ideas regarding this, drop me a comment!

Take a look at some other posts about REST in SharePoint I’ve written Before, you’ll find them over here

The main parts of this is the search API

_api/search/query?querytext=

And the ViewsLifeTime property

ViewsLifeTime

/Christian

Getting started with REST in SharePoint 2013 – Part VIII — December 31, 2014

Getting started with REST in SharePoint 2013 – Part VIII

Welcome to the last post in this series about REST in SharePoint 2013. In this post it’s time to take a look into Knockout, a JS library that let’s you associate DOM elements with ‘model data’, instead of pushing or appending data by JS you can separate markup from the JS. You can think of Knockout as a general way to make UIs for editing JSON data.

Please read the previous posts in this series before you go on to this post:

Hey what’s Knockout?

Knockout js (shortly called KO) is a popular JS library that helps to create rich & interactive web applications. It works directly with the web application’s underlying data model. Using KO with any web application is simple, clean and straightforward. Its powerful in the context of dynamic UI creation.

In previous example I’ve used jQuery for the Ajax stuff, but what should you use? Well KO doesn’t compete with jQuery or similar low-level DOM APIs. KO provides a complementary, high-level way to link a data model to a UI. KO itself doesn’t depend on jQuery, but you can certainly use jQuery at the same time, and indeed that’s often useful if you want things like animated transitions. I would try to use KO in the first hand if it’s about a more complex structure of data you are going do display in let’s say an app, otherwise if its just about to roll up some stuff from a list in SharePoint I would just do as described in the previous posts in this series. Please note that KO is not the only player here, there are as always a bunch of alternative techniques and framworks out there, but that’s maybe a subject for a another post in the future.

KO in short

  • Declarative bindings
  • Pure JS, minimal and works cross browser
  • A framework that let’s you build interactive CRUD applications in SharePoint with help of REST

Let’s try Knockout!

For this example I have created a custom list called ‘Knockout’ in a subsite called ‘knockout’ below the root site collection. I have added two custom columns (multiple text) to the list called ‘Introduction’ and ‘Content’ and added a few example items. The idea is to display the content from the list in a app or web part on the start page of the root site. How to create an app or web part is out of scoope for this post, if you want to try this you can just add this stuff into a textfile in a document library in the root site and use a content editor and link it to the textfile including the JS and the markup you’ll find down below.

KnockOut

It’s a standard SharePoint list at the top, and below is an example of you can create your own custom look and feel with help of KnockOut

<script type="text/javascript" src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.11.1.min.js"></script>
<script type="text/javascript" src="https://ajax.aspnetcdn.com/ajax/knockout/knockout-3.1.0.js"></script>
<script type="text/javascript">
var rootSite = "https://swe.sharepoint.com/";
var subSite = "knockout";
var results = [];

function LoadStuff(index) {
$.ajax({
url: rootSite + subSite + "/_api/web/lists/GetByTitle('KnockoutList')/items",
method: "GET",
headers: {"Accept": "application/json; odata=verbose"},	
  success: function(data){
    results.push.apply(results, data.d.results);
    ko.applyBindings(results);
  },
  error: function (fn, status, error) {
    alert('Error:' + error);
  }	
});
}
$(function(){LoadStuff(0)})
</script>

<div>
<div data-bind="template:{name:'KoList', foreach:results, as:'rows'}"></div>
<script type="text/html" id="KoList">
  <table cellpadding="0" cellspacing="0" class="knockOutTable">
    <tr>
     <td id="td-alfa" data-bind="text:Title"></td>
     <td id="td-beta" data-bind="text:Introduction"></td>
     <td id="td-gamma" data-bind="text:Content"></td>
  </tr>
  </table>
</script>
</div>

Download the complete example with CSS from here

Find more information on the Knockout site

Thats the last post in this series about REST, hope you liked it!

/ Christian

Getting started with REST in SharePoint 2013 – Part VII — November 30, 2014

Getting started with REST in SharePoint 2013 – Part VII

Welcome to post number seven in this series about REST in SharePoint 2013. In the previous posts I wrote about how to interact with the search API.
This time, we will take a look at how to use search queries together with a graphQuery. Graph Query Language (GQL) is designed to query the Office graph via the SharePoint Online Search REST API.

Please read the previous posts in this series before you go on to this post:

Delve

Take advantage of Office Graph in your SharePoint Online apps

Office Graph, can be seen as an underlying intelligence layer that leverages machine learning to surface information and content that is relevant to a user’s project, role and responsibilities within an organization.
Delve is powered by Office Graph (built on top of it), but what’s about to use this Office Graph layer and build an app that you can customize the way you want? You can build an App much like the Delve interface but from you own needs!
The following example will get a list of Items viewed by a actor (in this case the logged in user) the last three months, sort by ranking. You can turn around the information through the GQL in many different ways and combinations and even combine this with SharePoint search. Heres a few example of what you can get:

  • Object related to a specific person or current user
  • trending items
  • Related items
  • Recently viewed items

The following example will get a list of Items viewed by a actor (in this case the current user) the last three months, sort by ranking.

Download all the code here, including CSS. Just paste the code in a txt file and upload this in a document library in your SharePoint Online intranet and add a content editor web part onto a page in SharePoint, a add a reference to the .txt file for testing this out.

var actorId = 'ME' 
var actorGQL = "ACTOR(" + actorId + "\\, action\\:1001)";

  var searchQuery = _spPageContextInfo.webAbsoluteUrl + "/_api/search/query?Querytext='*'&Properties='GraphQuery:" + actorGQL + "'&RowLimit=10&SelectProperties='Path,Title,Rank,ViewsLifeTime,FileType,LastModifiedTime'"
	$.ajax({
		url: searchQuery,
		method: "GET",
		headers: {"Accept": "application/json; odata=verbose"},
		success: onQuerySuccess,
		error: onQueryFail
	});

   	function onQuerySuccess(data) {
  
		var items = [];
			items.push("<ul id='listContainer'>");
	        items.push("<div id='listHeader'>" + 'Delve says..' + "</div>");

		    if (data.d.query.PrimaryQueryResult.RelevantResults.Table.Rows.results.length == 0) {
		        $("#listResult").append('No results..');
		    }
		    else{
			$(data.d.query.PrimaryQueryResult.RelevantResults.Table.Rows.results).each(function(){

			var path = keyValue(this, 'Path');
			var title = keyValue(this, 'Title');
			var FileType = keyValue(this, 'FileType');	
			

	
			// get the file extension 
				var iconUrl =  "/_layouts/15/images/";
				var filename = path.substring(path.lastIndexOf('.')+1);
				
				if (filename == 'pdf') {
					var iconPath = iconUrl + 'ic' + filename + '.png';
				}
				else if (filename == 'PDF'){
					var iconPath = iconUrl + 'ic' + filename + '.png';
				}
				else{
					var iconPath = iconUrl + 'ic' + filename + '.png';
				}
				
				
				
			// convert date
			var modified = moment(keyValue(this, 'LastModifiedTime')).format("YYYY-MM-DD");
				if (!moment(modified,'YYYY-MM-DD').isValid()) {
					var modified = 'Date is not applicable..';
				} 
				else {
					var modified = moment(keyValue(this, 'LastModifiedTime')).format("YYYY-MM-DD");
				}		

				items.push('<li id="' + 'listContent' + '">' +     		
				    			'<span id="' + 'listContentInner' + '">' + 
					    			'<img src="' +  iconPath + '">' + ' <a href="' + path + '">' +  title + '</a>' +
					        	'</span>' + 
					        	'<span id="' + 'listContentInnerTime' + '">' + 
					        		' - ' + modified +
					        	'</span>' + 
				    		'</li>');
				    		
					});

				items.push("</ul>");
			
			$("#listResult").html(items.join(''));

   			} 
   		}

    function keyValue(row, fldName) {
        var ret = null;
        $.each(row.Cells.results, function () {
            if (this.Key == fldName) {
                ret = this.Value;
            }
        });
        return ret;
    } 

    function onQueryFail(sender, args) {
		$("#listResult").append('Query failed. Error:' + args.get_message());
    }

Read more about GQL and search REST API at MSDN
http://msdn.microsoft.com/en-us/office/office365/howto/query-Office-graph-using-gql-with-search-rest-api

Don’t use this in production yet, it could be some changes in the API. The Office Graph are in the time of writing in preview status.

Stay in tune for more posts!
/ Christian

Getting started with REST in SharePoint 2013 – Part VI — October 30, 2014

Getting started with REST in SharePoint 2013 – Part VI

Welcome to the sixt post in this series about REST in SharePoint 2013. In the previous posts I wrote about how to get external data into your SharePoint page. This time I’m stepping back into how to read information from SharePoint, and this time we will take a look into an example about how to use the SharePoint 2013 Search REST API, one of the most powerful REST access points in SharePoint, and yes, this will work the same no matter if it’s SharePoint Online or SharePoint Onprem.

Please read the previous posts in this series before you go on to this post:

SharePoint 2013 Search REST API

First of all, take a look at the overview at Office Dev center: http://msdn.microsoft.com/en-us/library/office/jj163876(v=office.15).aspx – from this page you can learn all the basic stuff about how to construct queries and parameters. The REST Search API gives a lot of possibilities, you can basically retrive just anything that the serach in SharePoint will index! Take a look at Chris O’Briens blog post as an cool example about how to use REST search API, an example that shows how to get related items to the content in an app.

In the following example I’ll show you how to create a table based on a search Query, just a single Word that’s stored as a variable. Instead of the Word ‘SharePoint’ you could for example store something more dynamic like a metadata onto the current page. Let’s say you add this in a page layout and use it to display other pages that are in some way related to this page.

App

Let’g go!

 

var queryText = 'SharePoint'
var startrow = '&amp;startrow=0'
var rowlimit = '&amp;rowlimit=10'
var searchQuery = _spPageContextInfo.webAbsoluteUrl + &quot;/_api/search/query?querytext='&quot; + queryText + &quot;'&quot; + rowlimit + startrow;

$.ajax({
url: searchQuery,
method: &quot;GET&quot;,
headers: {&quot;Accept&quot;: &quot;application/json; odata=verbose&quot;},
success: onQuerySuccess,
error: onQueryFail
});

function onQuerySuccess(data) {

var items = [];
items.push(&quot;&lt;ul id='listContainer'&gt;&quot;);
items.push(&quot;&lt;div id='listHeader'&gt;&quot; + 'Search results..' + &quot;&lt;/div&gt;&quot;);

if (data.d.query.PrimaryQueryResult.RelevantResults.Table.Rows.results.length == 0) {
$(&quot;#listResult&quot;).append('No results..');
}
else{
$(data.d.query.PrimaryQueryResult.RelevantResults.Table.Rows.results).each(function(){

var path = keyValue(this, 'Path');
var title = keyValue(this, 'Title');
var created = moment(keyValue(this, 'Write')).format(&quot;YYYY-MM-DD&quot;);
if (!moment(created,'YYYY-MM-DD').isValid()) {
var created = 'Date is not applicable..';
}
else {
var created = moment(keyValue(this, 'Write')).format(&quot;YYYY-MM-DD&quot;);
}

items.push('&lt;li id=&quot;' + 'listContent' + '&quot;&gt;' +
'&lt;span id=&quot;' + 'listContentInner' + '&quot;&gt;' +
'&lt;a href=&quot;' + path + '&quot;&gt;' +  title + '&lt;/a&gt;' +
'&lt;/span&gt;' +
'&lt;span id=&quot;' + 'listContentInnerTime' + '&quot;&gt;' +
' - ' + created +
'&lt;/span&gt;' +
'&lt;/li&gt;');
});

items.push(&quot;&lt;/ul&gt;&quot;);

$(&quot;#listResult&quot;).html(items.join(''));

}
}

function keyValue(row, fldName) {
var ret = null;
$.each(row.Cells.results, function () {
if (this.Key == fldName) {
ret = this.Value;
}
});
return ret;
}

function onQueryFail(sender, args) {
$(&quot;#listResult&quot;).append('Query failed. Error:' + args.get_message());
}

It’s a bit tricky to find the structure of the nodes, but if you using for example Advanced REST client in google chrome you’ll find it. Take a look at this image, hope this will help you to figure out the path for the data results: data.d.query.PrimaryQueryResult.RelevantResults.Table.Rows.results

Nodes

You can download the file from here, including the CSS and script references