Skip to content
This repository was archived by the owner on Sep 5, 2024. It is now read-only.

Commit 64fb803

Browse files
committed
fix(datepicker): prevent calendar clipping on small screens. For #4558
1 parent 65abc82 commit 64fb803

File tree

2 files changed

+34
-5
lines changed

2 files changed

+34
-5
lines changed

src/components/datepicker/datePicker.js

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -319,9 +319,7 @@
319319
this.calendarButton.disabled = isDisabled;
320320
};
321321

322-
/**
323-
* Resizes the input element based on the size of its content.
324-
*/
322+
/** Resizes the input element based on the size of its content. */
325323
DatePickerCtrl.prototype.resizeInputElement = function() {
326324
this.inputElement.size = this.inputElement.value.length + EXTRA_INPUT_SIZE;
327325
};
@@ -354,6 +352,7 @@
354352
/** Position and attach the floating calendar to the document. */
355353
DatePickerCtrl.prototype.attachCalendarPane = function() {
356354
var calendarPane = this.calendarPane;
355+
calendarPane.style.transform = '';
357356
this.$element.addClass('md-datepicker-open');
358357

359358
var elementRect = this.inputContainer.getBoundingClientRect();
@@ -365,7 +364,22 @@
365364
var paneLeft = elementRect.left - bodyRect.left;
366365

367366
// If the right edge of the pane would be off the screen and shifting it left by the
368-
// difference would not go past the left edge of the screen.
367+
// difference would not go past the left edge of the screen. If the calendar pane is too
368+
// big to fit on the screen at all, move it to the left of the screen and scale the entire
369+
// element down to fit.
370+
if (paneLeft + CALENDAR_PANE_WIDTH > bodyRect.right) {
371+
if (bodyRect.right - CALENDAR_PANE_WIDTH > 0) {
372+
paneLeft = bodyRect.right - CALENDAR_PANE_WIDTH;
373+
} else {
374+
paneLeft = 0;
375+
var scale = bodyRect.width / CALENDAR_PANE_WIDTH;
376+
calendarPane.style.transform = 'scale(' + scale + ')';
377+
}
378+
379+
calendarPane.classList.add('md-datepicker-pos-adjusted');
380+
}
381+
382+
369383
if (paneLeft + CALENDAR_PANE_WIDTH > bodyRect.right &&
370384
bodyRect.right - CALENDAR_PANE_WIDTH > 0) {
371385
paneLeft = bodyRect.right - CALENDAR_PANE_WIDTH;
@@ -382,7 +396,7 @@
382396

383397
calendarPane.style.left = paneLeft + 'px';
384398
calendarPane.style.top = paneTop + 'px';
385-
document.body.appendChild(this.calendarPane);
399+
document.body.appendChild(calendarPane);
386400

387401
// The top of the calendar pane is a transparent box that shows the text input underneath.
388402
// Since the pane is floating, though, the page underneath the pane *adjacent* to the input is

src/components/datepicker/datePicker.spec.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,21 @@ describe('md-date-picker', function() {
110110
document.body.removeChild(element);
111111
});
112112

113+
it('should shink the calendar pane when it would otherwise not fit on the screen', function() {
114+
// Make the body narrow so that the calendar pane won't fit on-screen.
115+
document.body.style.width = '300px';
116+
117+
// Open the calendar pane.
118+
element.querySelector('md-button').click();
119+
$timeout.flush();
120+
121+
// Expect the calendarPane to be scaled by an amount between zero and one.
122+
expect(controller.calendarPane.style.transform).toMatch(/scale\(0\.\d+\)/);
123+
124+
// Reset the body width.
125+
document.body.style.width = '';
126+
});
127+
113128
it('should disable the internal inputs based on ng-disabled binding', function() {
114129
expect(controller.inputElement.disabled).toBe(false);
115130
expect(controller.calendarButton.disabled).toBe(false);

0 commit comments

Comments
 (0)