Skip to content
This repository has been archived by the owner on Sep 5, 2024. It is now read-only.

Commit

Permalink
fix(dialog): transition in and out properly to/from click element
Browse files Browse the repository at this point in the history
Closes #568.
  • Loading branch information
ajoslin committed Dec 5, 2014
1 parent fbdf013 commit 1f5029d
Show file tree
Hide file tree
Showing 7 changed files with 97 additions and 63 deletions.
33 changes: 21 additions & 12 deletions src/components/backdrop/_backdrop.scss
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
md-backdrop {
z-index: $z-index-backdrop;
&.md-dialog-backdrop {
z-index: $z-index-dialog - 1;
}
&.md-bottom-sheet-backdrop {
z-index: $z-index-bottom-sheet - 1;
}
&.md-bottom-sidenav-backdrop {
z-index: $z-index-sidenav - 1;
}

background-color: rgba(0,0,0,0);

position: fixed;
Expand All @@ -8,20 +18,19 @@ md-backdrop {
right: 0;
bottom: 0;


&.ng-enter {
transition-delay: 0.1s;
transition: $swift-ease-out;
animation: $swift-ease-out-timing-function mdBackdropFadeIn 0.5s both;
}
&.ng-leave {
transition: $swift-ease-in;
}
&.ng-enter,
&.ng-leave.ng-leave-active {
opacity: 0;
}
&.ng-leave,
&.ng-enter.ng-enter-active {
opacity: 1;
animation: $swift-ease-in-timing-function mdBackdropFadeOut 0.2s both;
}
}

@keyframes mdBackdropFadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
@keyframes mdBackdropFadeOut {
from { opacity: 1; }
to { opacity: 0; }
}
2 changes: 1 addition & 1 deletion src/components/bottomSheet/bottomSheet.js
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ function MdBottomSheetProvider($$interimElementProvider) {

function onShow(scope, element, options) {
// Add a backdrop that will close on click
backdrop = $compile('<md-backdrop class="md-opaque ng-enter">')(scope);
backdrop = $compile('<md-backdrop class="md-opaque md-bottom-sheet-backrop">')(scope);
backdrop.on('click touchstart', function() {
$timeout($mdBottomSheet.cancel);
});
Expand Down
19 changes: 8 additions & 11 deletions src/components/dialog/_dialog.scss
Original file line number Diff line number Diff line change
Expand Up @@ -8,29 +8,26 @@
right: 0;
bottom: 0;
z-index: $z-index-dialog;
}

&.md-active {
md-dialog {
&.transition-in {
opacity: 1;
transition: $swift-ease-out;
transform: translate3d(0,0,0) scale(1.0);
opacity: 1;
}
&.ng-leave.ng-leave-active {
transition: $swift-ease-in;
transform: translate3d(0,100%,0) scale(0.5);
opacity: 0;
&.transition-out {
transition: $swift-ease-out;
transform: translate3d(0,100%,0) scale(0.2);
}

}

md-dialog {

opacity: 0.05;
min-width: 240px;
max-width: 80%;
max-height: 80%;
margin: auto;
position: relative;


box-shadow: $whiteframe-shadow-z5;

display: flex;
Expand Down
79 changes: 48 additions & 31 deletions src/components/dialog/dialog.js
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ function MdDialogProvider($$interimElementProvider) {
}

/* @ngInject */
function dialogDefaultOptions($timeout, $rootElement, $compile, $animate, $mdAria,
function dialogDefaultOptions($timeout, $rootElement, $compile, $animate, $mdAria, $document,
$mdUtil, $mdConstant, $mdTheming, $$rAF, $q, $mdDialog) {
return {
hasBackdrop: true,
Expand All @@ -325,9 +325,9 @@ function MdDialogProvider($$interimElementProvider) {
configureAria(element.find('md-dialog'));

if (options.hasBackdrop) {
options.backdrop = $compile('<md-backdrop class="md-opaque ng-enter">')(scope);
options.backdrop = angular.element('<md-backdrop class="md-dialog-backdrop md-opaque">');
$mdTheming.inherit(options.backdrop, options.parent);
$animate.enter(options.backdrop, options.parent, null);
$animate.enter(options.backdrop, options.parent);
}

return dialogPopIn(
Expand Down Expand Up @@ -376,15 +376,19 @@ function MdDialogProvider($$interimElementProvider) {

if (options.backdrop) {
$animate.leave(options.backdrop);
element.data('backdrop', undefined);
}
if (options.escapeToClose) {
$rootElement.off('keyup', options.rootElementKeyupCallback);
}
if (options.clickOutsideToClose) {
element.off('click', options.dialogClickOutsideCallback);
}
return $animate.leave(element).then(function() {
return dialogPopOut(
element,
options.parent,
options.popInTarget.length && options.popInTarget
).then(function() {
options.scope.$destroy();
element.remove();
options.popInTarget && options.popInTarget.focus();
});
Expand All @@ -410,45 +414,58 @@ function MdDialogProvider($$interimElementProvider) {
});
}

function dialogPopIn(element, parentElement, clickElement) {
var deferred = $q.defer();
parentElement.append(element);
function dialogPopIn(container, parentElement, clickElement) {
var dialogEl = container.find('md-dialog');

parentElement.append(container);
transformToClickElement(dialogEl, clickElement);

$$rAF(function() {
dialogEl.addClass('transition-in')
.css($mdConstant.CSS.TRANSFORM, '');
});

return dialogTransitionEnd(dialogEl);
}

function dialogPopOut(container, parentElement, clickElement) {
var dialogEl = container.find('md-dialog');

dialogEl.addClass('transition-out').removeClass('transition-in');
transformToClickElement(dialogEl, clickElement);

var startPos;
return dialogTransitionEnd(dialogEl);
}

function transformToClickElement(dialogEl, clickElement) {
if (clickElement) {
var clickRect = clickElement[0].getBoundingClientRect();
startPos = 'translate3d(' +
(clickRect.left - element[0].offsetWidth / 2) + 'px,' +
(clickRect.top - element[0].offsetHeight / 2) + 'px,' +
'0) scale(0.2)';
} else {
startPos = 'translate3d(0,100%,0) scale(0.5)';
}
var dialogRect = dialogEl[0].getBoundingClientRect();

element
.css($mdConstant.CSS.TRANSFORM, startPos)
.css('opacity', 0);
var scaleX = Math.min(0.5, clickRect.width / dialogRect.width);
var scaleY = Math.min(0.5, clickRect.height / dialogRect.height);

$$rAF(function() {
$$rAF(function() {
element
.addClass('md-active')
.css($mdConstant.CSS.TRANSFORM, '')
.css('opacity', '')
.on($mdConstant.CSS.TRANSITIONEND, finished);
});
});
dialogEl.css($mdConstant.CSS.TRANSFORM, 'translate3d(' +
(-dialogRect.left + clickRect.left + clickRect.width/2 - dialogRect.width/2) + 'px,' +
(-dialogRect.top + clickRect.top + clickRect.height/2 - dialogRect.height/2) + 'px,' +
'0) scale(' + scaleX + ',' + scaleY + ')'
);
}
}

function dialogTransitionEnd(dialogEl) {
var deferred = $q.defer();
dialogEl.on($mdConstant.CSS.TRANSITIONEND, finished);
function finished(ev) {
//Make sure this transitionend didn't bubble up from a child
if (ev.target === element[0]) {
element.off($mdConstant.CSS.TRANSITIONEND, finished);
if (ev.target === dialogEl[0]) {
dialogEl.off($mdConstant.CSS.TRANSITIONEND, finished);
deferred.resolve();
}
}

return deferred.promise;
}

}
}

Expand Down
22 changes: 16 additions & 6 deletions src/components/dialog/dialog.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ describe('$mdDialog', function() {
expect(buttons.eq(0).text()).toBe('Next');
buttons.eq(0).triggerHandler('click');
$rootScope.$apply();
$animate.triggerCallbacks();
parent.find('md-dialog').triggerHandler('transitionend');
$rootScope.$apply();
expect(parent.find('h2').length).toBe(0);
expect(resolved).toBe(true);
}));
Expand Down Expand Up @@ -100,7 +101,8 @@ describe('$mdDialog', function() {
expect(buttons.eq(1).text()).toBe('Forget it');
buttons.eq(1).triggerHandler('click');
$rootScope.$digest();
$animate.triggerCallbacks();
parent.find('md-dialog').triggerHandler('transitionend');
$rootScope.$apply();
expect(parent.find('h2').length).toBe(0);
expect(rejected).toBe(true);
}));
Expand Down Expand Up @@ -136,7 +138,7 @@ describe('$mdDialog', function() {
expect(ready).toBe( false );

var container = angular.element(parent[0].querySelector('.md-dialog-container'));
container.triggerHandler('transitionend');
parent.find('md-dialog').triggerHandler('transitionend');
$rootScope.$apply();

container = angular.element(parent[0].querySelector('.md-dialog-container'));
Expand Down Expand Up @@ -170,7 +172,7 @@ describe('$mdDialog', function() {
$rootScope.$apply();

var container = angular.element(parent[0].querySelector('.md-dialog-container'));
container.triggerHandler('transitionend');
parent.find('md-dialog').triggerHandler('transitionend');
$rootScope.$apply();

expect(parent.find('md-dialog').length).toBe(1);
Expand All @@ -180,6 +182,8 @@ describe('$mdDialog', function() {
});

$timeout.flush();
parent.find('md-dialog').triggerHandler('transitionend');
$rootScope.$apply();
expect(parent.find('md-dialog').length).toBe(0);
}));

Expand Down Expand Up @@ -216,7 +220,7 @@ describe('$mdDialog', function() {
$rootScope.$apply();

var container = angular.element(parent[0].querySelector('.md-dialog-container'));
container.triggerHandler('transitionend');
parent.find('md-dialog').triggerHandler('transitionend');
$rootScope.$apply();

expect(parent.find('md-dialog').length).toBe(1);
Expand All @@ -226,7 +230,7 @@ describe('$mdDialog', function() {
target: container[0]
});
$timeout.flush();
container.triggerHandler('transitionend');
parent.find('md-dialog').triggerHandler('transitionend');
$rootScope.$apply();

expect(parent.find('md-dialog').length).toBe(0);
Expand Down Expand Up @@ -300,6 +304,8 @@ describe('$mdDialog', function() {
var container = angular.element(parent[0].querySelector('.md-dialog-container'));
container.triggerHandler('transitionend');
$rootScope.$apply();
parent.find('md-dialog').triggerHandler('transitionend');
$rootScope.$apply();


expect($document.activeElement).toBe(parent[0].querySelector('.dialog-close'));
Expand All @@ -326,6 +332,8 @@ describe('$mdDialog', function() {
var container = angular.element(parent[0].querySelector('.md-dialog-container'));
container.triggerHandler('transitionend');
$rootScope.$apply();
parent.find('md-dialog').triggerHandler('transitionend');
$rootScope.$apply();

expect($document.activeElement).toBe(parent[0].querySelector('#focus-target'));
}));
Expand All @@ -346,6 +354,8 @@ describe('$mdDialog', function() {
parent: parent
});

$rootScope.$apply();
parent.find('md-dialog').triggerHandler('transitionend');
$rootScope.$apply();
expect(parent[0].querySelectorAll('md-dialog.one').length).toBe(0);
expect(parent[0].querySelectorAll('md-dialog.two').length).toBe(1);
Expand Down
2 changes: 1 addition & 1 deletion src/components/sidenav/sidenav.js
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ function mdSidenavDirective($timeout, $animate, $parse, $mdMedia, $mdConstant, $
function postLink(scope, element, attr, sidenavCtrl) {
var isLockedOpenParsed = $parse(attr.mdIsLockedOpen);
var backdrop = $compile(
'<md-backdrop class="md-sidenav-backdrop md-opaque">'
'<md-backdrop class="md-sidenav-backdrop md-opaque ng-enter">'
)(scope);

$mdTheming.inherit(backdrop, element);
Expand Down
3 changes: 2 additions & 1 deletion src/core/services/interimElement/interimElement.js
Original file line number Diff line number Diff line change
Expand Up @@ -169,8 +169,9 @@ function InterimElementProvider() {
function showInterimElement(opts) {
// opts is either a preset which stores its options on an _options field,
// or just an object made up of options
if (opts && opts._options) opts = opts._options;
return interimElementService.show(
angular.extend({}, defaultOptions, (opts || {})._options || opts)
angular.extend({}, defaultOptions, opts)
);
}

Expand Down

0 comments on commit 1f5029d

Please sign in to comment.