Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
255 changes: 124 additions & 131 deletions src/features/move-columns/js/column-movable.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,17 @@
*/
colMovable: {
moveColumn: function (originalPosition, finalPosition) {
self.redrawColumnAtPosition(grid, originalPosition, finalPosition);
var columns = grid.columns;
var findPositionForRenderIndex = function (index) {
var position = index;
for (var i = 0; i <= position; i++) {
if (angular.isDefined(columns[i]) && ((angular.isDefined(columns[i].colDef.visible) && columns[i].colDef.visible === false) || columns[i].isRowHeader === true)) {
position++;
}
}
return position;
};
self.redrawColumnAtPosition(grid, findPositionForRenderIndex(originalPosition), findPositionForRenderIndex(finalPosition));
}
}
}
Expand Down Expand Up @@ -110,22 +120,9 @@
return $q.all(promises);
},
redrawColumnAtPosition: function (grid, originalPosition, newPosition) {
var columns = grid.columns;

//Function to find column position for a render index, ths is needed to take care of
// invisible columns and row headers
var findPositionForRenderIndex = function (index) {
var position = index;
for (var i = 0; i <= position; i++) {
if (angular.isDefined(columns[i]) && ((angular.isDefined(columns[i].colDef.visible) && columns[i].colDef.visible === false) || columns[i].isRowHeader === true)) {
position++;
}
}
return position;
};
var columns = grid.columns;

originalPosition = findPositionForRenderIndex(originalPosition);
newPosition = findPositionForRenderIndex(newPosition);
var originalColumn = columns[originalPosition];
if (originalColumn.colDef.enableColumnMoving) {
if (originalPosition > newPosition) {
Expand Down Expand Up @@ -224,8 +221,8 @@
* Events that invoke repositioning of column:
* - mouseup
*/
module.directive('uiGridHeaderCell', ['$q', 'gridUtil', 'uiGridMoveColumnService', '$document', '$log',
function ($q, gridUtil, uiGridMoveColumnService, $document, $log) {
module.directive('uiGridHeaderCell', ['$q', 'gridUtil', 'uiGridMoveColumnService', '$document', '$log', 'uiGridConstants',
function ($q, gridUtil, uiGridMoveColumnService, $document, $log, uiGridConstants) {
return {
priority: -10,
require: '^uiGrid',
Expand All @@ -235,122 +232,113 @@

if ($scope.col.colDef.enableColumnMoving) {

var mouseDownHandler = function (evt) {
if (evt.target.className !== 'ui-grid-icon-angle-down' && evt.target.tagName !== 'I' &&
evt.target.className.indexOf('ui-grid-filter-input') < 0) {
$scope.$on(uiGridConstants.events.COLUMN_HEADER_CLICK, function (event, args) {

//Setting some variables required for calculations.
var gridLeft = $scope.grid.element[0].getBoundingClientRect().left;
var previousMouseX = evt.pageX;
var totalMouseMovement = 0;
var rightMoveLimit = gridLeft + $scope.grid.getViewportWidth() - $scope.grid.verticalScrollbarWidth;
if (args.columnName === $scope.col.colDef.name) {

//Clone element should move horizontally with mouse.
var elmCloned = false;
var movingElm;
var reducedWidth;
var evt = args.event;
if (evt.target.className !== 'ui-grid-icon-angle-down' && evt.target.tagName !== 'I' &&
evt.target.className.indexOf('ui-grid-filter-input') < 0) {

var cloneElement = function() {
elmCloned = true;
//Setting some variables required for calculations.
var gridLeft = $scope.grid.element[0].getBoundingClientRect().left;
var previousMouseX = evt.pageX;
var totalMouseMovement = 0;
var rightMoveLimit = gridLeft + $scope.grid.getViewportWidth() - $scope.grid.verticalScrollbarWidth;

//Cloning header cell and appending to current header cell.
movingElm = $elm.clone();
$elm.parent().append(movingElm);
//Clone element should move horizontally with mouse.
var elmCloned = false;
var movingElm;
var reducedWidth;

//Left of cloned element should be aligned to original header cell.
movingElm.addClass('movingColumn');
var movingElementStyles = {};
var elmLeft = $elm[0].getBoundingClientRect().left;
movingElementStyles.left = (elmLeft - gridLeft) + 'px';
var gridRight = $scope.grid.element[0].getBoundingClientRect().right;
var elmRight = $elm[0].getBoundingClientRect().right;
if (elmRight > gridRight) {
reducedWidth = $scope.col.drawnWidth + (gridRight - elmRight);
movingElementStyles.width = reducedWidth + 'px';
}
movingElm.css(movingElementStyles);
};
var cloneElement = function () {
elmCloned = true;

var moveElement = function(changeValue) {
//Hide column menu
uiGridCtrl.fireEvent('hide-menu');
//Cloning header cell and appending to current header cell.
movingElm = $elm.clone();
$elm.parent().append(movingElm);

//Calculate new position of left of column
var currentElmLeft = movingElm[0].getBoundingClientRect().left - 1;
var currentElmRight = movingElm[0].getBoundingClientRect().right;
var newElementLeft;
if (gridUtil.detectBrowser() === 'ie') {
newElementLeft = currentElmLeft + changeValue;
}
else {
newElementLeft = currentElmLeft - gridLeft + changeValue;
}
newElementLeft = newElementLeft < rightMoveLimit ? newElementLeft : rightMoveLimit;
//Left of cloned element should be aligned to original header cell.
movingElm.addClass('movingColumn');
var movingElementStyles = {};
var elmLeft = $elm[0].getBoundingClientRect().left;
movingElementStyles.left = (elmLeft - gridLeft) + 'px';
var gridRight = $scope.grid.element[0].getBoundingClientRect().right;
var elmRight = $elm[0].getBoundingClientRect().right;
if (elmRight > gridRight) {
reducedWidth = $scope.col.drawnWidth + (gridRight - elmRight);
movingElementStyles.width = reducedWidth + 'px';
}
movingElm.css(movingElementStyles);
};

//Update css of moving column to adjust to new left value or fire scroll in case column has reached edge of grid
if ((currentElmLeft >= gridLeft || changeValue > 0) && (currentElmRight <= rightMoveLimit || changeValue < 0)) {
movingElm.css({visibility: 'visible', 'left': newElementLeft + 'px'});
}
else {
changeValue *= 6;
uiGridCtrl.fireScrollingEvent({ x: { pixels: changeValue * 4} });
}
totalMouseMovement += changeValue;
var moveElement = function (changeValue) {
//Hide column menu
uiGridCtrl.fireEvent('hide-menu');

//Increase width of moving column, in case the rightmost column was moved and its width was
//decreased because of overflow
if (reducedWidth < $scope.col.drawnWidth) {
reducedWidth += Math.abs(changeValue);
movingElm.css({'width': reducedWidth + 'px'});
}
};
//Calculate new position of left of column
var currentElmLeft = movingElm[0].getBoundingClientRect().left - 1;
var currentElmRight = movingElm[0].getBoundingClientRect().right;
var newElementLeft;
if (gridUtil.detectBrowser() === 'ie') {
newElementLeft = currentElmLeft + changeValue;
}
else {
newElementLeft = currentElmLeft - gridLeft + changeValue;
}
newElementLeft = newElementLeft < rightMoveLimit ? newElementLeft : rightMoveLimit;

var mouseMoveHandler = function (evt) {
var changeValue = evt.pageX - previousMouseX;
if (!elmCloned && Math.abs(changeValue) > 50) {
cloneElement();
}
else if (elmCloned) {
moveElement(changeValue);
previousMouseX = evt.pageX;
}
};
//Update css of moving column to adjust to new left value or fire scroll in case column has reached edge of grid
if ((currentElmLeft >= gridLeft || changeValue > 0) && (currentElmRight <= rightMoveLimit || changeValue < 0)) {
movingElm.css({visibility: 'visible', 'left': newElementLeft + 'px'});
}
else {
changeValue *= 8;
uiGridCtrl.fireScrollingEvent({x: {pixels: changeValue}});
}
totalMouseMovement += changeValue;

/*
//Commenting these lines as they are creating trouble with column moving when grid has huge scroll
// On scope destroy, remove the mouse event handlers from the document body
$scope.$on('$destroy', function () {
$document.off('mousemove', mouseMoveHandler);
$document.off('mouseup', mouseUpHandler);
});
*/
$document.on('mousemove', mouseMoveHandler);
//Increase width of moving column, in case the rightmost column was moved and its width was
//decreased because of overflow
if (reducedWidth < $scope.col.drawnWidth) {
reducedWidth += Math.abs(changeValue);
movingElm.css({'width': reducedWidth + 'px'});
}
};

var mouseUpHandler = function (evt) {
var renderIndexDefer = $q.defer();
var mouseMoveHandler = function (evt) {
var changeValue = evt.pageX - previousMouseX;
if (!elmCloned && Math.abs(changeValue) > 50) {
cloneElement();
}
else if (elmCloned) {
moveElement(changeValue);
previousMouseX = evt.pageX;
}
};

var renderIndex;
$attrs.$observe('renderIndex', function (n, o) {
renderIndex = $scope.$eval(n);
renderIndexDefer.resolve();
});
/*
//Commenting these lines as they are creating trouble with column moving when grid has huge scroll
// On scope destroy, remove the mouse event handlers from the document body
$scope.$on('$destroy', function () {
$document.off('mousemove', mouseMoveHandler);
$document.off('mouseup', mouseUpHandler);
});
*/
$document.on('mousemove', mouseMoveHandler);

renderIndexDefer.promise.then(function () {
var mouseUpHandler = function (evt) {

//Remove the cloned element on mouse up.
if (movingElm) {
movingElm.remove();
}

var renderedColumns = $scope.grid.renderContainers['body'].renderedColumns;

//This method will calculate the number of columns hidden in lift due to scroll
//renderContainer.prevColumnScrollIndex could also have been used but this is more accurate
var scrolledColumnCount = 0;
var columns = $scope.grid.columns;
var columnIndex = 0;
for (var i = 0; i < columns.length; i++) {
if (columns[i].colDef.visible && columns[i].colDef.name !== renderedColumns[0].colDef.name) {
scrolledColumnCount++;
if (columns[i].colDef.name !== $scope.col.colDef.name) {
columnIndex++;
}
else {
break;
Expand All @@ -360,37 +348,43 @@
//Case where column should be moved to a position on its left
if (totalMouseMovement < 0) {
var totalColumnsLeftWidth = 0;
for (var il = renderIndex - 1; il >= 0; il--) {
totalColumnsLeftWidth += renderedColumns[il].drawnWidth;
if (totalColumnsLeftWidth > Math.abs(totalMouseMovement)) {
uiGridMoveColumnService.redrawColumnAtPosition
($scope.grid, scrolledColumnCount + renderIndex, scrolledColumnCount + il + 1);
break;
for (var il = columnIndex - 1; il >= 0; il--) {
if (angular.isUndefined(columns[il].colDef.visible) || columns[il].colDef.visible === true) {
totalColumnsLeftWidth += columns[il].drawnWidth || columns[il].width || columns[il].colDef.width;
if (totalColumnsLeftWidth > Math.abs(totalMouseMovement)) {
uiGridMoveColumnService.redrawColumnAtPosition
($scope.grid, columnIndex, il + 1);
break;
}
}
}
//Case where column should be moved to beginning of the grid.
if (totalColumnsLeftWidth < Math.abs(totalMouseMovement)) {
uiGridMoveColumnService.redrawColumnAtPosition
($scope.grid, scrolledColumnCount + renderIndex, scrolledColumnCount + 0);
($scope.grid, columnIndex, 0);
}
}

//Case where column should be moved to a position on its right
else if (totalMouseMovement > 0) {
var totalColumnsRightWidth = 0;
for (var ir = renderIndex + 1; ir < renderedColumns.length; ir++) {
totalColumnsRightWidth += renderedColumns[ir].drawnWidth;
if (totalColumnsRightWidth > totalMouseMovement) {
uiGridMoveColumnService.redrawColumnAtPosition
($scope.grid, scrolledColumnCount + renderIndex, scrolledColumnCount + ir - 1);
break;
for (var ir = columnIndex + 1; ir < columns.length; ir++) {
if (angular.isUndefined(columns[ir].colDef.visible) || columns[ir].colDef.visible === true) {
totalColumnsRightWidth += columns[ir].drawnWidth || columns[ir].width || columns[ir].colDef.width;
if (totalColumnsRightWidth > totalMouseMovement) {
uiGridMoveColumnService.redrawColumnAtPosition
($scope.grid, columnIndex, ir - 1);
break;
}
}
}
//Case where column should be moved to end of the grid.
if (totalColumnsRightWidth < totalMouseMovement) {
uiGridMoveColumnService.redrawColumnAtPosition
($scope.grid, scrolledColumnCount + renderIndex, scrolledColumnCount + renderedColumns.length - 1);
($scope.grid, columnIndex, columns.length - 1);
}
}

else if (totalMouseMovement === 0) {
if (uiGridCtrl.grid.options.enableSorting && $scope.col.enableSorting) {
//sort the current column
Expand All @@ -412,14 +406,13 @@

$document.off('mousemove', mouseMoveHandler);
$document.off('mouseup', mouseUpHandler);
});
};
};

//Binding the mouseup event handler
$document.on('mouseup', mouseUpHandler);
//Binding the mouseup event handler
$document.on('mouseup', mouseUpHandler);
}
}
};
$elm.on('mousedown', mouseDownHandler);
});
}
}
};
Expand Down
3 changes: 2 additions & 1 deletion src/js/core/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
events: {
GRID_SCROLL: 'uiGridScroll',
COLUMN_MENU_SHOWN: 'uiGridColMenuShown',
ITEM_DRAGGING: 'uiGridItemDragStart' // For any item being dragged
ITEM_DRAGGING: 'uiGridItemDragStart', // For any item being dragged
COLUMN_HEADER_CLICK: 'uiGridColumnHeaderClick'
},
// copied from http://www.lsauer.com/2011/08/javascript-keymap-keycodes-in-json.html
keymap: {
Expand Down
2 changes: 2 additions & 0 deletions src/js/core/directives/ui-grid-header-cell.js
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,8 @@
uiGridCtrl.columnMenuScope.showMenu($scope.col, $elm, event);
}
});

uiGridCtrl.fireEvent(uiGridConstants.events.COLUMN_HEADER_CLICK, {event: event, columnName: $scope.col.colDef.name});
});

var upEvent = gridUtil.isTouchEnabled() ? 'touchend' : 'mouseup';
Expand Down