1

I'm trying to create my first Chrome extension right now. It's a simple pop-up window with a number of pictures of sloths in it. What I'm trying to do is make it so that when you click on the picture of the sloth it appends the image URL into the current text field in the content page.

Here is my JSON:

{
"manifest_version": 2,

"name" : "Instant Sloth",
"description": "One button, many sloth.",
"version": "1",

"permissions": [
    "https://secure.flickr.com/"
],

"browser_action": {
    "default_icon": "icon.png",
    "default_popup": "popup.html"
},
"content_scripts": [{
    "js": ["jquery.min.js", "tab.js", "jquery-ui.min.js", "input.js"],
    "matches": ["http://*/*", "https://*/*"],
    "run_at": "document_end"
    }]
}

Where popup.html is the HTML file with the pictures of the sloths, and input.js is the script that I'm hoping will add interactivity, like here:

$("img").click(function(){
var form = $(document.activeElement);
var sloth = $(this).attr('src');
form.value = (form.value + " " + sloth);
});

I'm having trouble trying to figure out how to access elements of both the content page and the pop-up within the same script. I also have the input.js file linked to pop-up.html. Thanks for the help!

nao
  • 1,128
  • 1
  • 14
  • 37
  • This page may answer a lot of questions: https://developer.chrome.com/extensions/overview#arch – Xan Dec 16 '14 at 23:09

1 Answers1

2

This page may answer a lot of questions: Architecture Overview

In short, you can't do that in one script, because the popup and the current open page are different contexts. You need a script in the popup that handles the click and gets the source URL, a script in the page (a Content Script) that inserts the text, and some form of communication between two.

One approach is to use Messaging, where you have the content script listening for a command from the popup. This approach is valid, but has a slight problem I described here: there is no 100% warranty that the content script is actually ready in a given tab.

In your case, it's much easier to just construct a short code snippet and inject it into the page programmatically.

// Popup code
$(document).ready(function() {
  $("img").click(function() {
    var sloth = $(this).attr('src');
    var script = 'var form = document.activeElement;' +
      + 'form.value = (form.value + " ' + sloth + '");';
    chrome.tabs.executeScript({code : script});
  });
});

P.S. You will need the "activeTab" permission in your manifest for this to work.

Community
  • 1
  • 1
Xan
  • 74,770
  • 16
  • 179
  • 206
  • Thank you. I'm trying to understand programmatic injection... So if I put that code into input.js and link it to the HTML file, the line "chrome.tabs.executeScript({code : script});" will cause it to execute on the current tab at hand? Do I need to link it to the content-scripts part of the manifest at all? – nao Dec 16 '14 at 23:43
  • Also, an additional problem is that when I click the pop-up icon on the omnibar, the active "window" becomes the pop-up window, so there is no active element in the content page anymore... Would you know of any way to prevent that from happening (i.e. make the pop-up window appear without switching the activeElement?) – nao Dec 16 '14 at 23:45
  • In case you go with my code, the `content_scripts` section in the manifest is not needed. You decide when to inject code yourself - and it saves resources, as your code is not loaded in every tab. – Xan Dec 16 '14 at 23:45
  • Well, then you don't understand what's happening. Read the Overview again. `executeScript` will take the currently open tab (unless you feed it another tab ID) and execute code _there_, not in the popup. As such, `document` will refer to the active tab, not the popup. Also, see my edit about permissions. – Xan Dec 16 '14 at 23:48
  • I think I'm starting to understand. I'll keep messing around with it.Thank you!! – nao Dec 16 '14 at 23:53