Skip to content

Commit 26c9c91

Browse files
committed
Merge pull request #1742 from PaulL1/1710_animation
Fix 1710(menu animations): fix animations, track by row.uid, menu move
2 parents a23bfee + bdedaab commit 26c9c91

File tree

10 files changed

+170
-180
lines changed

10 files changed

+170
-180
lines changed

src/js/core/directives/ui-grid-column-menu.js

+42-51
Original file line numberDiff line numberDiff line change
@@ -285,16 +285,20 @@ function ( i18nService, uiGridConstants, gridUtil ) {
285285
// default value the last width for _this_ column, otherwise last width for _any_ column, otherwise default to 170
286286
var myWidth = column.lastMenuWidth ? column.lastMenuWidth : ( $scope.lastMenuWidth ? $scope.lastMenuWidth : 170);
287287
var paddingRight = column.lastMenuPaddingRight ? column.lastMenuPaddingRight : ( $scope.lastMenuPaddingRight ? $scope.lastMenuPaddingRight : 10);
288-
if (menu.length !== 0){
289-
myWidth = gridUtil.elementWidth(menu, true);
290-
$scope.lastMenuWidth = myWidth;
291-
column.lastMenuWidth = myWidth;
292-
293-
// TODO(c0bra): use padding-left/padding-right based on document direction (ltr/rtl), place menu on proper side
294-
// Get the column menu right padding
295-
paddingRight = parseInt(gridUtil.getStyles(angular.element(menu)[0])['paddingRight'], 10);
296-
$scope.lastMenuPaddingRight = paddingRight;
297-
column.lastMenuPaddingRight = paddingRight;
288+
289+
if ( menu.length !== 0 ){
290+
var mid = menu[0].querySelectorAll('.ui-grid-menu-mid');
291+
if ( mid.length !== 0 && !mid[0].classList.contains('ng-hide') ){
292+
myWidth = gridUtil.elementWidth(menu, true);
293+
$scope.lastMenuWidth = myWidth;
294+
column.lastMenuWidth = myWidth;
295+
296+
// TODO(c0bra): use padding-left/padding-right based on document direction (ltr/rtl), place menu on proper side
297+
// Get the column menu right padding
298+
paddingRight = parseInt(gridUtil.getStyles(angular.element(menu)[0])['paddingRight'], 10);
299+
$scope.lastMenuPaddingRight = paddingRight;
300+
column.lastMenuPaddingRight = paddingRight;
301+
}
298302
}
299303

300304
var left = positionData.left + renderContainerOffset - containerScrollLeft + positionData.width - myWidth + paddingRight;
@@ -355,37 +359,37 @@ function ($log, $timeout, gridUtil, uiGridConstants, uiGridColumnMenuService) {
355359
// Swap to this column
356360
$scope.col = column;
357361

358-
// Remove an existing document click handler
359-
// $document.off('click', documentClick);
360-
361362
// Get the position information for the column element
362363
var colElementPosition = uiGridColumnMenuService.getColumnElementPosition( $scope, column, $columnElement );
363364

364-
var repositionMenuClosure = function( $scope, column, colElementPosition, $elm, $columnElement ) {
365-
return function() {
366-
uiGridColumnMenuService.repositionMenu( $scope, column, colElementPosition, $elm, $columnElement );
367-
};
368-
};
369-
370365
if ($scope.menuShown) {
371-
$scope.$broadcast('hide-menu');
366+
// we want to hide, then reposition, then show, but we want to wait for animations
367+
// we set a variable, and then rely on the menu-hidden event to call the reposition and show
372368
$scope.col = column;
373-
374-
uiGridColumnMenuService.repositionMenu( $scope, column, colElementPosition, $elm, $columnElement );
375-
$scope.$broadcast('show-menu');
376-
$timeout( repositionMenuClosure( $scope, column, colElementPosition, $elm, $columnElement ));
369+
$scope.colElement = $columnElement;
370+
$scope.colElementPosition = colElementPosition;
371+
$scope.hideThenShow = true;
372+
373+
$scope.$broadcast('hide-menu');
377374
} else {
378375
self.shown = $scope.menuShown = true;
379376
uiGridColumnMenuService.repositionMenu( $scope, column, colElementPosition, $elm, $columnElement );
380377
$scope.$broadcast('show-menu');
381-
$timeout( repositionMenuClosure( $scope, column, colElementPosition, $elm, $columnElement ));
382-
}
378+
$timeout( $scope.repositionMenuClosure( $scope, column, colElementPosition, $elm, $columnElement ));
379+
}
383380

384-
// Hide the menu on a click on the document
385-
// $document.on('click', documentClick);
386381
};
387382

388383

384+
$scope.repositionMenuClosure = function( $scope, column, colElementPosition, $elm, $columnElement ) {
385+
return function() {
386+
uiGridColumnMenuService.repositionMenu( $scope, column, colElementPosition, $elm, $columnElement );
387+
delete $scope.colElementPosition;
388+
delete $scope.columnElement;
389+
};
390+
};
391+
392+
389393
/**
390394
* @ngdoc method
391395
* @methodOf ui.grid.directive:uiGridColumnMenu
@@ -404,32 +408,19 @@ function ($log, $timeout, gridUtil, uiGridConstants, uiGridColumnMenuService) {
404408
}
405409
};
406410

407-
/*
408-
function documentClick() {
409-
$scope.$apply($scope.hideMenu);
410-
$document.off('click', documentClick);
411-
}
412411

413-
function resizeHandler() {
414-
$scope.$apply($scope.hideMenu);
415-
}
416-
angular.element($window).bind('resize', resizeHandler);
417-
418-
$scope.$on('$destroy', $scope.$on(uiGridConstants.events.GRID_SCROLL, function(evt, args) {
419-
$scope.hideMenu();
420-
}));
412+
$scope.$on('menu-hidden', function() {
413+
if ( $scope.hideThenShow ){
414+
delete $scope.hideThenShow;
421415

422-
$scope.$on('$destroy', $scope.$on(uiGridConstants.events.ITEM_DRAGGING, function(evt, args) {
423-
$scope.hideMenu();
424-
}));
416+
uiGridColumnMenuService.repositionMenu( $scope, $scope.col, $scope.colElementPosition, $elm, $scope.colElement );
417+
$scope.$broadcast('show-menu');
418+
$timeout( $scope.repositionMenuClosure( $scope, $scope.col, $scope.colElementPosition, $elm, $scope.colElement ));
425419

426-
$scope.$on('$destroy', function() {
427-
angular.element($window).off('resize', resizeHandler);
428-
$document.off('click', documentClick);
429-
});
430-
*/
431-
$scope.$on('menu-hidden', function() {
432-
$scope.hideMenu( true );
420+
$scope.menuShown = true;
421+
} else {
422+
$scope.hideMenu( true );
423+
}
433424
});
434425

