|
213 | 213 | scrollTo: function (grid, $scope, rowEntity, colDef) {
|
214 | 214 | service.scrollTo(grid, $scope, rowEntity, colDef);
|
215 | 215 | },
|
| 216 | + |
216 | 217 | /**
|
217 | 218 | * @ngdoc function
|
218 | 219 | * @name getFocusedCell
|
|
389 | 390 | }
|
390 | 391 | },
|
391 | 392 |
|
| 393 | + /** |
| 394 | + * @ngdoc method |
| 395 | + * @methodOf ui.grid.cellNav.service:uiGridCellNavService |
| 396 | + * @name scrollToIfNecessary |
| 397 | + * @description Scrolls the grid to make a certain row and column combo visible, |
| 398 | + * in the case that it is not completely visible on the screen already. |
| 399 | + * @param {Grid} grid the grid you'd like to act upon, usually available |
| 400 | + * from gridApi.grid |
| 401 | + * @param {object} $scope a scope we can broadcast events from |
| 402 | + * @param {GridRow} gridRow row to make visible |
| 403 | + * @param {GridCol} gridCol column to make visible |
| 404 | + */ |
| 405 | + scrollToIfNecessary: function (grid, $scope, gridRow, gridCol) { |
| 406 | + var args = {}; |
| 407 | + |
| 408 | + // Alias the visible row and column caches |
| 409 | + var visRowCache = grid.renderContainers.body.visibleRowCache; |
| 410 | + var visColCache = grid.renderContainers.body.visibleColumnCache; |
| 411 | + |
| 412 | + // Get the top, left, right, and bottom "scrolled" edges of the grid |
| 413 | + var topBound = grid.renderContainers.body.prevScrollTop + grid.headerHeight; |
| 414 | + topBound = (topBound < 0) ? 0 : topBound; |
| 415 | + |
| 416 | + var leftBound = grid.renderContainers.body.prevScrollLeft; |
| 417 | + |
| 418 | + var bottomBound = grid.renderContainers.body.prevScrollTop + grid.gridHeight - grid.headerHeight; |
| 419 | + |
| 420 | + if (grid.horizontalScrollbarHeight) { |
| 421 | + bottomBound = bottomBound - grid.horizontalScrollbarHeight; |
| 422 | + } |
| 423 | + |
| 424 | + var rightBound = leftBound + grid.gridWidth; |
| 425 | + if (grid.verticalScrollbarWidth) { |
| 426 | + rightBound = rightBound - grid.verticalScrollbarWidth; |
| 427 | + } |
| 428 | + |
| 429 | + if (gridRow !== null) { |
| 430 | + var seekRowIndex = visRowCache.indexOf(gridRow); |
| 431 | + var totalRows = visRowCache.length; |
| 432 | + // var percentage = ( seekRowIndex + ( seekRowIndex / ( totalRows - 1 ) ) ) / totalRows; |
| 433 | + // args.y = { percentage: percentage }; |
| 434 | + var scrollLength = (grid.renderContainers.body.getCanvasHeight() - grid.renderContainers.body.getViewportHeight()); |
| 435 | + |
| 436 | + // Add the height of the native horizontal scrollbar, if it's there. Otherwise it will mask over the final row |
| 437 | + if (grid.horizontalScrollbarHeight && grid.horizontalScrollbarHeight > 0) { |
| 438 | + scrollLength = scrollLength + grid.horizontalScrollbarHeight; |
| 439 | + } |
| 440 | + |
| 441 | + // var pixelsToSeeRow = (scrollLength * percentage) + grid.options.rowHeight; |
| 442 | + var pixelsToSeeRow = ((seekRowIndex + 1) * grid.options.rowHeight); |
| 443 | + pixelsToSeeRow = (pixelsToSeeRow < 0) ? 0 : pixelsToSeeRow; |
| 444 | + |
| 445 | + var scrollPixels, percentage; |
| 446 | + if (pixelsToSeeRow < topBound) { |
| 447 | + scrollPixels = grid.renderContainers.body.prevScrollTop - (topBound - pixelsToSeeRow); |
| 448 | + percentage = scrollPixels / scrollLength; |
| 449 | + args.y = { percentage: percentage }; |
| 450 | + } |
| 451 | + else if (pixelsToSeeRow > bottomBound) { |
| 452 | + scrollPixels = pixelsToSeeRow - bottomBound + grid.renderContainers.body.prevScrollTop; |
| 453 | + percentage = scrollPixels / scrollLength; |
| 454 | + args.y = { percentage: percentage }; |
| 455 | + } |
| 456 | + } |
| 457 | + |
| 458 | + if (gridCol !== null) { |
| 459 | + var pixelsToSeeColumn = this.getLeftWidth(grid, gridCol) + gridCol.drawnWidth; |
| 460 | + |
| 461 | + if (pixelsToSeeColumn < leftBound || pixelsToSeeColumn > rightBound) { |
| 462 | + args.x = { percentage: this.getLeftWidth(grid, gridCol) / this.getLeftWidth(grid, visColCache[visColCache.length - 1] ) }; |
| 463 | + } |
| 464 | + } |
| 465 | + |
| 466 | + if (args.y || args.x) { |
| 467 | + $scope.$broadcast(uiGridConstants.events.GRID_SCROLL, args); |
| 468 | + } |
| 469 | + }, |
| 470 | + |
392 | 471 | /**
|
393 | 472 | * @ngdoc method
|
394 | 473 | * @methodOf ui.grid.cellNav.service:uiGridCellNavService
|
|
462 | 541 | </file>
|
463 | 542 | </example>
|
464 | 543 | */
|
465 |
| - module.directive('uiGridCellnav', ['gridUtil', 'uiGridCellNavService', 'uiGridCellNavConstants', |
466 |
| - function (gridUtil, uiGridCellNavService, uiGridCellNavConstants) { |
| 544 | + module.directive('uiGridCellnav', ['$log', 'gridUtil', 'uiGridCellNavService', 'uiGridCellNavConstants', |
| 545 | + function ($log, gridUtil, uiGridCellNavService, uiGridCellNavConstants) { |
467 | 546 | return {
|
468 | 547 | replace: true,
|
469 | 548 | priority: -150,
|
|
500 | 579 | };
|
501 | 580 | }]);
|
502 | 581 |
|
503 |
| - module.directive('uiGridRenderContainer', ['gridUtil', 'uiGridCellNavService', 'uiGridCellNavConstants', |
504 |
| - function (gridUtil, uiGridCellNavService, uiGridCellNavConstants) { |
| 582 | + module.directive('uiGridRenderContainer', ['$log', '$timeout', 'gridUtil', 'uiGridConstants', 'uiGridCellNavService', 'uiGridCellNavConstants', |
| 583 | + function ($log, $timeout, gridUtil, uiGridConstants, uiGridCellNavService, uiGridCellNavConstants) { |
505 | 584 | return {
|
506 | 585 | replace: true,
|
507 | 586 | priority: -99999, //this needs to run very last
|
508 |
| - require: '^uiGrid', |
| 587 | + require: ['^uiGrid', 'uiGridRenderContainer'], |
509 | 588 | scope: false,
|
510 | 589 | compile: function () {
|
511 | 590 | return {
|
512 | 591 | pre: function ($scope, $elm, $attrs, uiGridCtrl) {
|
513 | 592 | },
|
514 |
| - post: function ($scope, $elm, $attrs, uiGridCtrl) { |
| 593 | + post: function ($scope, $elm, $attrs, controllers) { |
| 594 | + var uiGridCtrl = controllers[0], |
| 595 | + renderContainerCtrl = controllers[1]; |
| 596 | + |
| 597 | + var containerId = renderContainerCtrl.containerId; |
| 598 | + |
515 | 599 | var grid = uiGridCtrl.grid;
|
516 | 600 | //needs to run last after all renderContainers are built
|
517 | 601 | uiGridCellNavService.decorateRenderContainers(grid);
|
| 602 | + |
| 603 | + $elm.on('keydown', function (evt) { |
| 604 | + var direction = uiGridCellNavService.getDirection(evt); |
| 605 | + if (direction === null) { |
| 606 | + return true; |
| 607 | + } |
| 608 | + |
| 609 | + var lastRowCol = uiGridCtrl.grid.api.cellNav.getFocusedCell(); |
| 610 | + var rowCol = uiGridCtrl.grid.renderContainers[containerId].cellNav.getNextRowCol(direction, lastRowCol.row, lastRowCol.col); |
| 611 | + // $log.debug('next id', rowCol.row.entity.id); |
| 612 | + |
| 613 | + uiGridCtrl.cellNav.broadcastCellNav(rowCol); |
| 614 | + uiGridCellNavService.scrollToIfNecessary(grid, $scope, rowCol.row, rowCol.col); |
| 615 | + // setTabEnabled(); |
| 616 | + |
| 617 | + evt.stopPropagation(); |
| 618 | + evt.preventDefault(); |
| 619 | + |
| 620 | + return false; |
| 621 | + }); |
| 622 | + |
| 623 | + // When there's a scroll event we need to make sure to re-focus the right row, because the cell contents may have changed |
| 624 | + $scope.$on(uiGridConstants.events.GRID_SCROLL, function (evt, args) { |
| 625 | + // We have to wrap in TWO timeouts so that we run AFTER the scroll event is resolved. |
| 626 | + $timeout(function () { |
| 627 | + $timeout(function () { |
| 628 | + var lastRowCol = uiGridCtrl.grid.api.cellNav.getFocusedCell(); |
| 629 | + uiGridCtrl.cellNav.broadcastCellNav(lastRowCol); |
| 630 | + }); |
| 631 | + }); |
| 632 | + }); |
518 | 633 | }
|
519 | 634 | };
|
520 | 635 | }
|
|
528 | 643 | * @restrict A
|
529 | 644 | * @description Stacks on top of ui.grid.uiGridCell to provide cell navigation
|
530 | 645 | */
|
531 |
| - module.directive('uiGridCell', ['uiGridCellNavService', 'gridUtil', 'uiGridCellNavConstants', |
532 |
| - function (uiGridCellNavService, gridUtil, uiGridCellNavConstants) { |
| 646 | + module.directive('uiGridCell', ['$log', '$timeout', 'uiGridCellNavService', 'gridUtil', 'uiGridCellNavConstants', 'uiGridConstants', |
| 647 | + function ($log, $timeout, uiGridCellNavService, gridUtil, uiGridCellNavConstants, uiGridConstants) { |
533 | 648 | return {
|
534 | 649 | priority: -150, // run after default uiGridCell directive and ui.grid.edit uiGridCell
|
535 | 650 | restrict: 'A',
|
|
542 | 657 |
|
543 | 658 | setTabEnabled();
|
544 | 659 |
|
545 |
| - $elm.on('keydown', function (evt) { |
546 |
| - var direction = uiGridCellNavService.getDirection(evt); |
547 |
| - if (direction === null) { |
548 |
| - return true; |
549 |
| - } |
| 660 | + // $elm.on('keydown', function (evt) { |
| 661 | + // var direction = uiGridCellNavService.getDirection(evt); |
| 662 | + // if (direction === null) { |
| 663 | + // return true; |
| 664 | + // } |
550 | 665 |
|
551 |
| - var rowCol = $scope.colContainer.cellNav.getNextRowCol(direction, $scope.row, $scope.col); |
| 666 | + // var rowCol = $scope.colContainer.cellNav.getNextRowCol(direction, $scope.row, $scope.col); |
| 667 | + // $log.debug('next id', rowCol.row.entity.id); |
552 | 668 |
|
553 |
| - uiGridCtrl.cellNav.broadcastCellNav(rowCol); |
554 |
| - setTabEnabled(); |
| 669 | + // uiGridCtrl.cellNav.broadcastCellNav(rowCol); |
| 670 | + // setTabEnabled(); |
555 | 671 |
|
556 |
| - evt.stopPropagation(); |
557 |
| - evt.preventDefault(); |
| 672 | + // evt.stopPropagation(); |
| 673 | + // evt.preventDefault(); |
558 | 674 |
|
559 |
| - return false; |
560 |
| - }); |
| 675 | + // return false; |
| 676 | + // }); |
561 | 677 |
|
562 |
| - $elm.find('div').on('focus', function (evt) { |
563 |
| - uiGridCtrl.cellNav.broadcastFocus($scope.row, $scope.col); |
| 678 | + $elm.find('div').on('click', function (evt) { |
| 679 | + uiGridCtrl.cellNav.broadcastCellNav(new RowCol($scope.row, $scope.col)); |
| 680 | + |
| 681 | + evt.stopPropagation(); |
564 | 682 | });
|
565 | 683 |
|
566 | 684 | //this event is fired for all cells. If the cell matches, then focus is set
|
|
569 | 687 | rowCol.col === $scope.col) {
|
570 | 688 | setFocused();
|
571 | 689 | }
|
| 690 | + else { |
| 691 | + clearFocus(); |
| 692 | + } |
| 693 | + |
| 694 | + // $scope.grid.queueRefresh(); |
572 | 695 | });
|
573 | 696 |
|
| 697 | + // $scope.$on(uiGridConstants.events.GRID_SCROLL, function (evt, args) { |
| 698 | + // clearFocus(); |
| 699 | + |
| 700 | + // $log.debug('scrollIndex 1', uiGridCtrl.grid.renderContainers.body.prevRowScrollIndex); |
| 701 | + |
| 702 | + // $timeout(function () { |
| 703 | + // $log.debug('scrollIndex 2', uiGridCtrl.grid.renderContainers.body.prevRowScrollIndex); |
| 704 | + |
| 705 | + // var lastRowCol = uiGridCtrl.grid.api.cellNav.getFocusedCell(); |
| 706 | + |
| 707 | + // if (lastRowCol === null) { |
| 708 | + // return; |
| 709 | + // } |
| 710 | + |
| 711 | + // if (lastRowCol.hasOwnProperty('row') && lastRowCol.row === $scope.row && lastRowCol.hasOwnProperty('col') && lastRowCol.col === $scope.col) { |
| 712 | + // setFocused(); |
| 713 | + // } |
| 714 | + // }); |
| 715 | + // }); |
| 716 | + |
574 | 717 | function setTabEnabled() {
|
575 | 718 | $elm.find('div').attr("tabindex", -1);
|
576 | 719 | }
|
577 | 720 |
|
578 | 721 | function setFocused() {
|
579 | 722 | var div = $elm.find('div');
|
580 | 723 | // gridUtil.logDebug('setFocused: ' + div[0].parentElement.className);
|
581 |
| - div[0].focus(); |
582 |
| - div.attr("tabindex", 0); |
583 |
| - $scope.grid.queueRefresh(); |
| 724 | + // div[0].focus(); |
| 725 | + // div.attr("tabindex", 0); |
| 726 | + div.addClass('ui-grid-cell-focus'); |
| 727 | + // $scope.grid.queueRefresh(); |
584 | 728 | }
|
585 | 729 |
|
| 730 | + function clearFocus() { |
| 731 | + var div = $elm.find('div'); |
| 732 | + // gridUtil.logDebug('setFocused: ' + div[0].parentElement.className); |
| 733 | + // div[0].focus(); |
| 734 | + // div.attr("tabindex", 0); |
| 735 | + div.removeClass('ui-grid-cell-focus'); |
| 736 | + // $scope.grid.queueRefresh(); |
| 737 | + } |
| 738 | + |
| 739 | + $scope.$on('$destroy', function () { |
| 740 | + $elm.find('div').off('click'); |
| 741 | + }); |
586 | 742 | }
|
587 | 743 | };
|
588 | 744 | }]);
|
|
0 commit comments