Creating anchor links in rich text fields with SDL Tridion 2011 SP1
Asked Answered
C

4

6

I am trying to use the anchor button in a RTF field of a Component, and getting unexpected behavior. Using the Chrome Browser from the design view, I highlight/select the heading (i.e. <h2>My Heading</h2>) I want to use as an anchor, and press the anchor button and enter the anchor name (i.e. my_place).

This results in the following code being displayed in my source tab:

<a name="my_place" id="myplace"/><h2>My Heading</h2>

This causes render problems when displaying the HTML in a browser due to the self closing <a/> tag.

I would have expected one of the following three HTML fragments being inserted into the HTML source:

<a name="my_place" id="myplace"><h2>My Heading</h2></a>

or

<h2><a name="my_place" id="myplace">My Heading</a></h2>

or

<a name="my_place" id="myplace"><a><h2>My Heading</h2>

Has anyone else experienced this? or know of a way to achieve what I had expected (without manually editing the HTML). Or is this a bug in the current version of the product.

Cattery answered 10/5, 2012 at 15:46 Comment(0)
C
6

Attached is my sample XSLT template:

<template match="a[(@name) and (count(node()) = 0)]">
    <copy>
        <apply-templates select="@*"/>
        <xhtml:span xmlns:xhtml="http://www.w3.org/1999/xhtml" class="hidden"> </xhtml:span>
    </copy>
</template>

This adds a bit more than strictly needed, but handles some other issues we have due to XML manipulation on the Content Delivery side.

Essentially it matches all empty a tags with a name attribute, and add something between them in order to stop them self closing. In our case we post process all of the XML with XSLT, so we have challenges with empty tags getting closed all the time. So as a dirty hack, we are now inserting a hidden span tag between empty tags to prevent the issue.

Cattery answered 10/5, 2012 at 19:48 Comment(0)
M
6

Thanks Chris, I've edited your solution to fit my requirements so wanted to share for anyone with this issue in the future.

Note: This moves the text inside the anchor and deletes the text outside. Fixes anchors that were intended to contain text only, not html. i.e My solution fixes this tag:

<p><a name="anchor1" id="anchor1"></a>Anchor text</p>

To

<p><a name="anchor1" id="anchor1">Anchor text</a></p>

But not this:

<p><a name="anchor1" id="anchor1"></a><h1>Anchor text</h1></p>

Here's my xsl. Hopefully it will help give you a base, I'm sure you could easily update it to look for a following tag (I don't require this for my solution).

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output omit-xml-declaration="yes" method="html" cdata-section-elements="script"/>
    <xsl:template match="/ | node() | @*">
        <xsl:copy>
            <xsl:apply-templates select="node() | @*"/>
        </xsl:copy>
    </xsl:template>

    <!-- fixes Tridion bug when using interface button to insert anchor in rich text field -->
    <!-- gets all empty anchor tags with an id and takes any following text and copies it inside anchor -->
    <xsl:template match="a[(@id) and (count(node()) = 0)]">
       <xsl:copy>
            <xsl:for-each select="@*">
                <xsl:attribute name="{name(.)}">
                    <xsl:value-of select="."/>                    
                </xsl:attribute>
            </xsl:for-each>
            <xsl:value-of select="normalize-space(following-sibling::text())"/>
        </xsl:copy>
    </xsl:template>
    <!-- delete any text after an empty anchor (template above has already copied this text inside the anchor) -->
    <xsl:template match="text()[preceding-sibling::a[(@id) and (count(node()) = 0)]]" ></xsl:template>
</xsl:stylesheet>

Here's my test XML

<?xml version ="1.0"?>
<?xml-stylesheet type="text/xsl" href="tridionhtmlfield.xsl"?>
<html>
    <head></head>
    <body>
        <p><a id="anchorlink" name="anchorlink" title="Anchor link" href="#Anchor">Anchor link</a>Some text after</p>
        <p><a name="broken-with-html-name" id="broken-with-html-id"></a><h1>Anchor - broken with html</h1></p>
        <p><a name="broken-text-only-name" id="broken-text-only-id"></a>Anchor - broken text only</p>
        <p><a name="broken-notext-name" id="broken-notext-id"></a></p>
        <p><a name="correct-name" id="correct-id">Anchor - correctly rendered</a> Some text after</p>
    </body>
</html>

After transform:

<html>
    <head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"></head>
    <body>
        <p><a id="anchorlink" name="anchorlink" title="Anchor link" href="#Anchor">Anchor link</a>Some text after</p>
        <p><a name="broken-with-html-name" id="broken-with-html-id"></a><h1>Anchor - broken with html</h1></p>
        <p><a name="broken-text-only-name" id="broken-text-only-id">Anchor - broken text only</a></p>
        <p><a name="broken-notext-name" id="broken-notext-id"></a></p>
        <p><a name="correct-name" id="correct-id">Anchor - correctly rendered</a> Some text after</p>
    </body>
</html>

Hope this helps

Malcommalcontent answered 15/8, 2012 at 16:39 Comment(1)
Hi Jonathan, Glad some of this helped you - Please consider committing to our SDL Tridion Area 51 proposal using your SO ID so that we can get a dedicated Q&A area for Tridion: area51.stackexchange.com/proposals/38335/…Cattery
H
4

It looks like a bug to me Chris. I've just confirmed it on Chrome, Firefox and IE. It's completely counter-intuitive that the current text selection should be ignored. (On the plus side, once you fix it manually in the source tab, everything appears to behave perfectly.)

I suggest that you report this to Tridion, and perhaps work around it by altering your templating or filter XSLT.

Hexagonal answered 10/5, 2012 at 16:48 Comment(1)
I think you are correct @Dom - I have modified my XSLT Filter for the schema to handle the issue as you recommended. I have added my XSLT below so others can seeCattery
H
2

It is a bug in Tridion. One work-around that I suggest (and have implemented in our particular installation) is to do the following:

  1. Edit the FormatAreaStyles.css file (found in the Tridion CMS program files) — as well as your CSS file used by the website — to include a class like this:

.hiddenanchor { width:1px; height: 1px; display: block; text-indent:-50000px; }

  1. Publish out your CSS file (with the new class) so that it'll format your anchors properly.
  2. And then in the component where you are building out the anchors, you will have to:

    a. type a word or series of words in your component (where you want the target to be),

    b. select that text, and apply the anchor tag to it,

    c. then apply the new class you've created (.hiddenanchor) to the anchor.

In the end, your "invisible" anchor would look like this:

<a name="anchorname" id="anchorname" class="hiddenanchor">Anchor Name</a>

It's a crude work-around — fully acknowledged. But it works. You don't end up with the hyperlink/underline styling until the close of the next DOM object.

As an explanation to the CSS, the anchor technically has to be visible in the DOM for it to work and to be accessible by the anchor link. So "display: none" won't work. Alternatively to taking the text-indent approach, you could absolute or fixed position the text off the screen as well.

Hanrahan answered 12/7, 2012 at 18:59 Comment(2)
This might be a work-around in this case, but not necessarily crude. +1 as a quick and useful alternative technique for adding "merge" field type information (aka data tags) to rich text format areas. hiddenanchor works here, but we can "template" business-friendly names into whatever the presentation server needs. Alternatively you could keep some items visible, but styled differently as needed.Eau
It may be worth noting that there is no need to restart the COM+ or IIS on the Tridion server after updating FormatAreaStyles.css. You may need to clear your browser cache to make the new style available in the Component's Format toolbar though. Please also note that any empty CSS elements (e.g. a.ReadMore{/**/}) will not show up either - they have to have formatting settings to show.Highhat

© 2022 - 2024 — McMap. All rights reserved.