Friday, January 27, 2006

Implementing page transitions in Firefox using AJAX and CSS

Page is a feature in IE which allows you to add visual effects on your site using filters when a user enters or exits a page, the problem is that filters are IE-only. What if you want to add same transitions on your site for users who are visiting on Fx? You can emulate some filters of IE by using and CSS on to achieve the same results, here is a simple way to achieve fade-in transition in Fx for page exit:
Instead of redirecting user to second page directly (using links or JS:location.href), retrieve the second page contents using XmlHttpRequest, once the httpRequest has retrieved the contents of page 2, add a timeout function where in you reduce the opacity of the page by steps. Once the opacity falls below a certain value, do a document.write of page 2's response text. Here is the piece of JS code:

var xmlhttp;
var timerId = 0;
var op = 1;
function getPageFx()
{
url = "/transpage2.html";
if (window.XMLHttpRequest)
{
xmlhttp=new XMLHttpRequest()
xmlhttp.onreadystatechange=xmlhttpChange
xmlhttp.open("GET",url,true)
xmlhttp.send(null)
}
else
getPageIE();
}

function xmlhttpChange()
{
// if xmlhttp shows "loaded"
if (xmlhttp.readyState==4)
{
// if "OK"
if (xmlhttp.status==200)
{
if(timerId!=0)
window.clearTimeout(timerId);
timerId = window.setTimeout("trans();",100);
}
else
{
alert(xmlhttp.status)
}
}
}

function trans(){
op -= .1;
document.body.style.opacity = op;
if(op<.4){ window.clearTimeout(timerId); timerId = 0; document.body.style.opacity = 1; document.open(); document.write(xmlhttp.responseText); document.close(); return; } timerId = window.setTimeout("trans();",100); } function getPageIE(){ window.location.href = "transpage2.html"; }

You can see this code in action here.

16 comments:

  1. edsterb,
    Take a look at the e.g. link that I've given in the post and do a view-source, the code in the blogger tends to be messy due to formatting issues and hence difficult to understand :).
    Now to the bit about applying transitions every time someone leaves your page, could be handled by just reducing the opacity of the page (you don't need AJAX in that case) step by step in the onbodyunload() function of the body. Let me know if that works or else I'll try to put some e.g. demonstrating this technique.

    ReplyDelete
  2. My bad in comment #2, wrote it before trying it. I was thinking that hooking onbeforeunload function would do the trick but forgot that onbeforeunload function would have the unwanted side-effect of showing the "Do you want to navigate away from this page?" confirmation. So the only way to implement transitions on your page would be to hook your own links and buttons which take user to the other page on your site. This can be implemented as part of a centralized js function which takes the url to navigate to and uses Ajax to retrieve the content of hte next page and reduces opacity gradually (Ajax is needed to provide smooth page navigation and avoid the flickering when user navigates from page 1 to page 2).
    In my free time I will write & post the reusable js function.

    PS: The e.g. site is down (it was deleted for CPU overuse!), well you can't complain much if you're using a free host.

    ReplyDelete
  3. Handy! Used your idea to implement a fading-in title on my website. Cheers!

    ReplyDelete
  4. Is it also possible to use your code to fade in the next page instead of fading out the current page ?

    Greetings,

    Rees

    ReplyDelete
  5. Rees,

    There are two issues with fading after the page has loaded; the fade-out would have to be done by a js function which has to be part of the called page (as the callee page's js would not be available after doing a document.write); and even if you copy the js functions to both the pages, I am not sure if the js would be loaded by then.

    ReplyDelete
  6. Your code is flawed in several places.

    For a start, detecting for non-IE by checking if there is a native XMLHTTPREQUEST object will allow IE7 to pass by (it has it as a native object). You seem to think it's totally sensible to set intervals by putting the functions (called without params) inside "" quotes. This is inefficient and requires the browser to eval the string, you do not cover for the possibility of a 404, you use a global variable for the xmlhttp request object when you don't need to, you are using a functionality developed for xml to pick up html. In fact I could continue to list the faults in what is a very small piece of code.

    I advice nobody to use this code, it's very very poor. Sorry Sachin, but suggesting people use this is tantamount folly.

    Ric.

    ReplyDelete
  7. Ric,

    Your comments taken in good spirit. Below are my answers:
    a)"detecting for non-IE by checking if there is a native XMLHTTPREQUEST object will allow IE7 to pass by (it has it as a native object)."
    This code is not to show, how you detect a browser; there are tons of ex./libraries on the web just for that. Heck, this doesn't even check for other browsers like Opera, Safari et al (even though the code says it's only meant for Fx).
    b) "You seem to think it's totally sensible to set intervals by putting the functions (called without params) inside "" quotes. This is inefficient and requires the browser to eval the string, you do not cover for the possibility of a 404, you use a global variable for the xmlhttp request object when you don't need to."
    These are all coding practices (and being OT in general); I will delve on that later (see d).
    c) "you are using a functionality developed for xml to pick up html."
    This is a matter of perception, going by your logic, JSON should be banned!
    d) "Sorry Sachin, but suggesting people use this is tantamount folly."
    First of all, I nowhere have suggested that this piece of code will solve the earth's problem and we all will live happily, ever after. This is just an extension of a simple concept, applied to a page on the whole. I don't expect people to use this code as-is, this is just a POC to show that you can achieve some sorta transitions in Fx. Even the urls in the js functions are hard-coded; which further iterates my point about it being just a POC.

    HTH,
    S

    ReplyDelete
  8. also works in Safari 3.0.4. Thanks. :)

    ReplyDelete
  9. Hi Sachin,

    I've been looking all over the internet for this method, but apparently the document is down and all that is left is your JS code. Is there any chance you could make the whole code public? I'd really appreciate it!

    Thanks!

    ReplyDelete
  10. Ram,
    sorry for the delay in comment moderation, it was lost somewhere in the queue. The e.g. link should be live now, let me know if it doesn't work for you.

    ReplyDelete
  11. Hi Sachin, the link to your example page seems to be dead. I'd love to see the script in action.

    ReplyDelete
  12. Unfortunately, that's one of the issue with hosting on a free host (heck even my google maps mashup is dead); they just keep on deleting my site for CPU overuse & I keep on re-registering with the same name but this time looks like somebody beat me to it :(. I will try to see if I can get this example up somewhere else.

    ReplyDelete
  13. where can i put this code?

    ReplyDelete
  14. hello, I didn't understand about "where do I put this code?". The example code is live back at the link provided in the blog; you can take a look & let me know if you still have questions.

    S

    ReplyDelete
  15. This comment has been removed by a blog administrator.

    ReplyDelete
  16. This is (mostly) what I was looking for.
    I'm building a presentation that runs locally on Apache2 server.
    The Ubuntu OS default browser is Firefox.
    The presentation uses a dark background image with light color text on top.
    When I use the code as written, the page actually gets lighter (not darker).
    I need a Firefox transition that will darken the type and other html code to black before the transition.
    The same dark (mostly black) background image will be used throughout the presentation as the background.
    How do I adjust the code so that the type disappears into the black picture before the next page displays?

    ReplyDelete