Here's a sample code:
HTML
<script> alert('This is alert!') </script>
JS
window.alert = function(data) //alert() over-riding
{
console.log("Alert over-ridden");
}
Issue:
HTML
<iframe src=javascript:alert('Iframealert')>
JS
window.alert = function(data) //alert() over-riding
{
console.log("Alert over-ridden"); //This doesn't execute - I mean, this over-ride function is not called when the above iframe alert is executed
}
I knew iframe in another document is not applicable for parent over-riding (due to same domain policy), but, the src JS execution happens only in the parent.
So, how do I over-ride alert() which is applicable to above iframe tag?
Update 1:
The HTML code is static, and I cannot make any modifications to it. I can only write some JS and append to the HTML.
Is there any way to over-ride the alert() of nested browsing window?
Nice question! The answer starts by looking at the rules for what happens when the src attribute is evaluated.
When this happens, the spec follows a number of steps during navigation. We end up step 14, which pertains to javascript: schemes.
Within that step, there are a series of sub-steps, one of which is:
Create a script, using script source as the script source, address as the script source URL, JavaScript as the scripting language, and the script settings object of the Window object of the active document of the browsing context being navigated.
The important thing here is "the Window object of the active document of the browsing context being navigated". Because you're navigating an <iframe>, you're actually dealing with a Nested Browsing Context, which has it's own window, so having overridden the parent window.alert makes no difference.
You can, however, override the alert of the inner window:
document.getElementById('myIframe').contentWindow.alert = function(msg) {
console.log('Overridden iframe: ' + msg);
}
This will only work for the javascript: scheme url presented to the src attribute, as at the time this code executes we were simply trying to get the address of the page to navigate the <iframe> to. When navigation actually occurs, a new Document object with it's own window is created in step 23 of the navigation steps, at which point you lose your overridden alert.
This also relies on setting the src attribute using JavaScript after you've overridden the alert, you can't use an inline src attribute on the element as the element needs to be in the page to get hold of it and it's contentWindow, and putting it in the page means the src will get evaluated.
Here's a fiddle demonstrating the overriding of the alert within the <iframe>'s src attribute.
Related
I need the following:
I got a html document, in which I have an iframe and an object. Both, the iframe and the object contain separat html files.
Now I want to click a link in the iframe, and this should affect the links inside the object to hide.
How do I use jQuery selectors to select the links in the object html file?
Structure:
<html file parent>
<iframe> html site 1 with link to click</iframe>
<object> html site 2 with links to affect </object>
<html file parent>
Thanks in advance!
This is not possible if the domain of the iframe is different from that of your .
This is a javascript restriction.
For this to possible you need to have control on the url loaded in the iframe.
If it is of same domain then you can probably do that.
If you have control over the iframe's url try this.
First, have a look at window.postMessage. Using this, you may send an event from your iframe to the window parent target. Listening for that event in the window parent (when something in your iframe changed), you will then be able to access any element inside the object tag using a syntax like this:
$('object').contents().find('linkSelector')
Give your iframe an id, let's say myIframe:
<iframe id="myIframe"> html site 1 with link to click</iframe>
Get a reference to the iframe:
var myIframe = document.getElementById('myIframe');
Post a message from iframe:
myIframe.contentWindow.postMessage('iframe.clicked', 'http://your-domain.here.com');
Handler for iframe change:
var handleIframeChange = function(e) {
//
if(e.origin == 'http://your-domain.here.com') {
// Get reference to your `object` tag
var objContent = $('object').contents();
// For instance, let's hide an element with a class of `link-class-here`
objContent.find('.link-class-here').hide();
}
}
Listen on parent window for the event sent by the iframe:
window.addEventListener('iframe.clicked', handleIframeChange, false);
Haven't tested it right now (did this in the past, when I had control over iframe) but it should work, but as I said, only if you can have control over the iframe.
I just discovered that the source of my issues is that the parent HTML makes calls to controls in a child IFRAME but is too quick about that and, sometimes, the super onLoad attempts to do so before the sub onLoad had a chance to add stuff to the DOM.
What can I do about it?
I've tried to set up some kind of feed-back from onLoad in the child. Failed miserably with so many strange errors that they can be summarized by dude, just please don't.
I've tried to set up a delayer, which is ugly of epic proportions and not 100% reliable.
EDIT:
In onload I do this:
var stuff = getReferenceToStuff();
var someDiv = stuff.contentWindow.document.getElementById("someDiv");
someDiv.className = "classy";
The problem is that sometimes the reference someDiv is null and sometimes (often when I reload the page by F5), it points to the correct element. I know it's because the contents of the IFRAME are a bit slower.
So my questions is this. How can I ensure that onload is postponed until the embedded IFRAME component's onload ensures that it's been loaded and all the components are there?
The onLoad event isn't always working correctly on document. It works correctly on each element though.
var iframes = document.getElementsByTagName('iframe'),
counter = 0,
max = iframes.length;
[].forEach.call(iframes, iLoaded);
function iLoaded() {
if (++counter === max) {
callback();
}
}
function callback() {
// All the iframes are loaded
}
When using window.onload all content of the body, including content of the iframes and all other resources like images, should be loaded before the onload is fired. However, some browsers have had problems with timing on firing onload, i.e. different browsers trigger the event in different stage of page parsing.
If you're using DOMContentLoaded or jQuery's $(document).ready(), only the HTML of the main page is loaded, but some resources are still under work (including iframe's content loading). I'm not aware what happens if you attach an inline listener for the iframe element itself.
If there's timing problems, maybe not trigger the function needing iframe reference in main window at all. Instead invoke that function in main window in irame's window.onload. But even this won't tackle the problem, if you're using some asynchronous technique to populate the iframe. In this case you need to invoke the function in main window after all requests have been completed.
(Now you maybe also know, what are the codesnippets I'd like to see in your post : ) ).
I have 2 solutions to your problem:
If you are on HTML5, use window.postMessage. Just message from iFrame to the parent in the onload of iFrame. Parent should register handler in <script> tag, that appears before iFrame.
Add a callback function to window in the '' tag before iFrame. This function is called by iFrame when it's load is complete. Here is the basic template.
Here is the sample template:
<script>
window.iframeCallback = function(message) {
// first clear the temp function we added to the window
// It is a bad practice to corrupt the global namespace
delete window.iframeCallback;
// you do your work here
};
</script>
..
..
<!-- iFrame should appear after the above script-->
<iframe/>
Is there anyway to set the title of a website via JS onload? I wrote this but I'm not sure where it's incorrect:
function my_code(){
document.title = "The new title goes here.";
}
window.onload=my_code();
The page title is static by the way.
Edit: The reason why I want to do it this way is because I'm writing a Safari Extension for a website that does not include tags so I wanted to insert one via JS.
You don't need to wait for the load event.
Just write document.title = ... anywhere.
If you want to change the title after the page loaded, you have to assign a function reference to onload (your function assigns the return value of my_code):
window.onload = my_code;
However, you most certainly can set the title without waiting for the load event.
I'm not familiar with Safari extensions, but you should also make sure that window actually refers to the page's window.
In my web application, the user can open a popup window to select an edit an object. When the user presses OK on the popup, it's supposed to update the src of an iframe in the parent window (and of course reload the iframe) according to which object was selected.
My function (in the parent window) is:
function dismissEditPopup(win, newId) {
newId = html_unescape(newId);
var elem_iframe = document.getElementById("iframe_id");
// (*) this line doesn't work
elem_iframe.src = '/view_object/' + newId;
elem_iframe.contentWindow.location.reload();
win.close();
}
This function is called from a popup window, which contains a script:
<script type="text/javascript">
opener.dismissEditPopup(window, "hash_of_new_object");
</script>
The problem is that the line (*) fails silently. In the inspector in both Firefox 3.6 and Google Chromium, I see that the src attribute of the iframe is being updated, but elem_iframe.contentWindow.location.href is unchanged. (If I add a line elem_iframe.contentWindow.location.href = elem_iframe.src;, the assignment is ignored.). There are no errors in the Javascript error console. Strangely, it does work as expected if I assign to elem_iframe.src from the Javascript console.
I am able to change the value of a hidden <input> field in the same way, using document.getElementById("hidden_id").value = newId;.
Everything is served from the same website.
(Similar to Changing iframe src with Javascript, but the answers to that question don't work, presumably because the code is called from a popup.)
Take this line out:
elem_iframe.contentWindow.location.reload();
It's reloading the iframe and the new src is not loaded.
I like YUI sandbox but I have a problem with it. Consider a document with an iframe (for instance ckedior that I included) with an initialization script. It is always executed before the outer document's sections (don't know why).
And I need to call a function, that is initialized in YUI sandbox in the parent document. But it can never be initialized, because the execution starts in the iframe.
var getWordCount;
AUI().ready('aui-node', 'console', function(A) {
getWordCount = function (htmlData) {
var target = A.one('div.my-png-image');
target.one('div:fist-child').set('text', strip(htmlData).trim().split(/\s+/).length);
};
});
Without yui sandbox I'd just declared a function in the parent document, and even tough the execution starts in the iframe, the global function would exist and could be called from the iframe.
The problem might be AUI.ready, as it executes only when the whole HTML is loaded. This means the iFrame would load before the browser triggers the .ready-event.
You could try to test this by changing the AUI event you use to trigger your code, and put the code you want to run before the iFrame-load outside the AUI.ready.
If you need a certain element in dOM to be loaded before running, you could try checking if the element is loaded and then run your script, like in this example.
Could you perhaps create the IFrame from within the AUI().ready?