From 073ea84d69293ec964ccb2a3dcb9e6cd1639984b Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 9 Jan 2014 16:05:00 -0700 Subject: [PATCH] Handle consequences of item removal in the model --- spec/pane-model-spec.coffee | 20 ++++++++++++++++++++ src/pane-model.coffee | 11 +++++------ src/pane.coffee | 31 +++++++++++-------------------- 3 files changed, 36 insertions(+), 26 deletions(-) diff --git a/spec/pane-model-spec.coffee b/spec/pane-model-spec.coffee index 794507ba5..2b9cb40bb 100644 --- a/spec/pane-model-spec.coffee +++ b/spec/pane-model-spec.coffee @@ -1,6 +1,7 @@ PaneModel = require '../src/pane-model' PaneAxisModel = require '../src/pane-axis-model' PaneContainerModel = require '../src/pane-container-model' +FocusContext = require '../src/focus-context' describe "PaneModel", -> describe "split methods", -> @@ -83,6 +84,25 @@ describe "PaneModel", -> pane2 = pane1.splitRight() expect(pane2.focused).toBe true + describe "::removeItemAtIndex(index)", -> + describe "when the removal of the item causes blur to be called on the pane model", -> + it "remains focused if it was before the item was removed", -> + pane = new PaneModel(items: ["A", "B", "C"], focusContext: new FocusContext) + pane.on 'item-removed', -> pane.blur() + pane.focus() + pane.removeItemAtIndex(0) + expect(pane.focused).toBe true + + pane.blur() + pane.removeItemAtIndex(0) + expect(pane.focused).toBe false + + describe "when the last item is removed", -> + it "destroys the pane", -> + pane = new PaneModel(items: ["A", "B"]) + pane.removeItemAtIndex(0) + pane.removeItemAtIndex(0) + expect(pane.isDestroyed()).toBe true describe "::destroy()", -> [pane1, container] = [] diff --git a/src/pane-model.coffee b/src/pane-model.coffee index 6d310c47c..1930e93db 100644 --- a/src/pane-model.coffee +++ b/src/pane-model.coffee @@ -94,16 +94,15 @@ class PaneModel extends Model item # Public: - removeItem: (item, detach) -> + removeItem: (item) -> index = @items.indexOf(item) - @removeItemAtIndex(index, detach) if index >= 0 + @removeItemAtIndex(index) if index >= 0 # Public: Just remove the item at the given index. - removeItemAtIndex: (index, detach) -> + removeItemAtIndex: (index) -> item = @items[index] @showNextItem() if item is @activeItem and @items.length > 1 - @items.splice(index, 1) - @emit 'item-removed', item, index, detach + @suppressBlur => @items.splice(index, 1) # Public: Moves the given item to a the new index. moveItem: (item, newIndex) -> @@ -115,7 +114,7 @@ class PaneModel extends Model # Public: Moves the given item to another pane. moveItemToPane: (item, pane, index) -> pane.addItem(item, index) - @removeItem(item, true) + @removeItem(item) # Public: Remove the currently active item. destroyActiveItem: -> diff --git a/src/pane.coffee b/src/pane.coffee index 0121c8d36..c145c5b6b 100644 --- a/src/pane.coffee +++ b/src/pane.coffee @@ -53,6 +53,8 @@ class Pane extends View @is(':focus') or @is(':has(:focus)') handleEvents: -> + @subscribe @model, 'destroyed', => @remove() + @subscribe @model.$activeItem, 'value', @onActiveItemChanged @subscribe @model, 'item-added', @onItemAdded @subscribe @model, 'item-removed', @onItemRemoved @@ -158,12 +160,10 @@ class Pane extends View @trigger 'pane:active-item-changed', [item] onItemAdded: (item, index) => - if typeof item.on is 'function' - @subscribe item, 'destroyed', => @destroyItem(item) @trigger 'pane:item-added', [item, index] - onItemRemoved: (item, index, detach) => - @cleanupItemView(item, detach) + onItemRemoved: (item, index) => + @cleanupItemView(item) @trigger 'pane:item-removed', [item, index] onItemMoved: (item, newIndex) => @@ -181,27 +181,15 @@ class Pane extends View @trigger 'pane:active-item-title-changed' # Private: - cleanupItemView: (item, detach) -> + cleanupItemView: (item) -> if item instanceof $ viewToRemove = item else if viewToRemove = @viewsByItem.get(item) @viewsByItem.delete(item) - if @items.length > 0 - if detach and item is viewToRemove - viewToRemove?.detach() - else if detach and viewToRemove?.setModel - viewToRemove.setModel(null) # dont want to destroy the model, so set to null - viewToRemove.remove() - else - viewToRemove?.remove() - else - if detach and item is viewToRemove - viewToRemove?.detach() - else if detach and viewToRemove?.setModel - viewToRemove.setModel(null) # dont want to destroy the model, so set to null - - @parent().view().removeChild(this) + if viewToRemove? + viewToRemove.setModel?(null) + viewToRemove.detach() # Private: viewForItem: (item) -> @@ -231,6 +219,9 @@ class Pane extends View getContainer: -> @closest('.panes').view() + beforeRemove: -> + @trigger 'pane:removed', [this] + # Private: remove: (selector, keepData) -> return super if keepData