Category Archives: Accordion

Accordion for SharePoint forms v2.0

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

The CEWP code must be updated from v2.0 to include the new parameters.


This solution is used to break up a SharePoint form into sections – like in an accordion.
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 section
  • You can have a section displaying all fields
  • You can have a section catching all orphans (fields that are not displayed in any other section). Useful if one adds columns to a list without updating the script call.
  • Highlights section if a field fails validation upon save
  • Use a URL query string parameter to expand a specific section

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 “AccordionForSharePointForms.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/Accordion/NewForm.aspx?toolpaneview=2
/Lists/Accordion/DispForm.aspx?ID=1&toolpaneview=2
/Lists/Accordion/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/Accordion/v2.0/AccordionForSharePointForms.js"></script>
<script type="text/javascript">

var accConstructor = {sections:[{name:'First section',fields:['InMultipleSections','Column1','Column2'],mouseOver:'This is the first section',sectionStyle:'',clickFunction:''},
							{name:'Second section',fields:['InMultipleSections','Column3','Column4','Lookup1','MyMultiLookup'],mouseOver:'This is the second section',sectionStyle:'',clickFunction:'secondSectionClick(this)'},
							{name:'Third section',fields:['InMultipleSections','Title'],mouseOver:'This is the third section',sectionStyle:'',clickFunction:''},
							{name:'Forth section',fields:['Column5','Column6','MyPeoplePicker'],mouseOver:'This is the forth section',sectionStyle:'',clickFunction:''},
							{name:'Attachments',fields:['attachments'],mouseOver:'',sectionStyle:'',clickFunction:''}],
					  settings:{viewAllFields:{show:true,position:'bottom',name:'All fields',mouseOver:'This section shows all fields',sectionStyle:'',clickFunction:''},
					  orphanFields:{show:true,name:'Orphans',mouseOver:'All orphan fields',sectionStyle:'',clickFunction:''},
					  bgColor:'#8EB4E8',
					  hoverColor:'#FFF68F',
					  selectedColor:'#C6E2FF',
					  formBgColor:'#C6E2FF'},
					  clickFunctionShared:'clickFunctionShared(this)'};

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

function secondSectionClick(elm){
	var acc = $(elm);
	var arrOfFields = acc.attr('fields').split(',');
	alert("The fields included in the second section is these:n"+arrOfFields);
}
				  
init_buildAccordionForm(accConstructor,'1');
</script>

This is explained in detail below.
You must change the “src” to “AccordionForSharePointForms.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_buildAccordionForm” takes two parameters:
accConstructor: The object constructed in “var accConstructor”.
selectedAcc: Integer that specifies which section to preselect.

Variable “accConstructor” explained:

IMG

Attachments

I have added the attachment row as a “field” you can insert in a selected section. It is named “attachments”. Look at the example CEWP code and the image.

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

Specify the section to preselect in the URL like this:
http://*************/Lists/Accordion/NewForm.aspx?sAcc=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:
preSaveHighlightAccOnValidation();

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 left of the lower button row.

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

Ask if anything is unclear
Alexander

SharePoint form – Accordion in Tabs

This is a draft/example to keep Steve busy over the weekend 🙂 (see his request here).

To get anything out of this code, you have to read the following articles: Tabs in SharePoint form and Accordion in SharePoint form


Here is the code:

<!-- Date field text size -->
<style type="text/css">
.ms-dtinput,.ms-dttimeinput{
	font-size:0.7em;
}
</style>
<DIV id="tabs">
	<UL style="font-size:12px">
		<LI><A href="#tabs-1">Tab 1</A></LI>
		<LI><A href="#tabs-2">Tab 2</A></LI>
		<LI><A href="#tabs-3">Tab 3</A></LI>
	</UL>

	<div id="tabs-1">	
		<div id="accordion-1">	
			<H3><A href="#accordion-0">Tab 1 Accordion 1</A></H3>
			<div><table width="100%" id="accTable-0"></table> </div>
			<H3><A href="#accordion-1">Tab 1 Accordion 2</A></H3>
			<div><table width="100%" id="accTable-1"></table> </div>
			<H3><A href="#accordion-2">Tab 1 Accordion 3</A></H3>
			<div><table width="100%" id="accTable-2"></table> </div>	
		</div>	
	</div>
	<div id="tabs-2">
		<div id="accordion-2">	
			<H3><A href="#accordion-3">Tab 2 Accordion 1</A></H3>
			<div><table width="100%" id="accTable-3"></table> </div>
			<H3><A href="#accordion-4">Tab 2 Accordion 2</A></H3>
			<div><table width="100%" id="accTable-4"></table> </div>
			<H3><A href="#accordion-5">Tab 2 Accordion 3</A></H3>
			<div><table width="100%" id="accTable-5"></table> </div>	
		</div>
	</div>
	<div id="tabs-3">
		<div id="accordion-3">	
			<H3><A href="#accordion-6">Tab 3 Accordion 1</A></H3>
			<div><table width="100%" id="accTable-6"></table> </div>
			<H3><A href="#accordion-7">Tab 3 Accordion 2</A></H3>
			<div><table width="100%" id="accTable-7"></table> </div>
			<H3><A href="#accordion-8">Tab 3 Accordion 3</A></H3>
			<div><table width="100%" id="accTable-8"></table> </div>	
		</div>
	</div>
</DIV>

<link type="text/css" href="/test/English/Javascript/jQueryUI/jquery-ui-1.7.2.custom.css" rel="stylesheet" />
<script type="text/javascript" src="/test/English/Javascript/jquery-1.3.2.min.js"></script>
<script type="text/javascript" src="/test/English/Javascript/jQueryUI/jquery-ui-1.7.2.custom.min.js"></script>
<script type="text/javascript">
// Array of all fields - format: accordionID|FieldInternalName
arrTabAccordion = ['0|Title','0|Dummyfield1','0|Dummyfield2',
			'1|Dummyfield3','1|Dummyfield4','1|Dummyfield5',
			'2|Dummyfield6','2|Dummyfield7','2|Dummyfield8',
			'3|Dummyfield9','3|Dummyfield10','3|Dummyfield11',
			'4|Dummyfield12','4|Dummyfield13','4|Dummyfield14',
			'5|Dummyfield15','5|Dummyfield16','5|Dummyfield17',
			'6|Dummyfield18','6|Dummyfield19','6|Dummyfield20',
			'7|Dummyfield21','7|Dummyfield22','7|Dummyfield23',
			'8|Dummyfield24','8|Dummyfield25','8|Dummyfield26'];

// Initiate all the fields
fields = init_fields();

// Add the "tabs" to the formtable
$("#tabs").insertAfter('.ms-formtable').tabs();
// Add accordion
$("#accordion-1").accordion({autoHeight: false,animated: false});
$("#accordion-2").accordion({autoHeight: false,animated: false});
$("#accordion-3").accordion({autoHeight: false,animated: false});

// Loop trough all fields and move them to the right accordion section
$.each(arrTabAccordion,function(idx,item){
	var split = item.split('|');
	var accID = split[0];
	var fieldName = split[1];
	if(fields[fieldName]!=undefined){
		currField = $(fields[fieldName]);
		currField.appendTo('#accTable-'+accID);
	}
});

// Fix IE8 issue with zoom
$(".ui-accordion-content").css({'zoom':1,'padding':'0px'});

// function - to make "object" of all tr's in the form
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;
}
</script>

This is the same code, but added two fields to tab-2, outside the accordion:

<!-- Date field text size -->
<style type="text/css">
.ms-dtinput,.ms-dttimeinput{
	font-size:0.7em;
}
</style>
<DIV id="tabs">
	<UL style="font-size:12px">
		<LI><A href="#tabs-1">Tab 1</A></LI>
		<LI><A href="#tabs-2">Tab 2</A></LI>
		<LI><A href="#tabs-3">Tab 3</A></LI>
	</UL>

	<div id="tabs-1">	
		<div id="accordion-1">	
			<H3><A href="#accordion-0">Tab 1 Accordion 1</A></H3>
			<div><table width="100%" id="accTable-0"></table> </div>
			<H3><A href="#accordion-1">Tab 1 Accordion 2</A></H3>
			<div><table width="100%" id="accTable-1"></table> </div>
			<H3><A href="#accordion-2">Tab 1 Accordion 3</A></H3>
			<div><table width="100%" id="accTable-2"></table> </div>	
		</div>	
	</div>
	<div id="tabs-2">
	<table cellpadding="0" cellspacing="0" id="tabs-2-table"></table>
		<div id="accordion-2">	
			<H3><A href="#accordion-3">Tab 2 Accordion 1</A></H3>
			<div><table width="100%" id="accTable-3"></table> </div>
			<H3><A href="#accordion-4">Tab 2 Accordion 2</A></H3>
			<div><table width="100%" id="accTable-4"></table> </div>
			<H3><A href="#accordion-5">Tab 2 Accordion 3</A></H3>
			<div><table width="100%" id="accTable-5"></table> </div>	
		</div>
	</div>
	<div id="tabs-3">
		<div id="accordion-3">	
			<H3><A href="#accordion-6">Tab 3 Accordion 1</A></H3>
			<div><table width="100%" id="accTable-6"></table> </div>
			<H3><A href="#accordion-7">Tab 3 Accordion 2</A></H3>
			<div><table width="100%" id="accTable-7"></table> </div>
			<H3><A href="#accordion-8">Tab 3 Accordion 3</A></H3>
			<div><table width="100%" id="accTable-8"></table> </div>	
		</div>
	</div>
</DIV>

<link type="text/css" href="/test/English/Javascript/jQueryUI/jquery-ui-1.7.2.custom.css" rel="stylesheet" />
<script type="text/javascript" src="/test/English/Javascript/jquery-1.3.2.min.js"></script>
<script type="text/javascript" src="/test/English/Javascript/jQueryUI/jquery-ui-1.7.2.custom.min.js"></script>
<script type="text/javascript">
// Array of all fields - format: accordionID|FieldInternalName
arrTabAccordion = ['0|Title','0|Dummyfield1','0|Dummyfield2',
			'1|Dummyfield3','1|Dummyfield4','1|Dummyfield5',
			'2|Dummyfield6','2|Dummyfield7','2|Dummyfield8',
			'3|Dummyfield9','3|Dummyfield10','3|Dummyfield11',
			'4|Dummyfield12','4|Dummyfield13','4|Dummyfield14',
			'5|Dummyfield15','5|Dummyfield16','5|Dummyfield17',
			'6|Dummyfield18','6|Dummyfield19','6|Dummyfield20',
			'7|Dummyfield21','7|Dummyfield22','7|Dummyfield23',
			'8|Dummyfield24','8|Dummyfield25','8|Dummyfield26'];

arrTab = ['1|FieldInTab1','1|FieldInTab2'];

// Initiate all the fields
fields = init_fields();

// Add the "tabs" to the formtable
$("#tabs").insertAfter('.ms-formtable').tabs();
// Add accordion
$("#accordion-1").accordion({autoHeight: false,animated: false,collapsible: true,active: false});
$("#accordion-2").accordion({autoHeight: false,animated: false,collapsible: true,active: false});
$("#accordion-3").accordion({autoHeight: false,animated: false,collapsible: true,active: false});

// Loop trough all fields and move them to the right accordion section
$.each(arrTabAccordion,function(idx,item){
	var split = item.split('|');
	var accID = split[0];
	var fieldName = split[1];
	if(fields[fieldName]!=undefined){
		currField = $(fields[fieldName]);
		currField.appendTo('#accTable-'+accID);
	}
});

// Loop trough all fields and move them to the right tab
$.each(arrTab,function(idx,item){
	var split = item.split('|');
	var tabID = split[0];
	var fieldName = split[1];
	if(fields[fieldName]!=undefined){
		currField = $(fields[fieldName]);
		currField.appendTo('#tabs-2-table');		
	}
});

// Fix IE8 issue with zoom
$(".ui-accordion-content").css({'zoom':1,'padding':'0px'});

// function - to make "object" of all tr's in the form
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;
}
</script>

