Search code examples
javascriptgoogle-chrome-extensionuserscripts

Need important advice on Chrome Extension development


Sorry for the vague title, I'll try to be as specific as I can for the description.

If you look at my previous question on this site, you'll see that I asked for tips on how to populate Chrome context menus. The reason why I am using the context menus is that I want an easy-to-access interface that presents the user with a list of values. Those values represent different types of documents (for example a birth certificate or a tax report). Each of these documents have unique attributes (ex: birth certificate is "Birth certificate" and "Identity") and rules. Those attributes and rules are used when I have to upload the files to a DMS (document management system), which is basically an ASP.Net web site. Text fields and dropdown lists are used to receive the rules and attributes I mentioned earlier. Usually, when adding a file, I have to fill those fields by hand based of the type of document, a very time consuming process.

Now, what I want to do is to simply be able to click on one of my context menu's items (again, let's say I click on "Birth certificate") and the fields on the page will automatically be updated with the corresponding values.

What I have done so far is to put most of the menu items/document types and their corresponding attributes/rules in JSON format. My original intention was to set the values of the page's fields with a script included in the context menu extension. Only, if I'm not mistaken (if I am, please tell me), you cannot modify the value of HTML elements on a web page directly through a Chrome extension.

From what I understand, userscript would be able to fulfill that task, but I still want to have a control interface (the context menu) to choose the type of document (I don't want a script that always executes with the same parameters).

So, from what I have described, what would you say is the best way to achieve this task ? Can I "call" userscript or at least pass some parameter so that I can modify the values of text fields/dropdown lists as I wish ? Any advice is greatly weclome.

P.S. I tested some script to see if the fields could actually have their values changed programatically. I just copy pasted the code (with some pre-defined values for the fields) in the adress bar with the "javascript:" prefix and it works like a charm! Now, I just need to

  • 1) Be able to do this without using this address bar trick and
  • 2) have an actual interface to chose values instead of just hard coding them.

Solution

  • Only, if I'm not mistaken (if I am, please tell me), you cannot modify the value of HTML elements on a web page directly through a Chrome extension.

    Sure they can. Check out content scripts, which can be set up to inject themselves automatically in sites that match a specified pattern. You can also do programmatic injection via chrome.tabs.executeScript. Chrome extensions have access to far more tools than user scripts.

    You'd just use whatever onclick callback you've set when creating your context menu, then you'd run:

    chrome.tabs.executeScript(null, { file: "script_to_inject.js"});
    

    Once that script loads, you have several options, but I would just use message passing to get the appropriate info from your background page and then modify the fields.

    Simple example

    manifest.json (add this to your permissions)

    "permissions": [ "http://*/*" ],
    

    script_to_inject.js

    chrome.extension.sendRequest("options", function(response) {
      alert(response.birthday); // Alerts the birthday in the response
      alert(response.name);     // Alerts the name in the response
      document.getElementById("some_field_id").value = response.name;
    });
    

    background.html (or background.js)

    chrome.extension.onRequest.addListener(function(request, sender, sendResponse) {
      switch (request) {
        case "options":
          sendResponse({birthday: "1/1/1970", name: "Unix"});
          break;
        default: // Add other cases as you see fit
          sendResponse({});
          break;
      }
    });