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

Commit bd38e8f

Browse files
Pavel R3VoLuT1OneR Zhytomirskywesleycho
Pavel R3VoLuT1OneR Zhytomirsky
authored andcommitted
feat(modal): Added ability to add CSS class to top window
- Added ability to add a class to the most recently opened modal window. Note that even if different classes are specified, the class will only be present if the modal is the most recently opened modal, i.e. if modal1 was opened with a top class of `foo`, and modal2 is opened afterwards with a top class of `bar`, modal2 will have the class `bar` for the modal window, and modal1 will not have the class `foo`. Closes #2524
1 parent 0328a76 commit bd38e8f

File tree

4 files changed

+66
-2
lines changed

4 files changed

+66
-2
lines changed

src/modal/docs/readme.md

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ The `$modal` service has only one method: `open(options)` where available option
1515
* `keyboard` - indicates whether the dialog should be closable by hitting the ESC key, defaults to true
1616
* `backdropClass` - additional CSS class(es) to be added to a modal backdrop template
1717
* `windowClass` - additional CSS class(es) to be added to a modal window template
18+
* `windowTopClass` - CSS class(es) to be added to the top modal window
1819
* `windowTemplateUrl` - a path to a template overriding modal's window template
1920
* `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`
2021
* `openedClass` - class added to the `body` element when the modal is opened. Defaults to `modal-open`

src/modal/modal.js

+18-1
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@ angular.module('ui.bootstrap.modal', [])
176176
},
177177
link: function(scope, element, attrs) {
178178
element.addClass(attrs.windowClass || '');
179+
element.addClass(attrs.windowTopClass || '');
179180
scope.size = attrs.size;
180181

181182
scope.close = function(evt) {
@@ -340,6 +341,7 @@ angular.module('ui.bootstrap.modal', [])
340341
var modalBodyClass = modalWindow.openedClass || OPENED_MODAL_CLASS;
341342
openedClasses.remove(modalBodyClass, modalInstance);
342343
body.toggleClass(modalBodyClass, openedClasses.hasKey(modalBodyClass));
344+
toggleTopWindowClass(true);
343345
});
344346
checkRemoveBackdrop();
345347

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

