Category Archives: Form modification

Tabs for SharePoint forms v2.0

26.11.2011 I have updated the script to v2.4 to attempt to fix some problems withe overlapping tabs in IE7. I have moved the files to another server. Follow the link under the “How to use this solution” section below. I have added one new “attibute” under the settings section in the CEWP code: “baseTabColor”. See below for details.


24.03.2011 Updated the script to fix an issue with the attachments. They now appear at the bottom of every tab – like in a unmodified form. If there are no attachments, the field is hidden.

In the CEWP-code the example-tab containing the attachments has been removed.


19.03.2011 v2.1 adds the ability to call a function after the tab has expanded. You can specify a shared function that will be called on every tab, and/or a function that is called on one specific tab.


This solution has previously been published over at NothingButSharePoint


This solution is used to “tab” SharePoint forms. If you have a long form, you can group fields together and present them in tabs for a better overview.
IMG

Features

  • Full SP2007 and SP2010 support for both lists and document libraries
  • Works for all standard field types (Custom field types are not guaranteed to work)
  • A field can be used in multiple tabs
  • You can have a tab displaying all fields
  • You can have a tab catching all orphans (fields that are not displayed in any other tab). Useful if one adds columns to a list without updating the script call.
  • Highlights tab if a field fails validation upon save
  • Use a URL query string parameter to expand a specific tab

Browser compatibility tested in:

  • IE6 (Works in SP2007 only due to SP2010 incompatibility with IE6)
  • IE7
  • IE8
  • Firefox 3.6.13
  • Google Chrome 8.0.552.237
  • Safari 5.0.2

How to use this solution

Download the code for the file “TabsForSharePointForms.js” from this location

Upload the file to your script repository. This can be a shared document library in the site where you will be using the solution (ensure ALL users have read access).

For each of the forms (NewForm.aspx, DispForm.aspx and EditForm.aspx) add a Content Editor Web Part (CEWP) below the form.

For SharePoint 2007

To put the page in edit mode, modify the URL like this:
/Lists/Tabs/NewForm.aspx?toolpaneview=2
/Lists/Tabs/DispForm.aspx?ID=1&toolpaneview=2
/Lists/Tabs/EditForm.aspx?ID=1&toolpaneview=2

For SharePoint 2010

IMG

Add this code block to the CEWP:

<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js"></script>
<script type="text/javascript" src="/test/English/Javascript/Tabs/TabsForSharePointForms.js"></script>
<script type="text/javascript">

var tabConstructor = {tabs:[{name:'First Tab',fields:['InMultipleTabs','Column1','Column2'],mouseOver:'This is the first tab',tabStyle:'',clickFunction:''},
							{name:'Second Tab',fields:['InMultipleTabs','Column3','Column4','Lookup1','MyMultiLookup'],mouseOver:'This is the second tab',tabStyle:'',clickFunction:'secondTabClick(this)'},
							{name:'Third Tab',fields:['InMultipleTabs','Title'],mouseOver:'This is the third tab',tabStyle:'',clickFunction:''},
							{name:'Forth Tab',fields:['Column5','Column6','MyPeoplePicker'],mouseOver:'This is the forth tab',tabStyle:'',clickFunction:''}],
					  settings:{viewAllFields:{show:true,name:'All fields',mouseOver:'This tab shows all fields',tabStyle:'',clickFunction:''},
					  orphanFields:{show:true,name:'...',mouseOver:'All orphan fields',tabStyle:'',clickFunction:''},
					  breakTabRowAt:null,
					  baseTabColor:'#F5F5F5',
					  hoverTabColor:'#FFF68F',
					  selectedTabColor:'#B9D3EE',
					  formBgColor:'#C6E2FF'},
					  clickFunctionShared:'clickFunctionShared(this)'};

function clickFunctionShared(elm){
	var tab = $(elm);
	// This code is run on click on any tab
}

function secondTabClick(elm){
	var tab = $(elm);
	var arrOfFields = tab.attr('fields').split(',');
	alert("The fields included in the second tab is these:n"+arrOfFields);
}

init_buildTabbedForm(tabConstructor);
</script>

