Using Polymer elements as native Jahia components
At Google IO 2014, Google presented it’s new Material Design look and feel, and implemented it for the web using Polymer elements. Polymer is a state of the art project aiming at implementing the future of the web, notably HTML web components, available in most versions of modern browsers. Polymer makes it possible to define “custom” HTML elements, that can implement their own behavior and look and feel, while at the same time making it possible to integrate the elements easily on HTML pages and even provide interactions between multiple custom elements.
Polymer is by far not production ready, it is a long-term project to implement the new and upcoming technologies that will be part of tomorrow’s web, although it also provides “polyfills” to make the technology also work with the last two versions of almost every browser (including Internet Explorer 10). This way you can start experimenting with Polymer custom HTML elements (aka Polymer elements) in your projects now, to get a feel of what’s coming next and learn the potential of these new HTML technologies.
Of course, if you're reading this post, you are probably already wondering how Polymer may be integrated with Jahia Digital Experience Manager websites ? And also what level of integration might be possible as well as the potential benefits of such a solution.
Jahia's drag and drop page building capabilities -available in context for business authors and also as a visual tool for developers in the Studio- has always made it possible for non-technical marketers and business users to simply drop components (once made ready and securely deployed) into a page to add content or even functionality to the site. These components may range from simple static content all the way to complex AJAX-based elements that add functionality to the page they are embedded in. Components may also be thought of as content nodes that are rendered using views that usually generate HTML fragments.
In this regard custom HTML elements seem like a natural fit for Jahia's components. Polymer elements may be used in Jahia component views to help build powerful user interfaces for the content. Components also have the ability to declare their own static dependencies such as CSS files, images, JavaScript files or fragments or any other static resource you may think of. This again seems like a good fit for Polymer elements that also come with their own CSS files, images as well as HTML fragments.
Integrating Polymer elements as components also makes it possible to define properties for these elements and populate them using Jahia's UI : we’ll see how this simple combination can yield some powerful results.
Now that we have introduced the rationale, benefits and potential of this type of integration, let's get down to business and start building a module that integrates Polymer elements. Here are the prerequisites we will assume:
- Oracle JDK 1.7+
- A working installation of Jahia Digital Experience Manager, in community or enterprise edition, installed in development mode
- Maven 3.0.x installed
Steps:
- Login into the Digital Experience Manager studio
- Click -> New -> New module
- Enter a name for your new module. We will use : “polymer-sample”
- Open the src/main/resources/META-INF/definitions.cnd file and add the following definitions:
<jnt http:="" jahia="" nt="" www.jahia.org=""> <jmix http:="" jahia="" mix="" www.jahia.org=""> [jmix:polymerComponents] > jmix:droppableContent mixin [jnt:customHTMLElement] > jnt:content, mix:title [jnt:polymerCoreHeaderPanel] > jnt:customHTMLElement, jmix:polymerComponents + * (jnt:customHTMLElement) [jnt:polymerCoreToolbar] > jnt:customHTMLElement, jmix:polymerComponents + * (jnt:customHTMLElement) [jnt:polymerPaperTabs] > jnt:customHTMLElement, jmix:polymerComponents + * (jnt:polymerPaperTab) [jnt:polymerPaperTab] > jnt:customHTMLElement, jmix:polymerComponents
- Create views for your definitions, for example here is the source for the file src/main/resources/jnt_polymerCoreHeaderPanel/html/polymerCodeHeaderPanel.jsp:
<%@ page language="java" contentType="text/html;charset=UTF-8" %> <%@ taglib prefix="jcr" uri="http://www.jahia.org/tags/jcr" %> <%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ taglib prefix="functions" uri="http://www.jahia.org/tags/functions" %> <%@ taglib prefix="template" uri="http://www.jahia.org/tags/templateLib" %> <%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> <%--@elvariable id="currentNode" type="org.jahia.services.content.JCRNodeWrapper"--%> <%--@elvariable id="out" type="java.io.PrintWriter"--%> <%--@elvariable id="script" type="org.jahia.services.render.scripting.Script"--%> <%--@elvariable id="scriptInfo" type="java.lang.String"--%> <%--@elvariable id="workspace" type="java.lang.String"--%> <%--@elvariable id="renderContext" type="org.jahia.services.render.RenderContext"--%> <%--@elvariable id="currentResource" type="org.jahia.services.render.Resource"--%> <%--@elvariable id="url" type="org.jahia.services.render.URLGenerator"--%> <template:addResources type="css" resources="polymer.css" /> <template:addResources type="javascript" resources="/modules/polymer-sample/html/components/platform/platform.js" /> <template:addResources type="html" resources="components/font-roboto/font-roboto.html" /> <template:addResources type="html" resources="components/core-header-panel/core-header-panel.html" /> <core-header-panel> <c:forEach items="${currentNode.nodes}" var="subchild"> <template:module node="${subchild}"/> </c:forEach> </core-header-panel> <template:module path="*"/>
Note the usage of the template:addResources tag to add static resources such as CSS files, javascript files and even HTML imports. In order to make the HTML imports we will have to modify a script in Digital Experience Manager, which we will perform a little later in this process.
- Download the Polymer tutorial code available on this page : http://www.polymer-project.org/docs/start/tutorial/intro.html and copy the components directory to the src/main/resources/html directory
- Make the html directory accessible to the outside world by adding the following configuration to the module’s pom.xml file:
<plugin> <groupId>org.apache.felix</groupId> <artifactId>maven-bundle-plugin</artifactId> <extensions>true</extensions> <configuration> <instructions> <Jahia-Depends>default</Jahia-Depends> <Jahia-Static-Resources>/css,/icons,/images,/img,/javascript,/html</Jahia-Static-Resources> </instructions> </configuration> </plugin>
- In Digital Experience Manager’s installation directory, open the following file tomcat/webapps/ROOT/WEB-INF/scripts/resources.groovy and add the following code just before the “default” statement for the switch :
case "html" : type.value.eachWithIndex { html, i -> condition = html.value.get("condition"); if (condition != null) println("<!--["+condition+"]>"); rel = html.value.get("rel"); println "<link id=\"staticAssetHTML${i}\" rel=\"${rel!=null?rel:"import"}\" href=\"${html.key}\" />"; if (condition != null) println("<![endif]-->"); } break;
The addResources tag is extremely powerful despite it’s simple cases. It will include all static resources of components dragged and dropped into the page into the HEAD section of the HTML page, and also prevent resources declared multiple times to be declared multiple times in the HTML. It is even capable of aggregating JavaScript code dynamically for faster loading times.
- Add a src/main/resources/css/polymer.css file with the following contents:
core-header-panel { height: 300px; overflow: auto; -webkit-overflow-scrolling: touch; } core-toolbar { background: #03a9f4; color: white; } #tabs { width: 100%; margin: 0; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; }
- Compile and deploy the module to your Digital Experience Manager installation either using the Studio’s compile and deploy button (in the first tab of the left panel at the top left), or using Maven from the command line : mvn clean install jahia:deploy -P digital-factory-profile where digital-factory-profile is a Maven profile that looks something like this:
<profile> <id>digital-factory-profile</id> <properties> <jahia.deploy.targetServerType>tomcat</jahia.deploy.targetServerType> <jahia.deploy.targetServerVersion>7</jahia.deploy.targetServerVersion> <jahia.deploy.targetServerDirectory>/Users/loom/java/deployments/jahia-7.0/apache-tomcat-7.0.53 </jahia.deploy.targetServerDirectory> <jahia.deploy.war.dirName>ROOT</jahia.deploy.war.dirName> <jahia.deploy.war.contextPath>/</jahia.deploy.war.contextPath> <jahia.deploy.war.servletPath>/cms</jahia.deploy.war.servletPath> <jahia.debug.address>socket:hostname=localhost,port=8000</jahia.debug.address> </properties> </profile>
- You should then go into the administration -> System Components -> Modules -> search for your module name and click on “Details” and enable usage on the sites you want to use it on.
- In Digital Experience Manager’s edit mode, create a new page with the template “full” and then click on the arrow on the right of “main” to activate the area
- Drag & drop the jnt:polymerCoreHeaderPanel into the main area
- You will see a “custom HTML element” button appear. Click on it and add a jnt:polymerCoreToolbar component
- Inside the jnt:polymerCoreToolbar component, add a jnt:polymerPaperTabs component
- Inside the jnt:polymerPaperTabs you can only add jnt:polymerPaperTab elements, so create as many as you want and give them proper names. Your component structure should look something like this in the JCR repository explorer:
- Switch to preview mode, you should get a result that looks something like this:
The tabs should be clickable, generating motion animations.
As you can see, despite the number of steps, these are relatively straight-forward for someone familiar with Jahia’s Digital Experience Manager. Even for a newcomer this could serve as a nice introduction to integrating existing technologies using component modules.
The integration of Polymer is of course just one example of creating Digital Experience Manager components to provide re-usable HTML fragments. In a similar way this could be done for X-Tags or even AngularJS directives. Also, being able to use components in the Studio to edit template makes it possible to “lock” elements onto page templates, making it then easy for content editors to build new pages with already populated custom elements.
You can find the full source code of this blog post in the following public Github repository :https://github.com/Jahia/polymer-sample