Skip to main content

Adobe

How to Create “Drag and Drop” Experiences for AEM Authors

In this blog post, I’m going to show you how to enable custom drag and drop interactions in AEM Author mode. In my specific use case, I wanted to give authors the ability to drag assets and drop them into dialog field. Upon dropping, the asset path should be copied into the field.
This article assumes basic knowledge of AEM clientlibs, JavaScript, and jQuery.
First, let’s create a clientlib with appropriate categories and dependencies:

  • categories: cq.authoring.dialog (this clientlib will be included as part of clientlibs for authoring dialog)
  • dependencies: cq.authoring.editor (this client lib depends on editor clientlib, which has the interaction definition – we’ll get to that in a second)

Now that we have a clientlib, let’s define the interaction!
Granite.author.ui.Interaction is OOTB JavaScript prototype defined in the JCR path:  /libs/cq/gui/components/authoring/clientlibs/editor/js/ui/ui.Interaction.js 
Take a look at the prototype and its API.
Here is how to use Interaction to create a Drag and Drop experience:
(I’m attaching a working package to the end of this blog.)

This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
/* JsLint ignore Granite object from validation */
/* globals Granite*/
//define new interaction for dropping assets into fields, this wil copy the Asset's path into the field
var customePathbrowserInteraction;
(function (Granite, $) {
if (Granite && Granite.author && Granite.author.ui && Granite.author.ui.Interaction) {
// selector of element we want to drag
var DRAGGABLE_SELECTOR = '.cq-draggable.card-asset',
// selecttor of target element
DROP_TARGET_SELECTOR = '.js-coral-pathbrowser-input',
// class to be added when dropzone is active, ie. we started dragging
// use this class to add some border color to indicate that element is droppable in this zone
DROPZONE_ACTIVE = 'custom-dropzone-active',
// class to be added when dragged element is over dropzone
// use this class to add some border color to indicate that element is droppable in this zone
DROPZONE_OVER = 'custom-dropzone-over',
// true to log all events
logMessages = true;
var log = function(msg){
if(logMessages){
console.log(msg);
}
};
customePathbrowserInteraction = customePathbrowserInteraction || new Granite.author.ui.Interaction({
// The selector of elements that can be dragged
dragOrigin: DRAGGABLE_SELECTOR,
// The drop target/ drop zone element selector
dropTarget: DROP_TARGET_SELECTOR,
// when entering dropTarget
enter: function (e) {
log("enter");
if (e.target) {
$(e.target).addClass(DROPZONE_OVER);
}
},
// when over dropTarget
over: function () {
log("over");
},
// when leaving dropTarget
leave: function (e) {
log("leave");
if (e.target) {
$(e.target).removeClass(DROPZONE_OVER).addClass(DROPZONE_ACTIVE);
}
},
// when dropping dragOrigin into dropTarget
drop: function (e) {
log("drop");
if (e.target && this.path) {
var $target = $(e.target);
$target.val(this.path);
// optional to check if the input fiels is valid
$target.checkValidity();
$target.updateErrorUI();
}
},
// when starting to drag dragOrigin
start: function (e) {
log("start");
this.path = (e.target) ? $(e.target).data("path") : "";
this.$dropTarget = $(DROP_TARGET_SELECTOR);
this.$dropTarget.addClass(DROPZONE_ACTIVE);
},
// end drag or dropped
end: function () {
log("end");
this.$dropTarget.removeClass(DROPZONE_ACTIVE).removeClass(DROPZONE_OVER);
}
});
}
})(Granite, Granite.$);

The above code is documented line by line. But let’s explore what is happening:
Line 10-19, we define some constants for classes we’d like use later on.
Line 29, we instantiate a new Interaction via its constructor. We pass an object to the constructor that has the following properties:

  • dragOrigin:{String} a CSS selector (class/id/etc) of an element that can be dragged.
  • dropTarget: {String} a CSS selector (class/id/etc) of the element we can drop onto.
  • start {Function} called once when we start dragging dragOrigin
  • end {Function} called once at the end of interaction
  • enter {Function} called when dragging dragOrigin, then entering the dropTarget
  • over {Function} called when dragOrigin is dragged over dropTarget
  • leave {Function} called after enter if dragOrigin leaves dropTarget
  • drop {Function} called if dragOrigin is dropped onto dropTarget

Additionally, on each of those functions above, we are adding CSS classes to dropTarget backed by CSS rules that will add border styling once a user starts the interaction (drags a dragOrigin).
Line 58, we are setting the dropzone’s val to the path of the dragged image. In this case, I know the dropzone is an input.
Here is a package that you can deploy on your AEM instance:
interactionSample.zip

Tags

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Ahmed Musallam, Adobe Technical Lead

Ahmed is an Adobe Technical Lead and expert in the Adobe Experience Cloud.

More from this Author

Categories
Follow Us