This example is setup in a custom list with 26 single line text fields (Dummyfield1-26).

I have stripped off everything related to selecting the correct tab or accordion on form validation.

I may update this code later.

Regards
Alexander

Accordion in SharePoint form

12.03.2011: I have posted a new release, you find it here.


In this example i will show how to use the jQuery UI widget “Accordion” in a SharePoint form.

NewForm:
IMG
On form validation (refresh) it selects the first section containing empty fields:
IMG
DispForm with attachment:
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

A folder named “jQueryUI” containing the scripts and the “images”-folder for the selected theme:
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 jQuery UI-library is found here. Find the theme of your choice – mine is “smootness” – and download the files (select the widgets and effects you want – the file is dynamically built according to your selection).

Add a CEWP below your NewForm, DispForm and EditForm.

Add this code:

<DIV id="accordion" style="font-size:14px">	
	<H3><A href="#accordion-0">Section 1</A></H3>
	<div><table width="100%" id="accTable-0"></table> </div>
	<H3><A href="#accordion-1">Section 2</A></H3>
	<div><table width="100%" id="accTable-1"></table> </div>
	<H3><A href="#accordion-2">Section 3</A></H3>
	<div><table width="100%" id="accTable-2"></table> </div>
	<H3><A href="#accordion-3">Attachments</A></H3>
	<div><table width="100%" id="accTable-3"></table> </div>	
</DIV>

<link type="text/css" href="/test/English/Javascript/jQueryUI/jquery-ui-1.7.2.custom.css" rel="stylesheet" />
<script type="text/javascript" src="/test/English/Javascript/jquery-1.3.2.min.js"></script>
<script type="text/javascript" src="/test/English/Javascript/jQueryUI/jquery-ui-1.7.2.custom.min.js"></script>
<script type="text/javascript">

// Array of all fields - format: accID|FieldInternalName
// Note that accID is zero-indexed
arrOfFields = ['0|Title','0|SectionOneText','0|Section1Choice',
		  '1|Responsible','1|Section2Text',
		  '2|Section3Multiline','2|Section3Choice'];

// Initiate all the fields
fields = init_fields();

// Add the "accordion" to the formtable	
$("#accordion").insertAfter('.ms-formtable').accordion({autoHeight: false,animated: false});
// Loop trough all fields and move them to the right accordion section
fValAccID = '';
$.each(arrOfFields,function(idx,item){
	var split = item.split('|');
	var accID = split[0];
	var fieldName = split[1];
	if(fields[fieldName]!=undefined){
		currField = $(fields[fieldName]);
		currField.appendTo('#accTable-'+accID);
		
		// Formvalidation - find the first tab with empty required fields
		if(fValAccID == '' && currField.find('.ms-formbody span.ms-formvalidation').length>0){
			fValAccID = accID;
		}
	}
});

// Move the Attachment's to the last section
$("#idAttachmentsRow").appendTo('#accTable-3');

// Are there any required fields not filled? - select the section containing the first field
if(fValAccID !=''){
	// Show the right section
	setTimeout(function(){$('#accordion').accordion('activate',parseInt(fValAccID));},10);
}

// Fix IE8 issue with content not showing (because it is in a table within the DIV) + remove the default padding
$(".ui-accordion-content").css({'zoom':1,'padding':'0px'});

// function - to make "object" of all tr's in the form
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;
}
</script>

The only parameters you need to edit in the script is the array of FieldInternalNames. The format of the variable “arrOfFields” is accID|FieldInternalName.

In the html above the script, adapt the number’s of sections – and the section’s display name. The accID corresponds with the index of the table to insert the content in (zero-indexed).

All fields must be added to a section – if not it looks ugly….

Note: As for the “Tabs in SharePoint form”, by now i have tested and found that columns of type “Multiple lines of text (Rich text or Enhanced rich text) do not work. What happens is that the section shows some of the fields hidden parts.

I have not done any testing on how to prevent this issue, so feel free to notify me if you find a workaround.

Note: The animation is disabled because of a “flicker problem” in IE8 due to the page being rendered in “Quirks Mode”.

Regards
Alexander