Category Archives: Requests

Parent-child-grandchild relationship in SharePoint 2010 lists with javascript only

09.12.2011 I have updated the solution to v1.1 to let the user chose the icon (or no icon) before the “child” title. The code for the file “ParentChildResources.js”, and the CEWP code for “Parent DispForm” and Child DispForm” has changed. The new “argObj-property” “iconBefore” should be the path to the image to prepend to the “child title”.


I got this request:

Hi Alex,

I am new to SharePoint and have been struggling with steep learning curve and would really appreciate your help…

I created a parent-child-grandchild relation where I inserted a related view in the parent’s dispform to show all children and also in the child’s dispform to show all grandchildren. I’ve also followed http://geekswithblogs.net/SoYouKnow/archive/2010/12/16/creating-a-sharepoint-parentchild-list-relationshipndash-sharepoint-2010-edition.aspx to set the parent’s ID on the child’s newform using javascript but I need to take it a step further. In the child’s newform I need to retrieve the parent list’s 2nd field and use that value to build a dynamic drop down field in the child’s newform. The field items in the drop down preferably to be pulled from another list for the ease of maintenance but hard coding is also acceptable. This is probably a no-brainer for you so I hope you wouldn’t mind spending some time on it and I will make sure some donation is made . Thank you so much!

This involves putting scripts in NewForm and/or DispForm in three lists. Please follow the steps carefully.

Please note that this code is for SharePoint 2010 only.
Step 1

Create the three custom lists used in this example:

  • Parent
    This list has the Title field only.
  • Child
    Add one field of type Lookup (single choice) with the name “Parent”. This lookup should target the title field of the "Parent" list.
  • Grandchild
    Add one field of type Lookup (single choice) with the name “Parent”. This lookup should target the title field of the "Child" list.
Step 2

Download the code from here
The code is presented in individual folders so it’s easy to get the right code in the right form.

Step 3

Important:
Edit the code that goes in the CEWPs to fix the script src attributes in all files, the “childListUrl” in the DispForm code and the various “argObj” variables if your lists or fields has different names. You will have to read trough the code for the CEWPs to find the bits to change.

The file “ParentChildResources.js” does not need any modification.

Upload the code to a shared document library and maintain the folder structure (or rename the files so that you know which file goes where).

Step 4

Add CEWPs to the list forms and insert the code corresponding with the folder and file name. It is important that you use the content link option to link to the code.

To add a CEWP, go to the list, activate it by clicking in the “list area” to bring up the list tools ribbon. Select the tab “List” and “Form Web Parts”.

You find the content link option like this:
Edit the page and activate the CEWP. In the ribbon toolbar, select “Web Part Tools” and then “Web Part Properties”.

To ensure you get the correct file path, go to the document library, right click the file and select “Copy shortcut”. Paste this URL in the content link field. You might want to edit the URL to make it relative.

Note Add the CEWP below the list form.

The result should look like this

Parent
IMG
Child
IMG
Grandchild
IMG

Final words

This solution uses the Client Object Model introduced in SharePoint 2010 and therefore it will not work on previous SharePoint versions.

To keep this solution clean and simple, the last bits from the request regarding the lookup column, is kept out of this post – it will be emailed to the person requesting this article.

If there is demand for it, i will post it as an appendix to this post later on.

Hope someone can make use of this code.
Alexander

SharePoint 2010 – The view selector is back!

In SharePoint 2010 you loose the list view selector in a list view if there are more than 1 web part in the page. This makes navigating the list views very cumbersome.

I have previously created a solution for adding a view selector in these list views, but that solution was a bit clunky.

I looked at this again today, and came up with a solution for re-enabling the missing list view selector that was clean and simple – and it doesn’t even require jQuery…

This is the first article where I’m using the “SharePoint 2010 Client Object Model”.

This solution is placed in a ContentEditorWebPart (CEWP) somewhere in the page you want the list view menu re-enable in. I recommend using the “Content Link” option in the CEWP as the code might be messed with by SharePoint if you paste it directly in the CEWP’s HTML-source.

To achieve this, put the code in a text-file and place it in a shares document library (all users must have read access), or in a folder created in SharePoint Designer. You then copy the file’s url and paste it into the “Content Link” field in the “Edit web part” panel like this:
IMG

You do not get any pictures of the menu itself as it is no different from the standard list view selector.

Here is the code:
Get the code here

Remove group label in grouped list view

17.09.2011 I have updated the script to support lookup columns and people pickers.


I got a request from Djamel asking for a solution for removing the group label (the field name) in a grouped list view.

Add this code to a Content Editor Web Part (CEWP) in the list view. Adding a CEWP in a SharePoint 2010 list view will unfortunately remove the list view selector.

SharePoint 2007

[javascript]
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function(){
$("table.ms-listviewtable td[class^=’ms-gb’]").each(function(){
var aLen = $(this).find(‘a’).length;
switch(aLen){
case 2:
var newLabel = $(this).find("a:last")[0].nextSibling.nodeValue;
$(this).find("a:last")[0].nextSibling.nodeValue = ”;
$(this).find("a:last").text(" "+newLabel.substring(3));
break;
case 3:
var newLabel = $(this).find("a:last").text();
$(this).find("a:eq(1)")[0].nextSibling.nodeValue = ”;
$(this).find("a:eq(1)").text(newLabel+" ");
$(this).find("a:eq(2)").remove();
break;
case 4:
var newLabel = $(this).find("a:eq(2)").text();
$(this).find("a:eq(1)")[0].nextSibling.nodeValue = ”;
$(this).find("a:eq(1)").text(newLabel+" ");
$(this).find("nobr:last").remove();
break;
}
});
});
</script>
[/javascript]

SharePoint 2010

[javascript]
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function(){
$("table.ms-listviewtable td[class^=’ms-gb’]").each(function(){
var newLabel;
var aLen = $(this).find(‘a’).length;
switch(aLen){
case 1:
newLabel = $(this).find("a:last")[0].nextSibling.nodeValue;
$(this).find("a:last")[0].nextSibling.nodeValue = ”;
$(this).find("img:last")[0].nextSibling.nodeValue = " "+newLabel.substring(3);
break;
case 2:
newLabel = $(this).find("a:last")[0].nextSibling.nodeValue;
if(newLabel === null){
newLabel = $(this).find("a:last").text();
$(this).find("a:last").remove();
$(this).find("a:first")[0].nextSibling.nodeValue = ”;
$(this).find("img:first")[0].nextSibling.nodeValue = " "+newLabel;
}else{
$(this).find("a:last")[0].nextSibling.nodeValue = ”;
$(this).find("a:last").text(" "+newLabel.substring(3));
}
break;
case 3:
newLabel = $(this).find("nobr:last").text();
$(this).find("nobr:last").remove();
$(this).find("a:eq(0)")[0].nextSibling.nodeValue = ”;
$(this).find("img:last")[0].nextSibling.nodeValue = " "+newLabel;
break;
}
});
});
</script>
[/javascript]

Ask if anything is unclear.

Alexander

CommentBox for SharePoint

13.08.2011 v1.2 released with these changes to the argObj:

  • paging: Use this in conjunction with the next parameter to set the number of top level comments to display initially.
  • topLevelCommentsLimit: The number of top level comments to display initially.
  • showMoreCommentsText: If there are more comments, this text is used for the link to show the rest of the comments.
  • sortAscending: true or false. Used to control the order of the comments.
  • commentFormVisible: true or false. Used to have the comment box expanded or collapsed initially.

There are changes to these files:

  • CommentBox.js
  • CommentBox.css

And the CEWP-code. See the CEWP-code section below for details.


17.07.2011 v1.1 released with these changes:

  • Anonymous users can read comments, but must sign in to post.
  • Added new parameter “loadLiveProfile” to the CEWP argObj. This defines whether or not to load the profile image and email from the user profile, or to use the values stored in the comment. This will automatically be set to false for anonymous users. To accompany this change i have added some new fields to the configuration list (these will be automatically created when submitting the first comment), and changed the parameters “newCommentText” and “replyText” from string to array.

There are changes to these files:

  • CommentBox.js
  • spjs-webservices.js

And to the CEWP-code.


I got this request from Brett:

Hi Alexander,

Got an awesome request for your mad skills.
Are you able to provide a Javascript/JQuery code for a Comments Box Web Part? So it can be added to any page, list or library?

I’m thinking you could set it like the Poll web part, where the Admin can specify the ID Name for each Comments Web Part instance, which will allow the user comments be allocated to the correct web part.

So it would function exactly like the Comments Web Part in a Blog Site, using the authenticated user credentials and/or anonymous comments if you desire.

There are a few Posts mentioning DVWP’s and SP Designer but I’m hoping to use a Javascript based solution.

I’ve looked everywhere for this function and closest I found was this Post.
http://devgrow.com/simple-threaded-comments-with-jcollapsible/

Many thanks for your time and efforts,

Brett


I thought this would be a useful solution for many users – myself included. It’s not very complicated as all comments are stored in a single list – identified by the pages relative URL.

Of course – as i started building – i incorporated this and that, an all of a sudden i had myself a full featured, multi level comment solution.

Sample thread:

IMG

New comment – plain text:

IMG

New comment – Rich text:

IMG

List of features

  • Supports both SharePoint 2007 and SharePoint 2010
  • Tested in IE7, IE9, Safari 5.0.5 for Windows, Firefox 5.0 and Google Chrome 12.0.742.112
  • Multi level comments
  • You can collapse top level threads
  • Rich text or plain text comments
  • Option to allow the authors to edit their comments
  • Option to let specific users act as “moderators”
  • Can be used in multiple locations within the site as each instance is identified by the relative URL of the page
  • Simple “drop in CEWP-setup”
  • On list holds all comments for all instances within the site
  • This list that holds the comments is automatically created
  • Layout customizable trough separate css-file
  • And more…

How to use

This solution is designed to be put in a CEWP where you want to use it. You will have to download all the files from the download section to a local folder/library where all users have read access, and change the <script src=”… in the CEWP code to reflect your local path.

CEWP code example

<div id="myCommentBox"></div>
<link rel="stylesheet" href="/test/EMSKJS/CommentBox/CommentBox.css">
<script type="text/javascript" src="/test/EMSKJS/CommentBox/jquery-1.6.2.min.js"></script>
<script type="text/javascript" src="/test/EMSKJS/CommentBox/CommentBox.js"></script>
<script type="text/javascript" src="/test/EMSKJS/CommentBox/spjs-webservices.js"></script>
<script type="text/javascript" src="/test/EMSKJS/CommentBox/tiny_mce/tiny_mce.js"></script>
<script type="text/javascript">

var pageID = location.pathname+"?ID="+GetUrlKeyValue('ID');
var argObj = {pageID:pageID,
			 containerID:'myCommentBox',
			 containerWidth:600,
			 replyLevels:2,
			 threadInitiallyCollapsed:false,
			 commentIndent:40,			 
			 commentBoxHeight:100,
			 showProfileImage:true,
			 createdByPrefix:'Posted by ',
			 createdPrefix:' on ',
			 modifiedPrefix:'- Modified: ',
			 modifiedByPrefix:' by ',
			 showUserEmail:true,
			 authorCanEdit:true,
			 editText:'Edit',			 
			 commentBoxRTE:false,
			 expandThread:"<span title='Expand thread'><img style='vertical-align:text-bottom' src='/_layouts/images/tpmax2.gif'  border='0'> Expand</span>",
			 collapseThread:"<span title='Collapse thread'><img style='vertical-align:text-bottom' src='/_layouts/images/tpmin2.gif' border='0'> Collapse</span>",
			 newCommentText:['Leave comment','You must sign in to comment'],
			 replyText:['Reply','<span title="You must be signed in to leave replies">Sign in</span>'],			 
			 submitText:'Submit comment',
			 canceImgHover:"Cancel",
			 deleteThreadText:'Delete comment',
			 moderateText:'Moderate',
			 moderatorID:['15','27'],
			 loadLiveProfile:true,
		 	 paging:false,
			 topLevelCommentsLimit:25,
			 showMoreCommentsText:"More comments",
			 sortAscending:true,
			 commentFormVisible:true
			 };

init_getComments(argObj);
</script>

Note to SharePoint 2010 users:
Add this code to a text file and put it in a document library, then use the content link option on the CEWP to link to this code. This is necessary to overcome a “bug” in the CEWP handling when editing a SP2010 page. If you put a script that generates HTML directly into a CEWP, the HTML is accumulated when editing the page.

This tip is also recommended for SharePoint 2007 users, but is not absolutely necessary.

Argument object parameters

  • pageID: The identifier for the unique instance – see separate description below.
  • containerID: The container where the comments are inserted – see separate description below.
  • containerWidth: Width in pixels.
  • replyLevels: The number of nested levels.
  • threadInitiallyCollapsed: true or false to indicate whether the threads are initially collapsed.
  • commentIndent: The number of pixels to indent each nested level of comments.
  • commentBoxHeight: The textbox (for new comments or reply) height in pixels.
  • showProfileImage: true or false to indicate whether or not to display the profile image from the SharePoint user profile.
  • createdByPrefix: The text before the user name of the author.
  • createdPrefix: The text between the author name and the date/time for when the comment is created.
  • modifiedPrefix: The text before the date/time for when the comment is modified.
  • modifiedByPrefix: The text before the name of the editor.
  • showUserEmail: true or false to indicate whether to show the email for the author.
  • authorCanEdit: true or false to indicate whether the author can edit his or hers own comments.
  • editText: The text on the “Edit item link”.
  • commentBoxRTE: true or false to indicate whether to use the TinyMCE rich text editor – see separate description below.
  • expandThread: The text/image of the “Expand thread” link.
  • collapseThread: The text/image of the “Collapse thread” link.
  • newCommentText: Array with the text on the “Leave comment” link for both authenticated and unauthenticated users.
  • replyText: Array with the text on the “Reply” link for both authenticated and unauthenticated users.
  • submitText: The text on the “Submit comment button”.
  • canceImgHover: The mouseover text on the “Cancel comment image”
  • deleteThreadText: The text on the “Delete comment” link.
  • moderateText: The text on the “Moderate item link”.
  • moderatorID: An array of the user ID’s (as string) for the moderators.
  • loadLiveProfile: true or false to indicate whether to load the profile image and email from the user profile, or to use the values stored in the comment.

New in v1.2

  • paging: Use this in conjunction with the next parameter to set the number of top level comments to display initially.
  • topLevelCommentsLimit: The number of top level comments to display initially.
  • showMoreCommentsText: If there are more comments, this text is used for the link to show the rest of the comments.
  • sortAscending: true or false. Used to control the order of the comments.
  • commentFormVisible: true or false. Used to have the comment box expanded or collapsed initially.

Details on “pageID”
For ordinary aspx-pages, use

location.pathname

When using in DispForm/EditForm, use

location.pathname+"?ID="+GetUrlKeyValue('ID')

Details on “containerID”

You can supply a placeholder in the page with the ID corresponding with the parameter “containerID” from the function call. You will want to do this to control the placement of the container, or to supply some custom settings (style or class). If you do not supply a container, it will be created automatically by the script.

Details on “commentBoxRTE”

TinyMCE – Javascript WYSIWYG Editor is a platform independent web based Javascript HTML WYSIWYG editor control released as Open Source under LGPL by Moxiecode Systems AB.

You can change the buttons and plugins for the TinyMCE by modifying the function “init_MCE” at the bottom of the file “CommentBox.js”. Refer the official site for details.

SharePoint 2010 users:
The TinyMCE solution has to be modified to change all “htm” files (and the references in the scripts) to “aspx” as the built in security feature in SharePoint 2010 does not let you open htm-files unless you change the “Browser file handling” from “Strict” to “Permissive”.

I have modified the files used in the default setup for the CommentBox solution. If you change the setup to include more plugins you must change the appropriate files. The modified package can be found in the download section.

Download

You find the files here

Copyright and disclaimer


Please let me know if you find any bugs.
Alexander

If you use this solution, please consider donating a few dollars to keep me motivated.

Pull on-call information from calendar

10.06.2011 Update: I forgot to separate out the FieldInternalNames for the start and end date. See updated code.


This solution is an answer to a request from Colin Blake:

Hey Alexander,

I’ve been browsing through your blog (amazing!) and have not been able
to come up with anything yet using your posted solutions so I was
hoping you could help me or get me pointed in the right direction. I
have a calender that holds our “On-Call” information. I have added a
custom column to the calender that holds a text value(the name of the
on call person). What I would like to do is is on another Web Part
Page is have the text value from the custom “on-call” column for the
current week displayed in a CEWP Web Part. Is this something that
could be easily done?

Thanks,
Colin Blake

This solution is designed to be put directly into a CEWP and will insert the name of the person “on call” in a placeholder <div>.

Note to SharePoint 2010 users:
Add this code to a text file and put it in a document library, then use the content link option on the CEWP to link to this code. This is necessary to overcome a “bug” in the CEWP handling when editing a SP2010 page. If you put a script that generates HTML directly into a CEWP, the HTML is accumulated when editing the page.

CEWP code:

[javascript]
<div id="insertOnCallNameHere"></div>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js"></script>
<script type="text/javascript">

// Define list name or GUID
var calendarName = "OnCallCalendar";
// Define the FieldInternalName to pull in the value from
var fieldToReturn = ‘OnCallPerson’;
// Define the start and end date fields
var startDateFIN = ‘EventDate’;
var endDateFIN = ‘EndDate’;
// Call the cunction
var onCallArr = getOnCallInfo(calendarName,fieldToReturn,startDateFIN,endDateFIN);

// Handle the result
var buffer = [];
$.each(onCallArr,function(i,obj){
// obj.url = hyperlink to profile page
// obj.name = name
// obj.userId = user id
// url and userid is available only when "fieldToReturn" is a people picker.
buffer.push("<div>"+obj.url+"</div>");
});
$("#insertOnCallNameHere").html(buffer.join(”));

// ****************************************************************
// Do not edit below this line
// ****************************************************************

function getOnCallInfo(listName,fieldNameToReturn,startDateFIN,endDateFIN){
var result = [];
var queryBuffer = [];
queryBuffer.push("<Where>");
queryBuffer.push("<And>");
queryBuffer.push("<Leq><FieldRef Name=’"+startDateFIN+"’ /><Value Type=’DateTime’><Today /></Value></Leq>");
queryBuffer.push("<Geq><FieldRef Name=’"+endDateFIN+"’ /><Value Type=’DateTime’><Today /></Value></Geq>");
queryBuffer.push("</And>");
queryBuffer.push("</Where>");
var res = spjs_QueryItems({listName:listName,query:queryBuffer.join(”),viewFields:[‘ID’,fieldNameToReturn]});
$.each(res.items,function(i,item){
if(item[fieldNameToReturn]!==null){
var split = item[fieldNameToReturn].split(‘;#’);
var name = split[1];
var userId = split[0];
if(split.length===2&&!isNaN(parseInt(split[0],10))){
result.push({url:"<a href=’"+L_Menu_BaseUrl+"/_layouts/userdisp.aspx?Force=True&ID="+userId+"’ target=’_blank’>"+name+"</a>",
name:name,
userId:userId});
}else{
if(split.length===2){
name = split[1];
}
result.push({url:’URL: This value is available using a people picker only.’,
name:name,
userId:’userId: This value is available using a people picker only.’});
}
}
});
return result;
}

function spjs_QueryItems(argObj){
if(argObj.listBaseUrl==undefined)argObj.listBaseUrl=L_Menu_BaseUrl;
if(argObj.listName==undefined || (argObj.query==undefined && argObj.viewName==undefined)){
alert("Missing parameters!nnYou must provide a minimum of "listName", "query" or "viewName" and "viewFields".");
return;
}
var content = spjs_wrapQueryContent({‘listName’:argObj.listName,’query’:argObj.query,’viewName’:argObj.viewName,’viewFields’:argObj.viewFields,’rowLimit’:argObj.rowLimit,’pagingInfo’:argObj.pagingInfo});
var result = {‘count’:-1,’nextPagingInfo’:”,items:[]};
spjs_wrapSoapRequest(argObj.listBaseUrl + ‘/_vti_bin/lists.asmx’, ‘http://schemas.microsoft.com/sharepoint/soap/GetListItems’, content, function(data){
result.count = $(data).find("[nodeName=’rs:data’]").attr(‘ItemCount’);
result.nextPagingInfo = $(data).find("[nodeName=’rs:data’]").attr(‘ListItemCollectionPositionNext’);
$(data).find("[nodeName=’z:row’]").each(function(idx, itemData){
var fieldValObj = {}
$.each(argObj.viewFields,function(i,field){
var value = $(itemData).attr(‘ows_’ + field);
if(value == undefined) value = null;
fieldValObj[field]=value;
});
result.items.push(fieldValObj);
});
});
return result;
}

function spjs_wrapQueryContent(paramObj){
var result = [];
result.push(‘<GetListItems xmlns="http://schemas.microsoft.com/sharepoint/soap/">’);
result.push(‘<listName>’ + paramObj.listName + ‘</listName>’);
if(paramObj.viewName!=undefined && paramObj.viewName!=”){
result.push(‘<viewName>’ + paramObj.viewName + ‘</viewName>’);
}
if(paramObj.query != null && paramObj.query != ”){
result.push(‘<query><Query xmlns="">’);
result.push(paramObj.query);
result.push(‘</Query></query>’);
}
if(paramObj.viewFields!=undefined && paramObj.viewFields!=” && paramObj.viewFields.length > 0){
result.push(‘<viewFields><ViewFields xmlns="">’);
$.each(paramObj.viewFields, function(idx, field){
result.push(‘<FieldRef Name="’ + field + ‘"/>’);
});
result.push(‘</ViewFields></viewFields>’);
}
// A view overrides the itemlimit
if(paramObj.viewName==undefined){
if(paramObj.rowLimit != undefined && paramObj.rowLimit > 0){
result.push(‘<rowLimit>’ + paramObj.rowLimit + ‘</rowLimit>’);
}else{
result.push(‘<rowLimit>100000</rowLimit>’);
}
}
result.push(‘<queryOptions><QueryOptions xmlns=""><IncludeMandatoryColumns>FALSE</IncludeMandatoryColumns>’);
if(paramObj.pagingInfo != undefined && paramObj.pagingInfo != null && paramObj.pagingInfo != ”)
result.push(‘<Paging ListItemCollectionPositionNext="’ + paramObj.pagingInfo.replace(/&/g, ‘&amp;’) + ‘" />’);
result.push(‘</QueryOptions></queryOptions>’);
result.push(‘</GetListItems>’);
return result.join(”);
}

function spjs_wrapSoapRequest(webserviceUrl,requestHeader,soapBody,successFunc){
var xmlWrap = [];
xmlWrap.push("<?xml version=’1.0′ encoding=’utf-8′?>");
xmlWrap.push("<soap:Envelope xmlns:xsi=’http://www.w3.org/2001/XMLSchema-instance’ xmlns:xsd=’http://www.w3.org/2001/XMLSchema’ xmlns:soap=’http://schemas.xmlsoap.org/soap/envelope/’>");
xmlWrap.push("<soap:Body>");
xmlWrap.push(soapBody);
xmlWrap.push("</soap:Body>");
xmlWrap.push("</soap:Envelope>");
xmlWrap = xmlWrap.join(”);
$.ajax({
async:false,
type:"POST",
url:webserviceUrl,
contentType:"text/xml; charset=utf-8",
processData:false,
data:xmlWrap,
dataType:"xml",
beforeSend:function(xhr){
xhr.setRequestHeader(‘SOAPAction’,requestHeader);
},
success:successFunc,
error:function(xhr){
alert(xhr.status+"n"+xhr.responseText);
}
});
}
</script>
[/javascript]

The parameters

calendarName: The list name or list GUID of the list/calendar.
fieldToReturn: The FieldInternalName of the field to return the value from.
startDateFIN: The FieldInternalName of the start date field.
endDateFIN: The FieldInternalName of the end date field.

The returnvalue

The returnvalue from call to the function “getOnCallInfo” is an array of objects. The object has three properties:
url = a link to the SharePoint user info for the user.
userId = the userId from SharePoints user profile.
name = the name stored in the field.

The property “url” and “userId” is for use with people pickers only.

Hope someone can make use of this.
Alexander

Toggle appended comments in multi line fields

I got this request from Tim:

Tim Says:
Is there a way to hide the appended comments to a multipe line field with version control. Actually can it a a click hide/show, and can it display the last comment by default? click it the see all pervious comments.

Larry got a bit on the way, but the appended comments are a bit different in a plain text field and in a rich text field. This approach splits up the comments and wraps them in new div’s to handle the visibility.

The end result looks like this:
DispForm:
IMG
EditForm:
IMG

Put this code in a CEWP below the form in DispForm.aspx or EditForm.aspx
[javascript]
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.5.2/jquery.min.js"></script>
<script type="text/javascript">
fields = init_fields_v2();

toggleAppendOnMultiline(‘MyRichText’);
toggleAppendOnMultiline(‘MyPlainMultiLine’);

function toggleAppendOnMultiline(fin){
var currField = $(fields[fin]);
var rich = (currField.find(‘.ms-formbody div:last’).parent().find(‘div’).length>1)?true:false;
if(rich){
var allArr = currField.find(‘.ms-formbody div:last’).parent().find(‘div’).remove();
}else{
var all = currField.find(‘.ms-formbody div:last’).remove();
var allArr = all.html().split(/<br>/i);
}
var buffer = ["<table style=’width:410px’><tr><td valign=’top’ style=’font-size:0.7em;width:99%’>"];
$.each(allArr,function(i,part){
var disp = "block"
if(i>0){
disp = "none";
}
buffer.push("<div class=’"+fin+"_dummyHide’ style=’display:"+disp+"’>");
if(rich){
buffer.push($(part).html());
}else{
buffer.push(part)
}
buffer.push("</div>")
});
buffer.push("</td>");
if(allArr.length>1){
buffer.push("<td title=’Toggle visibility’ onclick=’toggleShowAll(this,""+fin+"_dummyHide")’ valign=’top’ style=’cursor:pointer;’>");
buffer.push("<div style=’white-space:nowrap;border:1px silver solid;padding:2px;background-color:#ffffff’>");
buffer.push("<img style=’vertical-align:middle’ src=’"+L_Menu_BaseUrl+"/_layouts/images/tpmax1.gif’ border=’0′>");
buffer.push("<img style=’vertical-align:middle’ src=’"+L_Menu_BaseUrl+"/_layouts/images/tpmax1.gif’ border=’0′>");
buffer.push("</div>");
buffer.push("</td>");
}
buffer.push("</tr></table>");
currField.find(‘.ms-formbody’).append(buffer.join(”));
}

function toggleShowAll(elm,id){
var img = $(elm).find(‘img’);
if(img.attr(‘on’)!==’1′){
img.attr(‘src’,L_Menu_BaseUrl+"/_layouts/images/tpmin1.gif");
img.attr(‘on’,’1′);
}else{
img.attr(‘src’,L_Menu_BaseUrl+"/_layouts/images/tpmax1.gif");
img.attr(‘on’,’0′);
}
$("div."+id+":first").nextAll().toggle();
}

function init_fields_v2(){
var res = {};
$("td.ms-formbody").each(function(){
var myMatch = $(this).html().match(/FieldName="(.+)"s+FieldInternalName="(.+)"s+FieldType="(.+)"s+/);
if(myMatch!=null){
// Display name
var disp = myMatch[1];
// FieldInternalName
var fin = myMatch[2];
// FieldType
var type = myMatch[3];
if(type==’SPFieldNote’){
if($(this).find(‘script’).length>0){
type=type+"_HTML";
}
}
if(type==’SPFieldLookup’){
if($(this).find(‘input’).length>0){
type=type+"_Input";
}
}
// Build object
res[fin] = this.parentNode;
res[fin].FieldDispName = disp;
res[fin].FieldType = type;
}
});
return res;
}
</script>
[/javascript]

Please note line 5 and 6 – i have addressed my two fields by FieldInternalName there. In the images, the comments in the field “MyRichText” has been toggled visible.

Alexander

Poll for SharePoint

March 15, 2015: I have updated this solution. You find v2.0 here.

Please note: The Google Image Charts used in this solution is deprecated and will stop working April 20, 2015.

Change log
January 28. 2014
v1.54 fixes one incompatibility with SP 2013. I have not fully tested this so please let me know if you find any bugs.

July 01. 2013 v1.53: The sort order of answers in chart now reflects the order given in the setup. I have removed some script references so that you now must refer spjs-utility.js – get it here

You must update the CEWP code to include reference to spjs-utility.js

15.12.2011 v1.5.1: Bugfix in the file “PollForSharePoint.js” – line 238. The property “listBaseUrl” were missing – thanks to Jaap Dijkma for finding this bug.


04.12.2011 I have updated the solution to support putting the list in a central location. See “listBaseUrl” below.


22.10.2011 Updated the code to support free input rather than predefined answers – as requested by Claudia:

Hi, thank you for this wonderful piece of code, I think it’s great and we use it on our intranet :).
I wondered if it is possible to use a single line of text for free input instead of radiobuttons with preset answers?
We like to use the poll for ‘brandtagging’ so that people can type keywords.
Just wondering…..
thanks! Claudia

I thought this was a clever idea and have implemented this in v1.4. See updated CEWP code and description below.


17.08.2011 Updated the code with these changes:

  • Lets you view the results and come back to answer.
  • Tidied up the code.
  • The charts now supports https (Thanks to Google).
  • Removed the poll question from the chart title to preserve the formatting.

01.03.2011 Updated the code to fix a bug when “singleResponse” is true. Thanks to “Al”. I have also included two more settings in the “argObj”: qStyle and aStyle. These sets the CSS style of question and answers. See CEWP code below.


28.11.2010 Updated the code to support special characters in the poll question and answers. Thanks to Christophe for the tip.


This code lets you generate polls using JavaScript/jQuery only. No need for server side installed WebParts.

Poll
IMG

Result with column chart
IMG

Result with bar chart
IMG

Result with pie chart
IMG

Result with “table chart”
IMG

Already answered
IMG

Not active
IMG

Finished
IMG

The charts are generated using Google Chart Tools / Image Charts (aka Chart API).


Create a custom list with the following fields

  • Answer: Single line of text
  • Question: Single line of text

Name it anything you like, but keep the display name fairly simple (no special characters) as you will use the display name in the CEWP code.

CEWP code

The CEWP code below refers jQuery from Google. If you have a local copy of jQuery you can change the script src. You find the code for the file “PollForSharePoint.js” at the bottom of the page. In this example the file “PollForSharePoint.js” is placed in a document library named “Javascript”.

NOTE: You must change the script src for the file “PollForSharePoint.js” and “spjs-utility.js” to point your instance of the files – the CEWP code will not work unless you do this.

Place this code where you want the poll to appear:

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script type="text/javascript" src="/test/English/Javascript/Poll/spjs-utility.js"></script>
<script type="text/javascript" src="/test/English/Javascript/Poll/PollForSharePoint.js"></script>
<script type="text/javascript">

buildQueryWP({pollAnswerListName:'PollA',
				listBaseUrl:L_Menu_BaseUrl,				
				id:'myPoll_01-03-2011', // Allowed characters id a-z, 0-9 - and _
				start:'10/22/2011', // format: mm/dd/yyyy
				end:'11/10/2011', // format: mm/dd/yyyy
				singleResponse:false,
				q:"What is your<br />favorite junk food?",
				qStyle:'font-size:small;font-weight:bold;color:gray',
				aStyle:'font-size:xx-small',
				a:['Pizza','Hot dog','Hamburger','Neither of them'], // Leave empty for free input				
				color:['32CD32','FFCC11','FF3300','C0C0C0'],
				forceLowerCaseAnswer:false, // Group result by lowercase				
				chart:'col', // table, bar, col or pie
				height:100,
				width:450});
</script>

You can control these values in the top of the file “PollForSharePoint.js”:

var submitLinkText = 'Submit';
var backLinkText = 'Back';
var showResultBtnText = 'Show result';
var pollNotActiveText = 'The poll is not active prior to {0}';
var pollEndedText = 'The poll ended on {0}';
var alreadyRespondedText = 'You answered: ';
var totalResponsesLabel = "Total responses: ";

Object attributes explained

  • pollAnswerListName: DisplayName or GUID of the list that stores the answers
  • listBaseUrl: The baseUrl of the site. This is like “/sites/hr” when the list is located in the site “hr” under “/sites”. Use L_Menu_BaseUrl (or omit the property) for current site. New in v1.5
  • id: The unique id of the poll. All poll answers are stored in a list and this id is used to separate each poll
  • start: Start date in the format mm/dd/yyyy
  • end: End date in the format mm/dd/yyyy
  • singleResponse: true for one reply per user, false for unlimited number of replies
  • q: Poll question. To have a linefeed in the question, use <br>
  • qStyle: CSS syntax style
  • aStyle: CSS syntax style
  • a: Answers in an array format. To use free input and not predefined answers, leave the array empty.
  • color: Colors for the chart in an array format. This must have the same length as the previous parameter – one color for each answer
  • forceLowerCaseAnswer: Primarily for use with free input to avoid getting two “series” when the only difference are uppercase characters. New in v1.4
  • chart: “bar” for bar chart, “col” for column chart, “pie” for pie chart or “table” for a plain table.
  • height: Height in pixels
  • width: Width in pixels

Regarding free input
If you leave the attribute “a” as an empty array, the user can supply free text as “answer”. When using free input, the result are automatically presented as a table.

Download code

The code for the file “PollForSharePoint.js”:
Download code from this location

Ask if anything is unclear.

Alexander

Visual status indicator based on 5 date columns in a list view

31.07.2010 Updated the code for the file “FiveDateColumnStatus.js” and the CEWP code for ListView, NewForm, DispForm and EditForm. Added support for column name in the mouse over tooltip and the percentage is now “0 %” if none of the date fields are applicable. The CEWP code has changed as the “arrOfFields” has become an object (changed the parameter name to “arrOfFieldsObj”).

29.07.2010 Fixed bug when using using calculated columns and a date field is empty. Thanks to Charlie Epes for noticing the bug. The code for the file “FiveDateColumnStatus.js” is updated.

