I wanted that by default all external links on my page open in a new window (or tab), but I wanted to have an option to force specific links to open in same window. I also wanted to keep XHTML 1.0 Strict compliancy ... so "target" attribute in the anchor tags was not an option.
In the end I've come up with the following javascript code that I've put into a separate *.js file and include in all pages (in page.tpl.php of my
Drupal template):
function m_addLoadEvent(func) {
var oldOnload = window.onload;
if (typeof window.onload != "function") {
window.onload = func;
}
else {
window.onload = function() {
oldOnload();
func();
}
}
}
function m_externalLinks() {
if (typeof document.getElementsByTagName == "undefined") {
return;
}
var anchors = document.getElementsByTagName("a");
var mesg = "(this link opens in a new window)";
for (var i = 0; i < anchors.length; i++) {
var anchor = anchors[i];
var rel = "" + anchor.getAttribute("rel");
if (
typeof anchor.hostname != "undefined"
&& typeof anchor.protocol != "undefined"
&& anchor.protocol.indexOf("javascript") < 0
&& (
(
rel.length > 0
&& rel.indexOf("blank") >= 0
)
|| (
(
rel.length == 0
|| rel.indexOf("self") < 0
)
&& anchor.hostname != document.location.hostname
)
)
) {
anchor.target = "_blank";
if (typeof anchor.title != "undefined") {
anchor.title = (anchor.title ? anchor.title + " " : "") + mesg;
}
else {
anchor.title = mesg;
}
}
}
}
m_addLoadEvent(m_externalLinks);
I copied Drupal's "addLoadEvent" into my script since the Drupal version of the function is not loaded in all generated pages.
"m_externalLinks" does the following:
- changes "target" attribute of anchors to "_blank" if the anchor points to an url with a hostname different from the current site's hostname
- also changes the title of the anchor to "<original title> (this link opens in a new window)" in the above described case
- you can force internal links to open in a new window by adding the "rel=blank" attribute to the anchor
- you can force external links to open in same window by adding the "rel=self" attribute to the anchor
This works perfectly for me and no additional module or whatsoever is required.
Update: meanwhile a module named
Extlink was created which does just what I intended with the above code. You might consider using the module instead of this code snippet (I use the module since it's a more "Drupalish" way of doing it
).
PS: I've found a bug in Firefox which raises an exception (and thus prevents the script from processing all links on the page) if there's a link without a
href
attribute. You can find details on the bug
here.
Comments
Hi there, can you help me a
It works great if i paste it into the head of my page.tpl.php - but how do I include it? I tried a php include but that didnt work...
Thanks!
ok i got round this by
do not use PHP's include ...
I did it like this:
<script>
tag with an "src" attribute to the<head>
part of "page.tpl.php" to include the "commons.js" file. The<head>
looks now something like this:<head>
<title><?php print $head_title ?></title>
<meta http-equiv="Content-Style-Type" content="text/css" />
<?php print $head ?>
<script type="text/javascript" src="/files/website/common.js"></script>
<?php print $styles ?>
</head>
<SCRIPT>
tag into page.tpl.php directly.translating the new title of the links
anchor.title = (anchor.title ? anchor.title + " " : "") + "(this link opens in a new window)";
anchor.title = (anchor.title ? anchor.title + " " : "") + "(<?= t("this link opens in a new window") ?>)";
... and refer to this PHP file in the
<head>
part of your "page.tpl.php" to get the JS included:<head>
<title><?php print $head_title ?></title>
<meta http-equiv="Content-Style-Type" content="text/css" />
<?php print $head ?>
<script type="text/javascript" src="common-js.inc.php"></script>
<?php print $styles ?>
</head>
This way you can add translation of the "this link opens in a new window" text via Drupal's "administration / localization" page.
thanks for the tips - i will
Having a little problem now - im using the quicktags bar and whenver i hit a quicktag button its opening a new window. This is pretty annoying - i cant see why its happening though as there are no external links referenced anyway in the quicktag files.
It would also be cool if one could enter other domains in the script which didnt want to open in a new window - eg my site is on both a .org and a .org.uk address!
Thanks for your help
replace the generic hostname comparison with a specific one
&& anchor.hostname != document.location.hostname
comparison with something that matches all your domain names.Eg. in your case I'd add something like this:
&& anchor.hostname != "domain.org"
&& anchor.hostname != "domain.org.uk"
This is not a generic solution (since the code becomes site-specific due to the included domain names), but it's simple and works.
Very good post, thanks a lot.
So.. What about javascript
added support for JS links
I added support for javascript links which means you can define by including or excluding a line of code whether to open javascript links on current page or on a new page by default.
How to define the size of the new window
you cannot
target
attribute of<A>
anchor tags (and thetitle
as well, but that's just eye candy) to make the links open in a new window. One can define window attributes (size, scrollbar, etc.) if and only if you use a JavaScript function call to open the new window.My script could be modified to replace the
href
attribute with some JavaScript function call to open the window in a controlled way. First add a new function to the script for opening a new window, eg.:function openWindow(url) {
window.open(url, "_blank", "width=600,height=400,menubar=yes,location=yes,resizable=yes,scrollbars=yes,status=yes");
}
Then replace the
anchor.target = "_blank";
line in them_externalLinks
function with something like this:anchor.href = "javascript:openWindow('" + anchor.href + "')";
I don't know whether the above example really works (haven't tested it), but you see the "trick" and can debug it yourself.
You can check the Mozilla Developer Center for a full list of available parameters for use with the
window.open
function.Thank you
It works nicely! I think it could be more useful than only open a new window, once you can preserve the visibility of your original site, while give a view of a external one.
Again,
Thank you
Open single internal link in new window
How should I do it?
Please advise
Thank you
Re: Open single internal link in new window
rel="blank"
attribute (in the anchor tag).Use Extlink for Drupal sites
New window in primary link
Thanks for the reply,and I'm sorry for not being clear,
Im using extlink, but I need to configure the one primary link which link to Mantis in the same domain.
The extlink can open all links(internal and external) in new window,but I only need one particular link.
Do you have any idea?
Thank you very much
Re: New window in primary link
extlink.js
for that.Replace the following code in
extlink.js
:$("a").each(function(el) {
try {
var url = this.href.toLowerCase();
if (url.indexOf('http') == 0 && !url.match(internal_link)) {
external_links.push(this);
}
else if (url.indexOf('mailto:') == 0) {
mailto_links.push(this);
}
}
with something like this:
$("a").each(function(el) {
try {
var url = this.href.toLowerCase();
if ((url.indexOf('http') == 0 && !url.match(internal_link)) || $(this).hasClass("ext")) {
external_links.push(this);
}
else if (url.indexOf('mailto:') == 0) {
mailto_links.push(this);
}
}
Now you should be able to force any single link to open in a new window by adding the
"ext"
class to the anchor tag.PS: I didn't test the above code so it might have errors in it (but better not since I only touched one line ). With a little modification you could add the feature to force external links to open in the current window too.
Re: New window in primary link
Thank you so much for your help,
sorry for another dumb question.
How should I add the "ext" class to the anchor tag?
Should I just type this in primary menu path:
http://localhost/mantis ext
Thank you so much.
Re: New window in primary link
<A HREF="some/relative/link" CLASS="ext">this is a link</A>
). Primary links are a feature of Drupal ... you can specify them on a fixed UI and customize their look-and-feel through CSS. However you cannot assign any specific class to a primary menu link through the admin screen in Drupal. You could do that by using some JavaScript (eg. jQuery).Create a new block (in Administer/Site building/Blocks), place it in the footer section, use input format "Full HTML", and place the following code into it:
<script type="text/javascript">
$("ul.primary-links > li.menu-1-1-2 a").addClass("ext");
</script>
The specific
menu-1-1-2
class should specify the menuitem of your choice.PS: the above jQuery line is not tested ... might not work at all or might need some debugging. It's just one way to do what you want.
Re: New window in primary link
Thank you for the explanation,
and thank you for your patience.
I will give it a try.
Thank you very much
Re: New window in primary link
Thanks for the advise, its working.
But after that I upgraded to Drupal 6.6 and unload all my modules,
testing to replace the text editor,
and suddenly the <code>$("ul.primary-links > li.menu-1-1-2").addClass("ext");</code> start showing in the footer, and the "magic" is missing .
Is there any other way to put the snippet?
Im still trying to figure it out where did I went wrong in the input filter .
Thank you so much for your help.
Re: New window in primary link
$("ul.primary-links > li.menu-1-1-2").addClass("ext");
But this could not work since it added the "ext" class to the
<li>
tag and not the<a>
tag. I've fixed that in the comment with the example.I don't know what broke, when you upgraded to Drupal 6.6. What Drupal version did you upgrade from? 5.x? In Drupal 6.x jQuery got a major update, but actually my example code should be compatible with the jQuery both in Drupal 5.x and 6.x. Is the input format of the given block still "Full HTML"? Did you put the
<script ...> ... </script>
tags around the jQuery code?Thanks for the guide!
-James Keller
Thanks!
PERFECT Solution to what i wanted!!!!
Its a grate article it helps
very interesting, good job!