5/29/2010

SharePoint: Rotating Pictures, Random Pictures (yet again!)

 

This little Content Editor Web Part trick has turned out to be pretty popular. Too popular… it has generated a lot of requests for “could also add…”.  So here are two of those, navigation buttons, and caption text.

 

image

 

First go the original article and read about how this all works:
   http://techtrainingnotes.blogspot.com/2009/07/sharepoint-rotating-pictures-random.html

 

What’s been added:

  • Two new options:
    • manualClick – set this to true to display the First, Previous, Play, Next and Last buttons
    • customTextColumn – set this to true to add a “caption” or custom text

What else you will need/want to do:

  • Customize the HTML at the end of the code. My example puts the picture on the left and the text on the right and left aligns the buttons
  • Replace the navigation hyperlinks with real buttons or images

Now the revised steps to setup this up:

  • Create your picture library and upload your pictures
     
  • If you would like to supply text/captions for the pictures, add a “Single line of text” or “Multiple lines of text” column 
     
  • If you would like to filter the list of pictures to be displayed, customize the library to add additional columns to how the filter data. (Event name, department, product, etc)
     
  • Go to your web part page and add the web part for the new library
     
  • Important steps:
    • Click Edit, Modify Shared Web Part
    • Optional: In the appearance section give the web part a meaningful name
    • Click Edit the Current View
    • Un-checkmark all of the columns except for “Name (linked to document)”
    • Checkmark a column to use for the custom URL (if you don’t have a custom URL then select any column)   (this must be the second column in the view)
    • Checkmark a column to use as a custom text/caption (this must be the third column in the view)
    • Optional: Set the sort order
    • Optional: Set filter options to select only the pictures you want displayed
    • Make sure the the list web part view is not using a "Item Limit" less then the number of pictures in the list. (You could just set this to be BIG number).
    • Click OK to save the view changes
    • Click OK to save the web part changes
       
  • Add a Content Editor Web Part (CEWP) below the picture library web part
     
  • Click Edit, Modify Shared Web Part
     
  • Click Source Editor
     
  • Copy and paste the code from below
  • Edit the “vars” at the beginning of the JavaScript
    • pictureWebPartName – enter the web part, and if your library has a description, then include it:
         Example: Library name: “Airshow Pictures”
                 var pictureWebPartName="Airshow Pictures
         Example: Library name: “Airshow Pictures”,  description: “Pictures from the Dayton Airshow” 
                 var pictureWebPartName="Airshow Pictures -  Pictures from the Dayton Airshow”
       
    • Also edit showThumbnails, randomImg, useCustomLinks, RotatingPicturesLoopTime, imgToImgTransition, manualClick and customTextColumn as needed
       
  • Click OK for the Source Editor
     
  • Click OK to save the web part changes
     
  • Click Exit Edit Mode and see if it works!
     

The Code

<script>
// another CEWP trick from http://techtrainingnotes.blogspot.com
var pictureWebPartName="Airshow Pictures - Pictures from the Dayton Airshow"; // name of the picture library web part
var showThumbnails = true;      //otherwise show full sized images
var randomImg = true;           //set to true to show in random order
var useCustomLinks = true;     //true to use second column as URL for picture clicks
var RotatingPicturesLoopTime = 5000;  //2000 = 2 seconds
var imgToImgTransition = 1.0;         //2 = 2 seconds  
var manualClick = true;         //true to use the play pause buttons
var customTextColumn = true;    //true to display text / caption

// don't change these
var selectedImg = 0;
var imgCache = [];
var imgTag;

