Skip to content

Commit 169e236

Browse files
committed
Merge pull request #274 from pineconellc/modal_reposition
Modal reposition
2 parents 33067ae + 3029c24 commit 169e236

File tree

5 files changed

+58
-21
lines changed

5 files changed

+58
-21
lines changed

src/modal/docs/demo.html

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ <h3>I'm a modal!</h3>
77
</li>
88
</ul>
99
<p>Selected: <b>{{ selected.item }}</b></p>
10+
<button class="button secondary" ng-click="reposition()">Reset top position</button>
1011
<button class="button" ng-click="ok()">OK</button>
1112
<a class="close-reveal-modal" ng-click="cancel()">&#215;</a>
1213
</script>

src/modal/docs/demo.js

+5-1
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,15 @@ angular.module('foundationDemoApp').controller('ModalInstanceCtrl', function ($s
3232
item: $scope.items[0]
3333
};
3434

35+
$scope.reposition = function () {
36+
$modalInstance.reposition();
37+
};
38+
3539
$scope.ok = function () {
3640
$modalInstance.close($scope.selected.item);
3741
};
3842

3943
$scope.cancel = function () {
4044
$modalInstance.dismiss('cancel');
4145
};
42-
});
46+
});

src/modal/docs/readme.md

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ The `open` method returns a modal instance, an object with the following propert
1818

1919
* `close(result)` - a method that can be used to close a modal, passing a result
2020
* `dismiss(reason)` - a method that can be used to dismiss a modal, passing a reason
21+
* `reposition()` - a method that can be used to re-calculate the top position of the modal
2122
* `result` - a promise that is resolved when a modal is closed and rejected when a modal is dismissed
2223
* `opened` - a promise that is resolved when a modal gets opened after downloading content's template and resolving all variables
2324

src/modal/modal.js

+23-6
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ angular.module('mm.foundation.modal', ['mm.foundation.transition'])
118118

119119
var OPENED_MODAL_CLASS = 'modal-open';
120120

121-
var backdropDomEl, backdropScope;
121+
var backdropDomEl, backdropScope, cssTop;
122122
var openedWindows = $$stackedMap.createNew();
123123
var $modalStack = {};
124124

@@ -199,6 +199,14 @@ angular.module('mm.foundation.modal', ['mm.foundation.transition'])
199199
}
200200
}
201201

202+
function calculateModalTop(modalElement, offset) {
203+
if (angular.isUndefined(offset)) {
204+
offset = 0;
205+
}
206+
var scrollY = $window.pageYOffset || 0;
207+
return offset + scrollY;
208+
}
209+
202210
$document.bind('keydown', function (evt) {
203211
var modal;
204212

@@ -236,13 +244,10 @@ angular.module('mm.foundation.modal', ['mm.foundation.transition'])
236244
// distance to top
237245
var faux = angular.element('<div class="reveal-modal" style="z-index:-1""></div>');
238246
parent.append(faux[0]);
239-
var marginTop = parseInt(getComputedStyle(faux[0]).top) || 0;
247+
cssTop = parseInt($window.getComputedStyle(faux[0]).top) || 0;
248+
var openAt = calculateModalTop(faux, cssTop);
240249
faux.remove();
241250

242-
// Using pageYOffset instead of scrollY to ensure compatibility with IE
243-
var scrollY = $window.pageYOffset || 0;
244-
var openAt = scrollY + marginTop;
245-
246251
var angularDomEl = angular.element('<div modal-window style="visibility: visible; top:' + openAt +'px;"></div>')
247252
.attr({
248253
'window-class': modal.windowClass,
@@ -257,6 +262,15 @@ angular.module('mm.foundation.modal', ['mm.foundation.transition'])
257262
parent.addClass(OPENED_MODAL_CLASS);
258263
};
259264

265+
$modalStack.reposition = function (modalInstance) {
266+
var modalWindow = openedWindows.get(modalInstance).value;
267+
if (modalWindow) {
268+
var modalDomEl = modalWindow.modalDomEl;
269+
var top = calculateModalTop(modalDomEl, cssTop);
270+
modalDomEl.css('top', top + "px");
271+
}
272+
};
273+
260274
$modalStack.close = function (modalInstance, result) {
261275
var modalWindow = openedWindows.get(modalInstance);
262276
if (modalWindow) {
@@ -331,6 +345,9 @@ angular.module('mm.foundation.modal', ['mm.foundation.transition'])
331345
},
332346
dismiss: function (reason) {
333347
$modalStack.dismiss(modalInstance, reason);
348+
},
349+
reposition: function () {
350+
$modalStack.reposition(modalInstance);
334351
}
335352
};
336353

src/modal/test/modal.spec.js

+28-14
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
describe('$modal', function () {
22
var $rootScope, $document, $compile, $templateCache, $timeout, $q, $window, $provide;
33
var $modal, $modalProvider;
4-
var mockWindow = {};
4+
var mockWindow, mockComputedStyle;
55

66
var triggerKeyDown = function (element, keyCode) {
77
var e = $.Event("keydown");
@@ -27,13 +27,18 @@ describe('$modal', function () {
2727
var mockdocument = angular.element(document);
2828
$provide.value('$document', mockdocument);
2929

30-
mockwindow = {
30+
mockComputedStyle = {
31+
top: 0
32+
};
33+
34+
mockWindow = {
3135
location: "val",
3236
document: mockdocument,
3337
pageYOffset: 4,
34-
this_is_a_mock_window: true
38+
this_is_a_mock_window: true,
39+
getComputedStyle: jasmine.createSpy("$window.getComputedStyle").andReturn(mockComputedStyle)
3540
};
36-
$provide.value('$window', mockwindow);
41+
$provide.value('$window', mockWindow);
3742

3843
}));
3944

@@ -159,16 +164,14 @@ describe('$modal', function () {
159164
}
160165

161166
describe('modal invoked with y offsets', function () {
167+
it('should create the modal at the correct location based on window y position', function () {
168+
$window.pageYOffset = 400;
162169

163-
it('should create the modal at the correct location based on window y position', function () {
164-
$window.pageYOffset = 400;
165-
166-
var modal = open({template: '<div>Content</div>'});
167-
expect($document).toHaveModalsOpen(1);
168-
expect($document).toHaveModalOpenWithStyle('top', '400px');
169-
});
170-
171-
});
170+
var modal = open({template: '<div>Content</div>'});
171+
expect($document).toHaveModalsOpen(1);
172+
expect($document).toHaveModalOpenWithStyle('top', '400px');
173+
});
174+
});
172175

173176
describe('basic scenarios with default options', function () {
174177

@@ -304,12 +307,23 @@ describe('$modal', function () {
304307
$timeout.flush();
305308
expect($rootScope.$$childTail).toEqual(null);
306309
});
310+
311+
describe("$modalInstance.reposition()", function() {
312+
it('should re-calculate the modal margin top', function () {
313+
$window.pageYOffset = 400;
314+
var modal = open({template: '<div>Content</div>'});
315+
expect($document).toHaveModalOpenWithStyle('top', '400px');
316+
317+
$window.pageYOffset = 500;
318+
modal.reposition();
319+
expect($document).toHaveModalOpenWithStyle('top', '500px');
320+
});
321+
});
307322
});
308323

309324
describe('default options can be changed in a provider', function () {
310325

311326
it('should allow overriding default options in a provider', function () {
312-
313327
$modalProvider.options.backdrop = false;
314328
var modal = open({template: '<div>Content</div>'});
315329

0 commit comments

Comments
 (0)