diff --git a/client/src/js/directives/bhGridDateEditor.js b/client/src/js/directives/bhGridDateEditor.js index bed88abd29..2c99f4e10d 100644 --- a/client/src/js/directives/bhGridDateEditor.js +++ b/client/src/js/directives/bhGridDateEditor.js @@ -1,100 +1,46 @@ -/** forked from https://github.com/Joiler/ui-grid-edit-datepicker */ - -var app = angular.module('ui.grid.edit'); - -app.directive('uiGridEditDatepicker', ['$timeout', '$document', 'uiGridConstants', 'uiGridEditConstants', function($timeout, $document, uiGridConstants, uiGridEditConstants) { +/** originally forked from https://github.com/Joiler/ui-grid-edit-datepicker */ + +angular.module('ui.grid.edit') + .directive('uiGridEditDatepicker', uiGridEditDatePicker); + +uiGridEditDatePicker.$inject = [ + '$timeout', 'uiGridConstants', 'uiGridEditConstants' +]; + +/** + * @class uiGridEditDatePicker + * + * @description + * This directive implements a datepicker editor for angular's ui-grid. + */ +function uiGridEditDatePicker($timeout, uiGridConstants, uiGridEditConstants) { return { - template: function(element, attrs) { - var html = '
'; - return html; - }, + template : + '', require: ['?^uiGrid', '?^uiGridRenderContainer'], scope: true, - compile: function() { + compile: function () { return { - pre: function($scope, $elm, $attrs) { - - }, - post: function($scope, $elm, $attrs, controllers) { - var setCorrectPosition = function() { - var gridElement = $('.ui-grid-viewport'); - var gridPosition = { - width: gridElement.outerWidth(), - height: gridElement.outerHeight(), - offset: gridElement.offset() - }; - - var cellElement = $($elm); - var cellPosition = { - width: cellElement.outerWidth(), - height: cellElement.outerHeight(), - offset: cellElement.offset() - }; - - var datepickerElement = $('body > .dropdown-menu'); - var datepickerPosition = { - width: datepickerElement.outerWidth(), - height: datepickerElement.outerHeight() - }; - - var setCorrectTopPositionInGrid = function() { - var topPosition; - var freePixelsOnBottom = gridPosition.height - (cellPosition.offset.top - gridPosition.offset.top) - cellPosition.height; - var freePixelsOnTop = gridPosition.height - freePixelsOnBottom - cellPosition.height; - var requiredPixels = (datepickerPosition.height - cellPosition.height) / 2; - if (freePixelsOnBottom >= requiredPixels && freePixelsOnTop >= requiredPixels) { - topPosition = cellPosition.offset.top - requiredPixels + 10; - } else if (freePixelsOnBottom >= requiredPixels && freePixelsOnTop < requiredPixels) { - topPosition = cellPosition.offset.top - freePixelsOnTop + 10; - } else { - topPosition = gridPosition.height - datepickerPosition.height + gridPosition.offset.top - 20; - } - return topPosition; - }; - - var setCorrectTopPositionInWindow = function() { - var topPosition; - var windowHeight = window.innerHeight - 10; - - var freePixelsOnBottom = windowHeight - cellPosition.offset.top; - var freePixelsOnTop = windowHeight - freePixelsOnBottom - cellPosition.height; - var requiredPixels = (datepickerPosition.height - cellPosition.height) / 2; - if (freePixelsOnBottom >= requiredPixels && freePixelsOnTop >= requiredPixels) { - topPosition = cellPosition.offset.top - requiredPixels; - } else if (freePixelsOnBottom >= requiredPixels && freePixelsOnTop < requiredPixels) { - topPosition = cellPosition.offset.top - freePixelsOnTop; - } else { - topPosition = windowHeight - datepickerPosition.height - 10; - } - return topPosition; - }; - + post: function ($scope, $elm, $attrs, controllers) { - var newOffsetValues = {}; - - var isFreeOnRight = (gridPosition.width - (cellPosition.offset.left - gridPosition.offset.left) - cellPosition.width) > datepickerPosition.width; - if (isFreeOnRight) { - newOffsetValues.left = cellPosition.offset.left + cellPosition.width; - } else { - newOffsetValues.left = cellPosition.offset.left - datepickerPosition.width; - } - - if (datepickerPosition.height < gridPosition.height) { - newOffsetValues.top = setCorrectTopPositionInGrid(); - } else { - newOffsetValues.top = setCorrectTopPositionInWindow(); - } - - datepickerElement.offset(newOffsetValues); - datepickerElement.css('visibility', 'visible'); - }; - - $timeout(function() { - setCorrectPosition(); - }, 0); + // the original datepicker values + var originalValue = new Date($scope.row.entity[$scope.col.field]); + // bind datePickerValue to the correct value $scope.datePickerValue = new Date($scope.row.entity[$scope.col.field]); $scope.isOpen = true; + $scope.datepickerOptions = { initDate : new Date() }; + + var uiGridCtrl = controllers[0]; var renderContainerCtrl = controllers[1]; @@ -105,8 +51,7 @@ app.directive('uiGridEditDatepicker', ['$timeout', '$document', 'uiGridConstants if (!inDatepicker && evt.target.nodeName !== 'INPUT') { $scope.stopEdit(evt); } - } - else { + } else { $scope.stopEdit(evt); } }; @@ -116,10 +61,10 @@ app.directive('uiGridEditDatepicker', ['$timeout', '$document', 'uiGridConstants $scope.stopEdit(evt); }; - $scope.changeDate = function (evt) { - $scope.row.entity[$scope.col.field] = $scope.datePickerValue; - $scope.stopEdit(evt); - }; + // @todo - make sure this actually gets cleaned up when $scope is destroyed! + uiGridCtrl.grid.api.edit.on.cancelCellEdit($scope, function () { + $scope.stopEdit(); + }); $scope.$on(uiGridEditConstants.events.BEGIN_CELL_EDIT, function () { if (uiGridCtrl.grid.api.cellNav) { @@ -129,25 +74,32 @@ app.directive('uiGridEditDatepicker', ['$timeout', '$document', 'uiGridConstants } else { angular.element(document.querySelectorAll('.ui-grid-cell-contents')).on('click', onCellClick); } - angular.element(window).on('click', onWindowClick); - }); - $scope.$on('$destroy', function () { - angular.element(window).off('click', onWindowClick); - $('body > .dropdown-menu').remove(); + angular.element(window).on('click', onWindowClick); }); - $scope.stopEdit = function(evt) { + $scope.stopEdit = function (evt) { + $scope.row.entity[$scope.col.field] = $scope.datePickerValue; $scope.$emit(uiGridEditConstants.events.END_CELL_EDIT); }; - $elm.on('keydown', function(evt) { - switch (evt.keyCode) { - case uiGridConstants.keymap.ESC: - evt.stopPropagation(); - $scope.$emit(uiGridEditConstants.events.CANCEL_CELL_EDIT); - break; + // Make sure that the edit is canceled on the ESC key. The event is not + // propogated by uib-datepicker-popup. + // See: https://github.com/angular-ui/bootstrap/commit/000d6c309e7c2065576d535feaf6868ac06b75d0 + $scope.$watch('isOpen', function (isOpen) { + if (!isOpen) { + $timeout($scope.stopEdit, 0, false); } + }); + + // when we cancel the edit, we want to preserve the original value. + function cancelEdit() { + $scope.row.entity[$scope.col.field] = originalValue; + $scope.$emit(uiGridEditConstants.events.CANCEL_CELL_EDIT); + } + + // make sure we quit when we need to. + function handleKeydown(evt) { if (uiGridCtrl && uiGridCtrl.grid.api.cellNav) { evt.uiGridTargetRenderContainerId = renderContainerCtrl.containerId; if (uiGridCtrl.cellNav.handleKeyDown(evt) !== null) { @@ -163,10 +115,19 @@ app.directive('uiGridEditDatepicker', ['$timeout', '$document', 'uiGridConstants break; } } + return true; + } + + $elm.on('keydown', handleKeydown); + + $scope.$on('$destroy', function () { + angular.element(window).off('click', onWindowClick); + $('body > .dropdown-menu').remove(); + $elm.off('keydown', handleKeydown); }); } }; } }; -}]); +} diff --git a/client/src/js/services/grid/GridEditors.js b/client/src/js/services/grid/GridEditors.js index 37b9619d78..6c7a633ee1 100644 --- a/client/src/js/services/grid/GridEditors.js +++ b/client/src/js/services/grid/GridEditors.js @@ -16,12 +16,20 @@ function GridEditorService(util) { util.after(gridOptions, 'onRegisterApi', function onRegisterApi(api) { this.api = api; - this.api.edit.on.beginCellEdit(null, function beginCellEdit() { - if (gridOptions.authenticateEdits && !this.authenticated) { - this.requestUserAuthentication(); - } + this.api.edit.on.beginCellEdit(null, function beginCellEdit(row, column) { + console.log('[external] beginCellEdit'); + this.requestUserAuthentication(); }.bind(this)); + // notify that edits have been canceled + this.api.edit.on.cancelCellEdit(null, function cancelCellEdit(row, column) { + console.log('[external] cancelCellEdit'); + }); + + this.api.edit.on.afterCellEdit(null, function afterCellEdit(row, column) { + console.log('[external] afterCellEdit'); + }); + }.bind(this)); } @@ -34,7 +42,15 @@ function GridEditorService(util) { * user's edit session. It is currently unimplemented. */ GridEditors.prototype.requestUserAuthentication = function requestUserAuthentication() { - this.authenticated = true; + + // pretend we got authentication + //this.authenticated = true; + + // if we are not authenticated, cancel the edit + if (!this.authenticated) { + this.api.edit.raise.cancelCellEdit(); + } + // noop() };