2013-07-03 123 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