diff --git a/src/features/edit/js/gridEdit.js b/src/features/edit/js/gridEdit.js index 3a5b864757..f48664c654 100644 --- a/src/features/edit/js/gridEdit.js +++ b/src/features/edit/js/gridEdit.js @@ -369,8 +369,10 @@ * */ module.directive('uiGridCell', - ['$compile', '$injector', 'uiGridConstants', 'uiGridEditConstants', 'gridUtil', '$parse', 'uiGridEditService', - function ($compile, $injector, uiGridConstants, uiGridEditConstants, gridUtil, $parse, uiGridEditService) { + ['$compile', '$injector', '$timeout', 'uiGridConstants', 'uiGridEditConstants', 'gridUtil', '$parse', 'uiGridEditService', + function ($compile, $injector, $timeout, uiGridConstants, uiGridEditConstants, gridUtil, $parse, uiGridEditService) { + var touchstartTimeout = 500; + return { priority: -100, // run after default uiGridCell directive restrict: 'A', @@ -386,6 +388,7 @@ var inEdit = false; var isFocusedBeforeEdit = false; var cellModel; + var cancelTouchstartTimeout; registerBeginEditEvents(); @@ -395,6 +398,37 @@ if ($scope.col.colDef.enableCellEditOnFocus) { $elm.find('div').on('focus', beginEditFocus); } + + // Add touchstart handling. If the users starts a touch and it doesn't end after X milliseconds, then start the edit + $elm.on('touchstart', touchStart); + } + + function touchStart(event) { + // jQuery masks events + if (typeof(event.originalEvent) !== 'undefined' && event.originalEvent !== undefined) { + event = event.originalEvent; + } + + // Bind touchend handler + $elm.on('touchend', touchEnd); + + // Start a timeout + cancelTouchstartTimeout = $timeout(function() { }, touchstartTimeout); + + // Timeout's done! Start the edit + cancelTouchstartTimeout.then(function () { + // Use setTimeout to start the edit because beginEdit expects to be outside of $digest + setTimeout(beginEdit, 0); + + // Undbind the touchend handler, we don't need it anymore + $elm.off('touchend', touchEnd); + }); + } + + // Cancel any touchstart timeout + function touchEnd(event) { + $timeout.cancel(cancelTouchstartTimeout); + $elm.off('touchend', touchEnd); } function cancelBeginEditEvents() { @@ -403,6 +437,7 @@ if ($scope.col.colDef.enableCellEditOnFocus) { $elm.find('div').off('focus', beginEditFocus); } + $elm.off('touchstart', touchStart); } function beginEditFocus(evt) { @@ -634,8 +669,8 @@ * */ module.directive('uiGridEditor', - ['uiGridConstants', 'uiGridEditConstants', - function (uiGridConstants, uiGridEditConstants) { + ['gridUtil', 'uiGridConstants', 'uiGridEditConstants', + function (gridUtil, uiGridConstants, uiGridEditConstants) { return { scope: true, require: ['?^uiGrid', '?^uiGridRenderContainer'], diff --git a/src/features/resize-columns/js/ui-grid-column-resizer.js b/src/features/resize-columns/js/ui-grid-column-resizer.js index e0a7cdaa0d..31081afcdc 100644 --- a/src/features/resize-columns/js/ui-grid-column-resizer.js +++ b/src/features/resize-columns/js/ui-grid-column-resizer.js @@ -263,6 +263,19 @@ module.directive('uiGridColumnResizer', ['$document', 'gridUtil', 'uiGridConstants', 'columnBounds', 'uiGridResizeColumnsService', function ($document, gridUtil, uiGridConstants, columnBounds, uiGridResizeColumnsService) { var resizeOverlay = angular.element('
'); + var downEvent, upEvent, moveEvent; + + if (gridUtil.isTouchEnabled()) { + downEvent = 'touchstart'; + upEvent = 'touchend'; + moveEvent = 'touchmove'; + } + else { + downEvent = 'mousedown'; + upEvent = 'mouseup'; + moveEvent = 'mousemove'; + } + var resizer = { priority: 0, scope: { @@ -321,7 +334,7 @@ if (event.originalEvent) { event = event.originalEvent; } event.preventDefault(); - x = event.clientX - gridLeft; + x = (event.targetTouches ? event.targetTouches[0] : event).clientX - gridLeft; if (x < 0) { x = 0; } else if (x > uiGridCtrl.grid.gridWidth) { x = uiGridCtrl.grid.gridWidth; } @@ -379,12 +392,12 @@ resizeOverlay.remove(); // Resize the column - x = event.clientX - gridLeft; + x = (event.changedTouches ? event.changedTouches[0] : event).clientX - gridLeft; var xDiff = x - startX; if (xDiff === 0) { - $document.off('mouseup', mouseup); - $document.off('mousemove', mousemove); + $document.off(upEvent, mouseup); + $document.off(moveEvent, mousemove); return; } @@ -431,11 +444,11 @@ uiGridResizeColumnsService.fireColumnSizeChanged(uiGridCtrl.grid, col.colDef, xDiff); - $document.off('mouseup', mouseup); - $document.off('mousemove', mousemove); + $document.off(upEvent, mouseup); + $document.off(moveEvent, mousemove); } - $elm.on('mousedown', function(event, args) { + $elm.on(downEvent, function(event, args) { if (event.originalEvent) { event = event.originalEvent; } event.stopPropagation(); @@ -444,7 +457,7 @@ gridLeft = uiGridCtrl.grid.element[0].getBoundingClientRect().left; // Get the starting X position, which is the X coordinate of the click minus the grid's offset - startX = event.clientX - gridLeft; + startX = (event.targetTouches ? event.targetTouches[0] : event).clientX - gridLeft; // Append the resizer overlay uiGridCtrl.grid.element.append(resizeOverlay); @@ -453,8 +466,8 @@ resizeOverlay.css({ left: startX }); // Add handlers for mouse move and up events - $document.on('mouseup', mouseup); - $document.on('mousemove', mousemove); + $document.on(upEvent, mouseup); + $document.on(moveEvent, mousemove); }); // On doubleclick, resize to fit all rendered cells @@ -539,10 +552,10 @@ }); $elm.on('$destroy', function() { - $elm.off('mousedown'); + $elm.off(downEvent); $elm.off('dblclick'); - $document.off('mousemove', mousemove); - $document.off('mouseup', mouseup); + $document.off(moveEvent, mousemove); + $document.off(upEvent, mouseup); }); } }; diff --git a/src/features/resize-columns/test/resizeColumns.spec.js b/src/features/resize-columns/test/resizeColumns.spec.js index 3379e7b4ff..59ba0ebc95 100644 --- a/src/features/resize-columns/test/resizeColumns.spec.js +++ b/src/features/resize-columns/test/resizeColumns.spec.js @@ -1,6 +1,8 @@ -describe('ui.grid.resizeColumns', function () { +ddescribe('ui.grid.resizeColumns', function () { var grid, gridUtil, gridScope, $scope, $compile, recompile, uiGridConstants; + var downEvent, upEvent, moveEvent; + var data = [ { "name": "Ethel Price", "gender": "female", "company": "Enersol" }, { "name": "Claudine Neal", "gender": "female", "company": "Sealoud" }, @@ -17,6 +19,17 @@ describe('ui.grid.resizeColumns', function () { uiGridConstants = _uiGridConstants_; gridUtil = _gridUtil_; + if (gridUtil.isTouchEnabled()) { + downEvent = 'touchstart'; + upEvent = 'touchend'; + moveEvent = 'touchmove'; + } + else { + downEvent = 'mousedown'; + upEvent = 'mouseup'; + moveEvent = 'mousemove'; + } + $scope.gridOpts = { enableColumnResizing: true, data: data @@ -133,7 +146,7 @@ describe('ui.grid.resizeColumns', function () { it('should cause the column separator overlay to be added', function () { var firstResizer = $(grid).find('[ui-grid-column-resizer]').first(); - firstResizer.trigger('mousedown'); + firstResizer.trigger(downEvent); $scope.$digest(); var overlay = $(grid).find('.ui-grid-resize-overlay'); @@ -156,7 +169,7 @@ describe('ui.grid.resizeColumns', function () { initialX = firstResizer.position().left; - $(firstResizer).simulate('mousedown', { clientX: initialX }); + $(firstResizer).simulate(downEvent, { clientX: initialX }); $scope.$digest(); // Get the overlay @@ -164,7 +177,7 @@ describe('ui.grid.resizeColumns', function () { initialOverlayX = $(overlay).position().left; xDiff = 100; - $(document).simulate('mousemove', { clientX: initialX + xDiff }); + $(document).simulate(moveEvent, { clientX: initialX + xDiff }); $scope.$digest(); }); @@ -186,7 +199,7 @@ describe('ui.grid.resizeColumns', function () { describe('then releasing the mouse', function () { beforeEach(function () { - $(document).simulate('mouseup', { clientX: initialX + xDiff }); + $(document).simulate(upEvent, { clientX: initialX + xDiff }); $scope.$digest(); }); @@ -243,10 +256,10 @@ describe('ui.grid.resizeColumns', function () { var firstResizer = $(grid).find('[ui-grid-column-resizer]').first(); initialX = firstResizer.position().left; - $(firstResizer).simulate('mousedown', { clientX: initialX }); + $(firstResizer).simulate(downEvent, { clientX: initialX }); $scope.$digest(); - $(document).simulate('mouseup', { clientX: initialX - minWidth }); + $(document).simulate(upEvent, { clientX: initialX - minWidth }); $scope.$digest(); }); @@ -297,10 +310,10 @@ describe('ui.grid.resizeColumns', function () { var firstResizer = $(grid).find('[ui-grid-column-resizer]').first(); initialX = firstResizer.position().left; - $(firstResizer).simulate('mousedown', { clientX: initialX }); + $(firstResizer).simulate(downEvent, { clientX: initialX }); $scope.$digest(); - $(document).simulate('mouseup', { clientX: initialX + maxWidth }); + $(document).simulate(upEvent, { clientX: initialX + maxWidth }); $scope.$digest(); }); diff --git a/src/js/core/directives/ui-grid-header-cell.js b/src/js/core/directives/ui-grid-header-cell.js index c75d4c166c..76a7f75db5 100644 --- a/src/js/core/directives/ui-grid-header-cell.js +++ b/src/js/core/directives/ui-grid-header-cell.js @@ -136,13 +136,15 @@ * */ - if ( $scope.sortable || $scope.colMenu ){ + if ($scope.sortable || $scope.colMenu) { // Long-click (for mobile) var cancelMousedownTimeout; var mousedownStartTime = 0; var downEvent = gridUtil.isTouchEnabled() ? 'touchstart' : 'mousedown'; $contentsElm.on(downEvent, function(event) { + gridUtil.logDebug('mouse event', event.type); + event.stopPropagation(); if (typeof(event.originalEvent) !== 'undefined' && event.originalEvent !== undefined) { @@ -203,6 +205,8 @@ if ($scope.sortable) { var clickEvent = gridUtil.isTouchEnabled() ? 'touchend' : 'click'; $contentsElm.on(clickEvent, function(event) { + gridUtil.logDebug('mouse event 2', event.type); + event.stopPropagation(); $timeout.cancel(cancelMousedownTimeout); @@ -211,10 +215,12 @@ var mousedownTime = mousedownEndTime - mousedownStartTime; if (mousedownTime > mousedownTimeout) { + gridUtil.logDebug('long click'); // long click, handled above with mousedown } else { // short click + gridUtil.logDebug('short click'); handleClick(event); } });