Невозможно добавить элемент в popup.html для chrome plugin [duplicate]

Многие объяснения уже присутствуют, чтобы объяснить, как это происходит и как это исправить, но вы также должны следовать рекомендациям, чтобы избежать NullPointerException вообще.

См. также: A хороший список лучших практик

Я бы добавил, очень важно, хорошо использовать модификатор final. Использование "окончательной" модификатор, когда это применимо в Java

Сводка:

  1. Используйте модификатор final для обеспечения хорошей инициализации.
  2. Избегайте возврата null в методы, например, при возврате пустых коллекций.
  3. Использовать аннотации @NotNull и @Nullable
  4. Быстрое завершение работы и использование утверждений, чтобы избежать распространения нулевых объектов через все приложение, когда они не должен быть пустым.
  5. Сначала используйте значения с известным объектом: if("knownObject".equals(unknownObject)
  6. Предпочитают valueOf() поверх toString ().
  7. Используйте null safe StringUtils StringUtils.isEmpty(null).

66
задан Sumair Baloch 16 November 2013 в 17:10
поделиться

2 ответа

Хотя вы определенно находитесь в правильном направлении (и на самом деле довольно близки к концу), в вашем коде существует несколько (imo) плохих практик (например, для инъекции целой библиотеки (jquery) для такой тривиальной задачи, объявления ненужных разрешений , делая суперплошные вызовы API-методам и т. д.). Я сам не тестировал ваш код, но из краткого обзора считаю, что исправление следующего может привести к рабочему решению (хотя и не очень близкому к оптимальному):

  1. В manifest.json: Изменить порядок скриптов содержимого, сначала добавив jquery. Согласно соответствующие документы : «js» [...] Список файлов JavaScript, которые будут вставляться в соответствующие страницы. Они вводятся в порядке их появления в этом массиве. (emphasis mine)
  2. В contentscript.js: Переместите блок chrome.runtime.sendMessage ({...}) внутри обратного вызова слушателя onMessage.

Итак, вот мой предложенный подход:

Управляющий поток:

  1. Скрипт содержимого вводится в каждый страница, соответствующая некоторым критериям.
  2. После ввода скрипты содержимого отправляют сообщение на страницу событий (непостоянная фоновая страница), а страница событий присоединяет к странице вкладку = действие.
  3. Как только всплывающее окно с действием страницы загружается, оно отправляет сообщение в скрипт контента, запрашивая информацию, в которой она нуждается.
  4. Скрипт контента обрабатывает запрос и отвечает так, чтобы действие страницы popup может отображать информацию.

Структура каталогов:

          root-directory/
           |_____img
                 |_____icon19.png
                 |_____icon38.png
           |_____manifest.json
           |_____background.js
           |_____content.js
           |_____popup.js
           |_____popup.html

manifest.json:

{
  "manifest_version": 2,
  "name":    "Test Extension",
  "version": "0.0",
  "offline_enabled": true,

  "background": {
    "persistent": false,
    "scripts": ["background.js"]
  },

  "content_scripts": [{
    "matches":    ["*://*.stackoverflow.com/*"],
    "js":         ["content.js"],
    "run_at":     "document_idle",
    "all_frames": false
  }],

  "page_action": {
    "default_title": "Test Extension",
    //"default_icon": {
    //    "19": "img/icon19.png",
    //    "38": "img/icon38.png"
    //},
    "default_popup": "popup.html"
  }

  // No special permissions required...
  //"permissions": []
}

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);
  }
});

popup.js:

// Update the relevant fields with the new data
function setDOMInfo(info) {
  document.getElementById('total').textContent   = info.total;
  document.getElementById('inputs').textContent  = info.inputs;
  document.getElementById('buttons').textContent = info.buttons;
}

// 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);
  });
});

popup.html:

<!DOCTYPE html>
<html>
  <head>
    <script type="text/javascript" src="popup.js"></script>
  </head>
  <body>
    <h3 style="font-weight:bold; text-align:center;">DOM Info</h3>
    <table border="1" cellpadding="3" style="border-collapse:collapse;">
      <tr>
        <td nowrap>Total number of elements:</td>
        <td align="right"><span id="total">N/A</span></td>
      </tr>
      <tr>
        <td nowrap>Number of input elements:</td>
        <td align="right"><span id="inputs">N/A</span></td>
      </tr>
      <tr>
        <td nowrap>Number of button elements:</td>
        <td align="right"><span id="buttons">N/A</span></td>
      </tr>
    </table>
  </body>
</html>
133
ответ дан gkalpak 19 August 2018 в 00:31
поделиться
  • 1
    Вау ! спасибо брату, проверяя ваш подход, теперь я чувствую, сколько проблем я создал с моим кодом. Спасибо, что это работает как шарм. :) – Sumair Baloch 17 November 2013 в 06:25
  • 2
    hello, Извините, но я не был на некоторое время, просто проверил ваш комментарий. Я не могу принять никакого ответа. он говорит, что вам нужно 15 очков репутации для этого. – Sumair Baloch 30 November 2013 в 15:04
  • 3
    nvm Я получил то, что на самом деле имел в виду. спасибо за головы. – Sumair Baloch 30 November 2013 в 15:05
  • 4
    Не могли бы вы помочь мне решить очень похожую проблему? & lt; a href = " stackoverflow.com/questions/34467627/… ; Мой текущий выстрел в это в значительной степени ваш код из этого ответа. Но я все еще не могу заставить его работать и не могу найти хорошую помощь в этом вопросе. – wuno 26 December 2015 в 03:37
  • 5
    @hkm: Потому что вы отправляете и получаете сообщения. Все это в документах . – gkalpak 23 January 2016 в 10:46

Для этого вы можете использовать localStorage. Вы можете хранить любые данные в формате хэш-таблицы в памяти браузера, а затем обращаться к нему в любое время. Я не уверен, можем ли мы получить доступ к localStorage из сценария содержимого (ранее он был заблокирован), попробуйте сделать это самостоятельно. Вот как это сделать на вашей фоновой странице (сначала я передаю данные из сценария контента на фоновый рисунок, а затем сохранил его в localStorage):

в contentScript.js:

chrome.runtime.sendMessage({
  total_elements: totalElements // or whatever you want to send
});

в eventPage.js (ваша фоновая страница):

chrome.runtime.onMessage.addListener(
    function(request, sender, sendResponse){
       localStorage["total_elements"] = request.total_elements;
    }
);

Затем вы можете получить доступ к этой переменной в popup.js с помощью localStorage ["total_elements"].

Возможно, вы можете получить доступ к localStorage непосредственно из сценария содержимого в современных браузерах. Затем вам не нужно передавать данные через вашу фоновую страницу.

Хорошее чтение о localStorage: http://diveintohtml5.info/storage.html

3
ответ дан Xan 19 August 2018 в 00:31
поделиться
  • 1
    Пожалуйста, не поощряйте использование устаревшего chrome.extension.onRequest / sendRequest (который, кстати, не загружает непостоянную фоновую страницу перед выполнением). Вместо этого используйте chrome.runtime. * . – gkalpak 16 November 2013 в 20:17
  • 2
    @ExpertSystem. Если вы видите такую ​​устаревшую информацию, предложите / внесите изменения. – Xan 12 June 2014 в 08:03
  • 3
    @Xan: Итак, вы преемник в [Google-Chrome-Extension] :) Мне не нравится редактировать сообщения людей (я нахожу это слишком навязчивым). Кроме того, с таким количеством устаревших учебных пособий и примеров (по крайней мере в то время) я нашел, что лучше иметь явный комментарий о том, почему bad использовать .extension.xxx вместо того, чтобы просто показывать правильный путь (которые некоторые люди могут рассматривать как «альтернативу в равной степени»). Думаю, это скорее вопрос стиля. Продолжайте хорошую работу ! – gkalpak 12 June 2014 в 09:08
Другие вопросы по тегам:

Похожие вопросы: