Upgrade to Pro — share decks privately, control downloads, hide ads and more …

AJAX navigation

AJAX navigation

The proliferation of Ajax has brought with it problems bookmarking, sharing and navigating in a world where an entire site may now hide under a single URL. Ajax navigation fixes this, but often isn't perfect. This talk addresses some of the shortcomings and looks at the future of dynamic web applications.

Andrew Betts

April 20, 2012
Tweet

More Decks by Andrew Betts

Other Decks in Technology

Transcript

  1. 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!
  2. 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
  3. 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
  4. 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
  5. No non-JavaScript alternatives <a href="#frag">Tab A</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): <a href="/page2" onclick="return goToPage(2)">2</a> Better, if you want to load remote content (return false to cancel the href):
  6. 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…
  7. 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. “
  8. 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
  9. 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
  10. 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
  11. Forgetting scroll position A (Browser default) Page 1 Page 2

    Back to page 1 B (Typical solution) C (Ideal)
  12. 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
  13. 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'
  14. 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'
  15. 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); }
  16. Ignoring inline JavaScript If fragments contain <script> 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); });
  17. 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
  18. 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(); }});
  19. 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; }
  20. Cutting edge stuff Things to watch: §  HTML5 History pushState

    §  Google crawlable AJAX applications spec
  21. 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
  22. 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