Почему greasemonkey не обнаруживает некоторые изменения страницы в Facebook? - PullRequest
5 голосов
/ 12 сентября 2011

Я пытался создать страницу user.js для / messages в Facebook, но похоже, что greasemonkey не замечает, когда навигация меняется с / на / messages. Это также происходит на других внутренних страницах. Сначала я подумал, что это вызвано AJAX-навигацией, но URL-адрес меняется (не хэш-часть), поэтому это нормальная навигация, верно?

Это тестовая страница, которую я использовал:

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

alert(location.href);

Как правильно определить изменения страницы?


Версия Firefox: 6.0.2

Версия Greasemonkey: 0.9.11

Ответы [ 3 ]

9 голосов
/ 12 сентября 2011

Для браузеров, которые поддерживают его, включая Firefox 4+, Facebook использует API истории HTML5. Этот API позволяет изменять местоположение с помощью метода history.pushState(), хотя на самом деле навигации не происходит. Хотя может показаться, что страница изменилась, все, что произошло, - это скрытый ajax-вызов, который меняет большую часть содержимого.

Если вы хотите зафиксировать это изменение, вам придется проксировать метод pushState() с помощью собственной функции:

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

Подробнее об API истории можно узнать по адресу https://developer.mozilla.org/en/DOM/Manipulating_the_browser_history.

3 голосов
/ 08 января 2014

Другой подход заключается в подключении DOMNodeInserted для страницы и запуске при совпадении пути /messages после вставки:

// ==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
});

Обратите внимание, что если вы пользуетесь кнопками «Вперед» и «Назад», вы можете получить события «DOMNodeInserted» для контента, который повторно вставляется на страницу, которую вы уже изменили с помощью своего скрипта, поэтому вам необходимо убедиться, что вы проверили были ли внесены какие-либо изменения, которые вы обычно вносите в страницу, для предотвращения вставки дублирующих элементов управления или чего-либо другого.

0 голосов
/ 21 апреля 2015

+ 1 к @rampion предложениям.Я хотел выполнить простое перенаправление, хотя поиск элементов на странице был не очень полезен, так как я не хочу перенаправлять пользователя без присмотра.

В любом случае, я использовал этот код для установки прослушивателя, который перенаправлял бы в случае необходимостипосле того, как пользователь нажмет на ссылку с конкретным 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);
}

Работает довольно аккуратно.Мне пришлось вычислить правильный третий параметр addEventListener, чтобы мой слушатель выполнялся раньше других.

Для полного сценария посмотрите на https://greasyfork.org/en/scripts/8176-switch-to-mobile-version-on-facebook-video-page

Я не смог найти какой-либо способ надежно обнаружить изменения URLнезависимо от метода, используемого веб-сайтом для изменения этого URL.@ Andy-e подход кажется удивительным, но по какой-то причине у меня не работаетВозможно, я не смог сделать скрипт @grant должным образом.

...