выбор и поиск по сайту в расширении chrome - PullRequest
1 голос
/ 06 апреля 2011

Я пытаюсь написать расширение Google Chrome, которое принимает выбранное пользователем слово и определяемое пользователем веб-сайт и ищет это слово на этом сайте (через Google и contextmenu). На странице настроек есть форма. Пользователь вводит сайты в поля формы (есть переменное количество полей / сайтов - пользователь указывает какие сайты и, следовательно, сколько). Все сайты сохраняются в массиве. массив сохраняется в localStorage ["arr"]. все это было в options.html.

На bg.html (Фоновая страница) во-первых, я получаю массив из localStorage (сейчас все в порядке). Затем я создаю элементы contextmenu в цикле. У меня есть ТОЛЬКО ОДИН обработчик события onclick для всех элементов контекстного меню. Внутри обработчика событий я пытаюсь получить правильный элемент массива (на каком сайте искать) и выберите текст (что искать), а затем откройте новую вкладку с результатами поиска Google.
Мои самые большие проблемы: 1) я не могу получить элемент массива (в обработчике событий) вообще !! (на каком сайте поиск не определен). 2) событие onclick работает только для одного из пунктов контекстного меню. 3) иногда создаются элементы контекстного меню, но нажатие вообще не работает !!

Мой код: 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>

Пожалуйста, помогите! Что я делаю неправильно?? как это исправить ?? Любая помощь приветствуется.

Спасибо заранее !!

ОБНОВЛЕНИЕ: Благодаря Сергу, я наконец-то что-то получаю ... но есть новые проблемы: 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) Элементы контекстного меню по-прежнему не меняются. они меняются ТОЛЬКО ПОСЛЕ перезагрузки расширения ..: (( В чем разница между перезагрузкой расширения и изменением localStorage ??

Ответы [ 2 ]

1 голос
/ 06 апреля 2011

Когда вы назначаете функцию свойству 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 внутри замыкания.

0 голосов
/ 06 апреля 2011
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 имеет значение null, и при нажатии ничего не происходит.Я исправил это, просто определив встроенную функцию при создании пункта меню.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...