fix(list): make reorder/delete button animation work well on all devices

This commit is contained in:
Andrew
2014-07-08 11:31:48 -06:00
parent 0e89fb3aee
commit 4f10a72306
8 changed files with 59 additions and 73 deletions

View File

@@ -1,5 +1,5 @@
var ITEM_TPL_DELETE_BUTTON =
'<div class="item-left-edit item-delete ng-hide enable-pointer-events">' +
'<div class="item-left-edit item-delete enable-pointer-events">' +
'</div>';
/**
* @ngdoc directive
@@ -49,7 +49,7 @@ IonicModule
itemCtrl.$element.append(container).addClass('item-left-editable');
if (listCtrl && listCtrl.showDelete()) {
$animate.removeClass(container, 'ng-hide');
container.addClass('visible active');
}
};
}

View File

@@ -1,5 +1,5 @@
var ITEM_TPL_REORDER_BUTTON =
'<div data-prevent-scroll="true" class="item-right-edit item-reorder ng-hide enable-pointer-events">' +
'<div data-prevent-scroll="true" class="item-right-edit item-reorder enable-pointer-events">' +
'</div>';
/**
@@ -72,7 +72,7 @@ IonicModule
itemCtrl.$element.append(container).addClass('item-right-editable');
if (listCtrl && listCtrl.showReorder()) {
$animate.removeClass(container, 'ng-hide');
container.addClass('visible active');
}
};
}

View File

@@ -140,13 +140,13 @@ function($animate, $timeout) {
if (isShown) listCtrl.closeOptionButtons();
listCtrl.canSwipeItems(!isShown);
var deleteButton = jqLite($element[0].getElementsByClassName('item-delete'));
$element.children().toggleClass('list-left-editing', isShown);
toggleNgHide(deleteButton, isShown);
$element.toggleClass('disable-pointer-events left-editing', isShown);
$element.toggleClass('disable-pointer-events', isShown);
var deleteButton = jqLite($element[0].getElementsByClassName('item-delete'));
setButtonShown(deleteButton, listCtrl.showDelete);
});
$scope.$watch(function() {
return listCtrl.showReorder();
}, function(isShown, wasShown) {
@@ -156,21 +156,17 @@ function($animate, $timeout) {
if (isShown) listCtrl.closeOptionButtons();
listCtrl.canSwipeItems(!isShown);
var reorderButton = jqLite($element[0].getElementsByClassName('item-reorder'));
$element.children().toggleClass('list-right-editing', isShown);
toggleNgHide(reorderButton, isShown);
$element.toggleClass('disable-pointer-events right-editing', isShown);
$element.toggleClass('disable-pointer-events', isShown);
var reorderButton = jqLite($element[0].getElementsByClassName('item-reorder'));
setButtonShown(reorderButton, listCtrl.showReorder);
});
function toggleNgHide(element, shouldShow) {
forEach(element, function(node) {
if (shouldShow) {
$animate.removeClass(jqLite(node), 'ng-hide');
} else {
$animate.addClass(jqLite(node), 'ng-hide');
}
function setButtonShown(el, shown) {
shown() && el.addClass('visible') || el.removeClass('active');
ionic.requestAnimationFrame(function() {
shown() && el.addClass('active') || el.removeClass('invisible');
});
}
}

View File

@@ -88,9 +88,9 @@
if(!lastDrag) return;
lastDrag.content.style[ionic.CSS.TRANSITION] = '';
lastDrag.content.style[ionic.CSS.TRANSFORM] = '';
ionic.requestAnimationFrame(function() {
lastDrag.content.style[ionic.CSS.TRANSITION] = '';
lastDrag.content.style[ionic.CSS.TRANSFORM] = '';
setTimeout(function() {
lastDrag.buttons && lastDrag.buttons.classList.add('invisible');
}, 250);

View File

@@ -595,28 +595,11 @@ button.item.item-button-right {
// setup standard transition settings
@include transition-duration( $item-edit-transition-duration );
@include transition-timing-function( $item-edit-transition-function );
@include transition-property( none );
}
.item-left-editable .item-content {
// set transition property for an item just left editable
-webkit-transition-property: -webkit-transform;
-moz-transition-property: -moz-transform;
transition-property: transform;
}
.item-right-editable .item-content {
// set transition property for an item just right editable
@include transition-property(margin-right);
}
.item-left-editable.item-right-editable .item-content {
// set transition property for an item that's both left/right editable
-webkit-transition-property: -webkit-transform, margin-right;
-moz-transition-property: -moz-transform, margin-right;
transition-property: transform, margin-right;
}
.list-left-editing .item-left-editable .item-content,
.item-left-editing.item-left-editable .item-content {
// actively editing the left side of the item
@@ -625,8 +608,8 @@ button.item.item-button-right {
.list-right-editing .item-right-editable .item-content,
.item-right-editing.item-right-editable .item-content {
// actively editing the right side of the item
margin-right: $item-right-edit-open-width;
// actively editing the left side of the item
@include translate3d(-$item-right-edit-open-width, 0, 0);
}
@@ -634,8 +617,7 @@ button.item.item-button-right {
// -------------------------------
.item-left-edit {
@include transition(all $item-edit-transition-function $item-edit-transition-duration);
@include translate3d( $item-left-edit-left - $item-left-edit-open-width, 0, 0);
@include transition(all $item-edit-transition-function $item-edit-transition-duration / 2);
position: absolute;
top: 0;
left: 0;
@@ -655,13 +637,21 @@ button.item.item-button-right {
height: 100%;
}
}
}
.list-left-editing .item-left-edit,
.item-left-editing .item-left-edit {
@include translate3d($item-left-edit-left, 0, 0);
display: none;
opacity: 0;
@include translate3d( ($item-left-edit-left - $item-left-edit-open-width) / 2, 0, 0);
&.visible {
display: block;
&.active {
opacity: 1;
@include translate3d($item-left-edit-left, 0, 0);
}
}
}
.list-left-editing .item-left-edit {
@include transition-delay($item-edit-transition-duration / 2);
}
// Item Delete (Left side edit button)
// -------------------------------
@@ -680,12 +670,12 @@ button.item.item-button-right {
// -------------------------------
.item-right-edit {
@include transition(all $item-edit-transition-function $item-edit-transition-duration);
@include transition(all $item-edit-transition-function $item-edit-transition-duration / 2);
position: absolute;
top: 0;
right: 0;
z-index: 0;
width: $item-right-edit-open-width;
width: $item-right-edit-open-width * 1.5;
height: 100%;
background: inherit;
@@ -702,6 +692,20 @@ button.item.item-button-right {
font-size: $item-reorder-icon-size;
}
}
display: none;
opacity: 0;
@include translate3d($item-right-edit-open-width / 2, 0, 0);
&.visible {
display: block;
&.active {
opacity: 1;
@include translate3d(0, 0, 0);
}
}
}
.list-right-editing .item-right-edit {
@include transition-delay($item-edit-transition-duration / 2);
}
@@ -732,18 +736,6 @@ button.item.item-button-right {
opacity: 0.7;
}
.item-left-edit.item-delete,
.item-right-edit.item-reorder {
opacity: 1;
&.ng-hide {
opacity: 0;
}
&.ng-hide-add,
&.ng-hide-remove {
display: block !important;
}
}
/**
* The hidden right-side buttons that can be exposed under a list item

View File

@@ -6,8 +6,8 @@
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<title>Ionic List Directive</title>
<link href="../../dist/css/ionic.css" rel="stylesheet">
<script src="../../dist/js/ionic.bundle.js"></script>
<link href="../../dist/css/ionic.min.css" rel="stylesheet">
<script src="../../dist/js/ionic.bundle.min.js"></script>
</head>
<body ng-controller="MyCtrl">
@@ -117,7 +117,7 @@ angular.module('ionicApp', ['ionic'])
};
$scope.items = [];
for (var i=0; i<100; i++) {
for (var i=0; i<15; i++) {
$scope.items.push({id:i});
}

View File

@@ -64,7 +64,7 @@ describe('ionDeleteButton directive', function() {
$compile(el)($rootScope.$new());
$rootScope.$apply();
var deleteContainer = angular.element(el[0].querySelector('.item-left-edit.item-delete.ng-hide'));
var deleteContainer = angular.element(el[0].querySelector('.item-left-edit.item-delete'));
expect(deleteContainer.length).toBe(1);
expect(deleteContainer.children().hasClass('button icon button-icon')).toBe(true);
}));
@@ -79,7 +79,8 @@ describe('ionDeleteButton directive', function() {
var deleteContainer = angular.element(el[0].querySelector('.item-left-edit.item-delete'));
expect(deleteContainer.length).toBe(1);
expect(deleteContainer.hasClass('ng-hide')).toBe(false);
expect(deleteContainer.hasClass('visible')).toBe(true);
expect(deleteContainer.hasClass('active')).toBe(true);
}));
});
@@ -94,13 +95,13 @@ describe('ionReorderButton directive', function() {
$compile(el)($rootScope.$new());
$rootScope.$apply();
var reorderContainer = angular.element(el[0].querySelector('.item-right-edit.item-reorder.ng-hide'));
var reorderContainer = angular.element(el[0].querySelector('.item-right-edit.item-reorder'));
expect(reorderContainer.length).toBe(1);
expect(reorderContainer.children().hasClass('button icon button-icon')).toBe(true);
expect(reorderContainer.attr('data-prevent-scroll')).toBe('true');
expect(reorderContainer.children().attr('data-prevent-scroll')).toBe('true');
}));
it('should remove ng-hide if reorder is already active', inject(function($compile, $rootScope) {
it('should show if reorder is already active', inject(function($compile, $rootScope) {
var setSpy = jasmine.createSpy('setReorderButton');
var el = angular.element('<ion-item><ion-reorder-button></ion-reorder-button></ion-item>');
el.data('$ionListController', {
@@ -110,7 +111,8 @@ describe('ionReorderButton directive', function() {
$rootScope.$apply();
var reorderContainer = angular.element(el[0].querySelector('.item-right-edit.item-reorder'));
expect(reorderContainer.length).toBe(1);
expect(reorderContainer.hasClass('ng-hide')).toBe(false);
expect(reorderContainer.hasClass('visible')).toBe(true);
expect(reorderContainer.hasClass('active')).toBe(true);
}));
});

View File

@@ -92,7 +92,6 @@ describe('ionList directive', function() {
expect(el.controller('ionList').closeOptionButtons).toHaveBeenCalled();
var deleteButtons = angular.element(el[0].querySelectorAll('.item-delete.item-left-edit'));
expect(deleteButtons.length).not.toBe(0);
expect(deleteButtons.hasClass('ng-hide')).toBe(false);
expect(el.children().hasClass('list-left-editing')).toBe(true);
var content = angular.element(el[0].querySelectorAll('.item-content'));
}));
@@ -111,7 +110,6 @@ describe('ionList directive', function() {
expect(el.controller('ionList').canSwipeItems()).toBe(true);
expect(el.controller('ionList').closeOptionButtons.callCount).toBe(1);
var deleteButtons = angular.element(el[0].querySelectorAll('.item-delete.item-left-edit'));
expect(deleteButtons.hasClass('ng-hide')).toBe(true);
expect(deleteButtons.length).not.toBe(0);
expect(el.children().hasClass('list-left-editing')).toBe(false);
var content = angular.element(el[0].querySelectorAll('.item-content'));
@@ -131,7 +129,6 @@ describe('ionList directive', function() {
expect(el.controller('ionList').canSwipeItems()).toBe(false);
var reorderButtons = angular.element(el[0].querySelectorAll('.item-reorder.item-right-edit'));
expect(reorderButtons.length).not.toBe(0);
expect(reorderButtons.hasClass('ng-hide')).toBe(false);
expect(el.children().hasClass('list-right-editing')).toBe(true);
var content = angular.element(el[0].querySelectorAll('.item-content'));
}));
@@ -151,7 +148,6 @@ describe('ionList directive', function() {
expect(el.controller('ionList').closeOptionButtons.callCount).toBe(1);
var reorderButtons = angular.element(el[0].querySelectorAll('.item-reorder.item-right-edit'));
expect(reorderButtons.length).not.toBe(0);
expect(reorderButtons.hasClass('ng-hide')).toBe(true);
expect(el.children().hasClass('list-right-editing')).toBe(false);
var content = angular.element(el[0].querySelectorAll('.item-content'));
}));