3

I am trying to create a context menu option which copies some text to the system clipboard.

Currently, I am just copying a hard-coded string literal, but I am wondering how it could be changed to copy selected text. Specifically, I don't know how to properly create the createProperties object (see bottom)

It is my understanding that this can only be done through a background page.

I have the following background page:

background.html

<textarea id="temp"></textarea>
<script src="context.js"></script>

context.js is as follows:

chrome.contextMenus.create({
    "title": "Freedom",
    "contexts": ["editable"],
    "onclick" : copyToClipboard
  });        

function copyToClipboard()
{ 
    var tempNode = document.getElementById("temp");
    tempNode.value = "some text";
    tempNode.select();
    var status = document.execCommand('copy',false,null);

    if(status) alert('successful');

    else alert('unsuccessful');
}    

my manifest.json is as follows:

{
    "manifest_version": 2,

    "name": "Freedom",
    "description": "Provides users useful and fun context menu options that they can access from anywhere.",
    "version": "1.0",

    "permissions": [
        "contextMenus",
        "clipboardWrite"
        ],  

    "background": {
        "page": "background.html"
    }   

}    

I am apparently declaring the chrome.contextMenus.create() function incorrectly. I have read the docs for it and I can only imagine that I am not properly creating the createProperties object.

I have been trying to mimic these sources:

Is that possible calling content script method by context menu item in Chrome extension?

http://paul.kinlan.me/chrome-extension-adding-context-menus/

some other related questions are:

Copy to Clipboard in Chrome Extension

How to copy text to clipboard from a Google Chrome extension?

Community
  • 1
  • 1
Luke
  • 5,567
  • 4
  • 37
  • 66
  • 1
    You're calling the function instead of passing a function reference. And carefully read the documentation of the [`click` event handler of `chrome.contextMenus.create`](https://developer.chrome.com/extensions/contextMenus#property-createProperties-onclick), your function signature is completely off. – Rob W Jan 11 '15 at 21:29
  • can you possibly provide an example, I have been reading and rereading that page, but I am confused. I see plenty of examples though that do what I did. Are they outdated? – Luke Jan 11 '15 at 21:34
  • do you mean that I'm not creating the createProperties object correctly? – Luke Jan 11 '15 at 21:35
  • The problem here consists of two parts: 1) you call a function instead of passing a function reference (there are literally hundreds of questions on Stack Overflow about this issue, search and you will find...) and 2) the onclick handler does not match the API description. Can you first link to some of the "oudated" examples that you mention? Perhaps the example is not outdated, but a misunderstanding at your part. – Rob W Jan 11 '15 at 21:37
  • will do, editing now. – Luke Jan 11 '15 at 21:38
  • I fixed the part about passing a function reference, please re-read the question as the details are different now – Luke Jan 11 '15 at 21:53
  • `textvalue` -> `value`. – Rob W Jan 11 '15 at 22:02
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/68610/discussion-between-lukep-and-rob-w). – Luke Jan 11 '15 at 22:10

1 Answers1

3

"createProperties" in the documentation is the dictionary that is passed to the chrome.contextMenus.create method (i.e. that thing with "title", "contexts", etc.)

The onclick event description of chrome.contextMenus.create states that the function receives two parameters. The first parameter ("info") is a dictionary with information about the selected text. The second parameter ("tab") contains information about the tab (in your case, you don't need though).
The "info" dictionary has a property "selectionText" that holds the selected text when the context menu item was clicked. This can be used in your code as follows:

function copyToClipboard(info) {
    var tempNode = document.getElementById("temp");
    tempNode.value = info.selectionText; // <-- Selected text
    tempNode.select();
    document.execCommand('copy', false, null);
}

That would solve your immediate question.
Besides that, your extension can be improved by converting your background page to an event page. The main benefit of event pages over background pages is that your extension will not unnecessarily use memory while sitting idle in the background.

// background.js

// Register context menu
chrome.runtime.onInstalled.addListener(function() {
    chrome.contextMenus.create({
        "id": "some id",  // Required for event pages
        "title": "Copy selected text to clipboard",
        "contexts": ["editable"],
        // "onclick" : ...  // Removed in favor of chrome.contextMenus.onClicked
    });

});

// Register a contextmenu click handler.
chrome.contextMenus.onClicked.addListener(copyToClipboard);

Here is a minimal manifest.json (note the "persistent": false key, which specifies that you want to use an event page)

{
    "manifest_version": 2,

    "name": "Copy selected text to clipboard",
    "version": "1.0",

    "permissions": [
        "contextMenus",
        "clipboardWrite"
     ],

    "background": {
        "page": "background.html",
        "persistent": false
    }
}   
Rob W
  • 341,306
  • 83
  • 791
  • 678