I'm trying to attach new <div> element with some content via bookmarklet and add some inline CSS.
The problem is that the CSS from the main page usually affects this div too.
What would be preferred approach to ensure that my styles from bookmarklet are always more important that the ones from any parent page?
The most trustworthy solution would be to set all possible CSS properties for each element inside the div. Is this wise? Where can I get the list?
I've found cleanstate.css which may do the reset.
Maybe some js solution would work better? Eg. detect which styles has been aplied by the main page, and reset them to default values? I'll have jQuery available in this bookmarklet anyways.
The reliable solution would be iframe.
You can create it dynamically and assign content using 'javascript:' protocol in src tag.
var iframe = document.createElement('iframe');
iframe.src = "javascript:'<div> Yours Content </div>'";
document.body.appendChild(iframe);
Or you can insert empty iframe, wait it to be loaded and modify iframe document as required. For example:
var iframe = document.createElement('iframe');
iframe.src = 'about:blank';
document.body.appendChild( iframe );
iframe.onload = function() {
iframe.contentWindow.document.body.innerHTML = '<div> Yours content </div>';
};
Alternatively, you can create separate .html page and insert it as iframe. <iframe src="http://example.com">Although, you will need to host page somewhere and document won't be able to access parent page without additional scripting. ( .postMessage() )
Related
My goal is to change a fill attribute in a polyline element in an svg sitting in a nested, same-domain, iframe.
When my page loads, I can see the content in the browser. In the chrome console, from javascript, I can access the nested iframe, and the div containing the svg.
document.querySelectorAll('iframe#my-frame')[0]
.contentDocument.querySelectorAll('iframe')[0]
.contentDocument.querySelector('#mydiv')
but the content of that div is evidently not in any dom that I can interrogate. The div is effectively empty, even though it's content is rendered in the browser.
<div id="mydiv"></div>
When I right-click > 'Inspect' the nested iframe, the devtools redirect to the body element of the iframe#document. I am now able to interrogate the div, and manipulate the svg elements' attributes. At this point I can no longer interrogate the parent page, because the window object is now the nested iframe itself--this is not unexpected.
But I can't reset window programmatically, I don't think, i.e., this doesn't work:
window = document.querySelectorAll('iframe#my-frame')[0].contentDocument.querySelectorAll('iframe')[0].contentWindow
Is there a way to programmatically change focus or window of the javascript running in the browser--what I assume is forcing the iframe content into the dom in order to manipulate a css attribute after page load? Remember this is not an iframe domain issue.
You can't access the iframe's content instantly
You need something like a load eventListener to wait until the <iframe> content is fully loaded.
const myFrame = document.querySelector("#my-frame");
myFrame.addEventListener("load", (e) => {
// content loaded - query and manipulate elements
let doc = myFrame.contentDocument;
let iframeSvg = doc.querySelector("svg");
let svgEl = iframeSvg.querySelector("rect");
svgEl.style.fill = "green";
});
I have a JavaScript script (no plugins, just pure JS) that creates an iframe element in the body of the page, and inside this iframe is placed a huge HTML to be displayed in this iframe.
This script uses document.write to write this content to the iframe, however, performance tools report that this procedure is too slow to load the page.
Below is my code:
var body = document.getElementsByTagName('body'),
iframe,
container;
container = document.createElement('div');
container.id = 'iframePlaceholder';
iframe = document.createElement('iframe');
iframe.id = 'myPageIframe';
iframe.name = 'page-content-frame';
iframe.allowfullscreen = true;
container.appendChild(iframe);
body[0].appendChild(container);
iframe = document.getElementById('myPageIframe');
iframe.contentWindow.document.open();
iframe.contentWindow.document.write('<html><body>content........<script src="..."></script></body></html>');
iframe.contentWindow.document.close();
What can I do to avoid using document.write without having to rewrite all my HTML in DOM?
Is it possible to convert this HTML string into a DOM element and add it to the iframe?
Edit:
The content loaded by the iframe is dynamic, so it is not possible to place an HTML file to be loaded by the iframe's SRC.
Perhaps you can try placing the HTML content inside a new file and add the name of the file to the src attribute of the iframe.
Something like the following:
<iframe id="myPageIframe" name="page-content-frame" src="newfile.html"></iframe>
I'm having trouble accessing the DOM of an iframe content document if I create the iframe dynamically in JavaScript rather than hard-coding it in the HTML.
I'm finding this so far testing in Mac FF26 and Safari 6. It is a local iframe document on the desktop, so there should be no cross-domain issues.
The iframe I generate appears normally in the browser window. But trying to access it with contentDocument, the body element seems to be empty.
Is this a known issue? Perhaps I'm generating my iframe in an unusual way:
var newIframe = document.createElement("iframe");
newIframe.id = "generatedIframe";
newIframe.src = "test.html";
document.body.appendChild(newIframe);
var iframeTag = document.getElementById("generatedIframe");
// the iframe will be appearing normally in the browser now
// but this fails -- innerHTML is empty string:
var iframeContent = iframeTag.contentDocument.getElementsByTagName("body")[0].innerHTML;
// same reference code works if the iframe is hard-coded in HTML instead
In fact your problem is not the way you generated your iframe.
The iframe DOM is only available after it has been loaded.
The code behind illustrates what I mean :
In your parent window container :
<script>
function doSomething() { alert(iframeTag.contentDocument.getElementsByTagName("body")[0].innerHTML()); }
</script>
In your iframe document
<body onload="window.parent.doSomething();"></body>
I have a main page that include a javascript that was creating an iframe dynamically same below:
<script>
document.domain = "mydomain.com"
var iframe = document.createElement("iframe");
document.body.appendChild(iframe);
// creating other element in ifram dynamically
</script>
But in IE I kept receiving a security warning because of document.domain = "mydomain.com" (I need document.domain and I can not remove it).
I found a solution for IE8. this is the solution :
var u = 'javascript:(function(){document.open();document.domain="mydomain.com";document.close();})()';
iframe.src = u;
But it does not work on IE6. Is there any solution for my problem?
Note: I want to create other element in iframe by script and I want to load the content of iframe by src.
Create the iFrame using innerHTML.
Write the full HTML for the iFrame including the SRC attribute. Then find your element and set innerHTML to the string with the iFrame source.
I want to be able to remove an iframe from within itself. The iframe is created dynamically and the content is loaded with 'src'.
I create my iframe like this:
var i = document.createElement('iframe');
i.id = 'proxy_frame';
i.name = 'proxy_frame';
i.setAttribute('src', url);
document.body.appendChild(i);
Then from within 'url' I want to be able to remove/close the iframe.
Before loading the data into the iframe with src I used document.write:
window.frames['proxy_frame'].document.write(html);
and then I was abloe to remove the iframe with:
window.parent.document.getElementById("proxy_frame").parentNode.removeChild(window.parent.document.getElementById("proxy_frame"));
But this does not work with 'src'.
Note: This is for a bookmarklet so I don't want to use jQuery or another library.
Define a method in your parent page
function removeElement() {
var d = document.getElementById('body'); // or any other parent element
var proxy_frame = document.getElementById('proxy_frame');
d.removeChild(proxy_frame);
}
To call this method from your iframe simply use this
Remove me
For local domain iframes you don't need to rely on ids.
window.parent.document.body.removeChild(window.frameElement);
window.frameElement has reasonable support https://developer.mozilla.org/en-US/docs/Web/API/Window/frameElement
You can't access the parent page as long as it's in a different domain.
Set up a page in your site that can be used to remove the iframe, then in the iframe you just go to that page.