435426

src/js/core/directives/ui-grid-menu.js

+67-7
Original file line numberDiff line numberDiff line change
@@ -43,14 +43,50 @@ angular.module('ui.grid')
4343
replace: false,
4444
link: function ($scope, $elm, $attrs, uiGridCtrl) {
4545
var self = this;
46-
gridUtil.enableAnimations($elm);
47-
48-
46+
var menuMid;
47+
var $animate;
48+
4949
// *** Show/Hide functions ******
5050
self.showMenu = $scope.showMenu = function() {
51-
$scope.shown = true;
51+
if ( !$scope.shown ){
52+
53+
/*
54+
* In order to animate cleanly we remove the ng-if, wait a digest cycle, then
55+
* animate the removal of the ng-hide. We can't successfully (so far as I can tell)
56+
* animate removal of the ng-if, as the menu items aren't there yet. And we don't want
57+
* to rely on ng-show only, as that leaves elements in the DOM that are needlessly evaluated
58+
* on scroll events.
59+
*
60+
* Note when testing animation that animations don't run on the tutorials. When debugging it looks
61+
* like they do, but angular has a default $animate provider that is just a stub, and that's what's
62+
* being called. ALso don't be fooled by the fact that your browser has actually loaded the
63+
* angular-translate.js, it's not using it. You need to test animations in an external application.
64+
*/
65+
$scope.shown = true;
66+
67+
$timeout( function() {
68+
menuMid = $elm[0].querySelectorAll( '.ui-grid-menu-mid' );
69+
$animate = gridUtil.enableAnimations(menuMid);
70+
if ( $animate ){
71+
$scope.shownMid = true;
72+
$animate.removeClass(menuMid, 'ng-hide');
73+
} else {
74+
$scope.shownMid = true;
75+
}
76+
});
77+
} else if ( !$scope.shownMid ){
78+
// we're probably doing a hide then show, so we don't need to wait for ng-if
79+
menuMid = $elm[0].querySelectorAll( '.ui-grid-menu-mid' );
80+
$animate = gridUtil.enableAnimations(menuMid);
81+
if ( $animate ){
82+
$scope.shownMid = true;
83+
$animate.removeClass(menuMid, 'ng-hide');
84+
} else {
85+
$scope.shownMid = true;
86+
}
87+
}
5288

53-
// Turn off an existing dpcument click handler
89+
// Turn off an existing document click handler
5490
angular.element(document).off('click', applyHideMenu);
5591

5692
// Turn on the document click handler, but in a timeout so it doesn't apply to THIS click if there is one
@@ -59,9 +95,33 @@ angular.module('ui.grid')
5995
});
6096
};
6197

98+
6299
self.hideMenu = $scope.hideMenu = function() {
63-
$scope.shown = false;
64-
$scope.$emit('menu-hidden');
100+
if ( $scope.shown ){
101+
/*
102+
* In order to animate cleanly we animate the addition of ng-hide, then use a $timeout to
103+
* set the ng-if (shown = false) after the animation runs. In theory we can cascade off the
104+
* callback on the addClass method, but it is very unreliable with unit tests for no discernable reason.
105+
*
106+
* The user may have clicked on the menu again whilst
107+
* we're waiting, so we check that the mid isn't shown before applying the ng-if.
108+
*/
109+
menuMid = $elm[0].querySelectorAll( '.ui-grid-menu-mid' );
110+
$animate = gridUtil.enableAnimations(menuMid);
111+
112+
if ( $animate ){
113+
$scope.shownMid = false;
114+
$animate.addClass(menuMid, 'ng-hide', function() {
115+
if ( !$scope.shownMid ){
116+
$scope.shown = false;
117+
$scope.$emit('menu-hidden');
118+
}
119+
});
120+
} else {
121+
$scope.shownMid = false;
122+
$scope.shown = false;
123+
}
124+
}
65125
angular.element(document).off('click', applyHideMenu);
66126
};
67127

src/js/core/services/ui-grid-util.js

+1
Original file line numberDiff line numberDiff line change
@@ -614,6 +614,7 @@ module.service('gridUtil', ['$log', '$window', '$document', '$http', '$templateC
614614
try {
615615
$animate = $injector.get('$animate');
616616
$animate.enabled(true, element);
617+
return $animate;
617618
}
618619
catch (e) {}
619620
},

src/less/header.less

+24-6
Original file line numberDiff line numberDiff line change
@@ -96,19 +96,37 @@
9696
}
9797

9898
/* Slide up/down animations */
99-
.ui-grid-column-menu .ui-grid-menu .ui-grid-menu-inner {
100-
&.ng-enter, &.ng-leave {
99+
.ui-grid-column-menu .ui-grid-menu .ui-grid-menu-mid {
100+
&.ng-hide-add, &.ng-hide-remove {
101101
.transition(all, 0.05s, linear);
102102
display: block !important;
103103
}
104104

105-
&.ng-leave.ng-leave-active,
106-
&.ng-enter {
105+
&.ng-hide-add.ng-hide-add-active,
106+
&.ng-hide-remove {
107107
.transform(translateY(-100%));
108108
}
109109

110-
&.ng-leave,
111-
&.ng-enter.ng-enter-active {
110+
&.ng-hide-add,
111+
&.ng-hide-remove.ng-hide-remove-active {
112+
.transform(translateY(0));
113+
}
114+
}
115+
116+
/* Slide up/down animations */
117+
.ui-grid-menu-button .ui-grid-menu .ui-grid-menu-mid {
118+
&.ng-hide-add, &.ng-hide-remove {
119+
.transition(all, 0.05s, linear);
120+
display: block !important;
121+
}
122+
123+
&.ng-hide-add.ng-hide-add-active,
124+
&.ng-hide-remove {
125+
.transform(translateY(-100%));
126+
}
127+
128+
&.ng-hide-add,
129+
&.ng-hide-remove.ng-hide-remove-active {
112130
.transform(translateY(0));
113131
}
114132
}

src/templates/ui-grid/uiGridHeaderCell.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<div ng-class="{ 'sortable': sortable }" ng-style="{ 'height': renderContainer.explicitHeaderHeight + 'px' }">
1+
<div ng-class="{ 'sortable': sortable }">
22
<div class="ui-grid-vertical-bar">&nbsp;</div>
33
<div class="ui-grid-cell-contents" col-index="renderIndex">
44
{{ col.displayName CUSTOM_FILTERS }}

src/templates/ui-grid/uiGridMenu.html

+14-12
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
11
<div class="ui-grid-menu" ng-if="shown">
2-
<div class="ui-grid-menu-inner">
3-
<ul class="ui-grid-menu-items">
4-
<li
5-
ng-repeat="item in menuItems"
6-
ui-grid-menu-item action="item.action"
7-
title="item.title"
8-
active="item.active"
9-
icon="item.icon"
10-
shown="item.shown"
11-
context="item.context"
12-
template-url="item.templateUrl"></li>
13-
</ul>
2+
<div class="ui-grid-menu-mid" ng-show="shownMid">
3+
<div class="ui-grid-menu-inner">
4+
<ul class="ui-grid-menu-items">
5+
<li
6+
ng-repeat="item in menuItems"
7+
ui-grid-menu-item action="item.action"
8+
title="item.title"
9+
active="item.active"
10+
icon="item.icon"
11+
shown="item.shown"
12+
context="item.context"
13+
template-url="item.templateUrl"></li>
14+
</ul>
15+
</div>
1416
</div>
1517
</div>

src/templates/ui-grid/uiGridViewport.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<div class="ui-grid-viewport">
22
<div class="ui-grid-canvas">
3-
<div ng-repeat="(rowRenderIndex, row) in rowContainer.renderedRows track by $index" class="ui-grid-row" ng-style="containerCtrl.rowStyle(rowRenderIndex)">
3+
<div ng-repeat="(rowRenderIndex, row) in rowContainer.renderedRows track by row.uid" class="ui-grid-row" ng-style="containerCtrl.rowStyle(rowRenderIndex)">
44
<div ui-grid-row="row" row-render-index="rowRenderIndex"></div>
55
</div>
66
</div>

0 commit comments

Comments
 (0)