This is explained in detail below.
You must change the “src” to “TabsForSharePointForms.js” to match your local file. If you like to use a local instance of jQuery, change that as well.

You must also change this example to match your columns FieldInternalName.

The call to the function “init_buildTabbedForm” takes two parameters:
tabConstructor: The object constructed in “var tabConstructor”.
selectedTab: Integer that specifies which tab to preselect.

Variable “tabConstructor” explained:

IMG

New in v2.4:

baseTabColor: Set the default background color for the tabs. See CEWP code for example.

Attachments

I have changed the attachment handling in v2.2. Now attachments are left untouched and they will display at the bottom of all tabs. If there are no attachments, the field is hidden.

How to find the FieldInternalName

Go to your list. Open one existing list element in DispForm.aspx. Right click and select “View source”. Search for “FieldInternalName”. All fields should be found in this format:
IMG

Link directly to a tab:

Specify the tab to preselect in the URL like this:
http://*************/Lists/Tabs/NewForm.aspx?sTab=3

Note:

This is true only for unmodified forms. If you have modified the form in SharePoint designer, you will have to look at the function “init_fields_v2()” in the code to adapt it to your custom form. You will find a bit more information here.

Overriding native SharePoint functions

To overcome some issues with rich text fields I had to override one function: RTE_OnFocus.
I have added one line to the bottom of the function:
g_elemRTELastTextAreaConverted=document.getElementById(strBaseElementID);

To catch “empty field validation” on date and time columns “pre save”, I had to override the function “PreSaveItem”. I have added one line to the top of the function:
preSaveHighlightTabOnValidation();

This will not interfere with the use of the function “PreSaveAction” often used to “do stuff” before save.

Finale notes

The solution is licensed under the MIT X11 license. You find the license agreement by clicking the little (c) to the right of the tabs.

I have set the initial release to v2.0 as I have previously posted a similar solution.

Ask if anything is unclear
Alexander

Convert a standard SharePoint lookup column to a full blown cross site lookup using javascript only

I have updated the tool described in this article with some new functionality.

The functionality i will describe here is the ability to convert a standard SharePoint lookup column to a cross site lookup column using javascript/jquery only!

Download the script from the above referred article. Create a Lookup column in your list and have it point to the actual list it is created from (it is in fact not relevant what list you point it towards). Load the script from the above described article and select your list:

Images

IMG


Select the list
IMG


Modify the web and list association and hit “Save”:
IMG

NOTE: The web selector is only available for site collection administrators.

If you are a non site collection administrator, you may change the list association, but not the web association.

This method requires NO modification to the field schema and is fully compatible with Data sheet view etc.

I have not had the chance to test it in SharePoint 2010 yet, but i can see no reason why it should not work.

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

Numbers only in single line text field

18.06.2010 – small update to set “lengthOfInputNumber” relative to the array of FieldInternalnames.

By request from Larry, here is a solution that restricts input in a single line text field to number only.

Note: It is treated as text in SharePoint and you cannot sum or average in a list view.

Add this code to a CEWP below the list form in your NewForm or EditForm:

<script type="text/javascript" src="/test/English/Javascript/jquery-1.4.2.min.js"></script>
<script type="text/javascript">
fields = init_fields_v2();

// Allow numbers only in text fields
// Array of FieldInternalNames to lilmit to numbers only
var arrToCheckForNum = ['Title','Num'];
// Array of length of input string - set to 255 if you do not want to limit input length. Corresponds to the same array index in the "arrToCheckForNum"
var lengthOfInputNumber = [9,2];

$.each(arrToCheckForNum,function(idx,item){
$(fields[item]).find('input').css({'width':'75px'});
	$(fields[item]).find('input').keyup(function(e){
		var thisVal = $(this).val();
		thisVal = thisVal.substring(0,lengthOfInputNumber[idx]);
		$(this).val(thisVal.replace(/[^0-9]/g,''));
	}).blur(function(){
		var thisVal = $(this).val();
		thisVal = thisVal.substring(0,lengthOfInputNumber[idx]);
		$(this).val(thisVal.replace(/[^0-9]/g,''));
	});
});

/*
  LastMod: 07.05.2010
*/
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>

The parameters “arrToCheckForNum” and “lengthOfInputNumber” must be adapted to suite your needs.

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

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:

