Javascript:如何确定链接是否与其所在页面的目标域相同?

时间:2021-07-08 17:40:08

For the purposes of tracking non-HTML documents via google analytics, I need the mentioned algorithm. It should:

为了通过谷歌分析跟踪非HTML文档,我需要提到的算法。这应该:

  • not hard-code the domain
  • 不硬编码域名

  • ignore the protocol (i.e. http/https)
  • 忽略协议(即http / https)

  • not worry about the presence/absence of "www" (any absolute links WILL prefix with "www" and all pages WILL be served via "www")
  • 不用担心“www”的存在/不存在(任何绝对链接都会以“www”为前缀,所有页面都将通过“www”提供)

This is complicated by the fact that I need to access it via a function called from the IE-only 'attachEvent'.

这是因为我需要通过从仅IE的“attachEvent”调用的函数来访问它。

UPDATE Sorry, I've worded this question really badly. The real problem is getting this to work via an event, since IE has its own made-up world of event handling. Take the following:

更新对不起,我的措辞非常糟糕。真正的问题是通过一个事件使这个工作,因为IE有自己的事件处理组成世界。请采取以下措施:

function add_event(obj) {
    if (obj.addEventListener)
        obj.addEventListener('click', track_file, true);
    else if (obj.attachEvent)
        obj.attachEvent("on" + 'click', track_file);
}

function track_file(obj) { }

It seems as if the "obj" in track_file is not the same across browsers - how can I refer to what was clicked in IE?

好像浏览器中track_file中的“obj”不一样 - 我如何引用IE中点击的内容?

7 个解决方案

#1


5  

I would like to point out that, if you're on so.com, the following links are URLs within the same domain:

我想指出,如果你在so.com上,以下链接是同一域内的URL:

(it may seem odd, but the last two ones are valid: if you're on http://so.com, the last one would take you to http://so.com/mail.google.com/index.php?var=value, which is perfectly valid)

(这可能看起来很奇怪,但最后两个是有效的:如果你在http://so.com上,最后一个会带你去http://so.com/mail.google.com/index。 php?var = value,这是完全有效的)

This doesn't really answer the question but I hope it will guide the rest of the answers. If there's anything else weird enough, feel free to add it.

这并没有真正回答这个问题,但我希望它能指导其余的答案。如果还有其他奇怪的东西,请随意添加。

#2


3  

This sounds like a comedy answer but in all seriousness it would be be advisable that you could also do something like:

这听起来像是一个喜剧的答案,但严肃地说,你也可以这样做:

$('a.external')

Certainly the regex comparison to your window.location is the programmatic answer.

当然,与window.location的正则表达式比较是程序化的答案。

#3


2  

The method of attachment is not the only way IE and W3 event listeners differ. For IE you must read window.event.srcElement; in W3 it's event.target where event is the parameter passed to the callback function.

附着方法不是IE和W3事件监听器不同的唯一方式。对于IE,您必须阅读window.event.srcElement;在W3中,它是event.target,其中event是传递给回调函数的参数。

If you don't need multiple event handlers on links, old-school DOM 0 event handlers are probably an easier way for you to approach this, allowing you to just us ‘this’ to get the object on any browser.

如果你不需要在链接上使用多个事件处理程序,那么老式的DOM 0事件处理程序可能是一种更简单的方法来处理这个问题,让你只需要我们“这个”来获取任何浏览器上的对象。

function bindtolinks() {
    for (var i= document.links.length; i-->0;)
        document.links.onclick= clicklink;
}

function clicklink() {
    if (this.host==window.location.host) {
        dosomething();
        return true; // I'm an internal link. Follow me.
    } else {
        dosomethingelse();
        return false; // I'm an external link. Don't follow, only do something else.
    }
}

#4


0  

Maybe this will help: http://www.quirksmode.org/js/events_properties.html#target

也许这会有所帮助:http://www.quirksmode.org/js/events_properties.html#target

#5


0  

I will answer the question in the update, about events in IE:

我将在更新中回答有关IE中事件的问题:

function track_file(evt)
{
  if (evt == undefined)
  {
    evt = window.event; // For IE
  }
  // Use evt
}

is the classical way to get consistent event object across browsers.

是跨浏览器获得一致事件对象的经典方法。

After that, I would use regexes to normalize the URL, but I am not sure what you look after.

之后,我会使用正则表达式来规范化URL,但我不确定你要照顾什么。

[EDIT] Some real code to put in practice what I wrote above... :-)

[编辑]一些真实的代码,以实践我上面写的... :-)