356+
// Add or remove "windowTopClass" from the top window in the stack
357+
function toggleTopWindowClass(toggleSwitch) {
358+
var modalWindow;
359+
360+
if (openedWindows.length() > 0) {
361+
modalWindow = openedWindows.top().value;
362+
modalWindow.modalDomEl.toggleClass(modalWindow.windowTopClass || '', toggleSwitch);
363+
}
364+
}
365+
354366
function checkRemoveBackdrop() {
355367
//remove backdrop if no longer needed
356368
if (backdropDomEl && backdropIndex() == -1) {
@@ -447,13 +459,16 @@ angular.module('ui.bootstrap.modal', [])
447459
var modalOpener = $document[0].activeElement,
448460
modalBodyClass = modal.openedClass || OPENED_MODAL_CLASS;
449461

462+
toggleTopWindowClass(false);
463+
450464
openedWindows.add(modalInstance, {
451465
deferred: modal.deferred,
452466
renderDeferred: modal.renderDeferred,
453467
modalScope: modal.scope,
454468
backdrop: modal.backdrop,
455469
keyboard: modal.keyboard,
456-
openedClass: modal.openedClass
470+
openedClass: modal.openedClass,
471+
windowTopClass: modal.windowTopClass
457472
});
458473

459474
openedClasses.put(modalBodyClass, modalInstance);
@@ -477,6 +492,7 @@ angular.module('ui.bootstrap.modal', [])
477492
angularDomEl.attr({
478493
'template-url': modal.windowTemplateUrl,
479494
'window-class': modal.windowClass,
495+
'window-top-class': modal.windowTopClass,
480496
'size': modal.size,
481497
'index': openedWindows.length() - 1,
482498
'animate': 'animate'
@@ -701,6 +717,7 @@ angular.module('ui.bootstrap.modal', [])
701717
backdrop: modalOptions.backdrop,
702718
keyboard: modalOptions.keyboard,
703719
backdropClass: modalOptions.backdropClass,
720+
windowTopClass: modalOptions.windowTopClass,
704721
windowClass: modalOptions.windowClass,
705722
windowTemplateUrl: modalOptions.windowTemplateUrl,
706723
size: modalOptions.size,

src/modal/test/modal.spec.js

+38-1
Original file line numberDiff line numberDiff line change
@@ -773,6 +773,17 @@ describe('$modal', function () {
773773
});
774774
});
775775

776+
describe('top window class', function () {
777+
it('should support top class option', function () {
778+
open({
779+
template: '<div>With custom window top class</div>',
780+
windowTopClass: 'top-class'
781+
});
782+
783+
expect($document.find('div.modal')).toHaveClass('top-class');
784+
});
785+
});
786+
776787
describe('size', function() {
777788
it('should support creating small modal dialogs', function() {
778789
open({
@@ -805,7 +816,7 @@ describe('$modal', function () {
805816
describe('animation', function() {
806817
it('should have animation fade classes by default', function() {
807818
open({
808-
template: '<div>Small modal dialog</div>',
819+
template: '<div>Small modal dialog</div>'
809820
});
810821

811822
expect($document.find('.modal')).toHaveClass('fade');
@@ -1079,6 +1090,32 @@ describe('$modal', function () {
10791090
permute(3, function(a) { test(a.map(function(x, i) { return i === 0 ? {reject:x} : x; })); });
10801091
permute(3, function(a) { test(a.map(function(x, i) { return i === 1 ? {reject:x} : x; })); });
10811092
});
1093+
1094+
it('should have top class only on top window', function () {
1095+
var modal1 = open({template: '<div>Content1</div>', windowClass: 'modal1', windowTopClass: 'modal-top'});
1096+
expect($document.find('div.modal1')).toHaveClass('modal-top');
1097+
expect($document).toHaveModalsOpen(1);
1098+
1099+
var modal2 = open({template: '<div>Content1</div>', windowClass: 'modal2', windowTopClass: 'modal-top'});
1100+
expect($document.find('div.modal1')).not.toHaveClass('modal-top');
1101+
expect($document.find('div.modal2')).toHaveClass('modal-top');
1102+
expect($document).toHaveModalsOpen(2);
1103+
1104+
var modal3 = open({template: '<div>Content1</div>', windowClass: 'modal3', windowTopClass: 'modal-top'});
1105+
expect($document.find('div.modal1')).not.toHaveClass('modal-top');
1106+
expect($document.find('div.modal2')).not.toHaveClass('modal-top');
1107+
expect($document.find('div.modal3')).toHaveClass('modal-top');
1108+
expect($document).toHaveModalsOpen(3);
1109+
1110+
dismiss(modal2);
1111+
expect($document.find('div.modal1')).not.toHaveClass('modal-top');
1112+
expect($document.find('div.modal3')).toHaveClass('modal-top');
1113+
expect($document).toHaveModalsOpen(2);
1114+
1115+
close(modal3);
1116+
expect($document.find('div.modal1')).toHaveClass('modal-top');
1117+
expect($document).toHaveModalsOpen(1);
1118+
});
10821119
});
10831120

10841121
describe('modal.closing event', function() {

src/modal/test/modalWindow.spec.js

+9
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,15 @@ describe('modal window', function() {
2525
expect(windowEl).toHaveClass('foo');
2626
});
2727

28+
it('should support window top class', function () {
29+
$rootScope.animate = false;
30+
var windowEl = $compile('<div modal-window animate="animate" window-top-class="test foo">content</div>')($rootScope);
31+
$rootScope.$digest();
32+
33+
expect(windowEl).toHaveClass('test');
34+
expect(windowEl).toHaveClass('foo');
35+
});
36+
2837
it('should support custom template url', inject(function($templateCache) {
2938
$templateCache.put('window.html', '<div class="mywindow" ng-transclude></div>');
3039

0 commit comments

Comments
 (0)