Accessing an iFrame's dom from a Firefox Extension - javascript

I've spent a long time trying different things to get this to work but nothing does and documentation is not helping much.
I'm trying to populate a form inside an iframe that I dynamically inject into a page. To inject that iframe I do:
myObject.iframe = document.createElement("iframe");
myObject.iframe.setAttribute("src", data.url);
myObject.iframe.setAttribute("id","extension-iframe");
myObject.window.document.getElementById('publisher').appendChild(myObject.iframe);
myObject.iframe.addEventListener("load", function(){
myObject.populate(data);
}, false);
which works fine and DOES trigger the populate() method. My problem is getting the document or window objects for that iframe. I've tried all of the following:
myObject.iframe.window
myObject.iframe.document
myObject.iframe.content
but these are all undefined.
I also tried passing the event object to that iframe's load event listener and then doing:
event.originalTarget
But that didn't work either.
I am reading the following documentation:
https://developer.mozilla.org/En/Working_with_windows_in_chrome_code
https://developer.mozilla.org/en/Code_snippets/Interaction_between_privileged_and_non-privileged_pages
But either I'm not understanding it or it's just not properly explained.
Can anyone shed some light?
Thanks!

Have you tried using the contentWindow property?
var doc = iframe.contentWindow.document;

Try myObject.iframe.contentDocument
Something along the lines of this:
// For accessing browser window from sidebar code.
var mainWindow = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIWebNavigation)
.QueryInterface(Components.interfaces.nsIDocShellTreeItem)
.rootTreeItem
.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIDOMWindow);
var gBrowser = mainWindow.gBrowser;
var iframes = gBrowser.contentDocument.getElementsByTagName("iframe");
for (var i=0; i < iframes.length; i++) {
var check_elem = iframes[i].contentDocument.getElementById('myid');
if (check_elem) {
...;
}
}

I'm passing in the event object and then event.originalTarget (like you mentioned) and it's working fine. Although I had to set useCapture parameter of addEventListener to true in order to get my event called.
So if I understand correctly you need to access document in populate method...
I would pass event.originalTarget as a parameter to your method
or
in load event I would set for example myObject.document property and then use it in populate method.
myObject.iframe.addEventListener("load", function(event){
var doc = event.originalTarget;
myObject.populate(data,doc);
}, false);

I almost had the same problem. Using the following code gets me the iframe (Firebug is used for debugging):
iframes = window.content.document.getElementsByTagName('iframe')
for (var i = 0; i < iframes.length; i++) {
var elmInput = iframes[i];
Firebug.Console.log(elmInput);
}

Related

How to postmessage HTMLIFrameElement?

I'm having issue passing HTMLIFrameElement object from parent site to iframe (located on a different domain) using postMessage method.
This is my code that I already tried:
var frame = document.getElementById('myHTMLIFrameElement');
frame = JSON.parse(JSON.stringify(frame));
event.source.postMessage(frame, "*");
Unfortunately, JSON.parse/JSON.stringify does not seem to be the right way of handling HTMLIFrameElement object. Can you please advise how to pass through HTMLIFrameElement object correctly?
Parsing DOM elements as JSON does not do anything useful as far as I know.
Since postMessage() is part of the window object, you could try using the window object of the frame, which is found under the contentWindow property of the iframe.
So you could try something like:
var frame = document.getElementById('myHTMLIFrameElement');
frame.contentWindow.postMessage( "stuffYouWantToSendToTheIframe", '*' );
And then in the script inside the iframe:
window.addEventListener('message', function( event ) {
// handle message
});

Issue communication with postMessage from parent to child iFrame

I'm having an issue communicating from my parent window to the child iFrame. But in the other side, everything works perfectly.
Here is how I get the chil iFrame object in order to fire the postMessage function:
var iFrame = document.getElementById('Frame').contentWindow;
When I print it int he console, I get the following:
Window {parent: Window, opener: null, top: Window, length: 0, frames: Window…}
When I proceed to the postMessage function as follows:
iFrame.postMessage("message", "http://contoso.com");
It shows me an error when loading the page: iFrame.postMessage is not a function.
When I execute the postMessage in console, I get an undefined
What am I doing wrong ?
try this
var iFrame = document.getElementById('Frame');
iFrame.contentWindow.postMessage("message", "http://contoso.com");
I had this problem too. I found solution from this website https://www.viget.com/articles/using-javascript-postmessage-to-talk-to-iframes
I wasn't able to get this working using a querySelector approach.
What worked for me was the following. I'll refer to the two webpages as the parent that has an iframe on it and the src as the page inside the iframe.
On the src page, I post a message, with the parent url as the origin:
// src
window.parent.postMessage({
type: "connect",
url: window.location.href
}, "http://iframeparent.dev", );
Then in the parent page, I listen for this. It will have a property called source which is the iframe in question. This property can be posted to.
// parent
window.addEventListener("message", (event) => {
// this is the magic connection:
event.source;
}, false);
So you could do something like:
// parent
let sources = [];
window.addEventListener("message", (event) => {
sources.push(event.source);
}, false);
function something() {
sources.forEach(source => {
source.postMessage({some: "data"}, "http://iframesrc.dev")
})
}
Below code also works.
$('#id')[0].contentWindow.postMessage("hello world",targetOrigin);
There is a difference between jQuery selector and document.getElementById.
Document.getElementByID returns HTML DOM object.
jQuery selector returns jQuery object.
For more information please find below link.
document.getElementById vs jQuery $()

Calling url assigned in a var

