Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to automatically add target="_blank" to external links only?

I'm building a custom, industry-specific cms (using django). In the backend, webmasters can specify either an internal link, e.g. "/page1" or an external link to use for various navigation elements throughout the website (all use <a> when rendered) . The problem is that I would like internal links to open in the current tab, but external links should use target="_blank" to open a new tab or window.

How can I process the html to accomplish this?

I'd prefer a server-side solution, but am not aware of any clean way to pre-process rendered templates in django. So, I assume the most straightforward way to do this is probably a javascript/jquery solution: a script that runs when each page loads, which adds the target="_blank" attribute to all external links but not internal links. But I'm not sure how to do this, either.

like image 751
B Robster Avatar asked Aug 20 '12 17:08

B Robster


People also ask

Can you add target _blank to URL?

You can use the target="_blank" attribute if you want your users to click on a link that opens up a new browser tab. The target="_blank" attribute is used inside the opening anchor tag like this.

When should the target _blank attribute be used in a hyperlink?

One of the possible values of that attribute is _blank , which tells the browser to open a new window (or tab, if that's the user's preference) when that link is clicked. This used to be “invalid” in HTML (maybe only XHTML?) but people used it anyway since it worked. It's now perfectly valid in HTML5.

Can you add target _blank in CSS?

There are a few ways CSS can 'target' navigation. This will style internal and external links using attribute styling, which could help signal visitors to what your links will do. You can also target the traditional inline HTML 'target=_blank'. Also :target selector to style navigation block and element targets.

Why target _blank is deprecated?

If you use target="_blank" only to open links in a new tab, then it is vulnerable to an attacker. When you open a link in a new tab ( target="_blank" ), the page that opens in a new tab can access the initial tab and change its location using the window.


3 Answers

Try something like

for (var links = document.links, i = 0, a; a = links[i]; i++) {
        if (a.host !== location.host) {
                a.target = '_blank';
        }
}

Don't forget to run the script by the time all links exist in the document tree - in window.onload event.

like image 155
duri Avatar answered Sep 21 '22 15:09

duri


I've been using the following for awhile. Can't remember where I found it originally:

$.expr[':'].external = function(obj){
    return !obj.href.match(/^mailto\:/)
           && (obj.hostname != location.hostname)
           && !obj.href.match(/^javascript\:/)
           && !obj.href.match(/^$/)
};

That adds an :external jQuery selector, so then you can just do:

$('a:external').attr('target', '_blank');

The nice part about using the custom selector, is that if you need to modify what contitutes an "external" link, you can change it in one place and not worry about the rest of your code. For instance in my organization, we have certain subdomains that aren't "external", but that we still want to open in new windows.

like image 45
Chris Pratt Avatar answered Sep 20 '22 15:09

Chris Pratt


You could do something like this:

$(document.body).on('mouseover', 'a[target!=_blank]:not(.local)', function (evt) {
    var a = $(this);
    var href = a.attr('href');
    var domain = href.match(/^https?:\/\/([^:\/]+)/);
    if (domain && domain[1] && domain[1] !== "yourdomain.com") {
        a.attr('target', '_blank');
    } else {
        a.addClass('local');
    }
});

This will process each link as you click it, and shouldn't process each link more than once. If it needs to be external, the target will be set to _blank and it should open in a new window. Here's a working jsfiddle.

Update: My method of determining if the link stays on-site or not is quite crude. The method in this answer is more thorough. I would probably replace my simple regex match with that test instead.

like image 45
benekastah Avatar answered Sep 20 '22 15:09

benekastah