Skip to content

Instantly share code, notes, and snippets.

@srsudar
Created July 27, 2014 18:00
Show Gist options
  • Star 28 You must be signed in to star a gist
  • Fork 14 You must be signed in to fork a gist
  • Save srsudar/e9a41228f06f32f272a2 to your computer and use it in GitHub Desktop.
Save srsudar/e9a41228f06f32f272a2 to your computer and use it in GitHub Desktop.
Pasting from the system clipboard using a Chrome extension.
<!DOCTYPE html>
<html>
<head>
<script src="background.js"></script>
</head>
<body>
<textarea id="sandbox"></textarea>
</body>
</html>
'use strict';
// A gotcha of sorts with chrome extensions involving clipboard actions is that
// only the content scripts can interact with the page that a user loads. This
// means that we can't put our calls to actually paste into the page in the
// background file, because the background scripts are not able to paste into
// the dom of the page. However, only background pages are able to access the
// system clipboard. Therefore we have to do a little trickery to move between
// the two. We're going to define the functions here to actually read from the
// clipboard into a textarea we've defined in our background html, and then
// we'll get that pasted data from the background page and do the actual
// insertion in our content script. The idea of this comes from:
// http://stackoverflow.com/questions/7144702/the-proper-use-of-execcommandpaste-in-a-chrome-extension
/**
* Retrieve the current content of the system clipboard.
*/
function getContentFromClipboard() {
var result = '';
var sandbox = document.getElementById('sandbox');
sandbox.value = '';
sandbox.select();
if (document.execCommand('paste')) {
result = sandbox.value;
console.log('got value from sandbox: ' + result);
}
sandbox.value = '';
return result;
}
/**
* Send the value that should be pasted to the content script.
*/
function sendPasteToContentScript(toBePasted) {
// We first need to find the active tab and window and then send the data
// along. This is based on:
// https://developer.chrome.com/extensions/messaging
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
chrome.tabs.sendMessage(tabs[0].id, {data: toBePasted});
});
}
/**
* The function that will handle our context menu clicks.
*/
function onClickHandler(info, tab) {
var clipboardContent = getContentFromClipboard();
console.log('clipboardContent: ' + clipboardContent);
if (info.menuItemId === 'pasteDemo') {
console.log('clicked paste demo');
sendPasteToContentScript(clipboardContent);
}
}
// Register the click handler for our context menu.
chrome.contextMenus.onClicked.addListener(onClickHandler);
// Set up the single one item "paste"
chrome.runtime.onInstalled.addListener(function(details) {
chrome.contextMenus.create(
{
'title': 'Paste Demo',
'id': 'pasteDemo',
'contexts': ['editable']
});
});
'use strict';
/**
* Insert the text at the cursor into the active element. Note that we're
* intentionally not appending or simply replacing the value of the editable
* field, as we want to allow normal pasting conventions. If you paste at the
* beginning, you shouldn't see all your text be replaced.
* Taken from:
* http://stackoverflow.com/questions/7404366/how-do-i-insert-some-text-where-the-cursor-is
*/
function insertTextAtCursor(text) {
var el = document.activeElement;
var val = el.value;
var endIndex;
var range;
var doc = el.ownerDocument;
if (typeof el.selectionStart === 'number' &&
typeof el.selectionEnd === 'number') {
endIndex = el.selectionEnd;
el.value = val.slice(0, endIndex) + text + val.slice(endIndex);
el.selectionStart = el.selectionEnd = endIndex + text.length;
} else if (doc.selection !== 'undefined' && doc.selection.createRange) {
el.focus();
range = doc.selection.createRange();
range.collapse(false);
range.text = text;
range.select();
}
}
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
if (request.data) {
insertTextAtCursor(request.data);
}
});
{
"name": "Paste Demo",
"version": "0.0.1",
"manifest_version": 2,
"description": "Demonstration of how to paste in a Chrome extension",
"permissions": [
"clipboardRead",
"contextMenus"
],
"background": {
"persistent": false,
"page": "background.html"
},
"content_scripts": [
{
"matches": [
"http://*/*",
"https://*/*"
],
"js": [
"contentscript.js"
],
"run_at": "document_end",
"all_frames": false
}
]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment