Monday, April 30, 2012

SharePoint 2010 Random Image via REST Api

Want to display a random picture on your web page without a single line of code? Well, server side code that is?
Great. thanks to the REST API in SharePoint 2010 this has become rather simple to achieve.
To achieve the desired effect you will need to follow following steps:
1) Add a picture library to your site
2) Upload the JQuery script sourec to your site
3) create the js file which will pull a random number and add it to your site
4) create a txt file which will refrence both the jquery and your own script files in script blocks
Add a div to that txt file with id=randomimage
5) add a content editor web part to your page
6) point the content editor web part to your txt file which in turn loads the JQuery,custom script files and the placeholder html

Now the tricky bit is the custom script file. That's why I'm posting my version here for you to mimic:

var pictureCount;
var randNum;
var runningCount = 0;
$().ready(function() {

 getPicture();

});

function getPicture()
{
$.getJSON("/General/_vti_bin/listdata.svc/Photos/$count",{},setPictureCount);
}

function setPictureCount(data)
{
pictureCount = data;
randNum = Math.floor (Math.random ( ) * pictureCount);
$.getJSON("/General/_vti_bin/listdata.svc/Photos?$select=Path,Name&$top=1&$skip=" + randNum,{},displayPhoto);
}

function displayPhoto(data)
{
 if (data.d.Name.toLowerCase().indexOf("jpg") == -1)
 {
  runningCount = runningCount +1;
  if (runningCount <5)
  {
   getPicture();
  }
 }
 var url = data.d[0].Path + "/_w/" + data.d[0].Name.replace(".","_") + ".jpg";
$('#randomImage').html('<img src="' + url  + '"/>');
}


This is what happens:
1) once the document has loaded I execute the REST api to find the total amount of items in the picture library. TIP: the returned data object itself holds the data if the REST returns scalar (single value)
2) with the count I then go and create a random number within the range.
3) using that random number I call the picture library again and pull out the Path and the Name. Careful not to confuse the (1) function you can use to retrieve a list item by ID with an indexer. It is not an indexer! /Photos(15) will give you back the Photo with ID 15 and not the 15th element in the collection. To get the nth item use skip and top. $top to tell the call to only retrieve one item (albeit in a collection) and $skip to skip over the first n items. You will get a collection of 1 items back. So make sure to use an indexer when retrieving the values of the result set. [0] normally does the trick.

TIP: if more than one value is returned, but only one single item, then the values are to be found directly under data.d (If a collection of items is returned you must use data.d.results and iterate through it)

4) If I pulled out an item which is not a picture (for example a folder) then try the game again. Up to 5 times. Don't want to crash in an endless loop, now do we.
6) if it is a valid image, then create a random image in a placeholder on the page. (placeholder is best defined in the content editor txt file)

SharePoint 2010 Random Picture Web Part

We used to have a picture of the day web part back in 2007. Why the team took it out I don't know. But hey, we now need to find our own solutions to the problem.
Also, the Slideshow Web Part and view can not cope with folders. They simply won't show pictures in folders of an image library. Thus a different solution is needed altogether.

The easiest approach without any coding can be achieved through a clever combinaiton of JQuery and a CQWP.

CQWP Configurations:
1) add the content query web part to the page and set it to select  from the picture library in question
2) configure the cqwp to only show Document types, specifically Pictures
3) change the default style to include the image. That will then pre-populate the Thumbnail URL as a field it will use
4) Limit the amount of items returned. You don't want to load all images onto the page before randomising it. (I set mine to 20)

JQuery bits:
4) upload jquery-1.7.2.min.js to your server and reference it
5) add some JQuery to the page which selects a random item from the list
6) replace the _t part of the url with _w to give us the slightly bigger image version
7) then replace the html of the webpart with just one image

Code sample:
First, create an array of all items resturned by the cqwp.
Then create a random number from the array
Then select a random li and its associated image
Finally replace the web part html with just an image tag where you replaced the Thumbnail Url with the Web Friendly Url of the image


$().ready(function() {
  var $imageArr = $('ul.dfwp-column li'),
      imageArrLength = $imageArr.length,
      randNum = Math.floor ( Math.random ( ) * imageArrLength + 1 );
      // show image that is nth child of image array
  var img = $("ul.dfwp-column li:eq(" + randNum + ") a img");
 
    img.parents("div[id^=WebPart]").html('<img src="' + img.attr("src").replace("_t","_w") + '"/>');
});
Pros and Cons:
Pro: fast to deploy, No code, can select from multiple libraries and folders thanks to CQWP
Cons: limited set of images to choose from. A larger range of images to chose from could be achieved through combining JQuery and the REST API.  Of course you could change the cqwp to retrieve 100 images, but the page load would suffer greatly!