Article Summary

Summary
Discusses how to use HTML5 drag and drop functionality within an Adobe CQ client web page.
Digital Marketing Solution(s) Adobe Experience Manager (Adobe CQ)
Audience
Developer (intermediate)
Required Skills
JavaScript, JQuery, CSS
Tested On Adobe CQ 5.5, Adobe CQ 5.6

Introduction

You can create a custom CQ application that integrates drag and drop functionality supported with HTML5. By integrating drag and drop functionality into your CQ client applications, you offer your users a cutting edge and engaging experience. This drag and drop CQ application lets a user drag a PDF icon to the beginning of the list.

When the user clicks the View PDF Document button, the PDF icon name located at the beginning of the list is retrieved. The PDF name is sent to an OSGi bundle operation that saves the corresponding PDF document in a web server location. The IFrame control that is located on the client CQ application displays the PDF document.

Drop

Create a custom CQ application that supports drag and drop by performing these steps:

  1. Create an Adobe CQ application folder structure.
  2. Create a template on which the render component is based.
  3. Create a render component that represents the client. 
  4. Create an Eclipse Java project that handles PDF documents (this project defines the OSGi operation).
  5. Create and deploy the OSGi bundle that contains a Java class created in the previous step.
  6. Modify the JSP to support drag and drop functionality and call a Java method defined in the OSGi bundle.
  7. Create a CQ site that lets users drag and drop a PDF icon and view the corresponding PDF document.

Note:

Before following along with this development article, make sure that you install Adobe CQ 5.5 and have it running.

Create a CQ application folder structure

Your first step is to create a CQ application folder structure that contains templates, components, and pages by using CRXDE Lite. 

CQAppSetup

The following list describes each application folder:

  • Application name folder: contains all of the resources that an application uses. The resources can be templates, pages, components, and so on.
  • components folder: contains components that your application uses.
  • page folder: contains page components. A page component is a script such as a JSP file.
  • global: contains global components that your application uses.
  • template folder: contains templates that you can base page components on.
  • src folder: contains source code that comprises an OSGi component.
  • install folder: contains a  compiled OSGi bundles container.

Create an application folder structure in CRXDE Lite:

1. Go to the CQ welcome page at http://[host name]:[port]; for example, http://localhost:4502.

2. Select CRXDE Lite.

3. Right-click the apps folder (or the parent folder), select Create, Create Folder.

4. Enter the folder name into the Create Folder dialog box. Enter drag.

5. Repeat steps 1-4 for each folder specified in the previous illustration.

6. Click the Save All button.

Note:

You have to click the Save All button when working in CRXDE Lite for the changes to be made.

Create a template for the drag and drop application 

Create a CQ template by using CRXDE Lite that defines a consistent style for the pages in your CQ application. A template comprises of nodes that that specify the page structure. For more information about templates, see http://docs.adobe.com/docs/en/cq/current/developing/templates.html.

Create a template by using CRXDE Lite:

1. Go to the CQ welcome page at http://[host name]:[port]; for example, http://localhost:4502.

2. Select CRXDE Lite.

3. Right-click the template folder (within your application), select Create, Create Template.

4. Enter the following information into the Create Template dialog box:

  • Label: The name of the template to create. Enter dragtemplate.
  • Title: The title that is assigned to the template
  • Description: The description that is assigned to the template
  • Resource Type: The component's path that is assigned to the template and copied to implementing pages. Enter drag/components/page/dragtemplate.
  • Ranking: The order (ascending) in which this template appears in relation to other templates. Setting this value to 1 ensures that the template appears first in the list.

5. Add a path to Allowed Paths. Click on the plus sign and enter the following value: /content(/.*)?.

6. Click Next for Allowed Parents.

7. Select OK on Allowed Children.

Create a render component that uses the dragtemplate

Components are re-usable modules that implement specific application logic to render the content of your web site. You can think of a component as a collection of scripts (for example, JSPs, Java servlets, and so on) that completely realize a specific function. In order to realize this functionality, it is your responsibility as a CQ developer to create scripts that perform specific functionality. For more information about components, see http://docs.adobe.com/docs/en/cq/current/developing/components.html.

Note:

By default, a component has at least one default script, identical to the component name.

Create a render component that uses the dragtemplate:

1. Go to the CQ welcome page at http://[host name]:[port]; for example, http://localhost:4502.

2. Select CRXDE Lite.

3. Right-click /apps/drag/components/page, then select Create, Create Component.

4. Enter the following information into the Create Component dialog box:

  • Label: The name of the component. Enter dragtemplate
  • Title: The title that is assigned to the component
  • Description: The description that is assigned to the template

5. Select Next for Advanced Component Settings and Allowed Parents.

6. Select OK on Allowed Children.

7. Open the dragtemplate.jps located at: /apps/drag/components/page/dragltemplate/dragtemplate.jsp.

8. Enter the following JSP code:

<html>
<head>
<title>Hello World !!!</title>
</head>
<body>
<h1>Drag client</h1>
<h2>This page will contain a  HTML5 drag and drop client </h2>
</body>
</html>

Note:

This code will be modified in a later step. 

Create an Eclipse project that handles PDF documents

Create an Eclipse project that creates a Java class that saves a PDF file in a web server location. That is, when a user drags a PDF icon to the start of the list, this file name is sent to the OSGi bundle. The PDF file that corresponds to the file name is saved in the web server location. The IFrame control that is located in the client JSP display the PDF document located in this web server location.

The following Java code represents the Java class named HandlePDF. Notice that this class is located in a Java package named com.cq.drag. The SetPDF method is called from the client application. 

package com.cq.drag;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;

public class HandlePDF {
	
	//Saves a PDF file to a web server location where an
	//IFrame control in the client can display it
	public void SetPDF(String docName)
	{
		try{
                       
            File fileName = null;
            
            // Get the PDF file that corresponds to the file name passed to the OSGi bundle
            if (docName.equals("Loan.pdf") == true)
            	 fileName = new File("C:\\Adobe\\Loan.pdf");
            else if(docName.equals("Question.pdf") == true)
            	 fileName = new File("C:\\Adobe\\Question.pdf");
            else if(docName.equals("Policy.pdf") == true)
            	 fileName = new File("C:\\Adobe\\Policy.pdf");
            else if(docName.equals("Report.pdf") == true)
            	 fileName = new File("C:\\Adobe\\Report.pdf");
            else if (docName.equals("Vaction.pdf") == true)
            	 fileName = new File("C:\\Adobe\\Vaction.pdf");
            	
            // Get the length of the file stream and create a byte array
            FileInputStream inFs = new FileInputStream(fileName); 
               
            int inLen = (int)fileName.length();
            byte[] inByteArray = new byte[inLen];
            
            // Populate the byte array with the content of the file stream
            inFs.read(inByteArray, 0, inLen);
    
                        
            //Place the PDF document to the a web server location
            File outFile = new File("C:\\webapps\\dataservices\\Document.pdf");
            
            //Create a FileOutputStream object.
            FileOutputStream myFileW = new FileOutputStream(outFile);
            
            //Call the FileOutputStream object's write method and pass the pdf data
            myFileW.write(inByteArray);
            
            //Close the FileOutputStream object
            myFileW.close();
                 
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
	}

}

Note:

If you are following along with this development article, then ensure that you save the PDF file to a web server location. The IFrame control located in the client JSP application references this location and displays the PDF document.

Create an Eclipse project:

  1. Create an Eclipse Java project and name the project CQProject.
  2. Add a new Java class named HandlePDF to your project. Add the Java code specified in this section to this class.
  3. Compile and build your Java project.
  4. Export the project to a Java JAR named CQDrag.jar. (This JAR file is bundled into an OSGi bundle in the next step.)


Create and deploy the OSGi bundle

Create an OSGi bundle that contains the CQDrag.jar file. Once you upload the OSGi bundle to Adobe CQ, you can call the SetPDF method that is located in the HandlePDF class. To create the OSGi bundle, you can use another Eclipse project. An OSGi bundle is essentially a collection of Java files and a MANIFEST.MF file. The following code represents the MANIFEST file for this OSGi bunlde. Notice that the Export-Package value is com.cq.drag.

Manifest-Version: 1.0

Bundle-ManifestVersion: 2

Bundle-Name: ATestDrag

Bundle-SymbolicName: ATestDrag

Bundle-Version: 1.0.0

Export-Package: com.cq.drag

Bundle-RequiredExecutionEnvironment: JavaSE-1.6

To create an OSGi bundle that contains the HandlePDF class:

1 Start Eclipse (Indigo). The steps below have been tested on Eclipse Java EE IDE for Web Developers version Indigo Service Release 1.

2. Select File, New, Other.

3. Under the Plug-in Development folder, choose Plug-in from Existing JAR Archives. Name your project CQDragBundle.

4. In the JAR selection dialog, click the Add external button, and browse to the CQDrag.jar file that you created in the previous step.

5. Click Next.

6. In the Plug-in Project properties dialog, ensure that you check the checkbox for Analyze library contents and add dependencies.

7. Make sure that the Target Platform is the standard OSGi framework.

8 . Ensure the checkboxes for Unzip the JAR archives into the project and Update references to the JAR files are both checked.

9. Click Next, and then Finish.

10. Click on the Runtime tab.

11. Make sure that the Exported Packages list is populated, as shown in the above example. 

12. Make sure these have been added under the Export-Package header in MANIFEST.MF.

13. Remove the version information in the MANIFEST.MF file. Version numbers can cause conflicts when you upload the OSGi bundle to Adobe CQ.

14. Save the project.

15. Build the OSGi bundle by right clicking the project in the left pane, choose Export, Plug-in Development, Deployable plug-ins and fragments and click Next.

16. Select a location for the export (C:\TEMP) and click Finish. (Ignore any error messages).

17. In C:\TEMP\plugins, you should now find the OSGi bundle with a name similar to cqdragbundle_1.0.0.jar.

18. Login to Adobe CQ’s Apache Felix Web Console at http://server:port/system/console/bundles (default admin user = admin with password= admin).

19. Sort the bundle list by Id and note the Id of the last bundle.

20. Click the Install/Update button.

21. Check the Start Bundle checkbox.

22. Browse to the bundle JAR file you just built. (C:\TEMP\plugins).

23. Click Install.

24. Click the Refresh Packages button.

25. Check the bundle with the highest Id.

26. Your new bundle should now be listed with the status Active.

27. If the status is not Active, check the CQ error.log for exceptions. If you get “org.osgi.framework.BundleException: Unresolved constraint” errors, check the MANIFEST.MF for strict version requirements which might look as follows: javax.xml.namespace; version=”3.1.0”.

28. If the version requirement causes problems, remove it so that the entry looks like this: javax.xml.namespace.

29. If the entry is not required, remove it entirely.

30. Rebuild the bundle.

31. Delete the previous bundle and deploy the new one.

32. If all goes well, the CQ error.log should have log entries such as follows:

*INFO* [FelixDispatchQueue] com.oracle.jdbc BundleEvent INSTALLED

*INFO* [FelixDispatchQueue] com.oracle.jdbc BundleEvent RESOLVED

*INFO* [FelixDispatchQueue] com.oracle.jdbc BundleEvent STARTED

*INFO* [FelixDispatchQueue] org.apache.felix.framework FrameworkEvent PACKAGES REFRESHED

Modify the JSP to support HTML5 drag and drop

To create an Adobe CQ client tht supports HTML5 drag and drop and calls the OSGi bundle created in the previous step, create these two files:

  • pdfsecure.json.jsp: contains application logic that calls the OSGI bundle’s SetPDF operation. This file is the connection between a JSP front end and the back end OSGi operation.
  • dragtemplate.jsp: contains application logic that lets a user drag PDF icons. When the user clicks the View PDF Document button, the PDF that is at the start of the list is displayed within the IFrame control. (This file was created in a previous step; however, in this step it is modified.)

Create the pdfsecure.json.jsp file

Add a new JSP file named pdfsecure.json.jsp to the following path:

/apps/drag/components/page/dragtemplate

In the pdfsecure.json.jsp, create a com.cq.drag.HandlePDF object. This object allows you to invoke operations located in the OSGi bunlde. The following code represents the pdfsecure.json.jsp file.

<%@ page import="org.apache.sling.commons.json.io.* " %><%
 
//Get the value passed from the client
String pdf = request.getParameter("fileName");
com.cq.drag.HandlePDF ww = new com.cq.drag.HandlePDF(); 
ww.SetPDF(pdf);

To add the pdfsecure.json.jsp file:

1. To view the CQ welcome page, enter the URL http://[host name]:[port] into a web browser. For example, http://localhost:4502.

2. Select CRXDE Lite.

3. Right-click /apps/drag/components/dragtemplate, then select Create, File.

4. Enter pdfsecure.json.jsp in the Name field and click OK.

5. Enter the JSP code shown above.

6. Click Save All.

Modify the dragtemplate.jsp file

The dragtemplate file defines HTML5 drag and drop functionality by referencing these JQuery files:

<script type='text/javascript' src='http://code.jquery.com/jquery-1.4.2.js'></script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.4/jquery-ui.js"></script>

Note:

Instead of referencing JQuery library files, you can create a client library folder within your CQ application. For information, see http://scottsdigitalcommunity.blogspot.ca/2012/02/integrating-jquery-framework-into-day.html.

The part of the client that can be dragged is defined in a list, as shown in the following code.

<ul id="PDFDocuments">
	<li class="pdf" name="Policy.pdf">Policy.pdf</li>
	<li class="pdf" name="Loan.pdf">Loan.pdf</li>
	<li class="pdf" name="Report.pdf">Report.pdf</li>
	<li class="pdf" name="Question.pdf">Question.pdf</li>
	<li class="pdf" name="Vaction.pdf">Vaction.pdf</li>
</ul>

When the View PDF Document button is clicked, the first PDF icon in the list is retrieved, as shown in the following JavaScript method. The name of the PDF icon is sent to another method named send.

function ViewDocument() {

		//Get the first element in the drag area
		var dropzoneElements = document.getElementById('PDFDocuments');
		var iter = document.createNodeIterator(dropzoneElements,
		NodeFilter.SHOW_ELEMENT, null, false);
		var loop = true;
		var node = iter.nextNode();
		while ((node != null) && (loop == true)) {

			//Don't want the UL or A (ANchor) Tag -- skip over this tag
			//For each pass -- add a new Field element to the Fields element
			if ((node.tagName != "UL") && (node.tagName != "A")
					&& (node.tagName == "LI")) {

				//Get attributes for this element and build the values into the DOM
				var myname = node.getAttribute("name");

				send(myname);
				loop = false;

			} else {
				node = iter.nextNode();
			}
		}

	}

The send method uses an XMLHttpRequest object to send the PDF file name to the pdfsecure.json.jsp file that calls the OSGi method.

	function send(FileName) {

		var url = location.pathname.replace(".html",
				"/_jcr_content.pdfsecure.json")
				+ "?fileName=" + FileName;

		var request = new XMLHttpRequest();
		request.open('GET', url, false);
		request.send(); // because of "false" above, will block until the request is done 
		                // and status is available. Not recommended, however it works for simple cases.
		                
		var status = request.status ; 

		if (status = 200)
		{
			alert("The "+FileName +" Document is displayed below.") ;  
			 
                 //if2.window.top.location.reload();
                 var iframe = document.getElementById("if2");
                 iframe.src = iframe.src;
        
		}               

	}

Notice if the GET operation is successful, then the IFrame control is refreshed. The OSGi bundle saves a PDF document  (that corresponds to the name passed to the OSGi operation) to the URL. The IFrame control displays the PDF document located at this URL. 

The following code represents the entire templatedrag JSP file. 

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xml:lang="en" xmlns="http://www.w3.org/1999/xhtml" lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<title>CQ Drag and Drop</title>

<script type='text/javascript'
	src='http://code.jquery.com/jquery-1.4.2.js'></script>
<script type="text/javascript"
	src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.4/jquery-ui.js"></script>

<link rel="stylesheet" type="text/css" href="/css/normalize.css" />
<link rel="stylesheet" type="text/css" href="/css/result-light.css" />

<style type='text/css'>
.demo {
	background: darkgray;
	padding: 10px;
}

.demo ul {
	list-style-type: none;
	margin: 0;
	padding: 0;
	margin-bottom: 10px;
}

.demo li {
	margin: 5px;
	padding: background-position :   30px center; 5 px;
	width: 150px;
	height: 40px;
	background: white;
}

#favorites {
	background: silver;
	padding: 10px;
}

#PDFDocuments {
	background: gray;
	padding: 10px;
}

li.pdf {
	background-image: url('[URL TO PDF image file]/pdf.png');
	background-repeat: no-repeat;
	background-position: 140px center;
	box-shadow: inset 0 0 10px #000000;
	background-color: #A52A2A;
	font: bold 12px "helvetica neue", helvetica, arial, sans-serif;
	color: #fff;
	width: 200px;
	height: 50px;
	border: none;
	border-radius: 30%;
}

li.placeholder {
	background: lightgray;
}

li.fav {
	background-image: url();
	background-repeat: no-repeat;
	background-position: 138px center;
}

<!--
.dragOver {
	background: lightblue;
}

-->
#dropbox {
	width: 300px;
	height: 200px;
	border: 1px solid gray;
	border-radius: 5px;
	padding: 5px;
	color: gray;
	overflow: visible;
	background: #BDBDBD;
}
</style>



<script type='text/javascript'>
	//<![CDATA[ 
	$(function() {
		$("ul, li").disableSelection();

		$("#PDFDocuments").sortable( {
			containment : '.demo',
			cursor : "move",
			revert : 200,
			connectWith : "#PDFDocuments, #favorites",
			placeholder : 'placeholder',
			forcePlaceholderSize : true,
			start : startDrag,
			over : overConnectList,
			out : outConnectList,
			receive : doClone
		});

		var itemOriIndex;
		function startDrag(event, ui) {
			itemOriIndex = ui.item.index();
		}

		function doClone(event, ui) {
			if (ui.sender.is('#PDFDocuments')) {

				// clone and insert where we got it
				if (itemOriIndex == 0) {
					ui.item.clone().prependTo('#PDFDocuments');
				} else {
					itemOriIndex -= 1;
					ui.item.clone().insertAfter(
							'#PDFDocuments li:eq(' + itemOriIndex + ')');
				}

				var itemContent = ui.item.text();
				isDouble(itemContent);

				if (isDouble(itemContent) == false) {
					alert('add');
				} else {
					alert('don\'t add');
				}

				// sender favorites 
			} else {

				// clone and insert where we got it
				if (itemOriIndex == 0) {
					ui.item.clone().prependTo('#favorites');
				} else {
					itemOriIndex -= 1;
					ui.item.clone().insertAfter(
							'#favorites li:eq(' + itemOriIndex + ')');
				}
			}
		}

		function isDouble(content) {
			alert(($("#favorites li:contains(" + content + ")").length > 0));
		}

		function overConnectList(event, ui) {
			// This event is triggered when a sortable item is moved into a connected list.
			if (ui.sender.is('#PDFDocuments')) {
				if (ui.item.hasClass('fav')) {
					// $("#favorites").sortable("disable");
					// $(ui.sender).sortable('cancel');
				}
			} else {

			}
		}
		function outConnectList(event, ui) {
			// This event is triggered when a sortable item is moved away from a connected list.
		}

	});//]]>
