TreeView directories can be selected by clicking them. Start on keyboard nav.

This commit is contained in:
Nathan Sobo
2012-04-24 12:51:01 -06:00
parent 34a4bcf224
commit dd736ddf67
3 changed files with 73 additions and 27 deletions

View File

@@ -15,8 +15,8 @@ describe "TreeView", ->
describe ".initialize(project)", ->
it "renders the root of the project and its contents alphabetically with subdirectories first in a collapsed state", ->
expect(rootDirectoryView.find('> .disclosure-arrow')).toHaveText('')
expect(rootDirectoryView.find('> .name')).toHaveText('fixtures/')
expect(rootDirectoryView.find('> .header .disclosure-arrow')).toHaveText('')
expect(rootDirectoryView.find('> .header .name')).toHaveText('fixtures/')
rootEntries = rootDirectoryView.find('.entries')
subdir1 = rootEntries.find('> li:eq(0)')
@@ -34,27 +34,26 @@ describe "TreeView", ->
describe "when a directory's disclosure arrow is clicked", ->
it "expands / collapses the associated directory", ->
subdir = rootDirectoryView.find('.entries > li:contains(dir/)')
subdir = rootDirectoryView.find('.entries > li:contains(dir/)').view()
disclosureArrow = subdir.find('.disclosure-arrow')
expect(disclosureArrow).toHaveText('')
expect(subdir.disclosureArrow).toHaveText('')
expect(subdir.find('.entries')).not.toExist()
disclosureArrow.click()
subdir.disclosureArrow.click()
expect(disclosureArrow).toHaveText('')
expect(subdir.disclosureArrow).toHaveText('')
expect(subdir.find('.entries')).toExist()
disclosureArrow.click()
expect(disclosureArrow).toHaveText('')
subdir.disclosureArrow.click()
expect(subdir.disclosureArrow).toHaveText('')
expect(subdir.find('.entries')).not.toExist()
it "restores the expansion state of descendant directories", ->
child = rootDirectoryView.find('.entries > li:contains(dir/)')
child.find('> .disclosure-arrow').click()
child = rootDirectoryView.find('.entries > li:contains(dir/)').view()
child.disclosureArrow.click()
grandchild = child.find('.entries > li:contains(a-dir/)')
grandchild.find('> .disclosure-arrow').click()
grandchild = child.find('.entries > li:contains(a-dir/)').view()
grandchild.disclosureArrow.click()
rootDirectoryView.find('> .disclosure-arrow').click()
rootDirectoryView.find('> .disclosure-arrow').click()
@@ -84,6 +83,12 @@ describe "TreeView", ->
expect(treeView.find('.selected').length).toBe 1
expect(rootView.activeEditor().buffer.path).toBe require.resolve('fixtures/sample.txt')
describe "when a directory is clicked", ->
it "is selected", ->
subdir = rootDirectoryView.find('.directory:first').view()
subdir.click()
expect(subdir).toHaveClass 'selected'
describe "when a new file is opened in the active editor", ->
it "is selected in the tree view if visible", ->
sampleJs.click()
@@ -102,3 +107,28 @@ describe "TreeView", ->
expect(sampleTxt).toHaveClass('selected')
leftEditor.focus()
expect(sampleJs).toHaveClass('selected')
describe "keyboard navigation", ->
afterEach ->
expect(treeView.find('.selected').length).toBeLessThan 2
describe "move-down", ->
describe "if nothing is selected", ->
it "selects the first entry", ->
treeView.trigger 'move-down'
expect(rootDirectoryView).toHaveClass 'selected'
describe "if a collapsed directory is selected", ->
it "skips to the next directory", ->
rootDirectoryView.find('.directory:eq(0)').click()
treeView.trigger 'move-down'
expect(rootDirectoryView.find('.directory:eq(1)')).toHaveClass 'selected'
describe "if an expanded directory is selected", ->
it "selects the first entry of the directory", ->
describe "if the last entry of an expanded directory is selected", ->
it "selects the entry after its parent directory", ->
describe "if the last entry of the last directory is selected", ->
it "does not change the selection", ->

View File

@@ -13,26 +13,41 @@ class TreeView extends View
@subview 'root', new DirectoryView(directory: rootView.project.getRootDirectory(), isExpanded: true)
initialize: (@rootView) ->
@on 'click', '.file', (e) =>
clickedLi = $(e.target)
@rootView.open(clickedLi.attr('path'))
@find('.selected').removeClass('selected')
clickedLi.addClass('selected')
@on 'click', '.entry', (e) =>
entry = $(e.currentTarget)
@rootView.open(entry.attr('path')) if entry.is('.file')
@selectEntry(entry)
false
@on 'move-down', => @moveDown()
@on 'tree-view:expand-directory', => @selectActiveFile()
@rootView.on 'active-editor-path-change', => @selectActiveFile()
selectActiveFile: ->
console.log ""
@find('.selected').removeClass('selected')
activeFilePath = @rootView.activeEditor()?.buffer.path
@find(".file[path='#{activeFilePath}']").addClass('selected')
@selectEntry(@find(".file[path='#{activeFilePath}']"))
moveDown: ->
selectedEntry = @selectedEntry()
if selectedEntry.length
@selectEntry(selectedEntry.next())
else
@selectEntry(@root)
selectedEntry: ->
@find('.selected')
selectEntry: (entry) ->
@find('.selected').removeClass('selected')
entry.addClass('selected')
class DirectoryView extends View
@content: ({directory, isExpanded}) ->
@li class: 'directory', =>
@span '', class: 'disclosure-arrow', outlet: 'disclosureArrow', click: 'toggleExpansion'
@span directory.getName(), class: 'name'
@li class: 'directory entry', =>
@div class: 'header', =>
@span '', class: 'disclosure-arrow', outlet: 'disclosureArrow', click: 'toggleExpansion'
@span directory.getName(), class: 'name'
entries: null
@@ -45,7 +60,7 @@ class DirectoryView extends View
if entry instanceof Directory
@entries.append(new DirectoryView(directory: entry, isExpanded: false))
else
@entries.append $$ -> @li entry.getName(), class: 'file', path: entry.path
@entries.append $$ -> @li entry.getName(), class: 'file entry', path: entry.path
@append(@entries)
toggleExpansion: ->
@@ -59,6 +74,7 @@ class DirectoryView extends View
@deserializeEntries(@entryStates) if @entryStates?
@isExpanded = true
@trigger 'tree-view:expand-directory'
false
collapse: ->
@entryStates = @serializeEntries()
@@ -77,7 +93,7 @@ class DirectoryView extends View
deserializeEntries: (entryStates) ->
for directoryName, childEntryStates of entryStates
@entries.find("> .directory:contains(#{directoryName})").each ->
@entries.find("> .directory:contains('#{directoryName}')").each ->
view = $(this).view()
view.entryStates = childEntryStates
view.expand()

View File

@@ -16,7 +16,7 @@
padding-left: 2ex;
}
.tree-view .directory .selected {
.tree-view .file.selected, .tree-view .directory.selected > .header {
background: #333;
}