Skip to content

Commit

Permalink
feat(datepicker): migrate to mdPanel
Browse files Browse the repository at this point in the history
Migrates the datepicker's positioning logic to mdPanel. All the functionality should work as before.

Fixes angular#9564.
  • Loading branch information
crisbeto committed Sep 26, 2016
1 parent 1b9245a commit 0362caa
Show file tree
Hide file tree
Showing 6 changed files with 292 additions and 437 deletions.
3 changes: 2 additions & 1 deletion src/components/datepicker/datePicker.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@
angular.module('material.components.datepicker', [
'material.core',
'material.components.icon',
'material.components.virtualRepeat'
'material.components.virtualRepeat',
'material.components.panel'
]);
19 changes: 2 additions & 17 deletions src/components/datepicker/datePicker.scss
Original file line number Diff line number Diff line change
Expand Up @@ -116,19 +116,8 @@ md-datepicker {
}
}

.md-datepicker-is-showing .md-scroll-mask {
z-index: $z-index-calendar-pane - 1;
}

// Floating pane that contains the calendar at the bottom of the input.
.md-datepicker-calendar-pane {
// On most browsers the `scale(0)` below prevents this element from
// overflowing it's parent, however IE and Edge seem to disregard it.
// The `left: -100%` pulls the element back in order to ensure that
// it doesn't cause an overflow.
position: absolute;
top: 0;
left: -100%;
z-index: $z-index-calendar-pane;
border-width: 1px;
border-style: solid;
Expand All @@ -149,19 +138,15 @@ md-datepicker {
width: $md-calendar-width;
position: relative;
overflow: hidden;

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

// The calendar portion of the floating pane (vs. the input mask).
.md-datepicker-calendar {
opacity: 0;
// Use a modified timing function (from swift-ease-out) so that the opacity part of the
// animation doesn't come in as quickly so that the floating pane doesn't ever seem to
// cover up the trigger input.
transition: opacity $md-datepicker-open-animation-duration cubic-bezier(0.5, 0, 0.25, 1);
opacity: 0;

.md-pane-open & {
opacity: 1;
Expand Down Expand Up @@ -194,7 +179,7 @@ md-datepicker {
.md-datepicker-triangle-button {
position: absolute;
@include rtl-prop(right, left, 0, auto);
top: $md-date-arrow-size;
top: $md-date-arrow-size / 2;

// TODO(jelbourn): This position isn't great on all platforms.
@include rtl(transform, translateY(-25%) translateX(45%), translateY(-25%) translateX(-45%));
Expand Down
56 changes: 31 additions & 25 deletions src/components/datepicker/js/calendar.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,10 @@
minDate: '=mdMinDate',
maxDate: '=mdMaxDate',
dateFilter: '=mdDateFilter',
_currentView: '@mdCurrentView'
_currentView: '@mdCurrentView',

// private way of passing in the panel from the datepicker
_panelRef: '=mdPanelRef'
},
require: ['ngModel', 'mdCalendar'],
controller: CalendarCtrl,
Expand Down Expand Up @@ -197,13 +200,18 @@

var boundKeyHandler = angular.bind(this, this.handleKeyEvent);

// Bind the keydown handler to the body, in order to handle cases where the focused
// element gets removed from the DOM and stops propagating click events.
angular.element(document.body).on('keydown', boundKeyHandler);
if (this._panelRef) {
// Bind the keydown handler to the body, in order to handle cases where the focused
// element gets removed from the DOM and stops propagating key events.
angular.element(document.body).on('keydown', boundKeyHandler);

$scope.$on('$destroy', function() {
angular.element(document.body).off('keydown', boundKeyHandler);
});
$scope.$on('$destroy', function() {
angular.element(document.body).off('keydown', boundKeyHandler);
});
} else {
// If the calendar on it's own, it shouldn't bind global key handlers.
$element.on('keydown', boundKeyHandler);
}

if (this.minDate && this.minDate > $mdDateLocale.firstRenderableDate) {
this.firstRenderableDate = this.minDate;
Expand Down Expand Up @@ -345,27 +353,25 @@
CalendarCtrl.prototype.handleKeyEvent = function(event) {
var self = this;

this.$scope.$apply(function() {
// Capture escape and emit back up so that a wrapping component
// (such as a date-picker) can decide to close.
if (event.which == self.keyCode.ESCAPE || event.which == self.keyCode.TAB) {
self.$scope.$emit('md-calendar-close');

if (event.which == self.keyCode.TAB) {
if (!this._panelRef || this._panelRef.isAttached) {
this.$scope.$apply(function() {
// Capture tabbing and emit back up so that a wrapping component
// (such as a date-picker) can decide to close.
if (event.which === self.keyCode.TAB) {
self.$scope.$emit('md-calendar-close');
event.preventDefault();
return;
}

return;
}

// Broadcast the action that any child controllers should take.
var action = self.getActionFromKeyEvent(event);
if (action) {
event.preventDefault();
event.stopPropagation();
self.$scope.$broadcast('md-calendar-parent-action', action);
}
});
// Broadcast the action that any child controllers should take.
var action = self.getActionFromKeyEvent(event);
if (action) {
event.preventDefault();
event.stopPropagation();
self.$scope.$broadcast('md-calendar-parent-action', action);
}
});
}
};

/**
Expand Down
12 changes: 6 additions & 6 deletions src/components/datepicker/js/calendar.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ describe('md-calendar', function() {
function dispatchKeyEvent(keyCode, opt_modifiers) {
var mod = opt_modifiers || {};

angular.element(document.body).triggerHandler({
calendarController.$element.triggerHandler({
type: 'keydown',
keyCode: keyCode,
which: keyCode,
Expand Down Expand Up @@ -665,19 +665,19 @@ describe('md-calendar', function() {
});
});

it('should fire an event when escape is pressed', function() {
var escapeHandler = jasmine.createSpy('escapeHandler');
pageScope.$on('md-calendar-close', escapeHandler);
it('should fire an event when tabbing away', function() {
var tabHandler = jasmine.createSpy('tabHandler');
pageScope.$on('md-calendar-close', tabHandler);

pageScope.myDate = new Date(2014, FEB, 11);
applyDateChange();
var selectedDate = element.querySelector('.md-calendar-selected-date');
selectedDate.focus();

dispatchKeyEvent(keyCodes.ESCAPE);
dispatchKeyEvent(keyCodes.TAB);
pageScope.$apply();

expect(escapeHandler).toHaveBeenCalled();
expect(tabHandler).toHaveBeenCalled();
});
});

Expand Down

0 comments on commit 0362caa

Please sign in to comment.