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

feat(modal): Add CSS class(es) to the top modal window #2524

Closed
wants to merge 1 commit into from
Closed
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/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ The `$modal` service has only one method: `open(options)` where available option
* `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
* `windowClass` - additional CSS class(es) to be added to a modal window template
* `windowTopClass` - CSS class(es) to be added to the top modal window
* `windowTemplateUrl` - a path to a template overriding modal's window template
* `size` - optional suffix of modal window class. The value used is appended to the `modal-` class, i.e. a value of `sm` gives `modal-sm`
* `openedClass` - class added to the `body` element when the modal is opened. Defaults to `modal-open`
Expand Down
19 changes: 18 additions & 1 deletion src/modal/modal.js
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ angular.module('ui.bootstrap.modal', [])
},
link: function(scope, element, attrs) {
element.addClass(attrs.windowClass || '');
element.addClass(attrs.windowTopClass || '');
scope.size = attrs.size;

scope.close = function(evt) {
Expand Down Expand Up @@ -340,6 +341,7 @@ angular.module('ui.bootstrap.modal', [])
var modalBodyClass = modalWindow.openedClass || OPENED_MODAL_CLASS;
openedClasses.remove(modalBodyClass, modalInstance);
body.toggleClass(modalBodyClass, openedClasses.hasKey(modalBodyClass));
toggleTopWindowClass(true);
});
checkRemoveBackdrop();

Expand All @@ -351,6 +353,16 @@ angular.module('ui.bootstrap.modal', [])
}
}

// Add or remove "windowTopClass" from the top window in the stack
function toggleTopWindowClass(toggleSwitch) {
var modalWindow;

if (openedWindows.length() > 0) {
modalWindow = openedWindows.top().value;
modalWindow.modalDomEl.toggleClass(modalWindow.windowTopClass || '', toggleSwitch);
}
}

function checkRemoveBackdrop() {
//remove backdrop if no longer needed
if (backdropDomEl && backdropIndex() == -1) {
Expand Down Expand Up @@ -447,13 +459,16 @@ angular.module('ui.bootstrap.modal', [])
var modalOpener = $document[0].activeElement,
modalBodyClass = modal.openedClass || OPENED_MODAL_CLASS;

toggleTopWindowClass(false);

openedWindows.add(modalInstance, {
deferred: modal.deferred,
renderDeferred: modal.renderDeferred,
modalScope: modal.scope,
backdrop: modal.backdrop,
keyboard: modal.keyboard,
openedClass: modal.openedClass
openedClass: modal.openedClass,
windowTopClass: modal.windowTopClass
});

openedClasses.put(modalBodyClass, modalInstance);
Expand All @@ -477,6 +492,7 @@ angular.module('ui.bootstrap.modal', [])
angularDomEl.attr({
'template-url': modal.windowTemplateUrl,
'window-class': modal.windowClass,
'window-top-class': modal.windowTopClass,
'size': modal.size,
'index': openedWindows.length() - 1,
'animate': 'animate'
Expand Down Expand Up @@ -701,6 +717,7 @@ angular.module('ui.bootstrap.modal', [])
backdrop: modalOptions.backdrop,
keyboard: modalOptions.keyboard,
backdropClass: modalOptions.backdropClass,
windowTopClass: modalOptions.windowTopClass,
windowClass: modalOptions.windowClass,
windowTemplateUrl: modalOptions.windowTemplateUrl,
size: modalOptions.size,
Expand Down
42 changes: 41 additions & 1 deletion src/modal/test/modal.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -771,6 +771,20 @@ describe('$modal', function () {

expect($document.find('div.modal')).toHaveClass('additional');
});

});

describe('top window class', function () {

it('should support top class option', function () {
open({
template: '<div>With custom window top class</div>',
windowTopClass: 'top-class'
});

expect($document.find('div.modal')).toHaveClass('top-class');
});

});

describe('size', function() {
Expand Down Expand Up @@ -805,7 +819,7 @@ describe('$modal', function () {
describe('animation', function() {
it('should have animation fade classes by default', function() {
open({
template: '<div>Small modal dialog</div>',
template: '<div>Small modal dialog</div>'
});

expect($document.find('.modal')).toHaveClass('fade');
Expand Down Expand Up @@ -1079,6 +1093,32 @@ describe('$modal', function () {
permute(3, function(a) { test(a.map(function(x, i) { return i === 0 ? {reject:x} : x; })); });
permute(3, function(a) { test(a.map(function(x, i) { return i === 1 ? {reject:x} : x; })); });
});

it('should have top class only on top window', function () {
var modal1 = open({template: '<div>Content1</div>', windowClass: 'modal1', windowTopClass: 'modal-top'});
expect($document.find('div.modal1')).toHaveClass('modal-top');
expect($document).toHaveModalsOpen(1);

var modal2 = open({template: '<div>Content1</div>', windowClass: 'modal2', windowTopClass: 'modal-top'});
expect($document.find('div.modal1')).not.toHaveClass('modal-top');
expect($document.find('div.modal2')).toHaveClass('modal-top');
expect($document).toHaveModalsOpen(2);

var modal3 = open({template: '<div>Content1</div>', windowClass: 'modal3', windowTopClass: 'modal-top'});
expect($document.find('div.modal1')).not.toHaveClass('modal-top');
expect($document.find('div.modal2')).not.toHaveClass('modal-top');
expect($document.find('div.modal3')).toHaveClass('modal-top');
expect($document).toHaveModalsOpen(3);

dismiss(modal2);
expect($document.find('div.modal1')).not.toHaveClass('modal-top');
expect($document.find('div.modal3')).toHaveClass('modal-top');
expect($document).toHaveModalsOpen(2);

close(modal3);
expect($document.find('div.modal1')).toHaveClass('modal-top');
expect($document).toHaveModalsOpen(1);
});
});

describe('modal.closing event', function() {
Expand Down
10 changes: 10 additions & 0 deletions src/modal/test/modalWindow.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,15 @@ describe('modal window', function() {
expect(windowEl).toHaveClass('foo');
});

it('should support window top class', function () {
$rootScope.animate = false;
var windowEl = $compile('<div modal-window animate="animate" window-top-class="test foo">content</div>')($rootScope);
$rootScope.$digest();

expect(windowEl).toHaveClass('test');
expect(windowEl).toHaveClass('foo');
});

it('should support custom template url', inject(function($templateCache) {
$templateCache.put('window.html', '<div class="mywindow" ng-transclude></div>');

Expand All @@ -34,4 +43,5 @@ describe('modal window', function() {
expect(windowEl).toHaveClass('mywindow');
expect(windowEl).toHaveClass('test');
}));

});