Goal
Create a Multifield (CQ.form.MultiField) with RichText Editor widgets (CQ.form.RichText). User should be able to drag and drop images from content finder onto the richtext editors of multifield. Source code, Package Install and Demo Video are available for download
If an image is dragged into multifield item that already has image(s) added earlier, the new image dropped is appended (not replaced)
Bug Fixes
Tested on AEM 61 - Images couldnot be dropped on dialog close and reopen, unless page is refreshed. Removing a multifield item disables drop on new multifield items Demo | Package Install
Prerequisites
If you are new to CQ visit this blog post; it explains page component basics and setting up your IDE
Create Component
1) Login to CRXDE Lite (http://localhost:4502/crx/de) and create folder /apps/richtext-multifield
2) Copy /libs/foundation/components/text to /apps/richtext-multifield/text and change the componentGroup of text component to My Components
3) Add the following to dialog xml (/apps/richtext-multifield/text/dialog)
<?xml version="1.0" encoding="UTF-8"?> <jcr:root xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:nt="http://www.jcp.org/jcr/nt/1.0" jcr:primaryType="cq:Dialog" helpPath="en/cq/current/wcm/default_components.html#Text" title="Text" xtype="tabpanel"> <items jcr:primaryType="cq:WidgetCollection"> <tab1 jcr:primaryType="cq:Widget" anchor="100%" title="Text" xtype="panel"> <items jcr:primaryType="cq:WidgetCollection"> <text jcr:primaryType="cq:Widget" border="false" hideLabel="{Boolean}true" name="./text" xtype="multifield"> <fieldConfig jcr:primaryType="nt:unstructured" xtype="mrichtext"/> </text> </items> </tab1> </items> </jcr:root>
4) Create /apps/richtext-multifield/text/clientlib of type cq:ClientLibraryFolder and add property categories with value cq.widgets and dependencies with value underscore
5) Create /apps/richtext-multifield/text/clientlib/js.txt of type nt:file and add
richtextmultifield.js
6) Create /apps/richtext-multifield/text/clientlib/richtextmultifield.js of type nt:file and add the following JS logic.
CQ.Ext.ns("RichTextMultiField"); RichTextMultiField.RichText = CQ.Ext.extend(CQ.form.RichText, { afterRender: function() { RichTextMultiField.RichText.superclass.afterRender.call(this); var dialog = this.findParentByType('dialog'); var target = this.dropTargets[0]; if (dialog && dialog.el && target.highlight) { var dialogZIndex = parseInt(dialog.el.getStyle("z-index"), 10); if (!isNaN(dialogZIndex)) { target.highlight.zIndex = dialogZIndex + 1; } } target.parentMultiFieldItem = this.findParentByType("multifielditem"); var multifield = this.findParentByType('multifield'); if(!multifield.dropTargets){ multifield.dropTargets = []; dialog.on('hide', function (){ multifield.dropTargets = []; }); multifield.on("removeditem", function(panel){ resetDropTargets.call(this, panel); }); } multifield.dropTargets.push(target); this.dropTargets = undefined; function resetDropTargets(panel){ var dropTargets = []; var itemFields = panel.findByType("multifielditem"); if(_.isEmpty(itemFields)){ return; } var itemFieldsIds = _.pluck(itemFields, "id"); CQ.Ext.each(this.dropTargets, function(dTarget){ if(_.contains(itemFieldsIds, dTarget.parentMultiFieldItem.id)){ dropTargets.push(dTarget); } }, this); this.dropTargets = dropTargets; } }, syncValue: function() { if(!this.el || !this.el.dom){ return; } RichTextMultiField.RichText.superclass.syncValue.call(this); } }); CQ.Ext.reg('mrichtext', RichTextMultiField.RichText);
7) Line 36, we are extending the ootb richtext with necessary logic and registering as new xtype mrichtext
8) Add the following logic in /apps/richtext-multifield/text/text.jsp
<%@ page import="org.apache.commons.lang3.ArrayUtils" %> <%@include file="/libs/foundation/global.jsp" %> <% String[] texts = properties.get("text", String[].class); if(ArrayUtils.isEmpty(texts)){ %> Configure Texts <% }else{ for(String text : texts){ %> <%= text %> <% } } %>
Good post.
ReplyDeleteEverething works correctly, but after dialog was closed and opened again I can't drag image from content finder.
Error: Uncaught TypeError: Cannot read property 'id' of undefined.
stopFx : function(finish){
var me = this,
id = me.dom.id; ----------------> in this place
if(me.hasActiveFx()){
Do you have any idea how to fix that?
Yes, facing the same issue, tried using cq:editConfig -> cq: listener -> afteredit REFRESH_PAGE property as a work around for a dialog "Ok" button click. However the problem persists when user may click a dialog "cancel" button.
ReplyDeleteA fix to this issue will be of great help !
hi, check the bug fixes section above
ReplyDeleteHi Sreekanth, I have been using this component and realized that up and down arrow keys have stopped working for other components as well. It does not REORDER the content but COPIES it Can you please provide he solution.
ReplyDeletehi Jatin, can you upload the component with dialog to dropbox and share the link here, i'll check when i get some free time..
Delete