2013-07-03 23 views
4

我正在尝试使用Javascript来模拟CSS :target伪类,以便捕获导致页面中的元素成为目标的所有事件。我已经确定3个触发事件:仅捕获不是锚定点击造成的hashchange事件

  1. window.location.hash上初始化
  2. 锚靶向元件被点击
  3. hashchange事件是在上述的独立地发射已经靶向相同ID的元素(例如通过window.history API)

方案2是作为一个独特的情况下,重要的,因为我想调用click事件的preventDefault。此方案的简化代码如下:

$('body').on('click', 'a[href*=#]', function filterTarget(clickEvent){ 
    $(this.hash).trigger('target', [clickEvent]); 
}); 

试图实施方案3时,问题就来了:

$(window).on('hashchange', function filterTarget(hashChangeEvent){ 
    $(this.hash).trigger('target', [hashChangeEvent]); 
}); 

如果target处理取消本地行为方案2,它将在本机行为导致产生的hashchange事件时再次触发。我如何过滤掉这些边缘情况?

POST-SOLUTION编辑:

烤的答案举行的关键 - 基于点击处理程序及其内部的preventDefault处理逻辑处理命名空间hashchange事件,然后解除绑定并重新绑定的处理程序。 I wrote up the full plugin here

+0

你能给用户如何可以使用您所描述的系统的例子吗? –

+0

@SamuelReid我正在研究一个丰富的单页网页应用程序,重点关注渐进式增强功能:对于没有使用Javascript的用户代理在概念上可行的所有交互和导航都使用表单元素和(最经常)链接处理 - 一个很多时间哈希用于导航或显示页面内的元素。但是当应用Javascript时,我经常想要中断这些事件并取代原生行为。 – Barney

+0

@SamuelReid举个具体的例子:有一些像'脚注查看器'那样显示大量引用。本机行为只是跳转到引用问题,但增强的行为打开了一个模式界面,以更好地与引用和源文件引用进行整体交互。我希望人们能够分享永久链接到脚注,但如果JS可用,我仍然希望在可能的情况下使用“脚注查看器”。 – Barney

回答

5

如果我明白了,如果点击锚标签,您不希望激发hashchange事件。然后,您可以使用命名空间的事件设置你的逻辑:

DEMO

$('body').on('click', 'a[href*=#]', function (clickEvent) { 
    filterTarget(clickEvent,this); 
    $(window).off('hashchange.filter').on('hashchange.tmp', function() { 
      $(this).off('hashchange.tmp').on('hashchange.filter', filterTarget); 
    }); 
}); 
$(window).on('hashchange.filter', filterTarget); 

function filterTarget(event,elem) { 
    $(elem?elem.hash:window.location.hash).trigger('target', [event]); 
    //you could filter depending event.type 
    alert(event.type + '::'+ (elem?elem.hash:window.location.hash)); 
} 
+0

这几乎就是我想要的 - 事件嵌套和链接抛给我,但现在我有时间去处理它,我确信命名空间过滤就是解决方案。我将扩展捕获的'clickEvent'的'preventDefault'来重新设置'hashchange'处理程序,并在排序后发布结果。 – Barney

+0

很抱歉没有尽快给予赏金 - 我一直在等待,直到我找到了完成我的完整剧本的时间 - 但重点是您的解决方案绝对精美,其结果是为我创造奇迹。谢谢! – Barney

+0

Thx @Barney,很高兴帮助! :) –

0

好像你可以使用mousedown而不是点击,如果你打算对它调用preventDefault。那么推测hashchange不会被触发。

+0

感谢您的建议。面临的挑战在于,不是基于click事件触发'target',而是基于'hashchange'再次触发:实际上,如果'hashchange'不是'hashchange',我只想'target'激发本身是'click'的结果(它已经触发了'target'事件一次)。 – Barney

1

如果点击被设定与该片的哈希反正只是扔掉重复哈希改变事件:

onhashchange=function(e){ 
    if(e.newURL == e.oldURL){return; } 
//do your normal hashchange event stuff below: 

}; 

裁判:https://developer.mozilla.org/en-US/docs/Web/API/window.onhashchange

此修复级联问题不管是什么调用的变化。

+0

'hashchange'隐式处理这个问题,因为'e.newURL == e.oldURL'不会触发'hashchange'的理论事件(没有改变)。在实际的'hashchange'事件的上下文中,我确实想停止('e.newURL!= e.oldURL'),我需要知道根本原因是否是链接点击 - 它已经触发了一个“目标”事件。 – Barney