Firefox - replacing the whole page by the new one in Ajax response

E

evgenyg

Hello !

We have the following situation - when Ajax request is sent what's
being returned by the server is usually an XML (which is used for DOM
updates) but sometimes it's HTML which is a whole new page that should
replace an existing one. I.e when we issue an Ajax request we don't
know what will be returned and analyze the response to act accordingly.

Now, the way to replace the current document with a new one used to be
easy and portable for both browsers (we're only supporting IE6 and
Firefox 1.5):

document.open();
document.write( head );
document.write( body );
document.close();

where "head" and "body" are two parts of the result HTML. We had to cut
it to two (rather than going simply with document.write( NewHTML ))
because of IE - our head section contains references to external
JavaScript files (<script type="text/javascript"
src="sth.js"></script>) and IE only loads them when document.write()
call ends. So if body contains any script block (<script
type="text/javascript"> .. </script>) using any of JS referenced by
head - IE would fail with something like "Resource undefined" if we
push the whole new HTMl in one go by using document.write( NewHTML ).
But it worked perfectly fine in Firefox, meaning

document.open();
document.write( NewHTML );
document.close();

did the job just fine. What's even more important - it also evaluated
all JavaScripts correctly - both in external files referenced by the
head and in the JS blocks embedded in the body.

Until Firefox 1.5.0.6/7 where things stopped working completely - our
lovely and used-to-be portable code

document.open();
document.write( head );
document.write( body );
document.close();

caused Firefox to loose all CSS/JS and display an HTML only page (as if
CSS/JS were disabled). Removing document.close(); improved the
situation a bit by displaying the page with CSS this time but still -
*no* JavaScript was evaluated (meaning, JavaScript blocks embedded in
the document's body were not evaluated).

I took a different path from this point by pushing the new content to
document's head and body "innerHTML". It worked but not for JS
evaluation - I had to do that manually. To evaluate the JS referenced
in the head section of the document - I've traversed the head's DOM
tree while looking for the "script" nodes, then downloaded all of them
one by one using a synchronous Ajax calls (don't laugh!) and eval()-ed
the response. To evaluate JS blocks embedded in the body of the
document - I've traversed the body's DOM tree while looking for the
"script" nodes and eval()-ed them.

The problem is following: eval()-ing external JS files after
downloading them with Ajax doesn't work in 100% of cases - some
statements using Prototype functions fail to execute ("prototype.js" is
one of external JS files referenced in the head). Anyway, I'm almost
sure that what I'm doing is plain wrong, i.e it's sounds silly to
download all JS files referenced in the head and eval() them !

So how do I fix it ? Simply put - how do I replce the content of the
document to the completely new one received as a response to
asynchronous Ajax call ? The new content conatins doctype, head, body -
it's a completely new page. And all JS referenced in the head and
embedded in the body should be evaluated as well.

I really wish

document.open();
document.write( head );
document.write( body );
document.close();

was working in Firefox as before. Is it simply a Firefox bug, should I
submit it ?
Btw, document.open.write.write.close() works just fine in IE6.


Will be *very* grateful to hear any advise, thanks you all !
 
B

Bernard

I would do the following if the result of the request is a full page:

1) If it is NOT known that the response is a full page when the
request is made, then the server returns a URL for the full page, and
the script takes it and loads it (window.location=url). This is of
course a two stage process.

2) If the result of the request would be full page, and this is known
when the request is made, then the browser requests the full page
(again via window.location=url) instead.

If you don't like 1) and 2), then use this:

3) Use a frameset where all your control logic remains persistent in
the top level.

4) Use a 100% size iframe to load your content into.

I know that all the above things do work.

In contrast, what you are doing does not appear to be generally
supported, and the fact that it works under some conditions may be
enticing but I guess it has significant risks. I would not even try
this as it looks to me as if you were pulling the rug from under your
own feet.

Regards

Bernard
 
T

Tim Williams

Hello !

We have the following situation - when Ajax request is sent what's
being returned by the server is usually an XML (which is used for DOM
updates) but sometimes it's HTML which is a whole new page that should
replace an existing one. I.e when we issue an Ajax request we don't
know what will be returned and analyze the response to act accordingly.

Why not just have your server send back a "redirect" message in your Ajax
response instead of the full HTML page, and use your client-side code to
navigate to the "new" page (which could then be supplied by your server in
the "normal" fashion) ?

Tim
 
M

Martin Honnen

(e-mail address removed) wrote:


Until Firefox 1.5.0.6/7 where things stopped working completely - our
lovely and used-to-be portable code

document.open();
document.write( head );
document.write( body );
document.close();

caused Firefox to loose all CSS/JS and display an HTML only page (as if
CSS/JS were disabled).
Is it simply a Firefox bug, should I
submit it ?


Well you have to provide evidence of that problem if you want someone to
fix it. A simple test case
<http://home.arcor.de/martin.honnen/javascript/2006/09/test2006092401.html>
doing document.open(), two document.write(), document.close() does not
show any CSS or JavaScript failure for me here with Mozilla/5.0
(Windows; U; Windows NT 5.1; en-US; rv:1.8.0.7) Gecko/20060909
Firefox/1.5.0.7.

As for the whole approach, as already suggested simply sending a URL if
you want to load a complete HTML document and then doing
window.location.href = url;
is a much better approach.
 
E

evgenyg

Many thank's for your responses !

1) using window.location.href

I understand that's the most straightforward approach but let me
explain why it's not accessible out-of-the box for us. Our server-side
technology is JSF (Java Server Faces) and in JSF there's no one-to-one
mapping between a URL and corresponding content (meaning same URL may
return different content, according to the previous state). In JSF
navigation rules are specified on the server-side and not on the page
itself, like it's usually done with "href" of links and "action" of
forms. For example, when one requests
http://host/applicarion/sample.jsf and view the source - all "action"
attributes of all the forms on the page are targeted to the page itself
(http://host/applicarion/sample.jsf) so when any form is submitted -
you're "kind of" requesting the same page but when request is processed
on the serfer side and navigation rules are applied (according to
faces-config.xml residing on the server) - the corresponding content is
sent back. It may be the same page (if navigation rules say so) or a
new page - one really doesn't know until response comes back.

So for my situation I can't just return a URL of the new page from the
server as it's out of my control - JSF engine provides us with response
to send back to the browser. But you, guys, still got me thinking that
may be I can hold the whole response (whatever page it is coming from,
I simply don't know that) using in-memory buffer and generate a unique
URL for it and still redirect the browser to this unique URL (using
window.location) which will flush in-memory buffer to response .. So
far this seems to be the way according to your responses.

2) Using frames

I'm not sure. I mean, our Ajax support for JSF applications is
home-made and one of it's strengths is that any JSF application is made
Ajax-capable (all forms are submitted by Ajax and according to the
response the DOM is either updated or re-written completely, as was
described in my first post) without modifying any page or requesting
any special markup. But I'll surely keep that in mind !

3) Proving *there is* a problem in Firefox

I would be glad if that was the case as document.open()/write()/close()
is obviously the easiest way to implement document replace. So I wanted
to hear what would people say - does it seem logical to them that it
should work or we shouldn't rely on this behavior. So far nobody seems
100% convinced that it should work. But I'll try providing a simple
use-case demonstrating how it breaks and will post it here and to
Mozilla forum as well. Who knows - may be someone from Firefox team
will respond "It's a bug which will be fixed in the next version" and
then we'll simply go back to the old way with
document.open()/write()/close(). As for the reason why it does work for
someone else and doesn't work for us - I guess external JavaScript
files we're using may have something to do with that (we have
Prototype, script.aculo.us and then some ..)

Ok, again, thank's a lot for your ideas, guys. I'll be working on 1)
and 3) and will let you know as soon as possible. But till then - any
new ideas are still welcome, of course !
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,767
Messages
2,569,572
Members
45,045
Latest member
DRCM

Latest Threads

Top