Created
December 12, 2013 16:53
-
-
Save danielrichman/7931228 to your computer and use it in GitHub Desktop.
CoffeeScript to HTML5-history-ify a series of static pages. All the content is included in each page, but /section1, say, will have #section1 visible. The code hooks links and instead just hides/shows the relevant section, with optional animations.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
current_section = null | |
static_section = null | |
sections = null | |
url_map = {} | |
history_enable = null | |
hash_enable = null | |
log = (msg) -> console?.log? "history.coffee: #{msg}" | |
change = (to, animation="change") -> | |
if current_section == to | |
log "change nop - already at #{to}" | |
return | |
from = sections[current_section] | |
to = sections[to] | |
from["#{animation}_out"] $("##{from.id}") | |
to["#{animation}_in"] $("##{to.id}") | |
set_title to.title | |
current_section = to.id | |
return | |
page_load = -> | |
if history_enable | |
$(window).bind "popstate", -> | |
log "popstate '#{location.pathname}'" | |
id = url_map[location.pathname] | |
if id? | |
log "popstate - changing to #{id}" | |
change id | |
else | |
log "popstate - unknown section, no action" | |
else if hash_enable | |
$(window).bind "hashchange", -> | |
log "hashchange #{location.hash}" | |
if location.hash == "" | |
id = static_section | |
else | |
id = location.hash[2..] | |
if sections[id]? | |
change id | |
return | |
if location.hash | |
log "hash (load) '#{location.hash}'" | |
if location.hash[...2] == "#!" | |
id = location.hash[2..] | |
if sections[id]? | |
log "hash (load) found #!, instant change to #{id}" | |
change id, "instant" | |
else | |
log "hash (load) unknown section - no action" | |
return | |
hook_links = -> | |
for elem in $("a") | |
do -> | |
a_href = $(elem).attr('href') | |
a_id = url_map[a_href] | |
if a_id? | |
$(elem).click (event) -> | |
if history_enable | |
title = sections[a_id].title | |
log "click - pushing state '#{title}' #{a_href}" | |
history.pushState null, title, a_href | |
else if hash_enable | |
log "click - setting hash #{a_id}" | |
location.hash = "!#{a_id}" | |
log "click - changing to #{a_id} (#{a_href})" | |
change a_id | |
# TODO ga 'send', 'pageview', a_href | |
event.preventDefault() | |
return undefined | |
# static_section - the section made visible by HTML/CSS, corresponding to the | |
# URL / the document that was fetched from the server | |
# sections - map, section id -> object with optional properties | |
# title: string | |
# change_in,change_out: (jquery elem) -> | |
# transition this section in/out | |
# instant_in,instant_out: (jquery elem) -> | |
# instant transition (used when a hash is found after page load) | |
# allow_hash - can we use #hash history in HTML4 browsers? | |
# typically used to only allow #!hash history on the main page | |
# thereby avoiding /sectiona#!sectionb | |
window.history_init = (static_section_, sections_, allow_hash) -> | |
current_section = static_section = static_section_ | |
sections = sections_ | |
defaults = | |
title: window.document.title | |
instant_out: (elem) -> elem.hide() | |
instant_in: (elem) -> elem.show() | |
change_out: (elem) -> elem.hide() | |
change_in: (elem) -> elem.show() | |
for id, options of sections | |
extra = | |
title: options.title | |
id: id | |
sections[id] = $.extend {}, defaults, options, extra | |
if not sections[id].url? | |
throw "history: url not specified in section #{id}" | |
url_map[sections[id].url] = id | |
history_enable = | |
!!( window.onpopstate != undefined && window.history?.pushState ) | |
hash_enable = | |
!!( !history_enable && allow_hash && | |
location.hash != undefined && window.onhashchange != undefined ) | |
log "init static_section=#{static_section} " + | |
"sections=[#{(id for id, _ of sections).join ', '}] " + | |
"allow_hash=#{allow_hash}" | |
log "detect history_enable=#{history_enable} hash_enable=#{hash_enable}" | |
page_load() | |
if history_enable or hash_enable | |
hook_links() | |
else | |
log "disabled - not hooking links" | |
return |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment