Detect and handle a button click in the active HTML page

≡放荡痞女 提交于 2019-12-23 04:42:58

问题


Currently, I am creating a WebExtension for Firefox which displays a small div in the active HTML page on the active tab after 6 seconds (not the popup.html in browser_action!). I made a small example that shows a button in the div. My problem is that I don't know how to detect a click event of this button so I can kick off a function? In the moment I handle the event listener in content.js

manifest.json:

{
  "manifest_version": 2,
  "name": "Study06",
  "version": "1.0",
  "description": "My web extension",
  "permissions": [
  "tabs",
    "<all_urls>",
    "alarms"
  ],
  "background": {
    "scripts": ["background.js"]
  }
}

background.js:

browser.alarms.create("", {delayInMinutes: 0.1});
browser.alarms.onAlarm.addListener(injectScript);
function getActiveTab() {
  return browser.tabs.query({active: true, currentWindow: true});
}
function injectScript() {
  getActiveTab().then((tabs) => {
    browser.tabs.executeScript(null, {
      file: "/content.js"
    });
    // send message to contentscript
    browser.tabs.sendMessage(tabs[0].id, {message: "Hello"});
  });
}

After 6 seconds, content.js will be loaded and a message to content.js will be sent.

content.js:

document.addEventListener('DOMContentLoaded', function() {
  var button = document.getElementById('button_id');
  button.addEventListener('click', function() {
    console.log("CLICK");
  });
});

browser.runtime.onMessage.addListener(createModal);

function createModal(){
  document.getElementsByTagName('body')[0].appendChild(modal1);
}

//create div with button
var modal1 = document.createElement("div");
modal1.style.paddingTop = "100px";
modal1.setAttribute("id", "mymodal1");
modal1.style.position = "fixed";
modal1.style.top = 0;
modal1.style.left = 0;
modal1.style.zIndex = 1000000;
modal1.style.overflow = "auto";
var button1 = document.createElement("button");
button1.setAttribute("id", "button_id");
button1.innerHTML = "Click me";
modal1.appendChild(button1);

The event listener in content.js is not working. I also created a JavaScript file javascriptForButtonEvent.js with an event listener for the button and added this script in manifest content_script. Also, to inject this file in background script like:

browser.tabs.executeScript(null, {
      file: "/content.js";
      file: "/javascriptForButtonEvent.js"
    });

But, these solutions didn't work for me (when clicking the button nothing happens). Is there a way to handle events from the active HTML page?


回答1:


Your click event listener never gets added to the DOM. You have:

document.addEventListener('DOMContentLoaded', function() {

When injecting scripts, unless you are explicitly injecting at document_start, your script is guaranteed to be injected at least after DOMContentLoaded has already fired.1 Given that the event has already fired, and only fires once, your DOMContentLoaded listener is never called. As a result of how injection works, you do not need to listen for the DOMContentLoaded event at all. Just move your initialization such that it executes in the main sequence of your code (after you add the button):

document.getElementById('button_id').addEventListener('click', function() {
    console.log("CLICK");
});

No need to search for the <button> you create

However, in this case, you are adding this button yourself. There is no need to go searching for it in the DOM. You already have a reference to it. Add the listener at the time you are creating the button:

var button1 = document.createElement('button');
button1.id = 'button_id';
button1.textContent = 'Click me';
button1.addEventListener('click', function() {
    console.log("CLICK");
});
modal1.appendChild(button1);

Don't use generic IDs or classes

For extensions, you should not use IDs or classes that are as generic as button_id. Doing so results in a good chance that you will have a name collision with the random pages into which you are injecting content. You should pick a sequence of text which you use as a "namespace". You can then prepend this namespace to all IDs and classes. For instance, your ID should be something like: Study06-button_id. Exactly what you use is a personal choice. But, it should be specific to the extension you are working on.

When listening for DOMContentLoaded, you should check readyState

Any time you use a DOMContentLoaded listener, or a window load listener, you should always check the document.readyState to make sure that you are adding the listener prior to the DOMContentLoaded event being fired (or load event, if that is what you are listening for). This should be normal habit when you want to listen for these events. If you add the listener after the event has fired, the listener will never be run.

For adding a DOMContentLoaded listener, you should use something like:

if(document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded',afterLoaded);
} else {
    afterLoaded();
}

function afterLoaded(){
    //Everything that needs to happen after the DOM has initially loaded.
}

  1. Note that when using tabs.executeScript() you have to seriously work at having your tabs.executeScript() execute in a time-frame where the script is actually injected at document_start. The exact timing that is needed is different for different browsers. If you use a manifest.json content_script entry, this timing is handled by the browser.


来源:https://stackoverflow.com/questions/42553455/detect-and-handle-a-button-click-in-the-active-html-page

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!