Open external links in a new tab without jQuery - javascript

What's the best way to open all external links (URLs that don't match the current domain) in a new tab using JavaScript, without using jQuery?
Here's the jQuery I'm current using:
// Open external links in new tab
$('a[href^=http]').click(function () {
var a = new RegExp('/' + window.location.host + '/');
if (!a.test(this.href)) {
window.open(this.href);
return false;
}
});

Pure JS:
function externalLinks() {
for(var c = document.getElementsByTagName("a"), a = 0;a < c.length;a++) {
var b = c[a];
b.getAttribute("href") && b.hostname !== location.hostname && (b.target = "_blank")
}
}
;
externalLinks();

The links property returns a collection of all <area> and <a> elements in a document with a value for the href attribute.
var links = document.links;
for(var i = 0; i < links.length; i++) {
if (links[i].hostname != window.location.hostname) {
links[i].target = '_blank';
}
}
https://developer.mozilla.org/en-US/docs/Web/API/Document/links

Add a target="_blank" to the tag. You could do that in the pre-processor (e.g. PHP) or in a JS during the onload event.

$("a[href^=http]").each(function(){
if(this.href.indexOf(location.hostname) == -1) {
$(this).attr({
target: "_blank",
title: "Opens in a new window"
});
}
})
This script should work for you.
UPDATE : try this fiddle http://jsfiddle.net/sameerast/GuT2y/
JS version
var externalLinks = function(){
var anchors = document.getElementsByTagName('a');
var length = anchors.length;
for(var i=0; i<length;i++){
var href = anchor[i].href;
if(href.indexOf('http://sample.com/') || href.indexOf('http://www.sample.com/')){
return;
}
else{
anchor[i].target='_blank';
}
}
};

Related

Looping through array and clicking each link via CasperJS [duplicate]

I'm having trouble clicking all JavaScript based links in a DOM and saving the
output. The links have the form
<a id="html" href="javascript:void(0);" onclick="goToHtml();">HTML</a>
the following code works great:
var casper = require('casper').create();
var fs = require('fs');
var firstUrl = 'http://www.testurl.com/test.html';
var css_selector = '#jan_html';
casper.start(firstUrl);
casper.thenClick(css_selector, function(){
console.log("whoop");
});
casper.waitFor(function check() {
return this.getCurrentUrl() != firstUrl;
}, function then() {
console.log(this.getCurrentUrl());
var file_title = this.getTitle().split(' ').join('_') + '.html';
fs.write(file_title, this.getPageContent());
});
casper.run();
However, how can I get this to work with a selector of "a", clicking all
available links and saving content? I'm not sure how to get the clickWhileSelector to remove nodes from the selector as is done here: Click on all links matching a selector
I have this script that first will get all links from a page then save 'href' attributes to an array, then will iterate over this array and then open each link one by one and echo the url :
var casper = require('casper').create({
logLevel:"verbose",
debug:true
});
var links;
casper.start('http://localhost:8000');
casper.then(function getLinks(){
links = this.evaluate(function(){
var links = document.getElementsByTagName('a');
links = Array.prototype.map.call(links,function(link){
return link.getAttribute('href');
});
return links;
});
});
casper.then(function(){
this.each(links,function(self,link){
self.thenOpen(link,function(a){
this.echo(this.getCurrentUrl());
});
});
});
casper.run(function(){
this.exit();
});
rusln's answer works great if all the links have a meaningful href attribute (actual URL). If you want to click every a that also triggers a javascript function, you may need to iterate some other way over the elements.
I propose using the XPath generator from stijn de ryck for an element.
You can then sample all XPaths that are on the page.
Then you open the page for every a that you have the XPath for and click it by XPath.
Wait a little if it is a single page application
Do something
var startURL = 'http://localhost:8000',
xPaths
x = require('casper').selectXPath;
casper.start(startURL);
casper.then(function getLinks(){
xPaths = this.evaluate(function(){
// copied from https://stackoverflow.com/a/5178132/1816580
function createXPathFromElement(elm) {
var allNodes = document.getElementsByTagName('*');
for (var segs = []; elm && elm.nodeType == 1; elm = elm.parentNode) {
if (elm.hasAttribute('id')) {
var uniqueIdCount = 0;
for (var n=0;n < allNodes.length;n++) {
if (allNodes[n].hasAttribute('id') && allNodes[n].id == elm.id) uniqueIdCount++;
if (uniqueIdCount > 1) break;
};
if ( uniqueIdCount == 1) {
segs.unshift('id("' + elm.getAttribute('id') + '")');
return segs.join('/');
} else {
segs.unshift(elm.localName.toLowerCase() + '[#id="' + elm.getAttribute('id') + '"]');
}
} else if (elm.hasAttribute('class')) {
segs.unshift(elm.localName.toLowerCase() + '[#class="' + elm.getAttribute('class') + '"]');
} else {
for (i = 1, sib = elm.previousSibling; sib; sib = sib.previousSibling) {
if (sib.localName == elm.localName) i++; };
segs.unshift(elm.localName.toLowerCase() + '[' + i + ']');
};
};
return segs.length ? '/' + segs.join('/') : null;
};
var links = document.getElementsByTagName('a');
var xPaths = Array.prototype.map.call(links, createXPathFromElement);
return xPaths;
});
});
casper.then(function(){
this.each(xPaths, function(self, xpath){
self.thenOpen(startURL);
self.thenClick(x(xpath));
// waiting some time may be necessary for single page applications
self.wait(1000);
self.then(function(a){
// do something meaningful here
this.echo(this.getCurrentUrl());
});
// Uncomment the following line in case each click opens a new page instead of staying at the same page
//self.back()
});
});
casper.run(function(){
this.exit();
});

How can I strip out a the base URL using JavaScript?

I have this function from a previous problem, and it works great however I just realized my collection of links need to have the base URL stripped out.
These are the parts which I thought would strip out the baseURL:
baseUrlPattern = /^https?:\/\/[a-z\:0-9.]+/; // create the regexp
link.href.replace(baseUrlPattern ,""); // then use replace to strip it out of the URL
UPDATE
I should have mentioned:
The function already can discover the link and apply the attribute, but doesn't strip out the base URL.
This:
link1
Should look like this in the DOM afterwards:
link1
JS:
var URLChecker = (function iffe() {
var publicAPI = {
getURL: function() {
for (var i = 0; i < arguments.length; i++) {
return {
'smo': 'http://url.nyc.com',
'smodev': 'http://smodev.rye.foo.com',
'url1_sans_3w': 'http://url1.com',
'url2': 'http://www.url2.com',
'url3': 'http://www2.url3.com'
}[arguments[i]];
}
},
searchURL: function() {
var link, url, baseUrlPattern = /^https?:\/\/[a-z\:0-9.]+/;
for (var i = 0, len = arguments.length; i < len; i++) {
url = this.getURL(arguments[i]);
for (var j = 0, jlen = document.links.length; j < jlen; j++) {
link = document.links[j];
if (link.href.indexOf(url) !== -1) {
link.setAttribute("target", "_blank");
link.href.replace(baseUrlPattern ,"");
}
}
}
}
};
return publicAPI;
})();
HTML:
link1
<br>
link2
<br>
link3
<br>
link4
<br>
link5
Using native methods:
var url = 'http://url.nyc.com/x/xx/xxx';
var strippedUrl = new URL(url); // url.pathname == '/x/xx/xxx/'
Note: this may not work in Chrome; but browser wasn't specified
There's different ways you can go about this, here's one of them:
See comments below
searchURL: function() {
var link, url, parser; //added parser
for (var i = 0, len = arguments.length; i < len; i++) {
url = this.getURL(arguments[i]);
for (var j = 0, jlen = document.links.length; j < jlen; j++) {
link = document.links[j];
if (link.href.indexOf(url) !== -1) {
// create a dummy link just to get the pathname of the actual link
parser = document.createElement('a');
parser.href = link.href;
link.setAttribute("target", "_blank");
link.href = parser.pathname;
}
}
}
}
Should you need anything else, remember the parser just an anchor so you have the following
var href = "http://url.nyc.com/xxx/xxx/xxx";
parser = document.createElement('a');
parser.href = href;
console.dir(parser);
parser.protocol; // => "http:"
parser.hostname; // => "url.nyc.com"
parser.port; // => ""
parser.pathname; // => "/xxx/xxx/xxx"
parser.search; // => ""
parser.hash; // => ""
parser.host; // => "url.nyc.com"
Maybe it's late but if you want
This:
link1
Should look like this in the DOM afterwards:
link1
you can do this way
var x = 'http://url.nyc.com/xxx/xxx/xxx';
var y = x.split('/').slice(3).join('/');
console.log(y);

Redirecting multiple values in URL with Greasemonkey

I'm trying to get Greasemonkey to automatically redirect a page when it hits a certain URL, and redirect to a page with two of the same values. For instance:
http://www.google.com/page=438985&view=49834
into: http://www.google.com/document/page=438985/field&view=49834&DONE
I've tried the following:
var links,thisLink;
links = document.evaluate("//a[#href]",
document,
null,
XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,
null);
for (var i=0;i<links.snapshotLength;i++) {
var thisLink = links.snapshotItem(i);
thisLink.href = thisLink.href.replace(RegExp('http://www.google.com/page=($1)&view=($2)'),
'http://www.google.com/document/page=$1/field&view=$2&DONE');
}
var links = document.getElementsByTagName('a');
for(var i = links.length - 1; i >= 0; i--) {
if(links[i] && links[i].href) {
links[i].href = links[i].href.replace(/http:\/\/www\.google\.com\/page=(\d+)&view=(\d+)/,
'http://www.google.com/document/page=$1/field&view=$2&DONE');
}
}
Demo

Ask user if external link should be opened in an external window / tab

