New windows in xhtml strict

Sun 18 Sept, 8.30 p.m. This post is already marked “considered harmful” as the script does not give maximum accessibility, nor fill the browser with nourishing valid code. The comments are good, though: thanks Gez and Lachlan. A proper script will appear in a couple of days, so watch this space. (Hey, does that mean I’m a script-tease artist?). There’s also a good discussion of the subject on the Accessify forum.

target=”_blank”. We’ve all done it – whether because the boss says “open external links in new windows so our site is still open”, or for non-html documents, or just because we want to drive Jakob into an early grave.

But it doesn’t validate to out-of-the-box xhtml 1.0 strict. It’s been deprecated! A lot of people ask why this is, and I can tell you the answer: the top people at the w3c despise you, your family, everything you stand for and all that you hold dear. But obviously, they don’t admit their animosity towards you, so they give another two reasons.

So how can it be achieved? Well, given that the manner of opening a new window is a matter of behaviour, it should be done through JavaScript. Now, I’m no JavaScripter, so when I had to do this, I set about looking for someone else’s code to steal. (How different the Web would have been if the early browser developers hadn’t included a “View Source” menu option.)

Kevin Yank of SitePoint has a lovely script that requires you to mark links to be opened in new windows with rel="external" instead of target="_blank", and the JavaScript spawns new windows. If the user doesn’t have JavaScript, the link still works, but in the same browser window. Yay!

There’s only one problem. Our old mates at the w3c (not the ones who hate you, but the nice ones who like disabled people) say that, in order to be accessible, “do not change the current window without informing the user” (checkpoint 10.1), so we need to amend Kevin’s script slightly to add a title to those links so they comply with the guideline.

I’m no DOMscripter, so I asked the accessify forum members, and Patrick Lauke and Matthew Pennel came up with this adaptation of Kevin Yank’s script:

function externalLinks() {
if (!document.getElementsByTagName) return;
var anchors = document.getElementsByTagName("a");
for (var i=0; i<anchors .length; i++) {
var anchor = anchors[i];
if (anchor.getAttribute("href") && anchor.getAttribute("rel") == "external") {
anchor.target = "_blank";
anchor.title = (anchor.title != "") ? anchor.title+" (opens in a new window)" : "opens in a new window";
anchor.className = (anchor.className != '') ? anchor.className+' external' : 'external';
}
}
}
window.onload = externalLinks;

All you have to do is add a link to the javascript file in the head of the document like so:

<script type="text/javascript" src="/external.js">
</script>

and code your external links thus, <a href="http://www.brucelawson.co.uk" rel="external">hunktabulous studmuffin<a>, and everything will be fine: the JavaScript does the rest by tweaking the DOM.

Now, it would be lovely to have an indication of the new-windowness of the link for sighted users, too. In an ideal world (in which IE6 is standards-compliant, smoking is good for you and Meera Jasmine is my mistress), we’d use attribute selectors, which would automatically add a background image to any link which begins with “http://”:

a[href^="http://"] {
padding-left : 10px;
background : url(external.gif) no-repeat left center;
}

Unfortunately, IE6 doesn’t support attribute selectors (why? because Microsoft also loathes you – what the hell have you been doing?), so the script above adds a class of “external” to the link so you can add a graphic via the CSS.

a.external {
padding-left : 10px;
background : url(external.gif) no-repeat left center;
}

And there you are: semantic, standards-complyin’, Jakob-baitin’, boss-pleasin’ opening of selected links in new windows that validates to xhtml 1 strict.

As an aside, isn’t the Web a wonderful thing? Kevin Yank in Australia wrote the original script, Matthew Pennel in the UK and Patrick Lauke in his underwater lair improved it, all publicly available as a gift it to you, Dear Reader, in the hope that this might somehow soothe the pain of the w3c and Microsoft’s hatred.

18 Responses to “ New windows in xhtml strict ”

Comment by Gez Lemon

I’m sorry to be so negative, Bruce, but there are several flaws with that script. It definitely does not satisfy checkpoint 10.1. The title attribute cannot be relied on as a way to communicate information. The technique is device-dependent, as it’s only exposed in visual browsers when the mouse is hovered over the appropriate element. Also, it will only be exposed to visitors using certain assistive technology depending on their verbosity settings. Most people browse quickly, so even those using a mouse where the title attribute will be displayed as a tooltip will likely miss it, as they typically won’t wait to see if there was any other information they should be aware of before following the link. The only foolproof method of satisfying checkpoint 10.1 is to include the warning in the link phrase.

The technique adds an invalid attribute to some anchor elements in the DOM, so it is also definitely not a standards compliant technique. All it does is hide validation errors from a markup validator, so what’s the point of it? Satisfying a markup validator with no regards to standards is in no way beneficial to anyone.

Comment by Lachlan Hunt

It is true that opening new windows is behavioural and that the semantic equivalent to the target attribute are the rel and rev attributes, but I have to agree with Gez on this one bruce: I hate popup windows of all kinds and using the script simply to hide validation errors is pointless.

However, one advantage to this method is that it does separate the behaviour from the content quite well and if management wakes up one day and realises the awful mistake they’ve made by forcing new windows upon unsuspecting users, then fixing the problem is as simple as removing the script.

Comment by Bruce

Oh, some factual holes in my knowledge here, then, and some philosophical differences. (Why does every accessibility-related conversation always require that preface?).

Gez: you’re not being negative: open and informed debate is what we need in a new discipline like standards-based accessibility.

It seems that Lachlan and Gez have three different objections to this method: is it valid? is it accessible? is it philosophically the right thing to do?

Is it valid?

I’m thinking out loud here, but let’s look at the validiaty of this method. The xhtml certainly validates to xhtml strict, but whether the JavaScript conforms to the w3c DOM spec, I’m woefully unqualified to say. Does it do something to the DOM that uses a proprietory method or hack? If so, I’ll certainly mark this script as “considered harmful”.

Can you explain more about the “invalid attribute [added] to some anchor elements in the DOM”, please Gez? I’m evidently going to have to start learning more about the DOM, I fear. I was under the impression that there’s loads of stuff in the DOM that is manipulatable legitimately, even if it’s not open for manipulation by xhtml. Isn’t that the point of DOMscripting?

Is it philosophically legitimate?

Certainly, the w3c removed target from the out-of-the box xhtml strict dtd, in order to seperate behaviour, structure and presentation. Bravo, I think. But as you’ve shown, Gez, it’s possible to extend the xhtml 1.1 dtd to allow this behaviour in the markup. Philosophically, then, there’s no desire by the w3c to stop people opening links in new windows – otherwise the target module wouldn’t be there. By extending the xhtml dtd, you can even do that in the markup instead of in a seperate behaviour layer, which to me is something of a retrograde step.

Lachlan: I personally dislike opening in new windows, too (although I have sympathy with Jakob’s point that pdfs and the like are best opened in a new window so they don’t lock the browser up).

But sometimes the bosses and the client’s brand-police demand them. I personally don’t like Flash whizzbangery, but that’s often demanded, too, and I’m not in a financial position to turn down jobs, so I try to find the best way of doing what’s specified. It’s the old utilitarianist compromise between the best experience for the disabled minority and the best experience for the majority.

Is it accessible?

Here’s a conundrum that I’m internally debating (and I flip-flop between opinions). In the script above, a warning is sent as a title attribute to the browsing device. This certainly conforms to the html 4.01 spec (does the xhtml 1 strict spec redefine this? My google-fu has let me down this morning):

title = text [CS]
This attribute offers advisory information about the element for which it is set.

Unlike the TITLE element, which provides information about an entire document and may only appear once, the title attribute may annotate any number of elements. Please consult an element’s definition to verify that it supports this attribute.

Values of the title attribute may be rendered by user agents in a variety of ways. For instance, visual browsers frequently display the title as a “tool tip” (a short message that appears when the pointing device pauses over an object). Audio user agents may speak the title information in a similar context. For example, setting the attribute on a link allows user agents (visual and non-visual) to tell users about the nature of the linked resource

If the device doesn’t allow easy access to this information, is that a problem of the web page, or the device?

I’m not being rhetorical here; when I was hacking WordPress for accessibility, I deliberately chose not to use the title attribute on to distinguish one “read more” link from another, and amended the link text instead. But that’s a choice I can make, as it’s my site, and it’s as ugly as a Tory anyway.

Elsewhere, though, I use image replacement even though it means the text is inaccessible to those who have css on, images off. It’s a compromise between accessibility-to-the-max and visual loveliness which I (rather stupidly) summarised as “I don’t care if my site is inaccessible to you if you choose to read it through the wrong end of a telescope.”

Also, for a sighted user, missing the tool tip isn’t a problem, as the script above attaches a class to the link which is then used for a visual icon that a new window will be opened).

For a JAWS user, the out-of-the-box setting is that new windows are announced as such when they open (although not before they open). A controversial argument (which I don’t subscribe to, but I can see how it could be made) is that for a JAWS user (and maybe other screenreaders, too, I don’t know), the reasons for checkpoint 10.1 are satisfied by the default behaviour of the screenreader, in that the purpose of the checkpoint is not to ban new windows, but to allow the user to orientate herself and know that the back button won’t work. If JAWS says “new window”, the user can orientate herself and there is thus no accessiblity problem.

Of course, my opinion will shift in precisely 12 minutes …

Comment by Gez Lemon

Hi Bruce,

Can you explain more about the “invalid attribute [added] to some anchor elements in the DOM”, please Gez?

The following line in the script adds a value for the target attribute:

anchor.target = "_blank";

The target attribute doesn’t exist in an HTML 4.01 Strict DOCTYPE, or an XHTML 1.0 Strict DOCTYPE, but some DOM implementations will still have those attributes available for manipulation regardless of the DOCTYPE chosen. For clarity, the target attribute isn’t deprecated in those DOCTYPES; it’s been deleted. It’s marked as deprecated in the respective Transitional DOCTYPES, meaning that it will no longer be available in subsequent versions.

I was under the impression that there’s loads of stuff in the DOM that is manipulatable legitimately, even if it’s not open for manipulation by xhtml. Isn’t that the point of DOMscripting?

No, the point of DOM scripting is to add the behavioural layer to the document. Breaking standards compliance may hide validation errors from markup validators, but isn’t what DOM scripting is intended for. Most things can be done in a standards compliant manner. The proposed script here could have been written so that it didn’t invalidate the document. The following example uses the traditional event registration model, which isn’t good as it only allows one handler for each event (as does the proposed script), but as support is bad for event registration, is the safest at this moment in time:

window.onload = externalLinks;

function externalLinks()
{
if (document.getElementsByTagName)
{
var objAnchors = document.getElementsByTagName(‘a’);
for (var iCounter=0; iCounter<objAnchors.length; iCounter++)
{
if (objAnchors[iCounter].getAttribute(“href”) && objAnchors[iCounter].getAttribute(“rel”) == “external”)
{
objAnchors[iCounter].onclick = function(event){return launchWindow(this, event);}
objAnchors[iCounter].onkeypress = function(event){return launchWindow(this, event);}
}
}
}
}

function launchWindow(objAnchor, objEvent)
{
var iKeyCode;

if (objEvent && objEvent.type == ‘keypress’)
{
if (objEvent.keyCode)
iKeyCode = objEvent.keyCode;
else if (objEvent.which)
iKeyCode = objEvent.which;

if (iKeyCode != 13 && iKeyCode != 32)
return true;
}

return !window.open(objAnchor);
}

By extending the xhtml dtd, you can even do that in the markup instead of in a seperate behaviour layer, which to me is something of a retrograde step.

Yes, I agree.

Regarding the “Is it accessible” question:

If the device doesn’t allow easy access to this information, is that a problem of the web page, or the device?

Accessibility is about making content usable to people with disabilities. Someone whose motor skills make it impossible for them to use a pointing device don’t choose to navigate without a pointing device, it’s something that they can’t readily change. If authors put that information in a document so that it can only be accessed with a pointing device, it’s a problem with the web page. The only method of ensuring that checkpoint 10.1 is met is by informing the user in the link phrase.

Also, for a sighted user, missing the tool tip isn’t a problem, as the script above attaches a class to the link which is then used for a visual icon that a new window will be opened).

Providing the sighted user is using a visual browser, and has CSS enabled.

WCAG 1.0 Checkpoint 6.1: http://www.w3.org/TR/WAI-WEBCONTENT/wai-pageauth.html#tech-order-style-sheets
Organize documents so they may be read without style sheets. [Priority 1]

Comment by Bruce

Well, it was longer than 12 minutes, Gez, but my opinion shifted.

I was staggered to find that, if you tab to a link, the title doesn’t show as a tooltip. Or, indeed, at all. In IE6, Opera 8, Firefox 1.06, the title attribute of a link is only available if you hover over it with a pointing device. I must’ve seen this behaviour hundreds of times before, but never registered it. (Of course, maybe I should just do some fucking testing …)

I suggest, then, that this is a failure of browsers. The spec says only that the browser *may* be rendered as tooltip “when the pointing device pauses over an object”, not that it can only behave like that. Why shouldn’t someone using the keyboard get the title information, too? (I notice that Derek Featherstone agrees with me here.)

So, disregarding the invalidity of using JavaScript to add those attributes, the tweaked-Yank script is technically accessible to:

  • sighted users using a pointing device, with or without CSS, as they can see the target tooltip
  • screenreader users, as screenreaders can be configured to read the title attribute. (And, contentiously, because JAWS announces new window after opening one, so the requirement for orientation information is satisfied althought the checkpoint is broken)

However, it’s not very usably accessible, because

  • sighted, mouse-wielding users might not notice the tooltip
  • screenreader users need to configure their kit to read the title element

Crucially, sighted users who access via the keyboard never get the title, so are never warned under checkpoint 10.1.

Regarding the validity: I knew, of course, that using JavaScript for loads of document.writes to write an “embed” in order to fool the validator was naughty, but it didn’t occur to me that using Javascript to add a behaviour to the DOM was also A Bad Thing™.

My misapprehension was thus: html/ xhtml etc are methods of instructing a browser how to construct a document, and each language has its own rules. But the w3c DOM is the DOM is the DOM, and doesn’t change between markup languages, so that if you wanted to, you could add extra behaviours using scripting and still be compliant.

But that’s just fooling the validator. And fooling the a validator is like Dopey from “Snow White”: neither big nor clever.

Comment by Lachlan Hunt

although I have sympathy with Jakob’s point that pdfs and the like are best opened in a new window so they don’t lock the browser up

I have to disagree with Jakob this time. Although his advice is usually spot on, in this case there’s one very important point that he’s failed to consider: The behaviour of opening different file formats is user agent/system configuration dependant.

He makes the assumption that the browser will attempt to load the file internally within the browser, rather than launching a separate application. While this is typically the case with Adobe PDF, I have seen some systems launch adobe acrobat as a separate process from the browser (there’s a “Display PDF in browser” setting in the Acrobat preferences).

A more convincing example is probably MSWord documents. From experience, IE will typically load an MS Word document internally (much like a PDF), whereas Firefox will always launch MS Word as a separate application. The result is that, while opening a new window may have a positive result for IE users, Firefox users will end up with a new blank browser window, as well as MS Word. Now, would you call that good usability?

Comment by Jonathan Snook

Lachlan: but I have also seen the behaviour, at least in IE, where opening a file in a new window that results in a download will close the blank window.

I think the major problem is that various browser handle things differently and that any particular technique can only satisfy a majority, never all, of your audience.

And I would prefer files such as PDF’s and Word documents open in a new window. It’s become expected behaviour for me. So much so that when I document isn’t loaded in a new window, I’ll inadvertenly close the window instead of hitting Back. I’d rather ‘suffer’ through the chance of having a blank window to close then lose my window altogether.

Comment by Lachlan Hunt

Jonathan, such usability issues should be addressed by the user agent vendors, not the page authors. If you want your UA to open such documents in a certain way, configure your UA to do so.

Just because you want a new window for such documents, does not, in any way, mean that everyone else wants a new window too — I certainly don’t! I prefer to be informed about the file format, so that I can choose how to deal with it, either by opening in the same window, opening a new tab or saving to disk. Why should I let the page author attempt to make such decisions for me?

Comment by Jonathan Snook

But you’ve just proven my point, Lachlan. Everybody wants it differently and vendors implement it differently. And not everyone knows how to configure their agent to open PDF documents in a new window. In fact, can you tell me where I’d find the option for that in IE or Firefox?

So, while it’s nice to say vendors “should” do so, we have to play “majority wins”.

Comment by Lachlan Hunt

Jonathan, if you’re informed that a link is to a PDF document and you prefer to open such documents in a new tab/window, the following methods can be used in Firefox on Win32 systems (other UAs/systems have similar options):

New Tab: middle click, Ctrl+click or select open in new tab from the context menu
New Window: select open in new window from context menu.

In Firefox, there’s also some preferences you may wish to try out: In Tools>Options… Downloads tab, under “Download Actions”, select “View & Edit actions”. While there doesn’t appear to be an option to load the acrobat plugin within a new browser window, there are options to either use the browser plugin (default), launch an external application or save to disk.

Comment by Jonathan Snook

Lachlan… heh, I didn’t think you’d actually describe ways for me to do that. :) Your last paragraph was really more to my point. i.e: there is no way to configure the browser (besides something like greasemonkey) to allow certain document types to open in new browser windows.

Touching a bit on my original “majority rules” argument, I think it depends on your audience. While user agents offer a way for users to open links in new browsers, is the majority of your audience aware of such features and would they be better served by opening links in new windows? (insert actual user survey here)

Comment by Roger Karlsson

A dilemma with Checkpoint 10.1 is that (new) windows are a device dependent concept and a warning in the link phrase/title/icon could confuse some users accessing the site with devices where the concept does not exists, for example, many mobile phones does not have a windowing concept, some user agents open new tabs instead of new windows, etc.

I guess it comes down to knowing your users and their tools and build sites with that in mind?

Thank you for an interesting article and discussion.

Comment by Alan Neubauer

OK so I see there is much debate over this whole thing. Unfortunately I do not have the luxury of choosing. Add to that the fact that I am NOT a web person — but really a router person pretending to do web code. I thought I would do a favor for some of our legal staff and create a page for Jury Instructions that would be accessable by the general public. The content is a bunch of .rtf files that IE opens in a new page ( I happily used the _blank target). Unfortunately, the 26% of the world population that uses FF or NN get the blank page described earlier. I have performed a browser identification earlier in my page and used that information in some JS in the body of my page. Is there a way to build a tag that will behave differently based on the different browser type.

Comment by stephenrs

hi bruce,

i’m working on a new site that i’m striving to make standards compliant. some of my links i would prefer to have open in a new window. i’ve tried your solution using firefox 1.5, but the link still opens in the same window (tab).

do you know of a way around this? are the days of forcing a new window to open behind us as standards compliant developers? is conventional wisdom telling us that opening new windows is just plain wrong?

also, with popups blocked in firefox the link does nothing at all when using the code above. i modified the bottom of your launchWindow function as follows to avoid having seemingly dead links:

var canOpen = window.open(objAnchor);
if (!canOpen) document.location.href = objAnchor.getAttribute(“href”);

return !canOpen;

thanks,

stephenrs

Comment by Rob Cherny

I don’t think you’re breaking any rules by dynamically inserting the “target” attribute here, as some have said. If it was hard coded, that’d be one thing, but it’s not.

Comment by Frederik

W3C gives a more easy solution for exsample if you wish to use this on a link page. works very well>

From te website of W3C:
Why was the target attribute removed from XHTML 1.1?

It wasn’t. XHTML 1.0 comes in three versions: strict, transitional, and frameset. All three of these were deliberately kept as close as possible to HTML 4.01 as XML would allow. XHTML 1.1 is an updated version of XHTML 1.0 strict, and no version of HTML strict has ever included the target attribute. The other two versions, transitional and frameset, were not updated, because there was nothing to update. If you want to use the target attribute, use XHTML 1.0 transitional”.