2011-09-11 25 views
5

Tôi đã cố gắng để làm một trang user.js đến/tin nhắn trong facebook, nhưng trông giống như thông báo không có thông báo khi chuyển hướng từ/đến/tin nhắn. Nó cũng xảy ra ở các trang nội bộ khác. Đầu tiên tôi nghĩ rằng đó là do điều hướng AJAX gây ra, nhưng thay đổi URL (không phải là phần băm), vì vậy đó là điều hướng bình thường, phải không?Tại sao greasemonkey không phát hiện một số thay đổi trên trang trong facebook?

Đây là một trang thử nghiệm mà tôi đã sử dụng:

// ==UserScript== 
// @name   Test 
// @namespace  none 
// @description just an alert when page changes 
// @include  http*://www.facebook.com/* 
// ==/UserScript== 

alert(location.href); 

Làm thế nào tôi có thể phát hiện một cách chính xác những thay đổi trang?


Firefox phiên bản: 6.0.2

Greasemonkey phiên bản: 0.9.11

+0

Câu hỏi khác này có thể có liên quan. http://stackoverflow.com/questions/3522090/event-when-window-location-href-changes – bronsoja

Trả lời

8

Đối với trình duyệt hỗ trợ nó, bao gồm Firefox 4+, Facebook tận dụng API Lịch sử HTML5. API này cho phép thay đổi vị trí bằng cách sử dụng phương thức history.pushState() mặc dù không có điều hướng thực sự xảy ra. Mặc dù trang có vẻ đã thay đổi, tất cả những gì đã xảy ra là cuộc gọi ajax phía sau hậu trường làm thay đổi hầu hết nội dung.

Nếu bạn muốn nắm bắt sự thay đổi này, bạn phải để proxy phương pháp pushState() với chức năng riêng của bạn:

(function (old) { 
    window.history.pushState = function() { 
     old.apply(window.history, arguments); 
     alert(window.location.href); 
    } 
})(window.history.pushState); 

Đọc thêm về API Lịch sử tại https://developer.mozilla.org/en/DOM/Manipulating_the_browser_history.

+0

Tôi không nghĩ bạn phải sử dụng proxy - bạn không thể chỉ xử lý sự kiện 'window.onpopstate' ? – Coderer

+0

'onpopstate' không phát hiện khi pushState được gọi cho các trang mới, chỉ khi bạn sử dụng các nút tiến hoặc lùi (hoặc chuyển tiếp và quay lại các cuộc gọi API). – rampion

+0

vấn đề với cách tiếp cận này là các phần tử trang mới không nhất thiết phải được tải sau khi 'old.apply (window.history, arguments)' trả về, vì vậy nó có thể chưa sẵn sàng để kịch bản của bạn xử lý. – rampion

3

Một cách khác là để treo DOMNodeInserted cho trang, và để chạy khi con đường phù hợp với /messages sau khi chèn:

// ==UserScript== 
// ... 
// @include https://www.facebook.com/* 
// ... 
// ==/UserScript== 

var url = document.location.toString(); 
function scriptBody(){ 
    if (!url.match(/facebook.com\/messages/)) return; 
    // ... 
    // do stuff 
    // ... 
}); 

scriptBody(); // run on initial page load 

document.querySelector('html').addEventListener('DOMNodeInserted', function(ev){ 
    var new_url = document.location.toString(); 
    if (url == new_url) return; // already checked or processed 
    url = new_url; 

    scriptBody(); // run when URL changes 
}); 

Lưu ý rằng nếu bạn dùng sử dụng các chuyển tiếp/quay lại nút bạn có thể nhận được các sự kiện 'DOMNodeInserted' đối với nội dung đang được cài đặt lại cho trang mà bạn đã sửa đổi với tập lệnh của mình, vì vậy bạn cần đảm bảo bạn kiểm tra xem có thay đổi nào bạn thường thực hiện đối với trang đã được thực hiện hay không, để tránh chèn điều khiển trùng lặp hoặc bất kỳ điều gì .

0

+1 với đề xuất @rampion. Tôi muốn thực hiện một chuyển hướng đơn giản mặc dù và tìm kiếm các yếu tố trên trang không phải là rất hữu ích như tôi không muốn chuyển hướng người dùng không cần giám sát.

Dù sao, tôi đã sử dụng mã này để cài đặt một người biết lắng nghe mà sẽ chuyển hướng nơi cần thiết khi người dùng click vào một liên kết với đặc biệt href:

if (document.addEventListener){ 
    document.addEventListener("click", function(event) { 
    var targetElement = event.target || event.srcElement; 
    // TODO: support deeper search for parent element with a href attribute 
    var href = targetElement.getAttribute('href') || targetElement.parentElement.getAttribute('href') ; 
    if (href && videoURLRe.test(href)) { 
     var target = ""; 
     if (href.indexOf("/") == 0) { 
     target = "https://m.facebook.com" + href 
     } else { 
     target = href.replace("www.facebook", "m.facebook"); 
     } 
     window.location.assign(target); 
    } 
    }, true); 
} 

Làm việc khá gọn gàng. Tôi đã tìm đúng param thứ ba addEventListener để người nghe của tôi được thực thi trước bất kỳ người nào khác.

Đối với cái nhìn kịch bản đầy đủ tại https://greasyfork.org/en/scripts/8176-switch-to-mobile-version-on-facebook-video-page

tôi không thể tìm thấy bất kỳ cách nào đáng tin cậy phát hiện những thay đổi URL bất kể phương pháp được sử dụng bởi các trang web để thay đổi URL đó. Cách tiếp cận @ andy-e có vẻ tuyệt vời nhưng không hiệu quả đối với tôi vì một số lý do. Có lẽ tôi không thể làm cho tập lệnh @grant thẻ đúng cách.

Các vấn đề liên quan