Technical Conventions
These sections that follow are samples that should be built upon to adopt to your situation. Please refer to (Conventions)[/manual/conventions/] and (Image Conventions)[/manual/image-conventions/] for more detailed descriptions of conventions that need to be considered when developing AEM components.
Reference Material
Sample JS Project Namespace
location: /etc/designs/`/js/namespace-aem-design.js
//namespace-aemdesign.js
window.AEMDESIGN = window.AEMDESIGN || {};
window.AEMDESIGN.jQuery = window.jQuery || {};
window.AEMDESIGN.$ = window.jQuery || $;
;(function ($, ns, window, undefined) { //add additional dependencies
"use strict";
var _version = "0.1";
ns.version = function () {
return _version;
};
var http = AEMDESIGN.HTTP;
$.ajaxSetup({ // necessary global modifications for ajax calls
statusCode: {
403: function(jqXHR) {
if (jqXHR.getResponseHeader("X-Reason") === "Authentication Failed") {
// login session expired: redirect to login page
http.handleLoginRedirect();
}
}
}
});
$.ajaxSettings.traditional = true;
})(AEMDESIGN.jQuery, AEMDESIGN, this); //pass in additional dependencies
Sample JS Console Log Utility Class
location: /etc/designs/aem-design/js/aem-design.log.js
//aem-design.log.js
window.AEMDESIGN = window.AEMDESIGN || {};
window.AEMDESIGN.log = window.AEMDESIGN.log || {};
(function ($, ns, window, undefined) { //add additional dependencies
//"use strict";
var _version = "0.1";
var settings = {
enableLog: false
}
ns.version = function () {
return _version;
};
ns.enableLog = function() {
settings.enableLog = true;
}
ns.disableLog = function() {
settings.enableLog = false;
}
ns.log = function (data) {
if (window.console && window.console.log) {
var url = $(location).attr('href');
var traceStack;
if (typeof printStackTrace == "function") {
traceStack = printStackTrace();
}
var debug = {
"caller": arguments.caller,
"traceStack": traceStack
};
if (settings.enableLog) {
console.log([url,data,debug]);
}
}
};
})(AEMDESIGN.jQuery, AEMDESIGN.log, this); //pass in additional dependencies
Sample JS Component Namespace
location: /apps/aemdesign/componentX/clientslibs/js.txt
#base=js
functions.js
behaviour.js
location: /apps/aemdesign/componentX/clientslibs/js/behaviour.js
//componentX - behaviour
window.AEMDESIGN = window.AEMDESIGN || {};
window.AEMDESIGN.components = AEMDESIGN.components || {};
window.AEMDESIGN.components.componentX = AEMDESIGN.components.componentX || {};
;(function($, _, ko, componentXNs, window, undefined) { //add additional dependencies
function onDocumentReady() {
console.group("loading componentX");
//init component on all found instances
var elements = document.querySelectorAll(ns.selector);
for (var i = 0; i < elements.length; i++) {
componentXNs.init($(elements[i]));
}
//init component on all future instances when they are added to the DOM
var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver;
var body = document.querySelector("body");
var observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
// needed for IE
var nodesArray = [].slice.call(mutation.addedNodes);
if (nodesArray.length > 0) {
nodesArray.forEach(function(addedNode) {
if (addedNode.querySelectorAll) {
var elementsArray = [].slice.call(addedNode.querySelectorAll(ns.selector));
elementsArray.forEach(function(element) {
componentXNs.init($(element));
});
}
});
}
});
});
observer.observe(body, {
subtree: true,
childList: true,
characterData: true
});
console.groupEnd();
}
if (document.readyState !== "loading") {
onDocumentReady();
} else {
document.addEventListener("DOMContentLoaded", onDocumentReady);
}
})(AEMDESIGN.jQuery, _, ko, AEMDESIGN.components.componentX, this); //pass in additional dependencies
location: /apps/aemdesign/componentX/clientslibs/js/functions.js
//componentX - functions
window.AEMDESIGN = window.AEMDESIGN || {};
window.AEMDESIGN.components = AEMDESIGN.components || {};
window.AEMDESIGN.components.componentX = AEMDESIGN.components.componentX || {};
;(function ($, _, ko, ns, window, undefined) { //add additional dependencies
"use strict";
var _version = "0.1";
ns.selector = "[data-modules='componentX']";
ns.version = function () {
return _version;
};
ns.init = function($el) {
return $el; //chaining
};
})(AEMDESIGN.jQuery,_,ko, AEMDESIGN.components.componentX, this); //pass in additional dependencies
Sample Health Check
package com.aem-design.health;
import java.io.IOException;
import javax.servlet.ServletException;
import org.apache.felix.scr.annotations.sling.SlingServlet;
import org.apache.felix.scr.annotations.Property;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.api.servlets.SlingAllMethodsServlet;
@SlingServlet(paths = "/bin/aem-design/health", methods = "GET", metatype = true)
@Property(name = "sling.auth.requirements", value = "-/bin/aem-design/health", propertyPrivate = true)
public class HealthServlet extends SlingAllMethodsServlet {
private static final long serialVersionUID = 636174686179L;
@Override
protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response) throws ServletException, IOException {
response.getWriter().write("AEM-OK");
}
}
Sample Adaptive Image
location: /apps/aemdesign/content/image/variant.responsive.jsp
<a href="/content/geometrixx-media/en/events/andrew-novokov.html">
<div data-picture data-alt='Interview with Russian author Andrew Novokov'>
<div data-src='/content/geometrixx-media/en/events/andrew-novokov.image.370.150.medium.jpg' data-media="(min-width: 1px)"></div>
<div data-src='/content/geometrixx-media/en/events/andrew-novokov.image.480.190.medium.jpg' data-media="(min-width: 480px)"></div>
<div data-src='/content/geometrixx-media/en/events/andrew-novokov.image.770.300.medium.jpg' data-media="(min-width: 768px)"></div>
<div data-src='/content/geometrixx-media/en/events/andrew-novokov.image.940.340.high.jpg' data-media="(min-width: 980px)"></div>
<div data-src='/content/geometrixx-media/en/events/andrew-novokov.image.1170.400.high.jpg' data-media="(min-width: 1199px)"></div>
<noscript>
<img src='/content/geometrixx-media/en/events/andrew-novokov.image.370.150.low.jpg' alt='Interview with Russian author Andrew Novokov'>
</noscript>
</div>
</a>
location: /apps/aemdesign/content/image/clientslibs/js/functions.js
$("div[data-picture]", context).each(function () {
var currentPicture = this;
var matches = [];
$("div[data-media]", currentPicture).each(function () {
var media = $(this).attr("data-media");
if (!media || ( w.matchMedia && w.matchMedia(media).matches )) {
matches.push(this);
}
});
var $picImg = $("img", currentPicture).first();
if (matches.length) {
if ($picImg.size() === 0) {
var $currentPicture = $(currentPicture);
$picImg = $("<img />").attr("alt", $currentPicture.attr("data-alt")).appendTo($currentPicture);
}
$picImg.attr("src", matches.pop().getAttribute("data-src"));
} else {
$picImg.remove();
}
});
Sample Sling Content Manipulation
Sling allows ability to automate content creation, deletion and updates.
Sling API Manipulation Manual : https://sling.apache.org/documentation/bundles/manipulating-content-the-slingpostservlet-servlets-post.html
Import UTF Characters using Sling
curl -X POST -u "admin:admin" -F"_charset_=utf-8" --form-string "text-ja=あなたが喜んで学ぶならば、誰かが喜んで教えるでしょう!。" http://localhost:4502/content/testpage/jcr:content/par/label
Leave a Comment