function RotatingPictures()
{

  if (manualClick) {buttonRow.style.display="inline"};
  if (customTextColumn == "") {customTextTD.style.display="none"}

  imgTag = document.getElementById("RotatingImage");
  //Find the picture web part and hide it
  var Imgs = [];
  var x = document.getElementsByTagName("TD"); // find all of the table cells
  var LinkList;
  var i=0;

  for (i=0;i<x.length;i++) 
  {
    if (x[i].title == pictureWebPartName)
    {
      // tables in tables in tables... ah SharePoint!
      LinkList = x[i].parentNode.parentNode.parentNode.parentNode.parentNode.parentNode.parentNode;
      // hide the links list web part
      LinkList.style.display="none"; 
      break;
    } 
  }

  if (!LinkList)
  {
    document.all("RotatingImageMsg").innerHTML="Web Part '" + pictureWebPartName + "' not found!";
  }

  //Copy all of the links from the web part to our array

  var links = LinkList.getElementsByTagName("TR") // find all of the rows
  var url;
  var len;
  for (i=0;i<links.length;i++) 
  {
    
    if (links[i].childNodes[0].className=="ms-vb2")
    {
      len=Imgs.length
      Imgs[len]=[]
      Imgs[len][0] = links[i].childNodes[0].childNodes[0].href;
      if (useCustomLinks)
      {
        if (links[i].childNodes[1].childNodes.length>0)
         { Imgs[len][1] = links[i].childNodes[1].childNodes[0].href; }
         else
         { Imgs[len][1] = "" }
      }
      if (customTextColumn)
      { 
        if (links[i].childNodes[1].childNodes.length>0)
         {Imgs[len][2] = links[i].childNodes[1].nextSibling.childNodes[0].innerHTML;}
         else
         {Imgs[len][2] = "" }      }
    }
  }
  if (Imgs.length==0)
  {
    document.all("RotatingImageMsg").innerHTML="No images found in web part '" + pictureWebPartName + "'!";
  }
  for (i = 0; i < Imgs.length; i++)
  {
    imgCache[i] = new Image();
    imgCache[i].src = Imgs[i][0];
    if (useCustomLinks)
    {
      imgCache[i].customlink=Imgs[i][1];
    }
    if (customTextColumn)
    {
      imgCache[i].customtext=Imgs[i][2];
    }

  }
  RotatingPicturesLoop();
}


// now show the pictures...
function RotatingPicturesLoop()
{
  if (!manualClick)
    if (randomImg)
    {
      selectedImg=Math.floor(Math.random()*imgCache.length);
    }

  if (document.all){
      imgTag.style.filter="blendTrans(duration=" + imgToImgTransition + ")";
      imgTag.filters.blendTrans.Apply();
  }

  url=imgCache[selectedImg].src
  if (useCustomLinks)
  { RotatingImageLnk.href=imgCache[selectedImg].customlink; } 
  else
  { RotatingImageLnk.href = url; }

  if (customTextColumn) 
     customTextTD.innerHTML = imgCache[selectedImg].customtext.replace(/&lt;/g,'<').replace(/&gt;/g,'>');
  else
     customTextTD.innerHTML = "";

  if (showThumbnails)
  {
    // convert URLs to point to the thumbnails...
    //   from  airshow%20pictures/helicopter.jpg
    //   to    airshow%20pictures/_t/helicopter_jpg.jpg

    url = revString(url);
    c = url.indexOf(".");
    url = url.substring(0,c) + "_" + url.substring(c+1,url.length);
    c = url.indexOf("/");
    url = url.substring(0,c) + "/t_" + url.substring(c,url.length);
    url = revString(url) + ".jpg";
  }


  imgTag.src = url;
  if (document.all){
    imgTag.filters.blendTrans.Play();
  }

  if (!manualClick)
  {
    selectedImg += 1;
    if (selectedImg > (imgCache.length-1)) selectedImg=0;

    setTimeout(RotatingPicturesLoop, RotatingPicturesLoopTime);
  }
}


// utility function revString found here:
// http://www.java2s.com/Code/JavaScript/Language-Basics/PlayingwithStrings.htm
function revString(str) { 
   var retStr = ""; 
   for (i=str.length - 1 ; i > - 1 ; i--){ 
      retStr += str.substr(i,1); 
   } 
   return retStr; 
}

function moveFirst() {manualClick = true; selectedImg = 0; RotatingPicturesLoop()}
function moveNext() {manualClick = true; selectedImg += 1; if (selectedImg > (imgCache.length-1)) selectedImg=0; RotatingPicturesLoop()}
function movePrev() {manualClick = true; selectedImg -= 1; if (selectedImg < 0 ) selectedImg=imgCache.length-1; RotatingPicturesLoop()}
function moveLast() {manualClick = true; selectedImg = imgCache.length-1;  RotatingPicturesLoop()}

function movePlay() {
  if (PlayButton.innerHTML=="Play") 
  {
    manualClick = false; 
    PlayButton.innerHTML="Pause"; 
  } 
  else
  {
    manualClick = true; 
    PlayButton.innerHTML="Play"; 
  }

RotatingPicturesLoop()}




// add our function to the SharePoint OnLoad event
_spBodyOnLoadFunctionNames.push("RotatingPictures"); 

</script>




<!-- add your own formatting here... -->
<center>
  <table border="0" cellpadding="0" cellspacing="0" width="100%">
    <tr>
      <td id="VU" height="125" width="160" align="center" valign="middle">
<a name="RotatingImageLnk" id="RotatingImageLnk" alt="click for larger picture">
        <img src="/_layouts/images/dot.gif" name="RotatingImage" id="RotatingImage" border=0>
</a>
        <span name="RotatingImageMsg" id="RotatingImageMsg"></span>
      </td>
      <td ID="customTextTD" name="customTextTD"  width="100%" style="padding: 4px 1ex 4px 4px;">
         <span name="RotatingImageText" id="RotatingImageText"></span>
      </td>
    </tr>
    <tr id="buttonRow" style="display:none"><td colspan="2" align="left">
      <a href="" onclick="moveFirst();return false;">First</a>
      <a href="" onclick="movePrev();return false;">Previous</a>
      <a href="" onclick="movePlay();return false;" name="PlayButton" ID="PlayButton">Play</a>
      <a href="" onclick="moveNext();return false;">Next</a>
      <a href="" onclick="moveLast();return false;">Last</a>
    </td></tr>
  </table>
</center>

 

 

 

.

21 comments:

jay said...

How this is possible in sharepoint2010?

Mike Smith said...

Jay,

The 2010 version will be one of the many additions for the book that I'm working on. It will eventually end up here.

Mike

Jeff D. said...

Is there a way to edit the text format (make larger, bold, etc) in the 'description' field? I haven't quite been able to figure that out. Otherwise, my clients are a huge fan of this code!

Mike Smith said...

Jeff D,

Sure, just add your formatting (CSS) to the span tags:
span name="RotatingImageMsg"
span name="RotatingImageText"

For example:

span name="RotatingImageText" style="font-weight:bold; font-size:24pt;color:red"

Mike

Jeff D. said...

Thanks for the quick response, but adding that code to span tag (in between name and id) is not working. Any thoughts? Thanks again for your help!

Jeff D. said...

Putting the code in ID=customTextID worked!

ID="customTextTD" name="customTextTD" width="100%" style="font-weight:bold;font-size:14pt;color:red" padding: 4px 1ex 4px 4px;"
Thanks again!

Justin H. said...

Hi,
I am having a problem with the code in 2007. I got the code to work in one site and not in another. I keep getting 'No images found in web part'webpart Name'. Do you think there is something wrong with the view? I have gone through the instructions 3 times from scratch. Can you help me?

Justin

Mike Smith said...

Justin H,

The view is the most likely problem. Delete all of the JavaScript in the CEWP and see if the list of pictures is being displayed in the web part. It not, then there is a problem with the view.

Which templates were used to create both sites?

Mike

Anonymous said...

For some reason it is taking a really long time for the webpart to recognize and locate the picture library (prob a 30 second + delay). Is there any way to speed this up? Otherwise, great post

Mike Smith said...

Anonymous,

