Quantcast
Channel: Experiencing Adobe Experience Manager (AEM, CQ)
Viewing all articles
Browse latest Browse all 525

AEM 6440 - Touch UI Composite Image Multifield

$
0
0

Goal


Before trying out this extension, check if the AEM Core components Carousel serves your purpose - http://opensource.adobe.com/aem-core-wcm-components/library/carousel.html or using a Pathbrowser is good enough - /libs/granite/ui/components/coral/foundation/form/pathbrowser

Create  a Touch UI Composite Multifield configuration supporting Images, widgets of type /libs/cq/gui/components/authoring/dialog/fileupload

For AEM 62 check this post

Demo | Package Install | Github


Component Rendering




Image Multifield Structure




Nodes in CRX




Dialog



Dialog XML

<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" 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="nt:unstructured"
jcr:title="64 Image Multifield"
sling:resourceType="cq/gui/components/authoring/dialog">
<content
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/fixedcolumns">
<items jcr:primaryType="nt:unstructured">
<column
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/container">
<items jcr:primaryType="nt:unstructured">
<products
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/form/multifield"
composite="{Boolean}true"
fieldLabel="Products">
<field
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/container"
name="./products">
<items jcr:primaryType="nt:unstructured">
<column
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/container">
<items jcr:primaryType="nt:unstructured">
<product
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/form/textfield"
fieldDescription="Name of Product"
fieldLabel="Product Name"
name="./product"/>
<path
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/form/pathbrowser"
fieldDescription="Select Path"
fieldLabel="Path"
name="./path"
rootPath="/content"/>
<file
jcr:primaryType="nt:unstructured"
sling:resourceType="cq/gui/components/authoring/dialog/fileupload"
allowUpload="false"
autoStart="{Boolean}false"
class="cq-droptarget"
fileNameParameter="./fileName"
fileReferenceParameter="./fileReference"
mimeTypes="[image/gif,image/jpeg,image/png,image/webp,image/tiff]"
multiple="{Boolean}false"
name="./file"
title="Upload Image Asset"
uploadUrl="${suffix.path}"
useHTML5="{Boolean}true"/>
</items>
</column>
</items>
</field>
</products>
</items>
</column>
</items>
</content>
</jcr:root>


Solution


1) Login to CRXDE Lite, create folder (nt:folder) /apps/eaem-touchui-image-multifield

2) Create clientlib (type cq:ClientLibraryFolder) /apps/eaem-touchui-image-multifield/clientlib and set a property categories of String type to cq.authoring.dialog.all, dependencies of type String[] with value underscore

3) Create file ( type nt:file ) /apps/eaem-touchui-image-multifield/clientlib/js.txt, add the following

                         image-multifield.js

4) Create file ( type nt:file ) /apps/eaem-touchui-image-multifield/clientlib/image-multifield.js, add the following code

(function ($, $document) {
var COMPOSITE_MULTIFIELD_SELECTOR = "coral-multifield[data-granite-coral-multifield-composite]",
FILE_REFERENCE_PARAM = "fileReference",
registry = $(window).adaptTo("foundation-registry"),
ALLOWED_MIME_TYPE = "image/jpeg",
adapters = registry.get("foundation.adapters");

var fuAdapter = _.reject(adapters, function(adapter){
return ((adapter.type !== "foundation-field") || (adapter.selector !== "coral-fileupload.cq-FileUpload"));
});

if(_.isEmpty(fuAdapter)){
return;
}

fuAdapter = fuAdapter[0];

var orignFn = fuAdapter.adapter;

fuAdapter.adapter = function(el) {
return Object.assign(orignFn.call(el), {
getName: function () {
return el.name;
},
setName: function(name) {
var prefix = name.substr(0, name.lastIndexOf(el.name));

el.name = name;

$("input[type='hidden'][data-cq-fileupload-parameter]", el).each(function(i, el) {
if ($(el).data("data-cq-fileupload-parameter") !== "filemovefrom") {
this.setAttribute("name", prefix + this.getAttribute("name"));
}
});
}
});
};

$document.on("foundation-contentloaded", function(e) {
var composites = $(COMPOSITE_MULTIFIELD_SELECTOR, e.target);

composites.each(function() {
Coral.commons.ready(this, function(el) {
addThumbnails(el);
});
});
});

function addThumbnails(multifield){
var $multifield = $(multifield),
dataPath = $multifield.closest(".cq-dialog").attr("action"),
mfName = $multifield.attr("data-granite-coral-multifield-name");

dataPath = dataPath + "/" + getStringAfterLastSlash(mfName);

$.ajax({
url: dataPath + ".2.json",
cache: false
}).done(handler);

function handler(mfData){
multifield.items.getAll().forEach(function(item, i) {
var $mfItem = $(item),
$fileUpload = $mfItem.find("coral-fileupload");

if(_.isEmpty($fileUpload)){
return;
}

var itemName = getJustItemName($fileUpload.attr("name"));

if(_.isEmpty(mfData[itemName]) || _.isEmpty((mfData[itemName][FILE_REFERENCE_PARAM]))){
return;
}

var imagePath = mfData[itemName][FILE_REFERENCE_PARAM];

$fileUpload.trigger($.Event("assetselected", {
path: imagePath,
group: "",
mimetype: ALLOWED_MIME_TYPE, // workaround to add thumbnail
param: "",
thumbnail: getThumbnailHtml(imagePath)
}));
});
}

function getThumbnailHtml(path){
return "<img class='cq-dd-image' src='" + path + "/_jcr_content/renditions/cq5dam.thumbnail.319.319.png'>";
}

function getJustItemName(itemName){
itemName = itemName.substr(itemName.indexOf(mfName) + mfName.length + 1);

itemName = itemName.substring(0, itemName.indexOf("/"));

return itemName;
}
}

function getStringAfterLastSlash(str){
if(!str || (str.indexOf("/") == -1)){
return "";
}

return str.substr(str.lastIndexOf("/") + 1);
}
}(jQuery, jQuery(document)));


5) To render the composite multifield items eg. to create a Image Gallery component, create a HTL render script /apps/eaem-touchui-image-multifield/sample-image-multifield/sample-image-multifield.html

<div>
<b>6420 Composite Image Multifield</b>

<div data-sly-use.company="helper.js" data-sly-unwrap>
<div data-sly-test="${!company.products && wcmmode.edit}">
Add products using component dialog
</div>

<div data-sly-test="${company.products}">
<div data-sly-list.product="${company.products}">
<div>
<div>${product.name}</div>
<div>${product.path}</div>
<div><img src="${product.fileReference}" width="150" height="150"/></div>
</div>
</div>
</div>
</div>
</div>


6) Finally a HTL use-script to read the multifield data /apps/eaem-touchui-image-multifield/sample-image-multifield/helper.js

"use strict";

use( ["/libs/wcm/foundation/components/utils/ResourceUtils.js","/libs/sightly/js/3rd-party/q.js" ], function(ResourceUtils, Q){
var prodPromise = Q.defer(), company = {},
productsPath = granite.resource.path + "/products";

company.products = undefined;

ResourceUtils.getResource(productsPath)
.then(function (prodParent) {
return prodParent.getChildren();
})
.then(function(products) {
addProduct(products, 0);
});

function addProduct(products, currIndex){
if(!company.products){
company.products = [];
}

if (currIndex >= products.length) {
prodPromise.resolve(company);
return;
}

var productRes = products[currIndex],
properties = productRes.properties;

var product = {
path: properties.path,
name: properties.product,
fileReference: properties.fileReference
};

company.products.push(product);

addProduct(products, (currIndex + 1));
}

return prodPromise.promise;
} );




Viewing all articles
Browse latest Browse all 525

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>