Feb 01 2007

Accessible Ajax calls 2 solving history problem

Posted by admin under ASP.NET AJAX formally Atlas

The importance of accessibility has become more and more in focus as Ajax solution becomes more and more
spread.

I have talked a lot of the need for it in this article on Accessible Ajax calls  and while it certainly could be argued the solution might be a little "raw" and could be done much more elegant in terms of implementing it as an extender control or something like that I leave that for the future.

However - that solution (when using Ajax paging I mean) has some BIG problems.

a) you can't bookmark a certain page, say page number 5


b) history is totally messed up. You can't go to page 3 and then press back button in browser.

Especially it's irritating when you click away from the list and want to press back to get back to the current page of the list and keep on scrolling etc. These screenshots show what I mean (in the download this is page notworking.aspx)

Now lets press "Next" - which gets next page by ajax call and an update panel:

While we have read in new data you see the URL is still unchanged...Which means users can't bookmark that specific page.

Anyway - lets look at most annoying thing. Lets click on Eastern Connection:

 

and go back:

AAAARRGH! We are back at page 1.

Now lets look at a solution for this.

I have so to speak ported a JQuery history plugin by Taku Sano (Mikage Sawatari) to Microsoft Ajax - and that js file (ASPCodeHistory.js) is available in the download - and is also more described here.  The only browsers I have tested it on is IE 7 and Forefox 2 but I think it should work ok on older versions as well.

Lets look at how to use it (fire up simpletest.aspx from the downloadable solution)



        <asp:ScriptManager ID="ScriptManager1" runat="server" EnablePartialRendering="true" >
        <Scripts>
                    <asp:ScriptReference Path="scripts/aspcodehistory.js"/>
                </Scripts>
..
..
..
A link which should be added to history
    <a onclick="ASPCode.net.History.setLocation('no1');return false;" href="pekka.aspx">test</a><br />




The secret is simply to  call ASPCode.net.History.setLocation whenever you want an history item added to the browser.

Everytime we click on a link a different hash (the #) is modifying the current url. Also an history item is added - when IE is used we need to do some hidden iframe tricks but all that is hidden deep inside the js code so you will (hopefully) never need to look at it.

Now - the history works - we can click on test (#no1) then test2(#no2) and then click back in browser and we'll taken back to #no1.

Now it's up to us to do something about it. Cause the idea is that the hash should store the state - and we should be able to set the pages state from the hash.

We do that by a callback - called everytime the hash part changes:

Look further down in the simpletest.aspx code:



             var app = Sys.Application;
             app.add_load(applicationLoadHandler);
            
             function applicationLoadHandler(sender, args) {
		        // Create the DemoTimer component instance.  
		        // Set properties and bind events.
		        ASPCode.net.History.add_locationChanged(OnLocationChanged);
                app.remove_load(applicationLoadHandler);
		    }
       	    function OnLocationChanged(sender, args) 
       	    {
       	        if ( args.startsWith("ab") )
       	        {
       	            alert('Do whatever to adjust page to state ' + args);
       	        }
       	    }


the links

    <a onclick="ASPCode.net.History.setLocation('ab1');return false;" href="pekka.aspx">AB1</a>
    <a onclick="ASPCode.net.History.setLocation('ab2');return false;" href="pekka.aspx">AB2</a>
    <a onclick="ASPCode.net.History.setLocation('ab3');return false;" href="pekka.aspx">AB3</a>

We can add a callback to the singleton histopry object - add_locationChanged - and that will mean that function will be called each time the hash changes (i.e click forward/backward or a link that changes the location)

Now lets marry this solution with the paging - continued here in Part 3 

Links