</script>

<script>
function ViewDocument() {

		//Get the first element in the drag area
		var dropzoneElements = document.getElementById('PDFDocuments');
		var iter = document.createNodeIterator(dropzoneElements,
		NodeFilter.SHOW_ELEMENT, null, false);
		var loop = true;
		var node = iter.nextNode();
		while ((node != null) && (loop == true)) {

			//Don't want the UL or A (ANchor) Tag -- skip over this tag
			//For each pass -- add a new Field element to the Fields element
			if ((node.tagName != "UL") && (node.tagName != "A")
					&& (node.tagName == "LI")) {

				//Get attributes for this element and build the values into the DOM
				var myname = node.getAttribute("name");

				send(myname);
				loop = false;

			} else {
				node = iter.nextNode();
			}
		}

	}

	function send(FileName) {

		var url = location.pathname.replace(".html",
				"/_jcr_content.pdfsecure.json")
				+ "?fileName=" + FileName;

		var request = new XMLHttpRequest();
		request.open('GET', url, false);
		request.send(); // because of "false" above, will block until the request is done 
		                // and status is available. Not recommended, however it works for simple cases.
		                
		var status = request.status ; 

		if (status = 200)
		{
			alert("The "+FileName +" Document is displayed below.") ;  
			 
                 //if2.window.top.location.reload();
                 var iframe = document.getElementById("if2");
                 iframe.src = iframe.src;
        
		}               

	}
	function toBG(obj, color) {
		obj.style.backgroundColor = color;

	}
	$(function() {
		$("#droppable").droppable( {
			drop : function(event, ui) {
				$(ui.draggable).remove();

			}
		});
	});
</script>

</head>
<body>
<H1>Adobe CQ Drag and Drop Client </H1>
<div class="demo">
<h2>View first PDF Document in the list</h2>
<button type="button" onclick= 	ViewDocument(); >View PDF Document</button>
<ul id="PDFDocuments">
	<li class="pdf" name="Policy.pdf">Policy.pdf</li>
	<li class="pdf" name="Loan.pdf">Loan.pdf</li>
	<li class="pdf" name="Report.pdf">Report.pdf</li>
	<li class="pdf" name="Question.pdf">Question.pdf</li>
	<li class="pdf" name="Vaction.pdf">Vaction.pdf</li>
</ul>


<div id="panel5" class="panel">

<p><iframe id="if2"
	src="http://localhost:8400/dataservices/Document.pdf" width="700"
	height="600"> </iframe></p>
</div>

</div>
<!-- End demo -->



</body>

</html>

Note:

Replace the li.pdf background-image value in the CSS section with an URL to a PDF image file so that a PDF icon appears.

To modify the templatedrag.jsp file:

1. To view the CQ welcome page, enter the URL: http://[host name]:[port] into a web browser. For example, http://localhost:4502.

2. Select CRXDE Lite.

3. Double-click apps/drag/components/page/dragtemplate/dragtemplate.jsp.

4. Replace the JSP code with the code shown above.

5. Click Save All.

Create a CQ site that lets users drag and drop a PDF icon

The final task is to create a site that contains a page that is based on the dragtemplate (the template created earlier in this development article). Create a web page that lets users drag and drop content:

1. Go to the CQ welcome page at http://[host name]:[port]; for example, http://localhost:4502.

2. Select Websites.

3. From the left hand pane, select Websites.

4. Select New, New Page.

5. Specify the title of the page in the Title field.

6. Specify the name of the page in the Name field.

7. Select dragtemplate from the template list that appears. This value represents the template that is created in this development article. If you do not see it, then repeat the steps in this development article. For example, if you made a typing mistake when entering in path information when creating the template, the template will not show up in the New Page dialog box.

8. Open the page that you created by double-clicking it in the right pane. The new page opens in a web browser.

This work is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License  Twitter™ and Facebook posts are not covered under the terms of Creative Commons.

Legal Notices   |   Online Privacy Policy