Skip to content

Instantly share code, notes, and snippets.

@anselmh
Created July 24, 2013 12:12
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save anselmh/6069971 to your computer and use it in GitHub Desktop.
Save anselmh/6069971 to your computer and use it in GitHub Desktop.
Open all external links (different hostname than current page) in new tab/window with plain vanilla JavaScript.
/**
* Open external links in new tab/window
*/
// All http:// links should open in new tab/window. Internal links are relative.
var anchors = document.querySelectorAll('a');
for (var i = 0; i < anchors.length; i++) {
if (anchors[i].host !== window.location.hostname) {
anchors[i].setAttribute('target', '_blank');
}
}
@jkphl
Copy link

jkphl commented Jul 24, 2013

Not sure if you should rely on the .host property of links – I had some issues with it in the past (don't remember the exact cirumstances though; might be some browsers not supporting it properly). Also, I'd recommend normalizing the anchors[i].host and window.location.hostname values (e.g. toLowerCase() or similar), as some browsers might mangle capitalization of domain names (for both the .host and the .hostname property). Just saying ... ;)

@anselmh
Copy link
Author

anselmh commented Jul 24, 2013

Thanks for your feedback! What would you recommend instead for not relying on .host? Had only read that all common browsers support it but a insight would be helpful.

@jkphl
Copy link

jkphl commented Jul 24, 2013

There might well be better solutions (and this one might have issues I'm not aware of yet), but this is a piece of code I use in my Google Analytics TYPO3 extension for detecting "same domain links":

var host                    = window.location.hostname.toLowerCase(),
regex                       = new RegExp('^(?:f|ht)tp(?:s)?\://(?:[^\@]\@)?([^:/]+)', 'im'),
match                       = url.match(regex),
domain                      = ((match ? match[1].toString() : ((url.indexOf(':') < 0) ? host : ''))).toLowerCase();

// Same domain
if (domain == host) {
    ...
}

where url is the href attribute value of the link. I remember I fiddled quite a while with this ... Btw. I just realize that I have no idea what would be the result with a link starting with "//", never tried this. ^^

@anselmh
Copy link
Author

anselmh commented Jul 24, 2013

Yeah, that's the point I recognized today. Having // links makes such RegEx things a complete mess. That's why I just used .host. Maybe I'll change that for testing. toLowerCase() is a good suggestion.

@jkphl
Copy link

jkphl commented Jul 24, 2013

Give me some time please. I will do some tests with the regex later today, then let you know again ... Should be no problem to match the // properly as well ... I will also be able to improve my TYPO3 extension this way. ;)

@jkphl
Copy link

jkphl commented Jul 24, 2013

Indeed, the regex didn't work with // links yet (and had a typo as well). I set up a codepen with updated regex, seems to work fine with quite a lot of different URL formats now. Did I miss a format?

http://codepen.io/jkphl/pen/dyqLu

@rajeevedmonds
Copy link

I've tested the codepen version, but it's not working correctly. I'm using it in an XML template in the following form.

<script type='text/javascript'>
/*<![CDATA[*/
function makeExternal(link) {
  var url      = link.getAttribute('href'),
  host         = window.location.hostname.toLowerCase(),
  regex        = new RegExp('^(?:(?:f|ht)tp(?:s)?\:)?//(?:[^\@]+\@)?([^:/]+)', 'im'),
  match        = url.match(regex),
  domain       = ((match ? match[1].toString() : ((url.indexOf(':') < 0) ? host : ''))).toLowerCase();

  // Same domain
  if (domain != host) {    
    link.setAttribute('target', '_blank');    
  }
}

for (var l = 0, links = document.querySelectorAll('a'), ll = links.length; l < ll; ++l ){
   makeExternal(links[l]); 
} 
/*]]>*/
</script>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment