Replacing target=”_blank” for Strict XHTML using JQuery (redux)

Some time ago, I provided a simple JQuery solution for replacing target="_blank" when writing Strict XHTML. However, one commenter recently pointed out that my solution does not work if the rel attribute contains more than one value e.g. rel="external nofollow"

Well, JQuery to the rescue again. A very slight modification to the Attribute Filter fixes this issue. The code now reads:

$(function() {
	$('a[rel*=external]').click( function() {
		window.open(this.href);
		return false;
	});
});

Notice the asterisk. This matches attributes that contain a certain value, as explained in the JQuery docs.

However, this isn’t the full redux. Thanks to the power of JQuery, we can identify external links without the need for the rel="external" attribute at all.

Assuming that all internal links are relative e.g. href="/contact", we can simply search for all hyperlinks whose anchor contains a fully qualified url, or more precisely starts with http e.g. href="http://some.site.com".

The final code now looks like this:

$(function() {
	$('a[href^=http]').click( function() {
		window.open(this.href);
		return false;
	});
});

And that’s the power of JQuery

Tags: ,

13 Comments

Woody Gilk commented on March 3rd, 2009 at 7:55 pm

There is one potential pitfall here, and that is if you site generates complete URLs, or if you use a complete URL to switch to HTTPS/HTTP. My only other recommendation would be to use “*=://” instead, as that would capture non-http(s) links as well. However, that be _less_ correct than your method, depending on what other types of resources you link to (RSS, for example).

Alun commented on March 5th, 2009 at 2:37 pm

forgive my ignorance but what does rel external do? Am I right to assume that it signals that the link is to an external site but does that mean that the browser is supposed to respect the links and open in a new window. I’m guessing not. So if a customer wants those links to open in a new window this javascript will allow that. How do you cater for people without javascript? Or is this just something that you cannot implement for non js users if you adhere to the strict DTD?

badlyDrawnToy commented on March 5th, 2009 at 4:32 pm

@Alun, A few good questions there. Without javascript, or web browser preferences, Strict DTDs do not allow links to be opened in a new window, as this is seen as an event i.e. not part of the document structure.

rel=”external” doesn’t actually do anything. The rel attribute defines the ‘link type’. According to the W3C Spec:

‘User agents, search engines, etc. may interpret these link types in a variety of ways. For example, user agents may provide access to linked documents through a navigation bar.’

There is a list of recognised link types, such as stylesheet. ‘external’ is not a recognised link type.

http://www.w3.org/TR/REC-html40/types.html#type-links

I bet some of the new browsers will soon offer the facility to identify such links though.

[...] second solution I came across fixed some of the issues of the first by re‐writing the regex to account for [...]

zmpl commented on July 7th, 2009 at 3:11 am

Another possible attribute name is

xlink:show=”new”

from the XLink spec.

Justin Scheetz commented on August 21st, 2009 at 2:04 pm

This will search your entire page for external links and make them open in a new window. Try it out!

$(function() {
$(“a[href*='http://']:not([href*='"+location.hostname+"'])”).click( function() {
window.open(this.href);
return false;
});
});

Keith commented on April 16th, 2010 at 1:28 am

Man, that is sweet. Thanks!

Evan Carroll commented on May 6th, 2010 at 5:33 pm

This is my favorite solution to this problem, because it uses JQuery, and doesn’t assume the XHTML capable browser has implemented HTML4 “target” attribute on links.

Frank commented on June 15th, 2010 at 3:13 pm

Remember – if you happen to generate an external link or two dynamically after the page loads, the new link won’t “pop” into a new window – unless you bind the click event to the external links with live().

$(‘a[rel*=external]‘).live(‘click’, function(){
window.open($(this).attr(‘href’));
return false;
});

This ensures that any new elements are bound to the modified click event, too.

Andrew commented on July 5th, 2010 at 2:47 pm

I find this nice way to do it:

$(“a[rel*=external]“).attr( “target”, “_blank” );

It’s valid, since target is still an attribute in the DOM definition.

Brendan commented on September 3rd, 2010 at 4:45 pm

If you don’t want to use _target at all (cause it is kinda cheating, isn’t it?), this is what I did:

$(“a.pdf”).mouseover(function() {
pdfLink = this.href;
$(this).attr(“href”,”#”);
});

$(“a.pdf”).click(function() { window.open(pdfLink); });

$(“a.pdf”).mouseout(function() {
$(this).attr(“href”,pdfLink);
pdfLink = “”;
});

You pick your target (for me, it was things that linked out to PDFs, so I had a class called ‘pdf’). On mouseover, you put the href into a variable, you strip the href from the tag so that the link doesn’t open in the parent window as well. On click, you open that variable in the new window. On mouseout, put the variable back in the href.

Since we’re using JavaScript anyways, it’s a solution that avoids _target completely, and it allows for a functioning link if the user has JavaScript turned off.

Hope it helps someone!

Cheers,
Brendan

firebug commented on January 11th, 2011 at 2:41 pm

$(document).ready(function(){
$(‘a[rel*=external]‘).click(function(){
this.target= “_blank”;
});

Leonid Sharlandzhiev commented on April 21st, 2011 at 1:44 pm

@ Frank

The live() method has some flaws so you might need to use delegate() when working with arrays of elements like this:

$(‘.storycontent’).delegate(“a[href*='http://']:not([href*='"+location.hostname+"'])”, ‘click’, function() {
window.open($(this).attr(‘href’));
return false;
});

XHTML Strict target resolved with jQuery

This post has been updated. Please also see Replacing target=”_blank” for Strict XHTML using JQuery (redux)

All good web developers now design sites using the XHTML Strict DTD. Strict XHTML forbids the use of the target="_blank" attribute on anchors, used to open a link in anew browser window. The reason for this is that there should be a separation between presentation and behaviour.

This is all fine and dandy until your customer requests that all links to external sites open in a new browser window. This is not an unreasonable request.

The answer is to add an an event to such links using Javascript. As a fan of jQuery, this could not be easier.

Step 1. Add a rel attribute to all external links/anchors

e.g.

<a href="externalsite.com" rel="external" />

Step 2. Include the following jQuery script

$('a[rel=external]').attr('target', '_blank');

If adding the target attribute seems like a hack, then the following should achieve the same goal

$('a[rel=external]').click(function(){window.open(this.href);
return false;

This may all seem a bit obvious, but I’m sure there’s someone out there looking for an elegant fix like this.

Tags: ,

5 Comments

Karl Swedberg commented on October 25th, 2008 at 4:35 am

“All good web developers now design sites using the XHTML Strict DTD.”
That’s a gross overstatement. Consider these two “good” web developers, for example: Roger Johansson and Ian Hickson. Perhaps a more fair claim would be “most good web developers now design sites using a strict DTD.”

cobasa commented on January 17th, 2009 at 5:54 pm

very nice.
also i think you need an exact number for developers who use xhtml strict, a list of all good web developers, and a definition of “good” and “developers” translated into klingon (just in case).

Jaako commented on March 1st, 2009 at 5:24 am

Thanks for sharing,

However, this breaks on links with other information in the rel=”" attribute (such as rel=”nofollow”)

rel=”nofollow external” is no good.

[...] first solution I came across used jQuery to find external links with the rel="external" attribute and add a [...]

Erik commented on January 29th, 2010 at 7:09 am

This little snippet saved my bacon. Awesome, awesome work. Thanks for sharing.

Yahoo Pipes and JQuery : Goodbye Same Origin Policy

I was chatting yesterday with my friend Simon about my somewhat late discovery of Yahoo! Pipes. I knew about it, I’d just never played with it. Pipes is ideal if you’re looking to create a mash-up from RSS feeds. Simon asked if Pipes were constrained by the Same Origin Policy whereby XHR requests are restricted to the domain serving the original page. I said I’d look into it.
more »

Tags: , , , , ,

Comments are closed.

Colophon

badlyDrawnToy is the blog of Howie Weiner, a freelance web developer, based in Manchester.

Howie specialises in Django, PHP and Java web application development.

This site is no longer updated. You can now follow Howie at howieweiner.co.uk

View Howie Weiner's profile on LinkedIn
View Howie's twitter feed

Tags