While playing around with Raphael.js Australia map, I tried assigning URLs for each element by changing their attribute in the end of the path:
country.cityone = R.path("coordinates").attr({href: "cityone.html"}).attr(attr);
country.citytwo = R.path("coordinates").attr({href: "citytwo.html"}).attr(attr);
...
The above works with Firefox, Chrome etc, but IE6-IE9 have trouble with that declaration.
So I thought of declaring another variable after var country and assigning the urls to that:
var url = {};
url.cityone = "cityone.html";
url.citytwo = "citytwo.html";
then calling it on mouse click/down:
st[0].onmousedown = function() {
current && country[current] && document.getElementById(“current”).appendChild(url);
};
However it won't work at all. Apparently I'm not making the call properly from the function, to relate each URL to its respective city. What am I missing?
I haven't tested this but I'm pretty sure you should just do away with the href and add a mouse event:
country.cityone = R.path("coordinates").attr(attr).click(function(){
window.location.href = "cityone.html";
});
I'm pretty sure that will work.
Just to close this question, after several trials, I ended up finding out that IE requires a double-click on click(function(){ for the href page to open up
I found out that in the above code:
country.cityone = R.path("coordinates").attr(attr).click(function(){
window.location.href = "cityone.html";
});
I had to change the .click(function(){ into .mousedown(function(){ for IE to work as it should.
Thank you #Zevan!
Cheers

Under Chrome - Mootools inject fails with null element

I have this weird problem on Chrome - on my page I am injecting elements using Mootools specifically a lightbox that contains a jwplayer video. The problem on chrome is that referring to an element ie. $('grid_01'); returns null the second time I click on it. To get around this I'm trying to test the element is null and re-inject it
var ss = $('holderdiv');
var x = $('mb_inline_0_-1');
if(x == null)
{
var el = new Element("div", {id: "mb_inline_0_-1"});
//if this line below runs without error...
ss.inject(el);
}
//.........why would x2 be null?
var x2 = $('mb_inline_0_-1');
Chrome says its null. Is there something I can do to ensure the DOM is updated ?
Thanks
You mean to use grab, not inject.
ss.grab(el); // Or el.inject(ss);
Your code has ss being injected into el, which is never attached to the DOM.
Injecting a newly created Element is written in the format newElement.inject(existingElement, position);.
So in your case, if you are planning to inject the newly created div (contained in el) into $('holderdiv'), it should be done thusly:
var el = new Element('div', {
. . .
});
el.inject('holderdiv', 'bottom'); // Although 'bottom' is assumed if nothing is passed

Accessing contents of NativeWindow in a HTML AIR application?

I'm currently building a HTML/JS AIR application. The application needs to display to the user a different 'window' - dependant on whether this is the first time they've launched the application or not. This part is actually fine and I have the code below to do that:
if(!startUp()) { // this simply returns a boolean from a local preferences database that gets shipped with the .air
// do first time stuff
var windowOptions = new air.NativeWindowInitOptions();
windowOptions.systemChrome = 'none';
windowOptions.type = 'lightweight';
windowOptions.transparent = 'true';
windowOptions.resizable = 'false';
var windowBounds = new air.Rectangle(300, 300, 596, 490);
var newHtmlLoader = air.HTMLLoader.createRootWindow(true, windowOptions, true, windowBounds);
newHtmlLoader.load(new air.URLRequest('cover.html'));
}
else {
// display default window
// just set nativeWindow.visible = true (loaded from application.xml)
}
However, what I want to be able to do is manipulate the html content from within cover.html after it has loaded up. There seems to be plenty of tutorials online of how to move, resize, etc. the NativeWindow, but I simply want access to the NativeWindow's HTML content.
For example, how would I add a new paragraph to that page? I've tried the following:
newHtmlLoader.window.opener = window;
var doc = newHtmlLoader.window.opener.document.documentElement;
Using AIR's Introspector console, ....log(doc) returns [object HTMLHtmlElement].
Hmm, seems promising right? I then go on to try:
var p = document.createElement('p');
var t = document.createTextNode('Insert Me');
p.appendChild(t);
doc.appendChild(p);
...but nothing gets inserted. I've also tried the following replacements for doc:
var doc = newHtmlLoader.window.opener.document.body; // .log(doc) -> [object HTMLBodyElement]
var doc = newHtmlLoader.window.opener.document; // .log(doc) -> Error: HIERARCHY_REQUEST_ERR: DOM Exception 3
...as well as the following with jQuery:
$(doc).append('<p>Insert Me</p>'); // again, nothing
So, anyone had any experience in accessing a NativeWindow's inner content programmatically? Any help will be greatly appreciated.
Hmm, so I think I may have found out how to do it...If we amend the original code and add an event listener on the loader:
var newHtmlLoader = air.HTMLLoader.createRootWindow(true, windowOptions, true, windowBounds);
newHtmlLoader.addEventListener(air.Event.COMPLETE, doEventComplete);
newHtmlLoader.load(new air.URLRequest('cover.html'));
You can then interact (assuming you're using jQuery) with the contents of the newly created window by using:
function doEventComplete(event) {
doc = $(event.currentTarget.window.document.body);
doc.append('<p>Insert Me!</p>')
}
:)
I'm not sure this has the effect you intended:
newHtmlLoader.window.opener = window;
var doc = newHtmlLoader.window.opener.document.documentElement;
What is does is set var doc = window.document.documentElement;, so 'doc' is your local document, not the one in the other window.
I think what you want is
var doc = newHtmlLoader.window.document.documentElement;
Do note that this will not work until the document has loaded.

Categories

Resources