完全迷失了如何保存扩展弹出 window 内容
Completely lost on how to save extension popup window content
我对如何使弹出窗口 window 的添加内容在每次打开新的 link 或单击它 "away" 时都不会消失感到非常困惑。我读过有关内容脚本、背景脚本等的内容,但老实说我不知道如何将其实现到我自己的源代码中。下面是我的 popup.html, popup.js 和我的 manifest.js 文件。
{
"manifest_version": 2,
"name": "URL_save",
"description": "This extension saves an URL and renames the title to the user's wishes and hyperlink the title.",
"version": "0.1",
"browser_action": {
"default_icon": "/img/icon.png",
"default_popup": "popup.html",
"default_title": "See your saved websites!"
},
"permissions": [
"tabs"
]
}
弹出html:
<html>
<head>
<title>Your articles</title>
<link href="/css/style.css" rel="stylesheet"/>
<script src="/js/underscore-min.js"></script>
<script src="/js/popup.js"></script>
</head>
<body>
<div id="div">No content yet! Click the button to add the link of the current website!</div>
<div><ul id="list"></ul></div>
<br/>
<button id="button">Add link!</button>
</body>
</html>
popup.js:
// global variables
var url;
// event listener for the button inside popup window
document.addEventListener('DOMContentLoaded', function() {
var button = document.getElementById('button');
button.addEventListener('click', function() {
addLink();
});
});
// fetch the URL of the current tab, add inside the window
function addLink() {
// store info in the the queryInfo object as per:
// https://developer.chrome.com/extensions/tabs#method-query
var queryInfo = {
currentWindow: true,
active: true
};
chrome.tabs.query(queryInfo, function(tabs) {
// tabs is an array so fetch the first (and only) object-elemnt in tab
// put URL propery of tab in another variable as per:
// https://developer.chrome.com/extensions/tabs#type-Tab
url = tabs[0].url;
// format html
var html = '<li><a href=' + url + " target='_blank'>" + url + '</a><br/></li>';
// change the text message
document.getElementById("div").innerHTML = "<h2>Saved pages</h2>";
// get to unordered list and create space for new list item
var list = document.getElementById("list");
var newcontent = document.createElement('LI');
newcontent.innerHTML = html;
// while loop to remember previous content and append the new ones
while (newcontent.firstChild) {
list.appendChild(newcontent.firstChild);
}
});
}
在此图像中,您可以看到当我首先添加 link 但随后关闭(仅)弹出窗口 window,然后再次打开它时发生的情况:
添加当前URL后:
关闭并重新打开弹出窗口后:
弹出窗口会在每次 closed/reopened 时重新加载其文档。相反,您应该使用背景页面来保存状态。
执行此操作的一般方法是:
- 从弹出窗口到后台进行通信以执行某些操作。即:执行 ajax 请求并将结果存储在普通 javascript 对象中。
- 从后台页面执行一次获取,以获取 javascript 对象。即使您关闭弹出窗口,状态也会保留在后台页面中。
与网页类似,弹出窗口(或 options/settings 页面的)范围在显示时创建,在不再可见时销毁。这意味着在显示的时间之间弹出窗口本身没有存储任何状态。在弹出窗口被销毁后,您希望保留的任何信息都需要存储在其他地方。因此,您将需要使用 JavaScript 来存储您希望在下次打开弹出窗口时保持相同的任何状态。每次打开弹出窗口时,您都需要检索该信息并将其恢复到 DOM。最常用的两个地方是StorageAreaMDN,或者后台页面
存储信息的位置取决于您希望存储的数据保留多长时间,以及希望数据在何处显示。
您可以存储数据的一般位置包括(存在其他可能性,但以下是最常见的):
- 如果您希望数据仅在 Chrome 关闭之前存在,则为后台页面。 Chrome 重启后就不存在了。您可以通过couple/few种不同的方法将数据发送到后台页面,包括message passingMDN, or directly changing values on the background pageMDN。存储在StorageArea(下面两个选项)中的数据也可用于后台页面和内容脚本。
chrome.storage.local
MDN 如果您希望数据在 Chrome 关闭和重新启动后保留在本地计算机上。
chrome.storage.sync
MDN 如果您希望与使用当前 Chrome Chrome 的所有实例共享数据=119=]。数据也将持续存在直到更改。关闭并重新启动 Chrome 后即可使用。它将在使用相同配置文件的其他机器上可用。
window.localStorage
:在 chrome.storage
存在之前,将扩展数据存储在 window.localStorage
中很流行。虽然这仍然有效,但通常首选使用 chrome.storage
.
使用 chrome.storage
StorageAreaMDN 的优点之一是数据可直接用于扩展的所有部分,无需通过数据作为消息。1
您当前的代码
目前您的代码不存储在弹出窗口 DOM 以外的任何地方输入的 URL。您将需要建立一个数据结构(例如数组)来存储 URL 的列表。然后可以将此数据存储到上述存储位置之一。
Google 在 Options documentation page2, MDN 上的示例显示存储 chrome.storage.sync
并将值恢复到 DOM 时选项页面显示。此示例中使用的代码可以用于选项页面,只需将其 HTML 页面定义为 default_popup
用于 browser_action
,就可以像弹出窗口一样工作。还有许多其他示例可用。
不幸的是,如果您没有更具体地说明您想要什么,很难给您具体的代码。但是,关于您需要去的方向的一些建议是:
- 重构你的代码,这样你就有了一个单独的函数,你用 URL 作为参数调用,只是 将这个 URL 添加到列表中在 DOM 中有(例如
addUrlToDom(url)
)。当用户添加 URL 和当页面加载时恢复 URL 时将使用此函数。
将您的 URL 列表存储在数组中(例如 urlList
)。该数组将是您保存到弹出窗口之外的存储位置的内容。您将从 DOMContentLoaded
处理程序中的存储位置读取此数组,并使用重构的 addUrlToDom()
函数添加每个值。将其恢复到 DOM 中可能类似于:
urlList.forEach(function(url){
addUrlToDom(url);
});
将您的数据存储在 chrome.storage.local
假设您想要将 URLs 存储在 Chrome shutdown/restart 的本地计算机上(即使用 chrome.storage.local
),您的代码可能类似于:
manifest.json 仅更改为 permissions
:
"permissions": [
"tabs",
"storage"
]
popup.js:
// global variables
var urlList=[];
document.addEventListener('DOMContentLoaded', function() {
getUrlListAndRestoreInDom();
// event listener for the button inside popup window
document.getElementById('button').addEventListener('click', addLink);
});
// fetch the URL of the current tab, add inside the window
function addLink() {
chrome.tabs.query({currentWindow: true,active: true}, function(tabs) {
// tabs is an array so fetch the first (and only) object-element in tab
var url = tabs[0].url;
if(urlList.indexOf(url) === -1){
//Don't add duplicates
addUrlToListAndSave(url);
addUrlToDom(url);
}
});
}
function getUrlListAndRestoreInDom(){
chrome.storage.local.get({urlList:[]},function(data){
urlList = data.urlList;
urlList.forEach(function(url){
addUrlToDom(url);
});
});
}
function addUrlToDom(url){
// change the text message
document.getElementById("div").innerHTML = "<h2>Saved pages</h2>";
//Inserting HTML text here is a bad idea, as it has potential security holes when
// including content not sourced entirely from within your extension (e.g. url).
// Inserting HTML text is fine if it is _entirely_ sourced from within your
// extension.
/*
// format HTML
var html = '<li><a href=' + url + " target='_blank'>" + url + '</a></li>';
//Add URL to DOM
document.getElementById("list").insertAdjacentHTML('beforeend',html);
*/
//Build the new DOM elements programatically instead:
var newLine = document.createElement('li');
var newLink = document.createElement('a');
newLink.textContent = url;
newLink.setAttribute('href',url);
newLink.setAttribute('target','_blank');
newLine.appendChild(newLink);
document.getElementById("list").appendChild(newLine);
}
function addUrlToListAndSave(url){
if(urlList.indexOf(url) === -1){
//URL is not already in list
urlList.push(url);
saveUrlList();
}
}
function saveUrlList(callback){
chrome.storage.local.set({urlList},function(){
if(typeof callback === 'function'){
//If there was no callback provided, don't try to call it.
callback();
}
});
}
- 插入到页面上下文中的脚本除外。页面上下文是您可能不会 运行 脚本的内容。为此,您必须使用内容脚本(您的 StorageAreaMDN 数据直接可用) 将
<script>
标记插入网页的 DOM 中。这可能有点复杂,您可能不需要担心。这里提到它仅仅是因为 StorageAreaMDN 数据可用于扩展的所有区域的声明可能存在例外。
- Chrome 文档中的示例在 Firefox 上运行良好。是的,Firefox supports both
chrome.*
, using callbacks, and browser.*
, using promises.
我对如何使弹出窗口 window 的添加内容在每次打开新的 link 或单击它 "away" 时都不会消失感到非常困惑。我读过有关内容脚本、背景脚本等的内容,但老实说我不知道如何将其实现到我自己的源代码中。下面是我的 popup.html, popup.js 和我的 manifest.js 文件。
{
"manifest_version": 2,
"name": "URL_save",
"description": "This extension saves an URL and renames the title to the user's wishes and hyperlink the title.",
"version": "0.1",
"browser_action": {
"default_icon": "/img/icon.png",
"default_popup": "popup.html",
"default_title": "See your saved websites!"
},
"permissions": [
"tabs"
]
}
弹出html:
<html>
<head>
<title>Your articles</title>
<link href="/css/style.css" rel="stylesheet"/>
<script src="/js/underscore-min.js"></script>
<script src="/js/popup.js"></script>
</head>
<body>
<div id="div">No content yet! Click the button to add the link of the current website!</div>
<div><ul id="list"></ul></div>
<br/>
<button id="button">Add link!</button>
</body>
</html>
popup.js:
// global variables
var url;
// event listener for the button inside popup window
document.addEventListener('DOMContentLoaded', function() {
var button = document.getElementById('button');
button.addEventListener('click', function() {
addLink();
});
});
// fetch the URL of the current tab, add inside the window
function addLink() {
// store info in the the queryInfo object as per:
// https://developer.chrome.com/extensions/tabs#method-query
var queryInfo = {
currentWindow: true,
active: true
};
chrome.tabs.query(queryInfo, function(tabs) {
// tabs is an array so fetch the first (and only) object-elemnt in tab
// put URL propery of tab in another variable as per:
// https://developer.chrome.com/extensions/tabs#type-Tab
url = tabs[0].url;
// format html
var html = '<li><a href=' + url + " target='_blank'>" + url + '</a><br/></li>';
// change the text message
document.getElementById("div").innerHTML = "<h2>Saved pages</h2>";
// get to unordered list and create space for new list item
var list = document.getElementById("list");
var newcontent = document.createElement('LI');
newcontent.innerHTML = html;
// while loop to remember previous content and append the new ones
while (newcontent.firstChild) {
list.appendChild(newcontent.firstChild);
}
});
}
在此图像中,您可以看到当我首先添加 link 但随后关闭(仅)弹出窗口 window,然后再次打开它时发生的情况:
添加当前URL后:
关闭并重新打开弹出窗口后:
弹出窗口会在每次 closed/reopened 时重新加载其文档。相反,您应该使用背景页面来保存状态。
执行此操作的一般方法是:
- 从弹出窗口到后台进行通信以执行某些操作。即:执行 ajax 请求并将结果存储在普通 javascript 对象中。
- 从后台页面执行一次获取,以获取 javascript 对象。即使您关闭弹出窗口,状态也会保留在后台页面中。
与网页类似,弹出窗口(或 options/settings 页面的)范围在显示时创建,在不再可见时销毁。这意味着在显示的时间之间弹出窗口本身没有存储任何状态。在弹出窗口被销毁后,您希望保留的任何信息都需要存储在其他地方。因此,您将需要使用 JavaScript 来存储您希望在下次打开弹出窗口时保持相同的任何状态。每次打开弹出窗口时,您都需要检索该信息并将其恢复到 DOM。最常用的两个地方是StorageAreaMDN,或者后台页面
存储信息的位置取决于您希望存储的数据保留多长时间,以及希望数据在何处显示。
您可以存储数据的一般位置包括(存在其他可能性,但以下是最常见的):
- 如果您希望数据仅在 Chrome 关闭之前存在,则为后台页面。 Chrome 重启后就不存在了。您可以通过couple/few种不同的方法将数据发送到后台页面,包括message passingMDN, or directly changing values on the background pageMDN。存储在StorageArea(下面两个选项)中的数据也可用于后台页面和内容脚本。
chrome.storage.local
MDN 如果您希望数据在 Chrome 关闭和重新启动后保留在本地计算机上。chrome.storage.sync
MDN 如果您希望与使用当前 Chrome Chrome 的所有实例共享数据=119=]。数据也将持续存在直到更改。关闭并重新启动 Chrome 后即可使用。它将在使用相同配置文件的其他机器上可用。window.localStorage
:在chrome.storage
存在之前,将扩展数据存储在window.localStorage
中很流行。虽然这仍然有效,但通常首选使用chrome.storage
.
使用 chrome.storage
StorageAreaMDN 的优点之一是数据可直接用于扩展的所有部分,无需通过数据作为消息。1
您当前的代码
目前您的代码不存储在弹出窗口 DOM 以外的任何地方输入的 URL。您将需要建立一个数据结构(例如数组)来存储 URL 的列表。然后可以将此数据存储到上述存储位置之一。
Google 在 Options documentation page2, MDN 上的示例显示存储 chrome.storage.sync
并将值恢复到 DOM 时选项页面显示。此示例中使用的代码可以用于选项页面,只需将其 HTML 页面定义为 default_popup
用于 browser_action
,就可以像弹出窗口一样工作。还有许多其他示例可用。
不幸的是,如果您没有更具体地说明您想要什么,很难给您具体的代码。但是,关于您需要去的方向的一些建议是:
- 重构你的代码,这样你就有了一个单独的函数,你用 URL 作为参数调用,只是 将这个 URL 添加到列表中在 DOM 中有(例如
addUrlToDom(url)
)。当用户添加 URL 和当页面加载时恢复 URL 时将使用此函数。 将您的 URL 列表存储在数组中(例如
urlList
)。该数组将是您保存到弹出窗口之外的存储位置的内容。您将从DOMContentLoaded
处理程序中的存储位置读取此数组,并使用重构的addUrlToDom()
函数添加每个值。将其恢复到 DOM 中可能类似于:urlList.forEach(function(url){ addUrlToDom(url); });
将您的数据存储在 chrome.storage.local
假设您想要将 URLs 存储在 Chrome shutdown/restart 的本地计算机上(即使用 chrome.storage.local
),您的代码可能类似于:
manifest.json 仅更改为 permissions
:
"permissions": [
"tabs",
"storage"
]
popup.js:
// global variables
var urlList=[];
document.addEventListener('DOMContentLoaded', function() {
getUrlListAndRestoreInDom();
// event listener for the button inside popup window
document.getElementById('button').addEventListener('click', addLink);
});
// fetch the URL of the current tab, add inside the window
function addLink() {
chrome.tabs.query({currentWindow: true,active: true}, function(tabs) {
// tabs is an array so fetch the first (and only) object-element in tab
var url = tabs[0].url;
if(urlList.indexOf(url) === -1){
//Don't add duplicates
addUrlToListAndSave(url);
addUrlToDom(url);
}
});
}
function getUrlListAndRestoreInDom(){
chrome.storage.local.get({urlList:[]},function(data){
urlList = data.urlList;
urlList.forEach(function(url){
addUrlToDom(url);
});
});
}
function addUrlToDom(url){
// change the text message
document.getElementById("div").innerHTML = "<h2>Saved pages</h2>";
//Inserting HTML text here is a bad idea, as it has potential security holes when
// including content not sourced entirely from within your extension (e.g. url).
// Inserting HTML text is fine if it is _entirely_ sourced from within your
// extension.
/*
// format HTML
var html = '<li><a href=' + url + " target='_blank'>" + url + '</a></li>';
//Add URL to DOM
document.getElementById("list").insertAdjacentHTML('beforeend',html);
*/
//Build the new DOM elements programatically instead:
var newLine = document.createElement('li');
var newLink = document.createElement('a');
newLink.textContent = url;
newLink.setAttribute('href',url);
newLink.setAttribute('target','_blank');
newLine.appendChild(newLink);
document.getElementById("list").appendChild(newLine);
}
function addUrlToListAndSave(url){
if(urlList.indexOf(url) === -1){
//URL is not already in list
urlList.push(url);
saveUrlList();
}
}
function saveUrlList(callback){
chrome.storage.local.set({urlList},function(){
if(typeof callback === 'function'){
//If there was no callback provided, don't try to call it.
callback();
}
});
}
- 插入到页面上下文中的脚本除外。页面上下文是您可能不会 运行 脚本的内容。为此,您必须使用内容脚本(您的 StorageAreaMDN 数据直接可用) 将
<script>
标记插入网页的 DOM 中。这可能有点复杂,您可能不需要担心。这里提到它仅仅是因为 StorageAreaMDN 数据可用于扩展的所有区域的声明可能存在例外。 - Chrome 文档中的示例在 Firefox 上运行良好。是的,Firefox supports both
chrome.*
, using callbacks, andbrowser.*
, using promises.