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

Commit

Permalink
feat(calendar): add clickable arrow button and placeholder
Browse files Browse the repository at this point in the history
  • Loading branch information
jelbourn committed Aug 13, 2015
1 parent 24ae0fa commit c9a2324
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 11 deletions.
37 changes: 29 additions & 8 deletions src/components/calendar/datePicker.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,12 @@
// PRE RELEASE
// TODO(jelbourn): make down-arrow a button to open the calendar
// TODO(jelbourn): aria attributes tying together date input and floating calendar.
// TODO(jelbourn): actual calendar icon next to input
// TODO(jelbourn): something for mobile (probably calendar panel should take up entire screen)
// TODO(jelbourn): style to match specification
// TODO(jelbourn): make sure this plays well with validation and ngMessages.
// TODO(jelbourn): forward more attributes to the internal input (required, autofocus, etc.)
// TODO(jelbourn): floating panel open animation (see animation for menu in spec).
// TODO(jelbourn): error state
// TODO(jelbourn): auto-grow input to accomodate longer dates

// FUTURE VERSION
// TODO(jelbourn): input behavior (masking? auto-complete?)
Expand All @@ -30,7 +29,11 @@
'</md-button>' +
'<div class="md-datepicker-input-container">' +
'<input class="md-datepicker-input">' +
'<div class="md-datepicker-expand-triangle" ng-hide="ctrl.isCalendarOpen"></div>' +

'<md-button md-no-ink class="md-datepicker-triangle-button md-icon-button" ' +
'ng-click="ctrl.openCalendarPane()">' +
'<div class="md-datepicker-expand-triangle"></div>' +
'</md-button>' +
'</div>' +

// This pane (and its shadow) will be detached from here and re-attached to the
Expand All @@ -43,9 +46,12 @@
// inline input / trigger as one shadowed whole.
'<div class="md-date-calendar-pane-shadow md-whiteframe-z1"></div>',
require: ['ngModel', 'mdDatePicker'],
scope: {},
scope: {
placeholder: '@mdPlaceholder'
},
controller: DatePickerCtrl,
controllerAs: 'ctrl',
bindToController: true,
link: function(scope, element, attr, controllers) {
var ngModelCtrl = controllers[0];
var mdDatePickerCtrl = controllers[1];
Expand Down Expand Up @@ -98,6 +104,9 @@
/** @type {HTMLElement} Shadow for floating calendar pane and input trigger. */
this.calendarShadow = $element[0].querySelector('.md-date-calendar-pane-shadow');

/** @type {HTMLElement} Calendar icon button. */
this.calendarButton = $element[0].querySelector('.md-date-picker-button');

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

Expand All @@ -109,15 +118,15 @@

/** @type {boolean} */
this.isDisabled;
this.setDisabled($element[0].disabled);
this.setDisabled($element[0].disabled || angular.isString($attrs['disabled']));

/** @type {boolean} Whether the date-picker's calendar pane is open. */
this.isCalendarOpen = false;

/** Pre-bound click handler is saved so that the event listener can be removed. */
this.bodyClickHandler = this.handleBodyClick.bind(this);

// Unless the user specifies so, the calendar should not be a tab stop.
// Unless the user specifies so, the datepicker should not be a tab stop.
// This is necessary because ngAria might add a tabindex to anything with an ng-model
// (based on whether or not the user has turned that particular feature on/off).
if (!$attrs['tabindex']) {
Expand Down Expand Up @@ -196,7 +205,10 @@
});
};

/** Capture properties set to the date-picker and imperitively handle internal changes. */
/**
* Capture properties set to the date-picker and imperitively handle internal changes.
* This is done to avoid setting up additional $watches.
*/
DatePickerCtrl.prototype.installPropertyInterceptors = function() {
var self = this;

Expand All @@ -206,6 +218,11 @@
get: function() { return self.isDisabled; },
set: function(value) { self.setDisabled(value) }
});

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

/**
Expand All @@ -220,6 +237,8 @@
/** Position and attach the floating calendar to the document. */
DatePickerCtrl.prototype.attachCalendarPane = function() {
this.inputContainer.classList.add('md-open');
this.calendarButton.classList.add('md-open');

var elementRect = this.inputContainer.getBoundingClientRect();

this.calendarPane.style.left = (elementRect.left + window.pageXOffset) + 'px';
Expand All @@ -240,6 +259,8 @@
/** Detach the floating calendar pane from the document. */
DatePickerCtrl.prototype.detachCalendarPane = function() {
this.inputContainer.classList.remove('md-open');
this.calendarButton.classList.remove('md-open');

// Use native DOM removal because we do not want any of the angular state of this element
// to be disposed.
this.calendarPane.parentNode.removeChild(this.calendarPane);
Expand All @@ -248,7 +269,7 @@

/** Open the floating calendar pane. */
DatePickerCtrl.prototype.openCalendarPane = function() {
if (!this.isCalendarOpen) {
if (!this.isCalendarOpen && !this.isDisabled) {
this.isCalendarOpen = true;
this.attachCalendarPane();
this.focusCalendar();
Expand Down
32 changes: 30 additions & 2 deletions src/components/calendar/datePicker.scss
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ $md-datepicker-button-gap: 12px;
display: inline-block;
box-sizing: border-box;
background: none;

&.md-open {
fill: lightblue;
}
}

// The input into which the user can type the date.
Expand Down Expand Up @@ -51,7 +55,12 @@ $md-datepicker-button-gap: 12px;

.md-datepicker-input {
margin-left: 24px;
line-height: 40px;
//line-height: 40px;
height: 40px;
}

.md-datepicker-expand-triangle {
display: none;
}
}
}
Expand All @@ -77,11 +86,30 @@ $md-datepicker-button-gap: 12px;
}


.md-datepicker-triangle-button {
position: absolute;
right: 0;
top: 0;
transform: translateY(-25%) translateX(45%);

&:hover .md-datepicker-expand-triangle {
border-top-color: rgba(black, 0.54);
}
}

// Need crazy specificity to override .md-button.md-icon-button
.md-datepicker-triangle-button.md-button.md-icon-button {
height: auto;
}

$md-date-arrow-size: 6px;
.md-datepicker-expand-triangle {
// Center the triangle inside of the button so that the
// ink ripple origin looks correct.
position: absolute;
right: 0;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);

width: 0;
height: 0;
Expand Down
12 changes: 11 additions & 1 deletion src/components/calendar/demoDatePicker/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,17 @@ <h2>Development tools</h2>
</p>
<hr>

<md-date-picker ng-model="myDate"></md-date-picker>
<md-date-picker ng-model="myDate" md-placeholder="Enter date"></md-date-picker>

<hr>
<h3>Disabled with ng-disabled</h3>
<md-date-picker ng-model="myDate" md-placeholder="Enter date" ng-disabled="true">
</md-date-picker>

<hr>

<h3>Disabled with static disabled attribute</h3>
<md-date-picker ng-model="myDate" placeholder="Enter date" disabled></md-date-picker>

<br><br>
<br><br>
Expand Down

0 comments on commit c9a2324

Please sign in to comment.