The code is pre-caching the images so the transitions between pictures will be smooth. Does your library have a very large number of pictures or very large pictures?

You could create a view to select a subset of your pictures and use that with this code.

Mike

Greg :) said...

Hi Mike -

Can't get the customTextColumn to display. Have added a single line text colum for it, and made it 3rd in the web part view. If i set customtextColum to false, everything works ... set it to true, no image. Any thoughts ? Thanks !

Mike Smith said...

Greg,

Which version of SharePoint are you using? Make sure your new column really is the third column. 2010 adds additional columns to views. In any case, remember that the first column is #0 and if you have exactly three columns then the last is #2.

Mike

Greg :) said...

Mike -

Solved my own problem ... changed the single line of text column to multiple lines of text, and it worked :)

Dave said...

Hi Mike,

Excellent post.

Is it possible to do the following (can you show me how please).

1.) It defaults to "Play"

2.) How can I replace the text "play, pause, next, previous" with images

3.) The image a tthe top of the post shows a title and then a description, both in different styles. Is it possible to do this?

4.) It currentl displays text right alligned to whatever I set to as 3rd column in view. But Can I choose what it displays underneath this column??? e.g. a "read more....." link


THANK YOU!!!

Mike Smith said...

Dave,

1) Just after this line:
_spBodyOnLoadFunctionNames.push("RotatingPictures");

add this line:
_spBodyOnLoadFunctionNames.push("movePlay");

2) find the text lines and replace the text with an image tag. Upload your images to a library in the site.

<a href="" onclick="moveFirst();return false;"><img src="urltoyourimage"></a>

3) Just add some HTML to your message text:

<b>this is in bold</b> and this is regular text

4) Yes, add a hyperlink to your text:

Click <a href="urlToGoTo">here</a> to see more

Mike

Dave said...

Mike,

Your a true gentleman, thank-you very much for your help.

Just one last thing. When I change the buttons to images. My Play / Pause won't work; obviously this is because there is no "innerhtml" i.e. they don't say "Play" Pause"; they've got images!

Basically what change shall I make to:



if (PlayButton.innerHTML=="Play")
{
alert(PlayButton.innerhtml);

manualClick = false;
PlayButton.innerHTML="Pause";
}
else
{
alert(PlayButton.innerhtml);
manualClick = true;
PlayButton.innerHTML="Play";
}




I've tried stuff like:

PlayButton.src ==
PlayButton.img ==
PlayButton.image ==

Basically I'll need to modify it so that the IF statement works and the image setting works?

THANKYOU!!!!!!!

Wouter said...

Hey ! Thanks for this script. My sharepoint was just updated to 2010 and this broke the script. Any idea's on what I should update?

Anonymous said...

I replace the text "play, pause, next, previous" with images

This is how I did it

1- Replace the text with the image tag (Example below)

<_img alt="play" name="play" id="play" src=play.png>

2- Change the movePlay function

function movePlay() {
if (PlayButton.firstChild.getAttributeNode("id").value == "play")
{
manualClick = false;
PlayButton.innerHTML="<_img alt=pause name=pause id=pause src=pause.png border=0 />";
}
else
{
manualClick = true;
PlayButton.innerHTML="<_img alt=play name=play id=play src=play.png border=0 />";
}

Note: Remove the underscore from the _img tag.

Cheers,

George George Chackungal said...

I was trying to use multiple copies of this webpart in the same page with two different galleries as source. But when I do that both of them are blank. Any idea why is this issue happening?

Mike Smith said...

George,

It will not work with two lists as it is currently written. Why? Two functions with the same name confuses JavaScript. It could be rewritten to support multiple lists.

Mike

Anonymous said...

How do I make it so that it will rotate through my images on a timer as well as give the viewer the option to click through (Prev/Next). Currently, I can only get it to do one or the other through changing the manualClick to either True or False.

Note to spammers...

Spammers, don't waste your time... all posts are moderated. If your comment includes unrelated links, is advertising, or just pure spam, it will never be seen.