Building an Accordion Component in Adobe CQ5

| 14 Comments | No TrackBacks
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.)

cq5accordion1.jpg

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.

cq5accordion2.jpg

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

<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="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! 

No TrackBacks

TrackBack URL: http://jenikya.com/cgi-bin/mt5/mt-tb.cgi/590

14 Comments

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

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

Leave a comment

Archives

Recent Comments

  • jenn: Hello, the code is not mine to hand out. I'll read more
  • krishna: I am new to CQ5. Could you please share the read more
  • varoonee: My Mail id: p.varoonee@gmail.com read more
  • varoonee: Hi Jenikya, I am new to CQ. I have started read more
  • tbsr76: hi jenikya, its a nice tutorical could you prvoide the read more
  • https://me.yahoo.com/a/c6zkRuFkttj4s.ARByfZgG55wGhUrQ--#6aaaa: Hi Jenikya, Nice tutorial. I am currently creating components for read more
  • Robert's blog: How do you personally get information for your fresh entries read more
  • Md: Thank you for sharing this, really appreciate the quality info. read more
  • https://me.yahoo.com/a/eUQ7DrVhzvFjQcFzmXELcfSusmE-#081e4: Hey man, thanks for your post do you mind provide read more
  • jenn: The jQuery shows all accordion panels by default, and then read more
OpenID accepted here Learn more about OpenID