2012-11-07 98 views
2

我可以檢測history.pushState鉻瀏覽器用戶腳本(而不是擴展),沒有輪詢(或突破腳本的孤立世界攔截在網頁的JavaScript上下文中的調用)URL更改?如何攔截chrome腳本中的pjax頁面更改?

我的問題,更詳細:

由於Github使用history.pushState [WHAT-WG specs]通過[minimized example]的pjax在站點頁面到頁面的網站導航,而不是重新加載整個頁面爲你的方式瀏覽網站時,只有當您在該網址輸入網站或手動強制重新加載網頁時,纔會觸發針對網站上特定網址的用戶腳本。

我寫一個小的用戶腳本庫on.js對於幹:荷蘭國際集團了用戶腳本,處理那種對他們的事情通過攔截pushState通話時看到我們是一個新的網頁主機腳本要在運行和只有在相關時才援引它。

這將是比較容易,如果history.pushState引發的事件調用時,但最好我可以告訴,沒有popstate事件獲取時的第一頁加載或用戶觸發的歷史淵源/向前運動,這是相當無用除了解僱我的目的。我發現限制它只有一個pjax/github解決方案 - 當一個新的頁面加載時,github激發了一個$(document).trigger('pageUpdate')事件,但jQuery在內部而不是通過DOM事件實現了這些,我聽不到來自isolated world我的用戶腳本運行時,除非我在頁面本身注入一個小監聽器,讓其jQuery實例向我報告此事件,然後我不妨劫持頁面的history.pushState本身。

有沒有人看到其他整潔的方式來實現這一目標?

回答

0

現在,我採取了一種非常優秀的工作方式,即在注入腳本後攔截history.pushState調用,並在文檔中觸發同名事件(一次調用完成後) pjax pageUpdate事件被炒得):

function inject(fn, args) { 
    var script = document.createElement('script') 
    , parent = document.documentElement; 
    args = JSON.stringify(args || []).slice(1, -1); 
    script.textContent = '('+ fn +')('+ args +');'; 
    parent.appendChild(script); 
    parent.removeChild(script); 
} 

inject(function(pjax_event) { 
    function reportBack() { 
    var e = document.createEvent('Events'); 
    e.initEvent('history.pushState', !'bubbles', !'cancelable'); 
    document.dispatchEvent(e); 
    } 
    var pushState = history.pushState; 
    history.pushState = function on_pushState() { 
    if (pjax_event && window.$ && $.pjax) 
     $(document).one(pjax_event, reportBack); 
    else 
     setTimeout(reportBack, 0); 
    return pushState.apply(this, arguments); 
    }; 
}, ['pageUpdated']); 

document.addEventListener('history.pushState', function() { 
    console.log('history.pushState', location.pathname); 
    // user script code here 
}, false); 
+0

因此,我現在搜索後再次發現您的問題與解答,以前的代碼不再適用於使用GreaseMonkey(讀取Firefox)對沙箱進行的更改。你的代碼將失敗,因爲Github加強了他們的CSP以禁止內聯JavaScript。查看解答的其他答覆。 – jerone

0

的GreaseMonkey之前改變了它的沙箱政策(讀:火狐一樣,和GM沒能向後兼容)一個可以使用unsafeWindow獲取元素/窗口事件。現在已經改變了,與GreaseMonkey API's一起使用時,unsafeWindow不再工作。

由於內部安全策略(CSP)的內容安全策略(CSP)不允許內聯腳本,所以向Github提供了將腳本注入頁面的建議答案;

Content-Security-Policy:default-src *; script-src assets-cdn.github.com collector-cdn.github.com; [...]

我的解決方案是雙重的用於兩種不同的情況:一個@grant none和一個用的GreaseMonkey API @grant

test-grant-none.user。JS

// ==UserScript== 
// @name  test @grant none 
// @namespace https://github.com/jerone/UserScripts 
// @include https://github.com/* 
// @version 1 
// @grant  none 
// ==/UserScript== 

unsafeWindow.$(document).on("pjax:end", function() { 
    console.log('test @grant none 1'); 
}); 
unsafeWindow.$(window).on('popstate', function() { 
    console.log('test @grant none 2'); 
}); 

測試贈款GM.user.js

// ==UserScript== 
// @name  test @grant GM_* 
// @namespace https://github.com/jerone/UserScripts 
// @include https://github.com/* 
// @version 1 
// @grant  GM_setValue 
// ==/UserScript== 

unsafeWindow.$(document).on("pjax:end", exportFunction(function() { 
    console.log('test @grant GM_* 1'); 
}, unsafeWindow)); 
unsafeWindow.$(window).on('popstate', exportFunction(function() { 
    console.log('test @grant GM_* 2'); 
}, unsafeWindow)); 

你可以找到上面的腳本在這裏:https://gist.github.com/jerone/e38e8637887559870d84

您可以更在這裏讀到:https://greasyfork.org/en/forum/discussion/3648/hook-into-jquery-existing-events

感謝Athorcis指引我朝着正確的方向發展。