Targeting links to new browser windows with valid XHTML 1.1

One of the downsides of completely separating content from layout and programmatical behavious is the removed ability to set link targets so that they open new windows - a surprisingly common problem. In practice, this means that the a tag may not have target attribute in valid XHTML 1.1.

It is possible to include a special module for link targets and thus allow the usage of target, but that is quite a complex way to do such a simple thing. I have found out that a compromise which uses JavaScript (if available) works the best.

The solution is rather simple: by including the onclick attribute with code that opens the window and then returns false, the best behavior can be achieved. The link should also be written in the href attribute, as usual. The false return value of the click handler prevents the browser from opening the URI in href, yet it displays it in the status bar when the link is pointed with the mouse, as everyone expects. Also, browsers without JavaScript disabled can open the link, but it opens to the same window. Below is a simple example how to do it and here how it works: Google.

<a href="http://google.com" onclick="window.open('http://google.com'); return false;">Google</a>

Here is an xsl template for the a element, which outputs xhtml, in which external links (recognized by the fact that they start with http://) open in new windows, but internal links open in the same window.

<xsl:template match="a">
  <xsl:element name="a">
    <xsl:attribute name="style"><xsl:value-of select="@style" /></xsl:attribute>
    <xsl:choose>
      <xsl:when test="starts-with(@href, 'http')">
        <xsl:attribute name="href"><xsl:value-of select="@href" /></xsl:attribute>
        <xsl:attribute name="onclick">window.open('<xsl:value-of select="@href" />');return false;</xsl:attribute>
      </xsl:when>
      <xsl:otherwise>
        <xsl:attribute name="href"><xsl:value-of select="@href" /></xsl:attribute>
      </xsl:otherwise>
    </xsl:choose>
    <xsl:apply-templates />
  </xsl:element>
</xsl:template>

Another good solution is to programmatically change the link targets after the page has loaded - a script should iterate through the document object tree and change the targets of the a tags encountered. However, in my opinion, as a general rule, it is better to have the actions written explicitely in the document than to change them afterwards. In this case it wouldn't cause any problems, but it would definitely harden the maintaining and debugging of a more complex system.

Categories: Programming, Web
Posted by Matias at 06.11.2005 11.10 (11 years ago) | 386 comments

386 comments

Post a new comment


Will be displayed within an image file, hopefully undecipherable to address harvesters.

content licensed under Creative Commons BY-NC-SA - Valid HTML 5