Created
December 19, 2016 19:48
-
-
Save jhummel/7855fca3d7c9d66fc610dcde7284d1f0 to your computer and use it in GitHub Desktop.
ADA Tabs
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
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