Skip to content

Ouvrir un lien dans un nouvel onglet en XHTML Strict

juillet 25, 2009 - Javascript

World Wide Web

Comment ouvrir un lien dans une nouvelle fenêtre ? La réponse pourrait sembler bien simple : il suffit d’utiliser l’attribut target. Cela fonctionnera, certes. Cependant, cela ne respectera pas les dernières normes XHTML strictes. Comment peut-on alors concilier cette fonctionnalité avec le respect des standards du Web ? Il existe plusieurs méthodes de procéder.

Tout d’abord, pourquoi avoir enlevé cet attribut ? Imaginons un quidam lambda ne connaissant pas grand chose à la technologie. Il navigue sur un site Internet, et utilise le bouton Précédent pour revenir en arrière, n’ayant pas envie de rechercher un éventuel lien Retour à l’accueil. Maintenant, si on ouvre une nouvelle fenêtre à cet internaute, la navigation par historique ne fonctionnera pas : il sera obligé de fermer cette fenêtre pour revenir à la page précédente. Comportement fort peu intuitif.

Afin d’empêcher ce genre d’hérésie ergonomique, le W3C a décidé d’instaurer une nouvelle norme : c’est à l’utilisateur d’ouvrir une nouvelle fenêtre, et non pas au développeur de lui forcer la main. Exit donc le target= »_blank ». Cette fonctionnalité a été reprise par de nombreux (si ce n’est tous) navigateurs récents. Il suffit généralement de faire un CTRL + clic ou un clic sur la molette de votre souris pour ouvrir un nouvel onglet.

Problème : l’utilisateur n’est pas forcément au courant de ces astuces. Et, même si cela n’est généralement pas très gênant, fermer le site en cours pour rediriger l’internaute vers un lien partenaire n’est pas commercialement très encourageant. Il peut donc être intéressant, lorsqu’il s’agit d’un lien externe, d’ouvrir un nouvel onglet. On ne peut cependant pas le spécifier en XHTML, sous peine de se faire rejeter par le validateur. Il existe cependant quelques moyens de contournements.

C’est la plus simple, et celle dont je viens de vous signaler la non-conformité aux normes. Cependant, mais cela n’engage que moi, je considère les normes comme un must-have, mais m’autorise quelques écartades, du moment que cela ne bouleverse pas toute l’architecture, et que cela peut apporter un plus ergonomique à l’utilisateur (par exemple, pour proposer le téléchargement d’un document, et éviter que l’internaute ne se retrouve devant une page blanche). Il ne faut en effet pas perdre de vue, comme c’est hélas bien trop souvent le cas, que l’utilisateur qui nous ramènera notoriété et prospérité est bien l’internaute, et en aucun cas les moteurs de recherche ou les validateurs.

<a href="http://www.google.fr" target="_blank">Google</a>

Afin de respecter les normes, et comme les validateurs ne sont pas capables d’interpréter le Javascript, nous allons utiliser ce langage afin de tricher. On ne reviendra pas sur le sens moral de cet acte. Nous utiliserons pour ce faire le framework MooTools.

window.addEvent('domready', function(e){
	$each($$('a'), function(item){
		item.setProperty('target', '_blank');
	}
});

Et voilà comment, en 5 lignes de code, ouvrir tous les liens de la page dans une nouvelle fenêtre. Quelques explications…

Tout d’abord, nous utilisons la fonction addEvent, qui va permettre de rajouter un événement sur un élément, ici, la fenêtre (window). L’événement concerné sera domready. Cela signifie que la function anonyme passée en second argument ne sera executée que lorsque le modèle DOM sera prêt, c’est à dire une fois que toutes les balises seront créées et placées au bon endroit dans la page.

Une fois que le modèle DOM est prêt, nous allons itérer grâce à la fonction $each sur l’ensemble des balises de lien de la page. La fonction double dollars ($$) permet en effet de récupérer tous les éléments répondant au critère CSS passé en argument. Puis, pour chaque élément satisfaisant cette condition, nous lui ajoutons un attribut (une propriété dans le jargon MooTools) : nous attribuons à target la valeur _blank.

Cela fonctionne. Seul bémol, tous les liens seront ouverts dans une nouvelle fenêtre, même les liens internes. Ce qui peut poser un problème ergonomique majeur. Il nous faudra donc vérifier la cible du lien. Si celle-ci se rapporte à un domaine externe, alors (et seulement dans ce cas) on ajoute l’attribut target. Pour ce faire, rien de bien compliqué, avec une expression régulière…

window.addEvent('domready', function(e){

	var siteUrl = document.location.hostname;

	$each($$('a'), function(item){
		var linkUrl = item.get('href');
		if(linkUrl.test("^http://") && !linkUrl.test("^http://(www.)?" + siteUrl))
			item.setProperty('target', '_blank');
	});
});

On récupère dans un premier temps le nom de domaine de la page en cours, que nous stockons dans siteUrl. Puis, nous récupérons la cible du lien, que nous plaçons dans linkUrl. Enfin, nous regardons si linkUrl satisfait l’expression régulière concernant au domaine en cours (avec ou sans les www), afin de placer ou non l’attribut target. A noter que dans le cas où il n’y ait pas de http://, il s’agit d’un lien interne, et donc il est hors de question d’ajouter l’attribut target.

Et c’est tout. A présent, tous les liens externes s’ouvriront dans une nouvelle fenêtre. Il ne vous suffit plus que d’inclure ce script (ainsi que MooTools) sur toutes les pages de votre site, et vous n’aurez plus ces fuites de visiteurs. ;)

[MAJ 21/08/2009 : modification de l'expression régulière dans le dernier script, pour prendre en compte les liens sans http://.]


Comments

  1. Arnaud Lejosne juillet 25, 2009

    Bof rien de fantastique là-dedans. -_-

    Le target blank c’est assez commun tout de même… xD

  2. Lucas Courot juillet 25, 2009

    Intéressant, cependant ton article nous oblige à passer par une librairie.

  3. Jonathan Petitcolas juillet 25, 2009

    @Lucas : Tu n’es pas obligé de passer par une librairie. Tu peux aussi passer par le DOM, avec la fonction getElementByTagNames. C’est juste un peu plus complexe et pénible qu’avec MooTools. ^^

  4. Jonathan Petitcolas juillet 26, 2009

    Que d’activité nocturne sur ce blog ! Les geeks vivent la nuit, ce n’est pas une légende. :p

    Sinon, bonne idée ce script jQuery. N’hésitez pas à mettre les versions propres à vos librairies préférées. Je laisserais uniquement la version MooTools dans le billet, car c’est la seule sur laquelle je peux dépanner. Mais, vos commentaires sont bienvenus ! :)

  5. ChoiZ juillet 26, 2009

    Salut Jonathan,

    Avec jQuery c’est également possible en 3 lignes :

    $(document).ready(function(){
    $(&quot;a[href*='http://']:not([href*='&quot;+location.hostname+&quot;'])&quot;).attr(&quot;target&quot;,&quot;_blank&quot;);
    });

    Trés bonne idée ce script. Je vais installer ça un peu partout du coup. Merci ! ;)

  6. Syndrael juillet 26, 2009

    Si tu donnes une solution Mootools il faudra alors faire pareil avec d’autres frameworks, et à commencer par jQuery…

    Quelle est la solution préconisée par les standards pour conserver cette fonctionnalité ? Ce serait dommage de voir des évolutions avec des perte de fonctions de « confort »

    S.

  7. Jonathan Petitcolas juillet 27, 2009

    @Syndrael : Concernant la version jQuery, je ne connais pas du tout ce framework, mais il est toujours possible de la laisser dans les commentaires. Ce qu’a fait ChoiZ trois commentaires plus haut. ;)

    Sinon, pour plus de détails sur le point de vue vis à vis des standards, ainsi que sur une autre manière de procéder (via l’utilisation des DTD), voici un article sur l’attribut target en XHTML (via Ultra-Fluide).

  8. sirlepape juillet 30, 2009

    Quel tricheur !

    Donc au final tu préfère générer du code pour obtenir le même rendu tout en échappant à la validation. Tu aurais du faire coureur cycliste !

    En tout cas je suis très fan de la méthode qui permet d’assurer l’ouverture des liens externes dans un nouvel onglet. Merci pour ce tips ! (Et ça sera la version jQuery pour moi ;)

  9. Woodgate août 21, 2009

    Très bon article,

    Je pense comme Jonathan que l’utilisation d’une librairie pour permettre une petite modification du code est la meilleure solution possible à ce jour pour ce genre de truc.

    Je verrais bien par contre une petite modification : par exemple n’appliquer l’ouverture dans une nouvelle fenêtre que pour les lien qui ont par exemple une class « extern » ou « blank » ou un truc comme ça…

  10. @Lucas : Je viens de publier un article qui pourrait t’intéresser, avec la mise en place de la même chose en Javascript pur.

    @Woodgate : pour l’utilisation d’une classe supplémentaire, c’est tout à fait possible, et pas bien compliqué. Il suffit de rajouter une condition au test conditionnel. ;)

Trackbacks

There are no trackbacks on this entry.

Add a Comment

Required

Required

Optional