Slide 1

Slide 1 text

Ajax navigation Perils, pitfalls and anti-patterns: A guide to best practice Andrew Betts, Assanka

Slide 2

Slide 2 text

Hi Andrew, Found a great resource for your JavaScript talk. Can't seem to link to it directly, but just go to www.example.com/docs and click on the top left tab then 'AJAX' in the side menu and finally scroll about half way down where there's a tabbed widget and there's a cool demo on the fourth tab. Good luck! Ajax sometimes causes problems Hi Andrew, Found a great resource for your JavaScript talk. Can't seem to link to it directly, but just go to www.example.com/docs and click on the top left tab then 'AJAX' in the side menu and finally scroll about half way down where there's a tabbed widget and there's a cool demo on the fourth tab. Good luck!

Slide 3

Slide 3 text

Ajax problems §  Fewer things have URLs §  Substantial changes to the page made in JavaScript do not change the URL in the address bar Result: §  You can't link directly to stuff anymore §  The back button doesn't work

Slide 4

Slide 4 text

So it's like flash then? Yeah.

Slide 5

Slide 5 text

Framesets were kinda like that too While we're reminiscing…

Slide 6

Slide 6 text

Putting the hash to work §  Every time the context changes, update location.hash §  Detect change of context caused by back button •  hashchange event (FF 3.6, IE8, Safari 5, Opera 10.6, Chrome 5) •  polling the value of location.hash §  React accordingly www.example.com/#search?q=apples&page=1

Slide 7

Slide 7 text

Lots of sites do this

Slide 8

Slide 8 text

But they don't always get it right §  No non-JavaScript alternatives §  Lack of caching §  Forgetting scroll position §  Flash of blank content §  Assuming speed §  Ignoring inline JavaScript §  Ignoring modifier keys §  Mishandling focus rectangles Cartoon: http://pagedeclasse.recit05.qc.ca

Slide 9

Slide 9 text

No non-JavaScript alternatives Tab A For any link that loads a new fragment using AJAX, it must also work without JavaScript by simply navigating the user's browser to a new page Acceptable ONLY if the target fragment is already in the DOM (eg. tabs): 2 Better, if you want to load remote content (return false to cancel the href):

Slide 10

Slide 10 text

Lack of caching The Back button should not cause cacheable content previously loaded to be reloaded - if the browser would normally cache it locally, it should be cached locally. §  Avoid making all AJAX non-cacheable as a global rule §  Be aware of differences in browser AJAX caching policy •  IE particularly keen to cache AJAX •  Set correct Cache-Control and Expires headers on AJAX responses §  And also RFC2616, which says…

Slide 11

Slide 11 text

History mechanisms and caches are different. In particular history mechanisms SHOULD NOT try to show a semantically transparent view of the current state of a resource. Rather, a history mechanism is meant to show exactly what the user saw at the time when the resource was retrieved. “

Slide 12

Slide 12 text

Lack of caching // When deciding whether to load new content var ckey; if ((ckey = $.inArray(currenthash, cache_hashes)) != -1) { useContent(cache_html[ckey]); return; } // When new content loaded, add to cache. Keep n items (FIFO) if (cache_html.length > cache_size) { cache_html.shift(); cache_hashes.shift(); } cache_html.push(resphtml); cache_hashes.push(currenthash); §  Or: implement a cache in JavaScript •  Choice of algorithms: FIFO, least recently used, least frequently used •  Choice of how to store: as nodes in DOM (display: none) or HTML string

Slide 13

Slide 13 text

Forgetting scroll position // Scroll to top of page if navigating forwards, but not // if using back button var n = history.length-1; if (history[n] != history[n-2]) { window.scroll(0,0); } else { history.splice(-2, 2); } Forward navigation should force a scroll to the top of the page. Rearward navigation should restore the previous scroll position 1.  #page1 2.  #page2 3.  #page3 4.  #page2 Use of back button detected

Slide 14

Slide 14 text

Forgetting scroll position §  Scroll position is remembered by the browser itself and restored automatically §  But… this happens before content is changed §  Take care if content to be restored is longer than current content •  Browser can only scroll as far as the end of the page

Slide 15

Slide 15 text

Forgetting scroll position A (Browser default) Page 1 Page 2 Back to page 1 B (Typical solution) C (Ideal)

Slide 16

Slide 16 text

Flash of blank content The current content should not be removed until the new fragment has loaded. §  Browsers do not clear a webpage from the viewport while loading a new one. §  Old webpage only disappears when new HTML has begun to be received by the browser (or the operation times out) §  Mimic this behaviour for best user experience

Slide 17

Slide 17 text

Assuming speed Do not assume that loading a new fragment will take a very short time if it may take a long time and vice versa. *click* 250ms - 2sec Expectation More than 2 seconds: Frustration - danger of duplicate click 0-250ms 'Instant'

Slide 18

Slide 18 text

Assuming speed §  During the instant period, leave the old content in place •  Don't provide interstitial effects that last less time than it takes to properly perceive them §  After 250ms, consider an interstitial effect §  After 2 seconds, consider progress feedback •  Exact: progress bar, or 'x out of y items complete' •  Hedged: 'Estimated wait time: x seconds/minutes' •  No clue: 'This is taking longer than expected'

Slide 19

Slide 19 text

Assuming speed §  Set timers to activate high-latency behaviours, cancel them on receipt of the response: // Set up watchdog in case request takes a long time var loadingThrobberTimer; loadingThrobberTimer = setTimeout(function() { $('#fragcontainer').html('').addClass('loading'); }, 250); // Load fragment from server $.get(url, function(resp) { clearTimeout(loadingThrobberTimer); }

Slide 20

Slide 20 text

Ignoring inline JavaScript If fragments contain sections, they won't be executed when appended to the DOM. §  Probably best to avoid including inline script in page fragments §  If you have to, eval() it after loading $('#fragcontainer script').each(function() { eval(this.text); });

Slide 21

Slide 21 text

Mishandling focus rectangles It should be possible to see focus rectangles when tabbing through links on the page. When a link is clicked the focus should persist until the operation is complete, then be removed. §  Cannot select the item that currently has focus •  document.hasFocus() exists, but no equivalent for elements §  Can bind an event to an element receiving focus §  Remember which element has focus

Slide 22

Slide 22 text

Mishandling focus rectangles var linkWithFocus; // Keep track of which link element last had the focus $("a").live('focus', function() { linkWithFocus = this; }); // When any AJAX operation completes, blur any focused link $.ajaxSetup({complete:function(xhr, textStatus) { if (linkWithFocus) linkWithFocus.blur(); }});

Slide 23

Slide 23 text

Ignoring modifier keys If a link is clicked while the SHIFT or CONTROL keys are pressed, the user is saying they want to open the link in a new browser tab or window. Let them. §  Status of modifier keys is provided by the event object •  shiftKey •  ctrlKey •  altKey §  return true to allow the link to navigate normally if (e.shiftKey || e.ctrlKey) { return true; }

Slide 24

Slide 24 text

Cutting edge stuff Things to watch: §  HTML5 History pushState §  Google crawlable AJAX applications spec

Slide 25

Slide 25 text

HTML5 pushState §  Two new methods of the history object •  pushState •  replaceState §  Change the URL completely without navigating the browser §  Can stop using fragments §  Support: •  Chrome 6 •  Firefox 4

Slide 26

Slide 26 text

Google crawlable AJAX apps §  Proposal for translating hash fragments into query arguments §  Activated by using ! at the beginning of fragment string Example: http://example.com/#!search/widgets becomes http://example.com/?_escaped_fragment_=search/widgets

Slide 27

Slide 27 text

Thanks. We're recruiting, blah blah. [email protected] assanka.net/iwantajob