Showing posts with label Components. Show all posts
Showing posts with label Components. Show all posts

Monday, 10 April 2017

AEM Component is in satisfied state, not in active

Some times we face OSGI component is in active state when the component is installed for the first time. When we modify the component from configMgr, component state changes to satisfied.

To avoid this and make the component in active state add the annotation @Activate to the activate method. This helps in changing the component state to Active whenever the component is modified.

Thursday, 9 March 2017

Get the rendered HTML for an AEM resource, component or page

It's easy to retrieve a rendered component by making a GET request. Apache Sling's SlingMainServlet and DefaultGetServletwill process GET requests, take the path's extension into account, and return the rendered resource. The most obvious example of triggering this process is simply typing the component's path into the browser's address bar or making an AJAX call. You can retrieve the HTML markup (or JSON, XML, txt, PDF, etc...) for a component as well as a page if you provide the correct path. After all, they're both just Sling resources. 

Trying to get the rendered HTML of a component on the server side is still easy, but requires a little more work. Without knowing the inner workings of Sling, you might use Java's java.net.HttpUrlConnection class to construct and make an HTTP request from within your application to your application.

The better way is to use the SlingRequestProcessor service as the entry point into Sling's process. The processRequest method of the SlingRequestProcessor takes an HttpServletRequest, HttpServletResponse, and Resource Resolver as parameters. The only trick is that you need to provide a request that enables you to set the request path and a response that enables you to get the OutputStream as a String.

AEM provides the RequestResponseFactory where you can easily get such a request and response.

Using Granite DataSource objects to populate Experience Manager 6.2 Touch UI Select objects

You can create an Adobe Experience Manager (AEM) 6.2 Touch UI component that contains a drop-down control that can be used within the AEM Touch UI view. An AEM author selects drop-down values during design time. For example, an author can select a USA state value from an AEM component that displays address information. A drop-down control is populated by using a com.adobe.granite.ui.components.ds.DataSource object. For information, see DataSource.
Once you create a DataSource object, its data can be used to dynamically populate a drop-down control, as shown in this illustration.

A drop-down control populated by using a DataSouce object

Friday, 3 March 2017

Things to know about AEM Touch UI

Adobe introduced a new touch-optimized UI with AEM 5.6 for the author environment. This differs considerably from the original classic UI as it is designed to operate on both touch and desktop devices. The basic principles of the touch-optimized UI are:
  • Mobile first (with desktop in mind)
  • Responsive design
  • Context relevant display
  • Reusable
  • Include embedded reference documentation
  • Include embedded tests
  • Bottom-up design to ensure these principles are applied to every element and component

Friday, 17 February 2017

Creating a site footer in AEM 6 using Sightly and Sling Models

The Adobe-developed and recently-donated-to-Apache-Sling project Sightly project has been out for a little under a year now, alongside Adobe Experience Manager 6, and has slowly been amassing documentation and gaining presence. The server-side templating language aims to give a facelift to the web development facet of Java-based software stacks, Adobe's AEM chief among them.
This post will run the reader through a sample implementation of a site footer using Sightly, showcasing and describing a few of its features. It will also make use of Sling Models as the back-end tool to grab JCR data (nodes, properties) into useful class models.
What we want is an authorable footer serving all pages of a language branch of a content tree. Let's assume that our site is for Acme, the reputable maker of all things widgets, gadgets, and sprockets. Our site structure will be traditional and look like,
/content/acme/en
/content/acme/en/about-us
/content/acme/en/news
/content/acme/en/products
/content/acme/en/contact
and so on. Let's assume that the en page serves as the homepage for the English site, and similarly, the /content/acme/fr will serve as the French homepage, with all French content pages under it. As such, each homepage will need to have an instance of footer data.

Tuesday, 17 January 2017

Creating an Adobe Experience Manager HTL Component that parses MS Word Documents

You can develop an Adobe Experience Manager HTL (used to be known as Sightly) component that can parse and display content from MS Word documents. Some Experience Manager use cases require integrating MS Word documents with Experience Manager. The HTL component developed in this article parses a MS Word document and displays the content in in a HTL component. Consider the following Word document.

A MS Word document


You can develop a custom HTL component to parse this Word doc and display the data in an AEM web page, as shown in the following illustration.

A HTL component displaying data parsed from a Word document


Friday, 9 December 2016

Creating an Adobe Experience Manager HTL Headline component

You can create an Adobe Experience Manager (AEM) Headline component that you can use in your AEM web page. A headline component lets your website visitors read latest headlines about a specific subject. That is, you can enter keyword into an AEM dialog and the component will display headlines related to the keyword. For example, you can enter Facebook keyword and the component displays headlines, as shown in the following illustration.

Thursday, 23 June 2016

Developing a custom Adobe Experience Manager Quiz Component

You can develop a custom Adobe Experience Manager Quiz component that lets your web site visitors perform an on-line quiz and view the results. There are business requirements that require web visitors to perform an online quiz and then track the results. Building an AEM custom quiz component satisfies this business requirement. 
Assume that another requirement for the quiz component is the questions and corresponding answers are configurable. That is, an AEM author can set them without updating the component's application logic.
Note:
Using AEM adaptive forms or other forms is not a recommended way to develop a custom AEM quiz component. Instead, its better to develop a custom component as discussed in this article.
The Quiz application is made up of two parts:
  • Quiz component -  allows web visitors to answer displayed questions and view the results
  • Quiz configuration - allows AEM authors to set questions and answers
The following illustration shows the logic flow for the Quiz component. 
The Quiz component logic flow

1. The AEM Quiz configuration component lets an author set data values used in the quiz component. 
2. The quiz configuration data is stored in the AEM JCR. 
3. An AEM Service reads the JCR data.
4. The OSGi Service converts the JCR data to JSON data. 
5. The Quiz component uses the JSON data to render the quiz. 

Tuesday, 12 April 2016

Touch UI dynamic selection of multiple drop downs in AEM 6.1

This articles show the use case of have multiple chained drop down in Touch UI. Values in the next drop down depends on what has been selected on previous one. 
Brief on how it works:-
There are two drop downs with name Language and Country. When you select a Language from drop down, Country down down gets populated with the name of the countries using that language. For example if you select “German” as a language then all countries using German as language will get populated in second drop down.

Creating an AEM Headline Component

Discusses how to create an Adobe Experience Manager component that uses Sightly and a Sling Servlet to display headline news. 
A special thank you to Praveen Dubey, a top AEM community member, for contributing code towards this community article.   
This article covers many AEM concepts that are important to understand as an AEM developer. This article covers the following concepts. 
  • How to create a Sightly component that displays data from a third party service
  • How to use AJAX that invokes a servlet with a Sightly component
  • How you include a clientlibs folder using Sightly
  • How to pass dialog values to a Sling Servlet
This article uses an Adobe Maven Archetype project to build an OSGi bundle. If you are not familiar with an Adobe Maven Archetype project, it is recommended that you read the following article: Creating your first AEM Service using an Adobe Maven Archetype project.

Saturday, 12 December 2015

Asset Grabber – oEmbed a complete asset embed solution

If you are an AEM/CQ developer and had worked on multiple projects, then you might be very well familiar with how exasperating is to create components for embedding assets in for web page. Here’s how actually it goes from development perspective.
Things starts with video component. Now create a component for YouTube, let’s assume you created. Next day client knock’s your door and say’s, “We are now planning to embed Vimeo also, please add this into your requirement and start working“. Somehow you managed to create a Vimeo component. After 2 days, client again shoots a missile, “We had an internal discussion and now we are planning to feature Ted videos as well, please get started“. At this point what development team and with  how much anger they get into you will be aware, But before leaving for the day you run this command: “project XYZ: Completed Ted Video module“. It means you have completed this as well.
When it comes to assets, it’s very strenuous to take care of all scenarios. Let me introduce youoEmbed, we call it as “Assets Grabber”. Yes, you heard right, it’s having secret magnetic attraction power to pull things from other sites and show in yours. That’s so called secret magnetic attraction is it’s ability to handle and support huge amount of sites starting from VimeoYouTube for videos to Flickr for images to Infogram for charts to Slideshare for slide to Meetup for meetings.

Wednesday, 18 November 2015

Creating a Sightly component that uses the AEM QueryBuilder API

You can create an Adobe Experience Manager (AEM) 6 Sightly  component that can be used within the AEM Touch UI view. Furthermore, you can use Sightly and the QueryBuilder API to develop the AEM component that displays AEM JCR data.

Sightly is an AEM  template language that can be used to replace the use of JSP when developing an AEM component. Sightly helps you to separate your design from your application logic.  In this use case, the Sightly logic is located within an HTML file and displays the result set. The Java part of the Sightly component uses the QueryBuilder API.


To read this AEM community article, click https://helpx.adobe.com/experience-manager/using/sightly_querybuilder.html.


Monday, 16 November 2015

Brightcove AEM Integration



Brightcove Video Connect for AEM is a configurable integration enabling users to add/edit/manage videos, playlists and players directly within AEM's authoring interface.
The integration streamlines video publishing workflows for organizations who have been using Video Cloud and AEM concurrently. This is particularly evident in instances where there is a division of labor between the person or team responsible for uploading content to Video Cloud, setting business rules and creating players, and the person or team responsible for editing and publishing webpages via AEM. Both parties can now manage video content smoothly amongst themselves in the common AEM setting.
Brightcove Video Connect for AEM is free and open source. 
Brightcove Video Connect for AEM was developed by Coresecure, Brightcove’s official AEM development partner.
References:
http://www.coresecure.com/brightcove-aem-integration/
https://www.brightcove.com/en/partners/cq5
https://www.brightcove.com/en/partners/adobe-experience-manager

How to define component list dynamically for Sidekick and Insert dialog

https://helpx.adobe.com/experience-manager/kb/HowToDefineComponentListDynamically.html

Friday, 13 November 2015

Customization of parsys to restrict number of compnents in CQ 5.6.1

  1. Copy the parsys component from(/libs/foundation/components/parsys) to your poroject(/apps/<project nmae>/components/).
     2.  In the design dialog add number filed configuration to enter the number of components.

           Crate node noofcomp of type cq:widget under /apps/<project nmae>/components/parsys
              /design_dialog/items.
           Add the following properties

           xtype : numberfield
           name : noOfComp
           maxValue : 20
           fieldLabel : No of components


     3.   Create ajax.jsp and write the below logic.
           <%@page import="com.day.cq.wcm.foundation.ParagraphSystem"%>
           <%@include file="/libs/foundation/global.jsp"%>
           <%
                 ParagraphSystem parSys = ParagraphSystem.create(resource, slingRequest);
                 int totalComponents=parSys.paragraphs().size();
                 int restrictCompoNo=Integer.parseInt(currentStyle.get("noOfComp","20"));

                if(totalComponents >= restrictCompoNo){
                      out.println("true");
                  }else{
                            out.println("false");
                    }
               %>

    4.  You need to overlay the EditBase.js and Sidekick.js

          Create the following structure   /apps/cq/ui/widgets/source/widgets/wcm

         then copy the EditBase.js and Sidekick.js form libs . Place under /wcm /
   
         In Sidekic.js at line 4098 in set timeout method add this snippet.

            var parentPath=editComponent.path;
            var ajaxUrl=parentPath.substr(0,parentPath.lastIndexOf("/"))+".ajax";
            var notAllowToCreate = CQ.HTTP.eval(ajaxUrl);
           
            if(!notAllowToCreate){
                editComponent.createParagraph(definition);

            }else{
                CQ.Ext.Msg.show({
                                   msg: 'You reached  the maximun limit. You can set the limit in disign mode.',
                                   buttons: CQ.Ext.Msg.OK,
                                   icon: CQ.Ext.MessageBox.WARNING
                                });

               }
                dropTarget.editComponent.hideTarget();


         In EditBase.js at line 1181  in set timeout method add this snippet.
       
           var parentPath=e.path;
            var ajaxUrl=parentPath.substr(0,parentPath.lastIndexOf("/"))+".ajax";
            var notAllowToCreate = CQ.HTTP.eval(ajaxUrl);    
            if(!notAllowToCreate){
                e.createParagraph(definition);

            }else{
                CQ.Ext.Msg.show({
                    msg: 'You reached  the maximun limit. You can set the limit in disign mode.',
                    buttons: CQ.Ext.Msg.OK,
                    icon: CQ.Ext.MessageBox.WARNING
                });
               
            }
            e.dialogs[CQ.wcm.EditBase.INSERT].hide();
            e.insertDialogMask.hide();

Customize column control in 5.6.1 (Adding backgroud color which is configured in dialog)

1.   Create the folder structure like apps/foundation/components.

2.   Copy the parsys component from the(/libs/foundation/components) to  /apps/foundation/components.

3.   In the column control dialog add following configurations
       (/apps/foundation/components/parsys/colctrl/dialog/items)

.           jcr:primaryType ="cq:Widget"
            fieldDescription ="eg : #f7f7f7"
            fieldLabel = "Background color"
            name = "./bgColor"
            xtype = "textfield"

            jcr:primaryType="cq:Widget"
            fieldLabel="Apply linear gradient"
            name="./linearGradient"
            type="checkbox"
            xtype="selection"

4.    Add the following snippet of code in parsys.jsp at line number 50.

                 //ading styles for  background color to column
                Node parNode = par.adaptTo(Node.class);
                String bgColorStyle = "";
                String bgColor = "";
                String linearGradient = "";
                if(parNode.hasProperty("bgColor")){
                 bgColor = parNode.getProperty("bgColor").getString();
                 bgColorStyle = "background: "+bgColor;
                }
                if(parNode.hasProperty("linearGradient") &&
                 parNode.getProperty("linearGradient").getString().equalsIgnoreCase("true") ){
                
                bgColorStyle = "background-image: linear-gradient( "+bgColor + " 0%, #fff 45%,"+bgColor +
                                          " 75%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr="
                                         +bgColor+", endColorstr="+bgColor+" GradientType=0)";
                }
          
                // open outer div
                %><div class="parsys_column <%= par.getBaseCssClass()%>" style="<%=bgColorStyle%>">

Colorpicker RTE plugin for Richtext

1.  Create a clientlibs node (nodeTypecq:ClientLibraryFolder) under the root node of the project.
e.g. /apps/training
Assign the following properties to the newly created clientlibs node 
the property that identifies the category these custom Widgets will be referenced by

Name  = categories
Type  String []
Value  colorpicker.widgets
the property that defines JS library dependencies

Name  dependencies
Type  String[]
Value  cq.jquery#cq.foundaion-main

2.  Create a css folder under the newly created clientlibs node.
3.  Create a js folder under the newly created clientlibs node.
4.  Create a css.txt file under the newly created clientlibs node.
5.  Create a js.txt file under the newly created clientlibs node.
6.  Create colorpickerplugin.Js and colorpickerdialog.js in js folder under  clientlibs

colorpickerplugin.Js



 /**
 * @class CQ.form.rte.plugins.HtmlColorPickerPlugin
 * @extends CQ.form.rte.plugins.Plugin
 * <p>This class builds a Colorpicker pop up as a plugin.</p>
 * <p>The plugin ID is "<b>Colorpicker</b>".</p>
 * <p><b>Features</b></p>
 * <ul>
 *   <li><b>colorpicker</b> - pops up Colorpicker dialog</li>
 * </ul>
 */
