September 2009

One of the major shortcomings of SharePoint 2007 is that there is no easy way to display items from a list in another site collection. This is the kind of thing which is needed on a daily basis, in order for information to be centralized effectively and to avoid duplication.

I am currently developing a series of SharePoint templates, and I want training resources for these templates to be grouped in one central site collection. Each site created from one of the templates will need to pick up certain list information of training materials relevant for the template which has been used to create the site.

To meet this need, I decided to tackle this issue and find a solution. As a result, I found an approach (by Christophe at Path to SharePoint) which is a pure JavaScript solution and so can be configured through the Content Editor Web Part, making it available to power users. To use it, follow the steps below:

  1. Create a web part page and insert a Content Editor Web Part.
  2. Paste the following code into the Source Editor:
<!– Load and display list – iframe version –>

<!– Questions and comments: –>

<DIV id=”ListPlaceholder”><IMG src=”/_layouts/images/GEARS_AN.GIF”></DIV>

<script type=”text/javascript”>

var mystring1 = “<iframe id=\”SourceList\” style=\”display:none;\” src=\””;

var mystring2 = “/sites/it-Outages”;

var mystring3 = “/lists/outages/sapoutages.aspx\” onload=\”DisplayThisList()\”></iframe>”;



<script type=”text/javascript”>

function DisplayThisList()


var placeholder = document.getElementById(“ListPlaceholder”);

var displaylist = null;

var sourcelist = document.getElementById(“SourceList”);

