Created
January 5, 2017 14:23
-
-
Save sglanzer-deprecated/557d96e5ef4bc43f66472e65e4478df5 to your computer and use it in GitHub Desktop.
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
this.set('selectedItems', []) // TODO prefix | |
this.set('previousRangeEndItemIndex', null) // TODO prefix | |
this.set('rangeAnchorIndex', null) // TODO prefix | |
this.set('actions.select', function ({isCheckboxSelect, isRangeSelect, isCurrentlySelected, isSpecificSelect, item}) { | |
const selectedItems = this.get('selectedItems') | |
// Selects are proccessed in order of precedence: checkbox, specific, range, default | |
if (isCheckboxSelect) { | |
// Checkbox select works like a specific select, the target item | |
// is selected/deselected without modifying other existing selections | |
const isSelected = !isCurrentlySelected | |
this.setProperties({ | |
rangeAnchorItem: isSelected ? item : null, | |
previousRangeEndItemIndex: null | |
}) | |
if (isSelected) { | |
selectedItems.pushObject(item) | |
} else { | |
selectedItems.removeObject(item) | |
} | |
} else if (isSpecificSelect) { | |
// Select/deselect the item without modifying other existing selections | |
const isSelected = !isCurrentlySelected | |
this.setProperties({ | |
rangeAnchorItem: isSelected ? item : null, | |
previousRangeEndItemIndex: null | |
}) | |
if (isSelected) { | |
selectedItems.pushObject(item) | |
} else { | |
selectedItems.removeObject(item) | |
} | |
} else if (isRangeSelect) { | |
// The range anchor is the previous selection if: | |
// - the selection was positive | |
// - the selection wasn't the end of a range select | |
const rangeAnchorItem = this.get('rangeAnchorItem') | |
if (isNone(rangeAnchorItem)) { | |
// A range select without an established anchor is a specific select; | |
// however, a range select will always issue a positive select | |
this.setProperties({ | |
rangeAnchorItem: item, | |
previousRangeEndItemIndex: null | |
}) | |
selectedItems.pushObject(item) | |
} else { | |
// Select all of the items between the anchor and the item (inclusive) | |
// The range anchor doesn't update when selecting the end of a range | |
const items = this.get('items') | |
const rangeAnchorIndex = items.indexOf(rangeAnchorItem) | |
const itemIndex = items.indexOf(item) | |
const isSelectionAscending = rangeAnchorIndex < itemIndex | |
const rangeStartIndex = isSelectionAscending ? rangeAnchorIndex : itemIndex | |
const rangeEndIndex = isSelectionAscending ? itemIndex : rangeAnchorIndex | |
// If a previous range end was selected, deselect all selections no longer in the range | |
const previousRangeEndItemIndex = this.get('previousRangeEndItemIndex') | |
let deselectedItems = [] | |
if (!isNone(previousRangeEndItemIndex)) { | |
const isPreviousSelectionAscending = rangeAnchorIndex < previousRangeEndItemIndex | |
if (isSelectionAscending === isPreviousSelectionAscending) { | |
if (isSelectionAscending && itemIndex < previousRangeEndItemIndex) { | |
deselectedItems = items.slice(itemIndex + 1, previousRangeEndItemIndex + 1) | |
} else if (!isSelectionAscending && itemIndex > previousRangeEndItemIndex) { | |
deselectedItems = items.slice(previousRangeEndItemIndex, itemIndex) | |
} | |
} else if (isPreviousSelectionAscending) { | |
deselectedItems = items.slice(rangeAnchorIndex + 1, previousRangeEndItemIndex + 1) | |
} else { | |
deselectedItems = items.slice(previousRangeEndItemIndex, rangeAnchorIndex) | |
} | |
} | |
// Set the (now) previous range end item index | |
this.set('previousRangeEndItemIndex', itemIndex) | |
selectedItems.pushObjects(items.slice(rangeStartIndex, rangeEndIndex + 1)) | |
selectedItems.removeObjects(deselectedItems) | |
} | |
} else { | |
// If the item is part of a previous set of selections | |
// the item remains selected while the rest are deselected | |
const isInPreviousSelections = | |
selectedItems.get('length') > 1 && | |
selectedItems.findBy('id', item.get('id')) | |
const isSelected = isInPreviousSelections ? true : !isCurrentlySelected | |
this.setProperties({ | |
rangeAnchorItem: isSelected ? item : null, | |
previousRangeEndItemIndex: null | |
}) | |
// Default select clears out any prior selections | |
if (isSelected) { | |
selectedItems.setObjects([item]) | |
} else { | |
selectedItems.clear() | |
} | |
} | |
}) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment