Reputation: 874
manifest.json
{
"name": "Append Test Text",
"description": "Add test123 to body",
"version": "1.0",
"permissions": [
"activeTab"
],
"background": {
"scripts": ["background.js"],
"persistent": false
},
"browser_action": {
"default_title": "Append Test Text"
},
"manifest_version": 2,
"permissions": [
"https://*/*",
"http://*/*",
"tabs"
]
}
background.js
chrome.browserAction.onClicked.addListener(function(tab) {
chrome.tabs.executeScript({
code: 'var div=document.createElement("div"); document.body.appendChild(div); div.innerText="test123";'
});
});
What it does:
Upon clicking the chrome extension icon, it adds <div>test123</div>
to the <body></body>
of any given page.
Alike the bit.ly Chrome extension, I would like to append a lot of content to the DOM. Upon clicking on the extension icon, I would like an overlay element to be added tot he <body></body>
along with a sidebar where I can add jQuery tab switches.
As you can see, I've just taken this picture whilst creating this question for StackOverflow.
Upvotes: 4
Views: 1814
Reputation: 77482
Why not take a look at how bit.ly extension does it?
Looking at the code, bit.ly appends a fixed position, 100% width/height iframe to the page that contains an "app" page from the package. Clicking again removes the iframe. There's a bit of special code to work with frameset pages (which I won't comment on here), but other than that that's the general idea.
Part of the page is half-transparent, which gives the illusion of a sidebar, but it does indeed cover the whole page. This is the easiest way to do it, since otherwise you risk breaking the page's layout and there is no general "magic" solution that works everywhere to have your content side by side.
// Injection
var iframe = document.createElement("iframe");
iframe.id = "my-awesome-extension-iframe";
iframe.style.width = "100%";
/* ..more styling like that.. */
iframe.src = chrome.runtime.getURL('my_ui.html');
document.body.appendChild(iframe);
// Removal
var iframe = document.getElementById("my-awesome-extension-iframe");
if (iframe) {
iframe.parentNode.removeChild(iframe);
}
To have full control over the looks of your UI, injecting a frame is preferable, as the page's own CSS and scripts won't "bleed" into your context. Whatever libraries you want, you can include there as you would in a normal page.
If you vehemently object to the idea of using a frame, you can try and inject your UI directly into the page - but beware interfering/incompatible code, restrictive CSP and CSS that bleeds through. This question is relevant: How to really isolate stylesheets in the Google Chrome extension?
You could make the above snippets as separate files, and use executeScript
with the file attribute to inject them. They do not require any libraries like jQuery.
Note that code in that frame will have the same level of privilege as content script code - if you need APIs unavailable in content scripts, you'll need to message the background to do it. You'll also need to list the page itself, and all of its resources, in web_accessible_resources
.
Upvotes: 3
Reputation: 5610
Dynamic DOM elements may be the way to go if you are adding simple user controls inside a layout. However, if you want to inject a full layout it can be a pain. jQuery may come handy with its function load
.
You could have the layout of your sidebar in a static HTML file and have it loaded with jQuery in a given container. Something like this should do it, assuming an id="myContainer"
:
jQuery
$('#myContainer').load('layout.html')
To answer the first question, to give a specific ID to a dynamically created element, you only have to treat it like a DOM element and set an id to it.
JavaScript
var myElement = document.createElement('div');
myElement.id = 'myContainer';
myElement.className = 'kitten-background jumbo button';
// ...
// other properties you may need
// ...
document.body.appendChild(myElement);
For the second question, to check if an element exists you may as well use jQuery again. If a selector matches something, its length
attribute will be greater than zero so that's a clean validation to check that $('#myContainer').length == 0
before inserting.
Good luck in what you are trying to achieve and have fun!
Upvotes: 0