mirror of
https://github.com/atom/atom.git
synced 2026-01-22 21:38:10 -05:00
Add core:focus-next/focus-previous
Focus now cycles between elements with a positive tabindex on tab and shift-tab.
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
$ = require 'jquery'
|
||||
{$$} = require 'space-pen'
|
||||
fsUtils = require 'fs-utils'
|
||||
{less} = require 'less'
|
||||
WindowEventHandler = require 'window-event-handler'
|
||||
@@ -235,3 +236,81 @@ describe "Window", ->
|
||||
ChildProcess.spawn.reset()
|
||||
$("<a href='#scroll-me'>link</a>").appendTo(document.body).click().remove()
|
||||
expect(ChildProcess.spawn).not.toHaveBeenCalled()
|
||||
|
||||
describe "core:focus-next and core:focus-previous", ->
|
||||
describe "when there is no currently focused element", ->
|
||||
it "focuses the element with the lowest/highest tabindex", ->
|
||||
elements = $$ ->
|
||||
@div =>
|
||||
@button tabindex: 2
|
||||
@input tabindex: 1
|
||||
|
||||
elements.attachToDom()
|
||||
|
||||
elements.trigger "core:focus-next"
|
||||
expect(elements.find("[tabindex=1]:focus")).toExist()
|
||||
|
||||
$(":focus").blur()
|
||||
|
||||
elements.trigger "core:focus-previous"
|
||||
expect(elements.find("[tabindex=2]:focus")).toExist()
|
||||
|
||||
describe "when a tabindex is set on the currently focused element", ->
|
||||
it "focuses the element with the next highest tabindex", ->
|
||||
elements = $$ ->
|
||||
@div =>
|
||||
@input tabindex: 1
|
||||
@button tabindex: 2
|
||||
@button tabindex: 5
|
||||
@input tabindex: -1
|
||||
@input tabindex: 3
|
||||
@button tabindex: 7
|
||||
|
||||
elements.attachToDom()
|
||||
elements.find("[tabindex=1]").focus()
|
||||
|
||||
elements.trigger "core:focus-next"
|
||||
expect(elements.find("[tabindex=2]:focus")).toExist()
|
||||
|
||||
elements.trigger "core:focus-next"
|
||||
expect(elements.find("[tabindex=3]:focus")).toExist()
|
||||
|
||||
elements.focus().trigger "core:focus-next"
|
||||
expect(elements.find("[tabindex=5]:focus")).toExist()
|
||||
|
||||
elements.focus().trigger "core:focus-next"
|
||||
expect(elements.find("[tabindex=7]:focus")).toExist()
|
||||
|
||||
elements.focus().trigger "core:focus-next"
|
||||
expect(elements.find("[tabindex=1]:focus")).toExist()
|
||||
|
||||
elements.trigger "core:focus-previous"
|
||||
expect(elements.find("[tabindex=7]:focus")).toExist()
|
||||
|
||||
elements.trigger "core:focus-previous"
|
||||
expect(elements.find("[tabindex=5]:focus")).toExist()
|
||||
|
||||
elements.focus().trigger "core:focus-previous"
|
||||
expect(elements.find("[tabindex=3]:focus")).toExist()
|
||||
|
||||
elements.focus().trigger "core:focus-previous"
|
||||
expect(elements.find("[tabindex=2]:focus")).toExist()
|
||||
|
||||
elements.focus().trigger "core:focus-previous"
|
||||
expect(elements.find("[tabindex=1]:focus")).toExist()
|
||||
|
||||
it "skips disabled elements", ->
|
||||
elements = $$ ->
|
||||
@div =>
|
||||
@input tabindex: 1
|
||||
@button tabindex: 2, disabled: 'disabled'
|
||||
@input tabindex: 3
|
||||
|
||||
elements.attachToDom()
|
||||
elements.find("[tabindex=1]").focus()
|
||||
|
||||
elements.trigger "core:focus-next"
|
||||
expect(elements.find("[tabindex=3]:focus")).toExist()
|
||||
|
||||
elements.trigger "core:focus-previous"
|
||||
expect(elements.find("[tabindex=1]:focus")).toExist()
|
||||
|
||||
@@ -67,10 +67,10 @@
|
||||
|
||||
# allow standard input fields to work correctly
|
||||
'input:not(.hidden-input)':
|
||||
'tab': 'core:focus-next'
|
||||
'shift-tab': 'core:focus-previous'
|
||||
'left': 'native!'
|
||||
'right': 'native!'
|
||||
'tab': 'native!'
|
||||
'shift-tab': 'native!'
|
||||
'shift-left': 'native!'
|
||||
'shift-right': 'native!'
|
||||
'backspace': 'native!'
|
||||
@@ -81,3 +81,7 @@
|
||||
'meta-x': 'native!'
|
||||
'meta-c': 'native!'
|
||||
'meta-v': 'native!'
|
||||
|
||||
'button':
|
||||
'tab': 'core:focus-next'
|
||||
'shift-tab': 'core:focus-previous'
|
||||
|
||||
@@ -15,6 +15,9 @@ class WindowEventHandler
|
||||
window.close()
|
||||
@subscribeToCommand $(window), 'window:reload', => reload()
|
||||
|
||||
@subscribeToCommand $(document), 'core:focus-next', @focusNext
|
||||
@subscribeToCommand $(document), 'core:focus-previous', @focusPrevious
|
||||
|
||||
@subscribe $(document), 'keydown', keymap.handleKeyEvent
|
||||
|
||||
@subscribe $(document), 'drop', onDrop
|
||||
@@ -31,4 +34,50 @@ class WindowEventHandler
|
||||
require('child_process').spawn('open', [location])
|
||||
false
|
||||
|
||||
eachTabIndexedElement: (callback) ->
|
||||
for element in $('[tabindex]')
|
||||
element = $(element)
|
||||
continue if element.attr('disabled')
|
||||
|
||||
tabIndex = parseInt(element.attr('tabindex'))
|
||||
continue unless tabIndex >= 0
|
||||
|
||||
callback(element, tabIndex)
|
||||
|
||||
focusNext: =>
|
||||
focusedTabIndex = parseInt($(':focus').attr('tabindex')) or -Infinity
|
||||
|
||||
nextElement = null
|
||||
nextTabIndex = Infinity
|
||||
lowestElement = null
|
||||
lowestTabIndex = Infinity
|
||||
@eachTabIndexedElement (element, tabIndex) ->
|
||||
if tabIndex < lowestTabIndex
|
||||
lowestTabIndex = tabIndex
|
||||
lowestElement = element
|
||||
|
||||
if focusedTabIndex < tabIndex < nextTabIndex
|
||||
nextTabIndex = tabIndex
|
||||
nextElement = element
|
||||
|
||||
(nextElement ? lowestElement).focus()
|
||||
|
||||
focusPrevious: =>
|
||||
focusedTabIndex = parseInt($(':focus').attr('tabindex')) or Infinity
|
||||
|
||||
previousElement = null
|
||||
previousTabIndex = -Infinity
|
||||
highestElement = null
|
||||
highestTabIndex = -Infinity
|
||||
@eachTabIndexedElement (element, tabIndex) ->
|
||||
if tabIndex > highestTabIndex
|
||||
highestTabIndex = tabIndex
|
||||
highestElement = element
|
||||
|
||||
if focusedTabIndex > tabIndex > previousTabIndex
|
||||
previousTabIndex = tabIndex
|
||||
previousElement = element
|
||||
|
||||
(previousElement ? highestElement).focus()
|
||||
|
||||
_.extend WindowEventHandler.prototype, Subscriber
|
||||
|
||||
Reference in New Issue
Block a user