function CheckTarget(evt)
{
  if (evt == undefined)
  {
    // For IE
    evt = window.event;
//~     event.returnValue = false;
    var target = evt.srcElement;
    var console = { log: alert };
  }
  else
  {
    target = evt.target;
//~     preventDefault();
  }
  alert(target.hostname + " vs. " + window.location.hostname);
  var re = /^https?:\/\/[\w.-]*?([\w-]+\.[a-z]+)\/.*$/;
  var strippedURL = window.location.href.match(re);
  if (strippedURL == null)
  {
    // Oops! (?)
    alert("Where are we?");
    return false;
  }
  alert(window.location.href + " => " + strippedURL);
  var strippedTarget = target.href.match(re);
  if (strippedTarget == null)
  {
    // Oops! (?)
    alert("What is it?");
    return false;
  }
  alert(target + " => " + strippedTarget);
  if (strippedURL[1] == strippedTarget[1])
  {
//~     window.location.href = target.href;  // Go there
    return true; // Accept the jump
  }
  return false;
}

That's test code, not production code, obviously!

那显然是测试代码,而不是生产代码!

The lines with //~ comments show the alternative way of preventing the click on link to do the jump. It is, somehow, more efficient because if I use Firebug's console.log, curiously the return false is ineffective.
I used here the behavior "follow link or not", not knowing the real final purpose.

带有//~ comments的行显示了防止点击链接进行跳转的替代方法。它在某种程度上更有效率,因为如果我使用Firebug的console.log,奇怪的是返回false是无效的。我在这里使用的行为“跟随链接与否”,不知道真正的最终目的。

As pointed out in comments, the RE can be simpler by using hostname instead of href... I leave as it because it was already coded and might be useful in other cases.
Some special precautions should be taken in both cases to handle special cases, like localhost, IP addresses, ports...
I got rid of the domain name, before re-reading the question and seeing it wasn't a problem... Well, perhaps it can be useful to somebody else.

正如评论中指出的那样,通过使用主机名而不是href,RE可以更简单...我保留它因为它已经编码并且在其他情况下可能有用。在两种情况下都应该采取一些特殊的预防措施来处理特殊情况,比如localhost,IP地址,端口......我在重新阅读问题之前摆脱了域名,看到它不是问题...... ,也许它对其他人有用。

Note: I shown a similar solution in a question to decorate links: Editing all external links with javascript

注意:我在一个问题中展示了一个类似的解决方案来装饰链接:用javascript编辑所有外部链接

#6


0  

Given a click event and the original target element, this should work for the original question:

给定一个click事件和原始目标元素,这应该适用于原始问题:

if(target.protocol == window.location.protocol && target.host == window.location.host){
}

Browsers nicely convert the link from the various patterns mentioned by @Tom into full links, so the protocol and host values simply need to match your domain.

浏览器很好地将链接从@Tom提到的各种模式转换为完整链接,因此协议和主机值只需要匹配您的域。

#7


-2  

if( someDomElementWhichIsALink.href.indexOf(window.location) != -1 ) {
  // this is targeting your domain
}

#1


5  

I would like to point out that, if you're on so.com, the following links are URLs within the same domain:

我想指出,如果你在so.com上,以下链接是同一域内的URL:

