Search code examples
firefoxfirefox-addonfirefox-addon-sdk

How to pass user input from HTML panel to Addon script in firefox Addon SDK


I am using Addon SDK. I am confused on how to pass user input to my addon index.js. I looked at Content Script but it is not exactly what I look for. I have an HTML page that pops up when the user clicks on the Addon button. Here is the HTML code:

<html>
<head>
<style type="text/css" media="all">
textarea {
margin: 10px;
}
body {

        background-color:white;
      }
    </style>
  </head>

  <body>

  <form> 
      Enter name: <br>
      <input type="text" id="txt-field">
      <input type="submit" value="Add">
  </form>
  </body>
</html>

Once the user clicks the add button in the HTML, I need to pass the text that the user entered to my main.js file then I want to store it permanently unless the user deleted it manually. Here is the index.js:

var { ToggleButton } = require('sdk/ui/button/toggle');
var sdkPanels = require("sdk/panel");
var self = require("sdk/self");
var storage = require("sdk/simple-storage"); 

var button = ToggleButton({
  id: "my-button",
  label: "my button",
  icon: {
    "16": "./icon-16.png",
    "32": "./icon-32.png",
    "64": "./icon-64.png"
  },
  onChange: handleChange
});

var myPanel = sdkPanels.Panel({
  contentURL: "./text-entry.html",
  onHide: handleHide
});

function handleChange(state) {
  if (state.checked) {
    myPanel.show({
      position: button
    });
  }
}

function handleHide() {
  button.state('window', {checked: false});
}

Can you point to me how can I achieve such thing?


Solution

  • In order to pass values from the HTML panel page to the Addon script you need to add a content script. Since my panel is trusted (internal to the Addon and not external web page), you can achieve passing values entered in the HTML panel by attaching a script to the panel. The panel code looks like this (codes from: this link

    <html>
    <head>
        <style type="text/css" media="all">
          textarea {
            margin: 10px;
          }
          body {
            background-color: gray;
          }
        </style>
      </head>
      <body>
        <textarea rows="13" cols="33" id="edit-box"></textarea>
        <script src="get-text.js"></script>
      </body>
    </html>
    

    Then, the script code that takes the panel's entered text (in this example, the text ends by enter) and emits the value to the Addon looks like this:

    // When the user hits return, send the "text-entered"
    // message to main.js.
    // The message payload is the contents of the edit box.
    var textArea = document.getElementById("edit-box");
    textArea.addEventListener('keyup', function onkeyup(event) {
      if (event.keyCode == 13) {
        // Remove the newline.
        text = textArea.value.replace(/(\r\n|\n|\r)/gm,"");
        addon.port.emit("text-entered", text);
        textArea.value = '';
      }
    }, false);
    // Listen for the "show" event being sent from the
    // main add-on code. It means that the panel's about
    // to be shown.
    //
    // Set the focus to the text area so the user can
    // just start typing.
    addon.port.on("show", function onShow() {
      textArea.focus();
    });
    

    And the Addon code that receives the value and post it in the console.log is:

    var data = require("sdk/self").data;
    // Construct a panel, loading its content from the "text-entry.html"
    // file in the "data" directory, and loading the "get-text.js" script
    // into it.
    var textEntryPanel = require("sdk/panel").Panel({
      contentURL: data.url("text-entry.html")
    });
    
    // Create a button
    require("sdk/ui/button/action").ActionButton({
      id: "show-panel",
      label: "Show Panel",
      icon: {
        "16": "./icon-16.png",
        "32": "./icon-32.png",
        "64": "./icon-64.png"
      },
      onClick: handleClick
    });
    
    // Show the panel when the user clicks the button.
    function handleClick(state) {
      textEntryPanel.show();
    }
    
    // When the panel is displayed it generated an event called
    // "show": we will listen for that event and when it happens,
    // send our own "show" event to the panel's script, so the
    // script can prepare the panel for display.
    textEntryPanel.on("show", function() {
      textEntryPanel.port.emit("show");
    });
    
    // Listen for messages called "text-entered" coming from
    // the content script. The message payload is the text the user
    // entered.
    // In this implementation we'll just log the text to the console.
    textEntryPanel.port.on("text-entered", function (text) {
      console.log(text);
      textEntryPanel.hide();
    });