Over the past year, I have been developing websites with Adobe CQ5 as the CMS (Content Management System), including building components, so that content writers can populate the web pages. In some cases, the logical method of creating components did not work; with any CMS, there are limitations or bugs, and part of the 'fun' (if you could call it that) is discovering an alternative solution. This article describes and explains the accordion component development. This component was developed nearly one year ago now, so some of the particulars are not as fresh in my mind.
What The Heck is An Accordion in Web Terms?
For those who do not know, an 'accordion' in web terminology is a design element that can show or hide a panel of content (to save screen space or provide a consistent grouping of similar data), and the user can click onto the panel to expand the minimised view, or to minimise an expanded panel. The screenshot below shows an example of the component, which was the solution I implemented. Obviously, the styling (CSS) and Javascript required is beyond the scope of this. (For those who are interested, the functionality of the interaction is completed using the JQuery Javascript library.)

For setting this component up in CQ5 CMS for the content editors to use, I ideally wanted the content writer to be able to add a panel for each 'accordion' entry, which would consist of a title/subject and body text. The body text needed the ability to be styled, so the custom CQ5 rich text editor needed to be used. This would have been using a compositeField / MultiField component, but a bug was discovered while creating this, and the values did not save correctly. Unfortunately, Adobe CQ5 CMS cannot handle certain data types, even though it was meant to be supported. (Adobe CQ5 CMS does tend to have a lot of "TODO" comments in its code.)
Obviously, I needed to come up with an alternative and user-friendly solution. I read in forums online about using the column component and adapting it, but I wanted it to be more intuitive to the content writers. I'm mainly writing about my experience here as there seems to be many wanting to complete the same task, but the information does not exist.
My Accordion CQ5 Solution Explained
The alternative solution was to develop the accordion and accordion panel components separately, as a parsys, while providing a user-friendly interface to give the content writers direction. Simply, the content writer will drag and drop an accordion component from the Sidekick onto the screen. The accordion component will have a placeholder message to instruct the user to add accordion entries. The user will double-click the accordion component on the screen to add accordion entries. (The accordion entries are simply another component.) The accordion entries component is the only type of component that they will be able to add inside the accordion component parsys; no other components will be allowed to be placed.
What The Heck is An Accordion in Web Terms?
For those who do not know, an 'accordion' in web terminology is a design element that can show or hide a panel of content (to save screen space or provide a consistent grouping of similar data), and the user can click onto the panel to expand the minimised view, or to minimise an expanded panel. The screenshot below shows an example of the component, which was the solution I implemented. Obviously, the styling (CSS) and Javascript required is beyond the scope of this. (For those who are interested, the functionality of the interaction is completed using the JQuery Javascript library.)

For setting this component up in CQ5 CMS for the content editors to use, I ideally wanted the content writer to be able to add a panel for each 'accordion' entry, which would consist of a title/subject and body text. The body text needed the ability to be styled, so the custom CQ5 rich text editor needed to be used. This would have been using a compositeField / MultiField component, but a bug was discovered while creating this, and the values did not save correctly. Unfortunately, Adobe CQ5 CMS cannot handle certain data types, even though it was meant to be supported. (Adobe CQ5 CMS does tend to have a lot of "TODO" comments in its code.)
Obviously, I needed to come up with an alternative and user-friendly solution. I read in forums online about using the column component and adapting it, but I wanted it to be more intuitive to the content writers. I'm mainly writing about my experience here as there seems to be many wanting to complete the same task, but the information does not exist.
My Accordion CQ5 Solution Explained
The alternative solution was to develop the accordion and accordion panel components separately, as a parsys, while providing a user-friendly interface to give the content writers direction. Simply, the content writer will drag and drop an accordion component from the Sidekick onto the screen. The accordion component will have a placeholder message to instruct the user to add accordion entries. The user will double-click the accordion component on the screen to add accordion entries. (The accordion entries are simply another component.) The accordion entries component is the only type of component that they will be able to add inside the accordion component parsys; no other components will be allowed to be placed.
This tutorial shows some of the steps to create an accordion component in Adobe CQ5 CMS. First of all, I will explain the structure of the set-up for the component. A visual representation of the structure is displayed below. As you can see, the accordion is organised into the 'accordion' and 'accordion-entry' (one panel, consisting of a heading and rich text) components.


The 'accordion' Component
The 'Accordion' component is simply the placeholder that encompasses the accordion entries.
_cq_editConfig.xml:
To ensure that the screen updates so that the editor can see the output on the screen, the page in author mode in the CMS needs to be refreshed. The file demonstrates refreshing after creation, after deletion, after insertion, and after moving.
<jcr:root xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0"
cq:dialogMode="floating"
jcr:primaryType="cq:EditConfig">
<cq:listeners
jcr:primaryType="cq:EditListenersConfig"
aftercreate="REFRESH_PAGE"
afterdelete="REFRESH_PAGE"
afterinsert="REFRESH_PAGE"
aftermove="REFRESH_PAGE"/>
</jcr:root>
.content.xml
cq:dialogMode="floating"
jcr:primaryType="cq:EditConfig">
<cq:listeners
jcr:primaryType="cq:EditListenersConfig"
aftercreate="REFRESH_PAGE"
afterdelete="REFRESH_PAGE"
afterinsert="REFRESH_PAGE"
aftermove="REFRESH_PAGE"/>
</jcr:root>
.content.xml
The 'Accordions' .content.xml file specifies that the sling:resourceSuperType is the standard parbase component. This will allow us to drag and drop other components into it. However, we need to ensure that only a specific type of component can be put into that place - the 'accordion-entry'. The settings allowedChildren is set to be an 'accordion-entry' component type, and allowedParents is the parsys.
<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0"
cq:isContainer="{Boolean}true"
jcr:primaryType="cq:Component"
jcr:title="Accordion"
sling:resourceSuperType="foundation/components/parbase"
allowedChildren="[*/accordion-entry]"
allowedParents="[*/parsys]"
componentGroup=".hidden"/>
dialog.xml
When the user drags and drops the 'Accordion' component into place, they have the option to enter a unique ID for the accordion. See the snippet of code below.
<items jcr:primaryType="cq:WidgetCollection">
<title
jcr:primaryType="cq:Widget"
fieldDescription="Leave empty to use the page title."
fieldLabel="Title"
name="./jcr:title"
xtype="textfield"/>
<id
jcr:primaryType="cq:Widget"
fieldDescription="Enter a unique ID for the accordion"
fieldLabel="ID"
name="./id"
xtype="textfield"/>
</items>
accordion.jsp
The following shows the contents of the Accordion JSP and how it is rendered on the page. The resourceType is a parsys, since the content editor will be dragging and dropping the 'according-entries' components into place here.
<c:set var="accordionFlag" scope="request" value="yes"/>
<c:set var="accordionID" scope="request" value="1"/>
<div><cq:include path="entries" resourceType="myproject/components/my-accordion/components/parsys"/></div>
clientlibs folder
This folder holds the Javascript for the accordion. There's some configuirations here, such as defining the client libraries, such as the Javascript/jQuery file that will handle how the accordion should behave. The Javascript file is placed into the 'source' folder underneath the 'clientlibs' folder. Note that the name must match the name in the js.txt file.
- .content.xml:
<jcr:root xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0"
jcr:primaryType="cq:ClientLibraryFolder"
categories="[my.accordion-component]"/> - js.txt:
#base=source
jaccordion.congif.js
The 'accordion-entry' Component
The 'Accordion-entry' component is an actual entry or panel that sits inside the 'Accordion' component. This is a child of the 'Accordion' component.
.content.xml:
The 'accordion-entry' will only be allowed to be used if it is a child of the 'Accordion' component, so we set the allowedParents accordingly.<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0"
jcr:primaryType="cq:Component"
jcr:title="Accordion Entry"
sling:resourceSuperType="foundation/components/parbase"
allowedParents="[*/my-accordion/components/*parsys]"
componentGroup=".hidden"/>
dialog.xml:
The 'accordion-entry' dialog allows the user to enter a title for the accordion entry panel as well as rich text for the body text of the accordion.<jcr:root xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0"
jcr:primaryType="cq:Dialog"
helpPath="en/cq/current/wcm/default_components.html#Text"
title="Text"
xtype="tabpanel">
<items jcr:primaryType="cq:WidgetCollection">
<tab1
jcr:primaryType="cq:Widget"
anchor="100%"
title="Text"
xtype="panel">
<items jcr:primaryType="cq:WidgetCollection">
<title
jcr:primaryType="cq:Widget"
defaultValue="enter a title"
fieldLabel="Title"
name="./title"
xtype="textfield"/>
<isRichTextFlag
jcr:primaryType="cq:Widget"
ignoreData="{Boolean}true"
name="./textIsRich"
value="true"
xtype="hidden"/>
<text
jcr:primaryType="cq:Widget"
defaultValue="Please enter some text"
fieldDescription="Text displayed in panel"
fieldLabel="Text"
hideLabel="{Boolean}true"
name="./text"
xtype="richtext"/>
</items>
</tab1>
</items>
</jcr:root>
accordion-entry.jsp:
The JSP renders the accordion-entry's HTML. I'm not going to include all of the file's contents, but note that I use the lines below in order to obtain the title and text, set by the content editor by using the contents of the dialog.xml file above.<%
final String title = properties.get("title", "");
final String text = properties.get("text","");
%>
The 'parsys'
The parsys is used for ensuring that the component has the same properties to behave like the foundation parsys component. This component is a copy of the component in the foundation library, with a change to a few of the files for the accordion. The changed files are mentioned below.
.content.xml:
The parsys component superResourceType is the foundation's parsys component, and the allowedChildren is 'accordion-entry'.cq:isContainer="{Boolean}true"
jcr:primaryType="cq:Component"
jcr:title="Accordian Composite 1"
sling:resourceSuperType="foundation/components/parsys"
allowedChildren="*/*accordion-entry"
componentGroup=".hidden"/>
.content.xml (in the 'new' folder)
The resourceType needs to point to the accordion's copy of the parsys file.
<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0"
jcr:primaryType="cq:Component"
jcr:title="New Paragraph"
sling:resourceType="myprojectx/components/my-accordion/parsys/new"
componentGroup=".hidden"/>
_cq_editConfig.xml (in the 'new' folder)
Simply, we will tell the user to drag and drop accordion entries to this place. (So, we change the emptyText parameter here.)
<jcr:root xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0"
cq:actions="[_clear,insert]"
cq:emptyText="Drop Accordian entries here"
jcr:primaryType="cq:EditConfig"/>
Conclusion
Hopefully, I hope I have not missed anything important out from these steps. (It was a while ago since this was developed, so it's not very fresh in my memory.) I hope that this will allow you to think of alternative solutions where some of the components in CQ5 do not work as expected or as documented. The most important point is to develop the CMS website customisation so that the user can intuitively add their content and be prevented from making changes that could 'break' the website.
One more tip: I also think it's important to note that you can switch off Javascript or JQuery from running in EditMode, and this was done so that the user can view and edit all panels in the accordion by clicking onto any panel (without the behaviours applied to expand and contract).
Happy programming!
Nice tutorial. Just want to point out that the tag was introduced in 5.4. I keep trying to figure out why this wasn't working for me ..... turns out we are on 5.3 :-(
Thanks for the information about the cq:includeClientLib tag -- my blog decided to remove the tag name in the post. I think you may be able to do a little bit of restructure and not use the tag for older versions of CQ5....simply reference the Javascript to handle the accordion functionality in another way.
Thanks for this great tutorial. I have one question.
Can you tell me how to switch off jquery when running in EditMode, please? I am doing this accordion. But for some reasons, my accordion is pre-expanded for the first item in editmode. If I expand any other accordion other than first one then edit the item. I won't able to get the edit dialog box. I think your idea can solve my problem by disable the jquery in editmode. So the user can view and edit all panels in the accordion. Thjey can preview the effect in the preview mode. Thanks so much.
I'll have to look back at my code, but it may depend on the jQuery you are using. I know that in edit mode, I had expanded all items by default so the jQuery working would not get in the way of the content editors making the edits, giving them the visibility of the entire content. You can do a check to see if you are in edit mode, then behave accordingly.
The jQuery shows all accordion panels by default, and then it uses Javascript to append a new CSS class to the DIV to hide the items. Nothing special looks like it's been done, and there's nothing done differently in EDIT mode for this component. However, I believe that jQuery is only loaded if you are not in edit mode.
Find out about checking what mode (design/edit) you are in with the API, and write the logic around the script tags: http://dev.day.com/docs/en/cq/current/javadoc/com/day/cq/wcm/api/WCMMode.html
Hey man, thanks for your post do you mind provide some package or ZIP code with this sample just to able to install and run? Thanks again.. regards!
Thank you for sharing this, really appreciate the quality info.
How do you personally get information for your fresh entries and which exact search websites or techniques do you generally turn to?
Hi Jenikya,
Nice tutorial. I am currently creating components for our new project. Could you please share accordion component as CQ5 package so that I can import in CRX and see. As I am a newbie to CQ5. It will give me a great help in developing components. Your help will be much appreciated. My email kirthi_tg@yahoo.com
Regards Kirthi
hi jenikya, its a nice tutorical could you prvoide the source code.
Hi Jenikya,
I am new to CQ. I have started learning CQ as a part of our project and my current user story belongs to Accordion. Could you please share the Accordion CQ component as a Package ,It would be of a great help in developing the component.
Regards, Varoonee
My Mail id: p.varoonee@gmail.com
I am new to CQ5. Could you please share the Accordion CQ component as a Package. It will give me a great help in developing components. my email ckrishnasundaram@gmail.com
Hello, the code is not mine to hand out. I'll try to add some other CQ5 tutorials and examples on here with better code snippets.