views:

2140

answers:

2

Hello all,

I am using jQuery to access Sharepoint 2007's SOAP interface via the GetListItems method to read in a custom list of anouncements in such a way as to have that list refresh once a minute (in case the owners of the list add new content, so that the new content becomes visible without having the end user refresh their sharepoint screen). WHat I would like to do is not only refresh that list, I would like to have each item in the list cycle through one at a time (maybe have each item stay visible for 10 seconds, then the next item would load into that space.

Here is the code I have so far:

<script type="text/javascript" src="http://jqueryjs.googlecode.com/files/jquery-1.3.2.min.js"&gt;&lt;/script&gt;
<script type="text/javascript" src="/SiteCollectionDocuments/jquery.timers-1.0.0.js" ></script>  
<script type="text/javascript">

$(document).ready(function() {

// Create the SOAP request        
// NOTE: we need to be able to display list attachments to users, hence the addition of the
// <queryOptions> element, which necessitated the addition of the <query> element

var soapEnv =
"<soapenv:Envelope xmlns:soapenv='http://schemas.xmlsoap.org/soap/envelope/'&gt;
<soapenv:Body> \
   <GetListItems xmlns='http://schemas.microsoft.com/sharepoint/soap/'&gt; \
     <listName>testlist</listName> \
     <viewFields> \
       <ViewFields> \
         <FieldRef Name='Title' /> \
         <FieldRef Name='Body' /> \
         <FieldRef Name='ID' /> \
         <FieldRef Name='Attachments' /> \
       </ViewFields> \
     </viewFields> \
     <query> \
       <Query /> \
     </query> \
     <queryOptions> \
       <QueryOptions> \
         <IncludeAttachmentUrls>TRUE</IncludeAttachmentUrls> \
       </QueryOptions> \
     </queryOptions> \
    </GetListItems> \
  </soapenv:Body> \
  </soapenv:Envelope>";

// call this SOAP request every 20 seconds
$("#tasksUL").everyTime(20000,function(i){
    // our basic SOAP code to hammer the Lists web service
    $.ajax({
    url: "http://ourdomain.net/_vti_bin/lists.asmx",
    type: "POST",
    dataType: "xml",
    data: soapEnv,
    error: printError,
    complete: processResult,
    contentType: "text/xml; charset=\"utf-8\""
    });
  });
});

// basic error display that will pop out SOAP errors, very useful!
function printError(XMLHttpRequest, textStatus, errorThrown)
{
 alert("There was an error: " + errorThrown + " " + textStatus);
  alert(XMLHttpRequest.responseText);
}


// main method that will cycle through the SoAP response nodes
function processResult(xData, status) 
{

  $(xData.responseXML).find("z\\:row").each(function() 
  {
    // resets display element
   $("#tasksUL").empty();

   // gets attachments array - if there is more than one attachment,
   // they get seperated by semi-colons in the response
   // they look like this natively (just an example):
   // ows_Attachments = ";#http://server/Lists/Announcements/Attachments/2/test.txt;
   // #http://server/Lists/Announcements/Attachments/2/UIP_Setup.log;#"

       var mySplitResult = $(this).attr("ows_Attachments").split(";");
  // set up storage for later display of images
  var notice_images = "";

  // processes attachments - please forgive the kludge!  
  for(i = 0; i < mySplitResult.length; i++)
  {
   // check to see the proper link URL gets chosen
   if (i % 2 != 0 && i != 0)
   {
    // strips out pound sign
    mySplitResult[i] = mySplitResult[i].replace("#", "");

    // (possibly redundant) check to make sure element isn't simply a pound sign  
    if (mySplitResult[i] != "#")
    {
     // adds an img tag to an output container
     notice_images = notice_images + "<img src='" + mySplitResult[i] + "' border='0' align='right' style='float:right;' /><br />"; 
    }
   }
  }

  // create final output for printing
  var liHtml = "<h3>" + $(this).attr("ows_Title") + "</h3><p>" + notice_images + $(this).attr("ows_Body") + "</p>";

  // assign output to DIV tags
    $("#tasksUL").html(liHtml);

   });

}
</script>

<div id="tasksUL"/>&nbsp;</div>

It's pretty simple stuff so far (although finding decent documentation as to what you are able to do with the GetListItem SOAP request was daunting). Inside of the block where I iterate through the returned rows (the PprocessResult function), I am resetting the HTML being assigned to the DIV block so that only one row is showing as output. The way the code is set up, this means only the very last row in my custom list will be visible, as I have no code pausing the iterations.

My thought had been to wrap a timer around this block of code:

$(xData.responseXML).find("z\\:row").each(MYTIMER(10000, function(){...

But I met with zero or mixed results.

My question to you all is: What would be the best way to set up my current code to both refresh the source list data like it is now AND cycle through query results from that list one at a time (preferably with a small pause on each item so that people can read it)?

Thank you so much!!

Mike

+1  A: 

I would keep your visual cycle and your data update cycle as separate entities.

Set up your timeout function to update a container of divs with your data displayed inside. You can add and remove from this list to your desire.

You might start with something like:

<div id="container">
  <div id="1" class="task">task foo</div>
  <div id="2" class="task">task bar</div>
  <div id="3" class="task">task baz</div>
</div>

And then after a data update it could add another element:

<div id="container">
  <div id="1" class="task">task foo</div>
  <div id="2" class="task">task bar</div>
  <div id="3" class="task">task baz</div>
  <div id="4" class="task">task lol</div>
</div>

Then use a cycle plugin to simply cycle through the ordered collection of divs inside of a given container element. It will always just show the next div in the collection, rather than rely on your update plugin to restart the cycle.

The most popular plugin to cycle through elements in jQuery is jquery.cycle.js at http://malsup.com/jquery/cycle2/ . You may also be interested in the 'lite' version that is available online.

Alex Sexton
Holy cow that looks hot! I hadn't considered making the cycling of the list items separate from the AJAX code that refreshes the data set. I sort of really love this approach, and I could see using it in more than one area of my application. THANK YOU SO MUCH!!!
Mike Arsenault
Ok, I am running into a problem with this fix. No matter how I link into the cycle library, I am getting an error: Error: $("#tasksUL").cycle is not a functionHere are the linking statements: <script type="text/javascript" src="http://cloud.github.com/downloads/malsup/cycle/jquery.cycle.all.2.72.js"></script>Here is the code I wrote to add onto the code above: <script type="text/javascript"> $(document).ready(function() { $('#tasksUL').cycle({ fx: 'fade' }); });</script>The script above is now creating a seoperate div for each list row...
Mike Arsenault
It would be very helpful to see a test page of some sort. It's a bit tough to tell what's going on from here.
Alex Sexton
Can I e-mail you a link to my project site? I don't want to post it here due to having to pass you a username and password to the SharePoint instance in order for that instance to be viewable...
Mike Arsenault
A: 

Actually, and there was no way for anyone to know this, the reason this was failing was because someone had installed a site collection jQuery package that was old and didn't work very well with jCycle. Once I deactivated that feature on the collection, restarted IIS, and refreshed the page, everything worked fine. As an extra step I downloaded the latest full version of jQuery into a document library and linked to it instead of the Google-hosted version of the script. So all of the js I am using lives inside the site collection now.

I was able to figure out about the conflicting versions of jQuery but using Firebug's Console and Script debugger. I had to set the debugger to halt on all errors, but the very first error that came up was referencing the site collection jQuery package and not my included Google code. That is the reason I am answering my own question. There are other poor bastards out there doing SharePoint development and it may not occur to them to use FireFox to test their SP installations given how much it favours IE and all.

Thanks to all who read and answered/commented!

Mike Arsenault