From c0f21e15fec8522fd7df0bd570109228f7773e3f Mon Sep 17 00:00:00 2001 From: Ajay kumar Guthikonda Date: Mon, 12 Oct 2015 16:53:06 -0700 Subject: [PATCH] feat(modal): add container option feat(modal): add container option --- src/modal/docs/readme.md | 1 + src/modal/modal.js | 25 +++++++++++++-------- src/modal/test/modal.spec.js | 42 ++++++++++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+), 9 deletions(-) diff --git a/src/modal/docs/readme.md b/src/modal/docs/readme.md index e3c50643bf..80dc58ab29 100644 --- a/src/modal/docs/readme.md +++ b/src/modal/docs/readme.md @@ -19,6 +19,7 @@ The `$uibModal` service has only one method: `open(options)` where available opt * `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` +* `container` - Appends the modal to a specific element. container must be an `angular.element`. Defaults to `body` element. Example: `container: $document.find('aside')`. Global defaults may be set for `$uibModal` via `$uibModalProvider.options`. diff --git a/src/modal/modal.js b/src/modal/modal.js index 971e5410eb..b15770fc88 100644 --- a/src/modal/modal.js +++ b/src/modal/modal.js @@ -276,8 +276,8 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.stackedMap']) }); function removeModalWindow(modalInstance, elementToReceiveFocus) { - var body = $document.find('body').eq(0); var modalWindow = openedWindows.get(modalInstance).value; + var container = $document.find(modalWindow.container).eq(0); //clean up the stack openedWindows.remove(modalInstance); @@ -285,7 +285,7 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.stackedMap']) removeAfterAnimate(modalWindow.modalDomEl, modalWindow.modalScope, function() { var modalBodyClass = modalWindow.openedClass || OPENED_MODAL_CLASS; openedClasses.remove(modalBodyClass, modalInstance); - body.toggleClass(modalBodyClass, openedClasses.hasKey(modalBodyClass)); + container.toggleClass(modalBodyClass, openedClasses.hasKey(modalBodyClass)); toggleTopWindowClass(true); }); checkRemoveBackdrop(); @@ -294,7 +294,7 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.stackedMap']) if (elementToReceiveFocus && elementToReceiveFocus.focus) { elementToReceiveFocus.focus(); } else { - body.focus(); + container.focus(); } } @@ -413,14 +413,19 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.stackedMap']) backdrop: modal.backdrop, keyboard: modal.keyboard, openedClass: modal.openedClass, - windowTopClass: modal.windowTopClass + windowTopClass: modal.windowTopClass, + container: modal.container }); openedClasses.put(modalBodyClass, modalInstance); - var body = $document.find('body').eq(0), + var container = $document.find(modal.container).eq(0), currBackdropIndex = backdropIndex(); + if (!container.length) { + throw new Error('Container not found. Make sure that the container passed is in DOM.'); + } + if (currBackdropIndex >= 0 && !backdropDomEl) { backdropScope = $rootScope.$new(true); backdropScope.index = currBackdropIndex; @@ -430,7 +435,7 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.stackedMap']) angularBackgroundDomEl.attr('modal-animation', 'true'); } backdropDomEl = $compile(angularBackgroundDomEl)(backdropScope); - body.append(backdropDomEl); + container.append(backdropDomEl); } var angularDomEl = angular.element('
'); @@ -449,8 +454,8 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.stackedMap']) var modalDomEl = $compile(angularDomEl)(modal.scope); openedWindows.top().value.modalDomEl = modalDomEl; openedWindows.top().value.modalOpener = modalOpener; - body.append(modalDomEl); - body.addClass(modalBodyClass); + container.append(modalDomEl); + container.addClass(modalBodyClass); $modalStack.clearFocusListCache(); }; @@ -603,6 +608,7 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.stackedMap']) //merge and clean up options modalOptions = angular.extend({}, $modalProvider.options, modalOptions); modalOptions.resolve = modalOptions.resolve || {}; + modalOptions.container = modalOptions.container || 'body'; //verify options if (!modalOptions.template && !modalOptions.templateUrl) { @@ -669,7 +675,8 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.stackedMap']) windowClass: modalOptions.windowClass, windowTemplateUrl: modalOptions.windowTemplateUrl, size: modalOptions.size, - openedClass: modalOptions.openedClass + openedClass: modalOptions.openedClass, + container: modalOptions.container }); modalOpenedDeferred.resolve(true); diff --git a/src/modal/test/modal.spec.js b/src/modal/test/modal.spec.js index d6c7c03a37..ed48fe14d5 100644 --- a/src/modal/test/modal.spec.js +++ b/src/modal/test/modal.spec.js @@ -833,6 +833,48 @@ describe('$uibModal', function () { expect($document.find('.modal-backdrop')).not.toHaveClass('fade'); }); }); + + describe('container', function() { + it('should be added to body by default', function() { + var modal = open({template: '
Content
'}); + + expect($document).toHaveModalsOpen(1); + expect($document).toHaveModalOpenWithContent('Content', 'div'); + }); + + it('should not be added to body if container is passed', function() { + var element = angular.element('
Some content
'); + angular.element(document.body).append(element); + + var modal = open({template: '
Content
', container: element}); + + expect($document).not.toHaveModalOpenWithContent('Content', 'div'); + }); + + it('should be added to container if container is passed', function() { + var element = angular.element('
Some content
'); + angular.element(document.body).append(element); + + expect($document.find('section').children('div.modal').length).toBe(0); + open({template: '
Content
', container: element}); + expect($document.find('section').children('div.modal').length).toBe(1); + }); + + it('should throw error if container is not found', function() { + expect(function(){ + open({template: '
Content
', container: $document.find('aside')}); + }).toThrow(new Error('Container not found. Make sure that the container passed is in DOM.')); + }); + + it('should be removed from container when dismissed', function() { + var modal = open({template: '
Content
'}); + + expect($document).toHaveModalsOpen(1); + + dismiss(modal); + expect($document).toHaveModalsOpen(0); + }); + }); describe('openedClass', function() { var body;