Skip to content

Commit

Permalink
Merge pull request #274 from pineconellc/modal_reposition
Browse files Browse the repository at this point in the history
Modal reposition
  • Loading branch information
jbrowning committed Oct 13, 2015
2 parents 33067ae + 3029c24 commit 169e236
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 21 deletions.
1 change: 1 addition & 0 deletions src/modal/docs/demo.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ <h3>I'm a modal!</h3>
</li>
</ul>
<p>Selected: <b>{{ selected.item }}</b></p>
<button class="button secondary" ng-click="reposition()">Reset top position</button>
<button class="button" ng-click="ok()">OK</button>
<a class="close-reveal-modal" ng-click="cancel()">&#215;</a>
</script>
Expand Down
6 changes: 5 additions & 1 deletion src/modal/docs/demo.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,15 @@ angular.module('foundationDemoApp').controller('ModalInstanceCtrl', function ($s
item: $scope.items[0]
};

$scope.reposition = function () {
$modalInstance.reposition();
};

$scope.ok = function () {
$modalInstance.close($scope.selected.item);
};

$scope.cancel = function () {
$modalInstance.dismiss('cancel');
};
});
});
1 change: 1 addition & 0 deletions src/modal/docs/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
29 changes: 23 additions & 6 deletions src/modal/modal.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {};

Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -236,13 +244,10 @@ angular.module('mm.foundation.modal', ['mm.foundation.transition'])
// distance to top
var faux = angular.element('<div class="reveal-modal" style="z-index:-1""></div>');
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('<div modal-window style="visibility: visible; top:' + openAt +'px;"></div>')
.attr({
'window-class': modal.windowClass,
Expand All @@ -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) {
Expand Down Expand Up @@ -331,6 +345,9 @@ angular.module('mm.foundation.modal', ['mm.foundation.transition'])
},
dismiss: function (reason) {
$modalStack.dismiss(modalInstance, reason);
},
reposition: function () {
$modalStack.reposition(modalInstance);
}
};

Expand Down
42 changes: 28 additions & 14 deletions src/modal/test/modal.spec.js
Original file line number Diff line number Diff line change
@@ -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");
Expand All @@ -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);

}));

Expand Down Expand Up @@ -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: '<div>Content</div>'});
expect($document).toHaveModalsOpen(1);
expect($document).toHaveModalOpenWithStyle('top', '400px');
});

});
var modal = open({template: '<div>Content</div>'});
expect($document).toHaveModalsOpen(1);
expect($document).toHaveModalOpenWithStyle('top', '400px');
});
});

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

Expand Down Expand Up @@ -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: '<div>Content</div>'});
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: '<div>Content</div>'});

Expand Down

0 comments on commit 169e236

Please sign in to comment.