Skip to content

Commit

Permalink
feat(modal): add option to disable animations
Browse files Browse the repository at this point in the history
Note: Move backdropClass logic into compile function because otherwise
modifying classes in the compile function is broken when using an interpolated
class attribute.

Fixes angular-ui#1007
Closes angular-ui#2725
  • Loading branch information
chrisirhc authored and fernando-sendMail committed Jul 16, 2015
1 parent 30735ea commit 59cd1c3
Show file tree
Hide file tree
Showing 7 changed files with 74 additions and 12 deletions.
1 change: 1 addition & 0 deletions src/modal/docs/demo.html
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,6 @@ <h3 class="modal-title">I'm a modal!</h3>
<button class="btn btn-default" ng-click="open()">Open me!</button>
<button class="btn btn-default" ng-click="open('lg')">Large modal</button>
<button class="btn btn-default" ng-click="open('sm')">Small modal</button>
<button class="btn btn-default" ng-click="toggleAnimation()">Toggle Animation ({{ animationsEnabled }})</button>
<div ng-show="selected">Selection from a modal: {{ selected }}</div>
</div>
8 changes: 8 additions & 0 deletions src/modal/docs/demo.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@ angular.module('ui.bootstrap.demo').controller('ModalDemoCtrl', function ($scope

$scope.items = ['item1', 'item2', 'item3'];

$scope.animationsEnabled = true;

$scope.open = function (size) {

var modalInstance = $modal.open({
animation: $scope.animationsEnabled,
templateUrl: 'myModalContent.html',
controller: 'ModalInstanceCtrl',
size: size,
Expand All @@ -21,6 +24,11 @@ angular.module('ui.bootstrap.demo').controller('ModalDemoCtrl', function ($scope
$log.info('Modal dismissed at: ' + new Date());
});
};

$scope.toggleAnimation = function () {
$scope.animationsEnabled = !$scope.animationsEnabled;
};

});

// Please note that $modalInstance represents a modal window (instance) dependency.
Expand Down
4 changes: 4 additions & 0 deletions src/modal/docs/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ The `$modal` service has only one method: `open(options)` where available option
* `controller` - a controller for a modal instance - it can initialize scope used by modal. Accepts the "controller-as" syntax in the form 'SomeCtrl as myctrl'; can be injected with `$modalInstance`
* `controllerAs` - an alternative to the controller-as syntax, matching the API of directive definitions. Requires the `controller` option to be provided as well
* `resolve` - members that will be resolved and passed to the controller as locals; it is equivalent of the `resolve` property for AngularJS routes
* `animation` - set to false to disable animations on new modal/backdrop. Does not toggle animations for modals/backdrops that are already displayed.
* `backdrop` - controls presence of a backdrop. Allowed values: true (default), false (no backdrop), `'static'` - backdrop is present but modal window is not closed when clicking outside of the modal window.
* `keyboard` - indicates whether the dialog should be closable by hitting the ESC key, defaults to true
* `backdropClass` - additional CSS class(es) to be added to a modal backdrop template
Expand All @@ -35,3 +36,6 @@ Finally, a `modal.closing` event is broadcast to the modal scope before the moda
preventDefault on the event, then the modal will remain open. The $close and $dismiss methods return true if the
event was allowed. The event itself includes a parameter for the result/reason and a boolean parameter that indicates
whether the modal is being closed (true) or dismissed.

The `modalConfig` exposes the following global option for all modals/backdrops:

42 changes: 32 additions & 10 deletions src/modal/modal.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,17 +62,20 @@ angular.module('ui.bootstrap.modal', [])
restrict: 'EA',
replace: true,
templateUrl: 'template/modal/backdrop.html',
link: function (scope, element, attrs) {
scope.backdropClass = attrs.backdropClass || '';

scope.animate = false;

//trigger CSS transitions
$timeout(function () {
scope.animate = true;
});
compile: function (tElement, tAttrs) {
tElement.addClass(tAttrs.backdropClass);
return linkFn;
}
};

function linkFn(scope, element, attrs) {
scope.animate = false;

//trigger CSS transitions
$timeout(function () {
scope.animate = true;
});
}
}])

.directive('modalWindow', ['$modalStack', '$q', function ($modalStack, $q) {
Expand Down Expand Up @@ -144,6 +147,17 @@ angular.module('ui.bootstrap.modal', [])
};
}])

.directive('modalAnimationClass', [
function () {
return {
compile: function (tElement, tAttrs) {
if (tAttrs.modalAnimation) {
tElement.addClass(tAttrs.modalAnimationClass);
}
}
};
}])

.directive('modalTransclude', function () {
return {
link: function($scope, $element, $attrs, controller, $transclude) {
Expand Down Expand Up @@ -212,7 +226,7 @@ angular.module('ui.bootstrap.modal', [])
// Closing animation
scope.animate = false;

if ($animate.enabled()) {
if (domEl.attr('modal-animation') && $animate.enabled()) {
// transition out
domEl.one('$animate:close', function closeFn() {
$rootScope.$evalAsync(afterAnimating);
Expand Down Expand Up @@ -268,6 +282,9 @@ angular.module('ui.bootstrap.modal', [])
backdropScope.index = currBackdropIndex;
var angularBackgroundDomEl = angular.element('<div modal-backdrop="modal-backdrop"></div>');
angularBackgroundDomEl.attr('backdrop-class', modal.backdropClass);
if (modal.animation) {
angularBackgroundDomEl.attr('modal-animation', 'true');
}
backdropDomEl = $compile(angularBackgroundDomEl)(backdropScope);
body.append(backdropDomEl);
}
Expand All @@ -280,6 +297,9 @@ angular.module('ui.bootstrap.modal', [])
'index': openedWindows.length() - 1,
'animate': 'animate'
}).html(modal.content);
if (modal.animation) {
angularDomEl.attr('modal-animation', 'true');
}

var modalDomEl = $compile(angularDomEl)(modal.scope);
openedWindows.top().value.modalDomEl = modalDomEl;
Expand Down Expand Up @@ -336,6 +356,7 @@ angular.module('ui.bootstrap.modal', [])

var $modalProvider = {
options: {
animation: true,
backdrop: true, //can be also false or 'static'
keyboard: true
},
Expand Down Expand Up @@ -422,6 +443,7 @@ angular.module('ui.bootstrap.modal', [])
deferred: modalResultDeferred,
renderDeferred: modalRenderDeferred,
content: tplAndVars[0],
animation: modalOptions.animation,
backdrop: modalOptions.backdrop,
keyboard: modalOptions.keyboard,
backdropClass: modalOptions.backdropClass,
Expand Down
24 changes: 24 additions & 0 deletions src/modal/test/modal.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -558,6 +558,30 @@ describe('$modal', function () {
expect($document.find('div.modal-dialog')).toHaveClass('modal-custom');
});
});

describe('animation', function () {

it('should have animation fade classes by default', function () {
open({
template: '<div>Small modal dialog</div>',
});

expect($document.find('.modal')).toHaveClass('fade');
expect($document.find('.modal-backdrop')).toHaveClass('fade');
});

it('should not have fade classes if animation false', function () {
open({
template: '<div>Small modal dialog</div>',
animation: false
});

expect($document.find('.modal')).not.toHaveClass('fade');
expect($document.find('.modal-backdrop')).not.toHaveClass('fade');
});

});

});

describe('multiple modals', function () {
Expand Down
3 changes: 2 additions & 1 deletion template/modal/backdrop.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<div class="modal-backdrop fade {{ backdropClass }}"
<div class="modal-backdrop"
modal-animation-class="fade"
ng-class="{in: animate}"
ng-style="{'z-index': 1040 + (index && 1 || 0) + index*10}"
></div>
4 changes: 3 additions & 1 deletion template/modal/window.html
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
<div modal-render="{{$isRendered}}" tabindex="-1" role="dialog" class="modal fade" ng-class="{in: animate}" ng-style="{'z-index': 1050 + index*10, display: 'block'}" ng-click="close($event)">
<div modal-render="{{$isRendered}}" tabindex="-1" role="dialog" class="modal"
modal-animation-class="fade"
ng-class="{in: animate}" ng-style="{'z-index': 1050 + index*10, display: 'block'}" ng-click="close($event)">
<div class="modal-dialog" ng-class="size ? 'modal-' + size : ''"><div class="modal-content" modal-transclude></div></div>
</div>

0 comments on commit 59cd1c3

Please sign in to comment.