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. 🙂

Advertisements


So … here’s the real deal into measuring how much time a user spends on each individual page by url, and measured in milliseconds.

[1] As soon as page loads, set the current time in a variable in javascript with the help of the onload event. Let this variable be called tstart.

[2] On the unload event, get the current timestamp, and subtract from this the starting timestamp, the first one. So tTotal = tend – tstart.

[3] Now send this time information alongwith location.href to your server, which will record this in a log file, or database to use later, maybe to serve relevant content by keeping in mind a users viewing and browsing patterns.You get the picture right.

So here are the files. Just store monitorme.html & logtimefile.php somewhere on your server and create a writeable file in the same directory named as timelog.txt. Now get monitorme.html and now refresh your page, navigate away to some other page or just plain close the window to find your timelog.txt file piling up with times you spent on the page.

monitorme.html

<html>
<head>
<title>Duration Logging Demo</title>
<script type=”text/javascript”>
var oRequest;
var tstart = new Date();

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

function sendAReq(sendStr)
// a generic function to send away any data to the server
// specifically ‘logtimefile.php’ in this case
{
oRequest.open(“POST”, “logtimefile.php”, true); //this is where the stuff is going
oRequest.setRequestHeader(“Content-Type”, “application/x-www-form-urlencoded”);
oRequest.send(sendStr);
}

function calcTime()
{
var tend = new Date();
var totTime = (tend.getTime() – tstart.getTime())/1000;
msg = “[URL:” location.href “] Time Spent: ” totTime ” seconds”;
sendAReq(‘tmsg=’ msg);
}
</script>
</head>

<body onbeforeunload=”javascript:calcTime();”>
Hi, navigate away from this page or Refresh this page to find the time you spent seeing
this page in a log file in the server.
</body>
</html>

logtimefile.php

<?php
function logtimemsg($timemsg)
{
//write your own handling code here, store it in a file or store it in a DB, whatever
$logfilename = ‘timelog.txt’;
if (is_writable($logfilename))
{
if (!$handle = fopen($logfilename, ‘a’))
{
exit;
}
if (fwrite($handle, $timemsg.”\r\n”) === FALSE)
{
exit;
}
fclose($handle);
}
}

logtimemsg($_REQUEST[‘tmsg’]);
?>

UPDATE: People, I love if anyone of you writes back, even if to tell that this doesn’t work. Thanks to JayVee who pointed that <body onunload=”> sucks compared to <body onbeforeunload=”> for this post. Change accomodated.


I spend a considerable time debugging errors, and being a Web developer spans debugging CSS, JS and server end files as well. Often I find myself rolling up and down scrollbars on MySQL manual pages.

It annoys me no end to find that a user is seeing Javascript errors. And since Javascript being something that browsers have been trusted with, they had a field day unsupporting it. So it is very common to find that what you think is OK on browser1 is NOT_OK on browser2. And worse still, this incompatibility is reported by someone who is seeing a webpage on a live setup, a user or someone who least expects a nasty bug or something.

Now try this, save this as something.html on your server:

<html>
<head>
<title>Auto JS Bug Reporting Demo</title>
<script type=”text/javascript”>
var msg = null;
var opdiv;
var oRequest;

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

onerror = handleErrors;
function handleErrors(errorMessage, url, line)
{
msg = “[URL:” url “, line no.: ” line “] ERROR: ” errorMessage;
sendAReq(“err=” msg, ‘errdiv’);
return true;
}

function sendAReq(sendStr, odiv)
// a generic function to send away any data to the server
// specifically ‘handleerror.php’ in this case
// what the server replies is handled by showcontent()
{
opdiv = odiv;
oRequest.open(“POST”, “handleerror.php”, true); //this is where the stuff is going
oRequest.onreadystatechange = showcontent;
oRequest.setRequestHeader(“Content-Type”, “application/x-www-form-urlencoded”);
oRequest.send(sendStr);
}

function showcontent()
{
if(oRequest.readyState == 4)
{
// if the output is ready, print it to the div as set by the caller function
// in this case, the opdiv, the output div, was set to ‘errdiv’ in handleErrors(…)
if(oRequest.status == 200)
document.getElementById(opdiv).innerHTML = oRequest.responseText;
else
document.getElementById(opdiv).innerHTML = “<font color=#FF3300 > Try Again Later </font>”;
}
}
</script>
</head>

<body onload=”javascript:wow();”>
<div id=”testdiv”>
I am a div. Press this button to cause an error.<br>
<input type=”button” onclick=”javascript:sendAReq(‘err=hello, ‘errdiv’);” value=”GET some FUN”>
</div>
<div id=”errdiv”>
</div>
</body>
</html>

