【发布时间】:2016-03-31 18:35:06
【问题描述】:
我正在构建一个 Chrome 扩展程序。我试图让我的应用程序与扩展程序中的每个页面以及用户在浏览器中查看的页面进行通信。我需要从扩展访问 dom,然后更新它。
manifest.json
popup.html
popup.js
background.js
content.js
以及用户正在查看的当前页面。
我的目标是在页面加载时修改 dom 并在用户看到页面之前向他们展示新版本的页面。
在popup.js 中,用户可以在弹出窗口中输入关键字。关键字被保存到localStorage,当他们查看网络时,如果在他们正在查看的任何页面上找到关键字的父 div,则通过隐藏关键字的父 div 将关键字从他们的视图中删除。
我需要帮助让每个页面进行通信,我认为我在 popup.js 中隐藏父 div 的方式行不通。我对如何从前面对 dom 执行操作感到困惑。
将 dom 发送到 background.js 在页面上查找关键字并将其父 div 更改为隐藏。 将 dom 推回查看页面。
我认为这行是说如果我匹配任何 url 然后运行我的应用程序,但我不确定。
"matches": ["*://*/*"],
我的 manifest.json
{
"name": "Wuno Zensoring",
"version" : "1.0",
"permissions": [
"activeTab",
"tabs",
"storage"
],
"description": "This extension will search the document file for keywords and hide their parent div.",
"icons": {
"19": "icon19.png",
"38": "icon38.png",
"48": "icon48.png",
"128": "icon128.png"
},
"background": {
"persistent": false,
"scripts": ["jquery-1.11.3.min.js","background.js"]
},
"content_scripts": [{
"matches": ["*://*/*"],
"js": ["content.js"],
"run_at": "document_end",
"all_frames": true
}],
"web_accessible_resources": [
"popup.js", "content.js"
],
"browser_action": {
"default_icon": "icon.png128",
"default_popup": "popup.html",
"default_icon": {
"19": "icon19.png",
"38": "icon38.png",
"48": "icon48.png",
"128": "icon128.png"
}
},
"manifest_version": 2
}
popup.html
<!doctype html>
<html>
<head>
<title>Wuno Zensorship</title>
<script src="jquery-1.11.3.min.js"></script>
<script src="popup.js"></script>
<link rel="stylesheet" type="text/css" href="styles.css">
</head>
<body>
<img src="icon48.png">
<section>
<form id="form" action="#" method="POST">
<input id="description" name="description" type="text" />
<input id="add" type="submit" value="Add" />
<button id="clearChecked">Clear Checked Items</button>
<button id="clear">Clear All</button>
</form>
<div id="alert"></div>
<ul id="keyWords"></ul>
</body>
</html>
popup.js
$(document).ready(function () {
localArray = [];
if (!localStorage.keyWords) {
localStorage.setItem('keyWords', JSON.stringify(localArray));
}
loadKeyWords();
function loadKeyWords() {
$('#keyWords').html('');
localArray = JSON.parse(localStorage.getItem('keyWords'));
for(var i = 0; i < localArray.length; i++) {
$('#keyWords').prepend('<li><input class="check" name="check" type="checkbox">'+localArray[i]+'</li>');
}
}
$('#add').click( function() {
var Description = $('#description').val();
if($("#description").val() === '') {
$('#alert').html("<strong>Warning!</strong> You left the to-do empty");
$('#alert').fadeIn().delay(1000).fadeOut();
return false;
}
$('#form')[0].reset();
var keyWords = $('#keyWords').html();
localArray.push(Description);
localStorage.setItem('keyWords', JSON.stringify(localArray));
loadKeyWords();
return false;
});
$('#clear').click( function() {
window.localStorage.clear();
location.reload();
return false;
});
$('#clearChecked').click(function() {
currentArray = [];
$('.check').each(function() {
var $curr = $(this);
if (!$curr.is(':checked')) {
var value = $curr.parent().text();
currentArray.push(value);
localStorage.setItem('keyWords', JSON.stringify(currentArray));
loadKeyWords();
} else {
$curr.parent().remove();
}
});
});
// Update the relevant fields with the new data
function setDOMInfo(info) {
$("div p:contains(localStorage.getItem('keyWords')).parent('div').hide()");
}
// Once the DOM is ready...
window.addEventListener('DOMContentLoaded', function () {
// ...query for the active tab...
chrome.tabs.query({
active: true,
currentWindow: true
}, function (tabs) {
// ...and send a request for the DOM info...
chrome.tabs.sendMessage(
tabs[0].id,
{from: 'popup', subject: 'DOMInfo'},
// ...also specifying a callback to be called
// from the receiving end (content script)
setDOMInfo);
});
});
}); // End of document ready function
background.js
chrome.runtime.onMessage.addListener(function (msg, sender) {
// First, validate the message's structure
if ((msg.from === 'content') && (msg.subject === 'showPageAction')) {
// Enable the page-action for the requesting tab
chrome.pageAction.show(sender.tab.id);
}
});
content.js
// Inform the background page that
// this tab should have a page-action
chrome.runtime.sendMessage({
from: 'content',
subject: 'showPageAction'
});
// Listen for messages from the popup
chrome.runtime.onMessage.addListener(function (msg, sender, response) {
// First, validate the message's structure
if ((msg.from === 'popup') && (msg.subject === 'DOMInfo')) {
// Collect the necessary data
// (For your specific requirements `document.querySelectorAll(...)`
// should be equivalent to jquery's `$(...)`)
var domInfo = {
total: document.querySelectorAll('*').length,
inputs: document.querySelectorAll('input').length,
buttons: document.querySelectorAll('button').length
};
// Directly respond to the sender (popup),
// through the specified callback */
response(domInfo);
}
});
【问题讨论】:
-
在不查看整个代码的情况下,在后台页面中创建一个新的 DOM 并将其发送到内容脚本 not 听起来是个不错的计划 :) 它会破坏大多数页。 DOM 操作应该发生在适当的位置(例如,通过将具有必要逻辑的脚本注入页面)。
-
只需将 DOM 操作逻辑放在内容脚本中并将关键字发送给它(而不是发送 HTML,在后台或弹出页面中过滤并发送回内容脚本)。
-
不能完全解决你的问题,但我建议你看看这个解决方案来搜索文本容器stackoverflow.com/a/18089011/1705006。搜索直接父节点比 div 节点更高效、更符合逻辑。
标签: javascript jquery google-chrome google-chrome-extension