Skip to content
This repository has been archived by the owner on May 29, 2019. It is now read-only.

feat(modal): add option to disable animations #2725

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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></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>