All files / dgrid CellSelection.js

0% Statements 0/91
0% Branches 0/80
0% Functions 0/5
0% Lines 0/91

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202                                                                                                                                                                                                                                                                                                                                                                                                                   
define([
	'dojo/_base/declare',
	'dojo/aspect',
	'dojo/dom-class',
	'dojo/on',
	'dojo/has',
	'./Selection'
], function (declare, aspect, domClass, listen, has, Selection) {
 
	return declare(Selection, {
		// summary:
		//		Add cell level selection capabilities to a grid. The grid will have a selection property and
		//		fire "dgrid-select" and "dgrid-deselect" events.
 
		// ensure we don't select when an individual cell is not identifiable
		selectionDelegate: '.dgrid-cell',
 
		_selectionTargetType: 'cells',
 
		_select: function (cell, toCell, value) {
			var i,
				id;
			if (typeof value === 'undefined') {
				// default to true
				value = true;
			}
			if (typeof cell !== 'object' || !('element' in cell)) {
				cell = this.cell(cell);
			}
			else if (!cell.row) {
				// Row object was passed instead of cell
				if (value && typeof value === 'object') {
					// value is a hash of true/false values
					for (id in value) {
						this._select(this.cell(cell.id, id), null, value[id]);
					}
				}
				else {
					// Select/deselect all columns in row
					for (id in this.columns) {
						this._select(this.cell(cell.id, id), null, value);
					}
				}
				return;
			}
			if (this.allowSelect(cell)) {
				var selection = this.selection,
					rowId = cell.row.id,
					previousRow = selection[rowId];
				if (!cell.column) {
					for (i in this.columns) {
						this._select(this.cell(rowId, i), null, value);
					}
					return;
				}
				var previous = previousRow && previousRow[cell.column.id];
				if (value === null) {
					// indicates a toggle
					value = !previous;
				}
				var element = cell.element;
				previousRow = previousRow || {};
				previousRow[cell.column.id] = value;
				this.selection[rowId] = previousRow;
 
				// Check for all-false objects to see if it can be deleted.
				// This prevents build-up of unnecessary iterations later.
				var hasSelected = false;
				for (i in previousRow) {
					if (previousRow[i] === true) {
						hasSelected = true;
						break;
					}
				}
				if (!hasSelected) {
					delete this.selection[rowId];
				}
 
				if (element) {
					// add or remove classes as appropriate
					if (value) {
						domClass.add(element, 'dgrid-selected' +
							(this.addUiClasses ? ' ui-state-active' : ''));
					}
					else {
						domClass.remove(element, 'dgrid-selected ui-state-active');
					}
				}
				/* jshint eqeqeq: false */
				// This comparison could coerce if previous is undefined; TODO: rewrite
				if (value != previous && element) {
					this._selectionEventQueues[(value ? '' : 'de') + 'select'].push(cell);
				}
				if (toCell) {
					if (!toCell.element) {
						toCell = this.cell(toCell);
					}
 
					if (!toCell || !toCell.row) {
						this._lastSelected = element;
						console.warn('The selection range has been reset because the ' +
							'beginning of the selection is no longer in the DOM. ' +
							'If you are using OnDemandList, you may wish to increase ' +
							'farOffRemoval to avoid this, but note that keeping more nodes ' +
							'in the DOM may impact performance.');
						return;
					}
 
					var toElement = toCell.element;
					var fromElement = cell.element;
					// Find if it is earlier or later in the DOM
					var direction = this._determineSelectionDirection(fromElement, toElement);
					if (!direction) {
						// The original element was actually replaced
						toCell = this.cell(
							document.getElementById(toCell.row.element.id), toElement.columnId);
						toElement = toCell && toCell.element;
						direction = this._determineSelectionDirection(fromElement, toElement);
					}
					// now we determine which columns are in the range
					var idFrom = cell.column.id,
						idTo = toCell.column.id,
						started,
						columnIds = [];
 
					for (id in this.columns) {
						if (started) {
							columnIds.push(id);
						}
						if (id === idFrom && (idFrom = columnIds) ||
								id === idTo && (idTo = columnIds)) {
							// Once found, mark it off so we don't hit it again
							columnIds.push(id);
							if (started || (idFrom == columnIds && id == idTo)) {
								// We are done if we hit the last ID, or if the IDs are the same
								break;
							}
							started = true;
						}
					}
					// now we iterate over rows
					var row = cell.row,
						nextNode = row.element;
					toElement = toCell.row.element;
					do {
						// looping through each row..
						// and now loop through each column to be selected
						for (i = 0; i < columnIds.length; i++) {
							cell = this.cell(nextNode, columnIds[i]);
							this._select(cell, null, value);
						}
						if (nextNode == toElement) {
							break;
						}
					} while ((nextNode = cell.row.element[direction]));
				}
			}
		},
 
		_determineSelectionDirection: function () {
			// Extend Selection to return next/previousSibling instead of down/up,
			// given how CellSelection#_select is written
			var result = this.inherited(arguments);
			if (result === 'down') {
				return 'nextSibling';
			}
			if (result === 'up') {
				return 'previousSibling';
			}
			return result;
		},
 
		isSelected: function (object, columnId) {
			// summary:
			//		Returns true if the indicated cell is selected.
 
			if (typeof object === 'undefined' || object === null) {
				return false;
			}
			if (!object.element) {
				object = this.cell(object, columnId);
			}
 
			// First check whether the given cell is indicated in the selection hash;
			// failing that, check if allSelected is true (testing against the
			// allowSelect method if possible)
			var rowId = object.row.id;
			if (rowId in this.selection) {
				return !!this.selection[rowId][object.column.id];
			}
			else {
				return this.allSelected && (!object.row.data || this.allowSelect(object));
			}
		},
		clearSelection: function (exceptId) {
			// disable exceptId in cell selection, since it would require double parameters
			exceptId = false;
			this.inherited(arguments);
		}
	});
});