PDA

View Full Version : Offsite Link Confirmation Script?



oMaT
08-21-2007, 01:53 PM
Greetings!

I'm looking for a small piece of code which will simply identify when a link has been clicked that does not contain <myDomain> (eg; an offsite link) it will pop a confirmation dialog. While I would very much prefer to go back and edit the links themselves, at the point I became involved in this site there were already over 4000 links spread across hundreds of pages. Can it not be a simple matter of a regex which identifies where the user-clicked link is attempting to go?

I've come across a couple of *similar* scripts but none of them seem to work properly or they just miss the mark of my need. Unfortunately, I do not know javascript... at all. Also, this script needs to work in at least the major browsers.

Your help is greatly greatly appreciated.
Thank you.

oMaT

Twey
08-21-2007, 03:03 PM
<script type="text/javascript">
onload = function() {
for(var i = 0, a = document.links, n = a.length; i < n; ++i)
if(!/mydomain\.com/.test(a[i]))
a[i].onclick = function() {
return confirm("Are you sure you want to leave this page?");
};
a = null;
};
</script>

oMaT
08-21-2007, 03:08 PM
Holy Helpful, Batman.

That seems to do the exact trick.
Thank you, Twey.

Twey
08-21-2007, 03:26 PM
Welcome. It's not perfect (e.g. http://www.google.com/search?q=mydomain.com won't give a warning) but it'll do in most situations. To be a bit more specific you can just modify the regex:
<script type="text/javascript">
onload = function() {
for(var i = 0, a = document.links, n = a.length; i < n; ++i)
if(!/^(?:http:\/\/|www\.)(?:www\.)?mydomain\.com/.test(a[i]))
a[i].onclick = function() {
return confirm("Are you sure you want to leave this page?");
};
a = null;
};
</script>

jscheuer1
08-21-2007, 04:03 PM
Here is a slightly more involved version that requires no configuration (it gets the domain from the page), shouldn't conflict with other scripts on the page or other events already attached to the links:


var testlinks={
init:function(){
for (var i = 0, l = document.links; i < l.length; i++)
testlinks.ad_event(l[i], 'click', testlinks.test);
},
test:function(e){
var re=location.hostname? new RegExp(location.hostname) : new RegExp('^(?!http)');
if(re.test(this.href))
return true;
var test=confirm('Do you really want to leave?');
if(!test&&e&&e.preventDefault)
e.preventDefault();
return test;
},
events:[],
ad_event:function(el,etype,f){
if ( typeof window.addEventListener != "undefined" )
el.addEventListener( etype, f, false );
else if ( typeof window.attachEvent != "undefined" ){
var t = function() {
return f.apply(el);
};
testlinks.events.push({'element': el, 'event': 'on'+etype, 'handler': t});
el.attachEvent( "on"+etype, t );
}
}
};
if(document.links)
testlinks.ad_event(window, 'load', testlinks.init);
if(testlinks.events.length>0&&window.detachEvent)
window.attachEvent('onunload', function(){
for(var i = 0, e = testlinks.events; i < e.length; i++) {
e[i].element.detachEvent(e[i].event, e[i].handler);
e[i].element[e[i].event] = null;
};
});

oMaT
08-21-2007, 04:10 PM
You blokes are outstanding.

Thank you very much.

oMaT

oMaT
08-21-2007, 06:44 PM
Just one quick follow up, if I may...

Regarding the second script; how can I add in an exception for a javascript link? The site has several href="javascript:blahFunction();" links which also need to be considered internal.

Thank you very much.

oMaT

jscheuer1
08-21-2007, 06:52 PM
Not sure which script you mean, in mine:


var re=location.hostname? new RegExp(location.hostname+'|javascript:') : new RegExp('^(?!http)');

oMaT
08-21-2007, 06:56 PM
It was indeed yours I was referring to.
Thank you so much.. again!

oMaT

djr33
08-21-2007, 07:02 PM
Easy. Don't use that method.
It's a much better idea to include a real href as a backup to the javascript, such as, if you were making an image gallery, a direct link to the image you'd be displaying, etc.

Then use an onClick attribute with return false.

For example:

<a href="popup.htm" onClick="makePopUp(this.href); return false;">


Usually, if you actually don't have a page to link to, such as a javascript function that isn't crucial link changing text color on the page, etc., then you could use:
<a href="#" onClick="stuff(); return false;">

I'm not sure how # will work with the above script, either, but it's worth a try.

Alternatively, I suppose you could remove the href attribute entirely. That would allow the a tag to behave in the same way for the javascript and it should still take the style of the other a tags, such as underlining, but in some browsers it doesn't use the hand cursor. I believe you can do style="cursor:hand;" and that will override that. (Or you could set this in the css stylesheet which might be a good idea, if you have a number of such links.)