<script type="text/javascript" src="/test/English/Javascript/jquery-1.4.2.min.js"></script>
<script type="text/javascript" src="/test/English/Javascript/spjs_CascadingDropDowns_v2.js"></script>
<script type="text/javascript">
   // 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}','<select>',5,true,false);
</script>

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

Get or Set value for SharePoint field in NewForm, EditForm and DispForm (Get only in DispForm)

Change log
August 19. 2013
Updated to v1.17 of spjs-utility.js


21.03.2011 Fixed a bug in setFieldValue on “over 20 items single lookup”.


14.06.2010 Updated the function “getFieldvalue” to fix a bug when returning the value for an enhanced rich text column on page load. Thanks to Kat for finding the bug.


This article describes how to get or set the value for all standard SharePoint field types in in NewForm, EditForm and DispForm (Get only in DispForm). This solution is tested in IE8, Firefox 3.6.3.

Instructions for getFieldValue

The function “getFieldValue” takes four arguments:

  • fin: FieldInternalName of the field to set the value for.
  • dispform: true if used in DispForm. Defaults to false if omitted.
  • multiValueJoinBy: String to insert as separator between multiple returned values. If omitted, separated by a comma.
  • optionalFilter: Used for “SPFieldUser” and “SPFieldUserMulti” only. If set to “displayName” or omitted, returns the displayName for the user(s), if set to “loginName”, returns the loginName for the user(s).

getFieldValue – example code in CEWP placed below the form:

<script type="text/javascript" src="../../Javascript/jquery-1.4.2.min.js"></script>
<script type="text/javascript" src="../../Javascript/spjs-utility.js"></script>
<script type="text/javascript">
fields = init_fields_v2();
// Get the loginName from a people picker
var myPickerVal = getFieldValue('MyPeoplePicker','','; ','loginName');
alert(myPickerVal);
// Get value from a multiline textfield
var myRichTextValue = getFieldValue('MultiLineRich');
alert(myRichTextValue);
</script>

Instructions for setFieldValue

The function “setFieldValue” takes three arguments:

  • fin: FieldInternalName of the field to set the value for.
  • newVal: the new value.
  • onLoad: true or false to indicate whether the value is set on page load. Default value if omitted is true.

To set the value you specify the new value in the parameter “newVal”. The following fieldTypes require some extra formatting on the parameter “newVal”:

  • SPFieldMultiChoice: “newVal” is a array containing the values to select.
  • SPFieldUserMulti: “newVal” is a string with the names (LoginName, DisplayName or Email-address) separated by a semicolon (;).
  • SPFieldLookupMulti: “newVal” is a array containing the values to preSelect. Note: Setting this field is only supported onLoad.
  • SPFieldBoolean: Set to true by passing 1,”1″, or true in newVal.
  • SPFieldURL: “newVal” is a array containing the URL and the description for the hyperlink.
  • SPFieldDateTime: “newVal” is a array containing the date, the hour (with AM/PM), and the minutes. Specify only the parameters to set (for date only, add only one item to the array).

setFieldValue – example code in CEWP placed below the form:

<script type="text/javascript" src="../../Javascript/jquery-1.4.2.min.js"></script>
<script type="text/javascript" src="../../Javascript/spjs-utility.js"></script>
<script type="text/javascript">
fields = init_fields_v2();
// Set the value for a radio buttons select
setFieldValue('MyRadioButtons','Radio choice nr. 2');
// Set the value for a date and time field
setFieldValue('MyDateTime',['5/28/2010','9 AM','25']);
</script>

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. If you download another version, please be sure to update the script “src”.

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

Sourcecode for “spjs-Utility.js”:
Download here

Save as “spjs-utility.js”, mind the file extension, and upload to the scriptlibrary as shown above.

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

Get field value for all SharePoint FieldTypes or set field as read only in EditForm

16.10.2010 The function getFieldValue is posted in another – more updated – version here.

29.04.2010 Updated the code for the file “GetFieldValueOrSetAsReadonly.js” to support “SPFieldUserMulti” and for getting the field value in DispForm.


I have had several requests for a solution for setting fields as read only in EditForm. I have created this script to achieve this.

This script enables you to get the field value for any SharePoint field type in EditForm, and to set the field as read only by grabbing it’s value, hiding the <TD>, and adding a clean <TD> with the value in it’s place.

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. If you use another version, please update the reference in the code.

Read here how to add a CEWP to EditForm, and how to get the FieldInternalNames for your fields.

Add this code to a CEWP below the EditForm:

&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/GetFieldValueOrSetAsReadonly.js&quot;&gt;&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot;&gt;
// Array of FieldInternalNames to make readonly
var arrToMakeReadOnly = ['Title','MySelect','MyPeoplePicker','Lookup','Bool','Hyperlink','DateTime','Multiline'];

// The function call must be wrapped in the &quot;$(document).ready&quot; to work with complex field types
$(document).ready(function(){
	readOnlyFieldArray(arrToMakeReadOnly);
});
&lt;/script&gt;

The above code sets all fields in the array “arrToMakeReadOnly” as readonly. To simply get a fields value, do it like this:

&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/GetFieldValueOrSetAsReadonly.js&quot;&gt;&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot;&gt;

// The function call must be wrapped in the &quot;$(document).ready&quot; to work with complex field types
$(document).ready(function(){
	var myValue = getFieldValue(&quot;Insert the FieldInternalName of your field here&quot;);
});
&lt;/script&gt;

To get a fields value in DispForm, do it like this:

&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/GetFieldValueOrSetAsReadonly.js&quot;&gt;&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot;&gt;

	var myValue = getFieldValue(&quot;Insert the FieldInternalName of your field here&quot;,&quot;disp&quot;);

&lt;/script&gt;

The sourcecode for the file “GetFieldValueOrSetAsReadonly.js”:

/* Get field value for all field types, or set as readonly in EditForm 
 * ---------------------------------------------
 * Created by Alexander Bautz
 * alexander.bautz@gmail.com
 * https://spjsblog.com
 * v1.1
 * LastMod: 29.04.2010
 * LastChange: Supporting &quot;SPFieldUserMulti&quot; and for getting the field value in DispForm
 * ---------------------------------------------
 * Include reference to jquery - http://jquery.com
 * ---------------------------------------------
 * Call from a CEWP below the list form in EditForm like this:
	&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/readOnlyForSharepointFields.js&quot;&gt;&lt;/script&gt;
	&lt;script type=&quot;text/javascript&quot;&gt;
	// Array of FieldInternalNames to make readonly
	var arrToMakeReadOnly = ['Title','MySelect','MyPeoplePicker','Lookup','Bool','Hyperlink','DateTime','Multiline'];
	
	// The function call must be wrapped in the &quot;$(document).ready&quot; to work with complex field types
	$(document).ready(function(){
		redOnlyField(arrToMakeReadOnly);
	});
	&lt;/script&gt;
*/

function readOnlyFieldArray(arrayOfFieldInternalNames){
	$.each(arrayOfFieldInternalNames,function(i,fin){
		var fieldValue = getFieldValue(fin);
		if(!fieldValue)return false;
		thisField=$(fields[fin]);
		// Strip off any &quot;formvalidation star&quot;		
		thisField.find('.ms-formlabel span.ms-formvalidation').remove();
		// Set as &quot;readOnly&quot;
		thisField.find('td.ms-formbody').hide().after(&quot;&lt;td class='ms-formbody' style='width:450px'&gt;&quot;+fieldValue+&quot;&lt;/td&gt;&quot;);
	});
}

function getFieldValue(fin,edit_OR_disp){
// If not already done - init all fields
if(typeof(fields)=='undefined')fields = init_fields();
// Return if FieldInternalName is not found
if(fields[fin]==undefined)return;
var thisField = $(fields[fin]);
// If &quot;edit_OR_disp&quot; is undefined, default to &quot;edit&quot;
if(edit_OR_disp==undefined)edit_OR_disp='edit';
	if(edit_OR_disp=='disp'){ // If &quot;disp&quot;
		var valRaw = $(fields[fin]).find('.ms-formbody').text();
		return (valRaw.replace(/[ xA0]+$/,'')=='')?'':valRaw.replace(/[ xA0]+$/,'');
	}else{ // If &quot;edit&quot;		
		var fieldType = $(fields[fin]).attr('FieldType');
		if(fieldType==undefined){
			alert(&quot;The attribute &quot;FieldType&quot; is missing.nEnsure the function init_fields() used is the one included in the file &quot;GetFieldValueOrSetAsReadonly.js&quot;.&quot;);
			return false;
		}
		returnVal = '';		
		switch(fieldType){
			case 'SPFieldText':
			case 'SPFieldNumber':
			case 'SPFieldCurrency':
				returnVal = thisField.find('input').val();
			break;
			case 'SPFieldChoice':
				if(thisField.find('input:radio').length&gt;0){
					returnVal = thisField.find('input:radio:checked').next().text();
				}else{
					returnVal = thisField.find('select').val();
				}
			break;
			case 'SPFieldMultiChoice':
				var multiChoice = [];
				thisField.find('input:checkbox:checked').each(function(i,opt){
					opt = $(opt);
					multiChoice.push(opt.next().text());
				});
				returnVal = multiChoice.join('&lt;br /&gt;');
			break;
			case 'SPFieldUser':
				var myPeoplePicker = thisField.find(&quot;div[id='divEntityData']&quot;);
				returnVal = myPeoplePicker.attr('displaytext');
				returnVal = (returnVal!=undefined)?returnVal:'';
			break;
			case 'SPFieldUserMulti':
				var userMulti = [];
				thisField.find(&quot;div[id='divEntityData']&quot;).each(function(i,div){
					thisVal = $(div).attr('displaytext');
					if(thisVal!=undefined){
						userMulti.push(thisVal);
					}				
				});
				returnVal = userMulti.join('&lt;br /&gt;');
			break;
			case 'SPFieldLookup':
				if(thisField.find('select').length&gt;0){
					returnVal = thisField.find('select option:selected').text();
				}else{
					returnVal = thisField.find('input').val();
				}
			break;
			case 'SPFieldLookupMulti':
				var lookupMulti = [];
				thisField.find(&quot;select:last option&quot;).each(function(i,opt){
					opt = $(opt);
					lookupMulti.push(opt.text());
				});
				returnVal = lookupMulti.join('&lt;br /&gt;');
			break;
			case 'SPFieldBoolean':			
				returnVal = (thisField.find('input').attr('checked')==true)?true:false;
			break;
			case 'SPFieldURL':
				var link = thisField.find('input:first').val();
				var descr = thisField.find('input:last').val();
				returnVal = &quot;&lt;a href='&quot;+link+&quot;'&gt;&quot;+descr+&quot;&lt;/a&gt;&quot;;
			break;
			case 'SPFieldDateTime':
				var date = thisField.find('input:first').val();
				var hour = thisField.find('select:first option:selected').val()
					hour = (hour==null)?'':hour.match(/^[d]+/)+&quot;:&quot;;
				var AMPM = thisField.find('select:first option:selected').val()
					AMPM = (AMPM==null)?'':AMPM.match(/AM|PM/);
				var minutes = thisField.find('select:last option:selected').val();
					minutes = (minutes==null)?'':minutes;
				returnVal = date+&quot; &quot;+hour+minutes+&quot; &quot;+AMPM;
			break;
			case 'SPFieldNote':
				returnVal = thisField.find('textarea:first').val();
			break;
			case 'customHeading':
				returnVal = '';
			break;
			default:			
			returnVal = &quot;Unknown fieldType: &lt;strong&gt;&quot;+fieldType+&quot;&lt;/strong&gt;, please check the script.&quot;;
		}
		if(returnVal==='')returnVal=&quot;&amp;nbsp;&quot;;
		return returnVal;
	}		
}

function init_fields(){
	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]).attr('FieldDispName',disp);
			$(res[fin]).attr('FieldType',type);
		}		
	});
	return res;
}

Save as “GetFieldValueOrSetAsReadonly.js”, mind the file extension, and upload to the scriptlibrary as shown above.

Note!
The function init_fields() used in this code is the new one posted here: Revised function init_fields()

It has additional functionality not found in previous versions. Be sure to update the function if adding this to existing code.

Ask if anything is unclear

Regards
Alexander