Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Tridion RTF text selection

I'm writing a GUI extension that will essentially wrap selected text in a specific DIV. I have the text being encapsulated with the DIV but have hit a bit of a block...

When the user hasn't selected a specific piece of text I am assuming the intention is to wrap the nearest HTML element

htmlSelectedNode = target.editor.getSelectedHTMLElement()

This all seems to work fine and I pass the HTML element into my extension. After some manipulation I then apply the HTML but it is injecting the new HTML inside the previous element - instead of replacing it...

Is it possible to 'select' the HTML element - I can see a .focus() and a .setCapture() but these don't seem to do the trick - I guess the ideal would be to use the same functionality as applied when selecting an element from the "Current Element" dropdown on the ribbon bar but I've not been successful in locating the onclick/select method associated with this dropdown.

Just to clarify... with an example...

if the text was

    <div class="notrelevant"><p>test1</p><p>this is an example</p></div>

and the user inserted the cursor inbetween the i and s in 'is' I want the GUI to pre-select the nearest HTML Element - in this case the end result would be...

    <div class="notrelevant"><p>test1</p><div class="INJECTED_CORRECTLY"><p>this is an example</p></div></div>

EDIT: For completeness I've included the submit event that I use to (re)inject the HTML into the RTF (although I don't think it would make sense to manipulate the selection at this point and would prefer to have 'selected' the text above using a more 'standard', existing Tridion functionality...)

   $evt.addEventHandler(popup, "submit",
        function DateHighlighter$execute$onPopupSubmitted(event) {

            var el = event.data.html;
            if (el) {
                if (htmlSelectedNode != null) {
                    var lDocument = htmlSelectedNode.ownerDocument;
                    var lTempContainer = lDocument.createElement("span");

                    try {
                        lTempContainer.innerHTML = el || "";
                    }
                    catch (err) {
                        //assigning a value to innerHTML can be sensitive to browser but the error is fine to be ignored
                    }

                    var parentNode = htmlSelectedNode.parentNode;
                    parentNode.replaceChild(lTempContainer, htmlSelectedNode);

                    //Move to the new element
                    var lTextRange = $dom.createTextRange(lTempContainer);
                    $dom.moveRangeToElement(lTextRange, lTempContainer);
                    //Select and remove the temporary element
                    $dom.selectRange(lTextRange, $dom.getSelection(lDocument));
                    $dom.removeNode(lTempContainer, false);

                }
                else {
                    // Insert new created element (DIV)
                    target.editor.applyHTML(el);
                }

            }
            else {
                //TODO: test this - it's likely not required
                if (htmlSelectedNode.attributes["class"] != null)
                    htmlSelectedNode.removeAttribute("class");

                //TODO: test this - it's likely not required
                if (htmlSelectedNode.attributes["ondblclick"] != null)
                    htmlSelectedNode.removeAttribute("ondblclick");

                //TODO: the node isn't removed - leaves the empty <div>... 
                // - delete the node and then apply the node2.outerHTML? - or follow parentnode pattern above!
                var htmlSelectedNode2 = htmlSelectedNode.innerHTML;
                htmlSelectedNode = htmlSelectedNode2;
            }

            //Refreshes the Design view
            target.editor.setCurrentView("Source");
            target.editor.setCurrentView("RichText");
            target.item.closeActivePopup();
        });
    $evt.addEventHandler(popup, "unload", DateHighlighter$execute$onPopupCanceled);
like image 989
Dylan .. Mark Saunders Avatar asked Oct 01 '12 10:10

Dylan .. Mark Saunders


1 Answers

So I located the CurrentElement selection and saw the glaringly obvious setSelectedHTMLElement. Not sure how I missed it but alas here is is below... as the comments note - ensure the method is available (if the user has a string of text selected that doesn't equate directly to a HTMLElement the setSelectedHTMLElement method will fail and remove us the user selection (thus meaning the GUI Extension .aspx can't (re)inject the new HTML...

//if there's no tagname then the setSelected will fail and remove the (non-element based) select the user has done
if (htmlSelectedNode.nodeName && htmlSelectedNode.nodeName != '#text') { 
    //unlikely to get #text here as it's the htmlSelectedNode.commonAncestorContainer.nodeName
    $log.message(logt + 'selecting the htmlSelectedNode.nodeName:' + htmlSelectedNode.nodeName);
    target.editor.setSelectedHTMLElement(htmlSelectedNode);
}
else {
    $log.message(logt + 'no htmlSelectedNode.nodeName - user probably selected incomplete element:');
}
like image 123
Dylan .. Mark Saunders Avatar answered Oct 22 '22 21:10

Dylan .. Mark Saunders