From 4f10a72306e2b3b1f70097edf0f7872946198660 Mon Sep 17 00:00:00 2001 From: Andrew Date: Tue, 8 Jul 2014 11:31:48 -0600 Subject: [PATCH] fix(list): make reorder/delete button animation work well on all devices --- js/angular/directive/itemDeleteButton.js | 4 +- js/angular/directive/itemReorderButton.js | 4 +- js/angular/directive/list.js | 26 ++++---- js/views/listView.js | 4 +- scss/_items.scss | 72 ++++++++++------------- test/html/list.html | 6 +- test/unit/angular/directive/item.unit.js | 12 ++-- test/unit/angular/directive/list.unit.js | 4 -- 8 files changed, 59 insertions(+), 73 deletions(-) diff --git a/js/angular/directive/itemDeleteButton.js b/js/angular/directive/itemDeleteButton.js index dccbea297c..8046733793 100644 --- a/js/angular/directive/itemDeleteButton.js +++ b/js/angular/directive/itemDeleteButton.js @@ -1,5 +1,5 @@ var ITEM_TPL_DELETE_BUTTON = - '
' + + '
' + '
'; /** * @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'); } }; } diff --git a/js/angular/directive/itemReorderButton.js b/js/angular/directive/itemReorderButton.js index 29f8dd13c5..f4494915c3 100644 --- a/js/angular/directive/itemReorderButton.js +++ b/js/angular/directive/itemReorderButton.js @@ -1,5 +1,5 @@ var ITEM_TPL_REORDER_BUTTON = - '
' + + '
' + '
'; /** @@ -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'); } }; } diff --git a/js/angular/directive/list.js b/js/angular/directive/list.js index d81bad7b1b..c628cd1364 100644 --- a/js/angular/directive/list.js +++ b/js/angular/directive/list.js @@ -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'); }); } } diff --git a/js/views/listView.js b/js/views/listView.js index b517a2cd9b..57cb9e5368 100644 --- a/js/views/listView.js +++ b/js/views/listView.js @@ -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); diff --git a/scss/_items.scss b/scss/_items.scss index baac4c5882..c4b655e818 100644 --- a/scss/_items.scss +++ b/scss/_items.scss @@ -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 diff --git a/test/html/list.html b/test/html/list.html index 5ac2839e4c..1e1a341122 100644 --- a/test/html/list.html +++ b/test/html/list.html @@ -6,8 +6,8 @@ Ionic List Directive - - + + @@ -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}); } diff --git a/test/unit/angular/directive/item.unit.js b/test/unit/angular/directive/item.unit.js index ee40d2dccc..0b4d1b8834 100644 --- a/test/unit/angular/directive/item.unit.js +++ b/test/unit/angular/directive/item.unit.js @@ -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(''); 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); })); }); diff --git a/test/unit/angular/directive/list.unit.js b/test/unit/angular/directive/list.unit.js index 6bade8bc25..c7268fef84 100644 --- a/test/unit/angular/directive/list.unit.js +++ b/test/unit/angular/directive/list.unit.js @@ -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')); }));