16.07.2010 Updated the file “FiveDateColumnStatus.js” to support calculated columns.

03.07.2010 Updated the code to add DispForm integration and made the number of “date fields” dynamic – you can add as many as you like to the array. The code in the file “FiveDateColumnStatus.js” is updated, and there has been added a new section for DispForm.

I got an e-mail from Charlie Epes about a ticket over at STP

Hi Alexander:
You are mentioned in the thick of a request started by me. If you want to chime in here, please do!

http://www.endusersharepoint.com/STP/viewtopic.php?f=10&t=1319

My challenge was:
Here’s an example of what I’m trying to do in my List.

Let’s say my dog’s veterinarian offers 5 shots for my dog. The vet’s record needs to show the expiration of each of the 5 shots. The vet likes to keep a “score” for my dog showing that Rover is 80% up to date on his shots.

Of course there are exceptions. My dog will never need 1 of the shots, so it’s “not applicable” and using it as one of the 5 to calculate my percentage throws off my score. I figure that entering a distant date of 12/31/8900 would indicate that the shot is not applicable.

In my case, I’m using a List to indicate the “Health” of a client’s files by giving each client an overall score based on how up to date “eligible” files are.


I do not mean to hijack this discussion, but this code was to complex to insert in a comment over at STP… Feel free to continue the discussion where it originally started.

I thought of it and found that i could do this in another way than Charlie and Dessie had going in the discussion.

My approach reuses some scripts from this article Vertical Scrolling WebPart to get the items from a list view.

It then parses the dates and present the status by colored “boxes” and a “percent complete” value like this:
IMG

IMG

IMG = a date to come
IMG = a date that has passed
IMG = a date that is applicable, but is empty
IMG = a date that does not apply

It provides a mouse over with the “Overdue by X days” or “Due in X days”

This approach can be used with grouped views.

I have separated the main code in a file named “FiveDateColumnStatus.js”. This file should be saved locally and refered in the CEWP code. The code is found below.

To use this solution you have to:
Create some date columns, corresponding Yes/No type columns and one calculated column with the formula =”*Status*”

The date columns does not have to be in the list view, but the calculated column to hold the status and the “Title (linked to item with edit menu)” must be.

A modification from Charlie’s original idea is the presence of a checkbox for each date field to indicate whether it is applicable and should count in the total percentage – or not.
IMG
If the Checkbox is not checked – the corresponding date column is hidden.

NewForm and EditForm


This code goes in a CEWP below NewForm and/or EditForm and hides the date fields if the corresponding Yes/No column is not checked:
[javascript]
<script type="text/javascript" src="../../Javascript/jquery-1.4.2.min.js"></script>
<script type="text/javascript">
fields = init_fields_v2();
/*
This code goes in a CEWP below NewForm and/or EditForm and hides the date fields if the corresponding Yes/No column is not checked.
arrOfDateFieldsObj:
Array of objects containing FieldInternalName for the date column and FieldInternalName for the bool column to select whether the date column is applicable.
Format is {dateFIN:’FieldInternalNameOfDateColumn’,applicableFIN:’FieldInternalNameOfTriggerYesNoColumn’}.
*/

var arrOfDateFieldsObj = [{dateFIN:’DateField1′,applicableFIN:’Date1Applicable’},
{dateFIN:’DateField2′,applicableFIN:’Date2Applicable’},
{dateFIN:’DateField3′,applicableFIN:’Date3Applicable’},
{dateFIN:’DateField4′,applicableFIN:’Date4Applicable’},
{dateFIN:’DateField5′,applicableFIN:’Date5Applicable’}]

hideDateFieldsNotApplicable(arrOfDateFieldsObj);

function hideDateFieldsNotApplicable(arrOfFieldsObj){
$.each(arrOfFieldsObj,function(i,obj){
var thisChck = $(fields[obj.applicableFIN]).find(‘:checkbox’);
var checked = thisChck.attr(‘checked’);
// Onload
if(!checked){
$(fields[obj.dateFIN]).hide();
}
// Onclick
thisChck.click(function(){
var checked = $(this).attr(‘checked’);
if(checked){
$(fields[obj.dateFIN]).show();
}else if(!checked){
$(fields[obj.dateFIN]).hide();
}
});
});
}

function init_fields_v2(){
var res = {};
$("td.ms-formbody").each(function(){
var myMatch = $(this).html().match(/FieldName="(.+)"s+FieldInternalName="(.+)"s+FieldType="(.+)"s+/);
if(myMatch!=null){
// Display name
var disp = myMatch[1];
// FieldInternalName
var fin = myMatch[2];
// FieldType
var type = myMatch[3];
if(type==’SPFieldNote’){
if($(this).find(‘script’).length>0){
type=type+"_HTML";
}
}
if(type==’SPFieldLookup’){
if($(this).find(‘input’).length>0){
type=type+"_Input";
}
}
// Build object
res[fin] = this.parentNode;
res[fin].FieldDispName = disp;
res[fin].FieldType = type;
}
});
return res;
}
</script>
[/javascript]

DispForm


This code goes in a CEWP below the DispForm:
[javascript]
<script type="text/javascript" src="../../Javascript/jquery-1.4.2.min.js"></script>
<script type="text/javascript" src="../../Javascript/FiveDateColumnStatus.js"></script>
<script type="text/javascript">
fields = init_fields_v2();
/*
This code goes in a CEWP below DispForm. It displays the status field in the same way as in the list view.
It also hides the date fields if the corresponding Yes/No column is not checked.

Parameters:
listGuid: The GUID of this list
arrOfDateFieldsObj: Array of objects containing FieldInternalName for the date column, DisplayName for the date column and FieldInternalName for the bool column to select whether the date column is applicable.
Format is {dateFIN:’FieldInternalNameOfDateColumn’,dateDispName:’DisplayNameOfDateColumn’,applicableFIN:’FieldInternalNameOfTriggerYesNoColumn’}.
*/
var listGuid = "31FFC357-74DA-4830-8288-D8214781556D";
var arrOfDateFieldsObj = [{dateFIN:’_Date1′,dateDispName:’Datefield number 1′,applicableFIN:’Date1Applicable’},
{dateFIN:’DateField2′,dateDispName:’Datefield number 2′,applicableFIN:’Date2Applicable’},
{dateFIN:’DateField3′,dateDispName:’Datefield number 3′,applicableFIN:’Date3Applicable’},
{dateFIN:’DateField4′,dateDispName:’Datefield number 4′,applicableFIN:’Date4Applicable’},
{dateFIN:’DateField5′,dateDispName:’Datefield number 5′,applicableFIN:’Date5Applicable’}]

// Get ID from querystring
var thisItemID = getQueryParameters().ID;
// Call function to generate "Status field contents"
var res = getDateFieldStatus(arrOfDateFieldsObj,{‘listName’:listGuid,’ID’:thisItemID});
// Write back the result to the calculated field containig the value "*Status*"
$.each(fields,function(id,obj){
if($(obj).find(‘.ms-formbody’).text().match(/*Status*/)){
$(obj).find(‘.ms-formbody’).html(res[thisItemID].html)
}
});

