![](/img/trans.png)
[英]How do I run Chrome extension content script after a site's javascript has finished building page?
[英]How do I write a chrome extension that applies a content script to a Single Page Application?
我目前正在編寫一個擴展程序,該擴展程序會將與 RegEx 模式(特別是德國電話號碼的 RegEx 模式)匹配的每個字符串轉換為可點擊的鏈接,方法是在元素的 href 中添加 tel: 並用如果需要,錨標記。
在過去的三天里,我一直在努力使其適用於我們公司用於聯系人的這個單頁應用程序。 但是每當我將擴展程序加載到瀏覽器然后重新啟動瀏覽器時,它首先不會應用我的內容腳本。 我首先需要在訪問后刷新頁面。
我正在使用以下文件:
清單.json:
{
"name": "testExtension",
"short_name": "testExtension",
"version": "1.0.0",
"manifest_version": 2,
"description": "Replace telephone numbers with clickable links.",
"author": "Ngelus",
"icons": {
"16": "icons/icon16.png",
"48": "icons/icon48.png",
"128": "icons/icon128.png"
},
"browser_action": {
"default_icon": "icons/icon48.png",
"default_title": "testExtension"
},
"default_locale": "en",
"permissions": [
"tabs",
"activeTab",
"<all_urls>",
"*://*.examplecontactsapp.de/*",
"storage",
"webRequest",
"webNavigation"
],
"content_scripts": [
{
"matches": [
"*://web.examplecontactsapp.de/contacts",
"*://web.examplecontactsapp.de/contacts*"
],
"js": ["src/inject/contentscript.js"]
}
],
"background": {
"scripts": ["src/bg/background.js"],
"persistent": true
}
}
背景.js:
let currentUrl = '';
let tabId;
chrome.webRequest.onCompleted.addListener(
function (details) {
const parsedUrl = new URL(details.url);
if (currentUrl && currentUrl.indexOf(parsedUrl.pathname) > -1 && tabId) {
chrome.tabs.sendMessage(tabId, { type: "pageRendered" });
}
},
{ urls: ['*://web.examplecontactsapp.de/contacts*'] }
);
chrome.webNavigation.onHistoryStateUpdated.addListener(
(details) => {
tabId = details.tabId;
currentUrl = details.url;
},
{
url: [
{
hostSuffix: 'examplecontactsapp.de',
},
],
}
);
內容腳本.js:
var readyStateCheckInterval = setInterval(function () {
if (!location.href.startsWith('https://web.examplecontactsapp.de/contacts')) return;
if (document.readyState === 'complete') {
clearInterval(readyStateCheckInterval);
console.log(
`[---testExtension---]: replacing all telephone numbers with clickable links...`
);
replaceNumbersWithLinks();
}
}, 10);
chrome.runtime.onMessage.addListener(function (request) {
if (request && request.type === 'pageRendered') {
const readyStateCheckInterval = setInterval(function () {
if (document.readyState === 'complete') {
clearInterval(readyStateCheckInterval);
console.log(
`[---testExtension---]: replacing all telephone numbers with clickable links...`
);
replaceNumbersWithLinks();
}
}, 10);
}
});
function replaceNumbersWithLinks() {
document
.querySelectorAll(
'body > main > div.page-content > div > table > tbody > tr > td > p > a'
)
.forEach((a) => {
var b = a.innerText.replaceAll(' ', '').trim();
a.removeAttribute('data-phonenumber');
if (b != '') a.href = 'tel:' + b;
});
}
這樣做的正確方法是什么? 每當我訪問該單頁應用程序時,如何使其工作?
謝謝大家。
使matches
匹配 manifest.json 中的整個站點:
{
"content_scripts": [
{
"matches": [
"*://web.examplecontactsapp.de/*"
],
"js": ["src/inject/contentscript.js"]
}
],
使用 MutationObserver 並使用中等速度的 querySelector 檢查 contentscript.js 中每個突變上的選擇器,然后在成功時繼續執行慢速 querySelectorAll:
const SEL = 'a[data-phonenumber]';
const mo = new MutationObserver(onMutation);
observe();
function onMutation() {
if (document.querySelector(SEL)) {
mo.disconnect();
replaceNumbersWithLinks();
observe();
}
}
function observe() {
mo.observe(document, {
subtree: true,
childList: true,
});
}
function replaceNumbersWithLinks() {
document.querySelectorAll(SEL).forEach((a) => {
a.removeAttribute('data-phonenumber');
const b = a.textContent.replaceAll(' ', '').trim();
if (b) a.href = 'tel:' + b;
});
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.