Skip to content

Commit b55612a

Browse files
authored
Handle SPA navigations in reading time example. (#1496)
In the move to new infrastructure for https://developer.chrome.com/, the site became an SPA which can soft navigate outside of browser navigations. Therefore, we need to update the sample to watch for changes to content after the content script is injected.
1 parent 8d6e02a commit b55612a

2 files changed

Lines changed: 29 additions & 3 deletions

File tree

functional-samples/tutorial.reading-time/README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ This sample demonstrates how to run scripts on any Chrome extension and Chrome W
66

77
This sample demonstrates how developers can use content scripts which employ Document Object Models to read and change the content of a page. In this instance, the extension checks to find an article element, counts all the words inside of it, and then creates a paragraph that estimates the total reading time for that article.
88

9+
As https://developer.chrome.com/ is a SPA (Single Page Application) it also includes an example of how to use `MutationObserver` to watch for changes to article content. Using `MutationObserver` can have a performance cost, so use them sparingly and only observe the most relevant changes.
10+
911
## Running this extension
1012

1113
1. Clone this repository.

functional-samples/tutorial.reading-time/scripts/content.js

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,12 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15-
const article = document.querySelector('article');
15+
function renderReadingTime(article) {
16+
// If we weren't provided an article, we don't need to render anything.
17+
if (!article) {
18+
return;
19+
}
1620

17-
// `document.querySelector` may return null if the selector doesn't match anything.
18-
if (article) {
1921
const text = article.textContent;
2022
/**
2123
* Regular expression to find all "words" in a string.
@@ -45,3 +47,25 @@ if (article) {
4547
// https://developer.mozilla.org/en-US/docs/Web/API/Element/insertAdjacentElement
4648
(date ?? heading).insertAdjacentElement('afterend', badge);
4749
}
50+
51+
renderReadingTime(document.querySelector('article'));
52+
53+
const observer = new MutationObserver((mutations) => {
54+
for (const mutation of mutations) {
55+
// If a new article was added.
56+
for (const node of mutation.addedNodes) {
57+
if (node instanceof Element && node.tagName === 'ARTICLE') {
58+
// Render the reading time for this particular article.
59+
renderReadingTime(node);
60+
}
61+
}
62+
}
63+
});
64+
65+
// https://developer.chrome.com/ is a SPA (Single Page Application) so can
66+
// update the address bar and render new content without reloading. Our content
67+
// script won't be reinjected when this happens, so we need to watch for
68+
// changes to the content.
69+
observer.observe(document.querySelector('devsite-content'), {
70+
childList: true
71+
});

0 commit comments

Comments
 (0)