我正在尝试编写接受用户选择的字词和用户定义的Google Chrome扩展程序 网站并在该网站上搜索此单词(通过Google和上下文菜单)。选项页面中有一个表单。 用户在表单字段中输入网站(用户指定的字段/网站数量可变 哪些网站,因此有多少)。所有网站都保存到阵列。数组保存到localStorage [“arr”]。所有这些都在options.html中。
关于bg.html(背景页面) 首先,我从localStorage获取数组(现在一切都很好)。然后我在循环中创建contextmenu项。对于所有contextmenu项,我只有一个onclick事件处理程序。 在事件处理程序内部,我正在尝试获取正确的数组元素(在哪个站点上搜索) 和selectontext(搜索内容),然后用谷歌搜索结果打开一个新选项卡 我最大的问题: 1)我根本无法得到数组元素(在事件处理程序中)!!(在哪个网站上搜索是未定义的)。 2)onclick事件仅适用于上下文菜单项之一。 3)有时,创建了contextmenu项,但点击根本不起作用!!
我的代码: 的manifest.json
{
"name": "Context Site Search",
"version" : "0.0.0.1",
"background_page" : "bg.html",
"options_page": "options.html",
"permissions" : [
"tabs",
"contextMenus",
"http://www.google.com"
]
}
bg.html:
<script type="text/javascript">
var ar = localStorage.getItem("arr").split(",");//getting array from localStorage
for (var i=0;i<ar.length;i++){ // creating contextmenu items in a loop
chrome.contextMenus.create({
"title": "find ' %s' в "+ ar[i],
"contexts": [ "selection"],
"onclick" : clickhandler
});
}
var clickhandler = function(e,ar){
var baseUrl = "http://www.google.com/search?q=site%3A";
if (e.selectionText){
baseUrl += ar[i]+ "&q="+ encodeURI(e.selectionText);
chrome.tabs.create(
{"url": baseUrl}
);
}
}
</script>
请帮忙!我究竟做错了什么??怎么解决这个? 任何帮助表示赞赏。
提前致谢!!
更新:感谢serg,我终于得到了一些东西......但是有一些新问题: 1)在选项页面输入的上下文菜单数量神秘地翻倍(甚至五倍!!)。 2)单击保存按钮不会立即用新的菜单替换旧的菜单项。(重新加载 显然需要扩展)。 我怀疑,我错误地写了保存功能,保存按钮单击运行... 这是代码:
var arr = [];
function save() {
localStorage.clear();
var nodes = document.querySelectorAll("input[type=text]");
for (var i=0; i<nodes.length; i++){
if (nodes[i].value == "" ){
alert('Enter Data!');return false;
} else {
arr.push( nodes[i].value);
}}
localStorage['arr'] = JSON.stringify(arr);
}
</script>
UPDATE2:
我想出了加倍/五倍的事情。这取决于用户点击保存按钮的次数。 1)有机会阻止这个吗?例如多次点击只为数组添加一组值? 2)Contextmenu项目仍然没有变化。它们只在重新加载扩展后改变.. :(( 重新加载扩展和更改localStorage有什么区别??
答案 0 :(得分:1)
将功能分配给onclick
属性时,不会立即对其进行评估。在评估时,您的循环很久以前就会结束,ar[i]
不包含您的期望。
这是一个经典的javascript问题,它通过闭包来解决:
chrome.contextMenus.create({
"title": "find ' %s' в "+ ar[i],
"contexts": [ "selection"],
"onclick" : (function(element) {
return function(info, tab) {
var baseUrl = "http://www.google.com/search?q=site%3A";
if (info.selectionText) {
baseUrl += element + "&q="+ encodeURI(info.selectionText);
chrome.tabs.create({"url": baseUrl});
}
}
})(ar[i])
});
我们创建了一个匿名函数,它立即被评估并返回一个真实的事件处理程序。诀窍是,当前ar[i]
值现在始终可用作闭包内的element
变量。
答案 1 :(得分:0)
var ar = JSON.parse(localStorage.getItem("arr")); // you should also use JSON.stringify to store the array
var menuitems = []; // array to hold menu item ID's and sites
for (i in ar)
{
menuitem = chrome.contextMenus.create({
"title": "find ' %s' в " + ar[i],
"contexts": ["selection"],
"onclick": function(e)
{
var baseUrl = "http://www.google.com/search?q=site%3A";
if (e.selectionText)
{
baseUrl += encodeURIComponent(menuitems[e.menuItemId]) + "&q=" + encodeURIComponent(e.selectionText);
chrome.tabs.create({ "url": baseUrl });
}
}
});
menuitems[menuitem] = ar[i]; // store the ID of the current menuitem with the site
}
经过测试,这应该可以解决问题。注意我还添加了一些改进,比如使用for (.. in ..)
作为循环,encodeURIComponent
表示URL参数(encodeURI
表示完整的URL,encodeURIComponent
表示URI组件,即参数)。此外,使用JSON在localStorage
中存储数据。
我认为你做错了是你在创建菜单项后定义了clickHandler
。创建菜单项时,clickHandler
为空,单击它时没有任何反应。我通过简单地在菜单项创建中定义内联函数来解决这个问题。