CQ.form.rte.plugins.HtmlColorPickerPlugin = CQ.Ext.extend(CQ.form.rte.plugins.Plugin, {

/**
 * @private
 */
htmlColorPickerDialog: null,
/**
 * @private
 */
colorPickerText: null,
   /**
 * @private
 */
envEditContext:null,

constructor: function(editorKernel) {
CQ.form.rte.plugins.HtmlColorPickerPlugin.superclass.constructor.call(this,
editorKernel);
},
callDialog: function(context) {

if (CQ.Ext.isIE) {
this.savedRange = context.doc.selection.createRange();
}
var editorKernel = this.editorKernel;

var configdialog = {
"editContext": context,
"title": CQ.I18n.getMessage("Color Picker"),
"colorPickerText": this.colorPickerText,
"insertContentIntoRTE": this.insertContentIntoRTE.createDelegate(this),
"cancelFn": this.execCancel.createDelegate(this),
"listeners": {
"show": function() {
editorKernel.fireUIEvent("dialogshow");
},
"hide": function() {
editorKernel.fireUIEvent("dialoghide");
}
}
};
this.htmlColorPickerDialog =
                                        new CQ.form.rte.plugins.HtmlColorPickerDialog(configdialog);
this.htmlColorPickerDialog.setPosition(
                                                   this.editorKernel.calculateWindowPosition("left"));

this.htmlColorPickerDialog.show();
window.setTimeout(function() {
this.htmlColorPickerDialog.toFront();
this.htmlColorPickerDialog.focus();
}.createDelegate(this), 10);
},

getYourData: function(){

 // You might want to do something here and populate a value that needs to go inside your dialog.
this.colorPickerText = "Color Picker RTE Plugin";
this.callDialog(this.envEditContext);
},

// This gets called when you click OK button from your dialog
insertContentIntoRTE: function(context, options, dialog) {
 var selectionDef = this.editorKernel.analyzeSelection();
 var nodelist = selectionDef["nodeList"];
 var node = nodelist["nodes"][0];
 var nodeDom = node["dom"];
 var nodeText = nodeDom["nodeValue"];
 var selectedText=nodeText.substring(node["startPos"], node["startPos"] +
                                                            node["charCnt"]);
 var color;
 for(var opt in options){
if(opt!=undefined && opt!="" && opt!='remove' && opt!='indexOf'){
                                              //for IE alone indexOf comes as a function
color = options[opt].value;
}
}
var style="style=color:#"+color;
var htmlCode = '<span '+style+'>' + selectedText + '</span>';

this.editorKernel.execCmd("inserthtml", htmlCode);
dialog.hide();
},

// This gets called when you click Cancel button from your dialog
execCancel: function() {

},

getFeatures: function() {
return [ "colorpicker" ];
},

initializeUI: function(tbGenerator) {
var plg = CQ.form.rte.plugins;
var ui = CQ.form.rte.ui;
if (this.isFeatureEnabled("colorpicker")) {
this.checkTextUI = new ui.TbElement("colorpicker", this,
                                                                                       true,this.getTooltip("colorpicker"));
tbGenerator.addElement("htmlColorPicker", plg.Plugin.SORT_LISTS,
                                                                               this.checkTextUI,10);
}

},

notifyPluginConfig: function(pluginConfig) {
pluginConfig = pluginConfig || { };
CQ.Util.applyDefaults(pluginConfig, {
"tooltips": {
"colorpicker": {
"title": CQ.I18n.getMessage("Color Picker"),
"text":  CQ.I18n.getMessage("Color Picker pop-up")
}
}
});
this.config = pluginConfig;
},

execute: function(id, value, env) {
switch (id) {
case "colorpicker":
this.envEditContext = env.editContext;
this.getYourData();               
break;
}

},

updateState: function(selDef) {

// todo implement
}

});


// register plugin
CQ.form.rte.plugins.PluginRegistry.register("htmlColorPicker",
CQ.form.rte.plugins.HtmlColorPickerPlugin);

     

colorpickerdialog.js



/**
 * @class CQ.form.rte.plugins.HtmlColorPickerDialog
 * @extends CQ.Ext.Window
 * @private
 * This class implements the Hello World dialog.
 */
CQ.form.rte.plugins.HtmlColorPickerDialog = CQ.Ext.extend(CQ.Ext.Window, {
editContext: null,
insertContentIntoRTE: null,
constructor: function(config) {
var dialogRef = this;
var dialogItems = [ ];
var buttonItems = [ ];
var defaults = {
"title": "Html Color Picker"
};
CQ.Util.applyDefaults(config, defaults);
CQ.Ext.apply(this, config);
dialogItems.push({
"itemId": "colorPickerField",
"name": "colorPickerField",
"xtype": "colorfield",           
"fieldLabel": "colorPickerField",
"colors":['000000', '993300', '333300', '003300', '003366', '000080', '333399',
                                                    '333333','800000', 'FF6600', '808000', '008000', '008080', '0000FF',
                                                   '666699', '808080','FF0000', 'FF9900', '99CC00', '339966', '33CCCC',
                                                   '3366FF', '800080', '969696','FF00FF', 'FFCC00', 'FFFF00', '00FF00',
                                                   '00FFFF', '00CCFF', '993366', 'C0C0C0','FF99CC', 'FFCC99',
                                                    'FFFF99', 'CCFFCC', 'CCFFFF', '99CCFF', 'CC99FF', 'FFFFFF' ]
  });
// Buttons
buttonItems.push({
"itemId": "ok",
"name": "ok",
"text": "OK",
"handler": function() {
this.applyDialog(this.insertContentIntoRTE, null);
},
"scope": this
});
buttonItems.push({
"text": "Cancel",
"handler": function() {
if (this.cancelFn) {
this.cancelFn();
}
this.hide();
},
"scope": this
});
CQ.form.rte.plugins.HtmlColorPickerDialog.superclass.constructor.call(this, {
"renderTo": CQ.Util.ROOT_ID,
"title": this.title,
"stateful": false,
"minWidth": 400,
"minHeight": 170,
"width": 400,
"height": 310,
"plain": true,
"layout": "fit",
"items": [ {
"xtype": "panel",
"layout": "fit",
"stateful": false,
"items": [ {
"border": false,
"xtype": "form",
"itemId": "ColorPickerForm",
"name": "ColorPickerForm",
"stateful": false,
"autoHeight": true,
"items": dialogItems,
"bodyStyle": "overflow: auto;",
"afterRender": function() {
CQ.Ext.Panel.prototype.afterRender.call(this);
dialogRef.findItems = this.items;
this.body.addClass("cq-rte-helloworlddialog");
}
}
]
}
],
"buttons": buttonItems,
"modal": true
});
},
applyDialog: function(fn, options) {
options = options || [];
if (fn) {
var colorPickerTextValue = this.findItems.get("colorPickerField").getValue();
options.push({value: colorPickerTextValue, name: 'colorPickerTextValue'});
fn(this.editContext, options, this);
}
},
cancelFn: function(){

//Implement here
}
});


7.  List colorpickerplugin.js and  colorpickerdialog.js in js.txt file.
8.  Create cloorpicker.css in css folder under  clientlibs.

cloorpicker.css 


@CHARSET "UTF-8";
#CQ .x-html-editor-tb .x-edit-colorpicker{
  background: url(/libs/cq/ui/widgets/themes/default/icons/16x16/colorpicker.jpg)
                           center no-repeat;
}

9.  List cloorpicker.css in css.txt file underclientlibs.

10. Create a htmlColorPicker node (nodeType nt:unstructured) under the Training Complex Component's Dialog tab 1 widget collection.

e.g./apps/<project>/components/content/Complex/dialog/items/items/tab1/items/text/rtePlugins
 Assign the following properties to the newly created htmlColorPicker node:

 the property that will define where the content is stored

Name  features
Type  String
Value  *