You could also just leave the href blank or supply a local page, and if javascript was disabled (note that this is the only case in which return false; wouldn't override the link), it would take the visitor to that location, or, if blank, reload the current page. It would, however, not give you the external site message with this method. (Though, I suppose, it would not do so if javascript wasn't enabled anyway.)


EDIT: looks like it took me too long to post.

oMaT
08-21-2007, 07:09 PM
Thanks for your input, djr33!

Unfortunately, changing the structure of the links simply isn't an option. I very much appreciate your taking the time to answer, though. Everyone's help today has been invaluable.

Thank you.

oMaT

jscheuer1
08-21-2007, 07:20 PM
djr33,

It was determined from the beginning that this was a stop gap effort (read the first post in the thread).

Things like:


<a href="#" onclick="whatever" . . .

and:


<a href="image.jpg" onclick="whatever" . . .

should work just fine though, as they will pass the location.hostname test and should not be altered in their behavior by my script.

djr33
08-21-2007, 07:27 PM
Sure. No problem.
I thought it might be beneficial to consider what would happen if javascript isn't enabled in a browser, though.
But that's getting away from your original question. Glad it works.

jscheuer1
08-21-2007, 07:32 PM
Without javascript, there isn't much that can be done other than edit all the links for target attributes (_blank for off site links), even that isn't a substitute. It did just now occur to me that the code would be more economical (once loaded) and even less likely to interfere with other existing javascript, this way (moving the test of link type to the init function):


var testlinks={
init:function(){
var re=location.hostname? new RegExp(location.hostname+'|javascript:') : new RegExp('^(?!http)');
for (var i = 0, l = document.links; i < l.length; i++)
if(!re.test(l[i].href))
testlinks.ad_event(l[i], 'click', testlinks.test);
},
test:function(e){
var test=confirm('Do you really want to leave?');
if(!test&&e&&e.preventDefault)
e.preventDefault();
return test;
},
events:[],
ad_event:function(el,etype,f){
if ( typeof window.addEventListener != 'undefined' )
el.addEventListener( etype, f, false );
else if ( typeof window.attachEvent != 'undefined' ){
var t = function() {
return f.apply(el);
};
testlinks.events.push({'element': el, 'event': 'on'+etype, 'handler': t});
el.attachEvent( 'on'+etype, t );
}
}
};
if(document.links)
testlinks.ad_event(window, 'load', testlinks.init);
if(testlinks.events.length>0&&window.detachEvent)
window.attachEvent('onunload', function(){
for(var i = 0, e = testlinks.events; i < e.length; i++) {
e[i].element.detachEvent(e[i].event, e[i].handler);
e[i].element[e[i].event] = null;
};
});

That way, on site links will have nothing added to them. But, that would miss links whose href's were later dynamically altered to off site.

jscheuer1
08-22-2007, 12:47 AM
I'm now liking this version (below) even better. I am back to assigning the function to all links, but now, if it is an on site link, it returns undefined (before it returned true). This means that if the link has any type of existing scripted return value, true or false, that will be preserved. The reason this is nice is twofold. Once for the reason just mentioned, and second for links whose href value may change after page load, so that they can be processed properly as regards their off, or on site href status. I did the same for off site links that get 'approved' by the user. For those, the added function will now return undefined, preserving any previously scripted return value for those links as well. I also changed the fall-back RegExp test to ('^[^(http)]'), one that uses an older, more widely supported syntax. This would only be used testing locally in browsers like IE that don't support the 'localhost' convention for local pages, but, at least in theory, potentially extends this convenience to more browsers.


var testlinks={
init:function(){
for (var i = 0, l = document.links; i < l.length; i++)
testlinks.ad_event(l[i], 'click', testlinks.test);
},
test:function(e){
var re=location.hostname? new RegExp(location.hostname+'|javascript:') : new RegExp('^[^(http)]');
if(re.test(this.href))
return undefined;
var test=confirm('Do you really want to leave?');
if(!test&&e&&e.preventDefault)
e.preventDefault();
return test? undefined : false;
},
events:[],
ad_event:function(el,etype,f){
if ( typeof window.addEventListener != 'undefined' )
el.addEventListener( etype, f, false );
else if ( typeof window.attachEvent != 'undefined' ){
var t = function() {
return f.apply(el);
};
testlinks.events.push({'element': el, 'event': 'on'+etype, 'handler': t});
el.attachEvent( 'on'+etype, t );
}
}
};
if(document.links)
testlinks.ad_event(window, 'load', testlinks.init);
if(testlinks.events.length>0&&window.detachEvent)
window.attachEvent('onunload', function(){
for(var i = 0, e = testlinks.events; i < e.length; i++) {
e[i].element.detachEvent(e[i].event, e[i].handler);
e[i].element[e[i].event] = null;
};
});

oMaT
08-22-2007, 12:50 AM
Thank you yet again!
Your generosity is incredible.