/*!
* ui-grid - v4.6.3 - 2018-08-04
* Copyright (c) 2018 ; License: MIT
*/
(function () {
'use strict';
/**
* @ngdoc overview
* @name ui.grid.selection
* @description
*
* # ui.grid.selection
* This module provides row selection
*
*
Stable This feature is stable. There should no longer be breaking api changes without a deprecation warning.
*
*
*/
var module = angular.module('ui.grid.selection', ['ui.grid']);
/**
* @ngdoc object
* @name ui.grid.selection.constant:uiGridSelectionConstants
*
* @description constants available in selection module
*/
module.constant('uiGridSelectionConstants', {
featureName: 'selection',
selectionRowHeaderColName: 'selectionRowHeaderCol'
});
// add methods to GridRow
angular.module('ui.grid').config(['$provide', function ($provide) {
$provide.decorator('GridRow', ['$delegate', function ($delegate) {
/**
* @ngdoc object
* @name ui.grid.selection.api:GridRow
*
* @description GridRow prototype functions added for selection
*/
/**
* @ngdoc object
* @name enableSelection
* @propertyOf ui.grid.selection.api:GridRow
* @description Enable row selection for this row, only settable by internal code.
*
* The grouping feature, for example, might set group header rows to not be selectable.
*
Defaults to true
*/
/**
* @ngdoc object
* @name isSelected
* @propertyOf ui.grid.selection.api:GridRow
* @description Selected state of row. Should be readonly. Make any changes to selected state using setSelected().
*
Defaults to false
*/
/**
* @ngdoc object
* @name isFocused
* @propertyOf ui.grid.selection.api:GridRow
* @description Focused state of row. Should be readonly. Make any changes to focused state using setFocused().
*
Defaults to false
*/
/**
* @ngdoc function
* @name setSelected
* @methodOf ui.grid.selection.api:GridRow
* @description Sets the isSelected property and updates the selectedCount
* Changes to isSelected state should only be made via this function
* @param {Boolean} selected value to set
*/
$delegate.prototype.setSelected = function (selected) {
if (selected !== this.isSelected) {
this.isSelected = selected;
this.grid.selection.selectedCount += selected ? 1 : -1;
}
};
/**
* @ngdoc function
* @name setFocused
* @methodOf ui.grid.selection.api:GridRow
* @description Sets the isFocused property
* Changes to isFocused state should only be made via this function
* @param {Boolean} val value to set
*/
$delegate.prototype.setFocused = function(val) {
if (val !== this.isFocused) {
this.grid.selection.focusedRow && (this.grid.selection.focusedRow.isFocused = false);
this.grid.selection.focusedRow = val ? this : null;
this.isFocused = val;
}
};
return $delegate;
}]);
}]);
/**
* @ngdoc service
* @name ui.grid.selection.service:uiGridSelectionService
*
* @description Services for selection features
*/
module.service('uiGridSelectionService',
function () {
var service = {
initializeGrid: function (grid) {
// add feature namespace and any properties to grid for needed
/**
* @ngdoc object
* @name ui.grid.selection.grid:selection
*
* @description Grid properties and functions added for selection
*/
grid.selection = {
lastSelectedRow: null,
/**
* @ngdoc object
* @name focusedRow
* @propertyOf ui.grid.selection.grid:selection
* @description Focused row.
*/
focusedRow: null,
selectAll: false
};
/**
* @ngdoc object
* @name selectedCount
* @propertyOf ui.grid.selection.grid:selection
* @description Current count of selected rows
* @example
* var count = grid.selection.selectedCount
*/
grid.selection.selectedCount = 0;
service.defaultGridOptions(grid.options);
/**
* @ngdoc object
* @name ui.grid.selection.api:PublicApi
*
* @description Public Api for selection feature
*/
var publicApi = {
events: {
selection: {
/**
* @ngdoc event
* @name rowFocusChanged
* @eventOf ui.grid.selection.api:PublicApi
* @description is raised after the row.isFocused state is changed
* @param {object} scope the scope associated with the grid
* @param {GridRow} row the row that was focused/unfocused
* @param {Event} evt object if raised from an event
*/
rowFocusChanged: function (scope, row, evt) {},
/**
* @ngdoc event
* @name rowSelectionChanged
* @eventOf ui.grid.selection.api:PublicApi
* @description is raised after the row.isSelected state is changed
* @param {object} scope the scope associated with the grid
* @param {GridRow} row the row that was selected/deselected
* @param {Event} evt object if raised from an event
*/
rowSelectionChanged: function (scope, row, evt) {
},
/**
* @ngdoc event
* @name rowSelectionChangedBatch
* @eventOf ui.grid.selection.api:PublicApi
* @description is raised after the row.isSelected state is changed
* in bulk, if the `enableSelectionBatchEvent` option is set to true
* (which it is by default). This allows more efficient processing
* of bulk events.
* @param {object} scope the scope associated with the grid
* @param {array} rows the rows that were selected/deselected
* @param {Event} evt object if raised from an event
*/
rowSelectionChangedBatch: function (scope, rows, evt) {
}
}
},
methods: {
selection: {
/**
* @ngdoc function
* @name toggleRowSelection
* @methodOf ui.grid.selection.api:PublicApi
* @description Toggles data row as selected or unselected
* @param {object} rowEntity gridOptions.data[] array instance
* @param {Event} evt object if raised from an event
*/
toggleRowSelection: function (rowEntity, evt) {
var row = grid.getRow(rowEntity);
if (row !== null) {
service.toggleRowSelection(grid, row, evt, grid.options.multiSelect, grid.options.noUnselect);
}
},
/**
* @ngdoc function
* @name selectRow
* @methodOf ui.grid.selection.api:PublicApi
* @description Select the data row
* @param {object} rowEntity gridOptions.data[] array instance
* @param {Event} evt object if raised from an event
*/
selectRow: function (rowEntity, evt) {
var row = grid.getRow(rowEntity);
if (row !== null && !row.isSelected) {
service.toggleRowSelection(grid, row, evt, grid.options.multiSelect, grid.options.noUnselect);
}
},
/**
* @ngdoc function
* @name selectRowByVisibleIndex
* @methodOf ui.grid.selection.api:PublicApi
* @description Select the specified row by visible index (i.e. if you
* specify row 0 you'll get the first visible row selected). In this context
* visible means of those rows that are theoretically visible (i.e. not filtered),
* rather than rows currently rendered on the screen.
* @param {number} rowNum index within the rowsVisible array
* @param {Event} evt object if raised from an event
*/
selectRowByVisibleIndex: function (rowNum, evt) {
var row = grid.renderContainers.body.visibleRowCache[rowNum];
if (row !== null && typeof (row) !== 'undefined' && !row.isSelected) {
service.toggleRowSelection(grid, row, evt, grid.options.multiSelect, grid.options.noUnselect);
}
},
/**
* @ngdoc function
* @name unSelectRow
* @methodOf ui.grid.selection.api:PublicApi
* @description UnSelect the data row
* @param {object} rowEntity gridOptions.data[] array instance
* @param {Event} evt object if raised from an event
*/
unSelectRow: function (rowEntity, evt) {
var row = grid.getRow(rowEntity);
if (row !== null && row.isSelected) {
service.toggleRowSelection(grid, row, evt, grid.options.multiSelect, grid.options.noUnselect);
}
},
/**
* @ngdoc function
* @name unSelectRowByVisibleIndex
* @methodOf ui.grid.selection.api:PublicApi
* @description Unselect the specified row by visible index (i.e. if you
* specify row 0 you'll get the first visible row unselected). In this context
* visible means of those rows that are theoretically visible (i.e. not filtered),
* rather than rows currently rendered on the screen.
* @param {number} rowNum index within the rowsVisible array
* @param {Event} evt object if raised from an event
*/
unSelectRowByVisibleIndex: function (rowNum, evt) {
var row = grid.renderContainers.body.visibleRowCache[rowNum];
if (row !== null && typeof (row) !== 'undefined' && row.isSelected) {
service.toggleRowSelection(grid, row, evt, grid.options.multiSelect, grid.options.noUnselect);
}
},
/**
* @ngdoc function
* @name selectAllRows
* @methodOf ui.grid.selection.api:PublicApi
* @description Selects all rows. Does nothing if multiSelect = false
* @param {Event} evt object if raised from an event
*/
selectAllRows: function (evt) {
if (grid.options.multiSelect !== false) {
var changedRows = [];
grid.rows.forEach(function (row) {
if (!row.isSelected && row.enableSelection !== false && grid.options.isRowSelectable(row) !== false) {
row.setSelected(true);
service.decideRaiseSelectionEvent(grid, row, changedRows, evt);
}
});
grid.selection.selectAll = true;
service.decideRaiseSelectionBatchEvent(grid, changedRows, evt);
}
},
/**
* @ngdoc function
* @name selectAllVisibleRows
* @methodOf ui.grid.selection.api:PublicApi
* @description Selects all visible rows. Does nothing if multiSelect = false
* @param {Event} evt object if raised from an event
*/
selectAllVisibleRows: function (evt) {
if (grid.options.multiSelect !== false) {
var changedRows = [];
grid.rows.forEach(function(row) {
if (row.visible) {
if (!row.isSelected && row.enableSelection !== false && grid.options.isRowSelectable(row) !== false) {
row.setSelected(true);
service.decideRaiseSelectionEvent(grid, row, changedRows, evt);
}
} else if (row.isSelected) {
row.setSelected(false);
service.decideRaiseSelectionEvent(grid, row, changedRows, evt);
}
});
grid.selection.selectAll = true;
service.decideRaiseSelectionBatchEvent(grid, changedRows, evt);
}
},
/**
* @ngdoc function
* @name clearSelectedRows
* @methodOf ui.grid.selection.api:PublicApi
* @description Unselects all rows
* @param {Event} evt object if raised from an event
*/
clearSelectedRows: function (evt) {
service.clearSelectedRows(grid, evt);
},
/**
* @ngdoc function
* @name getSelectedRows
* @methodOf ui.grid.selection.api:PublicApi
* @description returns all selectedRow's entity references
*/
getSelectedRows: function () {
return service.getSelectedRows(grid).map(function (gridRow) {
return gridRow.entity;
}).filter(function (entity) {
return entity.hasOwnProperty('$$hashKey') || !angular.isObject(entity);
});
},
/**
* @ngdoc function
* @name getSelectedGridRows
* @methodOf ui.grid.selection.api:PublicApi
* @description returns all selectedRow's as gridRows
*/
getSelectedGridRows: function () {
return service.getSelectedRows(grid);
},
/**
* @ngdoc function
* @name getSelectedCount
* @methodOf ui.grid.selection.api:PublicApi
* @description returns the number of rows selected
*/
getSelectedCount: function () {
return grid.selection.selectedCount;
},
/**
* @ngdoc function
* @name setMultiSelect
* @methodOf ui.grid.selection.api:PublicApi
* @description Sets the current gridOption.multiSelect to true or false
* @param {bool} multiSelect true to allow multiple rows
*/
setMultiSelect: function (multiSelect) {
grid.options.multiSelect = multiSelect;
},
/**
* @ngdoc function
* @name setModifierKeysToMultiSelect
* @methodOf ui.grid.selection.api:PublicApi
* @description Sets the current gridOption.modifierKeysToMultiSelect to true or false
* @param {bool} modifierKeysToMultiSelect true to only allow multiple rows when using ctrlKey or shiftKey is used
*/
setModifierKeysToMultiSelect: function (modifierKeysToMultiSelect) {
grid.options.modifierKeysToMultiSelect = modifierKeysToMultiSelect;
},
/**
* @ngdoc function
* @name getSelectAllState
* @methodOf ui.grid.selection.api:PublicApi
* @description Returns whether or not the selectAll checkbox is currently ticked. The
* grid doesn't automatically select rows when you add extra data - so when you add data
* you need to explicitly check whether the selectAll is set, and then call setVisible rows
* if it is
*/
getSelectAllState: function () {
return grid.selection.selectAll;
}
}
}
};
grid.api.registerEventsFromObject(publicApi.events);
grid.api.registerMethodsFromObject(publicApi.methods);
},
defaultGridOptions: function (gridOptions) {
// default option to true unless it was explicitly set to false
/**
* @ngdoc object
* @name ui.grid.selection.api:GridOptions
*
* @description GridOptions for selection feature, these are available to be
* set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}
*/
/**
* @ngdoc object
* @name enableRowSelection
* @propertyOf ui.grid.selection.api:GridOptions
* @description Enable row selection for entire grid.
*
Defaults to true
*/
gridOptions.enableRowSelection = gridOptions.enableRowSelection !== false;
/**
* @ngdoc object
* @name multiSelect
* @propertyOf ui.grid.selection.api:GridOptions
* @description Enable multiple row selection for entire grid
*
Defaults to true
*/
gridOptions.multiSelect = gridOptions.multiSelect !== false;
/**
* @ngdoc object
* @name noUnselect
* @propertyOf ui.grid.selection.api:GridOptions
* @description Prevent a row from being unselected. Works in conjunction
* with `multiselect = false` and `gridApi.selection.selectRow()` to allow
* you to create a single selection only grid - a row is always selected, you
* can only select different rows, you can't unselect the row.
*
Defaults to false
*/
gridOptions.noUnselect = gridOptions.noUnselect === true;
/**
* @ngdoc object
* @name modifierKeysToMultiSelect
* @propertyOf ui.grid.selection.api:GridOptions
* @description Enable multiple row selection only when using the ctrlKey or shiftKey. Requires multiSelect to be true.
*
Defaults to false
*/
gridOptions.modifierKeysToMultiSelect = gridOptions.modifierKeysToMultiSelect === true;
/**
* @ngdoc object
* @name enableRowHeaderSelection
* @propertyOf ui.grid.selection.api:GridOptions
* @description Enable a row header to be used for selection
*
Defaults to true
*/
gridOptions.enableRowHeaderSelection = gridOptions.enableRowHeaderSelection !== false;
/**
* @ngdoc object
* @name enableFullRowSelection
* @propertyOf ui.grid.selection.api:GridOptions
* @description Enable selection by clicking anywhere on the row. Defaults to
* false if `enableRowHeaderSelection` is true, otherwise defaults to true.
*/
if (typeof (gridOptions.enableFullRowSelection) === 'undefined') {
gridOptions.enableFullRowSelection = !gridOptions.enableRowHeaderSelection;
}
/**
* @ngdoc object
* @name enableFocusRowOnRowHeaderClick
* @propertyOf ui.grid.selection.api:GridOptions
* @description Enable focuse row by clicking on the row header. Defaults to
* true if `enableRowHeaderSelection` is true, otherwise defaults to false.
*/
gridOptions.enableFocusRowOnRowHeaderClick = (gridOptions.enableFocusRowOnRowHeaderClick !== false)
|| !gridOptions.enableRowHeaderSelection;
/**
* @ngdoc object
* @name enableSelectRowOnFocus
* @propertyOf ui.grid.selection.api:GridOptions
* @description Enable focuse row by clicking on the row anywhere. Defaults true.
*/
gridOptions.enableSelectRowOnFocus = (gridOptions.enableSelectRowOnFocus !== false);
/**
* @ngdoc object
* @name enableSelectAll
* @propertyOf ui.grid.selection.api:GridOptions
* @description Enable the select all checkbox at the top of the selectionRowHeader
*
Defaults to true
*/
gridOptions.enableSelectAll = gridOptions.enableSelectAll !== false;
/**
* @ngdoc object
* @name enableSelectionBatchEvent
* @propertyOf ui.grid.selection.api:GridOptions
* @description If selected rows are changed in bulk, either via the API or
* via the selectAll checkbox, then a separate event is fired. Setting this
* option to false will cause the rowSelectionChanged event to be called multiple times
* instead
*
Defaults to true
*/
gridOptions.enableSelectionBatchEvent = gridOptions.enableSelectionBatchEvent !== false;
/**
* @ngdoc object
* @name selectionRowHeaderWidth
* @propertyOf ui.grid.selection.api:GridOptions
* @description can be used to set a custom width for the row header selection column
*
Defaults to 30px
*/
gridOptions.selectionRowHeaderWidth = angular.isDefined(gridOptions.selectionRowHeaderWidth) ? gridOptions.selectionRowHeaderWidth : 30;
/**
* @ngdoc object
* @name enableFooterTotalSelected
* @propertyOf ui.grid.selection.api:GridOptions
* @description Shows the total number of selected items in footer if true.
*
Defaults to true.
*
GridOptions.showGridFooter must also be set to true.
*/
gridOptions.enableFooterTotalSelected = gridOptions.enableFooterTotalSelected !== false;
/**
* @ngdoc object
* @name isRowSelectable
* @propertyOf ui.grid.selection.api:GridOptions
* @description Makes it possible to specify a method that evaluates for each row and sets its "enableSelection" property.
*/
gridOptions.isRowSelectable = angular.isDefined(gridOptions.isRowSelectable) ? gridOptions.isRowSelectable : angular.noop;
},
/**
* @ngdoc function
* @name toggleRowSelection
* @methodOf ui.grid.selection.service:uiGridSelectionService
* @description Toggles row as selected or unselected
* @param {Grid} grid grid object
* @param {GridRow} row row to select or deselect
* @param {Event} evt object if resulting from event
* @param {bool} multiSelect if false, only one row at time can be selected
* @param {bool} noUnselect if true then rows cannot be unselected
*/
toggleRowSelection: function (grid, row, evt, multiSelect, noUnselect) {
if ( row.enableSelection === false ) {
return;
}
var selected = row.isSelected,
selectedRows;
if (!multiSelect) {
if (!selected) {
service.clearSelectedRows(grid, evt);
}
else {
selectedRows = service.getSelectedRows(grid);
if (selectedRows.length > 1) {
selected = false; // Enable reselect of the row
service.clearSelectedRows(grid, evt);
}
}
}
// only select row in this case
if (!(selected && noUnselect)) {
row.setSelected(!selected);
if (row.isSelected === true) {
grid.selection.lastSelectedRow = row;
}
selectedRows = service.getSelectedRows(grid);
grid.selection.selectAll = grid.rows.length === selectedRows.length;
grid.api.selection.raise.rowSelectionChanged(row, evt);
}
},
/**
* @ngdoc function
* @name shiftSelect
* @methodOf ui.grid.selection.service:uiGridSelectionService
* @description selects a group of rows from the last selected row using the shift key
* @param {Grid} grid grid object
* @param {GridRow} row clicked row
* @param {Event} evt object if raised from an event
* @param {bool} multiSelect if false, does nothing this is for multiSelect only
*/
shiftSelect: function (grid, row, evt, multiSelect) {
if (!multiSelect) {
return;
}
var selectedRows = service.getSelectedRows(grid);
var fromRow = selectedRows.length > 0 ? grid.renderContainers.body.visibleRowCache.indexOf(grid.selection.lastSelectedRow) : 0;
var toRow = grid.renderContainers.body.visibleRowCache.indexOf(row);
// reverse select direction
if (fromRow > toRow) {
var tmp = fromRow;
fromRow = toRow;
toRow = tmp;
}
var changedRows = [];
for (var i = fromRow; i <= toRow; i++) {
var rowToSelect = grid.renderContainers.body.visibleRowCache[i];
if (rowToSelect) {
if (!rowToSelect.isSelected && rowToSelect.enableSelection !== false) {
rowToSelect.setSelected(true);
grid.selection.lastSelectedRow = rowToSelect;
service.decideRaiseSelectionEvent(grid, rowToSelect, changedRows, evt);
}
}
}
service.decideRaiseSelectionBatchEvent(grid, changedRows, evt);
},
/**
* @ngdoc function
* @name getSelectedRows
* @methodOf ui.grid.selection.service:uiGridSelectionService
* @description Returns all the selected rows
* @param {Grid} grid grid object
*/
getSelectedRows: function (grid) {
return grid.rows.filter(function (row) {
return row.isSelected;
});
},
/**
* @ngdoc function
* @name clearSelectedRows
* @methodOf ui.grid.selection.service:uiGridSelectionService
* @description Clears all selected rows
* @param {Grid} grid grid object
* @param {Event} evt object if raised from an event
*/
clearSelectedRows: function (grid, evt) {
var changedRows = [];
service.getSelectedRows(grid).forEach(function (row) {
if (row.isSelected) {
row.setSelected(false);
service.decideRaiseSelectionEvent(grid, row, changedRows, evt);
}
});
grid.selection.selectAll = false;
grid.selection.selectedCount = 0;
service.decideRaiseSelectionBatchEvent(grid, changedRows, evt);
},
/**
* @ngdoc function
* @name decideRaiseSelectionEvent
* @methodOf ui.grid.selection.service:uiGridSelectionService
* @description Decides whether to raise a single event or a batch event
* @param {Grid} grid grid object
* @param {GridRow} row row that has changed
* @param {array} changedRows an array to which we can append the changed
* @param {Event} evt object if raised from an event
* row if we're doing batch events
*/
decideRaiseSelectionEvent: function (grid, row, changedRows, evt) {
if (!grid.options.enableSelectionBatchEvent) {
grid.api.selection.raise.rowSelectionChanged(row, evt);
}
else {
changedRows.push(row);
}
},
/**
* @ngdoc function
* @name raiseSelectionEvent
* @methodOf ui.grid.selection.service:uiGridSelectionService
* @description Decides whether we need to raise a batch event, and
* raises it if we do.
* @param {Grid} grid grid object
* @param {array} changedRows an array of changed rows, only populated
* @param {Event} evt object if raised from an event
* if we're doing batch events
*/
decideRaiseSelectionBatchEvent: function (grid, changedRows, evt) {
if (changedRows.length > 0) {
grid.api.selection.raise.rowSelectionChangedBatch(changedRows, evt);
}
}
};
return service;
});
/**
* @ngdoc directive
* @name ui.grid.selection.directive:uiGridSelection
* @element div
* @restrict A
*
* @description Adds selection features to grid
*
* @example
var app = angular.module('app', ['ui.grid', 'ui.grid.selection']);
app.controller('MainCtrl', ['$scope', function ($scope) {
$scope.data = [
{ name: 'Bob', title: 'CEO' },
{ name: 'Frank', title: 'Lowly Developer' }
];
$scope.columnDefs = [
{name: 'name', enableCellEdit: true},
{name: 'title', enableCellEdit: true}
];
}]);
*/
module.directive('uiGridSelection', ['uiGridSelectionConstants', 'uiGridSelectionService', 'uiGridConstants',
function (uiGridSelectionConstants, uiGridSelectionService, uiGridConstants) {
return {
replace: true,
priority: 0,
require: '^uiGrid',
scope: false,
compile: function () {
return {
pre: function ($scope, $elm, $attrs, uiGridCtrl) {
uiGridSelectionService.initializeGrid(uiGridCtrl.grid);
if (uiGridCtrl.grid.options.enableRowHeaderSelection) {
var selectionRowHeaderDef = {
name: uiGridSelectionConstants.selectionRowHeaderColName,
displayName: '',
width: uiGridCtrl.grid.options.selectionRowHeaderWidth,
minWidth: 10,
cellTemplate: 'ui-grid/selectionRowHeader',
headerCellTemplate: 'ui-grid/selectionHeaderCell',
enableColumnResizing: false,
enableColumnMenu: false,
exporterSuppressExport: true,
allowCellFocus: true
};
uiGridCtrl.grid.addRowHeaderColumn(selectionRowHeaderDef, 0);
}
var processorSet = false;
var processSelectableRows = function (rows) {
rows.forEach(function (row) {
row.enableSelection = uiGridCtrl.grid.options.isRowSelectable(row);
});
return rows;
};
var updateOptions = function () {
if (uiGridCtrl.grid.options.isRowSelectable !== angular.noop && processorSet !== true) {
uiGridCtrl.grid.registerRowsProcessor(processSelectableRows, 500);
processorSet = true;
}
};
updateOptions();
var dataChangeDereg = uiGridCtrl.grid.registerDataChangeCallback(updateOptions, [uiGridConstants.dataChange.OPTIONS]);
$scope.$on('$destroy', dataChangeDereg);
},
post: function ($scope, $elm, $attrs, uiGridCtrl) {
}
};
}
};
}]);
module.directive('uiGridSelectionRowHeaderButtons', ['$templateCache', 'uiGridSelectionService', 'gridUtil',
function ($templateCache, uiGridSelectionService, gridUtil) {
return {
replace: true,
restrict: 'E',
template: $templateCache.get('ui-grid/selectionRowHeaderButtons'),
scope: true,
require: '^uiGrid',
link: function ($scope, $elm, $attrs, uiGridCtrl) {
var self = uiGridCtrl.grid;
$scope.selectButtonClick = selectButtonClick;
$scope.selectButtonKeyDown = selectButtonKeyDown;
// On IE, prevent mousedowns on the select button from starting a selection.
// If this is not done and you shift+click on another row, the browser will select a big chunk of text
if (gridUtil.detectBrowser() === 'ie') {
$elm.on('mousedown', selectButtonMouseDown);
}
function selectButtonKeyDown(row, evt) {
if (evt.keyCode === 32) {
evt.preventDefault();
selectButtonClick(row, evt);
}
}
function selectButtonClick(row, evt) {
evt.stopPropagation();
if (evt.shiftKey) {
uiGridSelectionService.shiftSelect(self, row, evt, self.options.multiSelect);
}
else if (evt.ctrlKey || evt.metaKey) {
uiGridSelectionService.toggleRowSelection(self, row, evt,
self.options.multiSelect, self.options.noUnselect);
}
else if (row.groupHeader) {
uiGridSelectionService.toggleRowSelection(self, row, evt, self.options.multiSelect, self.options.noUnselect);
for (var i = 0; i < row.treeNode.children.length; i++) {
uiGridSelectionService.toggleRowSelection(self, row.treeNode.children[i].row, evt, self.options.multiSelect, self.options.noUnselect);
}
}
else {
uiGridSelectionService.toggleRowSelection(self, row, evt,
(self.options.multiSelect && !self.options.modifierKeysToMultiSelect), self.options.noUnselect);
}
self.options.enableFocusRowOnRowHeaderClick && row.setFocused(!row.isFocused) && self.api.selection.raise.rowFocusChanged(row, evt);
}
function selectButtonMouseDown(evt) {
if (evt.ctrlKey || evt.shiftKey) {
evt.target.onselectstart = function () { return false; };
window.setTimeout(function () { evt.target.onselectstart = null; }, 0);
}
}
$scope.$on('$destroy', function unbindEvents() {
$elm.off();
});
}
};
}]);
module.directive('uiGridSelectionSelectAllButtons', ['$templateCache', 'uiGridSelectionService',
function ($templateCache, uiGridSelectionService) {
return {
replace: true,
restrict: 'E',
template: $templateCache.get('ui-grid/selectionSelectAllButtons'),
scope: false,
link: function ($scope) {
var self = $scope.col.grid;
$scope.headerButtonKeyDown = function (evt) {
if (evt.keyCode === 32 || evt.keyCode === 13) {
evt.preventDefault();
$scope.headerButtonClick(evt);
}
};
$scope.headerButtonClick = function (evt) {
if (self.selection.selectAll) {
uiGridSelectionService.clearSelectedRows(self, evt);
if (self.options.noUnselect) {
self.api.selection.selectRowByVisibleIndex(0, evt);
}
self.selection.selectAll = false;
}
else if (self.options.multiSelect) {
self.api.selection.selectAllVisibleRows(evt);
self.selection.selectAll = true;
}
};
}
};
}]);
/**
* @ngdoc directive
* @name ui.grid.selection.directive:uiGridViewport
* @element div
*
* @description Stacks on top of ui.grid.uiGridViewport to alter the attributes used
* for the grid row
*/
module.directive('uiGridViewport',
function () {
return {
priority: -200, // run after default directive
scope: false,
compile: function ($elm) {
var rowRepeatDiv = angular.element($elm[0].querySelector('.ui-grid-canvas:not(.ui-grid-empty-base-layer-container)').children[0]),
newNgClass = "'ui-grid-row-selected': row.isSelected, 'ui-grid-row-focused': row.isFocused}",
existingNgClass = rowRepeatDiv.attr('ng-class');
if (existingNgClass) {
newNgClass = existingNgClass.slice(0, -1) + ',' + newNgClass;
} else {
newNgClass = '{' + newNgClass;
}
rowRepeatDiv.attr('ng-class', newNgClass);
return {
pre: function ($scope, $elm, $attrs, controllers) {},
post: function ($scope, $elm, $attrs, controllers) {}
};
}
};
});
/**
* @ngdoc directive
* @name ui.grid.selection.directive:uiGridCell
* @element div
* @restrict A
*
* @description Stacks on top of ui.grid.uiGridCell to provide selection feature
*/
module.directive('uiGridCell',
['uiGridConstants', 'uiGridSelectionService',
function (uiGridConstants, uiGridSelectionService) {
return {
priority: -200, // run after default uiGridCell directive
restrict: 'A',
require: '?^uiGrid',
scope: false,
link: function ($scope, $elm, $attrs, uiGridCtrl) {
var touchStartTime = 0,
touchTimeout = 300;
// Bind to keydown events in the render container
if (uiGridCtrl.grid.api.cellNav) {
uiGridCtrl.grid.api.cellNav.on.viewPortKeyDown($scope, function (evt, rowCol) {
if (rowCol === null ||
rowCol.row !== $scope.row ||
rowCol.col !== $scope.col) {
return;
}
if (evt.keyCode === uiGridConstants.keymap.SPACE && $scope.col.colDef.name === 'selectionRowHeaderCol') {
evt.preventDefault();
uiGridSelectionService.toggleRowSelection($scope.grid, $scope.row, evt,
($scope.grid.options.multiSelect && !$scope.grid.options.modifierKeysToMultiSelect),
$scope.grid.options.noUnselect);
$scope.$apply();
}
});
}
var selectCells = function (evt) {
// if you click on expandable icon doesn't trigger selection
if (evt.target.className === "ui-grid-icon-minus-squared" || evt.target.className === "ui-grid-icon-plus-squared") {
return;
}
// if we get a click, then stop listening for touchend
$elm.off('touchend', touchEnd);
if (evt.shiftKey) {
uiGridSelectionService.shiftSelect($scope.grid, $scope.row, evt, $scope.grid.options.multiSelect);
}
else if (evt.ctrlKey || evt.metaKey) {
uiGridSelectionService.toggleRowSelection($scope.grid, $scope.row, evt,
$scope.grid.options.multiSelect, $scope.grid.options.noUnselect);
}
else if ($scope.grid.options.enableSelectRowOnFocus) {
uiGridSelectionService.toggleRowSelection($scope.grid, $scope.row, evt,
($scope.grid.options.multiSelect && !$scope.grid.options.modifierKeysToMultiSelect),
$scope.grid.options.noUnselect);
}
$scope.row.setFocused(!$scope.row.isFocused);
$scope.grid.api.selection.raise.rowFocusChanged($scope.row, evt);
$scope.$apply();
// don't re-enable the touchend handler for a little while - some devices generate both, and it will
// take a little while to move your hand from the mouse to the screen if you have both modes of input
window.setTimeout(function () {
$elm.on('touchend', touchEnd);
}, touchTimeout);
};
var touchStart = function () {
touchStartTime = (new Date()).getTime();
// if we get a touch event, then stop listening for click
$elm.off('click', selectCells);
};
var touchEnd = function (evt) {
var touchEndTime = (new Date()).getTime();
var touchTime = touchEndTime - touchStartTime;
if (touchTime < touchTimeout) {
// short touch
selectCells(evt);
}
// don't re-enable the click handler for a little while - some devices generate both, and it will
// take a little while to move your hand from the screen to the mouse if you have both modes of input
window.setTimeout(function () {
$elm.on('click', selectCells);
}, touchTimeout);
};
function registerRowSelectionEvents() {
if ($scope.grid.options.enableRowSelection && $scope.grid.options.enableFullRowSelection && $scope.col.colDef.name !== 'selectionRowHeaderCol') {
$elm.addClass('ui-grid-disable-selection');
$elm.on('touchstart', touchStart);
$elm.on('touchend', touchEnd);
$elm.on('click', selectCells);
$scope.registered = true;
}
}
function unregisterRowSelectionEvents() {
if ($scope.registered) {
$elm.removeClass('ui-grid-disable-selection');
$elm.off('touchstart', touchStart);
$elm.off('touchend', touchEnd);
$elm.off('click', selectCells);
$scope.registered = false;
}
}
registerRowSelectionEvents();
// register a dataChange callback so that we can change the selection configuration dynamically
// if the user changes the options
var dataChangeUnreg = $scope.grid.registerDataChangeCallback(function () {
if ($scope.grid.options.enableRowSelection && $scope.grid.options.enableFullRowSelection &&
!$scope.registered) {
registerRowSelectionEvents();
}
else if ((!$scope.grid.options.enableRowSelection || !$scope.grid.options.enableFullRowSelection) &&
$scope.registered) {
unregisterRowSelectionEvents();
}
}, [uiGridConstants.dataChange.OPTIONS]);
$elm.on('$destroy', dataChangeUnreg);
}
};
}]);
module.directive('uiGridGridFooter', ['$compile', 'gridUtil', function ($compile, gridUtil) {
return {
restrict: 'EA',
replace: true,
priority: -1000,
require: '^uiGrid',
scope: true,
compile: function () {
return {
pre: function ($scope, $elm, $attrs, uiGridCtrl) {
if (!uiGridCtrl.grid.options.showGridFooter) {
return;
}
gridUtil.getTemplate('ui-grid/gridFooterSelectedItems')
.then(function (contents) {
var template = angular.element(contents);
var newElm = $compile(template)($scope);
angular.element($elm[0].getElementsByClassName('ui-grid-grid-footer')[0]).append(newElm);
});
},
post: function ($scope, $elm, $attrs, controllers) {
}
};
}
};
}]);
})();