I have the following Javascript running on my site to open all external links in a new window / tab:
function linkopener(a) {
var b = a ? "_blank" : "_self";
var c = document.links;
for (var i=0; i < c.length; i++) {
if (c[i].href.search("domain.tld") == -1) c[i].target = b;
}
}
window.onload = linkopener;
Now I would like to add a question to the user as soon as she/he clicks on an external link whether she/he wants to open it in a new window/tab or open it in the current window/tab.
No question should be shown if she/he wants to exit the site manually.
Is that possible and if yes, how?
Thanks in advance!
function linkopener(a) {
var b = a ? "_blank" : "_self";
var c = document.links;
for (var i = 0; i < c.length; i++) {
if (c[i].href.search("peleke.de") == -1) {
c[i].addEventListener("click", function () {
if (confirm("Do you want to open this in a new window/tab?")) {
this.target = b;
} else {
this.target = '';
}
});
}
}
}
window.onload = linkopener;
DEMO

How to follow all links in CasperJS?

I'm having trouble clicking all JavaScript based links in a DOM and saving the
output. The links have the form
<a id="html" href="javascript:void(0);" onclick="goToHtml();">HTML</a>
the following code works great:
var casper = require('casper').create();
var fs = require('fs');
var firstUrl = 'http://www.testurl.com/test.html';
var css_selector = '#jan_html';
casper.start(firstUrl);
casper.thenClick(css_selector, function(){
console.log("whoop");
});
casper.waitFor(function check() {
return this.getCurrentUrl() != firstUrl;
}, function then() {
console.log(this.getCurrentUrl());
var file_title = this.getTitle().split(' ').join('_') + '.html';
fs.write(file_title, this.getPageContent());
});
casper.run();
However, how can I get this to work with a selector of "a", clicking all
available links and saving content? I'm not sure how to get the clickWhileSelector to remove nodes from the selector as is done here: Click on all links matching a selector
I have this script that first will get all links from a page then save 'href' attributes to an array, then will iterate over this array and then open each link one by one and echo the url :
var casper = require('casper').create({
logLevel:"verbose",
debug:true
});
var links;
casper.start('http://localhost:8000');
casper.then(function getLinks(){
links = this.evaluate(function(){
var links = document.getElementsByTagName('a');
links = Array.prototype.map.call(links,function(link){
return link.getAttribute('href');
});
return links;
});
});
casper.then(function(){
this.each(links,function(self,link){
self.thenOpen(link,function(a){
this.echo(this.getCurrentUrl());
});
});
});
casper.run(function(){
this.exit();
});
rusln's answer works great if all the links have a meaningful href attribute (actual URL). If you want to click every a that also triggers a javascript function, you may need to iterate some other way over the elements.
I propose using the XPath generator from stijn de ryck for an element.
You can then sample all XPaths that are on the page.
Then you open the page for every a that you have the XPath for and click it by XPath.
Wait a little if it is a single page application
Do something
var startURL = 'http://localhost:8000',
xPaths
x = require('casper').selectXPath;
casper.start(startURL);
casper.then(function getLinks(){
xPaths = this.evaluate(function(){
// copied from https://stackoverflow.com/a/5178132/1816580
function createXPathFromElement(elm) {
var allNodes = document.getElementsByTagName('*');
for (var segs = []; elm && elm.nodeType == 1; elm = elm.parentNode) {
if (elm.hasAttribute('id')) {
var uniqueIdCount = 0;
for (var n=0;n < allNodes.length;n++) {
if (allNodes[n].hasAttribute('id') && allNodes[n].id == elm.id) uniqueIdCount++;
if (uniqueIdCount > 1) break;
};
if ( uniqueIdCount == 1) {
segs.unshift('id("' + elm.getAttribute('id') + '")');
return segs.join('/');
} else {
segs.unshift(elm.localName.toLowerCase() + '[#id="' + elm.getAttribute('id') + '"]');
}
} else if (elm.hasAttribute('class')) {
segs.unshift(elm.localName.toLowerCase() + '[#class="' + elm.getAttribute('class') + '"]');
} else {
for (i = 1, sib = elm.previousSibling; sib; sib = sib.previousSibling) {
if (sib.localName == elm.localName) i++; };
segs.unshift(elm.localName.toLowerCase() + '[' + i + ']');
};
};
return segs.length ? '/' + segs.join('/') : null;
};
var links = document.getElementsByTagName('a');
var xPaths = Array.prototype.map.call(links, createXPathFromElement);
return xPaths;
});
});
casper.then(function(){
this.each(xPaths, function(self, xpath){
self.thenOpen(startURL);
self.thenClick(x(xpath));
// waiting some time may be necessary for single page applications
self.wait(1000);
self.then(function(a){
// do something meaningful here
this.echo(this.getCurrentUrl());
});
// Uncomment the following line in case each click opens a new page instead of staying at the same page
//self.back()
});
});
casper.run(function(){
this.exit();
});

Categories