Skip to content

Commit

Permalink
fix(modal): backdrop animation on AngularJS 1.4
Browse files Browse the repository at this point in the history
  • Loading branch information
chrisirhc committed Jul 6, 2015
1 parent 13a0354 commit 158d267
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 51 deletions.
70 changes: 31 additions & 39 deletions src/modal/modal.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,9 @@ angular.module('ui.bootstrap.modal', [])
/**
* A helper directive for the $modal service. It creates a backdrop element.
*/
.directive('modalBackdrop', ['$timeout', function ($timeout) {
.directive('modalBackdrop', [
'$animate', '$modalStack',
function ($animate , $modalStack) {
return {
restrict: 'EA',
replace: true,
Expand All @@ -69,12 +71,14 @@ angular.module('ui.bootstrap.modal', [])
};

function linkFn(scope, element, attrs) {
scope.animate = false;
if (attrs.modalInClass) {
$animate.addClass(element, attrs.modalInClass);

//trigger CSS transitions
$timeout(function () {
scope.animate = true;
});
scope.$on($modalStack.NOW_CLOSING_EVENT, function (e, setIsAsync) {
var done = setIsAsync();
$animate.removeClass(element, attrs.modalInClass).then(done);
});
}
}
}])

Expand Down Expand Up @@ -123,7 +127,7 @@ angular.module('ui.bootstrap.modal', [])
if (attrs.modalInClass) {
$animate.addClass(element, attrs.modalInClass);

scope.$on($modalStack.WINDOW_CLOSING_EVENT, function (e, setIsAsync) {
scope.$on($modalStack.NOW_CLOSING_EVENT, function (e, setIsAsync) {
var done = setIsAsync();
$animate.removeClass(element, attrs.modalInClass).then(done);
});
Expand Down Expand Up @@ -189,7 +193,7 @@ angular.module('ui.bootstrap.modal', [])
var backdropDomEl, backdropScope;
var openedWindows = $$stackedMap.createNew();
var $modalStack = {
WINDOW_CLOSING_EVENT: 'modal.stack.window-closing'
NOW_CLOSING_EVENT: 'modal.stack.now-closing'
};

function backdropIndex() {
Expand Down Expand Up @@ -217,25 +221,7 @@ angular.module('ui.bootstrap.modal', [])
//clean up the stack
openedWindows.remove(modalInstance);

var closingDeferred;
var closingPromise;
var setIsAsync = function () {
if (!closingDeferred) {
closingDeferred = $q.defer();
closingPromise = closingDeferred.promise;
}

return function () {
closingDeferred.resolve();
};
};
modalWindow.modalScope.$broadcast($modalStack.WINDOW_CLOSING_EVENT, setIsAsync);

//remove window DOM element
$q.when(closingPromise).then(function() {
modalWindow.modalDomEl.remove();
modalWindow.modalScope.$destroy();

removeAfterAnimate(modalWindow.modalDomEl, modalWindow.modalScope, function() {
body.toggleClass(OPENED_MODAL_CLASS, openedWindows.length() > 0);
checkRemoveBackdrop();
});
Expand All @@ -261,18 +247,24 @@ angular.module('ui.bootstrap.modal', [])
}

function removeAfterAnimate(domEl, scope, done) {
// Closing animation
scope.animate = false;

if (domEl.attr('modal-animation') && $animate.enabled()) {
// transition out
domEl.one('$animate:close', function closeFn() {
$rootScope.$evalAsync(afterAnimating);
});
} else {
// Ensure this call is async
$timeout(afterAnimating);
}
var asyncDeferred;
var asyncPromise = null;
var setIsAsync = function () {
if (!asyncDeferred) {
asyncDeferred = $q.defer();
asyncPromise = asyncDeferred.promise;
}

return function asyncDone() {
asyncDeferred.resolve();
};
};
scope.$broadcast($modalStack.NOW_CLOSING_EVENT, setIsAsync);

// Note that it's intentional that asyncPromise might be null.
// That's when setIsAsync has not been called during the
// NOW_CLOSING_EVENT broadcast.
return $q.when(asyncPromise).then(afterAnimating);

function afterAnimating() {
if (afterAnimating.done) {
Expand Down
16 changes: 5 additions & 11 deletions src/modal/test/modal.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ describe('$modal', function () {
function open(modalOptions) {
var modal = $modal.open(modalOptions);
$rootScope.$digest();
$timeout.flush(0);
return modal;
}

Expand Down Expand Up @@ -258,7 +259,6 @@ describe('$modal', function () {
expect(document.activeElement.tagName).toBe('A');

var modal = open({template: '<div>Content<button>inside modal</button></div>'});
$timeout.flush();
expect(document.activeElement.tagName).toBe('DIV');
expect($document).toHaveModalsOpen(1);

Expand All @@ -280,7 +280,6 @@ describe('$modal', function () {
expect(document.activeElement.tagName).toBe('A');

var modal = open({template: '<div>Content</div>'});
$timeout.flush();
expect(document.activeElement.tagName).toBe('DIV');
expect($document).toHaveModalsOpen(1);

Expand Down Expand Up @@ -580,20 +579,17 @@ describe('$modal', function () {
expect($document).toHaveBackdrop();
});

it('should animate backdrop on each modal opening', function () {
it('should contain backdrop in classes on each modal opening', function () {

var modal = open({ template: '<div>With backdrop</div>' });
var backdropEl = $document.find('body > div.modal-backdrop');
expect(backdropEl).not.toHaveClass('in');

$timeout.flush();
expect(backdropEl).toHaveClass('in');

dismiss(modal);

modal = open({ template: '<div>With backdrop</div>' });
backdropEl = $document.find('body > div.modal-backdrop');
expect(backdropEl).not.toHaveClass('in');
expect(backdropEl).toHaveClass('in');

});

Expand Down Expand Up @@ -750,13 +746,11 @@ describe('$modal', function () {
expect(document.activeElement.tagName).toBe('A');

var modal1 = open({template: '<div>Modal1<button id="focus">inside modal1</button></div>'});
$timeout.flush();
document.getElementById('focus').focus();
expect(document.activeElement.tagName).toBe('BUTTON');
expect($document).toHaveModalsOpen(1);

var modal2 = open({template: '<div>Modal2</div>'});
$timeout.flush();
expect(document.activeElement.tagName).toBe('DIV');
expect($document).toHaveModalsOpen(2);

Expand Down Expand Up @@ -789,7 +783,7 @@ describe('$modal', function () {
modal = open({template: template, controller: TestCtrl});

preventDefault = true;
expect(close(modal, 'result')).toBeFalsy();
expect(close(modal, 'result', true)).toBeFalsy();
expect($document).toHaveModalsOpen(1);

preventDefault = false;
Expand All @@ -799,7 +793,7 @@ describe('$modal', function () {
modal = open({template: template, controller: TestCtrl});

preventDefault = true;
expect(dismiss(modal, 'result')).toBeFalsy();
expect(dismiss(modal, 'result', true)).toBeFalsy();
expect($document).toHaveModalsOpen(1);

preventDefault = false;
Expand Down
2 changes: 1 addition & 1 deletion template/modal/backdrop.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<div class="modal-backdrop"
modal-animation-class="fade"
ng-class="{in: animate}"
modal-in-class="in"
ng-style="{'z-index': 1040 + (index && 1 || 0) + index*10}"
></div>

0 comments on commit 158d267

Please sign in to comment.