|
1 | 1 | (function(){
|
2 | 2 | 'use strict';
|
3 | 3 |
|
4 |
| - angular.module('ui.grid').directive('uiGridHeaderCell', ['$compile', '$timeout', '$window', '$document', 'gridUtil', 'uiGridConstants', 'ScrollEvent', |
5 |
| - function ($compile, $timeout, $window, $document, gridUtil, uiGridConstants, ScrollEvent) { |
| 4 | + angular.module('ui.grid').directive('uiGridHeaderCell', ['$compile', '$timeout', '$window', '$document', 'gridUtil', 'uiGridConstants', 'ScrollEvent', 'i18nService', |
| 5 | + function ($compile, $timeout, $window, $document, gridUtil, uiGridConstants, ScrollEvent, i18nService) { |
6 | 6 | // Do stuff after mouse has been down this many ms on the header cell
|
7 | 7 | var mousedownTimeout = 500;
|
8 | 8 | var changeModeTimeout = 500; // length of time between a touch event and a mouse event being recognised again, and vice versa
|
|
14 | 14 | row: '=',
|
15 | 15 | renderIndex: '='
|
16 | 16 | },
|
17 |
| - require: ['?^uiGrid', '^uiGridRenderContainer'], |
| 17 | + require: ['^uiGrid', '^uiGridRenderContainer'], |
18 | 18 | replace: true,
|
19 | 19 | compile: function() {
|
20 | 20 | return {
|
21 | 21 | pre: function ($scope, $elm, $attrs) {
|
22 | 22 | var cellHeader = $compile($scope.col.headerCellTemplate)($scope);
|
23 | 23 | $elm.append(cellHeader);
|
24 | 24 | },
|
25 |
| - |
| 25 | + |
26 | 26 | post: function ($scope, $elm, $attrs, controllers) {
|
27 | 27 | var uiGridCtrl = controllers[0];
|
28 | 28 | var renderContainerCtrl = controllers[1];
|
29 | 29 |
|
| 30 | + $scope.i18n = { |
| 31 | + headerCell: i18nService.getSafeText('headerCell'), |
| 32 | + sort: i18nService.getSafeText('sort') |
| 33 | + }; |
| 34 | + $scope.getSortDirectionAriaLabel = function(){ |
| 35 | + var col = $scope.col; |
| 36 | + //Trying to recreate this sort of thing but it was getting messy having it in the template. |
| 37 | + //Sort direction {{col.sort.direction == asc ? 'ascending' : ( col.sort.direction == desc ? 'descending':'none')}}. {{col.sort.priority ? {{columnPriorityText}} {{col.sort.priority}} : ''} |
| 38 | + var sortDirectionText = col.sort.direction === uiGridConstants.ASC ? $scope.i18n.sort.ascending : ( col.sort.direction === uiGridConstants.DESC ? $scope.i18n.sort.descending : $scope.i18n.sort.none); |
| 39 | + var label = sortDirectionText; |
| 40 | + //Append the priority if it exists |
| 41 | + if (col.sort.priority) { |
| 42 | + label = label + '. ' + $scope.i18n.headerCell.priority + ' ' + col.sort.priority; |
| 43 | + } |
| 44 | + return label; |
| 45 | + }; |
| 46 | + |
30 | 47 | $scope.grid = uiGridCtrl.grid;
|
31 | 48 |
|
32 | 49 | $scope.renderContainer = uiGridCtrl.grid.renderContainers[renderContainerCtrl.containerId];
|
33 |
| - |
| 50 | + |
34 | 51 | var initColClass = $scope.col.getColClass(false);
|
35 | 52 | $elm.addClass(initColClass);
|
36 |
| - |
| 53 | + |
37 | 54 | // Hide the menu by default
|
38 | 55 | $scope.menuShown = false;
|
39 |
| - |
| 56 | + |
40 | 57 | // Put asc and desc sort directions in scope
|
41 | 58 | $scope.asc = uiGridConstants.ASC;
|
42 | 59 | $scope.desc = uiGridConstants.DESC;
|
43 |
| - |
| 60 | + |
44 | 61 | // Store a reference to menu element
|
45 | 62 | var $colMenu = angular.element( $elm[0].querySelectorAll('.ui-grid-header-cell-menu') );
|
46 |
| - |
| 63 | + |
47 | 64 | var $contentsElm = angular.element( $elm[0].querySelectorAll('.ui-grid-cell-contents') );
|
48 |
| - |
| 65 | + |
49 | 66 |
|
50 | 67 | // apply any headerCellClass
|
51 | 68 | var classAdded;
|
52 | 69 | var previousMouseX;
|
53 | 70 |
|
54 | 71 | // filter watchers
|
55 | 72 | var filterDeregisters = [];
|
56 |
| - |
57 |
| - |
58 |
| - /* |
| 73 | + |
| 74 | + |
| 75 | + /* |
59 | 76 | * Our basic approach here for event handlers is that we listen for a down event (mousedown or touchstart).
|
60 |
| - * Once we have a down event, we need to work out whether we have a click, a drag, or a |
61 |
| - * hold. A click would sort the grid (if sortable). A drag would be used by moveable, so |
| 77 | + * Once we have a down event, we need to work out whether we have a click, a drag, or a |
| 78 | + * hold. A click would sort the grid (if sortable). A drag would be used by moveable, so |
62 | 79 | * we ignore it. A hold would open the menu.
|
63 |
| - * |
| 80 | + * |
64 | 81 | * So, on down event, we put in place handlers for move and up events, and a timer. If the
|
65 |
| - * timer expires before we see a move or up, then we have a long press and hence a column menu open. |
66 |
| - * If the up happens before the timer, then we have a click, and we sort if the column is sortable. |
| 82 | + * timer expires before we see a move or up, then we have a long press and hence a column menu open. |
| 83 | + * If the up happens before the timer, then we have a click, and we sort if the column is sortable. |
67 | 84 | * If a move happens before the timer, then we are doing column move, so we do nothing, the moveable feature
|
68 | 85 | * will handle it.
|
69 |
| - * |
| 86 | + * |
70 | 87 | * To deal with touch enabled devices that also have mice, we only create our handlers when
|
71 |
| - * we get the down event, and we create the corresponding handlers - if we're touchstart then |
| 88 | + * we get the down event, and we create the corresponding handlers - if we're touchstart then |
72 | 89 | * we get touchmove and touchend, if we're mousedown then we get mousemove and mouseup.
|
73 |
| - * |
| 90 | + * |
74 | 91 | * We also suppress the click action whilst this is happening - otherwise after the mouseup there
|
75 | 92 | * will be a click event and that can cause the column menu to close
|
76 | 93 | *
|
77 | 94 | */
|
78 |
| - |
| 95 | + |
79 | 96 | $scope.downFn = function( event ){
|
80 | 97 | event.stopPropagation();
|
81 | 98 |
|
82 | 99 | if (typeof(event.originalEvent) !== 'undefined' && event.originalEvent !== undefined) {
|
83 | 100 | event = event.originalEvent;
|
84 | 101 | }
|
85 |
| - |
| 102 | + |
86 | 103 | // Don't show the menu if it's not the left button
|
87 | 104 | if (event.button && event.button !== 0) {
|
88 | 105 | return;
|
|
91 | 108 |
|
92 | 109 | $scope.mousedownStartTime = (new Date()).getTime();
|
93 | 110 | $scope.mousedownTimeout = $timeout(function() { }, mousedownTimeout);
|
94 |
| - |
| 111 | + |
95 | 112 | $scope.mousedownTimeout.then(function () {
|
96 | 113 | if ( $scope.colMenu ) {
|
97 | 114 | uiGridCtrl.columnMenuScope.showMenu($scope.col, $elm, event);
|
98 | 115 | }
|
99 | 116 | });
|
100 | 117 |
|
101 | 118 | uiGridCtrl.fireEvent(uiGridConstants.events.COLUMN_HEADER_CLICK, {event: event, columnName: $scope.col.colDef.name});
|
102 |
| - |
| 119 | + |
103 | 120 | $scope.offAllEvents();
|
104 | 121 | if ( event.type === 'touchstart'){
|
105 | 122 | $document.on('touchend', $scope.upFn);
|
|
109 | 126 | $document.on('mousemove', $scope.moveFn);
|
110 | 127 | }
|
111 | 128 | };
|
112 |
| - |
| 129 | + |
113 | 130 | $scope.upFn = function( event ){
|
114 | 131 | event.stopPropagation();
|
115 | 132 | $timeout.cancel($scope.mousedownTimeout);
|
|
118 | 135 |
|
119 | 136 | var mousedownEndTime = (new Date()).getTime();
|
120 | 137 | var mousedownTime = mousedownEndTime - $scope.mousedownStartTime;
|
121 |
| - |
| 138 | + |
122 | 139 | if (mousedownTime > mousedownTimeout) {
|
123 | 140 | // long click, handled above with mousedown
|
124 | 141 | }
|
|
129 | 146 | }
|
130 | 147 | }
|
131 | 148 | };
|
132 |
| - |
| 149 | + |
133 | 150 | $scope.moveFn = function( event ){
|
134 | 151 | // Chrome is known to fire some bogus move events.
|
135 | 152 | var changeValue = event.pageX - previousMouseX;
|
|
140 | 157 | $scope.offAllEvents();
|
141 | 158 | $scope.onDownEvents(event.type);
|
142 | 159 | };
|
143 |
| - |
| 160 | + |
144 | 161 | $scope.clickFn = function ( event ){
|
145 | 162 | event.stopPropagation();
|
146 | 163 | $contentsElm.off('click', $scope.clickFn);
|
147 | 164 | };
|
148 |
| - |
| 165 | + |
149 | 166 |
|
150 | 167 | $scope.offAllEvents = function(){
|
151 | 168 | $contentsElm.off('touchstart', $scope.downFn);
|
|
156 | 173 |
|
157 | 174 | $document.off('touchmove', $scope.moveFn);
|
158 | 175 | $document.off('mousemove', $scope.moveFn);
|
159 |
| - |
| 176 | + |
160 | 177 | $contentsElm.off('click', $scope.clickFn);
|
161 | 178 | };
|
162 |
| - |
| 179 | + |
163 | 180 | $scope.onDownEvents = function( type ){
|
164 | 181 | // If there is a previous event, then wait a while before
|
165 | 182 | // activating the other mode - i.e. if the last event was a touch event then
|
|
172 | 189 | $contentsElm.on('click', $scope.clickFn);
|
173 | 190 | $contentsElm.on('touchstart', $scope.downFn);
|
174 | 191 | $timeout(function(){
|
175 |
| - $contentsElm.on('mousedown', $scope.downFn); |
| 192 | + $contentsElm.on('mousedown', $scope.downFn); |
176 | 193 | }, changeModeTimeout);
|
177 | 194 | break;
|
178 | 195 | case 'mousemove':
|
179 | 196 | case 'mouseup':
|
180 | 197 | $contentsElm.on('click', $scope.clickFn);
|
181 | 198 | $contentsElm.on('mousedown', $scope.downFn);
|
182 | 199 | $timeout(function(){
|
183 |
| - $contentsElm.on('touchstart', $scope.downFn); |
| 200 | + $contentsElm.on('touchstart', $scope.downFn); |
184 | 201 | }, changeModeTimeout);
|
185 | 202 | break;
|
186 | 203 | default:
|
187 | 204 | $contentsElm.on('click', $scope.clickFn);
|
188 | 205 | $contentsElm.on('touchstart', $scope.downFn);
|
189 | 206 | $contentsElm.on('mousedown', $scope.downFn);
|
190 |
| - } |
| 207 | + } |
191 | 208 | };
|
192 |
| - |
| 209 | + |
193 | 210 |
|
194 | 211 | var updateHeaderOptions = function( grid ){
|
195 | 212 | var contents = $elm;
|
196 | 213 | if ( classAdded ){
|
197 | 214 | contents.removeClass( classAdded );
|
198 | 215 | classAdded = null;
|
199 | 216 | }
|
200 |
| - |
| 217 | + |
201 | 218 | if (angular.isFunction($scope.col.headerCellClass)) {
|
202 | 219 | classAdded = $scope.col.headerCellClass($scope.grid, $scope.row, $scope.col, $scope.rowRenderIndex, $scope.colRenderIndex);
|
203 | 220 | }
|
204 | 221 | else {
|
205 | 222 | classAdded = $scope.col.headerCellClass;
|
206 | 223 | }
|
207 | 224 | contents.addClass(classAdded);
|
208 |
| - |
| 225 | + |
209 | 226 | var rightMostContainer = $scope.grid.renderContainers['right'] ? $scope.grid.renderContainers['right'] : $scope.grid.renderContainers['body'];
|
210 | 227 | $scope.isLastCol = ( $scope.col === rightMostContainer.visibleColumnCache[ rightMostContainer.visibleColumnCache.length - 1 ] );
|
211 | 228 |
|
|
216 | 233 | else {
|
217 | 234 | $scope.sortable = false;
|
218 | 235 | }
|
219 |
| - |
| 236 | + |
220 | 237 | // Figure out whether this column is filterable or not
|
221 | 238 | var oldFilterable = $scope.filterable;
|
222 | 239 | if (uiGridCtrl.grid.options.enableFiltering && $scope.col.enableFiltering) {
|
|
240 | 257 | uiGridCtrl.grid.api.core.notifyDataChange( uiGridConstants.dataChange.COLUMN );
|
241 | 258 | uiGridCtrl.grid.queueGridRefresh();
|
242 | 259 | }
|
243 |
| - })); |
| 260 | + })); |
244 | 261 | });
|
245 | 262 | $scope.$on('$destroy', function() {
|
246 | 263 | filterDeregisters.forEach( function(filterDeregister) {
|
|
251 | 268 | filterDeregisters.forEach( function(filterDeregister) {
|
252 | 269 | filterDeregister();
|
253 | 270 | });
|
254 |
| - } |
255 |
| - |
| 271 | + } |
| 272 | + |
256 | 273 | }
|
257 |
| - |
| 274 | + |
258 | 275 | // figure out whether we support column menus
|
259 |
| - if ($scope.col.grid.options && $scope.col.grid.options.enableColumnMenus !== false && |
| 276 | + if ($scope.col.grid.options && $scope.col.grid.options.enableColumnMenus !== false && |
260 | 277 | $scope.col.colDef && $scope.col.colDef.enableColumnMenu !== false){
|
261 | 278 | $scope.colMenu = true;
|
262 | 279 | } else {
|
263 | 280 | $scope.colMenu = false;
|
264 | 281 | }
|
265 |
| - |
| 282 | + |
266 | 283 | /**
|
267 | 284 | * @ngdoc property
|
268 | 285 | * @name enableColumnMenu
|
|
281 | 298 | * column menus. Defaults to true.
|
282 | 299 | *
|
283 | 300 | */
|
284 |
| - |
| 301 | + |
285 | 302 | $scope.offAllEvents();
|
286 |
| - |
| 303 | + |
287 | 304 | if ($scope.sortable || $scope.colMenu) {
|
288 | 305 | $scope.onDownEvents();
|
289 |
| - |
| 306 | + |
290 | 307 | $scope.$on('$destroy', function () {
|
291 | 308 | $scope.offAllEvents();
|
292 | 309 | });
|
293 |
| - } |
| 310 | + } |
294 | 311 | };
|
295 | 312 |
|
296 | 313 | /*
|
|
307 | 324 | });
|
308 | 325 | */
|
309 | 326 | updateHeaderOptions();
|
310 |
| - |
| 327 | + |
311 | 328 | // Register a data change watch that would get triggered whenever someone edits a cell or modifies column defs
|
312 | 329 | var dataChangeDereg = $scope.grid.registerDataChangeCallback( updateHeaderOptions, [uiGridConstants.dataChange.COLUMN]);
|
313 | 330 |
|
314 |
| - $scope.$on( '$destroy', dataChangeDereg ); |
| 331 | + $scope.$on( '$destroy', dataChangeDereg ); |
315 | 332 |
|
316 | 333 | $scope.handleClick = function(event) {
|
317 | 334 | // If the shift key is being held down, add this column to the sort
|
318 | 335 | var add = false;
|
319 | 336 | if (event.shiftKey) {
|
320 | 337 | add = true;
|
321 | 338 | }
|
322 |
| - |
| 339 | + |
323 | 340 | // Sort this column then rebuild the grid's rows
|
324 | 341 | uiGridCtrl.grid.sortColumn($scope.col, add)
|
325 | 342 | .then(function () {
|
326 | 343 | if (uiGridCtrl.columnMenuScope) { uiGridCtrl.columnMenuScope.hideMenu(); }
|
327 | 344 | uiGridCtrl.grid.refresh();
|
328 | 345 | });
|
329 | 346 | };
|
330 |
| - |
| 347 | + |
331 | 348 |
|
332 | 349 | $scope.toggleMenu = function(event) {
|
333 | 350 | event.stopPropagation();
|
334 |
| - |
| 351 | + |
335 | 352 | // If the menu is already showing...
|
336 | 353 | if (uiGridCtrl.columnMenuScope.menuShown) {
|
337 | 354 | // ... and we're the column the menu is on...
|
|
0 commit comments