diff --git a/src/modal/docs/demo.html b/src/modal/docs/demo.html index 3788c85..b24e55c 100644 --- a/src/modal/docs/demo.html +++ b/src/modal/docs/demo.html @@ -7,6 +7,7 @@

I'm a modal!

Selected: {{ selected.item }}

+ × diff --git a/src/modal/docs/demo.js b/src/modal/docs/demo.js index 5a7a2e4..f4c342d 100644 --- a/src/modal/docs/demo.js +++ b/src/modal/docs/demo.js @@ -32,6 +32,10 @@ angular.module('foundationDemoApp').controller('ModalInstanceCtrl', function ($s item: $scope.items[0] }; + $scope.reposition = function () { + $modalInstance.reposition(); + }; + $scope.ok = function () { $modalInstance.close($scope.selected.item); }; @@ -39,4 +43,4 @@ angular.module('foundationDemoApp').controller('ModalInstanceCtrl', function ($s $scope.cancel = function () { $modalInstance.dismiss('cancel'); }; -}); \ No newline at end of file +}); diff --git a/src/modal/docs/readme.md b/src/modal/docs/readme.md index b7c4886..947951e 100644 --- a/src/modal/docs/readme.md +++ b/src/modal/docs/readme.md @@ -18,6 +18,7 @@ The `open` method returns a modal instance, an object with the following propert * `close(result)` - a method that can be used to close a modal, passing a result * `dismiss(reason)` - a method that can be used to dismiss a modal, passing a reason +* `reposition()` - a method that can be used to re-calculate the top position of the modal * `result` - a promise that is resolved when a modal is closed and rejected when a modal is dismissed * `opened` - a promise that is resolved when a modal gets opened after downloading content's template and resolving all variables diff --git a/src/modal/modal.js b/src/modal/modal.js index f5a3ae5..9e02fb3 100644 --- a/src/modal/modal.js +++ b/src/modal/modal.js @@ -118,7 +118,7 @@ angular.module('mm.foundation.modal', ['mm.foundation.transition']) var OPENED_MODAL_CLASS = 'modal-open'; - var backdropDomEl, backdropScope; + var backdropDomEl, backdropScope, cssTop; var openedWindows = $$stackedMap.createNew(); var $modalStack = {}; @@ -199,6 +199,14 @@ angular.module('mm.foundation.modal', ['mm.foundation.transition']) } } + function calculateModalTop(modalElement, offset) { + if (angular.isUndefined(offset)) { + offset = 0; + } + var scrollY = $window.pageYOffset || 0; + return offset + scrollY; + } + $document.bind('keydown', function (evt) { var modal; @@ -236,13 +244,10 @@ angular.module('mm.foundation.modal', ['mm.foundation.transition']) // distance to top var faux = angular.element('
'); parent.append(faux[0]); - var marginTop = parseInt(getComputedStyle(faux[0]).top) || 0; + cssTop = parseInt($window.getComputedStyle(faux[0]).top) || 0; + var openAt = calculateModalTop(faux, cssTop); faux.remove(); - // Using pageYOffset instead of scrollY to ensure compatibility with IE - var scrollY = $window.pageYOffset || 0; - var openAt = scrollY + marginTop; - var angularDomEl = angular.element('
') .attr({ 'window-class': modal.windowClass, @@ -257,6 +262,15 @@ angular.module('mm.foundation.modal', ['mm.foundation.transition']) parent.addClass(OPENED_MODAL_CLASS); }; + $modalStack.reposition = function (modalInstance) { + var modalWindow = openedWindows.get(modalInstance).value; + if (modalWindow) { + var modalDomEl = modalWindow.modalDomEl; + var top = calculateModalTop(modalDomEl, cssTop); + modalDomEl.css('top', top + "px"); + } + }; + $modalStack.close = function (modalInstance, result) { var modalWindow = openedWindows.get(modalInstance); if (modalWindow) { @@ -331,6 +345,9 @@ angular.module('mm.foundation.modal', ['mm.foundation.transition']) }, dismiss: function (reason) { $modalStack.dismiss(modalInstance, reason); + }, + reposition: function () { + $modalStack.reposition(modalInstance); } }; diff --git a/src/modal/test/modal.spec.js b/src/modal/test/modal.spec.js index 5232d9c..c34efba 100644 --- a/src/modal/test/modal.spec.js +++ b/src/modal/test/modal.spec.js @@ -1,7 +1,7 @@ describe('$modal', function () { var $rootScope, $document, $compile, $templateCache, $timeout, $q, $window, $provide; var $modal, $modalProvider; - var mockWindow = {}; + var mockWindow, mockComputedStyle; var triggerKeyDown = function (element, keyCode) { var e = $.Event("keydown"); @@ -27,13 +27,18 @@ describe('$modal', function () { var mockdocument = angular.element(document); $provide.value('$document', mockdocument); - mockwindow = { + mockComputedStyle = { + top: 0 + }; + + mockWindow = { location: "val", document: mockdocument, pageYOffset: 4, - this_is_a_mock_window: true + this_is_a_mock_window: true, + getComputedStyle: jasmine.createSpy("$window.getComputedStyle").andReturn(mockComputedStyle) }; - $provide.value('$window', mockwindow); + $provide.value('$window', mockWindow); })); @@ -159,16 +164,14 @@ describe('$modal', function () { } describe('modal invoked with y offsets', function () { + it('should create the modal at the correct location based on window y position', function () { + $window.pageYOffset = 400; - it('should create the modal at the correct location based on window y position', function () { - $window.pageYOffset = 400; - - var modal = open({template: '
Content
'}); - expect($document).toHaveModalsOpen(1); - expect($document).toHaveModalOpenWithStyle('top', '400px'); - }); - - }); + var modal = open({template: '
Content
'}); + expect($document).toHaveModalsOpen(1); + expect($document).toHaveModalOpenWithStyle('top', '400px'); + }); + }); describe('basic scenarios with default options', function () { @@ -304,12 +307,23 @@ describe('$modal', function () { $timeout.flush(); expect($rootScope.$$childTail).toEqual(null); }); + + describe("$modalInstance.reposition()", function() { + it('should re-calculate the modal margin top', function () { + $window.pageYOffset = 400; + var modal = open({template: '
Content
'}); + expect($document).toHaveModalOpenWithStyle('top', '400px'); + + $window.pageYOffset = 500; + modal.reposition(); + expect($document).toHaveModalOpenWithStyle('top', '500px'); + }); + }); }); describe('default options can be changed in a provider', function () { it('should allow overriding default options in a provider', function () { - $modalProvider.options.backdrop = false; var modal = open({template: '
Content
'});