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

Commit

Permalink
fix(datepicker): fix bad valid date check and resize-on-open.
Browse files Browse the repository at this point in the history
Closes #4270.
  • Loading branch information
jelbourn authored and ThomasBurleson committed Aug 20, 2015
1 parent a6c14b3 commit 1fb8ab5
Show file tree
Hide file tree
Showing 6 changed files with 47 additions and 5 deletions.
18 changes: 16 additions & 2 deletions src/components/datepicker/datePicker.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,9 @@

// This pane will be detached from here and re-attached to the document body.
'<div class="md-datepicker-calendar-pane md-whiteframe-z1">' +
'<div class="md-datepicker-input-mask"></div>' +
'<div class="md-datepicker-input-mask">' +
'<div class="md-datepicker-input-mask-opaque"></div>' +
'</div>' +
'<div class="md-datepicker-calendar">' +
'<md-calendar role="dialog" aria-label="{{::ctrl.dateLocale.msgCalendar}}" ' +
'ng-model="ctrl.date" ng-if="ctrl.isCalendarOpen"></md-calendar>' +
Expand Down Expand Up @@ -134,6 +136,12 @@
/** @type {HTMLElement} Calendar icon button. */
this.calendarButton = $element[0].querySelector('.md-datepicker-button');

/**
* Element covering everything but the input in the top of the floating calendar pane.
* @type {HTMLElement}
*/
this.inputMask = $element[0].querySelector('.md-datepicker-input-mask-opaque');

/** @final {!angular.JQLite} */
this.$element = $element;

Expand Down Expand Up @@ -262,7 +270,7 @@

Object.defineProperty(this, 'placeholder', {
get: function() { return self.inputElement.placeholder; },
set: function(value) { self.inputElement.placeholder = value; }
set: function(value) { self.inputElement.placeholder = value || ''; }
});
};

Expand Down Expand Up @@ -313,6 +321,12 @@
calendarPane.style.top = (elementRect.top - bodyRect.top) + 'px';
document.body.appendChild(this.calendarPane);

// The top of the calendar pane is a transparent box that shows the text input underneath.
// Since the pane is flowing, though, the page underneath the pane *adjacent* to the input is
// also shown unless we cover it up. The inputMask does this by filling up the remaining space
// based on the width of the input.
this.inputMask.style.left = elementRect.width + 'px';

// Add CSS class after one frame to trigger open animation.
this.$$rAF(function() {
calendarPane.classList.add('md-pane-open');
Expand Down
15 changes: 14 additions & 1 deletion src/components/datepicker/datePicker.scss
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ $md-datepicker-button-gap: 12px; // Space between the text input and the calend
$md-datepicker-border-bottom-gap: 5px; // Space between input and the grey underline.
$md-datepicker-open-animation-duration: 0.2s;

md-datepicker {
// Don't let linebreaks happen between the open icon-button and the input.
white-space: nowrap;
}

// The calendar icon button used to open the calendar pane.
// Need absurd specificty to override md-button.md-icon-button.
Expand Down Expand Up @@ -62,12 +66,22 @@ $md-datepicker-open-animation-duration: 0.2s;
.md-datepicker-input-mask {
height: 40px;
width: $md-calendar-width;
position: relative;

background: transparent;
pointer-events: none;
cursor: text;
}

.md-datepicker-input-mask-opaque {
position: absolute;
right: 0;
left: 120px;
background: white;

height: 100%;
}

// The calendar portion of the floating pane (vs. the input mask).
.md-datepicker-calendar {
opacity: 0;
Expand Down Expand Up @@ -136,7 +150,6 @@ md-datepicker[disabled] {
// Open state for all of the elements of the picker.
.md-datepicker-open {
.md-datepicker-input-container {
min-width: $md-calendar-width;
margin-left: -$md-datepicker-button-gap;
border: none;
}
Expand Down
1 change: 1 addition & 0 deletions src/components/datepicker/datePicker.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ describe('md-date-picker', function() {
$timeout.flush();

expect(controller.calendarPane.offsetHeight).toBeGreaterThan(0);
expect(controller.inputMask.style.left).toBe(controller.inputContainer.clientWidth + 'px');

// Click off of the calendar.
document.body.click();
Expand Down
2 changes: 1 addition & 1 deletion src/components/datepicker/dateUtil.js
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@
* @return {boolean} Whether the date is a valid Date.
*/
function isValidDate(date) {
return date !== null && date.getTime && !isNaN(date.getTime());
return date != null && date.getTime && !isNaN(date.getTime());
}

/**
Expand Down
15 changes: 15 additions & 0 deletions src/components/datepicker/dateUtil.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -303,4 +303,19 @@ describe('$$mdDateUtil', function() {
expect(dayAtMidnight.getSeconds()).toBe(0);
expect(dayAtMidnight.getMilliseconds()).toBe(0);
});

it('should determine whether dates are valid', function() {
expect(dateUtil.isValidDate(null)).toBeFalsy();
expect(dateUtil.isValidDate(undefined)).toBeFalsy();
expect(dateUtil.isValidDate('')).toBeFalsy();
expect(dateUtil.isValidDate(0)).toBeFalsy();
expect(dateUtil.isValidDate(NaN)).toBeFalsy();
expect(dateUtil.isValidDate(123456789)).toBeFalsy();
expect(dateUtil.isValidDate('123456789')).toBeFalsy();
expect(dateUtil.isValidDate(new Date(''))).toBeFalsy();
expect(dateUtil.isValidDate(new Date('Banjo'))).toBeFalsy();
expect(dateUtil.isValidDate(new Date(NaN))).toBeFalsy();

expect(dateUtil.isValidDate(new Date())).toBe(true);
});
});
1 change: 0 additions & 1 deletion src/components/input/demoBasicUsage/script.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ angular
$scope.user = {
title: 'Developer',
email: 'ipsum@lorem.com',
submissionDate: new Date(),
firstName: '',
lastName: '' ,
company: 'Google' ,
Expand Down

0 comments on commit 1fb8ab5

Please sign in to comment.