Skip to content

Instantly share code, notes, and snippets.

@jlsync
Created February 13, 2011 11:27
Show Gist options
  • Save jlsync/824610 to your computer and use it in GitHub Desktop.
Save jlsync/824610 to your computer and use it in GitHub Desktop.
control.coffee
$ = jQuery
$window = $(window)
# closure globals
current_state = {}
$selected = null
states = {}
# callbacks...
process_keys = (key, event) ->
return if ! _.include(current_state.keys, key)
# otherwise, let's deal with it...
event.preventDefault
t = _.select current_state.transition_names, (tn) ->
return _.include(current_state.transitions[tn].keys, key)
trans = current_state.transitions[t]
trans.callback.call(this, key)
current_state = states[trans.next]
end_navigation = () ->
$selected.jhighlight 'remove'
$selected = null
prev_row = () ->
$selected.jhighlight 'remove'
$selected = prev_selection $selected
$selected.jscrollTo().jhighlight() # darken: true
next_row = () ->
$selected.jhighlight 'remove'
$selected = next_selection $selected
$selected.jscrollTo().jhighlight() # darken: true
highlight_first_row = () ->
$selected = first_visible_row()
$selected.jhighlight() # darken: true
next_selection = ($current) ->
if $current.hasClass 'row'
$next = $current.find 'div.ribbon:first'
if $next.length == 1
return $next
$next = $current.next 'div.row'
if $next.length == 1
return $next
$.gritter.add title: 'info', text: 'no next selection found'
return $current
else if $current.hasClass 'ribbon'
$next = $current.next 'div.ribbon'
if $next.length == 1
return $next
$next = $current.closest('div.row').next('div.row')
if $next.length == 1
return $next
$.gritter.add title: 'info', text: 'no next selection found'
return $current
prev_selection = ($current) ->
if $current.hasClass 'row'
$next = $current.prev('div.row').find('div.ribbon:last')
if $next.length == 1
return $next
$next = $current.prev 'div.row'
if $next.length == 1
return $next
$.gritter.add title: 'info', text: 'no next selection found'
return $current
else if $current.hasClass 'ribbon'
$next = $current.prev 'div.ribbon'
if $next.length == 1
return $next
$next = $current.closest('div.row')
if $next.length == 1
return $next
$.gritter.add title: 'info', text: 'no next selection found'
return $current
first_visible_row = () ->
for row in $('div.row').toArray()
$row = $(row)
if $row.offset().top > $window.scrollTop()
return $row
$('div.row:first')
# the states...
states =
start:
name: 'Keyboard Navigation'
transitions:
to_row_nav:
next: 'row_nav'
keys: [ 'j', 'k', 'up', 'down' ]
help: 'Begin keyboard navigation'
callback: highlight_first_row
row_nav:
name: 'Row Naviation'
transitions:
to_next_row:
next: 'row_nav'
keys: [ 'j', 'down' ]
help: 'Next row'
callback: next_row
to_prev_row:
next: 'row_nav'
keys: [ 'k', 'up' ]
help: 'Prev row'
callback: prev_row
to_hourly_nav:
next: 'hourly_nav'
keys: [ 'h' ]
help: '<b>H</b>ourly navigation'
callback: next_selection
to_start:
next: 'start'
keys: [ 'escape' ]
help: 'End keyboard naviation'
callback: end_navigation
all_keys = []
for own s, value of states
state_keys = []
transition_names = []
for own t, v of value.transitions
state_keys = state_keys.concat v.keys
transition_names.push t
state_keys = _(state_keys).uniq()
states[s].keys = state_keys
states[s].transition_names = transition_names
all_keys = all_keys.concat state_keys
all_keys = _(all_keys).uniq()
all_keys_string = all_keys.join(", ")
# initial state
current_state = states.start
$selected = null
# activate jkey
$window.jkey all_keys_string, true, process_keys
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment