Skip to content

Instantly share code, notes, and snippets.

@jhummel
Created December 19, 2016 19:48
Show Gist options
  • Save jhummel/7855fca3d7c9d66fc610dcde7284d1f0 to your computer and use it in GitHub Desktop.
Save jhummel/7855fca3d7c9d66fc610dcde7284d1f0 to your computer and use it in GitHub Desktop.
ADA Tabs
class AccordianController
constructor: (view, options) ->
@$view = $ view
@options = $.extend
header: 'dt'
body: 'dd'
header_class: 'opened'
body_class: 'expanded'
single: false
, options || {}
@keys = new VOX.Utils.key_codes()
@$tab = null
@$open = null
@$headers = @$view.find @options.header
@$panels = @$view.find @options.body
@setup()
setup: ->
@$view.attr 'aria-multiselectable', false
@$panels.attr 'aria-hidden', true
@$tab = @$headers.filter @options.header_class
unless @$tab.length
@$tab = @$headers.first()
@$tab.addClass @options.header_class
@switch_and_open_tab @$tab
@bind_handlers()
get_tab_panel: ($tab) ->
@$panels.filter('#' + $tab.attr('aria-controls'))
close_tab: ($tab) ->
$tab.removeClass @options.header_class
$tab.attr 'tabindex', -1
@close_panel $tab
@$headers.first().attr('tabindex', 0) unless @$headers.filter('[tabindex="0"]').length || @options.single
close_all_tabs: ->
@$headers.each (i, el) =>
@close_tab $(el)
open_tab: ($tab) ->
@close_all_tabs() if @options.single
$tab.addClass @options.header_class
$tab.attr 'tabindex', 0
$tab.focus()
@open_panel $tab
@$open = $tab
@$tab = $tab
toggle_tab: ($tab) ->
if @options.single
@open_tab $tab
else
if @get_tab_panel($tab).is(':visible') then @close_tab $tab else @open_tab $tab
switch_tab: ($tab) ->
@$tab.attr('tabindex', -1)
$tab.attr('tabindex', 0)
$tab.focus()
@$tab = $tab
switch_and_open_tab: ($tab) ->
@switch_tab $tab
@open_tab $tab
close_panel: ($tab) ->
@get_tab_panel($tab).attr('aria-hidden', 'true').removeClass @options.body_class
close_all_panels: ->
@$panels.each (i, el) =>
@close_panel $(el)
open_panel: ($tab) ->
@close_all_panels() if @options.single
@get_tab_panel($tab).addClass(@options.body_class).attr('aria-hidden', false)
toggle_panel: ($tab) ->
if @get_tab_panel($tab).is(':visible') then @close_panel $tab else @open_panel $tab
bind_handlers: ->
@$headers.on 'keydown', (e) =>
@handle_header_key e
@$headers.on 'keypress', (e) =>
@handle_header_press e
@$headers.on 'click', (e) =>
@handle_header_click e
@$panels.on 'keydown', (e) =>
@handle_panel_key e
handle_header_key: (e) ->
return if e.altKey
console.log(e.keyCode)
$target_tab = $ e.currentTarget
switch e.keyCode
when @keys.enter, @keys.space
@toggle_tab $target_tab
e.stopPropagation()
return false
when @keys.left, @keys.up
unless e.ctrlKey
index = @$headers.index $target_tab
new_tab = if index == 0 then @$headers.last() else @$headers.eq(index - 1)
@switch_tab new_tab
e.stopPropagation()
return false
when @keys.right, @keys.down
index = @$headers.index $target_tab
new_tab = if index == @$headers.length - 1 then @$headers.first() else @$headers.eq(index + 1)
@switch_tab new_tab
e.stopPropagation()
return false
when @keys.home
@switch_tab @$headers.first()
e.stopPropagation()
return false
when @keys.end
@switch_tab @$headers.last()
e.stopPropagation()
return false
handle_header_press: (e) ->
switch e.keyCode
when @keys.enter, @keys.space, @keys.left, @keys.up, @keys.right, @keys.down, @keys.home, @keys.end
e.stopPropagation
return false
when @keys.pageup, @keys.pagedown
unless e.ctrlKey
return true
e.stopPropagation()
return false
return true
handle_header_click: (e) ->
e.preventDefault()
$tab = $ e.currentTarget
@$headers.attr('tabindex', -1)
$tab.attr('tabindex', 0)
@toggle_tab $tab
handle_panel_key: (e) ->
return true if e.altKey
$panel = $(e.currentTarget)
switch e.keyCode
when @keys.tab
$focusable = $panel.find ':focusable'
index = $focusable.index $(e.target)
p_index = @$panels.index $panel
n_panels = @$panels.length
if e.shiftKey
if index == 0 && p_index > 0
for ndx in [p_index - 1..0]
$prev = @$panels.eq ndx
$prev_focusable = $prev.find ':focusable'
if $prev_focusable.length
$prev_focusable.last().focus()
e.stopPropagation()
return false
else if p_index < n_panels
if index == $focusable.length - 1
for ndx in [p_index + 1..n_panels]
$next = @$panels.eq ndx
$next_focusable = $next.find ':focusable'
if $next_focusable.length
$next_focusable.first().focus()
e.stopPropagation()
return false
return true
when @keys.left, @keys.up
return true unless e.ctrlKey
$('#' + $panel.attr('aria-labelledby')).focus()
e.stopPropagation()
return false
when @keys.pageup
return true unless e.ctrlKey
index = @$headers.index @$tab
if index == 0
@switch_tab @$headers.last()
else
@switch_tab @$headers.eq index - 1
e.stopPropagation()
e.preventDefault()
return false
when @keys.pagedown
return true unless e.ctrlKey
index @$headers.index @$tab
if index == @$headers.last().index()
@switch_tab @$headers.first()
else
@switch_tab @$headers.eq index + 1
VOX.plugin_maker 'accordian', AccordianController
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment