Prevent nested span styles (font tags)

2 posts, 1 answers
  1. Jonathan
    Jonathan avatar
    37 posts
    Member since:
    Sep 2012

    Posted 16 May 2012 Link to this post

    So I'm wanting to prevent nested styles for ease of interpretation by another system after the user has created the content in the RadEditor. I've been able to make some progress with this but run into problems when the user makes a selection and tries to apply a new css style to a block of text that contains more then one style already. For example one word is blue and the other red and the user has decided to make them both green and so has selected them together thinking they can change both at the same time. The style change is applied however my code currently fails to handle this situation and allows a nested style to be created. 

    More concrete example is this one: This will be the end of it all because that's all I care to write. 
    And I want to change the color of the words "the end" to both be blue. So I select both and I see the color change but I end up with this as my resulting text - nested spans: 
    <span class="yellow_bold">This will be </span><span class="blue_bold">the </span><span class="yellow_bold"></span><span class="red_bold"><span class="blue_bold">end</span> of it all </span><span class="blue_bold">because</span>...

    Where I think my problem is coming from is that when I ask for the selected element in the command event - I only get the first word and not the second. Is there someway for me to get each element (word) in turn and process them or is there an entirely different way I could be handling this to get the result I need?

    If I step into the code I see the following:

    var selectedHTML = "";
    var selectedHtmlElement;
    var selectionObject;

    function OnClientCommandExecuting(editor, args) {
    selectedHTML = editor.getSelectionHtml(); // becomes "<font class="yellow_bold">the </font><font class="red_bold">end</font>"
    selectedHtmlElement = editor.getSelectedElement(); // becomes "This will be the end of..."
    selectionObject = editor.getSelection(); // becomes an object I don't know how to use - maybe it is helpful and I don't know it
    }

    function OnClientCommandExecuted(editor, args) {
    var commandName = args.get_commandName();

    if (commandName == "ApplyClass") {

    var className = args.get_value();
    if (className == "") return;

    // alert("executing on " + selectedHTML);


    var selectedElement = editor.getSelectedElement(); // becomes an element with innerHtml = "the "
    var parentElement = getParentSpan(selectedElement.parentNode);
    if (parentElement) {
    var newNode1 = parentElemen


    The OnClientCommandExecuted is only fired once and I only get the one word/element when I request getSelectedElement. Is there some way to access the other word/element in this event as well so I can process it. And note how the element returned by getSelectedElement is different between the CommandExecuted and CommandExecuting events. The latter returns the top parent element that contains all the words/elements and not just the 2 that are affected by the style change.

    <telerik:RadEditor ID="RadEditor1" runat="server" Height="400px" EditModes="Design" StripFormattingOnPaste="AllExceptNewLines"
                        StripFormattingOptions="AllExceptNewLines" OnClientCommandExecuted="OnClientCommandExecuted"
                         OnClientCommandExecuting="OnClientCommandExecuting">
                        <Content></Content>
    </telerik:RadEditor>

    <telerik:RadScriptBlock ID="voteScript" runat="server" >
        <script type="text/javascript" >
     
            var selectedHTML = "";
            var selectedHtmlElement;
            var selectionObject;
     
            function OnClientCommandExecuting(editor, args) {
                selectedHTML = editor.getSelectionHtml();
                selectedHtmlElement = editor.getSelectedElement();
                selectionObject = editor.getSelection();
            }
     
            function OnClientCommandExecuted(editor, args) {
                var commandName = args.get_commandName();
     
                if (commandName == "ApplyClass") {
     
                    var className = args.get_value();
                    if (className == "") return;
     
                    // alert("executing on " + selectedHTML);
     
     
                    var selectedElement = editor.getSelectedElement();
                    var parentElement = getParentSpan(selectedElement.parentNode);
                    if (parentElement) {
                        // break the content into 3 pieces - before selected text, the selected text, and after selected text and apply span styles to each
                        var newNode1 = parentElement.cloneNode(false);
                        var newNode2 = selectedElement.cloneNode(true);
                        newNode2.innerHTML = newNode2.innerText;
                        // alert(newNode2.innerHTML);
                        newNode1.innerHTML = parentElement.firstChild.nodeValue;
                        parentElement.innerHTML = parentElement.lastChild.nodeValue;
     
                        parentElement.parentNode.insertBefore(newNode1, parentElement);
                        parentElement.parentNode.insertBefore(newNode2, parentElement);
                    }
                    else {
                        var justText = selectedElement.innerText;
                        var newNode = document.createElement("FONT");
                        newNode.setAttribute("class", className);
                        newNode.innerHTML = justText;
     
                        selectedElement.parentNode.replaceChild(newNode, selectedElement);
                    }
                }
            }
     
            function getParentSpan(el) {
                if (!el || el == null) return false;
     
                while (el && el.tagName && el.tagName.toLowerCase() != "font" && el.tagName.toLowerCase() != "body") {
                    el = el.parentNode;
                }
     
                if (el == null || !el.tagName || el.tagName.toLowerCase() == "body") return false
                else return el;
            }
     
        </script>
    </telerik:RadScriptBlock>

  2. Answer
    Rumen
    Admin
    Rumen avatar
    14419 posts

    Posted 18 May 2012 Link to this post

    Hello,

    You can programmatically clear the formatting before applying the class via the Apply Class tool using the following code:

        <head id="Head1" runat="server">
            <title></title>
            <style type="text/css">
                .redText { color: Red; }
                .greenText { color: Green; }
                .blueText { color: Blue; }
            </style>
        </head>
        <body>
            <form id="form1" runat="server">
                <asp:ScriptManager ID="Scriptmanager1" runat="server" />
                <telerik:RadEditor id="RadEditor1" runat="server" OnClientCommandExecuting="OnClientCommandExecuting">
                    <Content>dasdasdasdas dasdasdasdas dasdasdasdas
                    </Content>
                </telerik:RadEditor>
            <script type="text/javascript">
                function OnClientCommandExecuting(editor, args) {
                    if (args.get_commandName() == "ApplyClass") {
                        editor.get_document().execCommand("RemoveFormat", null, false);
                    }
                }
            </script>
            </form>
        </body>
    </html>

    This works on my end.

    Regards,
    Rumen
    the Telerik team
    If you want to get updates on new releases, tips and tricks and sneak peeks at our product labs directly from the developers working on the RadControls for ASP.NET AJAX, subscribe to their blog feed now.
Back to Top