(it may seem odd, but the last two ones are valid: if you're on http://so.com, the last one would take you to http://so.com/mail.google.com/index.php?var=value, which is perfectly valid)

(这可能看起来很奇怪,但最后两个是有效的:如果你在http://so.com上,最后一个会带你去http://so.com/mail.google.com/index。 php?var = value,这是完全有效的)

This doesn't really answer the question but I hope it will guide the rest of the answers. If there's anything else weird enough, feel free to add it.

这并没有真正回答这个问题,但我希望它能指导其余的答案。如果还有其他奇怪的东西,请随意添加。

#2


3  

This sounds like a comedy answer but in all seriousness it would be be advisable that you could also do something like:

这听起来像是一个喜剧的答案,但严肃地说,你也可以这样做:

$('a.external')

Certainly the regex comparison to your window.location is the programmatic answer.

当然,与window.location的正则表达式比较是程序化的答案。

#3


2  

The method of attachment is not the only way IE and W3 event listeners differ. For IE you must read window.event.srcElement; in W3 it's event.target where event is the parameter passed to the callback function.

附着方法不是IE和W3事件监听器不同的唯一方式。对于IE,您必须阅读window.event.srcElement;在W3中,它是event.target,其中event是传递给回调函数的参数。

If you don't need multiple event handlers on links, old-school DOM 0 event handlers are probably an easier way for you to approach this, allowing you to just us ‘this’ to get the object on any browser.

如果你不需要在链接上使用多个事件处理程序,那么老式的DOM 0事件处理程序可能是一种更简单的方法来处理这个问题,让你只需要我们“这个”来获取任何浏览器上的对象。

function bindtolinks() {
    for (var i= document.links.length; i-->0;)
        document.links.onclick= clicklink;
}

function clicklink() {
    if (this.host==window.location.host) {
        dosomething();
        return true; // I'm an internal link. Follow me.
    } else {
        dosomethingelse();
        return false; // I'm an external link. Don't follow, only do something else.
    }
}

#4


0  

Maybe this will help: http://www.quirksmode.org/js/events_properties.html#target

也许这会有所帮助:http://www.quirksmode.org/js/events_properties.html#target

#5


0  

I will answer the question in the update, about events in IE:

我将在更新中回答有关IE中事件的问题:

function track_file(evt)
{
  if (evt == undefined)
  {
    evt = window.event; // For IE
  }
  // Use evt
}

is the classical way to get consistent event object across browsers.

是跨浏览器获得一致事件对象的经典方法。

After that, I would use regexes to normalize the URL, but I am not sure what you look after.

之后,我会使用正则表达式来规范化URL,但我不确定你要照顾什么。

[EDIT] Some real code to put in practice what I wrote above... :-)

[编辑]一些真实的代码,以实践我上面写的... :-)

function CheckTarget(evt)
{
  if (evt == undefined)
  {
    // For IE
    evt = window.event;
//~     event.returnValue = false;
    var target = evt.srcElement;
    var console = { log: alert };
  }
  else
  {
    target = evt.target;
//~     preventDefault();
  }
  alert(target.hostname + " vs. " + window.location.hostname);
  var re = /^https?:\/\/[\w.-]*?([\w-]+\.[a-z]+)\/.*$/;
  var strippedURL = window.location.href.match(re);
  if (strippedURL == null)
  {
    // Oops! (?)
    alert("Where are we?");
    return false;
  }
  alert(window.location.href + " => " + strippedURL);
  var strippedTarget = target.href.match(re);
  if (strippedTarget == null)
  {
    // Oops! (?)
    alert("What is it?");
    return false;
  }
  alert(target + " => " + strippedTarget);
  if (strippedURL[1] == strippedTarget[1])
  {
//~     window.location.href = target.href;  // Go there
    return true; // Accept the jump
  }
  return false;
}

That's test code, not production code, obviously!

那显然是测试代码,而不是生产代码!

The lines with //~ comments show the alternative way of preventing the click on link to do the jump. It is, somehow, more efficient because if I use Firebug's console.log, curiously the return false is ineffective.
I used here the behavior "follow link or not", not knowing the real final purpose.

带有//~ comments的行显示了防止点击链接进行跳转的替代方法。它在某种程度上更有效率,因为如果我使用Firebug的console.log,奇怪的是返回false是无效的。我在这里使用的行为“跟随链接与否”,不知道真正的最终目的。

As pointed out in comments, the RE can be simpler by using hostname instead of href... I leave as it because it was already coded and might be useful in other cases.
Some special precautions should be taken in both cases to handle special cases, like localhost, IP addresses, ports...
I got rid of the domain name, before re-reading the question and seeing it wasn't a problem... Well, perhaps it can be useful to somebody else.

正如评论中指出的那样,通过使用主机名而不是href,RE可以更简单...我保留它因为它已经编码并且在其他情况下可能有用。在两种情况下都应该采取一些特殊的预防措施来处理特殊情况,比如localhost,IP地址,端口......我在重新阅读问题之前摆脱了域名,看到它不是问题...... ,也许它对其他人有用。

Note: I shown a similar solution in a question to decorate links: Editing all external links with javascript

注意:我在一个问题中展示了一个类似的解决方案来装饰链接:用javascript编辑所有外部链接

#6


0  

Given a click event and the original target element, this should work for the original question:

给定一个click事件和原始目标元素,这应该适用于原始问题:

if(target.protocol == window.location.protocol && target.host == window.location.host){
}

Browsers nicely convert the link from the various patterns mentioned by @Tom into full links, so the protocol and host values simply need to match your domain.

浏览器很好地将链接从@Tom提到的各种模式转换为完整链接,因此协议和主机值只需要匹配您的域。

#7


-2  

if( someDomElementWhichIsALink.href.indexOf(window.location) != -1 ) {
  // this is targeting your domain
}