Академический Документы
Профессиональный Документы
Культура Документы
This tutorial enables you to create a fully featured website with Adobe Experience Manager (AEM). The
website will be based on a generic website and is targeted primarily at web developers. All development will
take place within an author environment.
This tutorial describes how to:
1.
2.
3.
4.
5.
6.
Install AEM.
Access CRXDE Lite (the development environment).
Set up the project structure in CRXDE Lite.
Create the template, component, and scripts used as the basis for creating content pages.
Create the root page for your website and then content pages.
Create the following components for use on your pages:
Top Navigation
List Children
Logo
Image
Text-Image
Search
7. Include various foundation components.
After performing all the steps, your pages will look as follows:
Page 1
Created on 2014-09-05
NOTE
The URL of CRXDE Lite for an AEM authoring instance that is installed locally using the default
port is http://localhost:4502/crx/de/.
4.
In the tree on the left side of CRXDE Lite, right-click the /apps folder and click Create > Create Folder.
In the Create Folder dialog, type mywebsite as the folder name and click OK.
Right-click the /apps/mywebsite folder and click Create > Create Folder. In the Create Folder dialog,
type components as the folder name and click OK.
Right-click the /apps/mywebsite folder and click Create > Create Folder. In the Create Folder dialog,
type templates as the folder name and click OK.
The structure in the tree should now look something like this:
Click the following link to download mywebsite.zip. The archive contains the static.css and image
files for your design.
Page 2
Created on 2014-09-05
Page 3
Created on 2014-09-05
1.
2.
In the folder tree, select the Designs folder and then click New > New Page. Type mywebsite as the
title and click Create.
3.
If the mywebsite item does not appear in the table, refresh the tree or the table.
4.
Using WebDAV access to the URL at http://localhost:4502, copy the sample static.css file and images
folder from the downloaded mywebsite.zip file into the /etc/designs/mywebsite folder.
In the folder tree of CRXDE Lite, right-click /apps/mywebsite/templates and click Create > Create
Template.
2.
In the Create Template dialog, type the following values and then click Next:
Label: contentpage
Title: My Website Content Page Template
Description: This is my Website Content Page Template
Resource Type: mywebsite/components/contentpage
Use the default value for the Ranking property.
The resource type identifies the component that renders the page. In this case, all pages created using
the contentpage template are rendered by the mywebsite/components/contentpage component.
Page 4
Created on 2014-09-05
3.
To specify the paths of the pages that can use this template, click the plus button and type /
content(/.*)? in the text box that appears. Then, click Next.
The value of the allowed path property is a regular expression. Pages that have a path that matches
the expression can use the template. In this is case the regular expression matches the path of the /
content folder and all subpages.
When an author creates a page below /content, the contentpage template appears in a list of available
templates to use.
4.
Click Next in the Allowed Parents and Allowed Children panels and click OK. In CRXDE Lite, click
Save All.
2.
Page 5
Created on 2014-09-05
Click Next until the Allowed Children panel of the dialog appears, and then click OK. In CRXDE Lite,
click Save All.
The structure now looks as follows:
2.
Copy the following code and paste it in contentpage.jsp after the default code:
<%@ 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.
Page 6
Created on 2014-09-05
2.
3.
In the folder tree, select the Websites folder and then click New > New Page.
In the Create Page window, enter the following:
4.
5.
6.
7.
Title: My Website
Name: mywebsite
Select the My Website Content Page Template
Click Create. In the folder tree, select the /Websites/My Website page and click New > New Page.
In the Create Page dialog, enter the following property values and then click Create:
Title: English
Name: en
Select the My Website Content Page Template
In the folder tree, select the /Websites/My Website/English page and click New> New Page.
In the Create Page dialog, enter the following property values and then click Create:
Title: Products
Select the My Website Content Page Template
8.
In the folder tree, select the /Websites/My Website/English page and click New > New Page.
9.
In the Create Page dialog, enter the following property values and then click Create:
Title: Services
Select the My Website Content Page Template
In the folder tree, select the /Websites/My Website/English page and click New > New Page.
10.
11.
In the Create Page dialog, enter the following property values and then click Create:
Title: Customers
Select the My Website Content Page Template
Your structure looks as follows:
Page 7
Created on 2014-09-05
12.
To link your pages to the mywebsite design, in CRXDE Lite, select the /content/mywebsite/en/
jcr:content node. On the Properties tab, type the following values for a new property and then click
Add:
Name: cq:designPath
Type: String
Value: /etc/designs/mywebsite
13.
Page 8
Created on 2014-09-05
2.
3.
4.
Open the page source to see the javascript and HTML elements that the head.jsp and body.jsp scripts
generated. The following script snippet opens Sidekick when you open the page:
Page 9
Created on 2014-09-05
CQ.WCM.launchSidekick("/content/mywebsite/en/products",
{propsDialog: "/libs/foundation/components/page/dialog",
locked: false locked: false
});
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
Page 10
Created on 2014-09-05
</body>
12.
13.
2.
3.
Label: topnav
Title: My Top Navigation Component
Description: This is My Top Navigation Component
Click Next until you come to the last window where you click OK. Save your changes.
2.
Replace the code that is there by copying and pasting 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));
Page 11
Created on 2014-09-05
while (children.hasNext()) {
Page child = children.next();
%><a href="<%= child.getPath() %>.html"><%=child.getTitle() %></a><%
}
}
%>
with:
<cq:include path="topnav" resourceType="mywebsite/components/topnav" />
2.
3.
In your browser, reload the Products Page. The top navigation appears as follows:
2.
3.
4.
5.
Page 12
Created on 2014-09-05
4. Sling finds the script in this component that best matches the URL selector (navimage) and file name
extension (png).
In this exercise, Sling matches these URLs to the /apps/mywebsite/components/contentpage/
navimage.png.java script that you create.
1.
In CRXDE Lite, open the topnav.jsp under /apps/mywebsite/components/topnav. Locate the content of
the anchor element (line 14):
<%=child.getTitle() %>
2.
3.
4.
Right-click the /apps/mywebsite/components/contentpage node and click Create > Create File.
5.
6.
The .java file name extension indicates to Sling that the Apache Sling Scripting Java Support should be
used to compile the script and create a servlet.
Copy the following code into navimage.png.java. The code extends the AbstractImageServlet class:
AbstractImageServlet creates an ImageContext object that stores the properties of the current
resource.
The parent page of the resource is extracted from the ImageContext object. The page title and
subtitle are then obtained.
ImageHelper is used to generate the image from the navimage_bg.jpg file of the site design, the
page title, and the page subtitle.
package apps.mywebsite.components.contentpage;
import java.awt.Color;
import java.awt.Paint;
import java.awt.geom.Rectangle2D;
import java.io.IOException;
import javax.jcr.RepositoryException;
import
import
import
import
com.day.cq.wcm.api.Page;
com.day.cq.wcm.api.PageManager;
com.day.cq.wcm.api.components.Component;
com.day.cq.wcm.api.designer.Designer;
import
import
import
import
com.day.cq.commons.SlingRepositoryException;
com.day.cq.wcm.commons.WCMUtils;
com.day.cq.wcm.commons.AbstractImageServlet;
com.day.cq.commons.ImageHelper;
import com.day.image.Font;
import com.day.image.Layer;
import
import
import
import
org.apache.sling.api.SlingHttpServletRequest;
org.apache.sling.api.SlingHttpServletResponse;
org.apache.sling.api.resource.Resource;
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 for image appearance */
Page 13
Created on 2014-09-05
int scale = 6;
int paddingX = 24;
int paddingY = 24;
Color bgColor = new Color(0x004a565c, true);
/* obtain the page title */
String title = currentPage.getTitle();
if (title == null) {
title = currentPage.getName();
}
/* format the title text */
title = title.toUpperCase();
Paint titleColor = Color.WHITE;
Font titleFont = new Font("Myriad Pro", 10 * scale, Font.BOLD);
int titleBase = 10 * scale;
/* obtain and format the page subtitle */
String subtitle = currentPage.getProperties().get("subtitle", "");
Paint subtitleColor = new Color(0xffa9afb1, true);
Font subTitleFont = new Font("Tahoma", 7);
int subTitleBase = 20;
/* create a layer that contains the background image from the mywebsite design */
Designer dg = ctx.resolver.adaptTo(Designer.class);
String imgPath = new String(dg.getDesignPath(currentPage)+"/images/navimage_bg.jpg");
Layer bg = ImageHelper.createLayer(ctx.resolver.resolve(imgPath));
/* 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);
/* ensure subtitleExtent is wide enough */
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());
/* create the text layer */
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);
}
/* merge the image and text layers */
text.setY(paddingY);
text.setX(paddingX);
text.setBackgroundColor(bgColor);
int bgWidth = bg.getWidth();
if ( text.getWidth() + 2 * paddingX > bgWidth ) {
2012 Adobe Systems Incorporated.
All rights reserved.
Page 14
Created on 2014-09-05
7.
8.
In your browser, reload the Products page. The top navigation now appears as follows:
In the folder tree of the Websites page, select the Websites/My Website/English/Products item and
click New > New Page.
2.
In the dialog enter the following property values and then click Create:
Title: Product 1.
Name: product1.
Select My Website Content Page Template
3.
Create another page below Products using the following property values:
Title: Product 2
Name: product2
Select My Website Content Page Template
4.
In CRXDE Lite, set a description and a date for the Product 1 page:
1. Select the /content/mywebsite/en/products/product1/jcr:content node.
2. In the Properties tab, enter the following values:
Name: jcr:description
Type: String
Value: This is a description of the Product 1!.
3. Click Add.
4. In the Properties tab, create another property using the following values:
Name: date
Type: String
Value: 02/14/2008
Click Add.
5. Click Save All.
5.
In CRXDE Lite, set a description and a date for the Product 2 page:
Page 15
Created on 2014-09-05
3.
Label: listchildren.
Title: My Listchildren Component.
Description: This is My Listchildren Component.
Continue clicking Next until the Allowed Children panel appears, and then click OK.
2.
3.
Page 16
Created on 2014-09-05
1.
2.
3.
4.
Select the tab1 node and click Create > Create Node, enter the following property values, and click
OK:
Name: items
Type: cq:WidgetCollection
5.
Create a node below the items node using the following property values:
Name: listroot
Type: cq:Widget
6.
Add properties for the listroot node to configure it as a text field. Each row in the following table
represents a property. When finished, click Save All.
Name
Type
Value
fieldLabel
String
name
String
./listroot
xtype
String
textfield
Page 17
Created on 2014-09-05
In CRXDE Lite, open the file left.jsp under /apps/mywebsite/components/contentpage and locate the
following code (line 4):
<div>newslist</div>
2.
3.
In your browser, reload the Products Page. The listchildren component appears as follows:
2.
3.
As Path of list root, enter: /content/mywebsite/en. Click OK. The listchildren component on your page
now looks as follows:
Page 18
Created on 2014-09-05
Your design-mode dialog contains properties for setting 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:
NOTE
3.
Label: logo.
Title: My Logo Component.
Description: This is My Logo Component.
Click Next until you reach the final panel of the dialog and then click OK.
3.
Page 19
Created on 2014-09-05
1.
2.
3.
Type
Value
fileNameParameter
String
./imageName
fileReferenceParameter
String
./imageReference
name
String
./image
title
String
Image
xtype
String
html5smartimage
com.day.cq.wcm.foundation.Image;
com.day.cq.wcm.commons.RequestHelper;
com.day.cq.wcm.commons.WCMUtils;
com.day.cq.wcm.commons.AbstractImageServlet;
com.day.cq.commons.SlingRepositoryException;
com.day.image.Layer;
org.apache.commons.io.IOUtils;
org.apache.sling.api.SlingHttpServletRequest;
org.apache.sling.api.SlingHttpServletResponse;
org.apache.sling.api.resource.Resource;
org.apache.sling.api.resource.ValueMap;
org.apache.sling.api.servlets.SlingSafeMethodsServlet;
/**
Page 20
Created on 2014-09-05
* Renders an image
*/
public class img_GET extends AbstractImageServlet {
protected Layer createLayer(ImageContext c)
throws RepositoryException, IOException {
/* don't create the layer 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);
image.setItemName(Image.NN_FILE, "image");
image.setItemName(Image.PN_REFERENCE, "imageReference");
if (!image.hasContent()) {
resp.sendError(HttpServletResponse.SC_NOT_FOUND);
return;
}
/* get pure layer */
layer = image.getLayer(false, false, false);
/* do not re-encode layer, just spool */
Property data = image.getData();
InputStream in = data.getStream();
resp.setContentLength((int) data.getLength());
String contentType = image.getMimeType();
if (contentType.equals("application/octet-stream")) {
contentType=c.requestImageType;
}
resp.setContentType(contentType);
IOUtils.copy(in, resp.getOutputStream());
in.close();
resp.flushBuffer();
}
}
In CRXDE Lite, open the left.jsp under /apps/mywebsite/components/contentpage file and locate the
following line of code:
<div>logo</div>
2.
3.
4.
With the Products page open in your browser, click the Design button at the bottom of Sidekick to enter
design mode.
2.
3.
In the Design of logo bar, click Edit to use the dialog to edit the settings for the logo component.
In the dialog, click in the panel of the Image tab, browse for the logo.png image that you extracted from
the mywebsite.zip file, and click OK.
Page 21
Created on 2014-09-05
4.
Click the triangle on the Sidekick title bar to return to Edit mode.
5.
In CRXDE Lite, go to the following node to see the stored property values:
/etc/designs/mywebsite/jcr:content/contentpage/logo
with:
<cq:include path="trail" resourceType="foundation/components/breadcrumb" />
2.
3.
with:
<cq:include path="title" resourceType="foundation/components/title" />
2.
3.
Note: You can set a different Title and the Type/Size in edit mode.
Page 22
Created on 2014-09-05
2.
Replace that line of code with the following code, then save the changes:
<cq:include path="par" resourceType="foundation/components/parsys" />
3.
In your browser, refresh the Products page. It now has the parsys component, which is seen as
follows:
5.
6.
7.
8.
Page 23
Created on 2014-09-05
1.
2.
Open /apps/mywebsite/components/image/image.jsp
Replace the existing code with the following code, then save the changes:
<%@include file="/libs/foundation/global.jsp"%><%
%><%@ page import="com.day.cq.commons.Doctype,
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" %><%
/* global.jsp provides access to the current resource through the resource object */
Image img = new Image(resource);
img.setItemName(Image.NN_FILE, "image");
img.setItemName(Image.PN_REFERENCE, "imageReference");
img.setSelector("img");
img.setDoctype(Doctype.fromRequest(request));
img.setAlt("Home");
img.draw(out); %>
3.
Type
Value
accept
String
image/(gif|jpeg|png)
groups
String
media
propertyName
String
./imageReference
Page 24
Created on 2014-09-05
3.
4.
5.
6.
2.
Replace that code with the following code, and then save the changes.
<cq:include path="toolbar" resourceType="foundation/components/toolbar"/>
3.
4.
In the folder tree of the AEM Websites page, select Websites/My Website/English, then click New >
New Page. Specify the following property values and click Create:
Title: Toolbar
Select My Website Content Page Template
In the list of pages, right-click the Toolbar page and click Properties. Select Hide In Navigation, and
click OK.
The Hide in Navigation option prevents the page from appearing in navigation components, such as
topnav and listchildren.
5.
6.
Page 25
Created on 2014-09-05
3.
4.
5.
/libs/foundation/components/search/dialog
/libs/foundation/components/search/i18n
/libs/foundation/components/search/icon.png
Click Save All.
Page 26
Created on 2014-09-05
</c:when>
<c:otherwise>
<p class="searchmeta">Results ${result.startIndex + 1} - ${result.startIndex +
fn:length(result.hits)} of ${result.totalMatches} for <b>${fn:escapeXml(search.query)}</b>.
(${result.executionTime} seconds)</p>
<br/>
<div class="searchresults">
<div class="results">
<c:forEach var="hit" items="${result.hits}" varStatus="status">
<div class="hit">
<a href="${hit.URL}">${hit.title}</a>
<div class="excerpt">${hit.excerpt}</div>
<div class="hiturl"> ${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>
</div></div>
</c:forEach>
</div>
<br/>
<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}"/>
2012 Adobe Systems Incorporated.
All rights reserved.
Page 27
Created on 2014-09-05
3.
In CRXDE Lite, open the file left.jsp under /apps/mywebsite/components/contentpage and locate the
following code (line 2):
%><div class="left">
2.
Page 28
Created on 2014-09-05
3.
4.
Replace that code with the following code, and then save the changes.
<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>
5.
In your browser, reload the Products page. The search component 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 is in a similar format as the
following:
Page 29
Created on 2014-09-05
with:
<cq:include path="rightpar" resourceType="foundation/components/iparsys" />
2.
3.
Page 30
Created on 2014-09-05