AEM 6550 - Touch UI Rich Text Editor, configure emptyText

Goal

Configure emptyText property in Rich Text Editor (RTE) configuration to show placeholder text before entering content...

Another way is probably using CSS hack like below and setting data-eaem-placeholder attribute on the RTE div (however, it does not show the placeholder when there are empty tags in RTE, with no text content)...

[data-cq-richtext-editable="true"]:empty:before {
    content:attr(data-eaem-placeholder);
    color:gray
}


Demo | Package Install | Github


Configure emptyText

                   /apps/core/wcm/components/text/v2/text/cq:dialog/content/items/tabs/items/properties/items/columns/items/column/items/text

                     emptyText=Experience AEM - This richtext editor is empty, add some text...




Placeholder Text in RTE


Solution

1) Login to CRXDE Lite (http://localhost:4502/crx/de), create folder /apps/eaem-rte-empty-text

2) Create node /apps/eaem-rte-empty-text/clientlib of type cq:ClientLibraryFolder, add String[] property categories with value [cq.authoring.dialog.all], String[] property dependencies with value lodash.

3) Create file (nt:file) /apps/eaem-rte-empty-text/clientlib/css.txt, add


                        rte-empty-text.css

4) Create file (nt:file) /apps/eaem-rte-empty-text/clientlib/rte-empty-text.css, add the following code

.eaem-rte-placeholder{
    color: gray;
    display: block;
}


5) Create file (nt:file) /apps/eaem-rte-empty-text/clientlib/js.txt, add

                        rte-empty-text.js

6) Create file (nt:file) /apps/eaem-rte-empty-text/clientlib/rte-empty-text.js, add the following code

(function($, $document){
    var RTE_SEL = "[data-cq-richtext-editable='true']",
        DATA_PLACE_HOLDER = "data-eaem-rte-placeholder",
        PLACE_HOLDER_CSS = "eaem-rte-placeholder";

    $document.on("dialog-ready", function(){
        $(RTE_SEL).each(addPlaceHolderTextInData);
    });

    $document.on("click", ".cq-dialog-submit", handleBeforeSubmit);

    function handleBeforeSubmit(e){
        e.stopPropagation();
        e.preventDefault();

        $(RTE_SEL).each(clearPlaceholderText);

        var $form = $(this).closest("form.foundation-form"),
            $rteInputs = $form.find("[data-cq-richtext-input='true']");

        _.each($rteInputs, function(input){
            var $input = $(input),
                val = $input.val();

            if(!val.includes(PLACE_HOLDER_CSS)){
                return;
            }

            $input.val(getPlaceHolderTextRemovedFromRTEInput(val));
        });

        $form.submit();
    }

    function getPlaceHolderTextRemovedFromRTEInput(val){
        //todo: when there is no text, placeholder is getting saved, find a better way to remove
        return val.substring(val.indexOf("</div>") + 6);
    }

    function addPlaceholderText(){
        var $rte = $(this),
            text = $rte.text().trim(),
            placeholderText = $rte.attr(DATA_PLACE_HOLDER);

        if(!placeholderText){
            return;
        }

        if(text){
            $rte.find("." + PLACE_HOLDER_CSS).remove();
        }else{
            $rte.prepend(getPlaceholder(placeholderText));
        }
    }

    function clearPlaceholderText(){
        $(this).find("." + PLACE_HOLDER_CSS).remove();
    }

    function getPlaceholder(text){
        return "<div class='" + PLACE_HOLDER_CSS + "'>" + text + "</div>";
    }

    function addPlaceHolderTextInData(index, rte){
        var $rte = $(rte),
            configPath = $rte.attr("data-config-path");

        if(!configPath){
            return;
        }

        $.ajax(configPath).done(function(data){
            var emptyText = data["emptyText"];

            if(!emptyText){
                return;
            }

            $rte.attr(DATA_PLACE_HOLDER, emptyText);

            $rte.change(addPlaceholderText);

            $rte.click(clearPlaceholderText);

            addPlaceholderText.call($rte[0]);
        })
    }
}(jQuery, jQuery(document)));

2 comments:

  1. This comment has been removed by the author.

    ReplyDelete
  2. The code is really helpful. Just 1 suggestion, it would be better to use custom value for categories instead of "[cq.authoring.dialog.all]" and add the same in extraClientlibs property of dialog. Using the "[cq.authoring.dialog.all]" might interfere with the existing OOTB JS/JQuery.

    ReplyDelete