Category Archives: CAML Query

List all attachments when clicking the paperclip in a list view

Change log:

07.10.2011 A new version is published – you find it here.

23.09.2010 Moved the code to a server for direct download to make it easier for the users. You find the link below. The current stable version is 1.5.

13.09.2010 Fixed bug when ID column was not placed to the far right.

07.09.2010 Fixed bug when list view was not the topmost webpart.

30.08.2010 Added “one click open” if only one attachment is found.


I got this request from Chris:

…the challenge I’m currently trying to solve is to get the attachments paperclip in a listview clickable. Using a doclib and linking against the file is not an option since we are talking about a lot of files with the same name which should be stored with the list entry (one file per entry).

There’s a solution from Paul Grenier at EUSP, but that doesn’t work for large collections, so it’s not usable.

I thought of setting up the path ‘manually’, and displaying this entry, since I noticed that the attachment path is always like URL/site/lists/listname/attachments/list_item_id/filename. Though I might be able to come up with all the details up to the ID I have no idea on how to get the filename automatically.

Can you think of any other way to make the paperclip clickable to open the attachment?

Thanks,
Chris


Here we go:

This method uses the webservice lists.asmx and the operation GetAttachmentCollection.

It is tested in IE8, Chrome 5.0 and Firefox 3.6.8 in WSS3.0. It works in both standard list views, and grouped views.

It has briefly been tested in SP2010, but is only partially compatible (minor issue with the click on the paperclip selecting the row, and it only works in non-grouped views).

The only requirement for this solution to work is the ID column being in the view – it can be hidden by setting the variable hideIdColumn = true (default).

The CEWP code

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js" type="text/javascript"></script>
<script src="/test/English/Javascript/previewAttachmentsOnClick.js" type="text/javascript"></script>
<script type="text/javascript">

   hideIdColumn = true;
   customListAttachments();

</script>

Place the CEWP below the list view!

Download the file “previewAttachmentsOnClick.js” from this location

Note:

When new versions are released, they will be placed in a folder with the version number as label. Be sure to download the latest version.

If you are using a browser other than IE, right click the file and select “Save link as” or “Save linked content as…”.

As 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:

<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>

DispForm


This code goes in a CEWP below the DispForm:

<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>

List view


This code is used in the list view, and must be inserted in a CEWP below the list view webpart:

<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>

FiveDateColumnStatus.js


This is the code for the file “FiveDateColumnStatus.js”:

