SharePoint SOAP GetListItems VS jQuery - How to use Ajax to cycle through Custom List items as well as Ajax refresh the list contents?
I am using jQuery to access Sharepoint 2007's SOAP interface via the GetListItems method to read in a custom list of announcements 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"></script>
<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 th开发者_如何学Pythone
// <queryOptions> element, which necessitated the addition of the <query> element
var soapEnv =
"<soapenv:Envelope xmlns:soapenv='http://schemas.xmlsoap.org/soap/envelope/'>
<soapenv:Body> \
<GetListItems xmlns='http://schemas.microsoft.com/sharepoint/soap/'> \
<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"/> </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)?
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.
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!
精彩评论