This tutorial enables you to create a fully featured website with CQ5. The website will be based on Geometrixx, the reference website that comes with your CQ5 installation.

This tutorial is targeted primarily at web developers. All development will take place within an author environment.

This tutorial describes how to:

  • Install CQ5
  • Set up CRXDE
  • Set up the project in CRXDE
  • Create the template, component and scripts used as the basis for creating content pages
  • Create the following components for use on your pages:
    • Top Navigation
    • List Children
    • Logo
    • Image
    • Text-Image
    • Search
  • Include various foundation components

After performing all the steps, your pages will look as follows:

Website_overview

Installing CQ and the CRXDE development environment

To install a CQ instance for developing your website, follow either the instructions for setting up a deployment environment with author and publish instances, or just perform a generic installation, which makes this step as easy as downloading the CQ Quickstart jar package,  placing the license.properties file in the same directory and double-clicking the downloaded CQ Quickstart jar package.  

Additionally, proceed as follows in order to setup and start the CRXDE development environment:

  1. Ensure that CQ is installed and running.

  2. Download the CRXDE package.

  3. Extract the package.

  4. Double-click the executable.

  5. Enter the location of your CQ installation; for example http://localhost:4502 for CQ Quickstart.

  6. Enter your username (default: admin) and password (default: admin). 

  7. Click OK.

Setting up the project structure in CRXDE

In this section, you will create the mygeometrixx application and its structure in CRXDE. Proceed as follows:

  1. In CRXDE, right-click apps, select New, then Folder. In the wizard dialog, type mygeometrixx as Folder name and click Finish.

  2. Right-click mygeometrixx, select New, then Folder. In the wizard dialog, type components as Folder name and click Finish.

  3. Right-click mygeometrixx, select New, then Folder. In the wizard dialog, type templates as Folder name and click Finish.

    The structure in CRXDE looks as follows:

Setting up the Designer

In this section, you will set up the designer for your application using the Designer. Proceed as follows:

  1. In your browser, open the Tools tab of CQ WCM.

  2. Under Designs, create a new page. Enter mygeometrixx as the Title and click Create.

  3. In CRXDE refresh the tree in Navigator.

  4. In CRXDE, right-click the file etc/designs/geometrixx/static.css, then select Copy. Right-click the node etc/designs/mygeometrixx and select Paste.

  5. In CRXDE, right-click the folder /etc/designs/geometrixx/images, select Copy. Right-click the node etc/designs/mygeometrixx, select Paste.

Creating the Contentpage Template, Component, Script and Pages

In this section, you will create:

  • The contentpage template which will be used to create content pages in the example website mygeometrixx.

  • The contentpage component which will be used to render pages of content.

  • The contentpage script.

  • Following pages which all use the contentpage template: My Geometrixx, English and Products, Services and Customers.

The Products page that you will create will look as follows:

Website_contentpage_English

Creating the Contentpage Template

To create the contentpage template, which will be used to create all the pages of the website, follow the steps:

  1. In CRXDE, right-click /apps/mygeometrixx/templates, select New, then Template.
  2. In the wizard dialog, type:
    • Label: contentpage
    • Title: My Geometrixx Content Page Template
    • Description: This is My Geometrixx Content Page Template
    • Resource Type: mygeometrixx/components/contentpage
    • Click Finish.
  3. To display the template in the Create Page dialog when creating a page right under Websites from the Websites console, set the allowedPaths property of the template node to: /content(/.*)?

Creating the Contentpage Component

To create the contentpage component, which will be used to render pages of content, follow the steps:

  1. In CRXDE, right-click /apps/mygeometrixx/components, select New, then Component.

  2. In the wizard dialog, type:

    • Label: contentpage.

    • Title: My Geometrixx Content Page Component.

    • Description: This is My Geometrixx Content Page Component.

    • Click Finish.

  3. The structure now looks as follows:

Creating the Contentpage Script

This section describes how to create the first version of the contentpage script (it will be extended later):

  1. In CRXDE, open the file contentpage.jsp under /apps/mygeometrixx/components/contentpage.

  2. Copy the following code and paste it into the file:

    <%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>My title</title> </head> <body> <div>My body</div> </body> </html>
  3. Save the file.

Creating Contentpage based Pages

In order to create pages based on the contentpage template:

  1. In your browser,using the Websites tab, select Websites, click New... then select New Page....

  2. In the dialog enter:

    • Title: My Geometrixx.

    • Name: mygeometrixx.

    • Select the My Geometrixx Content Page Template.

    • Click Create.

  3. Select the My Geometrixx page (in the left pane), click New... then select New Page....

  4. In the dialog enter:

    • Title: English.

    • Name: en.

    • Select the My Geometrixx Content Page Template.

    • Click Create.

  5. Select the English page (in the left pane), click New... then select New Page....

  6. In the dialog enter:

    • Title: Products.

    • Select the My Geometrixx Content Page Template.

    • Click Create.

  7. Select the English page, click New... then select New Page....

  8. In the dialog enter:

    • Title: Services.

    • Select the My Geometrixx Content Page Template.

    • Click Create.

  9. Select the English page, click New... then select New Page....

  10. In the dialog enter:

    • Title: Customers.

    • Select the My Geometrixx Content Page Template.

    • Click Create.

  11. Your structure looks as follows:

  12. Link your pages to the mygeometrixx designer: in CRX Explorer, select the node /content/mygeometrixx/jcr:content. Double-click the property cq:designPath and set its Value to /etc/designs/mygeometrixx.

  13. In your browser, open a new tab and browse to http://localhost:4502/content/mygeometrixx/en/products.html. It looks as follows:

Enhancing the Contentpage Script

This section describes how to enhance the contentpage script:

  • first by using the foundation page scripts; the foundation components are those inbuilt in CQ

  • then by writing your own scripts

The Products page will look as follows:

Website_enhance_script_02

Using the Foundation Page Scripts

To include head.jsp and body.jsp from the foundation page component into your script:

  1. In CRXDE, add a property to the node apps/mygeometrixx/components/contentpage:

    • Select the node apps/mygeometrixx/components/contentpage.

    • In the Properties tab, right-click, select Add Property....

    • In the dialog, type sling:resourceSuperType as Name and set the Type to String. Click Finish.

    • For the new property click the column Value, enter foundation/components/page and press Enter to save the changes.

  2. Open the file contentpage.jsp under /apps/mygeometrixx/components/contentpage and replace the existing code with the following:

    <%@include file="/libs/foundation/global.jsp"%><% %><%@page session="false" contentType="text/html; charset=utf-8" %><% %><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <cq:include script="head.jsp"/> <cq:include script="body.jsp"/> </html>
  3. Save the changes.

  4. In your browser, reload the Products page. It looks as follows:

Using your own scripts

In this section you will split the body part of the contentpage component into several parts. You will do this by creating script files for every part, then by including them into the script body.jsp that defines the body. Follow the steps:

  1. In CRXDE, create the file left.jsp under /apps/mygeometrixx/components/contentpage:

    • Right-click the node /apps/mygeometrixx/components/contentpage, select New, then JSP.

    • In the dialog, as File name type left.jsp and click Finish.

  2. Edit the file left.jsp to remove the existing content and replace with the following code:

    <%@include file="/libs/foundation/global.jsp"%><% %><div class="left"> <div>logo</div> <div>newslist</div> <div>search</div> </div>
  3. Save the changes.

  4. In CRXDE, create the file center.jsp under /apps/mygeometrixx/components/contentpage:

    • Right-click the node /apps/mygeometrixx/components/contentpage, select New, then JSP.

    • In the dialog, as File name type center.jsp and click Finish.

  5. Edit the file center.jsp to remove the existing content and replace with the following code:

    <%@include file="/libs/foundation/global.jsp"%><% %><div class="center"> <div>trail</div> <div>title</div> <div>parsys</div> </div>
  6. Save the changes.

  7. In CRXDE, create the file right.jsp under /apps/mygeometrixx/components/contentpage:

    • Right-click the node /apps/mygeometrixx/components/contentpage, select New, then JSP.

    • In the dialog, as File name type right.jsp and click Finish.

  8. Edit the file right.jsp to remove the existing content and replace with the following code:

    <%@include file="/libs/foundation/global.jsp"%><% %><div class="right"> <div>iparsys</div> </div>
  9. Save the changes.

  10. In CRXDE, create the file body.jsp under /apps/mygeometrixx/components/contentpage:

    • Right-click the node /apps/mygeometrixx/components/contentpage, select New, then JSP.

    • In the dialog, as type body.jsp and click Finish.

  11. Edit the file body.jsp to remove the existing content and replace with the following code:

    <%@include file="/libs/foundation/global.jsp"%><% %><body> <div class="topnav">topnav</div> <div class="content"> <cq:include script="left.jsp" /> <cq:include script="center.jsp" /> <cq:include script="right.jsp" /> </div> <div class="footer"> <div class="toolbar">toolbar</div> <div class="disclaimer">disclaimer</div> </div> </body>
  12. Save the changes.

  13. In your browser, reload the Products Page. It looks as follows:

Creating the Top Navigation Component

In this section you will create a component that displays links to all top level pages of the website as a mechanism for navigating the website. This component will be displayed at the top of all pages created using the contentpage template.

In the first version of the top navigation component (topnav) the navigation items will be text links only. In the second version you will implement topnav with image navigation links.

Your top navigation will then look as follows:

Website_topnav_image

Creating the Top Navigation Component

To create the topnav component:

  1. In CRXDE, right-click /apps/mygeometrixx/components, select New, then Component.

  2. In the wizard dialog enter:

    • Label: topnav.

    • Title: My Top Navigation Component.

    • Description: This is My Top Navigation Component.

    • Click Finish.

Creating the Top Navigation Script with Textual Links

This section describes how to create the rendering script for the text-link based topnav component:

  1. In CRXDE, open the file topnav.jsp under /apps/mygeometrixx/components/topnav.

  2. Copy and paste the following code:

    <%@include file="/libs/foundation/global.jsp"%><% %><%@ page import="java.util.Iterator, com.day.text.Text, com.day.cq.wcm.api.PageFilter, com.day.cq.wcm.api.Page" %><% // get starting point of navigation Page navRootPage = currentPage.getAbsoluteParent(2); if (navRootPage == null && currentPage != null) { navRootPage = currentPage; } if (navRootPage != null) { Iterator<Page> children = navRootPage.listChildren(new PageFilter(request)); while (children.hasNext()) { Page child = children.next(); %><a href="<%= child.getPath() %>.html"><%=child.getTitle() %></a><% } } %>
  3. Save the changes.

Including Top Navigation in the Contentpage Component

To include topnav in your contentpage Component:

  1. In CRXDE, open the file body.jsp under /apps/mygeometrixx/components/contentpage and replace:

    <div class="topnav">topnav</div>

    with:

    <cq:include path="topnav" resourceType="mygeometrixx/components/topnav" />

  2. Save the changes.

  3. In your browser, reload the Products Page. The top navigation appears as follows:

Enhancing Pages with Subtitles

To enhance the pages with subtitles that will be displayed in the top navigation:

  1. In your browser, navigate to the Products Page.

  2. In the Sidekick, select the Page tab and click Page Properties....

  3. In the dialog, in the Basic tab, expand the More Titles and Description frame, as Subtitle, enter what we do. Click OK.

  4. Repeat the former steps to add the subtitle about our services to the Services Page.

  5. Repeat the former steps to add the subtitle the trust we earn to the Customers Page.

Creating the Top Navigation Script with Image Links

In this section you will enhance the rendering script of the topnav component to use linked images for the navigation items. The image should display the title and the description of the page reference. Follow the steps:

  1. In CRXDE, open the file topnav.jsp under /apps/mygeometrixx/components/topnav and replace:

    <%=child.getTitle() %>

    with:

    <img alt="<%= child.getTitle() %>" src="<%= child.getPath() %>.navimage.png">

  2. Save the changes.

  3. Again in CRXDE, right-click /apps/mygeometrixx/components/contentpage, select New, then File.

  4. In the dialog, as Name, type: navimage.png.java. Click Finish.

  5. Copy the following code into navimage.png.java:

    package apps.mygeometrixx.components.contentpage;
    import java.awt.Color;
    import java.awt.Paint;
    import java.awt.geom.Rectangle2D;
    import java.io.IOException;
    import javax.jcr.RepositoryException;
    import com.day.cq.wcm.api.Page;
    import com.day.cq.wcm.api.PageManager;
    import com.day.cq.wcm.api.components.Component;
    import com.day.cq.commons.SlingRepositoryException;
    import com.day.cq.wcm.commons.WCMUtils;
    import com.day.cq.wcm.commons.AbstractImageServlet;
    import com.day.cq.wcm.foundation.ImageHelper;
    import com.day.image.Font;
    import com.day.image.Layer;
    import org.apache.sling.api.SlingHttpServletRequest;
    import org.apache.sling.api.SlingHttpServletResponse;
    import org.apache.sling.api.resource.Resource;
    import org.apache.sling.api.servlets.SlingSafeMethodsServlet;

    /**
    * Renders the navigation image
    */
    public class navimage_png extends AbstractImageServlet {

    protected Layer createLayer(ImageContext ctx)
    throws RepositoryException, IOException {
    PageManager pageManager = ctx.resolver.adaptTo(PageManager.class);
    Page currentPage = pageManager.getContainingPage(ctx.resource);

    // constants
    int scale = 6;
    int paddingX = 24;
    int paddingY = 24;
    Color bgColor = new Color(0x004a565c, true);
    String title = currentPage.getNavigationTitle();
    if (title == null) {
    title = currentPage.getTitle();
    }
    if (title == null) {
    title = currentPage.getName();
    }
    title = title.toUpperCase();
    Paint titleColor = Color.WHITE;
    Font titleFont = new Font("Myriad Pro", 10 * scale, Font.BOLD);
    int titleBase = 10 * scale;

    String subtitle = currentPage.getProperties().get("subtitle", "");
    Paint subtitleColor = new Color(0xffa9afb1, true);
    Font subTitleFont = new Font("Tahoma", 7);
    int subTitleBase = 20;

    // load background image from docroot
    Component c = WCMUtils.getComponent(ctx.resource);
    Layer bg = ImageHelper.createLayer(c.getLocalResource("navimage_bg.jpg"));

    // draw the title text (4 times bigger)
    Rectangle2D titleExtent = titleFont.getTextExtent(0, 0, 0, 0, title, Font.ALIGN_LEFT, 0, 0);
    Rectangle2D subtitleExtent = subTitleFont.getTextExtent(0, 0, 0, 0, subtitle, Font.ALIGN_LEFT, 0, 0);

    // check if subtitleExtent is too width
    if ( subtitle.length() > 0 ) {
    int titleWidth = (int)titleExtent.getWidth() / scale;
    if ( subtitleExtent.getWidth() > titleWidth && subtitleExtent.getWidth() + 2 * paddingX >
    bg.getWidth() ) {
    int charWidth = (int)subtitleExtent.getWidth() / subtitle.length();
    int maxWidth = (bg.getWidth() > titleWidth + 2 * paddingX ? bg.getWidth() - 2 * paddingX : titleWidth);
    int len = (maxWidth - ( 2 * charWidth) ) / charWidth;
    subtitle = subtitle.substring(0, len) + "...";
    subtitleExtent = subTitleFont.getTextExtent(0, 0, 0, 0, subtitle, Font.ALIGN_LEFT, 0, 0);
    }
    }
    int width = Math.max((int) titleExtent.getWidth(), (int) subtitleExtent.getWidth());

    Layer text = new Layer(width, (int) titleExtent.getHeight() + 40, new Color(0x01ffffff, true));
    text.setPaint(titleColor);
    text.drawText(0, titleBase, 0, 0, title, titleFont, Font.ALIGN_LEFT | Font.ALIGN_BASE, 0, 0);
    text.resize(text.getWidth() / scale, text.getHeight() / scale);
    text.setX(0);
    text.setY(0);

    if (subtitle.length() > 0) {
    // draw the subtitle normal sized
    text.setPaint(subtitleColor);
    text.drawText(0, subTitleBase, 0, 0, subtitle, subTitleFont, Font.ALIGN_LEFT | Font.ALIGN_BASE, 0, 0);
    }

    // and merge the layers
    text.setY(paddingY);
    text.setX(paddingX);
    text.setBackgroundColor(bgColor);

    int bgWidth = bg.getWidth();
    if ( text.getWidth() + 2 * paddingX > bgWidth ) {
    bgWidth = text.getWidth() + 2 * paddingX;
    bg.resize(bgWidth, bg.getHeight());
    }
    bg.merge(text);

    return bg;
    }
    }
  6. Save the changes.

  7. To have navimage_bg.jpg as the background:

    • In CRXDE, right-click /apps/geometrixx/components/contentpage/navimage_bg.jpg and select Copy.

    • Right-click /apps/mygeometrixx/components/contentpage and select Paste.

  8. In your browser, reload the Products page. The top navigation now appears as follows:

Creating the List Children Component

In this section you will create the list children (listchildren) component which displays a list of links with the title, description and date of pages (for example, product pages) which are below either the current page or a root page defined in the component dialog.

It will look as follows:

Website_listchildren02

Creating Product Pages

In this section you will create two pages below the Products page, describing two specific products. For each page, you will set a title, a description and a date.

  1. In your browser, in the Websites tab, select the Products page in the left pane. Click New... then select New Page....

  2. In the dialog enter:

    • Title: Product 1.

    • Name: product1.

    • Select My Geometrixx Content Page Template.

    • Click Create.

  3. Select the Products page. Click New... then select New Page....

  4. In the dialog enter:

    • Title: Product 2.

    • Name: product2.

    • Select My Geometrixx Content Page Template.

    • Click Create.

  5. In CRX Explorer, set a description and a date for the Product 1 page:

    • Browse to the node /content/mygeometrixx/en/products/product1/jcr:content. Double-click the jcr:description property and set the Value to This is a description of the Product 1!. Save the update.

    • Right-click /content/mygeometrixx/en/products/product1/jcr:content, select New Property. Set Name to date and Value to 10/11/2008. Save the update.

  6. In CRX Explorer, set a description and a date for the Product 2 page:

    • Browse to the node /content/mygeometrixx/en/products/product2/jcr:content. Double-click the jcr:description property and set the Value to This is a description of the Product 2!. Save the update.

    • Right-click /content/mygeometrixx/en/products/product2/jcr:content, select New Property. Set Name to date and Value to 20/11/2008. Save the update.

Creating the List Children Component

To create the listchildren component:

  1. In CRXDE, right-click /apps/mygeometrixx/components, select New, then Component.

  2. In the wizard dialog enter:

    • Label: listchildren.

    • Title: My Listchildren Component.

    • Description: This is My Listchildren Component.

    • Click Finish.

Creating the List Children Script

This section describes how to create the listchildren script. This displays a list of links with title, description and date of pages (for example, product pages) that are below either the current page or a root page as defined in the component dialog. Follow the steps:

  1. In CRXDE, open the file listchildren.jsp under /apps/mygeometrixx/components/listchildren.

  2. Copy and paste the following code:

    <%@include file="/libs/foundation/global.jsp"%><%
    %><%@ page import="java.util.Iterator,
    com.day.cq.wcm.api.PageFilter"%><%
    String listroot = properties.get("listroot", currentPage.getPath());
    Page rootPage = pageManager.getPage(listroot);
    if (rootPage != null) {
    Iterator<Page> children = rootPage.listChildren(new PageFilter(request));
    while (children.hasNext()) {
    Page child = children.next();
    String title = child.getTitle() == null ? child.getName() : child.getTitle();
    String date = child.getProperties().get("date","");
    %><div class="item">
    <a href="<%= child.getPath() %>.html"><b><%= title %></b></a>
    <span><%= date %></span><br>
    <%= child.getProperties().get("jcr:description","") %><br>
    </div><%
    }
    }
    %>
  3. Save the changes.

Creating the List Children Dialog

In this section, you will create the dialog for the listchildren component.

  1. Create the dialog node under the listchildren component:

    • In CRXDE, right-click the node /apps/mygeometrixx/components/listchildren, select New, then Dialog.

    • In the wizard dialog, as Name enter dialog and as Title, select List Children. Click Finish. The dialog generated looks as follows:

      With the following properties:

  2. With CRXDE edit the title property for tab1 node. Set it to Edit Component.

  3. With the CRX Explorer, create an items node under the tab1 node:

  4. With the CRX Explorer, create the listroot node under the items node:

  5. Add properties for the listroot node as follows:

Note

The previous procedure uses the default dialog structure.

It is possible to create dialogs (such as those seen in Geometrixx) by manually creating and configuring the individual nodes.

Including List Children in the Contentpage Component

In order to include the listchildren component in your contentpage component, proceed as follows:

  1. In CRXDE, open the file left.jsp under /apps/mygeometrixx/components/contentpage and replace:

    <div>newslist</div>

    with:

    <cq:include path="newslist" resourceType="mygeometrixx/components/listchildren" />

  2. Save the changes.

Viewing List Children in a Page

To see the full operation of this component you can view the Products page:

  • when the parent page ("Path of list root") is not defined.

  • when the parent page ("Path of list root") is defined.

  1. In your browser, reload the Products Page. The listchildren component appears as follows:

  2. Double-click your component to open the edit dialog:

  3. As Path of list root, enter: /content/mygeometrixx/en. Click OK. The listchildren component on your page now looks as follows:

Creating the Logo Component

In this section you will create the component which displays the logo, with underlying link to the homepage of the example website mygeometrixx. The logo image and the home link can be configured globally (same for every page of the website). You will create a design mode dialog to provide the image and the link path. The logo component will be placed on the upper left side of all pages in the website.

It will look as follows:

Website_logo

Creating the Logo Component

To create the logo component, follow the steps:

  1. In CRXDE, right-click /apps/mygeometrixx/components, select New, then Component.

  2. In the wizard dialog enter:

    • Label: logo.

    • Title: My Logo Component.

    • Description: This is My Logo Component.

    • Click Finish.

Creating the Logo Script

This section describes how to create the script to display the logo image with a link to the homepage.

  1. In CRXDE, open the file logo.jsp under /apps/mygeometrixx/components/logo.

  2. Copy the following code to logo.jsp:

    <%@include file="/libs/foundation/global.jsp"%><% %>
    <%@ page import="com.day.text.Text" %><%

    long absParent = currentStyle.get("absParent", 2L);
    String home = Text.getAbsoluteParent(currentPage.getPath(), (int) absParent);
    Resource image = currentStyle.get("image", Resource.class);
    %><a href="<%= home %>.html"><%
    if (image ==null) {
    %>Home<%
    } else {
    %><img border="0" src="<%= image.getPath() %>" alt="Home" ><%
    }
    %></a>
  3. Save the changes.

Creating the Logo Design Dialog

In this section, you will create the design dialog for your logo component.

  1. In CRXDE, under the node /apps/mygeometrixx/components/logo, create a new dialog with:

    • Name: design_dialog.

    • Title: Logo (Design).

    • Properties as follows:

  2. For the node tab1 set the title property to General.

  3. Under the node tab1 create a node items (cq:WidgetCollection).

  4. Under the node design_dialog/i/items/tab1/items create a new node absParent (nt:unstructured) and set the following properties: 
  5. Under the node design_dialog/i/items/tab1/items create a new node margin (nt:unstructured) and set the following properties:

  6. Under the node design_dialog/items/items create a img node (cq:Widget) and set the following properties:

Including Logo in the Contentpage Component

In order to include the logo in your contentpage component, proceed as follows:

  1. In CRXDE, open the file left.jsp under /apps/mygeometrixx/components/contentpage and replace:

    <div>logo</div>

    with:

    <cq:include path="logo" resourceType="mygeometrixx/components/logo" />

  2. Save the changes.

  3. In your browser, reload the Products page. The logo looks as follows, though currently it only shows the underlying link:

Setting the Logo Image in a Page

This section describes how to set an image as your logo using the design mode dialog.

  1. In your browser, switch to design mode.

  2. In the Design of logo bar, click Edit to use the dialog to edit the settings for the logo component:

  3. In the dialog select the Image tab. Upload your image. Click OK. The logo looks as follows and is activated as a link:

Including the Breadcrumb Component

In this section, you will include the breadcrumb (trail) component, which is one of the foundation components.

  1. In CRXDE, browse to /apps/mygeometrixx/components/contentpage, open the file center.jsp and replace:<div>trail</div> with: <cq:include path="trail" resourceType="foundation/components/breadcrumb" />

  2. Save the changes.

  3. In your browser, reload the Products 1 page. The trail component looks as follows:

    Note: You have the possibility to define the Parent Level in design mode.

Including the Title Component

In this section, you will include the title component, which is one of the foundation components.

  1. In CRXDE, browse to /apps/mygeometrixx/components/contentpage, open the file center.jsp and replace:<div>title</div>with: <cq:include path="title" resourceType="foundation/components/title" />

  2. Save the changes.

  3. In your browser, reload the Products page. The title component looks as follows:

    Note: You have the possibility to set a different Title and the Type / Size in edit mode.