/* ---------------------------------------------
 * 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(' ')+" "+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, '&') + '" />'); 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; }

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

Vertical Scrolling WebPart

15.07.2010 Updated the code for the file “VerticalScrollingWebPart.js” to try to fix the overflow issue in IE6.

24.06.2010 The code for the file “VerticalScrollingWebPart.js” is updated. I actually forgot to update it as i made some adjustments in the CEWP code… I hope the overflow issue is fixed with this update.

I got this request from Charlie:

…a solution that I can use as a dashboard web part to vertically scroll the most recent “top 10” items from a 2nd list?

Example: I need to be able to grab the most recently items marked as “Completed” or “Sold” from a list and be able to show 2-3 fields in the scroller.

Click here for a crude example – the scrolling is not so choppy – this is only a animated gif to give you a hint of how the solution works.

The scrolling action pauses when hovered with the mouse.

As always we start like this:
Create a document library to hold your scripts (or a folder on the root created in SharePoint Designer). In this example i have made a document library with a relative URL of “/test/English/Javascript” (a sub site named “test” with a sub site named “English” with a document library named “Javascript”):
IMG

The jQuery-library is found here. The pictures and the sourcecode refers to jquery-1.4.2.min. Update the script “src” if you use another version.

The sourcecode for the file “VerticalScrollingWebPart.js” is provided below.

Add this code to a CEWP where you want the scrollable contents to appear:

<script type="text/javascript" src="/test/English/Javascript/jquery-1.4.2.min.js"></script>
<script type="text/javascript" src="/test/English/Javascript/VerticalScrollingWebPart.js"></script>
<script type="text/javascript">
init_fillScrollableDiv({'listGuid':'A4B4E15A-C5B0-47BC-A08B-739CD48FE58A',
	'listBaseUrl':'/test/English',
	'listViewGuid':'5BD378F4-25D5-4880-9C5B-1667FE43978D',											
	'viewFields':['Title','MultiLine'],
	'viewFieldsStyle':['font-weight:bold','padding:0 0 0 5'],	
	'divID':'myScrollableDiv',
	'divHeight':'250px',
	'divWidth':'500px',	
	'speed':4,
	'linkBack':true});
</script>

Read here how to find the FieldInternalNames for your fields and the “listGuid” or “listViewGuid” for your list.

Parameters explained:

  • listGuid: GUID of the source-list
  • listBaseUrl: Relative URL to site/subsite. If root site use only two quotes representing a blank string – like this: “”.
  • listViewGuid: GUID of the view to use from the source-list – if left empty it uses the default view.
  • viewFields: Array of FieldInternalNames to use in the scrolling webpart.
  • viewFieldsStyle: Array of styles to match the array of FieldInternalNames above.
  • divID: The ID of the scrollable DIV. Can be anything as long as it is unique on the page.
  • divHeight: The hight of the scrollable area.
  • divWidth: The width of the scrollable area.
  • speed: A number representing the scroll speed.
  • linkBack: If set to true it adds a link to open the item clicked on.

The sourcecode for the file “VerticalScrollingWebPart.js”:

/* Pulls items from a list view and presents them as a Vertical Scrolling Web Part
 * ---------------------------------------------
 * Created by Alexander Bautz
 * alexander.bautz@gmail.com
 * https://spjsblog.com
 * Copyright (c) 2009-2010 Alexander Bautz (Licensed under the MIT X11 License)
 * v1.2
 * LastMod: 14.07.2010
 	- LastChange: 23.12.2014 - fixed a jQuery incompatibility issue for newer jQuery versions. Please note that the code is still old and not the best of quality.
 * ---------------------------------------------
 * Include reference to:
 *  jquery - http://jquery.com
 *	VerticalScrollingWebPart.js (this file)
 * ---------------------------------------------
*/

function init_fillScrollableDiv(obj){
	// Build the div
	var myDivBuffer = [];
	myDivBuffer.push("<div style='vertical-align:top;position:relative;overflow:hidden;cursor:default;height:"+obj.divHeight+";width:"+obj.divWidth+"'>");
	myDivBuffer.push("<div id='"+obj.divID+"' style='position:relative'></div>");
	myDivBuffer.push("</div>");
	myDivContainer=myDivBuffer.join('');	
	document.write(myDivContainer);
	$(document).ready(function(){
		fillScrollableDiv(obj)
	});
}

function fillScrollableDiv(info){
	wsBaseUrl = info.listBaseUrl + '/_vti_bin/';
	info.animBegin = 0;
	info.animPart = 0;
	// Query the list for items	
	var res = queryItemsByViewName(info.listGuid,info.listViewGuid,info.viewFields.concat('ID','FileDirRef'));
	if(res.count==-1)alert("An error occured - check the parameters \"listGuid\", \"listBaseUrl\" and \"listViewGuid\".");
	var finalBuffer = [];
	var path = '';
	$.each(res.items,function(i,item){
		var partBuffer = [];
		if(path==''){
			var pathRaw = item['FileDirRef'];
			path = "/"+pathRaw.substring(pathRaw.indexOf(';#')+2);
		}	
		$.each(info.viewFields,function(idx,fin){
			var style = '';
			var thisVal = (item[fin]==null)?'':item[fin];
			if(thisVal.indexOf(';#')>-1){
				thisVal = thisVal.substring(thisVal.indexOf(';#')+2);
			}			
			if(info.viewFieldsStyle[idx]!=undefined){
				style = " style='"+info.viewFieldsStyle[idx]+"'";
			}
			partBuffer.push("<tr><td"+style+">"+thisVal+"</td></tr>");	
		});		
		finalBuffer.push("<hr style='height:1px;color:black' />");
		if(info.linkBack){
			finalBuffer.push("<table title='Go to item' style='cursor:pointer' ");
			finalBuffer.push("onclick='javascript:location.href=\""+path+"/DispForm.aspx?ID="+item['ID']+"&Source="+location.href+"\"' ");
			finalBuffer.push("cellspacing='0' cellpadding='0'>"+partBuffer.join('')+"</table>");
		}else{
			finalBuffer.push("<table cellspacing='0' cellpadding='0'>"+partBuffer.join('')+"</table>");
		}	
	});
	var myContents = finalBuffer.join('');
	// Update the content in the scrollable div
	$("#"+info.divID).html(myContents)
		.mouseenter(function(){			
			var now = new Date();
			info.animPart += (now-info.animBegin);		
			$(this).stop();
		})
		.mouseleave(function(){		
			$(this).stop();
			var partScr = parseInt($(this).css('top'));
			scrollMyDiv(partScr,info);
		});
	// Call scroll function
	scrollMyDiv('',info);
}

function scrollMyDiv(scroll,info){
	info.animBegin = new Date();
	var myDiv = $("#"+info.divID);
	var ch = myDiv.height();
	var chpHeight = myDiv.parent().height();	
	if(scroll==''){
		var scroll=chpHeight;
	}
	var duration = (ch*(info.speed*10))-info.animPart;
	myDiv.css({'top':scroll}).animate({"top":-ch},duration,'linear',function(){
		info.animPart = 0;
		scrollMyDiv('',info);
	});
}

// http://www.steveworkman.com/html5-2/javascript/2011/improving-javascript-xml-node-finding-performance-by-2000/
$.fn.filterNode = function(name) {
	return this.find('*').filter(function() {
		return this.nodeName === name;
	});
};

// Function to pull items from view
function queryItemsByViewName(listName, viewName, viewFields, pagingInfo){
	var content = buildQueryContentByViewName(listName, viewName, viewFields, pagingInfo);
	var result = {count:-1, nextPagingInfo:'', items:[]};
	wrapSoapRequest(wsBaseUrl + 'lists.asmx', 'http://schemas.microsoft.com/sharepoint/soap/GetListItems', content, function(data){
		result.count = parseInt($(data).filterNode("rs:data").attr('ItemCount'),10);
		result.nextPagingInfo = $(data).filterNode("rs:data").attr('ListItemCollectionPositionNext');
		$(data).filterNode('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 buildQueryContentByViewName(listName, viewName, viewFields, pagingInfo){
	var result = [];
	result.push('<GetListItems xmlns="http://schemas.microsoft.com/sharepoint/soap/">');
	result.push('<listName>' + listName + '</listName>');
	result.push('<viewName>' + viewName + '</viewName>');
	if(viewFields != null && viewFields.length > 0){
		result.push('<viewFields><ViewFields xmlns="">');
		$.each(viewFields, function(idx, field){
			result.push('<FieldRef Name="' + field + '"/>');
		});
		result.push('</ViewFields></viewFields>');
	}
	result.push('<queryOptions><QueryOptions xmlns=""><IncludeMandatoryColumns>FALSE</IncludeMandatoryColumns>');
	if(pagingInfo != undefined && pagingInfo != null && pagingInfo != '')
		result.push('<Paging ListItemCollectionPositionNext="' + pagingInfo.replace(/&/g, '&') + '" />');
	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
	});
}

Save as “VerticalScrollingWebPart.js” – mind the file extension – and upload to the scriplibrary as shown above.

Ask if anything is unclear!
Alexander

Cascading dropdowns in SharePoint text fields – populated by lookup in another list (version 2)

03.11.2010 Updated the code to eliminate the need to refer other external resources than jQuery. Removed the argument “lookupSourceListURL” from the function call.

The code is tested in IE, Chrome and Firefox. Opera is not supported.

NOTE: When updating existing script you must modify the function call and remove the argument “lookupSourceListURL”.


I have previously posted a solution for creating cascading dropdowns from SharePoint single line text fields. Populated based on a query against another list.

I have reviewed the script to add a few enhancements.

  • No more need to create a calculated column in the “lookup list”
  • Less arguments to pass to the function – sleeker code
  • Overcomes a possible bug regarding the previous version using “BeginsWith” rather than “Eq” to match the items

This release (as the previous) has these features:

  • “Converts” standard SharePoint single line text fields to dropdowns
  • Uses the converted SharePoint single line text fields to hold the values
  • Populates the dropdowns by querying any SharePoint list or library
  • Dynamically fills or clears the hidden fields holding the selected value to adapt to changes in the selections – thus preventing “impossible combinations”
  • Preserves selections during page refresh due to form validation
  • Reads back and fills the dropdowns if used in EditForm

As always we start like this:
Create a document library to hold your scripts (or a folder on the root created in SharePoint Designer). In this example i have made a document library with a relative URL of “/test/English/Javascript” (a sub site named “test” with a sub site named “English” with a document library named “Javascript”). Upload jQuery and the file “spjs_CascadingDropDowns_v2.js” to that library.

The jQuery-library is found here. The sourcecode refers to jquery-1.4.2.min. Some of the functions are not supported in previous releases.

The sourcecode for the file “spjs_CascadingDropDowns_v2.js” can be found below.

Read here how to add a CEWP to the NewForm or EditForm, how to find the list Guid of your list, and how to find the FieldInternalName of your columns.

You can pull any values from another list – an example provided below.

Source list:
IMG
The field “Make” is the native “Title” field.

Target list:
IMG

The CEWP code – place below the Form:

&lt;script type=&quot;text/javascript&quot; src=&quot;/test/English/Javascript/jquery-1.4.2.min.js&quot;&gt;&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot; src=&quot;/test/English/Javascript/spjs_CascadingDropDowns_v2.js&quot;&gt;&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot;&gt;
   // Use the FieldInternalName and not the Displayname.
   providerArr = ['Title','carModel','carColor','carInterior','carMilage'];
   consumerArr = ['Title','Model','Color','Year','Milage'];
   cascadingDropDowns_v2(providerArr,consumerArr,'{83eb224b-03fa-4a8b-b493-80253373a962}','&lt;select&gt;',5,true,false);
&lt;/script&gt;

Parameters explained:

  • providerArr: Array of FieldInternalNames of the fields in the source-list
  • consumerArr: Array of FieldInternalNames of the fields in the list where the dropdowns will be created
  • lookupSourceListGuid: GUID of the source-list
  • dropDownDefaultvalue: The default value of dropdowns that are not empty – ex. <select>
  • numberOfDropdowns: Number of levels of cascading dropdowns – (2-5)
  • debug: true or false – if true: the textfield that holds the dropdownvalue is visible and some alerts are displayed

The code for the file “spjs_CascadingDropDowns_v2.js” can be found here

How to use these scripts in a customized form

Ask if anything is unclear.

Alexander

Autocomplete for single line of text

I got a request form Charlie on how to accomplish autocomplete for a single line text-field, reading the values from itself.

This solution resembles my Autocomplete for SharePoint people picker, but it pulls date into a single line text field.

As always we start like this:
Create a document library to hold your scripts (or a folder on the root created in SharePoint Designer). In this example i have made a document library with a relative URL of “/test/English/Javascript” (a sub site named “test” with a sub site named “English” with a document library named “Javascript”):
IMG

In addition to the above scripts, i have the jQuery UI 1.8 in a separate folder. See the CEWP code and point the links to your jQuery UI location.

The jQuery UI-library is found here. The pictures and the sourcecode refers to jquery-ui-1.8. The autocomplete widget is not found in previous releases.

The jQuery-library is found here. The pictures and the sourcecode refers to jquery-1.4.2.min. The autocomplete widget is not supported in previous releases.

The scripts “interaction.js” and “stringBuffer.js” is created by Erucy and published on CodePlex.

Read here how to add a CEWP to the NewForm or EditForm, how to find the list Guid of your list, and how to find the FieldInternalName of your columns.

Add a CEWP below the list form in NewForm or EditForm, and insert this code:

&lt;link type=&quot;text/css&quot; href=&quot;../../jQueryUI18/smoothness/jquery-ui-1.8.custom.css&quot; rel=&quot;stylesheet&quot;&gt;
&lt;script type=&quot;text/javascript&quot; src=&quot;../../jQueryUI18/jquery-1.4.2.min.js&quot;&gt;&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot; src=&quot;../../jQueryUI18/jquery-ui-1.8.custom.min.js&quot;&gt;&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot; src=&quot;../../Javascript/interaction.js&quot;&gt;&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot; src=&quot;../../Javascript/StringBuffer.js&quot;&gt;&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot;&gt;
fields = init_fields_v2();

/* 
	Call autocomplete function with these parameters:
	sourceFIN: FieldInternalName of the field to query for the value
	targetFIN: FieldInternalName of the field to add the autocomplete to
	listName: List name or list GUID of the list to query
	listBaseUrl: The base url for the list to query. If on a managed path it must reflect this.	
*/

setAutocompletefromQuery('Title','Title','0582CD60-C312-4483-996B-A15C27E332AA','');

function setAutocompletefromQuery(sourceFIN,targetFIN,listName,listBaseUrl){
var availableTags = [];
wsBaseUrl = listBaseUrl + '/_vti_bin/';
var query = &quot;&lt;Where&gt;&lt;IsNotNull&gt;&lt;FieldRef Name='&quot;+sourceFIN+&quot;' /&gt;&lt;/IsNotNull&gt;&lt;/Where&gt;&quot;;
var res = queryItems(listName,query,[sourceFIN]);
	// Build array of unique values - might be slow if list contains large amounts of data
	$.each(res.items,function(i,item){
		var currVal = item[sourceFIN];
		if($.inArray(currVal,availableTags)==-1){
			availableTags.push(currVal);
		}
	});
	// Add autocomplete
	$(fields[targetFIN]).find('input').autocomplete({
			source: availableTags
	});
// Text size in dropdown
$(&quot;body&quot;).css({'font-size':'65%'});
}

/*
  LastMod: 07.05.2010
*/
function init_fields_v2(){
	var res = {};
	$(&quot;td.ms-formbody&quot;).each(function(){
	var myMatch = $(this).html().match(/FieldName=&quot;(.+)&quot;s+FieldInternalName=&quot;(.+)&quot;s+FieldType=&quot;(.+)&quot;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&gt;0){
					type=type+&quot;_HTML&quot;;
				}
			}
			if(type=='SPFieldLookup'){
				if($(this).find('input').length&gt;0){
					type=type+&quot;_Input&quot;;
				}
			}
			// Build object
			res[fin] = this.parentNode;
			res[fin].FieldDispName = disp;
			res[fin].FieldType = type;
		}		
	});
	return res;
}
&lt;/script&gt;

Ask if anything is unclear.

Alexander

Validate text field input against value in another list

I got this request from Sonaly:

I am using MOSS.

I have two lists Machines and TRansactions.

I have 3 following textboxes in newform.aspx/editform.aspx of Transactions List.

EnqNo – Plain Text box – Required field
Date – Datetime field – Required field
MachineID – Plain Text box – Required field

Here I want to validate Machine ID from Machines List (MachineId column) before save record into transaction list

Let me know if you need more information,


Alexander Says:
Take a look at this script: Convert Singleline textfield to filtered lookup dropdown and see if this could fill your need.

The script will convert your “MachineID” to a lookup from the list “Machines”.

Alexander


Sonaly Says:
Alexandar

I dont want to use lookup field as I have 1000+ item and it is not user friendly , that is why I am thinking of using Textbox coumn and validation.

Any other advise


This example has a two list setup with only the “Title” field present in each list. You will have to edit the FieldInternalName to match your fields.

Add this code to a CEWP below the form in NewForm and EditForm in the list the user will input the value in:

&lt;style type=&quot;text/css&quot;&gt;
.customError{
	background-color:#FF6A6A;
}
&lt;/style&gt;
&lt;script type=&quot;text/javascript&quot; src=&quot;/test/English/Javascript/jquery-1.3.2.min.js&quot;&gt;&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot; src=&quot;/test/English/Javascript/interaction.js&quot;&gt;&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot; src=&quot;/test/English/Javascript/stringBuffer.js&quot;&gt;&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot;&gt;
fields = init_fields();

// Attach a function to the blur event of the &quot;Title&quot; field
$(fields['Title']).find('input').blur(function(){
	var thisVal = $(this).val();
	validateTextAgainstList($(this));
});

function validateTextAgainstList(obj){
str = obj.val();
wsBaseUrl = L_Menu_BaseUrl + '/_vti_bin/';
// Edit the &quot;Title&quot; to match your FieldInternalName
var query = &quot;&lt;Where&gt;&lt;Eq&gt;&lt;FieldRef Name='Title' /&gt;&lt;Value Type='Text'&gt;&quot;+str+&quot;&lt;/Value&gt;&lt;/Eq&gt;&lt;/Where&gt;&quot;;
// Edit the list GUID to match your list - or use the list's displayName
	var itemCount = queryItemCount('D54206E8-5E98-4DCD-9D3D-39C321FD0792',query);
	if(itemCount==0){		
		$(&quot;input[id$='SaveItem']&quot;).attr('disabled',true);
		obj.addClass('customError');
		alert(&quot;Sorry mate, this value is not correct.&quot;);
	}else{
		// OK
		$(&quot;input[id$='SaveItem']&quot;).attr('disabled',false);
		obj.removeClass('customError');
	}
}

function init_fields(){
var res = {};
$(&quot;td.ms-formbody&quot;).each(function(){
if($(this).html().indexOf('FieldInternalName=&quot;')&lt;0) return; 
var start = $(this).html().indexOf('FieldInternalName=&quot;')+19;
var stopp = $(this).html().indexOf('FieldType=&quot;')-7; 
var nm = $(this).html().substring(start,stopp);
res[nm] = this.parentNode;
});
return res;
}
&lt;/script&gt;

You will have to edit the FieldRef Name=’Title’ to match your fields FieldInternalName, and the list GUID (D54206E8-5E98-4DCD-9D3D-39C321FD079) to match your list – or use the list’s displayName.

The jQuery-library is found here. The sourcecode refers to jquery-1.3.2.min. If you download another version, be sure to update the script reference in the sourcecode.

The scripts “interaction.js” and “stringBuffer.js” is created by Erucy and published on CodePlex.

Read here how to add a CEWP to the NewForm, DispForm or EditForm, how to find the list Guid of your list, and how to find the FieldInternalName of your columns.

Regards
Alexander

Display information from another list based on a lookup column connection

16.10.2013 New version: https://spjsblog.com/2013/10/16/display-information-from-another-list-based-on-a-lookup-column-connection-updated-version/

23.05.2010 Updated to fix hyperlink columns (splits the hyperlink by the first “, ” to separate URL and description).

20.05.2010 Updated to support hyperlink columns formatted as hyperlink and hiding of empty “rows”.

26.02.2010 Updated to support multiple lookup columns.


Here is is an example on how to display information from another list based on a lookup column connection.

You have a single choice lookup column connection to another list. When selecting a value from the lookup column, the script pulls the information from the “lookup source” and displays it below the lookup column.
IMG
As always we start like this:
Create a document library to hold your scripts (or a folder on the root created in SharePoint Designer). In this example i have made a document library with a relative URL of “/test/English/Javascript” (a sub site named “test” with a sub site named “English” with a document library named “Javascript”):
IMG

The jQuery-library is found here. The pictures and the sourcecode refers to jquery-1.3.2.min. If you download another version, be sure to update the script reference in the sourcecode.

The scripts “interaction.js” and “stringBuffer.js” is created by Erucy and published on CodePlex.

The sourcecode for the file “PullInformationFromConnectedList.js” is found below.

Add a CEWP below the list form in NewForm or EditForm, and insert this code:

<script type="text/javascript" src="../../Javascript/jquery-1.3.2.min.js"></script>
<script type="text/javascript" src="../../Javascript/interaction.js"></script>
<script type="text/javascript" src="../../Javascript/stringBuffer.js"></script>
<script type="text/javascript" src="../../Javascript/PullInformationFromConnectedList.js"></script>
<script type="text/javascript">
// Init all fields
fields = init_fields();
/* Object containing all arguments for the function
 * "arrFinAndDispName" is an array on format "FieldInternalName|Display name" from the list the lookup is pulling information from
 * "ListGuid" is the list Guid or the displayName of the list the lookup is pulling information from
 * "LookupFIN" id the FieldInternalName of the lookup column.
*/
var argumentObj = {'arrFinAndDispName':['Title|Element title',
					'TextField1|My text field 1',
					'TextField2|My text field 2',
					'TextField3|My text field 3',
					'Responsible|Responsible',
					'RichText|Rich text multi line'],
					'ListGuid':'405EC50E-FAF7-4473-8D50-F9E725BEAA9B',
					'LookupFIN':'Lookup'};

init_displayInfo(argumentObj);
</script>

You must change the list Guid of the “target list” to match your list, the “arrOfFieldsToReturn” to match your fields and the “Lookup column” FieldInternalName.

To use for multiple lookup columns, just build another “argumentObj”, and call the function “init_displayInfo” again with the new “argumentObj”.

Read here how to add a CEWP to the NewForm, DispForm or EditForm, how to find the list Guid of your list, and how to find the FieldInternalName of your columns.

The sourcecode for the file “PullInformationFromConnectedList.js” looks like this:

/* Display information from another list based on a lookup column connection
 * ----------------------------------------------------
 * Created by Alexander Bautz
 * alexander.bautz@gmail.com
 * https://spjsblog.com
 * Copyright (c) 2009-2010 Alexander Bautz (Licensed under the MIT X11 License)
 * Version: 1.3
 * LastMod: 23.05.2010
 * LastChange: Updated the hyperlink handling (splits the hyperlink by the first ", " to separate URL and description
 * ----------------------------------------------------
 * Must include reference to:
	jQuery - http://jQuery.com
	interaction.js and stringBuffer.js - http://spjslib.codeplex.com
*/

function init_displayInfo(argObj){
if(typeof(fields)=='undefined')fields = init_fields();
// On load - For EditForm or for page refresh on formvalidation
var inpHidID = $(fields[argObj['LookupFIN']]).find('input').attr('optHid');
var selID = $("*[id='"+inpHidID+"']").val();
displayInfo(selID,argObj);

// Bind events to the selection of elements
	if($(fields[argObj['LookupFIN']]).find('img').length==0){
	 // Lookup when it contains less than 20 elements
		$(fields[argObj['LookupFIN']]).find('select').change(function(){
			var selID = $(this).val();
			displayInfo(selID,argObj);
		});		
	}else{
	// Lookup when it contains more than 20 elements
		// Enter the lookup value in the input field	
		$(fields[argObj['LookupFIN']]).find('input').keydown(function(e){
			if(e.keyCode==13){
				var inpHidID = $(this).parents('tr:first').find('input').attr('optHid');
				var selID = $("*[id='"+inpHidID+"']").val();
				displayInfo(selID,argObj);
			}			
		});
		
		// Select from the dropdown
		$(fields[argObj['LookupFIN']]).find("img").click(function(){
			// The "options container" is shared between all lookup column
			$("*[id='_Select']").bind("dblclick keydown", function(e){
				var selID = $(this).val();
				displayInfo(selID,argObj);
			});
		});		
	}
}

function displayInfo(selectedID,argObj){
	var strRaw = getListItemFromLookup(selectedID,argObj);
	// Remove existing preview
	$("#customListAbstract_"+argObj['LookupFIN']).remove();
	str = "";
	// Display the selected element
	if(strRaw!=false){
		$.each(strRaw,function(fin,val){
			if(val!=' '){
				if(val.indexOf('http')==0){
					var part_1 = val.substring(0,val.indexOf(', '));
					var part_2 = val.substring(val.indexOf(', ')+2);
					val = "<a title='Opens in a new window' href='"+part_1+"' target='_blank'>"+part_2+"</a>";
				}
				str += "<tr style='font-size:10px;color:gray'>",
				str += "<td valign='top' width='200px' style='border-bottom:1px silver solid;border-right:1px silver solid;padding:2'>"+fin+"</td>";
				str += "<td valign='top' style='padding:2;border-bottom:1px silver solid'>"+val+"</td>";
				str += "</tr>";
			}
		});
		str = "<tr id='customListAbstract_"+argObj['LookupFIN']+"'>"+
			  "<td colspan='2' style='padding:5 10 5 10'>" +
			  "<table width='580' cellspacing='0' cellpadding='0' style='border-top:1px silver solid'>"+str+"</table>" +
			  "</td></tr>"
	}
	// Insert the preview below the lookup column
	$(fields[argObj['LookupFIN']]).after(str);
}

function getListItemFromLookup(LookupID,argObj){
var arrFin = [];
var arrDispName = [];
// Split the array in separate arrays for InternalName and DisplayName
$.each(argObj['arrFinAndDispName'],function(i,item){
	split = item.split('|');
	arrFin.push(split[0]);
	arrDispName.push(split[1]);
});
	// Get the correct list item
	wsBaseUrl = L_Menu_BaseUrl + '/_vti_bin/'; // Change this path if the list is not in the current site
	var item = getItemById(argObj['ListGuid'],LookupID,arrFin);
	if(item!=null){
		var ret = {};
		$.each(arrFin,function(i,fin){
			var thisVal = item[fin];
			if(thisVal==null){
				thisVal=' ';
			}else if(thisVal.indexOf(';#')>0){
				thisVal=thisVal.substring(thisVal.indexOf(';#')+2);
			}
			ret[arrDispName[i]]=thisVal;
		});
		return ret;
	}else{
		return false;
	}
}

function init_fields(){
var res = {};
$("td.ms-formbody").each(function(){
if($(this).html().indexOf('FieldInternalName="')<0) return; 
var start = $(this).html().indexOf('FieldInternalName="')+19;
var stopp = $(this).html().indexOf('FieldType="')-7; 
var nm = $(this).html().substring(start,stopp);
res[nm] = this.parentNode;
});
return res;
}

Save as “PullInformationFromConnectedList.js”, mind the file extension, and upload to the script library as shown above.

Ask is anything is unclear.

Regards
Alexander

Hit counter for SharePoint

28.05.2011 I have redone this solution to use a star-rating in stead of the simple “like” button. You find the new version here


01.11.2010 Redone the scripts and added support for rating individual items in a list – for example in “Dispform” in a blog:
IMG

The solution counts “Hits” and “Likes”.


Create a document library to hold your scripts

Or a folder on the root created in SharePoint Designer). In this example i have made a document library with a relative URL of “/test/English/Blog/Scripts” (a sub site named “test” with a sub site named “English” with a subsite named “Blog” and a document library named “Scripts”).

When you refer the scripts in the CEWP, ensure that you point to the correct location of your scripts.

The jQuery-library is found here. The CEWP code refers to jquery-1.4.2.min. If you download another version, be sure to update the script reference in the CEWP.

The sessvars.js is created by Thomas Frank and can be found here

The sourcecode for the file “HitCounterForSharePoint.js” is found here

Create a list with the name “HitCounter”, and add these fields:

  • URL: Multiline plain text
  • User: Person or Group
  • ReferringURL: Multiline plain text
  • Like: Single line of text

You have to give all users write access to the list “HitCounter”.

Add a CEWP where you want this counter to appear, and add this code:

&lt;script type=&quot;text/javascript&quot; src=&quot;/test/English/Blog/Scripts/jquery-1.4.2.min.js&quot;&gt;&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot; src=&quot;/test/English/Blog/Scripts/sessvars.js&quot;&gt;&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot; src=&quot;/test/English/Blog/Scripts/HitCounterForSharePoint.js&quot;&gt;&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot;&gt;
	hitCounter(true,true);
&lt;/script&gt;

Parameters:

  • oncePerSession: True to allow one “hit-count” per unique item per browser session.
  • isDispForm: If true, includes the ID of the item to allow individual counting of each item in a list.

Ask if something is unclear!

Regards
Alexander