try {


// Firefox, Opera

{displaylist = sourcelist.contentDocument.getElementById(“WebPartWPQ2”) ;}

else if(sourcelist.contentWindow)

// Internet Explorer

{displaylist = sourcelist.contentWindow.document.getElementById(“WebPartWPQ2”) ;}

else if(sourcelist.document)

// Others?

{displaylist = sourcelist.document.getElementById(“WebPartWPQ2”) ;}


catch(err) { alert (“Loading failed”);}


var allDescendants = displaylist.getElementsByTagName(“*”);

for (i=0;i<allDescendants.length;i++) {






placeholder.innerHTML = displaylist.innerHTML;



  1. This example displays a list of SAP Outages from the IT-Outages site directly in a CDM Blog page. You will need to adapt the path according to your needs.

I will explain in a later blog post why it is useful to have variables available in the JavaScript file as shown above.


The DataSheet view in SharePoint provides the means to edit lists in bulk, but sometimes it would be convenient to be able to edit items in a standard SharePoint view without opening the associated form each time. This is possible using a bit of Google Jquery wizardry which combines AJAX with traditional JavaScript.

In a typical SharePoint task list, both the Status and the Priority fields can be set direct from the Edit Control Block as follows:

Clicking the menu items changes the entry in the list directly. To make use of this functionality, you should insert a Content Editor Web Part in the page and past the following code into the Source:

<script type=”text/javascript” src=””></script&gt;

<script type=”text/javascript”>

// Ajax Enabled SharePoint 2007 Lists and Document Libraries version 1.0

// Created by Jan Tielens,,


// – Navigate to the page where you would like to use it (e.g.

// http://yoursite//Lists/Tasks/AllItems.aspx for the Task list).

// – Click Site Actions, Edit Page (top right)

// – Click Add a Web Part

// – Select the Content Editor Web Part in the Miscellaneous section and click Add.

// – Optionally drag the Content Editor Web Part to the bottom of the screen (otherwise a

// small space will be displayed on top of the page).

// – Click open the tool pane in the web part.

// – Click Source Editor … in the properties task pane.

// – Copy and paste the modified script in the Text Entry dialog and click Save.

// – Click Exit Edit Mode (top right) and verify the result.

// ****

var ajaxListConfig = {

columns :new Array(“Status”, “Priority”), // columns to ajaxify

values :new Array(

new Array(“Not Started”, “In Progress”, “Completed”,

“Deferred”, “Waiting on someone else”), // values for Status

new Array(“(1) High”, “(2) Normal”, “(3) Low”) // values for Priority


debug :0, // set to 1 to see log messages

animationSpeed :”fast” // possible values: “slow”, “normal”, “fast” or a number (milliseconds)


function Custom_AddListMenuItems(m, ctx) {

ajaxListLog(“Custom_AddListMenuItems entered.”)

// the element ID of the table containing the rows is a combination of the List ID and View ID.

var tableid = ctx.listName + “-” + ctx.view;

var wsurl = ctx.HttpRoot + “/_vti_bin/lists.asmx”;

// loop over all configured columns

for(var j in ajaxListConfig.columns) {

var column = ajaxListConfig.columns[j];

// create menu item for column

var menuItem = CASubM(m,”Update ” + column);

var currentValue = getColumnValueViaWS(column, ctx.listName, currentItemID, wsurl);

//var currentValue = getColumnValueViaHTML(column, ctx.listName, currentItemID, tableid);

// loop over all possible values for the column and add sub menu items

for(var i in ajaxListConfig.values[j]) {

var colValue = ajaxListConfig.values[j][i];

if(colValue != currentValue)

CAMOpt(menuItem, colValue , “setColumnValue(‘” + column + “‘,'” + ctx.listName + “‘,'” + currentItemID + “‘,'” +

colValue + “‘,'” + tableid + “‘,'” + wsurl + “‘);”);




return false;


function getColumnValueViaHTML(column, list, itemID, tableid) {

var $td = getItemTD(column, tableid, itemID);

return $td.text();


function getColumnValueViaWS(column, list, itemID, wsurl) {

ajaxListLog(“getColumnValueViaWS entered.”)

// build soap envelope to retrieve a list item based on it’s id

var soapEnv =

“<soapenv:Envelope xmlns:soapenv=’’&gt; \

<soapenv:Body> \

<GetListItems xmlns=’’&gt; \

<listName>” + list + “</listName> \

<viewFields> \

<ViewFields> \

<FieldRef Name='” + column + “‘ /> \

</ViewFields> \

</viewFields> \

<query> \

<Query><Where> \

<Eq> \

<FieldRef Name=’ID’ /> \

<Value Type=’Integer’>” + itemID + “</Value> \

</Eq> \


</query> \

</GetListItems> \

</soapenv:Body> \


ajaxListLog(“- Initializing AJAX call …”);

var itemStatus;


async: false,

url: wsurl,

type: “POST”,

dataType: “xml”,

data: soapEnv,

contentType: “text/xml; charset=\”utf-8\””,

complete: function(xData, status) {

// data is received, get and return the value

ajaxListLog(“- AJAX call done, status: ” + status);

var $itemElement = $(xData.responseXML).find(“z\\:row:eq(0)”);

itemStatus = $itemElement.attr(“ows_” + column);



return itemStatus;


function getItemTD(column, tableid, itemid) {

// This function retrieves the TD (table cell) that contains the data for the

// specified item and column.

// first check if the requested TD is in the cache

if(ajaxListConfig.cachedItemColumn != column || ajaxListConfig.cachedTableID != tableid ||

ajaxListConfig.cachedItemID != itemid || ajaxListConfig.cachedTD == null) {

// not in in the cache, let’s get it

ajaxListLog(“- Building new TD”);

ajaxListConfig.cachedTableID = tableid;

ajaxListConfig.cachedItemID = itemid;

ajaxListConfig.cachedItemColumn = column;

// escape the table id ({ and } should become \{ and \}

tableid = tableid.replace(/{/g, “\\{“).replace(/}/g, “\\}”);

// select them TR for the item

$itemrow = $(“#” + tableid + ” table[id='” + itemid + “‘]”).parent().parent();

// select the header row

$headerrow = $(“>tr:eq(0)”, $itemrow.parent());

// select the table in the header row for the specified column

$idtable = $(“th>div>table[Name='” + column + “‘]”, $headerrow);

// calculate the index of the column, based on the idtable

var columnIndex =$(“>th”,$headerrow).index($idtable.parent().parent());

// based on the index, let’s get the TD

ajaxListConfig.cachedTD = $(“>td:eq(” + columnIndex + “)”, $itemrow);



ajaxListLog(“- TD retreived from cache”);

return ajaxListConfig.cachedTD;


function setColumnValue(column, list, itemid, newstatus, tableid, wsurl) {

ajaxListLog(“setColumnValue entered.”)

// animate the table cell so it fades out, after that the new value is set in the cell

getItemTD(column, tableid, itemid).fadeTo(ajaxListConfig.animationSpeed,.01 , function() {

getItemTD(column, tableid,itemid).text(newstatus);


var batch =

“<Batch OnError=\”Continue\”> \

<Method ID=\”1\” Cmd=\”Update\”> \

<Field Name=\”ID\”>” + itemid + “</Field> \

<Field Name=\”” + column + “\”>” + newstatus + “</Field> \

</Method> \


var soapEnv =

“<?xml version=\”1.0\” encoding=\”utf-8\”?> \

<soap:Envelope xmlns:xsi=\”\” \

xmlns:xsd=\”\” \

xmlns:soap=\”\”> \

<soap:Body> \

<UpdateListItems xmlns=\”\”> \

<listName>” + list + “</listName> \

<updates> \

” + batch + “</updates> \

</UpdateListItems> \

</soap:Body> \


ajaxListLog(“- Initializing AJAX call …”);

// make the ws call


async: true,

url: wsurl,

beforeSend: function(xhr) {



type: “POST”,

dataType: “xml”,

data: soapEnv,

complete: function(xData, status) {

ajaxListLog(“- AJAX call done, status: ” + status);

// data is received, animate the cell so it fades in again

getItemTD(column, tableid, itemid).fadeTo(ajaxListConfig.animationSpeed, 1);

ajaxListLog(“- UI updated”)


contentType: “text/xml; charset=utf-8”



function ajaxListLog(message) {

// if logging is enabled, a div is added on op of the page to display

// log messages and thier timestamps (in ms)

if(ajaxListConfig.debug != 1)


if(ajaxListConfig.logDiv == null) {

$(“body”).append(“<div id=’ajaxListLogDiv’ class=’ms-vb’ style=’position:absolute; \

background-color:White; padding:2px; border-width:1px; border-style:solid; \

border-color:Black;display:none; position:absolute; width:600px; height:150px; overflow:auto;’></div>”);

ajaxListConfig.logDiv = $(“#ajaxListLogDiv”);

var topPos = document.body.clientHeight – ajaxListConfig.logDiv.height() – 20

var leftPos = document.body.clientWidth – ajaxListConfig.logDiv.width() – 20;

ajaxListConfig.logDiv.css(“top”, topPos).css(“left”, leftPos).show(“fast”);

logTimer = new Date();

ajaxListLog(“Log Initialized!”);


var logContent = “<div style=’width:60px; float:left’>” + (new Date().getTime() – logTimer.getTime())

+ “ms</div><div>” + message + “</div>”;




As you will see, the script (written by Jan Tielens) makes use of a JavaScript file hosted at Google. To save bandwidth traffic you can put a copy of the .js file in a SharePoint list somewhere which is easily accessible by the page you are customizing and edit the reference in the heading of the code above.

Depending on the list you are using and the columns you want to reference, you will also have to change some of the JavaScript.

It would be useful oftentimes in SharePoint, to be able to edit an item in a pop-up window. This can be done with a bit of Javascript in a Content Editor Web Part (CEWP) in the list view page concerned.

To use an additional Edit Content Block menu item as above, paste the following Javascript into a CEWP in the page concerned:

<script type=”text/javascript”>

function Custom_AddListMenuItems(m, ctx) {

var viewURL = window.location.protocol + “//” + +

ctx.displayFormUrl + “?ID=” + currentItemID;

var editURL = window.location.protocol + “//” + +

ctx.editFormUrl + “?ID=” + currentItemID;

var openMenu = CASubM(m,”Open in New Window”);

CAMOpt(openMenu, “View Item”, “‘” + viewURL + “‘);”);

CAMOpt(openMenu, “Edit Item”,

“‘” + editURL + “‘);”, “/_layouts/images/edititem.gif”);

return false; // render the default menu items too



With thanks to Jan Tielens

Windows Server 2003 virtual machine will not connect to the Internet ?

You need to set the DNS manually on the virtual server’s network card to – why? It is a long story but you can no doubt find more by searching the web if you are interested.

I just found the same issue concerning a Windows 7 VHD running in Virtual PC.