Including the Paragraph System Component

The paragraph system (parsys) is a significant part of a website as it manages a list of paragraphs. It is used to structure the content parts on a website.

In this section, you will include the parsys component (one of the foundation components) in your contentpage component.

  1. In CRXDE, browse to /apps/mygeometrixx/components/contentpage, open the file center.jsp and replace:<div>parsys</div>with: <cq:include path="par" resourceType="foundation/components/parsys" />

  2. Save the changes.

  3. In your browser, refresh the Products page. It now has the parsys component, which is seen as follows:

Creating the Image Component

In this section you will create a component which displays images in the main paragraph system of the example website mygeometrixx. You will create a dialog enabling you to specify the image and other properties (title, description, size) when in edit mode. These will be stored in the paragraph resource. Users will have the possibility to crop, map and rotate the image.

Creating the Image Component

To create the image component, follow the steps:

  1. In CRXDE, right-click /apps/mygeometrixx/components, select New, then Component.

  2. In the wizard dialog enter:

    • Label: image.

    • Title: My Image Component.

    • Description: This is My Image Component.

    • Group: MyGeometrixx.

    • Click Next.

    • Allowed Parents: */parsys.
    • Click Finish.

Creating the Image Script

This section describes how to create the image script.

  1. In CRXDE, browse to /apps/mygeometrixx/components/image and open the file image.jsp

  2. Copy the following code to image.jsp:

    <%@ page import="com.day.cq.wcm.foundation.Image,
    com.day.cq.wcm.api.components.DropTarget,
    com.day.cq.wcm.api.components.EditConfig,
    com.day.cq.wcm.commons.WCMUtils" %><%
    %><%@include file="/libs/foundation/global.jsp"%><%
    //drop target css class = dd prefix + name of the drop target in the edit config
    String ddClassName = DropTarget.CSS_CLASS_PREFIX + "image";

    Image image = new Image(resource);
    image.addCssClass(ddClassName);
    image.loadStyleData(currentStyle);
    image.setSelector(".img"); // use image script
    // add design information if not default (i.e. for reference paras)
    if (!currentDesign.equals(resourceDesign)) {
    image.setSuffix(currentDesign.getId());
    }
    %><% image.draw(out); %><br><%
    if (image.getDescription().length() > 0) {
    %><small><%= image.getDescription(true) %></small><%
    }

    %>
  3. Save the changes.

Creating the Image Rendering Script

 This section describes how to create the script that renders the image:

  1. In CRXDE, right-click /apps/mygeometrixx/components/image, select New, then New File....

  2. In the dialog, as Name enter img.png.java. Click Finish.

  3. Open the new file and copy the following code into it:

    package apps.mygeometrixx.components.image;
    import java.io.IOException;
    import java.io.InputStream;
    import javax.jcr.RepositoryException;
    import javax.jcr.Property;
    import javax.servlet.http.HttpServletResponse;
    import com.day.cq.wcm.foundation.Image;
    import com.day.cq.wcm.commons.RequestHelper;
    import com.day.cq.wcm.commons.WCMUtils;
    import com.day.cq.wcm.commons.AbstractImageServlet;
    import com.day.cq.commons.SlingRepositoryException;
    import com.day.image.Layer;
    import org.apache.commons.io.IOUtils;
    import org.apache.sling.api.SlingHttpServletRequest;
    import org.apache.sling.api.SlingHttpServletResponse;
    import org.apache.sling.api.resource.Resource;
    import org.apache.sling.api.resource.ValueMap;
    import org.apache.sling.api.servlets.SlingSafeMethodsServlet;

    /**
    * Renders an image
    */
    public class img_png extends AbstractImageServlet {

    protected Layer createLayer(ImageContext c)
    throws RepositoryException, IOException {
    // don't create the later yet. handle everything later
    return null;
    }

    protected void writeLayer(SlingHttpServletRequest req,
    SlingHttpServletResponse resp,
    ImageContext c, Layer layer)
    throws IOException, RepositoryException {

    Image image = new Image(c.resource);
    if (!image.hasContent()) {
    resp.sendError(HttpServletResponse.SC_NOT_FOUND);
    return;
    }
    // get style and set constraints
    image.loadStyleData(c.style);

    // get pure layer
    layer = image.getLayer(false, false, false);

    // crop
    boolean modified = image.crop(layer) != null;

    // resize
    modified |= image.resize(layer) != null;

    // rotate
    modified |= image.rotate(layer) != null;
    if (modified) {
    resp.setContentType("image/png");
    layer.write("image/png", 1.0, resp.getOutputStream());
    } else {
    // do not re-encode layer, just spool
    Property data = image.getData();
    InputStream in = data.getStream();
    resp.setContentLength((int) data.getLength());
    resp.setContentType(image.getMimeType());
    IOUtils.copy(in, resp.getOutputStream());
    in.close();
    }
    resp.flushBuffer();
    }
    }
  4. Save the changes.

Creating the Image Dialog

This section describes how to create the dialog for edit mode, so that the image and related properties (title, description, size) can be stored in the paragraph resource

You will copy the dialog from the foundation image component:

  1. In CRXDE, right-click the node /libs/foundation/components/image/dialog and select Copy.

  2. Right-click the node /apps/mygeometrixx/components/image and click Paste.

  3. Your dialog in /apps/mygeometrixx/components/image looks as follows:

Creating the Image cq:editConfig Node

In this section, you will create the cq:editConfig node structure. It enables you to drag assets from the Content Finder into your image component.

  1. Using the CRX Explorer, under the node /apps/mygeometrixx/components/image, create a new node as follows:

    • Name: cq:editConfig.

    • Type: cq:EditConfig.

  2. Under the node cq:editConfig, create a new node as follows:

    • Name: cq:dropTargets.

    • Type: cq:DropTargetConfig.

  3. Under the node cq:dropTargets, create a new node as follows:

    • Name: image.

    • Type: nt:unstructured.

  4. In CRXDE set the properties as follows:

Adding the icon

In this section, you will add the icon to appear beside the image component when it is listed in Sidekick:

  1. In CRXDE, right-click the file /libs/foundation/components/image/icon.png and select Copy.

  2. Right-click the node /apps/mygeometrixx/components/image and click Paste

Viewing Image in a Page

In this section, you will view the Products page and add your image component to the paragraph system.

  1. In your browser, reload the Products page.

  2. In the Sidekick, click the design mode icon.

  3. Click the Edit button to edit the design dialog of par.

  4. In the dialog, a list of Allowed Components is shown; check My Image Component and click OK.

  5. Return to edit mode.

  6. Double-click the parsys frame (on Drag components or assets here). The Insert New Component and Sidekick selectors look as follows:

The Text-Image Component

In this section you will create a component (textimage) which displays text and images in the main paragraph system of the example website mygeometrixx.

You will create a dialog for edit mode that enables you to specify the text and image, together with certain display properties (title, description, size) that are stored in the paragraph resource. Users will have the possibility to crop, map and rotate the image.

Creating the Text-Image Component

To create the textimage component, follow the steps:

  1. In CRXDE, right-click /apps/mygeometrixx/components, select New, then Component.

  2. In the wizard dialog enter:

    • Label: textimage.

    • Title: My Text-Image Component.

    • Description: This is My Text-Image Component.

    • Super Resource Type: apps/mygeometrixx/components/image.

    • Group: MyGeometrixx.

    • Click Next.

    • As Allowed Parents, type */parsys.

    • Click Finish.

Creating the Text-Image Script

 This section describes how to create the textimage script:

  1. In CRXDE, navigate to /apps/mygeometrixx/components/textimage and open the file textimage.jsp

  2. Copy the following code into textimage.jsp:

    <%@ page import="com.day.cq.wcm.foundation.Image, com.day.cq.wcm.foundation.TextFormat, org.apache.commons.lang.StringEscapeUtils, com.day.cq.wcm.api.components.DropTarget, com.day.cq.wcm.api.WCMMode" %><% %><%@include file="/libs/foundation/global.jsp"%><% //drop target css class = dd prefix + name of the drop target in the edit config String ddClassName = DropTarget.CSS_CLASS_PREFIX + "image"; Image img = new Image(resource, "image"); if (img.hasContent() || WCMMode.fromRequest(request) == WCMMode.EDIT) { %><div class="image"><% img.loadStyleData(currentStyle); // add design information if not default (i.e. for reference paras) if (!currentDesign.equals(resourceDesign)) { img.setSuffix(currentDesign.getId()); } img.addCssClass(ddClassName); img.setSelector(".img"); if (img.getTitle().length() > 0) { %><strong><%= img.getTitle(true) %></strong><br><% } %><% img.draw(out); %><br><% if (img.getDescription().length() > 0) { %><small><%= img.getDescription(true) %></small><% } %></div><% } if (properties.get("text", "").length() > 0) { %><div class="text"><% String text = properties.get("text", String.class); if (properties.get("textIsRich", "false").equals("true")) { %><%= text %><% } else { TextFormat fmt = new TextFormat(); fmt.setTagUlOpen("<ul>"); fmt.setTagOlOpen("<ol start=\"%s\">"); %><%= fmt.format(text) %><% } %></div><% } else if (WCMMode.fromRequest(request) == WCMMode.EDIT) { %><img src="/libs/widgets/0.gif" class="cq-text-placeholder <%= ddClassName %>" alt=""><% } %><div class="clear"></div>
  3. Save the changes.

Creating the Text-Image Dialog

This section describes how to create the edit mode dialog that will enable you to specify the text, image and display properties (title, description, size) to be stored in the paragraph resource.

You will copy the dialog from the corresponding foundation textimage component:

  1. In CRX Explorer, right-click the node /libs/foundation/components/textimage/dialog and select Copy.

  2. In the dialog, navigate to the node /apps/mygeometrixx/components/textimage and click Open. Click OK.

  3. The structure of your dialog in /apps/mygeometrixx/components/textimage looks as follows:

Creating the Text-Image cq:editConfig Node

In this section, you will create the cq:editConfig node structure. It enables you to drag assets from the Content Finder into the textimage component.

You will copy the cq:editConfig node from the foundation textimage component.

  1. In CRX Explorer, right-click the node /libs/foundation/components/textimage/cq:editConfig and select Copy.

  2. In the dialog, navigate to the node /apps/mygeometrixx/components/textimage and click Open. Click OK.

  3. The structure under /apps/mygeometrixx/components/textimage looks as follows:

  4. Select the node /apps/mygeometrixx/components/textimage/cq:editConfig/cq:dropTargets/image/parameters/image and set the Value of the sling:resourceType property to mygeometrixx/components/image. Save the change.

Adding the Icon

In this section, you will add the icon which appears in the Sidekick beside the textimage component :

  1. In CRX Explorer, right-click the file /libs/foundation/components/textimage/icon.png and select Copy.

  2. Navigate to the node /apps/mygeometrixx/components/textimage and click Open. Click OK.

Adding Text-Image to the Paragraph System

In this section, you will view the Products page and add your textimage component to the paragraph system.

  1. In your browser, reload the Products page.

  2. In the Sidekick, click the design mode icon.

  3. Click the Edit button to edit the design dialog of par.

  4. In the dialog, a list of Allowed Components is shown; check My Text-Image Component and click OK.

  5. Switch to edit mode.

  6. Double-click the parsys frame. The textimage component is now listed:

Including the Toolbar Component

In this section, you include the toolbar component, which is one of the foundation components.

You have several options, in edit mode as well as design mode.

  1. In CRXDE, navigate to /apps/mygeometrixx/components/contentpage, open the file body.jsp and replace:<div class="toolbar">toolbar</div>with: <cq:include path="toolbar" resourceType="foundation/components/toolbar"/><br>

  2. Save the changes.

  3. In the Websites tab, select the English page under My Geometrixx. Create the Toolbar page under English. Using the Page Properties... in Sidekick set Hide in Navigation (in Sidekick).

  4. Under Toolbar, create following pages:

    • Contacts

    • Feedback

    • Login

    • Search

  5. In your browser, reload the Products page. It looks as follows:

Creating the Search Component

In this section you will create the component to search for content on the website. This search component can be placed in the paragraph system of any page (for example, on a specialized search result page).

Your search input box will look as follows in the English page:

Website_search

Your search input box will look as follows in the Search page:

Website_search03

Creating the Search Component

To create the search component:

  1. In CRXDE, right-click /apps/mygeometrixx/components, select New, then Component.

  2. In the wizard dialog:

    • Label: search.

    • Title: My Search Component.

    • Description: This is My Search Component.

    • Group: MyGeometrixx.

    • Click Next.

    • As Allowed Parents, type */parsys.

    • Click Finish.

  3. In CRX Explorer, copy the node /libs/foundation/components/search/dialog to under /apps/mygeometrixx/components/search.

  4. In CRX Explorer, copy the node /libs/foundation/components/search/i18n to under /apps/mygeometrixx/components/search (for internationalization).

  5. In CRX Explorer, copy the node /libs/foundation/components/search/resources to under /apps/mygeometrixx/components/search (for the document format icons).

Creating the Search Script

 This section describes how to create the search script:

  1. In CRXDE, navigate to /apps/mygeometrixx/components/search and open the file search.jsp.

  2. Copy the following code to search.jsp:

    <%@ page import="com.day.cq.wcm.foundation.Search,com.day.cq.tagging.TagManager" %>
    <%--
    Copyright 1997-2008 Day Management AG
    Barfuesserplatz 6, 4001 Basel, Switzerland
    All Rights Reserved.

    This software is the confidential and proprietary information of
    Day Management AG, ("Confidential Information"). You shall not
    disclose such Confidential Information and shall use it only in
    accordance with the terms of the license agreement you entered into
    with Day.

    ==============================================================================

    Search component

    Draws the search form and evaluates a query

    --%><%@include file="/libs/foundation/global.jsp" %><%
    %><cq:setContentBundle/><%
    Search search = new Search(slingRequest);

    String searchIn = (String) properties.get("searchIn");
    String requestSearchPath = request.getParameter("path");
    if (searchIn != null) {
    // only allow the "path" request parameter to be used if it
    // is within the searchIn path configured
    if (requestSearchPath != null && requestSearchPath.startsWith(searchIn)) {
    search.setSearchIn(requestSearchPath);
    } else {
    search.setSearchIn(searchIn);
    }
    } else if (requestSearchPath != null) {
    search.setSearchIn(requestSearchPath);
    }

    pageContext.setAttribute("search", search);
    TagManager tm = resourceResolver.adaptTo(TagManager.class);
    %><c:set var="trends" value="${search.trends}"/><%
    %><center>
    <form action="${currentPage.path}.html">
    <input size="41" maxlength="2048" name="q" value="${fn:escapeXml(search.query)}"/>
    <input value="<fmt:message key="searchButtonText"/>" type="submit" />
    </form>
    </center>
    <br/>
    <c:set var="result" value="${search.result}"/>
    <c:choose>
    <c:when test="${empty result && empty search.query}">
    </c:when>
    <c:when test="${empty result.hits}">
    ${result.trackerScript}
    <c:if test="${result.spellcheck != null}">
    <p><fmt:message key="spellcheckText"/> <a href="<c:url value="${currentPage.path}.html"><c:param name="q" value="${result.spellcheck}"/></c:url>"><b><c:out value="${result.spellcheck}"/></b></a></p>
    </c:if>
    <fmt:message key="noResultsText">
    <fmt:param value="${fn:escapeXml(search.query)}"/>
    </fmt:message>
    </c:when>
    <c:otherwise>
    ${result.trackerScript}
    <fmt:message key="statisticsText">
    <fmt:param value="${result.startIndex + 1}"/>
    <fmt:param value="${result.startIndex + fn:length(result.hits)}"/>
    <fmt:param value="${result.totalMatches}"/>
    <fmt:param value="${fn:escapeXml(search.query)}"/>
    <fmt:param value="${result.executionTime}"/>
    </fmt:message>
    <div class="searchRight">
    <c:if test="${fn:length(trends.queries) > 0}">
    <p><fmt:message key="searchTrendsText"/></p>
    <div class="searchTrends">
    <c:forEach var="query" items="${trends.queries}">
    <a href="<c:url value="${currentPage.path}.html"><c:param name="q" value="${query.query}"/></c:url>"><span style="font-size:${query.size}px"><c:out value="${query.query}"/></span></a>
    </c:forEach>
    </div>
    </c:if>

    <c:if test="${result.facets.languages.containsHit}">
    <p>Languages</p>
    <c:forEach var="bucket" items="${result.facets.languages.buckets}">
    <c:set var="bucketValue" value="${bucket.value}"/>
    <c:set var="label" value='<%= new java.util.Locale((String) pageContext.getAttribute("bucketValue")).getDisplayLanguage(request.getLocale()) %>'/>
    <c:choose>
    <c:when test="${param.language != null}">${label} (${bucket.count}) - <a href="<cq:requestURL><cq:removeParam name="language"/></cq:requestURL>">remove filter</a></c:when>
    <c:otherwise><a title="filter results" href="<cq:requestURL><cq:addParam name="language" value="${bucket.value}"/></cq:requestURL>">${label} (${bucket.count})</a></c:otherwise>
    </c:choose><br/>
    </c:forEach>
    </c:if>

    <c:if test="${result.facets.tags.containsHit}">
    <p>Tags</p>
    <c:forEach var="bucket" items="${result.facets.tags.buckets}">
    <c:set var="bucketValue" value="${bucket.value}"/>
    <c:set var="tag" value="<%= tm.resolve((String) pageContext.getAttribute("bucketValue")) %>"/>
    <c:if test="${tag != null}">
    <c:set var="label" value="${tag.title}"/>
    <c:choose>
    <c:when test="<%= request.getParameter("tag") != null && java.util.Arrays.asList(request.getParameterValues("tag")).contains(pageContext.getAttribute("bucketValue")) %>">${label} (${bucket.count}) - <a href="<cq:requestURL><cq:removeParam name="tag" value="${bucket.value}"/></cq:requestURL>">remove filter</a></c:when>
    <c:otherwise><a title="filter results" href="<cq:requestURL><cq:addParam name="tag" value="${bucket.value}"/></cq:requestURL>">${label} (${bucket.count})</a></c:otherwise>
    </c:choose><br/>
    </c:if>
    </c:forEach>
    </c:if>

    <c:if test="${result.facets.mimeTypes.containsHit}">
    <jsp:useBean id="fileTypes" class="com.day.cq.wcm.foundation.FileTypes"/>
    <p>File types</p>
    <c:forEach var="bucket" items="${result.facets.mimeTypes.buckets}">
    <c:set var="bucketValue" value="${bucket.value}"/>
    <c:set var="label" value="${fileTypes[bucket.value]}"/>
    <c:choose>
    <c:when test="<%= request.getParameter("mimeType") != null && java.util.Arrays.asList(request.getParameterValues("mimeType")).contains(pageContext.getAttribute("bucketValue")) %>">${label} (${bucket.count}) - <a href="<cq:requestURL><cq:removeParam name="mimeType" value="${bucket.value}"/></cq:requestURL>">remove filter</a></c:when>
    <c:otherwise><a title="filter results" href="<cq:requestURL><cq:addParam name="mimeType" value="${bucket.value}"/></cq:requestURL>">${label} (${bucket.count})</a></c:otherwise>
    </c:choose><br/>
    </c:forEach>
    </c:if>

    <c:if test="${result.facets.lastModified.containsHit}">
    <p>Last Modified</p>
    <c:forEach var="bucket" items="${result.facets.lastModified.buckets}">
    <c:choose>
    <c:when test="${param.from == bucket.from && param.to == bucket.to}">${bucket.value} (${bucket.count}) - <a href="<cq:requestURL><cq:removeParam name="from"/><cq:removeParam name="to"/></cq:requestURL>">remove filter</a></c:when>
    <c:otherwise><a title="filter results" href="<cq:requestURL><cq:removeParam name="from"/><cq:removeParam name="to"/><c:if test="${bucket.from != null}"><cq:addParam name="from" value="${bucket.from}"/></c:if><c:if test="${bucket.to != null}"><cq:addParam name="to" value="${bucket.to}"/></c:if></cq:requestURL>">${bucket.value} (${bucket.count})</a></c:otherwise>
    </c:choose><br/>
    </c:forEach>
    </c:if>
    </div>

    <c:if test="${fn:length(search.relatedQueries) > 0}">
    <br/><br/>
    <fmt:message key="relatedSearchesText"/>
    <c:forEach var="rq" items="${search.relatedQueries}">
    <a style="margin-right:10px" href="${currentPage.path}.html?q=${rq}"><c:out value="${rq}"/></a>
    </c:forEach>
    </c:if>
    <br/>
    <c:forEach var="hit" items="${result.hits}" varStatus="status">
    <br/>
    ${hit.icon} <a href="${hit.URL}" onclick="trackSelectedResult(this, ${status.index + 1})">${hit.title}</a>
    <div>${hit.excerpt}</div>
    ${hit.URL}<c:if test="${!empty hit.properties['cq:lastModified']}"> - <c:catch><fmt:formatDate value="${hit.properties['cq:lastModified'].time}" dateStyle="medium"/></c:catch></c:if> - <a href="${hit.similarURL}"><fmt:message key="similarPagesText"/></a>
    <br/>
    </c:forEach>
    <br/>
    <c:if test="${fn:length(result.resultPages) > 1}">
    <fmt:message key="resultPagesText"/>
    <c:if test="${result.previousPage != null}">
    <a href="${result.previousPage.URL}"><fmt:message key="previousText"/></a>
    </c:if>
    <c:forEach var="page" items="${result.resultPages}">
    <c:choose>
    <c:when test="${page.currentPage}">${page.index + 1}</c:when>
    <c:otherwise>
    <a href="${page.URL}">${page.index + 1}</a>
    </c:otherwise>
    </c:choose>
    </c:forEach>
    <c:if test="${result.nextPage != null}">
    <a href="${result.nextPage.URL}"><fmt:message key="nextText"/></a>
    </c:if>
    </c:if>
    </c:otherwise>
    </c:choose>
  3. Save the changes.

Including a Search Box in the Contentpage Component

To include a search input box in the left section of your contentpage, proceed as follows:

  1. In CRXDE, open the file left.jsp under /apps/mygeometrixx/components/contentpage and before:

    %><div class="left">

    insert:

    %><%@ page import="com.day.text.Text"%><% String docroot = currentDesign.getPath(); String home = Text.getAbsoluteParent(currentPage.getPath(), 2);

  2. Replace:

    <div>search</div>

    with:

    <div class="form_1"> <form class="geo" action="<%= home %>/toolbar/search.html" id="form" > <p><input class="geo" type="text" name="q"><br> <a href="<%= home %>/toolbar/search.html" class="link_1">advanced search</a> </p> </form> </div>

  3. Save the changes.

  4. In your browser, reload the Products page. It looks as follows:

Including the Search Component in the Search Page

In this section, you will add your search component to the paragraph system.

  1. In your browser, open the Search page.

  2. In the Sidekick, click the design mode icon.

  3. Click the Edit button to edit the Design of par.

  4. In the dialog, a list of the Allowed Components is shown; check My Search Component and click OK.

  5. Return to edit mode.

  6. Drag the My Search Component from the Sidekick into the parsys frame. It looks as follows:

  7. Navigate to your Products page. Search for customers in the input box and press Enter. You are redirected to the Search page. Switch to preview mode: the output will be shown in a similar format as the following:

Including the Iparsys Component

In this section, you include the iparsys component, which is one of the foundation components.

For this component you can set several parameters in both edit mode and design mode.

  1. In CRXDE, navigate to /apps/mygeometrixx/components/contentpage, open the file right.jsp and replace:<div>iparsys</div> with: <cq:include path="rightpar" resourceType="foundation/components/iparsys" />

  2. Save the changes.

  3. In your browser, reload the Products page. The included iparsys component looks as follows:

  4. The whole page looks as follows:


Your comments are welcome!
Did you notice a way we could improve the documentation on this page? Is something unclear or insufficiently explained? Please leave your comments below and we will make the appropriate changes. Comments that have been addressed, by improving the documentation accordingly, will then be removed.

COMMENTS

  • By Irene - 1:18 PM on Jul 23, 2012   Reply
    <img alt="<%= child.getTitle() %>" src="<%= child.getPath() %>.navimage.png">

    In the above statement based on what .navimage.png is giben?
    • By ppiegaze - 5:37 PM on Jul 25, 2012   Reply
      The .navimage is a selector used to address the navigation image graphic associated the resource at an given path. You can search for "sling cheatsheet" or "sling resolution" for more information on how selectors work

    ADD A COMMENT

     

    In order to post a comment, you need to sign-in.

    Note: Customers with DayCare user accounts need to create a new account for use on day.com.

    ***