Skip to content
This repository was archived by the owner on Sep 5, 2024. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions src/components/datepicker/js/datepickerDirective.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
*
* @param {Date} ng-model The component's model. Expects a JavaScript Date object.
* @param {expression=} ng-change Expression evaluated when the model value changes.
* @param {expression=} ng-focus Expression evaluated when the input is focused or the calendar is opened.
* @param {expression=} ng-blur Expression evaluated when focus is removed from the input or the calendar is closed.
* @param {Date=} md-min-date Expression representing a min date (inclusive).
* @param {Date=} md-max-date Expression representing a max date (inclusive).
* @param {(function(Date): boolean)=} md-date-filter Function expecting a date and returning a boolean whether it can be selected or not.
Expand Down Expand Up @@ -676,6 +678,7 @@

this.attachCalendarPane();
this.focusCalendar();
this.evalAttr('ngFocus');

// Attach click listener inside of a timeout because, if this open call was triggered by a
// click, we don't want it to be immediately propogated up to the body and handled.
Expand All @@ -698,6 +701,7 @@

self.detachCalendarPane();
self.ngModelCtrl.$setTouched();
self.evalAttr('ngBlur');

self.documentElement.off('click touchstart', self.bodyClickHandler);
window.removeEventListener('resize', self.windowResizeHandler);
Expand Down Expand Up @@ -744,6 +748,13 @@
if (!isFocused) {
this.ngModelCtrl.$setTouched();
}

// The ng* expressions shouldn't be evaluated when mdOpenOnFocus is on,
// because they also get called when the calendar is opened/closed.
if (!this.openOnFocus) {
this.evalAttr(isFocused ? 'ngFocus' : 'ngBlur');
}

this.isFocused = isFocused;
};

Expand Down Expand Up @@ -772,4 +783,14 @@
DatePickerCtrl.prototype.handleWindowBlur = function() {
this.inputFocusedOnWindowBlur = document.activeElement === this.inputElement;
};

/**
* Evaluates an attribute expression against the parent scope.
* @param {String} attr Name of the attribute to be evaluated.
*/
DatePickerCtrl.prototype.evalAttr = function(attr) {
if (this.$attrs[attr]) {
this.$scope.$parent.$eval(this.$attrs[attr]);
}
};
})();
54 changes: 54 additions & 0 deletions src/components/datepicker/js/datepickerDirective.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ describe('md-datepicker', function() {
'md-date-filter="dateFilter"' +
'ng-model="myDate" ' +
'ng-change="dateChangedHandler()" ' +
'ng-focus="focusHandler()" ' +
'ng-blur="blurHandler()" ' +
'ng-required="isRequired" ' +
'ng-disabled="isDisabled">' +
'</md-datepicker>';
Expand Down Expand Up @@ -709,4 +711,56 @@ describe('md-datepicker', function() {
pageScope.$digest();
}
});

describe('ngFocus support', function() {
beforeEach(function() {
pageScope.focusHandler = jasmine.createSpy('ng-focus handler');
});

it('should trigger the ngFocus handler when the input is focused', function() {
controller.ngInputElement.triggerHandler('focus');
expect(pageScope.focusHandler).toHaveBeenCalled();
});

it('should trigger the ngFocus handler when the calendar is opened', function() {
controller.openCalendarPane({});
expect(pageScope.focusHandler).toHaveBeenCalled();
});

it('should only trigger once when mdOpenOnFocus is set', function() {
createDatepickerInstance('<md-datepicker ng-model="myDate" ng-focus="focusHandler()" ' +
'md-open-on-focus></md-datepicker>');

controller.ngInputElement.triggerHandler('focus');
expect(pageScope.focusHandler).toHaveBeenCalledTimes(1);
});
});

describe('ngBlur support', function() {
beforeEach(function() {
pageScope.blurHandler = jasmine.createSpy('ng-blur handler');
});

it('should trigger the ngBlur handler when the input is blurred', function() {
controller.ngInputElement.triggerHandler('blur');
expect(pageScope.blurHandler).toHaveBeenCalled();
});

it('should trigger the ngBlur handler when the calendar is closed', function() {
controller.openCalendarPane({
target: controller.ngInputElement
});
controller.closeCalendarPane();
expect(pageScope.blurHandler).toHaveBeenCalled();
});

it('should only trigger once when mdOpenOnFocus is set', function() {
createDatepickerInstance('<md-datepicker ng-model="myDate" ng-blur="blurHandler()" ' +
'md-open-on-focus></md-datepicker>');

controller.ngInputElement.triggerHandler('focus');
controller.closeCalendarPane();
expect(pageScope.blurHandler).toHaveBeenCalledTimes(1);
});
});
});