Display template with jqueryui Accordion widget

Ok.  This is driving me crazy. I've googled and as much as I've found about jquery and jquery ui in sharepoint. I can't find the one thing that pertains to me.  So here we go. maybe the masses can help. I want to implement the jquery UI plug in on a list.  I want to show the title and description.  I'm using the default List and "two line" item templates for my base.  my problem is the Accordion function is only applying to the first item on my list.  Everything else is styling normally.

Here's my item template.

<html xmlns:mso="urn:schemas-microsoft-com:office:office" xmlns:msdt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882"> 
<head>
<title>Burke Accordion</title>

<!--[if gte mso 9]><xml>
<mso:CustomDocumentProperties>
<mso:TemplateHidden msdt:dt="string">0</mso:TemplateHidden>
<mso:ManagedPropertyMapping msdt:dt="string">'Link URL'{Link URL}:'Path','Line 1'{Line 1}:'Title','Line 2'{Line 2}:'BurkeBenefitDescription'</mso:ManagedPropertyMapping>
<mso:MasterPageDescription msdt:dt="string">This Item Display Template will show a small thumbnail icon next to a hyperlink of the item title, with an additional line that is available for a custom managed property.</mso:MasterPageDescription>
<mso:ContentTypeId msdt:dt="string">0x0101002039C03B61C64EC4A04F5361F385106603</mso:ContentTypeId>
<mso:TargetControlType msdt:dt="string">;#Content Web Parts;#</mso:TargetControlType>
<mso:HtmlDesignAssociated msdt:dt="string">1</mso:HtmlDesignAssociated>
</mso:CustomDocumentProperties>
</xml><![endif]-->
</head>

<body>

    <!--
            Warning: Do not try to add HTML to this section. Only the contents of the first <div>
            inside the <body> tag will be used while executing Display Template code. Any HTML that
            you add to this section will NOT become part of your Display Template.
    -->
    <script>
        $includeLanguageScript(this.url, "~sitecollection/_catalogs/masterpage/Display Templates/Language Files/{Locale}/CustomStrings.js");
		$includeLanguageScript(this.url, "https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.2/jquery-ui.min.js");
		$includeCSS(this.url, "https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.2/themes/redmond/jquery-ui.css");
    </script>




    <!--
        Use the div below to author your Display Template. Here are some things to keep in mind:
        * Surround any JavaScript logic as shown below using a "pound underscore" (#_ ... _#) token
        inside a comment.

        * Use the values assigned to your variables using an "underscore pound equals"
        (_#= ... =#_) token.
    -->

    <div id="TwoLines">
<!--#_
var encodedId = $htmlEncode(ctx.ClientControl.get_nextUniqueId() + "_2lines_");

var linkURL = $getItemValue(ctx, "Link URL");
linkURL.overrideValueRenderer($urlHtmlEncode);
var iconURL = Srch.ContentBySearch.getIconSourceFromItem(ctx.CurrentItem);

var line1 = $getItemValue(ctx, "Line 1");
var line2 = $getItemValue(ctx, "Line 2");
line1.overrideValueRenderer($contentLineText);
line2.overrideValueRenderer($contentLineText);

var containerId = encodedId + "container";
var pictureLinkId = encodedId + "pictureLink";
var pictureId = encodedId + "picture";
var dataContainerId = encodedId + "dataContainer";
var line1LinkId = encodedId + "line1Link";
var line1Id = encodedId + "line1";
var line2Id = encodedId + "line2";
_#-->
<!--#_
		ctx.OnPostRender = [];

		ctx.OnPostRender.push(ctx, function() {
		    $( "#accordion" ).accordion({
				collapsible: true
			});
		});
_#-->
<!--#_
	
_#-->
		
        <div id="accordion">
            <h3><a title="_#= $htmlEncode(line1.defaultValueRenderer(line1)) =#_" id="_#= line1LinkId =#_">_#= line1 =#_</a></h3>
            
                
<!--#_
if(!line2.isEmpty)
{
_#-->
                <div title="_#= $htmlEncode(line2.defaultValueRenderer(line2)) =#_" id="_#= line2Id =#_">_#= line2 =#_</div>
<!--#_
}
_#-->
                
        </div>
    </div>
</body>
</html>

January 24th, 2015 8:28pm

Unless i'm missing someothing all the items going to be tagged with the it accordion, which means that each time an item is rendered the javascript will find the first accordian object and re-attach the same action.

Create a 'this item' ID variable and then use that in both the Jquery accordion section and in the div id.

Free Windows Admin Tool Kit Click here and download it now
January 24th, 2015 9:05pm

<div id="TwoLines">
<!--#_
var encodedId = $htmlEncode(ctx.ClientControl.get_nextUniqueId() + "_2lines_");

var linkURL = $getItemValue(ctx, "Link URL");
linkURL.overrideValueRenderer($urlHtmlEncode);
var iconURL = Srch.ContentBySearch.getIconSourceFromItem(ctx.CurrentItem);

var line1 = $getItemValue(ctx, "Line 1");
var line2 = $getItemValue(ctx, "Line 2");
line1.overrideValueRenderer($contentLineText);
line2.overrideValueRenderer($contentLineText);

var containerId = encodedId + "container";
var pictureLinkId = encodedId + "pictureLink";
var pictureId = encodedId + "picture";
var dataContainerId = encodedId + "dataContainer";
var line1LinkId = encodedId + "line1Link";
var line1Id = encodedId + "line1";
var line2Id = encodedId + "line2";
_#-->
<!--#_
		ctx.OnPostRender = [];

		ctx.OnPostRender.push(ctx, function() {
		    $( "#accordion" ).accordion({
				collapsible: true
			});
		});
_#-->
<!--#_
	
_#-->
	<div id="containerID">	
        <div id="accordion">
            <h3><a title="_#= $htmlEncode(line1.defaultValueRenderer(line1)) =#_" id="_#= line1LinkId =#_">_#= line1 =#_</a></h3>
            
                
<!--#_
if(!line2.isEmpty)
{
_#-->
                <div title="_#= $htmlEncode(line2.defaultValueRenderer(line2)) =#_" id="_#= line2Id =#_">_#= line2 =#_</div>
<!--#_
}
_#-->
                
        </div>
       </div>
    </div>

Are you talking about something like this? I used the ContainerID Variable in a DIV tag around accordion.

January 26th, 2015 2:32pm

Not quite. If you had four items your code at present will create them like this:

<div id="containerID">	
   <div id="accordion">
      <h3><a ...</a></h3>
</div>
<div id="containerID">	
   <div id="accordion">
      <h3><a ...</a></h3>
</div>
<div id="containerID">	
   <div id="accordion">
      <h3><a ...</a></h3>
</div>
<div id="containerID">	
   <div id="accordion">
      <h3><a ...</a></h3>
</div>

When your function looks for the object 'ContainerID' or 'accordion' it's going to find only one of those items as the id field must/should be unique. As the HTML standard assumes this is true it is probably just grabbing the first of those elements and returning that instead of attaching it to all the items as you want.

You'll either need to change the way you target things to hit a class or you'll have to assign unique IDs to the divs are they are built and reference those in your JQuery.

// valid way to handle it
<div class="accordion">
<a><h3>....</h3></a>
</div>
<div class="accordion">
<a><h3>....</h3></a>
</div>
<div class="accordion">
<a><h3>....</h3></a>
</div>

// or assign valid IDs and target them
<div id="accordion_1">
<a><h3>....</h3></a>
</div>
<div class="accordion_2">
<a><h3>....</h3></a>
</div>
<div class="accordion_3">
<a><h3>....</h3></a>
</div>

Free Windows Admin Tool Kit Click here and download it now
January 26th, 2015 2:47pm

Ok.  So here's the problem.  I tried changing the accordion to class but that screws with the jqueryui since it is specifically looking for the DIV with the id="accordion"
January 26th, 2015 4:08pm

It's only looking for it in one place.

Have a look at the HTML you're generating and compare it to the code in the example: https://jqueryui.com/accordion/

You need to output a top level div to hold the divs beneath.

<div id='accordian'>
  <h3>Blah</h3>
  <div>..</div>
  <h3>Blah</h3>
  <div>..</div>
  <h3>Blah</h3>
  <div>..</div>
  <h3>Blah</h3>
  <div>..</div>
</div>

You are creating this

<div id='accordian'>
  <h3>Blah</h3>
  <div>..</div>
</div>
<div id='accordian'>
  <h3>Blah</h3>
  <div>..</div>
</div>
<div id='accordian'>
  <h3>Blah</h3>
  <div>..</div>
</div>
<div id='accordian'>
  <h3>Blah</h3>
  <div>..</div>
</div>

Add a <div id="accordion"> (note i have a typo in my code blocks) in the header and a </div> in the footer
Free Windows Admin Tool Kit Click here and download it now
January 26th, 2015 4:19pm

Ok.  I'm just dense so I know I can do that manually but it's going to break if they add a new item to the list.  I need that accordion div to apply to the next unique id.  I've deleted my original code and for now I'm using the default List control and Two Line item.  I'm moved on to a page layout issue now.
January 27th, 2015 4:17pm

Hi Steaven,

Create your own template for implement the same functionality. 

1. control template

2. Item template

Accordion div in control template and JavaScript in this file. It should work.

Let  me know if you face any issue.

Regards,

Basant Pandey

http://sharepointfordeveloper.blogspot.com


Free Windows Admin Tool Kit Click here and download it now
January 27th, 2015 5:30pm

In your display template you can override the header and footer. In the header you would open a div, give it the accordion ID value, then in the footer you would close that div.

That'll cover the bit that tells the Accordion jQuery UI tool to make all the sub elements behave appropriately.

There might be a prettier way to do it but it does work.

January 28th, 2015 1:07pm

Wendy,

Can I see an example of what you are talking about?

Free Windows Admin Tool Kit Click here and download it now
February 20th, 2015 3:24pm

This topic is archived. No further replies will be accepted.

Other recent topics Other recent topics