<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Cheesy Title</title>
    <description>Mostly stuff about Adobe Experience Manager
</description>
    <link>http://blog.justinedelson.com/</link>
    <atom:link href="http://blog.justinedelson.com/feed.xml" rel="self" type="application/rss+xml" />
    <pubDate>Wed, 27 Apr 2016 18:08:49 +0000</pubDate>
    <lastBuildDate>Wed, 27 Apr 2016 18:08:49 +0000</lastBuildDate>
    <generator>Jekyll v3.0.4</generator>
    
      <item>
        <title>Do I need to recompile my AEM code for 6.2?</title>
        <description>&lt;p&gt;With the release last week of &lt;a href=&quot;https://docs.adobe.com/docs/en/aem/6-2/release-notes.html&quot; target=&quot;_blank&quot;&gt;Adobe Experience Manager 6.2&lt;/a&gt; many developers are going to start
testing their applications on this new release. In the past, most AEM releases have been, at least at an API level, almost entirely backwards compatible, but with this release, the product management and engineering teams have taken the opportunity to remove some long-deprecated APIs. As a result, many applications will need to be either refactored or recompiled to work with AEM 6.2.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Now might be a good time to review the &lt;a href=&quot;https://docs.adobe.com/docs/en/aem/6-2/release-notes/deprecated-removed-features.html&quot; target=&quot;_blank&quot;&gt;complete list of deprecated and removed features&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You will know recompilation is necessary if, when you install your application into an AEM 6.2 instance, your bundles fail to start and the log messages complain about various unresolved dependencies. Something like:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Unable to resolve com.myco.myco-bundle [472](R 472.0):
missing requirement [com.myco.myco-bundle [472](R 472.0)]
osgi.wiring.package;
(&amp;amp;(osgi.wiring.package=com.day.cq.commons)(version&amp;gt;=5.7.0)(!(version&amp;gt;=6.0.0)))
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;blockquote&gt;
  &lt;p&gt;The actual log message is more verbose, but this is the key part.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;What this means is that the bundle &lt;code class=&quot;highlighter-rouge&quot;&gt;com.myco.myco-bundle&lt;/code&gt;, which is bundle ID 472 has a dependency on a package named &lt;code class=&quot;highlighter-rouge&quot;&gt;com.day.cq.commons&lt;/code&gt;, meaning that a bundle must be export this package. This dependency has a constraint on it which requires that the exported package’s version must be greater than or equal to 5.7.0 and less than 6.0.&lt;/p&gt;

&lt;p&gt;This constraint got that way because, in general, OSGi tooling (such as the &lt;code class=&quot;highlighter-rouge&quot;&gt;maven-bundle-plugin&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;bnd&lt;/code&gt;) will automatically generate package import constraits based on the version of the exported package on the classpath at build time and assuming that &lt;a href=&quot;https://www.osgi.org/wp-content/uploads/SemanticVersioning.pdf&quot; target=&quot;_blank&quot;&gt;Semantic Versioning&lt;/a&gt; is being followed. In this case, the package &lt;code class=&quot;highlighter-rouge&quot;&gt;com.day.cq.commons&lt;/code&gt; was exported in AEM 6.1 with the version 5.7.0.&lt;/p&gt;

&lt;p&gt;But before doing some trial and error, it is actually possible to predict whether or not these types of errors will occur by looking at the changes in package versions. If your application depends upon &lt;em&gt;any&lt;/em&gt; package which had a major version change between AEM 6.1 and 6.2, it will at minimum need to be recompiled. While every application will be different, what I have observed is that the key packages are these:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;com.day.cq.commons&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;com.day.cq.commons.jcr&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;com.day.cq.replication&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;com.day.cq.security&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;com.day.cq.workflow&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;com.day.cq.workflow.exec&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href=&quot;/assets/aem62/major-package-changes.txt&quot; target=&quot;_blank&quot;&gt;Click here&lt;/a&gt; for a list of the packages which have had major version changes between AEM 6.1 and 6.2.&lt;/p&gt;

&lt;p&gt;In addition, there are some packages which have been entirely removed. These are long-deprecated features and, in some cases, packages which were never intended to be used. These have, at least in my observations, been much less problematic for early adopters, but one to call out specifically is &lt;code class=&quot;highlighter-rouge&quot;&gt;org.apache.sling.event&lt;/code&gt;. &lt;a href=&quot;/assets/aem62/removed-packages.txt&quot; target=&quot;_blank&quot;&gt;Click here&lt;/a&gt; for the full list. If your application depends upon any of these, it will need to be refactored. To see an example of such a refactoring, you can take a look at the &lt;a href=&quot;https://github.com/Adobe-Consulting-Services/acs-aem-commons/commit/d633dd4db10dfc20cd19a89ec9aaa4b7819242c9&quot; target=&quot;_blank&quot;&gt;first set of changes made for 6.2 support in ACS AEM Commons&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;updating-the-uberjar&quot;&gt;Updating the UberJar&lt;/h2&gt;

&lt;p&gt;Assuming you need to recompile, the first thing you need to do is update your project to reference the AEM 6.2 UberJar. As documented on &lt;a href=&quot;https://docs.adobe.com/docs/en/aem/6-2/develop/dev-tools/ht-projects-maven.html&quot; target=&quot;_blank&quot;&gt;https://docs.adobe.com/docs/en/aem/6-2/develop/dev-tools/ht-projects-maven.html&lt;/a&gt;, the UberJar is available in two different versions:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;An obfuscated version which is freely available on &lt;a href=&quot;http://repo.adobe.com&quot; target=&quot;_blank&quot;&gt;repo.adobe.com&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;An unobfuscated version which can only be obtained by licensed customers and partners through Adobe Support (Daycare).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are a variety of cases when you &lt;em&gt;need&lt;/em&gt; the unobfuscated version – certain types of unit tests, certain Declarative Services use cases, etc. These are laid out in the &lt;a href=&quot;http://adobe.ly/1SKsJnB&quot; target=&quot;_blank&quot;&gt;documentation&lt;/a&gt;. It is worth noting that these use cases &lt;strong&gt;haven’t changed between AEM 6.1 and AEM 6.2&lt;/strong&gt;. In other words, if you were using the obfuscated version before, you can continue to use the obfuscated version. And if you needed the unobfuscated version, you still need it.&lt;/p&gt;

&lt;p&gt;To use the 6.2 UberJar, update the dependency in your project’s &lt;em&gt;pom.xml&lt;/em&gt; file to:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-xml&quot; data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;com.adobe.aem&lt;span class=&quot;nt&quot;&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;uber-jar&lt;span class=&quot;nt&quot;&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;version&amp;gt;&lt;/span&gt;6.2.0&lt;span class=&quot;nt&quot;&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;classifier&amp;gt;&lt;/span&gt;obfuscated-apis&lt;span class=&quot;nt&quot;&gt;&amp;lt;/classifier&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;scope&amp;gt;&lt;/span&gt;provided&lt;span class=&quot;nt&quot;&gt;&amp;lt;/scope&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Or, if you are using the unobfuscated version:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-xml&quot; data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;com.adobe.aem&lt;span class=&quot;nt&quot;&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;uber-jar&lt;span class=&quot;nt&quot;&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;version&amp;gt;&lt;/span&gt;6.2.0&lt;span class=&quot;nt&quot;&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;classifier&amp;gt;&lt;/span&gt;apis&lt;span class=&quot;nt&quot;&gt;&amp;lt;/classifier&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;scope&amp;gt;&lt;/span&gt;provided&lt;span class=&quot;nt&quot;&gt;&amp;lt;/scope&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Once this is done, simply build your application. If you have compiler errors, those are most likely due to removed packages or classes and the referencing code needs to be refactored.&lt;/p&gt;

</description>
        <pubDate>Wed, 27 Apr 2016 00:00:00 +0000</pubDate>
        <link>http://blog.justinedelson.com/2016/04/27/recompile-code-for-aem62.html</link>
        <guid isPermaLink="true">http://blog.justinedelson.com/2016/04/27/recompile-code-for-aem62.html</guid>
        
        
      </item>
    
      <item>
        <title>ACS AEM Commons 2.4.2 and 3.0.2 Released</title>
        <description>&lt;p&gt;I’m pleased to announce the release of ACS AEM Commons 2.4.2 and 3.0.2.&lt;/p&gt;

&lt;p&gt;This is a significant release in this project’s history as we are now doing dual releases for compatibility between AEM 6.0, 6.1, and 6.2. As described in &lt;a href=&quot;/2016/04/27/recompile-code-for-aem62.html&quot; target=&quot;_blank&quot;&gt;this blog post&lt;/a&gt;, there are a variety of non-backwards compatible changes in Java packages between AEM 6.1 and 6.2 which requires that many projects, including ACS AEM Commons be recompiled.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;If you are using 6.0 or 6.1, you will need to use versions in the 2.x line, 2.4.2 in this case. If you are using 6.2, you need to use versions in the 3.x line, 3.0.4 in this case.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We expect to maintain this dual version release process for a while, based on user feedback.&lt;/p&gt;

&lt;p&gt;Aside from 6.2 compatibility, there are some new features in this release:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://adobe-consulting-services.github.io/acs-aem-commons/features/fast-action-manager.html&quot; target=&quot;_blank&quot;&gt;Fast Action Manager&lt;/a&gt; - A fluent API for parallization of synthetic workflows, replication and more.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://adobe-consulting-services.github.io/acs-aem-commons/features/path-rendercondition.html&quot; target=&quot;_blank&quot;&gt;Path-Based Render Condition&lt;/a&gt; - An implementation of the Granite UI Render Condition pattern which makes it easy to show and hide UI elements based on content paths.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There’s also the usual assortment of bug fixes and minor enhancements.&lt;/p&gt;

&lt;p&gt;Thanks to the following individuals for their contributions, complaints, ideas, and support:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;David Gonzalez (Adobe)&lt;/li&gt;
  &lt;li&gt;Brendan Robert (Adobe)&lt;/li&gt;
  &lt;li&gt;Kaushal Mall (Adobe)&lt;/li&gt;
  &lt;li&gt;Chris Pilsworth (Adobe)&lt;/li&gt;
  &lt;li&gt;Sreekanth Nalabotu (Adobe)&lt;/li&gt;
  &lt;li&gt;Steffen Roesinger (Adobe)&lt;/li&gt;
  &lt;li&gt;Johnny Yang (BizTech)&lt;/li&gt;
  &lt;li&gt;Dominik Förderreuther (Adobe)&lt;/li&gt;
  &lt;li&gt;Joseph Rignanese (Adobe)&lt;/li&gt;
  &lt;li&gt;Florian Brunswicker (Adobe)&lt;/li&gt;
  &lt;li&gt;Simo Tripodi (Adobe)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As always, while this projects are primarily produced and distributed within Adobe Consulting Services, it is available for usage by other Adobe groups, customers and partners. Contributions and feature suggestions from those groups are also most welcome. More information about this project, including detailed information about the included features, can be found &lt;a href=&quot;http://adobe-consulting-services.github.io/acs-aem-commons/&quot; target=&quot;_blank&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
</description>
        <pubDate>Wed, 27 Apr 2016 00:00:00 +0000</pubDate>
        <link>http://blog.justinedelson.com/2016/04/27/acs-aem-commons-242-release-announcement.html</link>
        <guid isPermaLink="true">http://blog.justinedelson.com/2016/04/27/acs-aem-commons-242-release-announcement.html</guid>
        
        
      </item>
    
      <item>
        <title>Adding JavaScript Functions for Sightly to Use</title>
        <description>&lt;p&gt;One of the great aspects of the addition of Sightly to Adobe Experience Manager is that it allows for standard web technologies (HTML, JavaScript) to be used to build AEM components, something which used to require a knowledge of Java Server Pages (JSP) even for the simplest of components. Structurally, an AEM Sightly template (an HTML page) can invoke a corresponding JavaScript script, called a &lt;em&gt;Use&lt;/em&gt; object.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;You can read more about how to use JavaScript Use objects in the &lt;a href=&quot;https://docs.adobe.com/docs/en/aem/6-1/develop/sightly/use-api-in-javascript.html&quot;&gt;AEM Documentation&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;JavaScript Use objects can do just about anything, but they are best suited to doing view-related data manipulation. For anything which is starting to look like complex business logic, you are going to want to refactor that into Java code, either a Java Use object, OSGi services, or a combination of both.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;There’s a brief description of the pros and cons of the Java and JavaScript Use APIs &lt;a href=&quot;http://adobe.ly/1PBYo6n&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But let’s say you started with a JavaScript Use object and then “outgrew” it and now need to integrate some backend services. One way of approaching that is to invoke Java methods from inside your Use object. The implementation of Sightly used in AEM uses the Mozilla Rhino project’s implementation of JavaScript and Rhino provides a high level of interoperability between &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Mozilla/Projects/Rhino/Scripting_Java&quot;&gt;Java and JavaScript&lt;/a&gt;. But this can get a bit verbose. For example, a Use object which gets a list of AEM Assets tagged with a particular tag would look something like this:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;nx&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;tagManager&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;resourceResolver&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;adaptTo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Packages&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;com&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;day&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;cq&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;tagging&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;TagManager&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;tags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;java&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;lang&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;reflect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;newInstance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;java&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;lang&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;taggedResources&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;taggedAssets&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[],&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;resource&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        
    &lt;span class=&quot;nx&quot;&gt;tags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;marketing:interest/product&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;taggedResources&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;tagManager&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;/content/dam&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;tags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;taggedResources&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;hasNext&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;resource&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;taggedResources&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;resource&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;metadata&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;nx&quot;&gt;taggedAssets&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;resource&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;parent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;parent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;adaptTo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;com&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;day&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;cq&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;dam&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Asset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;assets&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;taggedAssets&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;blockquote&gt;
  &lt;p&gt;For the purpose of illustration, I’m hard coding the tag identifier, although in a real case, you’d likely read this property from the current resource’s properties.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This isn’t awful, but by needing to reference Java class names in our JavaScript code (not to mention the need to create a new instance of an array via reflection) means that we are pretty much back to the state we were with JSPs – component developers need to know some Java specifics in order to write a component. This code would also be pretty hard to unit test.&lt;/p&gt;

&lt;p&gt;A different approach would be to further encapsulate this into an OSGi service and then invoke that service from your Use object with something like:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;nx&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;taggedAssetFinder&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;sling&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;getService&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Packages&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;com&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;myco&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;assets&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;TaggedAssetFinder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;assets&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;taggedAssetFinder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;resourceResolver&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;marketing:interest/product&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This is a lot better, but what I want to illustrate is a different technique which removes all references to Java classes from our code by injecting a custom object into the scope of the Use object. Specifically we’re going to inject a function into the scope so that this code instead becomes:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;nx&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;assets&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;findTaggedAssets&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;marketing:interest/product&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;For this, we’re going to use a relatively under-used, but very cool&lt;sup id=&quot;fnref:2&quot;&gt;&lt;a href=&quot;#fn:2&quot; class=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; Sling feature – the &lt;code class=&quot;highlighter-rouge&quot;&gt;BindingsValuesProvider&lt;/code&gt;. When a script is invoked by the Sling scripting engine as part of request processing&lt;sup id=&quot;fnref:1&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt; an object is created to store the list of global variables – the request, the current resource, and so on. This object is called the script bindings and is an instance of &lt;code class=&quot;highlighter-rouge&quot;&gt;javax.script.Bindings&lt;/code&gt;, a class defined in the &lt;a href=&quot;https://docs.oracle.com/javase/8/docs/technotes/guides/scripting/prog_guide/api.html&quot;&gt;Java Scripting API&lt;/a&gt;. The Sling scripting engine itself only adds a handful of global variables (listed &lt;a href=&quot;https://sling.apache.org/apidocs/sling6/org/apache/sling/api/scripting/SlingBindings.html&quot;&gt;here&lt;/a&gt;); applications built on top of Sling, including AEM, are able to add additional global variables. This is how, for example, the &lt;code class=&quot;highlighter-rouge&quot;&gt;currentPage&lt;/code&gt; object is made available to scripts.&lt;/p&gt;

&lt;p&gt;There are two ways to use this feature – an easy way and a less easy way. The easy way is that you can register an OSGi service using the &lt;code class=&quot;highlighter-rouge&quot;&gt;java.util.Map&lt;/code&gt; interface and having a service property named &lt;code class=&quot;highlighter-rouge&quot;&gt;javax.script.name&lt;/code&gt;. When Sling executes a script, it gets all of these services and adds their contents to the &lt;code class=&quot;highlighter-rouge&quot;&gt;Bindings&lt;/code&gt; object which will be passed to the script engine. This way is useful for when are adding an object which doesn’t require access to any of the existing bindings. For example, if we wanted to make the Java runtime version available as a global variable named &lt;code class=&quot;highlighter-rouge&quot;&gt;javaVersion&lt;/code&gt; we could do something like this:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;nd&quot;&gt;@Component&lt;/span&gt;
&lt;span class=&quot;nd&quot;&gt;@Service&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Map&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nd&quot;&gt;@Property&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;javax.script.name&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;any&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;JavaVersionBVP&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;HashMap&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Object&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;JavaVersionBVP&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;put&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;javaVersion&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getProperty&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;java.runtime.version&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;));&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;blockquote&gt;
  &lt;p&gt;The value &lt;code class=&quot;highlighter-rouge&quot;&gt;any&lt;/code&gt; for the property &lt;code class=&quot;highlighter-rouge&quot;&gt;javax.script.name&lt;/code&gt; indicates that this additional variable should be applied to any scripting language. If you only wanted to scope this to certain languages, the value would be the script engine name as we’ll see below.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now in a Sightly template, we can simply write:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;Currently running Java ${javaVersion}.&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;And see the value of that system property.&lt;/p&gt;

&lt;p&gt;The less easy way is when we need access to objects from the current bindings. For this, you implement the interface &lt;code class=&quot;highlighter-rouge&quot;&gt;org.apache.sling.scripting.api.BindingsValuesProvider&lt;/code&gt;. This interface has a single method, &lt;code class=&quot;highlighter-rouge&quot;&gt;addBindings&lt;/code&gt; which is passed the current &lt;code class=&quot;highlighter-rouge&quot;&gt;Bindings&lt;/code&gt; object. This allows you to get access to the current request, response, resource, and so on. Sling calls these services in the order of their OSGi service ranking, so you can ensure access to variables created by other &lt;code class=&quot;highlighter-rouge&quot;&gt;BindingsValuesProvider&lt;/code&gt;s as well.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;A warning about performance - these BindingsValuesProviders get invoked on every script call, so you need to be very careful implementing them to ensure that they are performant. Use some kind of lazy loading or deferred invocation pattern wherever possible.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So now that we know how to add global variables, how do we create a new JavaScript function? As I mentioned above, the current implementation of Sightly uses the Rhino JavaScript implementation. Rhino provides a mechanism for new JavaScript functions to be defined &lt;em&gt;in Java&lt;/em&gt; using the &lt;code class=&quot;highlighter-rouge&quot;&gt;org.mozilla.javascript.Function&lt;/code&gt; interface, although in practice you will most likely use the &lt;code class=&quot;highlighter-rouge&quot;&gt;org.mozilla.javascript.BaseFunction&lt;/code&gt; base class. There’s really a single method you need to implement, named &lt;code class=&quot;highlighter-rouge&quot;&gt;call&lt;/code&gt; (JavaDoc &lt;a href=&quot;http://bit.ly/rhino-function-javadoc&quot;&gt;here&lt;/a&gt;) which gets invoked when the function is… called. This method gets invoked with four parameters:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;context&lt;/code&gt; - this is the Rhino scripting context associated with the current thread. It has some utility methods for doing type conversions and working with the current thread.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;scope&lt;/code&gt; - the current JavaScript scope object.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;thisObj&lt;/code&gt; - the value of &lt;code class=&quot;highlighter-rouge&quot;&gt;this&lt;/code&gt; when the function is executed. In Sightly Use objects, &lt;code class=&quot;highlighter-rouge&quot;&gt;scope&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;thisObj&lt;/code&gt; will always be identical.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;args&lt;/code&gt; - an argument array.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If your function’s arguments are booleans, numbers or strings, they will be passed as part of the &lt;code class=&quot;highlighter-rouge&quot;&gt;args&lt;/code&gt; array as their corresponding Java type (the wrapper type for primitives, &lt;code class=&quot;highlighter-rouge&quot;&gt;java.lang.String&lt;/code&gt; for strings). If however, they are JavaScript objects or other Java objects, the &lt;code class=&quot;highlighter-rouge&quot;&gt;args&lt;/code&gt; array will contain instances of these classes:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;org.mozilla.javascript.NativeArray&lt;/code&gt; - represents a JavaScript array in Java.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;org.mozilla.javascript.NativeObject&lt;/code&gt; - represents a JavaScript object in Java.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;org.mozilla.javascript.NativeJavaObject&lt;/code&gt; - represents a Java object passed via JavaScript. The &lt;code class=&quot;highlighter-rouge&quot;&gt;unwrap&lt;/code&gt; method can be called to access the original Java object.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Putting this all together, we can write a function to get the tagged assets:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;FindTaggedAssetsFunction&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BaseFunction&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ResourceResolver&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;resourceResolver&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FindTaggedAssetsFunction&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ResourceResolver&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;resourceResolver&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;resourceResolver&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;resourceResolver&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;nd&quot;&gt;@Override&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Object&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Context&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cx&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Scriptable&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;scope&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Scriptable&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;thisObj&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Object&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Undefined&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;instance&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tagId&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;];&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Asset&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;assets&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ArrayList&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Asset&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;();&lt;/span&gt;

        &lt;span class=&quot;n&quot;&gt;TagManager&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tagManager&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;resourceResolver&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;adaptTo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TagManager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;RangeIterator&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Resource&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;resources&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tagManager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;/content/dam&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tagId&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;resources&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;hasNext&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;())&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;Resource&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;resources&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getName&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;equals&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;metadata&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;Asset&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;asset&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getParent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getParent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;adaptTo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Asset&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;assets&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;asset&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
            &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;NativeArray&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;assets&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;toArray&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;());&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This code gets the tag identifier from the &lt;code class=&quot;highlighter-rouge&quot;&gt;args&lt;/code&gt; array and then interacts with the &lt;code class=&quot;highlighter-rouge&quot;&gt;TagManager&lt;/code&gt; and assets API to obtain the proper list of assets. It then wraps that list of assets into a &lt;code class=&quot;highlighter-rouge&quot;&gt;NativeArray&lt;/code&gt; so that the JavaScript engine understands it as an array and not just a Java object.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Strictly speaking, because Sightly is able to iterate over &lt;code class=&quot;highlighter-rouge&quot;&gt;java.util.List&lt;/code&gt; objects, we don’t necessarily need the wrapping of the list into a &lt;code class=&quot;highlighter-rouge&quot;&gt;NativeArray&lt;/code&gt;, but this would be important if the array was going to be used elsewhere in our JavaScript Use object.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The corresponding &lt;code class=&quot;highlighter-rouge&quot;&gt;BindingsValuesProvider&lt;/code&gt; implementation would be:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;nd&quot;&gt;@Component&lt;/span&gt;
&lt;span class=&quot;nd&quot;&gt;@Service&lt;/span&gt;
&lt;span class=&quot;nd&quot;&gt;@Property&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;javax.script.name&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;sightly&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;FindTaggedAssetsFunctionBVP&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BindingsValuesProvider&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;nd&quot;&gt;@Override&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;addBindings&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Bindings&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bindings&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;SlingHttpServletRequest&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;SlingHttpServletRequest&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bindings&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;SlingBindings&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;REQUEST&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;request&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;bindings&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;put&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;findTaggedAssets&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FindTaggedAssetsFunction&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getResourceResolver&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;());&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;I hope you have found this post enlightening and adds a new tool to your AEM development arsenal.&lt;/p&gt;

&lt;p&gt;The code in this post can be found on &lt;a href=&quot;https://github.com/justinedelson/sample-sightly-function&quot;&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;div class=&quot;footnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:2&quot;&gt;
      &lt;p&gt;I will admit to being biased because I originally added this feature to Sling. &lt;a href=&quot;#fnref:2&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:1&quot;&gt;
      &lt;p&gt;Or other contexts, but for the purpose of this post, we are just talking about request processing. &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
        <pubDate>Mon, 18 Jan 2016 00:00:00 +0000</pubDate>
        <link>http://blog.justinedelson.com/2016/01/18/adding-javascript-functions-for-sightly-to-use.html</link>
        <guid isPermaLink="true">http://blog.justinedelson.com/2016/01/18/adding-javascript-functions-for-sightly-to-use.html</guid>
        
        <category>aem</category>
        
        <category>sightly</category>
        
        
      </item>
    
      <item>
        <title>Tracking Clicks in the AEM Interactive Video Viewer</title>
        <description>&lt;p&gt;AEM Assets includes a great feature called Interactive Video which allows for videos to be easily enhanced with links. While this is primarily intended for commerce use cases, it can be used for education, promotions, or really any case where you want to easily link a video to other content. You can read more about this feature in the &lt;a href=&quot;https://docs.adobe.com/docs/en/aod/overview/working-with-assets/dynamic-media/interactive-videos.html&quot;&gt;Documentation&lt;/a&gt; and watch a great video walkthrough &lt;a href=&quot;https://outv.omniture.com?v=s4NHQ2dzqd7hIqWjeG2sIdyNWsTWyupA&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Interactive Video supports two different types of links: quickviews and hyperlinks. Quickviews are designed allow the user to see further information such as product details and even add a product to their cart without navigating away from the current page. Hyperlinks are simple hyperlinks which can either open a new browser tab or navigate in the current tab.&lt;/p&gt;

&lt;p&gt;Links are displayed in two separate contexts. While the video is playing, they are displayed in a sidebar. These links are context-sensitive, meaning that the links associated with the current video segment are displayed.&lt;sup id=&quot;fnref:1&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; Upon completion of the video, all links are also displayed in a Call to Action screen.&lt;/p&gt;

&lt;p&gt;In this post, I’ll describe how to add reporting calls so that you can track how many users are clicking on these links as well as in which context (sidebar or Call to Action). For the purpose of this post, I’m using Adobe’s &lt;a href=&quot;http://www.adobe.com/marketing-cloud/web-analytics.html&quot;&gt;Analytics&lt;/a&gt; and Adobe &lt;a href=&quot;http://www.adobe.com/solutions/digital-marketing/dynamic-tag-management.html&quot;&gt;Dynamic Tag Management&lt;/a&gt; services, but the process would be the same for any analytics/tag management solution.&lt;/p&gt;

&lt;p&gt;You can see this code in action on &lt;a href=&quot;/demos/interactive-video.html&quot;&gt;this demo page&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;register-event-listeners&quot;&gt;Register Event Listeners&lt;/h2&gt;

&lt;p&gt;The first thing we have to do is register some event listeners. In the code below &lt;code class=&quot;highlighter-rouge&quot;&gt;videoViewer&lt;/code&gt; is an instance of the JavaScript class &lt;code class=&quot;highlighter-rouge&quot;&gt;s7viewers.InteractiveVideoViewer&lt;/code&gt; created as part of the Interactive Video embed code. As part of the initialization code for the viewer, &lt;code class=&quot;highlighter-rouge&quot;&gt;videoViewer&lt;/code&gt;’s &lt;code class=&quot;highlighter-rouge&quot;&gt;setHandlers()&lt;/code&gt; method is called with a list of event handlers. In the &lt;code class=&quot;highlighter-rouge&quot;&gt;initComplete&lt;/code&gt; handler, we can get access to two of the components within the viewer and register event listeners for user interactions. These two components &lt;code class=&quot;highlighter-rouge&quot;&gt;interactiveSwatches&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;interactiveThumbnailGridView&lt;/code&gt; correspond to the sidebar and Call to Action end slates respectively. In this case, we use the same listener for both events&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;s2&quot;&gt;&quot;initComplete&quot;&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; 
  &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;interactiveSwatches&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;videoViewer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;getComponent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;interactiveSwatches&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;callToAction&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;videoViewer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;getComponent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;interactiveThumbnailGridView&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; 

  &lt;span class=&quot;nx&quot;&gt;interactiveSwatches&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;s7sdk&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;UserEvent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;NOTF_USER_EVENT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;onUserEvent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;callToAction&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;s7sdk&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;UserEvent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;NOTF_USER_EVENT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;onUserEvent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;user-interaction-event-listener&quot;&gt;User Interaction Event Listener&lt;/h2&gt;

