Goal
Add default (placeholder) image capability to components with Granite File Upload widgets granite/ui/components/foundation/form/fileupload in cq:dialog. In the demo, a custom component /apps/touchui-fileupload-default-image/sample-image-component with two file upload widgets in cq:dialog are configured with placeholder attribute value /content/dam/Paintings/Placeholder.png. When a new component editable is created using drag/drop on page, the file upload widget fileReferenceParameter value is automatically filled with the placeholder file path. When a new component is added, user will always see placeholder image first, before any image can be dropped or uploaded in widget. The placeholder image may provide some instructions on what type of images can be used for the widget (eg. the placeholder may say upload PNGs only)
Demo | Package Install
Placeholder Image added on Component Drop
Placeholder configuration in cq:dialog
Placeholder path in CRX, added on Component Drop
Solution
1) Login to CRXDE Lite, create folder (nt:folder) /apps/touchui-fileupload-default-image
2) Create clientlib (type cq:ClientLibraryFolder) /apps/touchui-fileupload-default-image/clientlib and set a property categories of String type to cq.authoring.dialog, dependencies of type String[] with value underscore
3) Create file ( type nt:file ) /apps/touchui-fileupload-default-image/clientlib/js.txt, add the following
default-image.js
4) Create file ( type nt:file ) /apps/touchui-fileupload-default-image/clientlib/default-image.js, add the following code
(function ($document, gAuthor) {
var COMPONENT = "touchui-fileupload-default-image/sample-image-component",
FILE_UPLOAD_WIDGET = "granite/ui/components/foundation/form/fileupload",
DROP_TARGET_ENABLED_CLASS = "js-cq-droptarget--enabled",
FILE_REF_PARAM = "fileReferenceParameter",
PLACEHOLDER_PARAM = "placeholder";
$document.on('cq-inspectable-added', addPlaceholder);
$document.on('mouseup', setNewDropFlag);
var newComponentDrop = false;
function setNewDropFlag(event){
var LM = gAuthor.layerManager;
if (LM.getCurrentLayer() != "Edit") {
return;
}
var DC = gAuthor.ui.dropController,
generalIH = DC._interactionHandler.general;
if (!generalIH._hasStarted || !$(event.target).hasClass(DROP_TARGET_ENABLED_CLASS)) {
return;
}
newComponentDrop = true;
}
function addPlaceholder(event){
var LM = gAuthor.layerManager;
if ( (LM.getCurrentLayer() != "Edit") || !newComponentDrop) {
return;
}
newComponentDrop = false;
var editable = event.inspectable;
if(editable.type !== COMPONENT){
return;
}
$.ajax(editable.config.dialog + ".infinity.json").done(postPlaceholder);
function postPlaceholder(data){
var fileRefs = addFileRefs(data, {});
if(_.isEmpty(fileRefs)){
return;
}
$.ajax({
type : 'POST',
url : editable.path,
data : fileRefs
}).done(function(){
editable.refresh();
})
}
function addFileRefs(data, fileRefs){
if(_.isEmpty(data)){
return fileRefs;
}
_.each(data, function(value, key){
if(_.isObject(value)){
addFileRefs(value, fileRefs);
}
if( (key != "sling:resourceType") || (value != FILE_UPLOAD_WIDGET)){
return;
}
if(!data[FILE_REF_PARAM] || !data[PLACEHOLDER_PARAM]){
return;
}
fileRefs[data[FILE_REF_PARAM]] = data[PLACEHOLDER_PARAM];
}, this);
return fileRefs;
}
}
})($(document), Granite.author);