7

When copy-pasting content with line breaks into RTF fields in the Content Manager (2013 SP1 HR1) in Firefox and Chrome I see different HTML generated in the source tab. Is anyone aware of a fix for this other than manually editing the source?

Here's the source in Firefox...

enter image description here

and in Chrome

enter image description here

This is the test text for anyone wanting to test this out

Lorem ipsum dolor sit amet, consectetur adipiscing elit.

Vestibulum dui sapien, egestas id odio a.
sollicitudin vestibulum nisi.

Morbi ut sapien ut arcu viverra accumsan tincidunt vel neque.
  • 2
    In SDL Tridion 2011 the browsers handled returns differently, but there was an update to the default rich text format area XSLT filter. See webmasters.stackexchange.com/q/29505/15311 for the behavior. Does changing tabs or saving change the markup? Do you see the same for new Schemas (I believe older Schemas keep their original XSLT filters)? – Alvin Reyes Oct 15 '15 at 16:11
  • I tried the above in Tridion 2013 SP1 HR1 with Google Chrome 45.0.2 and got the something similar to the below. <pre class="default prettyprint prettyprinted" style="margin-top: 0px; padding: 5px;> <code style="margin: 0px; padding: 0px; border: 0px; font-family: Consolas, Menlo, Monaco, 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace, sans-serif; white-space: inherit;"><span class="typ" style="margin: 0px; padding: 0px; border: 0px; color: rgb(43, 145, 175);">Lorem</span> – Shiva Oct 22 '15 at 18:07
  • It`s sdl tridion product issue. please create sdl support for this RTF copy and Paste Issue. – Sudhakar Rao Aug 4 '17 at 21:44
1

We implemented the ValidateRtfCopyPasteCommand Extension to resolve this issue. Please find sample code below:

     Tridion.Type.registerNamespace("SDLPS.Extensions");

        SDLPS.Extensions.ValidateRtfInputCommand = function ValidateRtfInputCommand() {
            Tridion.OO.enableInterface(this, "SDLPS.Extensions.ValidateRtfInputCommand");
            this.addInterface("Tridion.Web.UI.Editors.Base.Commands.CommandBase", ["ValidateRtfInputCommand"]);};

        SDLPS.Extensions.ValidateRtfInputCommand.prototype._isAvailable = function ValidateRtfInputCommand$_isAvailable(selection, pipeline) {  
            return true;
        };

        SDLPS.Extensions.ValidateRtfInputCommand.prototype._isEnabled = function ValidateRtfInputCommand$_isEnabled(selection, pipeline) {    
            return true;
        };

    // Global variables exposed to all
    var currentData_cpc = {};
    var pasteEventFired_cpc = false;
    var activateExtension_cpc = false;
    $vri = SDLPS.Extensions.ValidateRtfInputCommand;
    $vri.range, $vri.cursorLocation;
    $vri.markerId = "PasteParent";


    // the pasted entry will be stripped of <br> tags if set to false the pasted content will be left as is.
    $vri.removeBrExisting = true;


    if ($display && activateExtension_cpc) {
        $evt.addEventHandler($display, "start", onDisplayStarted_cpc);
    }


    function onDisplayStarted_cpc() {  
        $evt.removeEventHandler($display, "start", onDisplayStarted_cpc);
        var view = $display.getView();
        if (view && Tridion.OO.implementsInterface(view, "Tridion.Cme.Views.Component")) {
            var fieldBuilder = view.properties.controls.fieldBuilder;
            $evt.addEventHandler(fieldBuilder, "load", _applyLoadEvent_cpc);      
            $evt.addEventHandler(fieldBuilder, "change", _applyLoadEvent_cpc);      
            $evt.addEventHandler(fieldBuilder, "insert", _applyLoadEvent_cpc);  
        }
    }

function evtPaste_cpc(event) {

    var entryKey = this.entrykey;
    var curCtrl = $j("iframe.FAIFrame[id='" + entryKey + "']");
    var selection = curCtrl.focus()[0].contentWindow.getSelection();

    $vri.range = selection.getRangeAt(0);
    $vri.caretStartContainer = $vri.range.startContainer;
    if ($vri.caretStartContainer.firstChild) {
        $vri.caretStartContainer.firstChild.id = "endPaste";
        $vri.endPasteSet = true;

    }
    else if ($vri.caretStartContainer.nextSibling) {
        $vri.caretStartContainer.nextSibling.id = "endPaste";
        $vri.endPasteSet = true;

    } else {

        $vri.endPasteSet = false;
    }
    $vri.caretEndContainer = $vri.range.endContainer;
    $vri.caretContainerNodeType = $vri.caretStartContainer.nodeType;
    $vri.pasteNodeText = $vri.range.startContainer.data;
    $vri.caretStartOffset = $vri.range.startOffset;

    pasteEventFired_cpc = true;
};
function finalizeRtfInput_cpc(entryKey) {

    console.debug("ValidateRtfInput: finalizeRtfInput_cpc called on save or save and close");

    var currentInput = $j("iframe.FAIFrame[id='" + entryKey + "']");

    if (!currentInput) {
        console.error("ValidateRtfInput: was unable to locate the RTF Field with id -> " + entryKey);
        return;
    }
    var currentVal;
    try {
        currentVal = currentInput[0].contentDocument.activeElement.innerHTML;
    } catch (err) {
        console.error("ValidateRtfInput: Unable to access the innerHTML of the RTF Filed with id -> " + entryKey);
        console.error("ValidateRtfInput Error Message: " + err.message);
        return;
    }

    var lastVal = currentData_cpc[entryKey];
    var dmp = new diff_match_patch();
    dmp.Patch_Margin = 10;
    console.debug("ValidateRtfInput: \n-------------\nLastEntry:\n" + lastVal + "\n-------------\n\nCurrentEntry:\n" + currentVal + "\n-------------\n");

    var arDiff = dmp.diff_main(lastVal, currentVal, false);

    if (arDiff.length >= 2) {
        for (index = 0; index < arDiff.length; index++) {
            // check each diff
            if (arDiff[index][0] == 1) {
                var valToCheck = arDiff[index][1];
                var newVal = valToCheck.replace(/ <br>/, ' ');
                newVal = newVal.replace(/ <\/p>/, '<\/p>');
                newVal = newVal.replace(/ <br><\/p>/, '<\/p>');
                console.debug("ValidateRtfInput: Checked val[" + index + "][1]: " + valToCheck);
                console.debug("ValidateRtfInput:  --- newVal: " + newVal);
                arDiff[index][1] = newVal;
                if (newVal == " ") console.debug("ValidateRtfInput: Final matches found a space all alone to be added. Maybe need to look ahead and see if the next change contains <br or other html");

            }
        }
    }
    else {
        console.debug("ValidateRtfInput extension expected a diff >= 2 and got " + arDiff.length + " It is likely there were no changes in this RTF Field");
    }
    var patchMade = dmp.patch_make(arDiff);


    var cleanedTxt = dmp.patch_apply(patchMade, lastVal);
    console.debug("ValidateRtfInput: patch_apply results: " + cleanedTxt[0]);

    var nextUpdate = cleanedTxt[0];
    if (nextUpdate.match(/ <br>/g)) {
        console.debug("ValidateRtfInput: Update data contains ' <br>' stripping now");
        nextUpdate = nextUpdate.replace(/ <br>/, ' ');
        console.debug("ValidateRtfInput: ------------\nNew save value: \n" + nextUpdate + "\n------------");
    }


    currentData_cpc[entryKey] = nextUpdate;

    currentInput[0].contentDocument.activeElement.innerHTML = nextUpdate;

    if (lastVal == currentVal) {
        console.debug("ValidateRtfInput: previous and current values have not changed for: " + entryKey);
    }

};

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.