Expand my Community achievements bar.

Don’t miss the AEM Skill Exchange in SF on Nov 14—hear from industry leaders, learn best practices, and enhance your AEM strategy with practical tips.
SOLVED

Links disappearing from RTE

Avatar

Level 2

Hi,

We have an RTE component. Our client has put links using the link plugin. But some times suddenly in some places the link disappears. I mean the anchor tag remains but the href property just disappears. 

Could anyone please help me out on this.

 

Thanks,

Tushar

1 Accepted Solution

Avatar

Correct answer by
Administrator

Hi

This is an bug.

Please reach out to the daycare with :- https://daycare.day.com/content/home/cbacomau/cbacomau_au/customer_services/105196.html#post0017 as a reference.

Workaround

In richtext.js (/libs/cq/gui/components/authoring/dialog/richtext/clientlibs/richtext/js/richtext.js).

In the file change the function 'rteFinish' from :
var rteFinish = function() {
        var rteInstance = $(this).data("rteinstance");
        if (rteInstance) {
            rteInstance.finish(false);
        }
};
to
var rteFinish = function() {
        var rteInstance = $(this).data("rteinstance");
        if (rteInstance) {
            rteInstance.finish(false);
            $(this).removeData("rteinstance");
        }
};

It will help you.

~kautuk



Kautuk Sahni

View solution in original post

10 Replies

Avatar

Community Advisor

It could be a code issue or the issue with link checker that for some reason identifies the links as not reachable. 

Try disabling the link checker and see if its still the same behavior.

You can disable link checking through felix console - http://<ip>:<port>/system/console/configMgr/com.day.cq.rewriter.linkchecker.impl.LinkCheckerTransformerFactory

If the problem still persist, then probably its the code issue. Are you doing any additional processing on link on page load? or through rewrite pipeline?

Avatar

Administrator

Hi 

Few questions here, what type of links are getting disappear ? and specific internal links or external links ?

Do you get any error or any xss warning ? 

Last, wherever you have href written add additional attribute x-cq-linkchecker= skip" or  Disable link checker and check.

 

Reference article :- http://experience-aem.blogspot.in/2015/05/aem-6-sp2-handling-custom-protocol-in-link-href-in-rte.htm...

I hope this would help you.

~kautuk



Kautuk Sahni

Avatar

Level 2

Hi,

What I have seen the external links are getting disappeared. I have already disabled link checker and trying.

The think this does not happen to all the links, it happens to some links only.

Thanks,

Tushar

Avatar

Community Advisor

Just to rule out the case of code issue, can you please configure the same links on geometrixx pages and see if its still getting disabled?

- Runal

Avatar

Correct answer by
Administrator

Hi

This is an bug.

Please reach out to the daycare with :- https://daycare.day.com/content/home/cbacomau/cbacomau_au/customer_services/105196.html#post0017 as a reference.

Workaround

In richtext.js (/libs/cq/gui/components/authoring/dialog/richtext/clientlibs/richtext/js/richtext.js).

In the file change the function 'rteFinish' from :
var rteFinish = function() {
        var rteInstance = $(this).data("rteinstance");
        if (rteInstance) {
            rteInstance.finish(false);
        }
};
to
var rteFinish = function() {
        var rteInstance = $(this).data("rteinstance");
        if (rteInstance) {
            rteInstance.finish(false);
            $(this).removeData("rteinstance");
        }
};

It will help you.

~kautuk



Kautuk Sahni

Avatar

Level 4

Kautuk,

Our team has a client experiencing the exact same issue. The code you provided does not resolve the problem. Is there any other direction we can take to solve this without going through daycare? Any hotfix or other update we can try?

Avatar

Level 4

Hi Katauk,

We are facing similar issue in rte inside a multifield.

href is getting removed from anchor tag.

Tried above solution but it is not working.

AEM Version : 6.2

We are saving nested multifield content as json.

Could you please let us know if we are missing anything else here.

Multifield js-

(function () {

    var DATA_EAEM_NESTED = "data-eaem-nested";

    var CFFW = ".coral-Form-fieldwrapper";

    var RTE_CONTAINER = "richtext-container";

    var RTE_EDITABLE = ".coral-RichText-editable";

    function setSelect($field, value){

        var select = $field.closest(".coral-Select").data("select");

        if(select){

            select.setValue(value);

        }

    }

    function setCheckBox($field, value){

        $field.prop( "checked", $field.attr("value") == value);

    }

     function setDateField($field, value) {

         if (value != "") {

            var date = moment(new Date(value)),

            $parent = $field.parent();

            $parent.find("input.coral-Textfield").val(date.format($parent.data("displayed-format")));

    

            $field.val(date.format($parent.data("stored-format")));

         }

       

    }

     function setHiddenOrRichText($field, value){

        $field.val(value);

        var $rteContainer = $field.parent();

        $(".richtext-container .coral-RichText-editable").css("height", "7rem");

        if(!$rteContainer.hasClass(RTE_CONTAINER)){

            return;

        }

        $rteContainer.children(RTE_EDITABLE).empty().append(value);

    }

    //reads multifield data from server, creates the nested composite multifields and fills them

    function addDataInFields() {

        $(document).on("dialog-ready", function() {

            dialogMultifield();

            $(".coral-RichText-editable").css("height", "7rem");    

        });

        // For page properties opened from projects.html in AEM

        if(('#shell-propertiespage-saveactivator').length){

            dialogMultifield();

        }

        function dialogMultifield(){

            if($("[data-eaem-nested][class='coral-Form-fieldset']").data("name") == "./iTabs"){

                if($("ol.js-coral-Multifield-list li").length == 5){

                    $("button.js-coral-Multifield-add").attr('disabled','true');

                }

            }

            var $fieldSets = $("[" + DATA_EAEM_NESTED + "][class='coral-Form-fieldset']");

            if(_.isEmpty($fieldSets)){

                return; 

            }

            var mNames = [];

            $fieldSets.each(function (i, fieldSet) {

                mNames.push($(fieldSet).data("name"));

            });

            mNames = _.uniq(mNames);

            var actionUrl = $fieldSets.closest("form.foundation-form").attr("action") + ".json";

            $.ajax(actionUrl).done(postProcess);

            function postProcess(data){

                _.each(mNames, function(mName){

                    buildMultiField(data, mName);

                });

            }

            //creates & fills the nested multifield with data

            function fillNestedFields($multifield, valueArr){

                _.each(valueArr, function(record, index){

                    $multifield.find(".js-coral-Multifield-add").click();

                    //a setTimeout may be needed

                    _.each(record, function(value, key){

                        var $field = $($multifield.find("[name='./" + key + "']")[index]);

                        var  type = $field.prop("type");

                         if(type == "hidden"){

                                setHiddenOrRichText($field, value);

                            }else{

                                $field.val(value);

                            }

                    })

                })

            }

            function buildMultiField(data, mName){

                if(_.isEmpty(mName)){

                    return;

                }

                $fieldSets = $("[data-name='" + mName + "']");

                //strip ./

                mName = mName.substring(2);

                var mValues = data[mName], $field, name,type;

                if(_.isString(mValues)){

                    mValues = [ JSON.parse(mValues) ];

                }

                _.each(mValues, function (record, i) {

                    if (!record) {

                        return;

                    }

                    if(_.isString(record)){

                        record = JSON.parse(record);

                    }

                    _.each(record, function(rValue, rKey){

                        $field = $($fieldSets[i]).find("[name='./" + rKey + "']");

                        type = $field.prop("type");

                        //handle single selection dropdown

                        if( type == "select-one"){

                            setSelect($field, rValue);

                        }else if( type == "checkbox"){

                            setCheckBox($field, rValue);

                        }else if( $field.parent().hasClass("coral-DatePicker")) {

                               setDateField($field, rValue);

                        }else if(type == "hidden"){

                            setHiddenOrRichText($field, rValue);

                        }else{

                            $field.val(rValue);

                        }

                        if(_.isArray(rValue) && !_.isEmpty(rValue)){

                            fillNestedFields( $($fieldSets[i]).find("[data-init='multifield']"), rValue);

                        }else{

                            $field.val(rValue);

                        }

                    });

                });

            }

        }

    }

    function fillValue($field, record){

        var name = $field.attr("name");

        if (!name) {

            return;

        }

        //strip ./

        if (name.indexOf("./") == 0) {

            name = name.substring(2);

        }

        if(name!='textIsRich') {

                record[name] = $field.val();

                }

        if( $field.prop("type") == "checkbox" ){

            value = $field.prop("checked") ? $field.val() : "";

        }

        //remove the field, so that individual values are not POSTed

        $field.remove();

    }

    //for getting the nested multifield data as js objects

    function getRecordFromMultiField($multifield){

        var $fieldSets = $multifield.find("[class='coral-Form-fieldset']");

        var records = [], record, $fields, name;

        $fieldSets.each(function (i, fieldSet) {

            $fields = $(fieldSet).find("[name]");

            record = {};

            $fields.each(function (j, field) {

                fillValue($(field), record);

            });

            if(!$.isEmptyObject(record)){

                records.push(record)

            }

        });

        return records;

    }

    //collect data from widgets in multifield and POST them to CRX as JSON

    function collectDataFromFields(){

        $(document).on("click", "#shell-propertiespage-saveactivator, .cq-dialog-submit", function (e) {

            e.prevent

            var $form = $(this).closest("form.foundation-form");

            // For page properties that are opened from projects.html in AEM

            if($(this).closest(".foundation-layout-panel") !== undefined && $(this).closest(".foundation-layout-panel").length){

                $form = $(this).closest(".foundation-layout-panel").find('form.foundation-form');

            }

            var $fieldSets = $("[" + DATA_EAEM_NESTED + "][class='coral-Form-fieldset']");

            var record, $fields, $field, name, $nestedMultiField;

            $fieldSets.each(function (i, fieldSet) {

                $fields = $(fieldSet).children().children(CFFW);

                record = {};

                $fields.each(function (j, field) {

                    $field = $(field);

                    //may be a nested multifield

                    $nestedMultiField = $field.find("[data-init='multifield']");

                    if($nestedMultiField.length == 0){

                        fillValue($field.find("[name]"), record);

                    }else{

                        name = $nestedMultiField.find("[class='coral-Form-fieldset']").data("name");

                        if(!name){

                            return;

                        }

                        //strip ./

                        name = name.substring(2);

                        record[name] = getRecordFromMultiField($nestedMultiField);

                    }

                });  

                if ($.isEmptyObject(record)) {

                    return;

                }

                //add the record JSON in a hidden field as string

                $('<input />').attr('type', 'hidden')

                .attr('name', $(fieldSet).data("name"))

                .attr('value', JSON.stringify(record))

                .appendTo($form);

            });

        });

    }

    $(document).ready(function () {

        addDataInFields();

        collectDataFromFields();

    });

    //extend otb multifield for adjusting event propagation when there are nested multifields

    //for working around the nested multifield add and reorder

    CUI.Multifield = new Class({

        toString: "Multifield",

        extend: CUI.Multifield,  

        construct: function (options) {

            this.script = this.$element.find(".js-coral-Multifield-input-template:last");

        },

        _addListeners: function () {

            this.superClass._addListeners.call(this);

            //otb coral event handler is added on selector .js-coral-Multifield-add

            //any nested multifield add click events are propagated to the parent multifield

            //to prevent adding a new composite field in both nested multifield and parent multifield

            //when user clicks on add of nested multifield, stop the event propagation to parent multifield

            this.$element.on("click", ".js-coral-Multifield-add", function (e) {

                  $(".richtext-container .coral-RichText-editable").css("height", "7rem");

                if($("[data-eaem-nested][class='coral-Form-fieldset']").data("name") == "./iTabs"){

                    if($("ol.js-coral-Multifield-list li").length == 5){

                        $("button.js-coral-Multifield-add").attr('disabled','true');

                    }

                }

                e.stopPropagation();

            });

            this.$element.on("click", ".js-coral-Multifield-remove", function (e) {

                if($("[data-eaem-nested][class='coral-Form-fieldset']").data("name") == "./iTabs"){

                    if($("ol.js-coral-Multifield-list li").length != 5){

                        $("button.js-coral-Multifield-add").removeAttr('disabled');

                    }

                }

                e.stopPropagation();

            });

            this.$element.on("drop", function (e) {

                e.stopPropagation();

            });

        }

    });

    CUI.Widget.registry.register("multifield", CUI.Multifield);

})();

Avatar

Level 1

Hi Katauk,

I don't find the method you suggested in AEM 5.6.1. Please let know where this should be changed for AEM 5.6.1

I see same issue happening in my richtext but the anchor tag is nested inside div tag this html is added using custom rte plugin.

Thanks

Amala

Avatar

Level 1

I had same issue, so I resolved it by adding like this(<a href="link" _rte_href="same link"></a>) to <a> tag.