$scope.handleRowClick = function($event, item) {
var index = $scope.list.indexValue(item);
+
if ($event.ctrlKey || $event.metaKey /* mac command */) {
- $scope.list.toggleOneSelection(index);
+ // control-click
+ if ($scope.list.toggleOneSelection(index))
+ self.lastSelectedRowIndex = index;
+
+ } else if ($event.shiftKey) {
+ // shift-click
+ if (!self.lastSelectedRowIndex) {
+ // no source row, just do a simple select
+ $scope.list.selectOne(index);
+ self.lastSelectedRowIndex = index;
+ return;
+ }
+
+ var selecting = false;
+ var ascending =
+ $scope.list.comesBefore(self.lastSelectedRowIndex, item);
+ var startPos =
+ $scope.list.indexOf(self.lastSelectedRowIndex);
+
+ // update to new last-selected
+ self.lastSelectedRowIndex = index;
+
+ while (true) {
+ startPos += ascending ? 1 : -1;
+ var curItem = $scope.list.items[startPos];
+ if (!curItem) break;
+ var curIdx = $scope.list.indexValue(curItem);
+ $scope.list.selected[curIdx] = true;
+ if (curIdx == index) break; // all done
+ }
+
} else {
$scope.list.selectOne(index);
+ self.lastSelectedRowIndex = index;
}
}
this.indexValue = function(item) {
if (!item) return null;
+ // assumes non-object's are bare indexes
+ if (typeof item != 'object') return item;
if (this.indexFieldAsFunction) {
return item[this.indexField]();
} else {
}
}
+ // returns true if item1 appears in the list before item2;
+ // false otherwise. this is slightly more efficient that
+ // finding the position of each then comparing them.
+ // item1 / item2 may be an item or an item index
+ this.comesBefore = function(itemOrIndex1, itemOrIndex2) {
+ var idx1 = this.indexValue(itemOrIndex1);
+ var idx2 = this.indexValue(itemOrIndex2);
+
+ // use for() for early exit
+ for (var i = 0; i < this.items.length; i++) {
+ var idx = this.indexValue(this.items[i]);
+ if (idx == idx1) return true;
+ if (idx == idx2) return false;
+ }
+ return false;
+ }
+
+ this.indexOf = function(item) {
+ var idx = this.indexValue(item);
+ for (var i = 0; i < this.items.length; i++) {
+ if (this.indexValue(this.items[i]) == idx)
+ return i;
+ }
+ return -1;
+ }
+
// returns item objects
this.selectedItems = function() {
var items = [];
}
// selects or deselects a row, without affecting the others
+ // returns true if the row is selected; false if de-selected.
this.toggleOneSelection = function(index) {
if (this.selected[index]) {
delete this.selected[index];
+ return false;
} else {
- this.selected[index] = true;
+ return this.selected[index] = true;
}
}