&lt;p&gt;The event listener (&lt;code class=&quot;highlighter-rouge&quot;&gt;onUserEvent&lt;/code&gt; in this case) is responsible for setting the proper variables in the data layer and then firing a DTM Direct Call Rule. As a data layer, we are using a global JavaScript object named &lt;code class=&quot;highlighter-rouge&quot;&gt;digitalData&lt;/code&gt;. The &lt;code class=&quot;highlighter-rouge&quot;&gt;event&lt;/code&gt; child object has these properties:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;link&lt;/code&gt; - the link the user clicked on. Will either be a URL in the case of a hyperlink or a query-string style (e.g. sku=12345) collection of key/value pairs in the case of a quickview.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;linkType&lt;/code&gt; - either &lt;code class=&quot;highlighter-rouge&quot;&gt;hyperlink&lt;/code&gt; or &lt;code class=&quot;highlighter-rouge&quot;&gt;quickview&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;location&lt;/code&gt; - either &lt;code class=&quot;highlighter-rouge&quot;&gt;sidebar&lt;/code&gt; or &lt;code class=&quot;highlighter-rouge&quot;&gt;cta&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Note that we could have used two separate event listeners, but since the link parsing logic is the same in both cases, it made more sense to reuse the event handler and just have some conditional logic to specify the &lt;code class=&quot;highlighter-rouge&quot;&gt;location&lt;/code&gt; property based on the event type.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;onUserEvent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;trackLink&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;eventData&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{};&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;s7event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;typeof&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;s7event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;string&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;

        &lt;span class=&quot;nx&quot;&gt;eventData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;link&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;s7event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;eventData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;linkType&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;hyperlink&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;eventData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;link&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;indexOf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;quickview&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;nx&quot;&gt;eventData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;linkType&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;quickview&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;nx&quot;&gt;eventData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;link&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;eventData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;link&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;substring&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// strip off &#39;quickview:&#39;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;s7event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;trackEvent&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;s7sdk&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;UserEvent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;INTERACTIVE_SWATCH&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;nx&quot;&gt;eventData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;location&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;sidebar&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;nx&quot;&gt;trackEvent&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;s7event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;trackEvent&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;s7sdk&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;UserEvent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;INTERACTIVE_THUMBNAIL_GRID_VIEW_SWATCH&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;nx&quot;&gt;eventData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;location&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;cta&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;nx&quot;&gt;trackEvent&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;trackEvent&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;_satellite&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;nx&quot;&gt;digitalData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;eventData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;nx&quot;&gt;_satellite&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;track&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;video-click&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;            
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;dtm-data-elements&quot;&gt;DTM Data Elements&lt;/h2&gt;

&lt;p&gt;In DTM, we have some &lt;a href=&quot;http://blogs.adobe.com/digitalmarketing/analytics/getting-started-dtm-data-elements/&quot;&gt;Data Elements&lt;/a&gt; set up to extract these variables from the data layer so that they can be passed easily to Analytics. For each of the properties of the global &lt;code class=&quot;highlighter-rouge&quot;&gt;digitalData.event&lt;/code&gt; object, we have a corresponding Data Element. Since the value of this object will change during the lifespan of this page (i.e. if a user clicks on multiple images), each Data Element uses the Custom Script type.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/article_images/2016-01-07-tracking-interactivity-in-video-player/data-element.png&quot; alt=&quot;DTM Data Element&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The script for each one is simple returning the appropriate value:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;digitalData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;linkType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;dtm-direct-call-rule&quot;&gt;DTM Direct Call Rule&lt;/h2&gt;

&lt;p&gt;Finally, we can create a DTM &lt;a href=&quot;http://webanalyticsfordevelopers.com/2015/11/03/direct-call-rules-what-are-they-good-for/&quot;&gt;Direct Call Rule&lt;/a&gt;&lt;sup id=&quot;fnref:2&quot;&gt;&lt;a href=&quot;#fn:2&quot; class=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt; which fires the desired Analytics event when a user clicks on one of these images. We use the Data Elements created above to map to 3 separate eVars&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/article_images/2016-01-07-tracking-interactivity-in-video-player/evars.png&quot; alt=&quot;DTM Data Element&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Once all of the pieces are in place, clicking on any of the images in the sidebar or the end slate causes an Analytics call with the proper values passed as the eVars.&lt;/p&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;With a little bit of JavaScript additions, we can add click tracking to AEM’s Interactive Video viewers so that we know how many users are clicking on which of the links in our viewers.&lt;/p&gt;

&lt;div class=&quot;footnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot;&gt;
      &lt;p&gt;Depending on the size on the player and the number of links associated with the current segment, links associated with other segments may also be displayed. &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:2&quot;&gt;
      &lt;p&gt;While a DTM Event Based Rule could be fired based on the click, the link data is not easily accessible, so a Direct Call Rule is more effective. &lt;a href=&quot;#fnref:2&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
        <pubDate>Mon, 11 Jan 2016 00:00:00 +0000</pubDate>
        <link>http://blog.justinedelson.com/2016/01/11/tracking-clicks-in-video-viewer.html</link>
        <guid isPermaLink="true">http://blog.justinedelson.com/2016/01/11/tracking-clicks-in-video-viewer.html</guid>
        
        <category>aem</category>
        
        <category>assets</category>
        
        
      </item>
    
      <item>
        <title>Does AEM Apps Require AngularJS?</title>
        <description>&lt;p&gt;TL;DR: No.&lt;/p&gt;

&lt;p&gt;In talking with customers and partners about AEM Apps, one of the most frequently asked questions I hear is “If I want to build a hybrid mobile app with AEM Apps, do I need to use AngularJS?” Or sometimes this gets phrased as “Why do I need to use AngularJS to build hybrid apps with AEM Apps?” Or even “Why are you guys so in love with AngularJS? We’d rather use &amp;lt;fill in the blank&amp;gt;.” So let me start by saying that no, there’s no requirement to use AngularJS for hybrid app development with AEM Apps. There was one place where using AngularJS was highly beneficial, but that’s actually not the case anymore and I’ll come back to this later.&lt;/p&gt;

&lt;p&gt;So where did this misconception come from? First and foremost, it comes from the pretty obvious fact that the hybrid sample application we ship with AEM Apps (Geometrixx Outdoors) uses AngularJS. And we do provide some specific utilities for building and exporting AngularJS views into a hybrid application. But the sample app is just that – a sample and those utilities are specifically there to make AngularJS application management easier. Neither is meant to suggest a &lt;strong&gt;requirement&lt;/strong&gt; to use AngularJS. At the end of the day (or, in this case, the beginning of the day), we had to choose something. If we chose ReactJS, odds are we would have this same misconception, just about ReactJS instead of AngularJS.&lt;/p&gt;

&lt;p&gt;So no, you don’t have to use AngularJS.&lt;/p&gt;

&lt;p&gt;Except for one little thing…&lt;/p&gt;

&lt;p&gt;With the version of AEM Apps available with the AEM 6.1 release this year, even if the application itself didn’t use AngularJS, the splash screen (the screen displayed for the brief window of time when the application is initializing) did use AngularJS. And whereas customer applications could write their own splash screen JavaScript code, that probably wouldn’t be a high priority item. However, that has recently changed.&lt;/p&gt;

&lt;p&gt;A few weeks ago, Adobe release &lt;a href=&quot;https://www.adobeaemcloud.com/content/marketplace/marketplaceProxy.html?packagePath=/content/companies/public/adobe/packages/cq610/featurepack2/cq-6.1.0-apps-featurepack&quot;&gt;AEM 6.1 Apps Feature Pack 2&lt;/a&gt;. The high profile features in this feature pack are &lt;a href=&quot;http://adobe.ly/1VSQaKl&quot;&gt;Deep Links for Push Messaging&lt;/a&gt; and &lt;a href=&quot;http://adobe.ly/1VSQfOk&quot;&gt;App Templates&lt;/a&gt;. Less heralded, but interesting for the question posed in this entry’s title is a new PhoneGap plugin – the Content Sync Phonegap plugin. This replaces a combination of JavaScript code and the Chromium Zip Cordova plugin with a single point of entry. The end result is reduced client-side code (thereby making the removal of AngularJS easy) and a significant performance boost, about 10x on Android and 2x on iOS.&lt;/p&gt;

&lt;p&gt;If you have already built a hybrid app using AEM Apps, updating it to use the new Content Sync plugin is simply a matter of adding the new plugin to your config.xml file and updating a few client library references. Examples of the changes can be found &lt;a href=&quot;https://github.com/justinedelson/pgehello/commit/7e04e8a724d9601aed5101aab4064700d109c2cb&quot;&gt;here&lt;/a&gt; and &lt;a href=&quot;https://github.com/blefebvre/aem-phonegap-kitchen-sink/commit/339039128956aa2fbb2ff89e0405a3d9772874a8&quot;&gt;here&lt;/a&gt;. I’ve also updated my &lt;a href=&quot;https://github.com/justinedelson/pgehello/blob/master/anatomy.md&quot;&gt;Anatomy of a Hello World App document&lt;/a&gt; (described here) to reflect these changes.&lt;/p&gt;

&lt;p&gt;With the release of Feature Pack 2, we should remove any doubt that you &lt;strong&gt;must&lt;/strong&gt; use AngularJS with AEM Apps. And if you still have doubts, let me know in the comments and we’ll try to clear up any outstanding misconceptions.&lt;/p&gt;
</description>
        <pubDate>Wed, 14 Oct 2015 00:00:00 +0000</pubDate>
        <link>http://blog.justinedelson.com/2015/10/14/does-aem-apps-require-angular-js.html</link>
        <guid isPermaLink="true">http://blog.justinedelson.com/2015/10/14/does-aem-apps-require-angular-js.html</guid>
        
        <category>aem</category>
        
        <category>mobile</category>
        
        
      </item>
    
      <item>
        <title>Hello World for AEM Apps - What? Why?</title>
        <description>&lt;p&gt;In recent weeks, I’ve been working on a small project to publish a “Hello World” mobile application using AEM Apps. That’s now done, and visible at &lt;a href=&quot;https://github.com/justinedelson/pgehello&quot;&gt;https://github.com/justinedelson/pgehello&lt;/a&gt;, but I also wanted to write up a bit of background on why I did this and how it might be useful to others. First, a bit of background. AEM Apps is a solution within the best-in-class Adobe Experience Manager digital experience management platform focused on mobile application development and management. At its essence, AEM Apps allows for the same separation of concerns which AEM Sites (and before that CQ) has done for websites, namely to allow developers to create a set of components and templates which marketers can then use to build and update digital experiences. And let me stress update here as that’s really where AEM Apps (and in fact AEM in general) shines – the ability for non-technical users to change the content of a mobile application without developer/IT intervention and without resubmitting applications to the various app stores. There’s more to AEM Apps than just this, which you can read all about at &lt;a href=&quot;http://www.adobe.com/marketing-cloud/enterprise-content-management/mobile-app-management.html&quot;&gt;http://www.adobe.com/marketing-cloud/enterprise-content-management/mobile-app-management.html&lt;/a&gt;. AEM Apps supports a variety of application types: hybrid (using Adobe’s PhoneGap), native (using either embedded web views or direct integration with AEM for content synchronization), and digital publications (using Adobe’s Digital Publishing Solution). For the purpose of this project, my focus was on a hybrid/PhoneGap Enterprise application.&lt;/p&gt;

&lt;p&gt;In tradition (&lt;a href=&quot;https://open.spotify.com/track/5O6seBChHx7oBtY1rVxRer&quot;&gt;Tradition!&lt;/a&gt;), a Hello World application simply outputs the text “Hello World” to the console. There are a variety of ways to generate Hello World applications for PhoneGap (or other mobile development systems). But for AEM Apps, this really doesn’t capture the spirit of what the solution can do. So I took a bit of creative license with the definition of a Hello World application in two significant ways. First, rather than just being an application containing static text, the text in the application is authorable and updatable over the air. So while the application outputs “Hello World” if you simply install it from GitHub, you can also change this text using the AEM authoring interface and get the updated text in the application over the air. You can also add images and again, get those updates over the air. Second, this application is integrated with Adobe Mobile Services. This is an optional, but highly recommended, integration for AEM Apps which provides rich application analytics and in-app messaging.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/article_images/2015-09-29-hello-world-for-aem-apps/action-paths.png&quot; alt=&quot;Action Paths in Adobe Mobile Services&quot; /&gt;&lt;/p&gt;

&lt;p&gt;So, why create a Hello World application in AEM Apps? In general, I’ve found there are two different ways in which we learn something new, specifically software development, but it true in other areas in life. These are taking something pre-built apart (and putting it back together) and building something up from nothing. Personally, I tend to prefer the latter. I think this probably comes from when I started programming 30 years ago by copying BASIC programs out of magazines line by line, making typos, fixing them, making more typos, etc. etc. Now we’d call that ‘iterative’ I guess. To bring this back to AEM Apps, the Apps development team has a “Starter Kit” available on GitHub at &lt;a href=&quot;https://github.com/adobe-marketing-cloud/aem-phonegap-starter-kit&quot;&gt;https://github.com/adobe-marketing-cloud/aem-phonegap-starter-kit&lt;/a&gt; for jumpstarting AEM Apps projects. For most projects, the Starter Kit is the right place to start. But for the purpose of building something up from the ground, there’s a bit too much magic in the Starter Kit.&lt;/p&gt;

&lt;p&gt;There was a second goal, which is perhaps more important than the actual Hello World application project itself, which was to create an Anatomy document, visible at &lt;a href=&quot;https://github.com/justinedelson/pgehello/blob/master/anatomy.md&quot;&gt;https://github.com/justinedelson/pgehello/blob/master/anatomy.md&lt;/a&gt;. This document describes, in detail, each file in the project and what it does. This was actually much more time consuming that building the application itself as I wanted to ensure that no stone was left unturned. It clocks in at 13 pages. And since the Hello World application is a subset of the Starter Kit (and thus any application based on the Starter Kit), everything in it would apply to the Starter Kit as well.&lt;/p&gt;

&lt;p&gt;If you’re interested in AEM Apps development, I’d recommend checking out this project and let me know if you have any questions, either in the comments, GitHub Issues, or by tweeting &lt;a href=&quot;http://www.twitter.com/justinedelson&quot;&gt;@justinedelson&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Now get to building some apps!&lt;/p&gt;
</description>
        <pubDate>Tue, 29 Sep 2015 00:00:00 +0000</pubDate>
        <link>http://blog.justinedelson.com/2015/09/29/hello-world-for-aem-apps.html</link>
        <guid isPermaLink="true">http://blog.justinedelson.com/2015/09/29/hello-world-for-aem-apps.html</guid>
        
        <category>aem</category>
        
        <category>mobile</category>
        
        
      </item>
    
      <item>
        <title>ACS AEM Commons 2.0.0 Released</title>
        <description>&lt;p&gt;I’m pleased to announce the release of ACS AEM Commons 2.0.0&lt;/p&gt;

&lt;p&gt;This is a significant release in that we are &lt;strong&gt;removing&lt;/strong&gt; support for AEM 5.6.1. For this release (and any future releases in the 2.x line), AEM 6.0 is considered the minimum platform.&lt;/p&gt;

&lt;p&gt;New Features in ACS AEM Commons 2.0.0 include:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://adobe-consulting-services.github.io/acs-aem-commons/features/icon-picker.html&quot;&gt;Font Awesome Icon Picker&lt;/a&gt; widget (for both Classic and Touch UI)&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://adobe-consulting-services.github.io/acs-aem-commons/features/authorizable-packager.html&quot;&gt;Authorizable Packager&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://adobe-consulting-services.github.io/acs-aem-commons/features/version-comparison.html&quot;&gt;Version Comparison Tool&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://adobe-consulting-services.github.io/acs-aem-commons/features/synthetic-workflow.html#synthetic-workflow-aem-workflow-model-support-v200&quot;&gt;Synthetic Workflow engine&lt;/a&gt; supports Workflow Models&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We also ported all of the custom CoralUI 1.x interfaces to use CoralUI 2.x. As part of this work, a handful of AngularJS directives were created. Although these are primarily intended to be used within the project, they may be of use outside the project. More information can be found here.&lt;/p&gt;

&lt;p&gt;Related to the removal of support for AEM 5.6.1 is that the &lt;a href=&quot;http://adobe-consulting-services.github.io/acs-aem-commons/features/cloud-services.html#adobe-dynamic-tag-manager-dtm&quot;&gt;Dynamic Tag Management&lt;/a&gt; cloud service is now deprecated. Anyone using it should be migrating to the out of the box cloud service.&lt;/p&gt;

&lt;p&gt;Thanks to the following individuals for their contributions, complaints, ideas, and support:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;David Gonzalez (Adobe)&lt;/li&gt;
  &lt;li&gt;Sreekanth Nalabotu (Adobe)&lt;/li&gt;
  &lt;li&gt;Steffen Roesinger (Adobe)&lt;/li&gt;
  &lt;li&gt;Simo Tripodi (Adobe)&lt;/li&gt;
  &lt;li&gt;Brian Johnson (3Share)&lt;/li&gt;
  &lt;li&gt;Koorosh Davoodian (Stanford University School of Medicine)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As always, while this projects are primarily produced and distributed within Adobe Consulting Services, it is available for usage by other Adobe groups, customers and partners. Contributions and feature suggestions from those groups are also most welcome. More information about this project, including detailed information about the included features, can be found &lt;a href=&quot;http://adobe-consulting-services.github.io/acs-aem-commons/&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
</description>
        <pubDate>Wed, 26 Aug 2015 00:00:00 +0000</pubDate>
        <link>http://blog.justinedelson.com/2015/08/26/acs-aem-commons-2-released.html</link>
        <guid isPermaLink="true">http://blog.justinedelson.com/2015/08/26/acs-aem-commons-2-released.html</guid>
        
        <category>aem</category>
        
        <category>opensource</category>
        
        
      </item>
    
  </channel>
</rss>
