in src/components/datepicker/js/datepickerDirective.js [278:453]
function DatePickerCtrl($scope, $element, $attrs, $window, $mdConstant, $mdTheming, $mdUtil,
$mdDateLocale, $$mdDateUtil, $$rAF, $filter, $timeout) {
/** @final */
this.$window = $window;
/** @final */
this.dateUtil = $$mdDateUtil;
/** @final */
this.$mdConstant = $mdConstant;
/** @final */
this.$mdUtil = $mdUtil;
/** @final */
this.$$rAF = $$rAF;
/** @final */
this.$mdDateLocale = $mdDateLocale;
/** @final */
this.$timeout = $timeout;
/**
* The root document element. This is used for attaching a top-level click handler to
* close the calendar panel when a click outside said panel occurs. We use `documentElement`
* instead of body because, when scrolling is disabled, some browsers consider the body element
* to be completely off the screen and propagate events directly to the html element.
* @type {!JQLite}
*/
this.documentElement = angular.element(document.documentElement);
/** @type {!ngModel.NgModelController} */
this.ngModelCtrl = null;
/** @type {HTMLInputElement} */
this.inputElement = $element[0].querySelector('input');
/**
* @final
* @type {!JQLite}
*/
this.ngInputElement = angular.element(this.inputElement);
/** @type {HTMLElement} */
this.inputContainer = $element[0].querySelector('.md-datepicker-input-container');
/** @type {HTMLElement} Floating calendar pane. */
this.calendarPane = $element[0].querySelector('.md-datepicker-calendar-pane');
/** @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 {!JQLite}
*/
this.inputMask = angular.element($element[0].querySelector('.md-datepicker-input-mask-opaque'));
/**
* @final
* @type {!JQLite}
*/
this.$element = $element;
/**
* @final
* @type {!angular.Attributes}
*/
this.$attrs = $attrs;
/**
* @final
* @type {!angular.Scope}
*/
this.$scope = $scope;
/**
* This holds the model that will be used by the calendar.
* @type {Date|null|undefined}
*/
this.date = null;
/** @type {boolean} */
this.isFocused = false;
/** @type {boolean} */
this.isDisabled = undefined;
this.setDisabled($element[0].disabled || angular.isString($attrs.disabled));
/** @type {boolean} Whether the date-picker's calendar pane is open. */
this.isCalendarOpen = false;
/** @type {boolean} Whether the calendar should open when the input is focused. */
this.openOnFocus = $attrs.hasOwnProperty('mdOpenOnFocus');
/** @type {Object} Instance of the mdInputContainer controller */
this.mdInputContainer = null;
/**
* Element from which the calendar pane was opened. Keep track of this so that we can return
* focus to it when the pane is closed.
* @type {HTMLElement}
*/
this.calendarPaneOpenedFrom = null;
/** @type {String} Unique id for the calendar pane. */
this.calendarPaneId = 'md-date-pane-' + $mdUtil.nextUid();
/** Pre-bound click handler is saved so that the event listener can be removed. */
this.bodyClickHandler = angular.bind(this, this.handleBodyClick);
/**
* Name of the event that will trigger a close. Necessary to sniff the browser, because
* the resize event doesn't make sense on mobile and can have a negative impact since it
* triggers whenever the browser zooms in on a focused input.
*/
this.windowEventName = IS_MOBILE_REGEX.test(
navigator.userAgent || navigator.vendor || window.opera
) ? 'orientationchange' : 'resize';
/** Pre-bound close handler so that the event listener can be removed. */
this.windowEventHandler = $mdUtil.debounce(angular.bind(this, this.closeCalendarPane), 100);
/** Pre-bound handler for the window blur event. Allows for it to be removed later. */
this.windowBlurHandler = angular.bind(this, this.handleWindowBlur);
/** The built-in AngularJS date filter. */
this.ngDateFilter = $filter('date');
/** @type {Number} Extra margin for the left side of the floating calendar pane. */
this.leftMargin = 20;
/** @type {Number} Extra margin for the top of the floating calendar. Gets determined on the first open. */
this.topMargin = null;
// 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) {
this.ngInputElement.attr('tabindex', $attrs.tabindex);
$attrs.$set('tabindex', null);
} else {
$attrs.$set('tabindex', '-1');
}
$attrs.$set('aria-owns', this.calendarPaneId);
$mdTheming($element);
$mdTheming(angular.element(this.calendarPane));
var self = this;
$scope.$on('$destroy', function() {
self.detachCalendarPane();
});
if ($attrs.mdIsOpen) {
$scope.$watch('ctrl.isOpen', function(shouldBeOpen) {
if (shouldBeOpen) {
self.openCalendarPane({
target: self.inputElement
});
} else {
self.closeCalendarPane();
}
});
}
// For AngularJS 1.4 and older, where there are no lifecycle hooks but bindings are
// pre-assigned, manually call the $onInit hook.
if (angular.version.major === 1 && angular.version.minor <= 4) {
this.$onInit();
}
}