AEM 61 - Touch UI Default Image (Placeholder) in Granite File Upload Widget

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.dialogdependencies 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);

2 comments:

  1. Hello Sreekanth, This works perfectly. However, if the author clears image in the dialog and reloads it. We see a broken image. I had seen the same issue with Default Text&Image component. Wondering if you any other workaround for that.

    ReplyDelete
  2. Hi Sreekanth,

    This is great post. Actually i need to show the current image reference in the touch ui dialog. Like we have an info button in th Classic UI, can you provide any suggestion over that?

    ReplyDelete