2013-08-23 27 views
8

Załóżmy, że mam rozszerzenie, które ładuje się po wyświetleniu strony z filmem w YouTube. Zauważyłem, że gdy ktoś nawiguje w tę iz powrotem przy użyciu przycisków Chrome, rozszerzenie najprawdopodobniej wygrało Ładunek.Rozszerzenie Chrome nie ładuje się podczas nawigacji w przeglądarce pod adresem YouTube

Jako przykład mam 2 pliki manifest:

{ 
    "name": "back forth", 
    "version": "0.1", 
    "manifest_version": 2, 
    "description": "back forth", 
    "permissions": ["storage", "*://www.youtube.com/watch*"], 
    "content_scripts": [ 
     { 
      "matches": ["*://www.youtube.com/watch*"], 
      "js": ["contentscript.js"] 
     } 
    ] 
} 

i contentscript

alert("loaded"); 

Alert nie zawsze pojawiają się podczas poruszania się tam iz powrotem. Jak mogę to przezwyciężyć, aby rozszerzenie ładowało się za każdym razem?

+0

Podobne http://stackoverflow.com/a/34100952/72321 – Dennis

Odpowiedz

17

YouTube rozpoczął próbę z nawigacją opartą na technologii pushState. Ogólnie rzecz biorąc, takie nawigacje można wykryć tylko w skrypcie treści poprzez wstrzyknięcie kodu, który przechwytuje połączenia do history.replaceState/history.pushState (lub za pomocą zdarzenia chrome.webNavigation.onHistoryStateUpdated na stronie w tle).

Pozostała część tej odpowiedzi dotyczy serwisu YouTube.
YouTube pokazuje (czerwony) pasek postępu na górze strony podczas ładowania. Ten pasek postępu jest animowany przy użyciu przejścia CSS. Ponieważ zdarzenia przejściowe są wyświetlane, można powiązać odbiornik zdarzeń przejścia z <body> i sprawdzić nawigację w tych przypadkach.

Trzeba wstawić skrypt treści w *://www.youtube.com/* zamiast *://www.youtube.com/watch*, ponieważ pushState mogą być wykorzystywane do nawigacji z / do /watch...

function afterNavigate() { 
    if ('/watch' === location.pathname) { 
     alert('Watch page!'); 
    } 
} 
(document.body || document.documentElement).addEventListener('transitionend', 
    function(/*TransitionEvent*/ event) { 
    if (event.propertyName === 'width' && event.target.id === 'progress') { 
     afterNavigate(); 
    } 
}, true); 
// After page load 
afterNavigate(); 

Uwaga: Ta metoda zależy od tego, czy wstawiono pasek postępu. Ilekroć Google postanowi zmienić nazwę paska postępu lub całkowicie usunąć pasek postępu, Twój kod przestanie działać.

Uwaga 2: Działa to tylko dla aktywnych kart. Jeśli chcesz wykryć zmiany nawigacji, gdy karta nie jest skupiona, musisz powiązać zdarzenie window.onfocus i window.onblur i sprawdzić, czy między tymi zdarzeniami zmienił się document.title.

+0

Dzięki za tę odpowiedź. Za pomocą tej metody działa, ale nie jest tak wcześnie, jak DOMContentLoaded, wydaje się, że jest to równoważne 'load', czy istnieje tak aby wykryć punkt typu" DOMContentLoaded'? – Noitidart

+1

@Noitidart Jeśli naprawdę chcesz otrzymywać powiadomienia tak szybko, jak to możliwe, możesz powiązać ze zdarzeniem 'transitionstart', przeprowadzić ankietę w celu zmiany dokumentu (używając' setTimeout' lub 'setInterval'). Po znalezieniu żądanego elementu wyrejestruj wydarzenie przejścia od stanu i zatrzymaj odpytywanie + wywołaj niestandardowe wywołanie zwrotne. Aby upewnić się, że nie marnujesz cykli procesora, połącz to ze zdarzeniem transitionend; jeśli twoja logika pollingu nie wykryła niczego w tym momencie, usuń detektory zdarzeń, zatrzymaj poller i wywołaj callback. –

+0

Pomysł geniusza @RobW dzięki! Próbowałem dodać 'window.onpopstate = function (e) {console.log (e)}' myślałem, że to by się udało, ale nie otrzymuję żadnych wywołań zwrotnych. – Noitidart