views:

1698

answers:

2

So - I have a page which contains a textarea and a dynamically created IFrame which displays a PDF using the adobe acrobat plugin.

Initially the textarea is focused.

I want the textarea to be focused, but the IFrame steals focus when the pdf is loaded.

In firefox it is trivial to reset the textarea as the focused element.

I do this by listening to the iframes "load" event and then calling .focus() on the textbox.

M$ IE doesnt fire the onload event for dynamically created Iframes, so to determine when its ready I use the readyState property of the IFrame:

var ieIframeReadyHandler = function() { 
    if( iframe.readyState=="complete" ) {
           textarea.focus();
    } else {
        setTimeout(ieIframeReadyHandler, 100);
    }
}


setTimeout(ieIframeReadyHandler, 100);

Note: I dont listen to the readystatechanged event of the iframe since it doesnt seem to fire for the readyState=="complete" case!!

So what happens when this code executes?..... Well nothing. The Iframe pdf is still focused, however if I check which element has focus using document.activeElement (previously this was IE only, howvever firefox 3 now supports this) I am informed that the textarea DOES have focus!!

What the hell??!?

Any ideas?

+1  A: 

Try to delay setting focus by 200-500 msec. It's quite common IE issue.

EDIT:

Use onLoad event in IFRAME:

<body onLoad="parent.window.check_focus()"> .... </body>
Thevs
The IFrame will contain only the PDF content, not HTML. So, you'll not be able to hook up the body's onload event.
Kirtan
@Kirtan: It's better to incorporate it into <body> element. Read comments on the next answer.
Thevs
A: 

In Internet Explorer, the iframe's readystate property only updates within the iframe, not outside of it. It's by design, for whatever reason. There's no reliable way, from outside the iframe, to determine whether the iframe contents have loaded.

If it's not critical that the iframe be displayed immediately on page load, you could simply wait to load it until the user requests it (via a link or button). That way they're expecting it.

Another alternative if the PDFs are hosted locally (or you don't mind doing some caching) is to use Flash and a tool like PDF2SWF from SWFTools to do a conversion on the back-end.

Steven Richards
I used iframes in pre-AJAX times, and there's absolutely no problem to set handler for iframe's onLoad event from whatever other window (using 'parent' property). F.e:<body onLoad="parent.window.check_load()" ...
Thevs
Setting onLoad for the body element of an HTML doc within an iframe is not the same as setting it for the iframe itself. Unless I'm misunderstanding you? In the case of ListenToRick's problem, the content within the iframe is a PDF, thus there's no body element to set an event on.
Steven Richards
the readyState property does change and is accessible by the parent js - i have demonstrated this above!
ListenToRick
So I am able to successfully call .focus on the textbox when the iframe is in a readyState="complete" state and as I mentioned above, the parent page does actually believe the textbox is the focused element for the parent page. Perhaps the parent page itself isnt focused?
ListenToRick
The problem in this case is that readystate is wrong. Try loading a large PDF (50mb or so). The readystate of the iframe will be set to 'complete' in less than a second, but the PDF has not finished loading yet! The order of events seems to be: 1) Plugin loaded (readystate is 'complete'), 2) Plugin finishes downloading first page (focus on iframe is set), 3) Plugin continues downloading rest of document. If you set focus between 1 and 2, it will be lost again immediately in most cases. If you use a longer delay as Thevs indicated, it will work correctly provided the plugin is loaded in time.
Steven Richards
What's about reading PDF into prepared <body> element of that IFRAME? I think onLoad event should do a trick in this case (i.e. to fire _after_ whole PDF document load).
Thevs
@Thevs: you mean in an <embed> tag, or a second iframe?
Steven Richards
I'm not sure you can use events on <embed> tag, but that could be a solution. Also you can use src attribute on iframe's <body> tag. I've even seen using <img src=... loading PDFs by changing mime type and preloaded with new Image().
Thevs
Also, you may consider using hidden <div> with <embed> instead of using IFRAME. Then it would be no problems at all with keeping focus.
Thevs
Yeah, I'm pretty sure most events don't work well on <embed> tags. Hiding a <div> and <embed> might work like you said. In any case, not to sound like a broken record, but I think using a SWF solution would be much more reliable and not much more work, assuming the PDFs are hosted locally. Scribd's API could also do the trick.
Steven Richards
Nicely played with votes. Keep going.
Thevs
@Thevs: 'nicely played with votes' - what votes?
Steven Richards