// Hide fields that does not apply
$.each(arrOfDateFieldsObj,function(i,obj){
var applicable = res[thisItemID][obj.applicableFIN];
if(!applicable){
$(fields[obj.dateFIN]).hide();
$(fields[obj.applicableFIN]).hide();
}
});
</script>
[/javascript]

List view


This code is used in the list view, and must be inserted in a CEWP below the list view webpart:
[javascript]
<script type="text/javascript" src="../../Javascript/jquery-1.4.2.min.js"></script>
<script type="text/javascript" src="../../Javascript/FiveDateColumnStatus.js"></script>
<script type="text/javascript">
/*
arrOfDateFieldsObj:
Array of objects containing FieldInternalName for the date column, DisplayName for the date column and FieldInternalName for the bool column to select whether the date column is applicable
Format is {dateFIN:’FieldInternalNameOfDateColumn’,dateDispName:’DisplayNameOfDateColumn’,applicableFIN:’FieldInternalNameOfTriggerYesNoColumn’}
*/

var arrOfDateFieldsObj = [{dateFIN:’_Date1′,dateDispName:’Datefield number 1′,applicableFIN:’Date1Applicable’},
{dateFIN:’DateField2′,dateDispName:’Datefield number 2′,applicableFIN:’Date2Applicable’},
{dateFIN:’DateField3′,dateDispName:’Datefield number 3′,applicableFIN:’Date3Applicable’},
{dateFIN:’DateField4′,dateDispName:’Datefield number 4′,applicableFIN:’Date4Applicable’},
{dateFIN:’DateField5′,dateDispName:’Datefield number 5′,applicableFIN:’Date5Applicable’}]

getDateFieldStatus(arrOfDateFieldsObj);
</script>
[/javascript]

FiveDateColumnStatus.js


This is the code for the file “FiveDateColumnStatus.js”:
[javascript]
/* ———————————————
* Created by Alexander Bautz
* alexander.bautz@gmail.com
* https://spjsblog.com
* Copyright (c) 2010 Alexander Bautz (Licensed under the MIT X11 License)
* v1.1
* LastMod: 31.07.2010
* LastChange:
– Variable number of date columns
– DispForm integration
– Support for calculated columns
– 29.07.2010: Fixed bug when using using calculated columns and a date field is empty.
– 31.07.2010: Added the column name in the mouseover tooltip. If none of the date fields are applicable, the percentage reads "0 %".

* See this blog post for instructions:

Visual status indicator based on 5 date columns in a list view

* ———————————————
*/

function getDateFieldStatus(arrOfFieldsObj,qParam){
if(typeof(arrOfFieldsObj)!=’undefined’){
viewFieldsArr = [];
dateFieldsArr = [];
dateFieldsDispNameArr = [];
dateApplicableArr = [];
$.each(arrOfFieldsObj,function(i,obj){
dateFieldsArr.push(obj.dateFIN);
dateFieldsDispNameArr.push(obj.dateDispName);
dateApplicableArr.push(obj.applicableFIN);
});
viewFields = viewFieldsArr.concat([‘ID’],dateFieldsArr,dateApplicableArr);
}
if(typeof(myCustomQueryRes)==’undefined’){
wsBaseUrl = L_Menu_BaseUrl + ‘/_vti_bin/’;
if(qParam==undefined){
myCustomQueryRes = queryItemsByViewName(ctx.listName,ctx.view,viewFields);
}else{
var query = ‘<Where><Eq><FieldRef Name="ID" /><Value Type="Text">’ + qParam.ID + ‘</Value></Eq></Where>’;
myCustomQueryRes = queryItemsByCAML(qParam.listName,query,viewFields);
}
if(myCustomQueryRes.count==-1){
alert("An error occured in the query.");
}else{
resObj = {};
var now = new Date();
$.each(myCustomQueryRes.items,function(i,item){
var thisID = item.ID;
resObj[thisID] = {};
var dArr = [];
$.each(dateFieldsArr,function(j,fin){
if(item[dateApplicableArr[j]]==1){
dArr.push((item[fin]==null)?”:item[fin].replace(/w+;#/,”).split(‘-‘));
// Add to the object: applicable
resObj[thisID][dateApplicableArr[j]]=true;
}else{
dArr.push(‘NotApplicable’);
// Add to the object: not applicable
resObj[thisID][dateApplicableArr[j]]=false
}
});

var percent = 0;
var increment = ((100/dArr.length)*100)/100;
var htmlBuffer = [];
var notApplicableCount = 0;
$.each(dArr,function(idx,dateArr){
if(typeof(dateArr)==’object’){
if(dateArr.length==1){
date = ”;
}else{
var y = dateArr[0];
var m = (dateArr[1]-1);
var d = dateArr[2].substring(0,dateArr[2].indexOf(‘ ‘));
var date = new Date(y,m,d);
}
}else if(dateArr==’NotApplicable’){
notApplicableCount += 1;
date = ‘NotApplicable’;
}else if(dateArr==undefined){
date = ”;
}
var dummyIMG = "<img src=’"+L_Menu_BaseUrl+"/_layouts/images/blank.gif’ style=’height:7px;width:7px;border:1px silver solid’>";
if(date==”){
htmlBuffer.push("<span title=’"+dateFieldsDispNameArr[idx]+" is empty’ style=’background-color:yellow’>"+dummyIMG+"</span>");
}else if(date==’NotApplicable’){
percent+=increment;
htmlBuffer.push("<span title=’"+dateFieldsDispNameArr[idx]+" is not applicable’ style=’background-color:white’>"+dummyIMG+"</span>");
}else if(date>now){
percent+=increment;
var countDays = Math.floor(((date-now)/86400000)*10)/10; // 86400000 in one day
var postfix = (countDays>1)?"s":”;
htmlBuffer.push("<span title=’"+dateFieldsDispNameArr[idx]+" is due in "+countDays+" day"+postfix+"’ style=’background-color:green’>"+dummyIMG+"</span>");
}else{
var countDays = Math.floor(((now-date)/86400000)*10)/10; // 86400000 in one day
var postfix = (countDays>1)?"s":”;
htmlBuffer.push("<span title=’"+dateFieldsDispNameArr[idx]+" is overdue by "+countDays+" day"+postfix+"’ style=’background-color:red’>"+dummyIMG+"</span>");
}
});
if(notApplicableCount==dArr.length){
var percentagePostfix = "0 %";
}else{
var percentagePostfix = Math.floor(percent)+" %";
}
resObj[thisID].html=htmlBuffer.join(‘&nbsp;’)+" "+percentagePostfix;
});
}
}
if(qParam==undefined){
updateView(resObj);
}else{
return resObj;
}
}

function updateView(obj){
$("table.ms-listviewtable td:contains(‘*Status*’)").each(function(){
var lineID = $(this).parent().find(‘table.ms-unselectedtitle’).attr(‘id’);
$(this).html(obj[lineID].html);
});
}

// Attaches a call to the function to the "expand grouped elements function" for it to function in grouped listview’s
function ExpGroupRenderData(htmlToRender, groupName, isLoaded){
var tbody=document.getElementById("tbod"+groupName+"_");
var wrapDiv=document.createElement("DIV");
wrapDiv.innerHTML="<TABLE><TBODY id="tbod"+groupName+"_" isLoaded=""+isLoaded+"">"+htmlToRender+"</TBODY></TABLE>";
tbody.parentNode.replaceChild(wrapDiv.firstChild.firstChild,tbody);
getDateFieldStatus();
}

/*****************************************************
Web service calls
*****************************************************/
function queryItemsByCAML(listName, query, viewFields, rowLimit, pagingInfo){
var content = wrapQueryContent({‘listName’:listName,’query’:query,’rowLimit’:rowLimit,’viewFields’:viewFields,’pagingInfo’:pagingInfo});
var result = {count:-1, nextPagingInfo:”, items:[]};
wrapSoapRequest(wsBaseUrl + ‘lists.asmx’, ‘http://schemas.microsoft.com/sharepoint/soap/GetListItems’, content, function(data){
result.count = $(data).find("[nodeName=’rs:data’]").attr(‘ItemCount’);
result.nextPagingInfo = $(data).find("[nodeName=’rs:data’]").attr(‘ListItemCollectionPositionNext’);
$(data).find("[nodeName=’z:row’]").each(function(idx, itemData){
var fieldValObj = {}
$.each(viewFields,function(i,field){
var value = $(itemData).attr(‘ows_’ + field);
if(value == undefined) value = null;
fieldValObj[field]=value;
});
result.items.push(fieldValObj);
});
});
return result;
}

// Function to pull items from view
function queryItemsByViewName(listName, viewName, viewFields, pagingInfo){
var content = wrapQueryContent({‘listName’:listName,’viewName’:viewName,’viewFields’:viewFields,’pagingInfo’:pagingInfo});
var result = {count:-1, nextPagingInfo:”, items:[]};
wrapSoapRequest(wsBaseUrl + ‘lists.asmx’, ‘http://schemas.microsoft.com/sharepoint/soap/GetListItems’, content, function(data){
result.count = $(data).find("[nodeName=’rs:data’]").attr(‘ItemCount’);
result.nextPagingInfo = $(data).find("[nodeName=’rs:data’]").attr(‘ListItemCollectionPositionNext’);
$(data).find("[nodeName=’z:row’]").each(function(idx, itemData){
var fieldValObj = {}
$.each(viewFields,function(i,field){
var value = $(itemData).attr(‘ows_’ + field);
if(value == undefined) value = null;
fieldValObj[field]=value;
});
result.items.push(fieldValObj);
});
});
return result;
}

