AEM 63 - Touch UI Extend Rich Text Link Dialog, Add Rel Attribute Select

Goal


Extend the Link Dialog of Touch UI Rich Text Editor to add Coral Select widget for selecting rel attribute of anchor tag

For AEM 62 check this post

Demo | Package Install | Github


rel Attribute select in Link Dialog




rel Applied to Anchor Tag




AntiSamy considerations

Adding new attributes in anchor tag may result in the attributes skipped during page rendering or link dialog load; the following warning can be seen in error.log...

26.09.2017 12:40:42.804 *INFO* [0:0:0:0:0:0:0:1 [1506447642680] GET /content/we-retail/language-masters/en.html HTTP/1.1] org.apache.sling.xss.impl.HtmlToHtmlContentContext AntiSamy warning: The a tag contained an attribute that we could not process. The rel attribute had a value of "bookmark". This value could not be accepted for security reasons. We have chosen to remove this attribute from the tag and leave everything else in place so that we could process the input.

To make rel accepted,  make the following changes in /apps/cq/xssprotection/config.xml (overlaying /libs/cq/xssprotection/config.xml), for Sightly/HTL its /libs/sling/xss/config.xml




Solution


1) Login to CRXDE Lite, create folder (nt:folder) /apps/eaem-touchui-extend-rte-link-options

2) Create clientlib (type cq:ClientLibraryFolder/apps/eaem-touchui-extend-rte-link-options/clientlib and set property categories of String type to cq.authoring.dialog.all and dependencies String[] to lodash

3) Create file ( type nt:file ) /apps/eaem-touchui-extend-rte-link-options/clientlib/js.txt, add the following

                         link-options.js

4) Create file (type nt:file) /apps/eaem-touchui-extend-rte-link-options/clientlib/link-options.js, add the following code

(function ($) {
    "use strict";

    var _ = window._,
        Class = window.Class,
        CUI = window.CUI,
        REL_FIELD = "rel",
        RTE_LINK_DIALOG = "rtelinkdialog";

    if(CUI.rte.ui.cui.CuiDialogHelper.eaemExtended){
        return;
    }

    var EAEMLinkBaseDialog = new Class({
        extend: CUI.rte.ui.cui.CQLinkBaseDialog,

        toString: "EAEMLinkBaseDialog",

        initialize: function(config) {
            this.superClass.initialize.call(this, config);

            this.$rteDialog = this.$container.find("[data-rte-dialog=link]");

            this.$rteDialog.find(".rte-dialog-columnContainer:last").before(getLinkRelOptionsHtml());
        },

        dlgToModel: function() {
            this.superClass.dlgToModel.call(this);

            var relField = this.getFieldByType(REL_FIELD);

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

            var relVal = relField.val();

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

            this.objToEdit.attributes["rel"] = relVal;
        },

        dlgFromModel: function() {
            this.superClass.dlgFromModel.call(this);

            if(_.isEmpty(this.objToEdit.attributes)){
                return;
            }

            var relValue = this.objToEdit.attributes['rel'];

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

            var relSelect = this.$rteDialog.find("[data-type='rel']")[0];

            relSelect.items.getAll().forEach(function(elem) {
                elem.selected = (elem.value === relValue);
            });
        }
    });

    CUI.rte.ui.cui.CuiDialogHelper = new Class({
        extend: CUI.rte.ui.cui.CuiDialogHelper,

        toString: "EAEMCuiDialogHelper",

        instantiateDialog: function(dialogConfig) {
            var type = dialogConfig.type;

            if(type !== RTE_LINK_DIALOG){
                this.superClass.instantiateDialog.call(this, dialogConfig);
                return;
            }

            var $editable = $(this.editorKernel.getEditContext().root),
                $container = CUI.rte.UIUtils.getUIContainer($editable),
                dialog = new EAEMLinkBaseDialog();

            dialog.attach(dialogConfig, $container, this.editorKernel);

            return dialog;
        }
    });

    function getLinkRelOptionsHtml(){
        var html =  "<div class='rte-dialog-columnContainer'>" +
                    "<div class='rte-dialog-column'>" +
                    "<coral-select data-type='rel' placeholder='Choose \"rel\" attribute'>";

        var options = ["alternate", "author", "bookmark", "external", "help",
                        "license", "next", "nofollow", "noreferrer", "noopener", "prev", "search", "tag" ];

        _.each(options, function(option){
            html = html + getOptionHtml(option);
        });

        html = html + "</coral-select></div></div>";

        return html;

        function getOptionHtml(option){
            return "<coral-select-item>" + option + "</coral-select-item>"
        }
    }

    CUI.rte.ui.cui.CuiDialogHelper.eaemExtended = true;
})(jQuery);




1 comment:

  1. Hi Sreekanth,
    It's awesome concept, it's works fine in my local server. But same is not working my production server in author instance, it's working in my production server in publish server. I think xssprotection have some restriction for security reasons. could you please give me proper solution for production author server.

    ReplyDelete