Animate this …

Fri, 20th Jun, '08

In a javascript world ruled by prototype and scriptaculous, all visual effects & animations in web pages are effected by them. But DIY still means Do-It-Yourself. Lets waste no time smelling the perfume and cut to the flesh …

function animateThis(fxargs, fxtp)
{
var fxargsstr = ”, argseparator = ”;
var fxname = fxargs.callee.toString();
fxname = fxname.substr(‘function ‘.length);
fxname = fxname.substr(0, fxname.indexOf(‘(‘));
for(var i = 0; i < fxargs.length; i++)
{
fxargsstr = fxargsstr + argseparator + “‘” + fxargs[i] + “‘”;
argseparator = ‘,’;
}
fnstr = fxname +'(‘+fxargsstr+’)’;
setTimeout(fnstr, fxtp);
}

What is that?? Hmmm … I guess I am seeing settimeout on steroids. Put:

animateThis(arguments, <a span of your choice measured in milliseconds>);

in a function body and that function gets called every that many milliseconds with the exact argument set supplied to it as was supplied when the function was first called. So a Fade-In function in javascript using this function would look like this:

function fadeIn(elementID)
{
var el = document.getElementById(elementID);
var opac = el.style.opacity; //read the current opacity value of the target element
if(opac < 1) //if not reached full opacity
{
opac = parseFloat(opac) + 0.05; //increase the current opacity value
el.style.opacity = opac.toString();
animateThis(arguments, 20); //call this function every 20 milliseconds
}
}

and just call this on a div with opacity set as 0 and an ID of lets say ‘testdiv’, with something like:

<a href=’#’ onclick=”javascript:fadeIn(‘testdiv’);”>bring in</a>

and see the div come into view. Geekness.

The example will only work on Firefox but the function animateThis() has been tested on FireFox 2-3, IE 6-7, Safari, Opera. In case you find some issue, tell me and I will have things set right.

And yeah, CS students, this is not recursion. This is a timer.


Prettifying the address bar is a last stop in the modern day Internet. It is always this way:

Good: http://www.whatasite.com/dude/djjo/music

Bad: http://www.whatasite.com/user.php?cat=dude&profile=djjo&page=music

The name here is search-friendly urls, although how search friendly they have been, nobody knows[SEO people ‘can’ tell], but they certainly are friendly to users, among other things. So if your question is “how to make search friendly urls or urls without question marks and full stops”, here is how I do it.

This article is based on the Apache server platform. If you are running Windows, you might try installing WAMP or XAMPP to get Apache. Once you have this running open up httpd.conf in your pink-n-blue text editor and look for something like this:

#LoadModule rewrite_module modules/mod_rewrite.so

If you can’t see the ‘#’ prefix to the rest of the line, you are lucky, or else remove the ‘#’ from the front[uncommenting the command] and restart Apache.

Once this has been done, to check if you are ready to begin and that mod_rewrite is really active, create a file in your web root directory, lets say test.txt with some text in it. And now over to doing the magic. Locate the .htaccess file in your webroot and again get your pink-n-yeahyeah editor and add the following lines:

RewriteEngine On
RewriteRule ^magic\.txt$ test.txt

Now try to get magic.txt in your browser and you will definitely see some magic txt. What you will see is the contents of test.txt, as if you asked for test.txt, which is what you did. Lets explain the above two lines to ourselves. URL Prettifying needs a little bit of knowledge of Regular Expressions. You can learn about regular expressions here, here & here. The first line sets the RewriteEngine rolling and the second line is a rewrite rule. The first part of the rule:

^magic\.txt$
^ = the beginning
\. = look for the character ‘.’. A plain ‘.’ in a regex means any non-whitespace character.
$ = and this is the end

The second part is the name of the file or the new url which is sent to the server instead of the first part. So in our case, asking for ‘magic.txt’ will get you test.txt. So basically a RewriteRule is of the form:

RewriteRule <what the browser asks> <what you serve>

Please note that, all rules should come after the ‘RewriteEngine On‘ directive, and unless this line is found, not a single rule will be interpreted it. And now for a funnier version, try this rule instead of the earlier one:

RewriteRule ^magic\.txt$ http://www.google.com

So before you get ideas, let me finish what we begun here. Lets say we have a website that generates a URL like this one to go to an album page:

http://www.whatasite.com/album.php?user=djjo&page=7

Now as cumbersome that is to remember, and search engines are known to run for cover on seeing such pages as these dynamic pages are known to be pointing towards itself and doing such round and closed references thus taking an awful lot of time of the search crawler. Bad. We want the crawler to see this, for which we need to make it look like regular html pages with no scary or ‘special’ characters:

http://www.whatasite.com/album/djjo/7

And the rule to do the above is:

RewriteRule ^album/([a-z]+)/([0-9]+)$ album.php?user=$1&page=$2

Just a gentle reminder, that these rules are to be written in a file named .htaccess lying in your web root(typically named ‘www’) directory. Now onto simplifying the above rule:

^album/([a-z]+)/([0-9]+)$

^, from the start match the string ‘album’ followed by the first slash

([a-z]+), after the first slash, look for a group of characters[the characters allowed are from ‘a’ to ‘z’ and ‘+’ sign means ‘one or more’], which we know to be the user name. A group enclosed in brackets is considered as a variable. Since this is the first group[the username], it will be called $1. We will use this in the second part of the rule.

/([0-9]+)$, and after the second slash, look for another group of numerals from 0 to 9, and one number or more. And as this is the second group[the page number], this is $2. The final $ at the end of the expression means we end the first part here, so its like a terminator.

album.php?user=$1&page=$2

We have $1[username] & $2[page number] from the first part of our rule. So we will substitute these values to our URL as they earlier were supplied, which make the second part quite easily look like what we have here.
I guess that pretty much does the job here. And oh yeah, if your user name has numerals in it[alongwith alphabets], just use something like this [a-z0-9]+ instead of [a-z]+. A range of uses of url rewriting have been written about here. Should you have any queries or doubts or clarifications to make, just leave a comment and I will be good enough to notice it.


You have a search page and as the results end you show a navigation bar with links to the other pages of the search. So boring. Seriously. This is the Web, and I am still turning pages.

And I think I am Pied Piper who will save you from this hell. The uber-cool solution is, detect as soon as a user is about to reach the end of the page and get new content[the second page of the search], just in time. Setting out, we need:

The height of the current document. So to this end, we will place a div with a decided upon ID at the end of the page. And all the content in the body will be loaded in another div just above this last div. We are detecting the document height by detecting where this ending div is located, pixel-wise, with this:

pageend = document.getElementById(‘laststop’).offsetTop;

So clearly, the ID of the last div is ‘laststop’. Next we need the screen resolution of the client window to find out how much of the document is visible right now. We do:

winheight = (typeof window.innerHeight != ‘undefined’ ? window.innerHeight : document.body.offsetHeight);

Now having this much, we need to detect when does the user scroll the page to the bottom. The following lines will give exactly how many pixels from the top have you scrolled to. Note that, this is the ‘height’ from the top of the document to the top of the visible area. The real end of the document is obtained by adding this ‘height’ and the window height retrieved earlier.

if(navigator.appName == “Microsoft Internet Explorer”)
alert(document.body.scrollTop);
else
alert(window.pageYOffset);

But these lines need to be run every few seconds to check as soon as as the user reaches the end of the current page. So we will do a setInterval() in the onload event of the body to do so. And keep the interval time to something a little over 2 seconds and nothing less than that, you of course don’t want your user’s browser to hang on them. It is annoying.

Said and done, this is what you end up with, demofile.php, annotated with explanatory comments:

<html>
<head>
<title>Page End Reached Detection Demo</title>
<script type=”text/javascript”>
var oRequest;
var pageend, winheight;
var howoften = 2000;
// this value implies that function howlow() will keep checking every
// 2000 milliseconds(2 seconds) to find out how low is the user on the page

var bufferHeight = 300;
// adjust bufferHeight, to take action as soon as the user is within these
// many pixels of the end of the page, so a larger buffer makes sure the user doesn’t
// see the dynamic page content loading. In this example, the script will fetch content
// as soon as you are within 200 pixels of the end of the page

// ooooo, ajax. ooooooo …
if(window.XMLHttpRequest)
oRequest = new XMLHttpRequest();
else if(window.ActiveXObject)
oRequest = new ActiveXObject(“Microsoft.XMLHTTP”);

function sendAReq()
// a generic function to send away any data to the server
// specifically ‘morecontent.php’ in this case, to get more content from the server
// all content fetched will be handled by showcontent()
{
oRequest.open(“POST”, “morecontent.php”, true);
oRequest.setRequestHeader(“Content-Type”, “application/x-www-form-urlencoded”);
oRequest.onreadystatechange = showcontent;
oRequest.send(null);
}

function showcontent()
{
if(oRequest.readyState == 4)
{
// now all the data that comes adds to the end of the page, specifically
// to the container div referenced with the ID ‘bodycontent’
if(oRequest.status == 200)
document.getElementById(‘bodycontent’).innerHTML = document.getElementById(‘bodycontent’).innerHTML + oRequest.responseText;
else
alert(‘No Response from Server. Try Again Later.’);
}
}

function calcParams()
{
// calculate the end coordinates of the page and the visibile height of a page
// at any time on the client’s desktop
pageend = document.getElementById(‘laststop’).offsetTop;
winheight = (typeof window.innerHeight != ‘undefined’ ? window.innerHeight : document.body.offsetHeight);
}

function isitend(curpos)
{
calcParams();
if((curpos + winheight + bufferHeight) > pageend)
{
alert(‘you are reaching the end of the page;’);
sendAReq();
}
else
{
alert(‘keep going’);
}
}

function howlow()
{
if(navigator.appName == “Microsoft Internet Explorer”)
isitend(document.body.scrollTop);
else
isitend(window.pageYOffset);
}
</script>
</head>

<body onload=”javascript:setInterval(‘howlow()’,howoften);”>
<div id=’bodycontent’>
<?php
for($index=0; $index<200; $index++)
echo ‘Line:’.$index.'<br>’;
?>
</div>
<div id=’laststop’/>
</body>
</html>

Oh and yeah, this sends a request using the XMLHttp object so we need another php file at the server to catch the request and send in additional content. This additional content will be appended to the div with ID ‘bodycontent’. So here is morecontent.php

<?php
for($index = 0; $index < 100; $index++)
echo ‘We Are New Lines:’.$index.'<br>’;
?>

That’s about it. Please do throw in your experiences with this in the comments section below and I will surely respond. I am jobless. 🙂