function wrapQueryContent(paramObj){
var result = [];
result.push(‘<GetListItems xmlns="http://schemas.microsoft.com/sharepoint/soap/">’);
result.push(‘<listName>’ + paramObj.listName + ‘</listName>’);
if(paramObj.viewName!=undefined){
result.push(‘<viewName>’ + paramObj.viewName + ‘</viewName>’);
}
if(paramObj.query != null && paramObj.query != ”){
result.push(‘<query><Query xmlns="">’);
result.push(paramObj.query);
result.push(‘</Query></query>’);
}
if(paramObj.viewFields != null && paramObj.viewFields.length > 0){
result.push(‘<viewFields><ViewFields xmlns="">’);
$.each(paramObj.viewFields, function(idx, field){
result.push(‘<FieldRef Name="’ + field + ‘"/>’);
});
result.push(‘</ViewFields></viewFields>’);
}
if(paramObj.rowLimit != undefined && paramObj.rowLimit != null && paramObj.rowLimit > 0){
result.push(‘<rowLimit>’ + paramObj.rowLimit + ‘</rowLimit>’);
}else{
result.push(‘<rowLimit>100000</rowLimit>’);
}
result.push(‘<queryOptions><QueryOptions xmlns=""><IncludeMandatoryColumns>FALSE</IncludeMandatoryColumns>’);
if(paramObj.pagingInfo != undefined && paramObj.pagingInfo != null && paramObj.pagingInfo != ”)
result.push(‘<Paging ListItemCollectionPositionNext="’ + paramObj.pagingInfo.replace(/&/g, ‘&amp;’) + ‘" />’);
result.push(‘</QueryOptions></queryOptions>’);
result.push(‘</GetListItems>’);
return result.join(”);
}

function wrapSoapRequest(webserviceUrl,requestHeader,soapBody,successFunc){
var xmlWrap = [];
xmlWrap.push("<?xml version=’1.0′ encoding=’utf-8′?>");
xmlWrap.push("<soap:Envelope xmlns:xsi=’http://www.w3.org/2001/XMLSchema-instance’ xmlns:xsd=’http://www.w3.org/2001/XMLSchema’ xmlns:soap=’http://schemas.xmlsoap.org/soap/envelope/’>");
xmlWrap.push("<soap:Body>");
xmlWrap.push(soapBody);
xmlWrap.push("</soap:Body>");
xmlWrap.push("</soap:Envelope>");
xmlWrap = xmlWrap.join(”);
$.ajax({
async:false,
type:"POST",
url:webserviceUrl,
contentType:"text/xml; charset=utf-8",
processData:false,
data:xmlWrap,
dataType:"xml",
beforeSend:function(xhr){
xhr.setRequestHeader(‘SOAPAction’,requestHeader);
},
success:successFunc
});
}

/*********************************
Helper functions
*********************************/
// Function to separate each url search string parameters
function getQueryParameters(){
qObj = {};
var urlSearch = window.location.search;
if(urlSearch.length>0){
var qpart = urlSearch.substring(1).split(‘&’);
$.each(qpart,function(i,item){
var splitAgain = item.split(‘=’);
qObj[splitAgain[0]] = splitAgain[1];
});
}
return qObj;
}

function init_fields_v2(){
var res = {};
$("td.ms-formbody").each(function(){
var myMatch = $(this).html().match(/FieldName="(.+)"s+FieldInternalName="(.+)"s+FieldType="(.+)"s+/);
if(myMatch!=null){
// Display name
var disp = myMatch[1];
// FieldInternalName
var fin = myMatch[2];
// FieldType
var type = myMatch[3];
if(type==’SPFieldNote’){
if($(this).find(‘script’).length>0){
type=type+"_HTML";
}
}
if(type==’SPFieldLookup’){
if($(this).find(‘input’).length>0){
type=type+"_Input";
}
}
// Build object
res[fin] = this.parentNode;
res[fin].FieldDispName = disp;
res[fin].FieldType = type;
}
});
return res;
}
[/javascript]
Save as “FiveDateColumnStatus.js” – mind the file extension and update the script “src” in the CEWP code to point to where you save this script.

Ask if anything is unclear!
Alexander