So this file has two Javascript errors. One is in the body onload function, which calls a nonexistent function, wow() . And the other is caused in the onclick event of the only input button on this page.

So this page is easy in the way that …

[1] It assigns handleErrors as the default error handler in the line onerror=handleErrors ;

[2] It puts together a error report in handleErrors and then calls sendAReq with the report string and the name of the output div, in this case being ‘errdiv’.

[3] sendAReq sends the error report to handleerror.php and sets the output div dutifully to ‘errdiv’ in the first line itself. The output div we keep referring to here is the div to which the server will send the output. Oh … so you looking for handleerror.php??


<?php
function logerr($errmsg)
{
//write your own handling code here, store it in a file or store it in a DB, whatever
$errfilename = ‘jsbugs.txt’;
if (is_writable($errfilename))
{
if (!$handle = fopen($errfilename, ‘a’))
{
exit;
}
if (fwrite($handle, $errmsg.’\r\n’) === FALSE)
{
exit;
}
fclose($handle);
}
}
logerr($_REQUEST[‘err’]);
echo “I got this: “.$_REQUEST[‘err’];
?>

[4] So handleerror.php gets the error report Javascript compiled and stores it in a file named jsbugs.txt. make sure you have a file created already named jsbugs.txt with write permissions before you run this script. Should you want to do more fancy things, you can store the User-Agent string, timestamp and a lot more things in a database maybe. I leave that to you.

So now, you are ready with something.html about to be fetched in your browser, and handleerror.php copied in the web root directory and jsbugs.txt in the same directory as well, with write permissions.

Now get something.html and you should see your jsbugs.txt file piling up with cute strings, which may later turn up to be sleep-stealing, girlfriend-eating monsters.

Queerer …

Wed, 13th Jun, '07

How this word came up is how I asked my immediate neighbours then to have a look at a talk delivered by Richard Dawkins. Strangeness, unusualness is what queer means, barring the sexual orientation connotation here. I could have linked the video here but I want you to go and check www.ted.com for more. Maybe you won’t find the video of the talk, but you will feel more benefitted if you actually did visit the site.
What got me from the talk is strangeness of observing things. The Sun revolved round the Earth??? …. because it looked like that???? well what do you expect to see if the earth were revolving round the sun. Pre-conceived half-matured notions. We, at the centre. We, know it all, or atleast can explain it. Like we do to our children folk. I think the children gave us this habit, of coming to us and asking something and our promptness to cook a story and telling something that has the least chance of being challenged.
When I was a kid, we had a science supplement delivered weekly alongwith the newspaper, the newspaper in question being, The Telegraph and the science section being KnowHow. Now I just wanted to go through the science section and waited 7 days to lay my hands on each new edition that came along. Now I may sound like Ross’ dream child, but I was like that. I kept them in my study room and that was my first library. All the supplements since they started it. That supplement was what ted.com is to today’s generation. It carried a cover story mostly revolving around quantum physics, astronomy, supercomputing and sometimes evolution theory. I always had to give myself a whole week with an edition explaining the ideas to me, any which way it could make sense to me. Nobody around was of much help. Now I may need only 6 days because I now know what beer is and invest the seventh day in it.
The most queer thing[is the use correct??] I had once read in it went something like this:
So you think you are free. You are free as a human being to do whatever you want to, or atleast think whatever you want to. Now there are no limits to the range of thoughts you can process and the swiftness with which you can move in and out of any thought. Impressive. But what is a thought?? Perhaps the state of some neurons in the brain processing some input. Who provided that input?? Some other neuron sure, cuz nobody else interacts with a neuron. And how do neurons communicate??? They send electrical pulses through links called synapses. And those pulses are generated by reactions occurring within a neuron. Now the stomach turner. If no amount of man-made-technology present can hold and make an atom “react” with another similarly held atom in a controlled manner, then does it in anyway imply that the chemical reactions within the neurons are essentially random??? We sure can’t control the gazillion atoms reacting every femtosecond within the neurons present in our brain, we can’t, and hence this implies that we can’t control our thoughts. So we aren’t free. If we can’t control our thoughts and still be having organized thoughts, either we are being controlled by something else or that our thoughts are actually random. Just that we have learnt to live with the randomness and those shortlived albeit random thoughts seem long enough that we feel we ponder over them . In the first case, it postulates the existence of god and the second case essentially dictates that we all are lunatics. In any case we aren’t reasonable free creatures. So where is that idea of freedom??
Now that was the first lesson in philosophy for me. That is how I explained it to me. This wasn’t science to me because science as I knew it then failed to explain this to me by any means. Years have passed and I know much better of what neurons and synapses do, but I am still to explain this to me someday in detail. Until then I will swear by this and whatever little sense I made out of it.