diff --git a/.gitignore b/.gitignore index b43aa595..6dc61600 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ node_modules bower_components /.project +.idea/ diff --git a/dist/mdPickers.css b/dist/mdPickers.css index ab5eb06a..46455750 100644 --- a/dist/mdPickers.css +++ b/dist/mdPickers.css @@ -72,6 +72,160 @@ -webkit-animation-name: mdp-animation-bounce; animation-name: mdp-animation-bounce; } +.mdp-clock { + width: 200px; + height: 200px; + border-radius: 50%; + cursor: pointer; + padding: 24px; + background: #ededed; +} +.mdp-clock .md-button { + box-shadow: none !important; + background-color: transparent; + display: block; + position: absolute; + min-height: 32px; + width: 32px; + height: 32px; + font-size: 12px; + line-height: 32px; + margin: 0; + padding: 0; + -webkit-transform: translate(-50%, -50%); + transform: translate(-50%, -50%); +} +.mdp-clock .mdp-clock-container { + width: 100%; + height: 100%; + position: relative; + display: block; +} +.mdp-clock .mdp-pointer { + min-height: 0px; + width: 1px; + height: 50%; + position: absolute; + left: 0; + right: 0; + bottom: 0; + margin: 0 auto; + -webkit-transform-origin: top center; + transform-origin: top center; + z-index: 0; + pointer-events: none; +} +.mdp-clock .mdp-clock-center { + min-height: 0px; + height: 6px; + width: 6px; + position: absolute; + left: 0; + right: 0; + top: 0; + bottom: 0; + margin: auto; + border-radius: 50%; +} +.mdp-clock .md-button.mdp-clock-selected { + position: absolute; + border-radius: 50%; + width: 8px; + height: 8px; + bottom: -8px; + left: 0px; + min-width: 0; + min-height: 0; + pointer-events: none; +} +.mdp-timepicker .mdp-clock-switch-container { + padding: 20px; + width: 309px; +} +.mdp-timepicker .mdp-timepicker-time { + padding: 15px; +} +.mdp-timepicker .mdp-timepicker-selected-time { + font-size: 3rem; +} +.mdp-timepicker:not(.portrait) .mdp-timepicker-time { + width: 138px; +} +.mdp-timepicker.portrait .mdp-timepicker-selected-time { + font-size: 4rem; + margin-right: 1.5rem; +} +mdp-time-picker md-input-container.md-has-icon { + padding-left: 40px; +} +mdp-time-picker .md-button.md-icon-button { + margin: 18px 0 0 0; +} +.mdp-timepicker-selected-time > span, +.mdp-timepicker-selected-ampm > span { + outline: 0; + opacity: 0.6; +} +.mdp-timepicker-selected-time > span:not(.active), +.mdp-timepicker-selected-ampm > span:not(.active) { + cursor: pointer; +} +.mdp-timepicker-selected-time > span.active, +.mdp-timepicker-selected-ampm > span.active { + opacity: 1; +} +.mdp-clock-deg0 { + top: 0%; + left: 50%; +} +.mdp-clock-deg30 { + top: 6.69872981%; + left: 75%; +} +.mdp-clock-deg60 { + top: 25%; + left: 93.30127019%; +} +.mdp-clock-deg90 { + top: 50%; + left: 100%; +} +.mdp-clock-deg120 { + top: 75%; + left: 93.30127019%; +} +.mdp-clock-deg150 { + top: 93.30127019%; + left: 75%; +} +.mdp-clock-deg180 { + top: 100%; + left: 50%; +} +.mdp-clock-deg210 { + top: 93.30127019%; + left: 25%; +} +.mdp-clock-deg240 { + top: 75%; + left: 6.69872981%; +} +.mdp-clock-deg270 { + top: 50%; + left: 0%; +} +.mdp-clock-deg300 { + top: 25%; + left: 6.69872981%; +} +.mdp-clock-deg330 { + top: 6.69872981%; + left: 25%; +} +.mdp-clock-deg360 { + top: 0%; + left: 50%; +} .mdp-datepicker { max-height: initial; min-width: 234px; @@ -264,157 +418,3 @@ mdp-calendar { .mdp-calendar-days .mdp-day-placeholder { margin: 0; } -.mdp-clock { - width: 200px; - height: 200px; - border-radius: 50%; - cursor: pointer; - padding: 24px; - background: #ededed; -} -.mdp-clock .md-button { - box-shadow: none !important; - background-color: transparent; - display: block; - position: absolute; - min-height: 32px; - width: 32px; - height: 32px; - font-size: 12px; - line-height: 32px; - margin: 0; - padding: 0; - -webkit-transform: translate(-50%, -50%); - transform: translate(-50%, -50%); -} -.mdp-clock .mdp-clock-container { - width: 100%; - height: 100%; - position: relative; - display: block; -} -.mdp-clock .mdp-pointer { - min-height: 0px; - width: 1px; - height: 50%; - position: absolute; - left: 0; - right: 0; - bottom: 0; - margin: 0 auto; - -webkit-transform-origin: top center; - transform-origin: top center; - z-index: 0; - pointer-events: none; -} -.mdp-clock .mdp-clock-center { - min-height: 0px; - height: 6px; - width: 6px; - position: absolute; - left: 0; - right: 0; - top: 0; - bottom: 0; - margin: auto; - border-radius: 50%; -} -.mdp-clock .md-button.mdp-clock-selected { - position: absolute; - border-radius: 50%; - width: 8px; - height: 8px; - bottom: -8px; - left: 0px; - min-width: 0; - min-height: 0; - pointer-events: none; -} -.mdp-timepicker .mdp-clock-switch-container { - padding: 20px; - width: 309px; -} -.mdp-timepicker .mdp-timepicker-time { - padding: 15px; -} -.mdp-timepicker .mdp-timepicker-selected-time { - font-size: 3rem; -} -.mdp-timepicker:not(.portrait) .mdp-timepicker-time { - width: 138px; -} -.mdp-timepicker.portrait .mdp-timepicker-selected-time { - font-size: 4rem; - margin-right: 1.5rem; -} -mdp-time-picker md-input-container.md-has-icon { - padding-left: 40px; -} -mdp-time-picker .md-button.md-icon-button { - margin: 18px 0 0 0; -} -.mdp-timepicker-selected-time > span, -.mdp-timepicker-selected-ampm > span { - outline: 0; - opacity: 0.6; -} -.mdp-timepicker-selected-time > span:not(.active), -.mdp-timepicker-selected-ampm > span:not(.active) { - cursor: pointer; -} -.mdp-timepicker-selected-time > span.active, -.mdp-timepicker-selected-ampm > span.active { - opacity: 1; -} -.mdp-clock-deg0 { - top: 0%; - left: 50%; -} -.mdp-clock-deg30 { - top: 6.69872981%; - left: 75%; -} -.mdp-clock-deg60 { - top: 25%; - left: 93.30127019%; -} -.mdp-clock-deg90 { - top: 50%; - left: 100%; -} -.mdp-clock-deg120 { - top: 75%; - left: 93.30127019%; -} -.mdp-clock-deg150 { - top: 93.30127019%; - left: 75%; -} -.mdp-clock-deg180 { - top: 100%; - left: 50%; -} -.mdp-clock-deg210 { - top: 93.30127019%; - left: 25%; -} -.mdp-clock-deg240 { - top: 75%; - left: 6.69872981%; -} -.mdp-clock-deg270 { - top: 50%; - left: 0%; -} -.mdp-clock-deg300 { - top: 25%; - left: 6.69872981%; -} -.mdp-clock-deg330 { - top: 6.69872981%; - left: 25%; -} -.mdp-clock-deg360 { - top: 0%; - left: 50%; -} diff --git a/dist/mdPickers.js b/dist/mdPickers.js index 372c76bb..01e2788e 100644 --- a/dist/mdPickers.js +++ b/dist/mdPickers.js @@ -61,108 +61,189 @@ module.directive("ngMessage", ["$mdUtil", function($mdUtil) { }]); /* global moment, angular */ -function DatePickerCtrl($scope, $mdDialog, $mdMedia, $timeout, currentDate, options) { - var self = this; - - this.date = moment(currentDate); - this.minDate = options.minDate && moment(options.minDate).isValid() ? moment(options.minDate) : null; - this.maxDate = options.maxDate && moment(options.maxDate).isValid() ? moment(options.maxDate) : null; - this.displayFormat = options.displayFormat || "ddd, MMM DD"; - this.dateFilter = angular.isFunction(options.dateFilter) ? options.dateFilter : null; - this.selectingYear = false; +function TimePickerCtrl($scope, $mdDialog, time, autoSwitch, $mdMedia) { + var self = this; + this.VIEW_HOURS = 1; + this.VIEW_MINUTES = 2; + this.currentView = this.VIEW_HOURS; + this.time = moment(time); + this.autoSwitch = !!autoSwitch; - // validate min and max date - if (this.minDate && this.maxDate) { - if (this.maxDate.isBefore(this.minDate)) { - this.maxDate = moment(this.minDate).add(1, 'days'); - } - } - - if (this.date) { - // check min date - if (this.minDate && this.date.isBefore(this.minDate)) { - this.date = moment(this.minDate); - } - - // check max date - if (this.maxDate && this.date.isAfter(this.maxDate)) { - this.date = moment(this.maxDate); - } - } + this.clockHours = parseInt(this.time.format("h")); + this.clockMinutes = parseInt(this.time.minutes()); + + $scope.$mdMedia = $mdMedia; - this.yearItems = { - currentIndex_: 0, - PAGE_SIZE: 5, - START: (self.minDate ? self.minDate.year() : 1900), - END: (self.maxDate ? self.maxDate.year() : 0), - getItemAtIndex: function(index) { - if(this.currentIndex_ < index) - this.currentIndex_ = index; - - return this.START + index; - }, - getLength: function() { - return Math.min( - this.currentIndex_ + Math.floor(this.PAGE_SIZE / 2), - Math.abs(this.START - this.END) + 1 - ); - } - }; - - $scope.$mdMedia = $mdMedia; - $scope.year = this.date.year(); - - this.selectYear = function(year) { - self.date.year(year); - $scope.year = year; - self.selectingYear = false; - self.animate(); - }; + this.switchView = function() { + self.currentView = self.currentView == self.VIEW_HOURS ? self.VIEW_MINUTES : self.VIEW_HOURS; + }; - this.showYear = function() { - self.yearTopIndex = (self.date.year() - self.yearItems.START) + Math.floor(self.yearItems.PAGE_SIZE / 2); - self.yearItems.currentIndex_ = (self.date.year() - self.yearItems.START) + 1; - self.selectingYear = true; - }; + this.setAM = function() { + if(self.time.hours() >= 12) + self.time.hour(self.time.hour() - 12); + }; + + this.setPM = function() { + if(self.time.hours() < 12) + self.time.hour(self.time.hour() + 12); + }; - this.showCalendar = function() { - self.selectingYear = false; - }; - this.cancel = function() { $mdDialog.cancel(); }; this.confirm = function() { - var date = this.date; - - if (this.minDate && this.date.isBefore(this.minDate)) { - date = moment(this.minDate); - } - - if (this.maxDate && this.date.isAfter(this.maxDate)) { - date = moment(this.maxDate); - } - - $mdDialog.hide(date.toDate()); + $mdDialog.hide(this.time.toDate()); }; +} + +function ClockCtrl($scope) { + var TYPE_HOURS = "hours"; + var TYPE_MINUTES = "minutes"; + var self = this; - this.animate = function() { - self.animating = true; - $timeout(angular.noop).then(function() { - self.animating = false; - }) + this.STEP_DEG = 360 / 12; + this.steps = []; + + this.CLOCK_TYPES = { + "hours": { + range: 12, + }, + "minutes": { + range: 60, + } + } + + this.getPointerStyle = function() { + var divider = 1; + switch(self.type) { + case TYPE_HOURS: + divider = 12; + break; + case TYPE_MINUTES: + divider = 60; + break; + } + var degrees = Math.round(self.selected * (360 / divider)) - 180; + return { + "-webkit-transform": "rotate(" + degrees + "deg)", + "-ms-transform": "rotate(" + degrees + "deg)", + "transform": "rotate(" + degrees + "deg)" + } }; + + this.setTimeByDeg = function(deg) { + deg = deg >= 360 ? 0 : deg; + var divider = 0; + switch(self.type) { + case TYPE_HOURS: + divider = 12; + break; + case TYPE_MINUTES: + divider = 60; + break; + } + + self.setTime( + Math.round(divider / 360 * deg) + ); + }; + + this.setTime = function(time, type) { + this.selected = time; + + switch(self.type) { + case TYPE_HOURS: + if(self.time.format("A") == "PM") time += 12; + this.time.hours(time); + break; + case TYPE_MINUTES: + if(time > 59) time -= 60; + this.time.minutes(time); + break; + } + + }; + + this.init = function() { + self.type = self.type || "hours"; + switch(self.type) { + case TYPE_HOURS: + for(var i = 1; i <= 12; i++) + self.steps.push(i); + self.selected = self.time.hours() || 0; + if(self.selected > 12) self.selected -= 12; + + break; + case TYPE_MINUTES: + for(var i = 5; i <= 55; i+=5) + self.steps.push(i); + self.steps.push(0); + self.selected = self.time.minutes() || 0; + + break; + } + }; + + this.init(); } -module.provider("$mdpDatePicker", function() { +module.directive("mdpClock", ["$animate", "$timeout", function($animate, $timeout) { + return { + restrict: 'E', + bindToController: { + 'type': '@?', + 'time': '=', + 'autoSwitch': '=?' + }, + replace: true, + template: '
' + + '
' + + '' + + '' + + '' + + '' + + '{{ step }}' + + '
' + + '
', + controller: ["$scope", ClockCtrl], + controllerAs: "clock", + link: function(scope, element, attrs, ctrl) { + var pointer = angular.element(element[0].querySelector(".mdp-pointer")), + timepickerCtrl = scope.$parent.timepicker; + + var onEvent = function(event) { + var containerCoords = event.currentTarget.getClientRects()[0]; + var x = ((event.currentTarget.offsetWidth / 2) - (event.pageX - containerCoords.left)), + y = ((event.pageY - containerCoords.top) - (event.currentTarget.offsetHeight / 2)); + + var deg = Math.round((Math.atan2(x, y) * (180 / Math.PI))); + $timeout(function() { + ctrl.setTimeByDeg(deg + 180); + if(ctrl.autoSwitch && ["mouseup", "click"].indexOf(event.type) !== -1 && timepickerCtrl) timepickerCtrl.switchView(); + }); + }; + + element.on("mousedown", function() { + element.on("mousemove", onEvent); + }); + + element.on("mouseup", function(e) { + element.off("mousemove"); + }); + + element.on("click", onEvent); + scope.$on("$destroy", function() { + element.off("click", onEvent); + element.off("mousemove", onEvent); + }); + } + } +}]); + +module.provider("$mdpTimePicker", function() { var LABEL_OK = "OK", - LABEL_CANCEL = "Cancel", - DISPLAY_FORMAT = "ddd, MMM DD"; - - this.setDisplayFormat = function(format) { - DISPLAY_FORMAT = format; - }; + LABEL_CANCEL = "Cancel"; this.setOKButtonLabel = function(label) { LABEL_OK = label; @@ -173,215 +254,54 @@ module.provider("$mdpDatePicker", function() { }; this.$get = ["$mdDialog", function($mdDialog) { - var datePicker = function(currentDate, options) { - if (!angular.isDate(currentDate)) currentDate = Date.now(); + var timePicker = function(time, options) { + if(!angular.isDate(time)) time = Date.now(); if (!angular.isObject(options)) options = {}; - - options.displayFormat = DISPLAY_FORMAT; return $mdDialog.show({ - controller: ['$scope', '$mdDialog', '$mdMedia', '$timeout', 'currentDate', 'options', DatePickerCtrl], - controllerAs: 'datepicker', + controller: ['$scope', '$mdDialog', 'time', 'autoSwitch', '$mdMedia', TimePickerCtrl], + controllerAs: 'timepicker', clickOutsideToClose: true, - template: '' + - '' + - '
' + - '' + - '{{ datepicker.date.format(\'YYYY\') }}' + - '{{ datepicker.date.format(datepicker.displayFormat) }} ' + - '' + - '
' + - '
' + - '
' + - '' + - '
' + - '{{ item }}' + - '
' + - '
' + + template: '' + + '' + + '' + + '
' + + '{{ timepicker.time.format("h") }}:' + + '{{ timepicker.time.format("mm") }}' + '
' + - '' + + '
' + + 'AM' + + 'PM' + + '
' + + '
' + + '
' + + '
' + + '' + + '' + + '
' + + '' + - '' + - '' + LABEL_CANCEL + '' + - '' + LABEL_OK + '' + + '' + + '' + LABEL_CANCEL + '' + + '' + LABEL_OK + '' + '' + '
' + '
' + - '
', - targetEvent: options.targetEvent, - locals: { - currentDate: currentDate, - options: options - }, - skipHide: true - }); - }; - - return datePicker; - }]; -}); - -function CalendarCtrl($scope) { - var self = this; - this.dow = moment.localeData().firstDayOfWeek(); - - this.weekDays = [].concat( - moment.weekdaysMin().slice( - this.dow - ), - moment.weekdaysMin().slice( - 0, - this.dow - ) - ); - - this.daysInMonth = []; - - this.getDaysInMonth = function() { - var days = self.date.daysInMonth(), - firstDay = moment(self.date).date(1).day() - this.dow; - - if(firstDay < 0) firstDay = this.weekDays.length - 1; - - - var arr = []; - for(var i = 1; i <= (firstDay + days); i++) { - var day = null; - if(i > firstDay) { - day = { - value: (i - firstDay), - enabled: self.isDayEnabled(moment(self.date).date(i - firstDay).toDate()) - }; - } - arr.push(day); - } - - return arr; - }; - - this.isDayEnabled = function(day) { - return (!this.minDate || this.minDate <= day) && - (!this.maxDate || this.maxDate >= day) && - (!self.dateFilter || !self.dateFilter(day)); - }; - - this.selectDate = function(dom) { - self.date.date(dom); - }; - - this.nextMonth = function() { - self.date.add(1, 'months'); - }; - - this.prevMonth = function() { - self.date.subtract(1, 'months'); - }; - - this.updateDaysInMonth = function() { - self.daysInMonth = self.getDaysInMonth(); - }; - - $scope.$watch(function() { return self.date.unix() }, function(newValue, oldValue) { - if(newValue && newValue !== oldValue) - self.updateDaysInMonth(); - }) - - self.updateDaysInMonth(); -} - -module.directive("mdpCalendar", ["$animate", function($animate) { - return { - restrict: 'E', - bindToController: { - "date": "=", - "minDate": "=", - "maxDate": "=", - "dateFilter": "=" - }, - template: '
' + - '
' + - '' + - '
{{ calendar.date.format("MMMM YYYY") }}
' + - '' + - '
' + - '
' + - '
{{ d }}
' + - '
' + - '
' + - '
' + - '{{ day.value }}' + - '
' + - '
' + - '
' + - '
', - controller: ["$scope", CalendarCtrl], - controllerAs: "calendar", - link: function(scope, element, attrs, ctrl) { - var animElements = [ - element[0].querySelector(".mdp-calendar-week-days"), - element[0].querySelector('.mdp-calendar-days'), - element[0].querySelector('.mdp-calendar-monthyear') - ].map(function(a) { - return angular.element(a); - }); - - scope.$watch(function() { return ctrl.date.format("YYYYMM") }, function(newValue, oldValue) { - var direction = null; - - if(newValue > oldValue) - direction = "mdp-animate-next"; - else if(newValue < oldValue) - direction = "mdp-animate-prev"; - - if(direction) { - for(var i in animElements) { - animElements[i].addClass(direction); - $animate.removeClass(animElements[i], direction); - } - } + '', + targetEvent: options.targetEvent, + locals: { + time: time, + autoSwitch: options.autoSwitch + }, + skipHide: true }); - } - } -}]); - -function formatValidator(value, format) { - return !value || angular.isDate(value) || moment(value, format, true).isValid(); -} - -function minDateValidator(value, format, minDate) { - var minDate = moment(minDate, "YYYY-MM-DD", true); - var date = angular.isDate(value) ? moment(value) : moment(value, format, true); - - return !value || - angular.isDate(value) || - !minDate.isValid() || - date.isSameOrAfter(minDate); -} - -function maxDateValidator(value, format, maxDate) { - var maxDate = moment(maxDate, "YYYY-MM-DD", true); - var date = angular.isDate(value) ? moment(value) : moment(value, format, true); + }; - return !value || - angular.isDate(value) || - !maxDate.isValid() || - date.isSameOrBefore(maxDate); -} - -function filterValidator(value, format, filter) { - var date = angular.isDate(value) ? moment(value) : moment(value, format, true); - - return !value || - angular.isDate(value) || - !angular.isFunction(filter) || - !filter(date); -} - -function requiredValidator(value, ngModel) { - return value -} + return timePicker; + }]; +}); -module.directive("mdpDatePicker", ["$mdpDatePicker", "$timeout", function($mdpDatePicker, $timeout) { +module.directive("mdpTimePicker", ["$mdpTimePicker", "$timeout", function($mdpTimePicker, $timeout) { return { restrict: 'E', require: 'ngModel', @@ -392,8 +312,8 @@ module.directive("mdpDatePicker", ["$mdpDatePicker", "$timeout", function($mdpDa openOnClick = angular.isDefined(attrs.mdpOpenOnClick) ? true : false; return '
' + - '' + - '' + + '' + + '' + '' + '' + '' + @@ -401,169 +321,128 @@ module.directive("mdpDatePicker", ["$mdpDatePicker", "$timeout", function($mdpDa '
'; }, scope: { - "minDate": "=mdpMinDate", - "maxDate": "=mdpMaxDate", - "dateFilter": "=mdpDateFilter", - "dateFormat": "@mdpFormat", + "timeFormat": "@mdpFormat", "placeholder": "@mdpPlaceholder", - "noFloat": "=mdpNoFloat", - "openOnClick": "=mdpOpenOnClick", + "autoSwitch": "=?mdpAutoSwitch", "disabled": "=?mdpDisabled" }, - link: { - pre: function(scope, element, attrs, ngModel, $transclude) { - - }, - post: function(scope, element, attrs, ngModel, $transclude) { - var inputElement = angular.element(element[0].querySelector('input')), - inputContainer = angular.element(element[0].querySelector('md-input-container')), - inputContainerCtrl = inputContainer.controller("mdInputContainer"); - - $transclude(function(clone) { - inputContainer.append(clone); - }); - - var messages = angular.element(inputContainer[0].querySelector("[ng-messages]")); - - scope.type = scope.dateFormat ? "text" : "date" - scope.dateFormat = scope.dateFormat || "YYYY-MM-DD"; - scope.model = ngModel; - - scope.isError = function() { - return !ngModel.$pristine && !!ngModel.$invalid; - }; - - // update input element if model has changed - ngModel.$formatters.unshift(function(value) { - var date = angular.isDate(value) && moment(value); - if(date && date.isValid()) - updateInputElement(date.format(scope.dateFormat)); - else - updateInputElement(null); - }); - - ngModel.$validators.format = function(modelValue, viewValue) { - return formatValidator(viewValue, scope.dateFormat); - }; - - ngModel.$validators.minDate = function(modelValue, viewValue) { - return minDateValidator(viewValue, scope.dateFormat, scope.minDate); - }; - - ngModel.$validators.maxDate = function(modelValue, viewValue) { - return maxDateValidator(viewValue, scope.dateFormat, scope.maxDate); - }; - - ngModel.$validators.filter = function(modelValue, viewValue) { - return filterValidator(viewValue, scope.dateFormat, scope.dateFilter); - }; - - ngModel.$validators.required = function(modelValue, viewValue) { - return angular.isUndefined(attrs.required) || !ngModel.$isEmpty(modelValue) || !ngModel.$isEmpty(viewValue); - }; - - ngModel.$parsers.unshift(function(value) { - var parsed = moment(value, scope.dateFormat, true); - if(parsed.isValid()) { - if(angular.isDate(ngModel.$modelValue)) { - var originalModel = moment(ngModel.$modelValue); - originalModel.year(parsed.year()); - originalModel.month(parsed.month()); - originalModel.date(parsed.date()); - - parsed = originalModel; - } - return parsed.toDate(); - } else - return null; - }); + link: function(scope, element, attrs, ngModel, $transclude) { + var inputElement = angular.element(element[0].querySelector('input')), + inputContainer = angular.element(element[0].querySelector('md-input-container')), + inputContainerCtrl = inputContainer.controller("mdInputContainer"); - // update input element value - function updateInputElement(value) { + $transclude(function(clone) { + inputContainer.append(clone); + }); + + var messages = angular.element(inputContainer[0].querySelector("[ng-messages]")); + + scope.type = scope.timeFormat ? "text" : "time" + scope.timeFormat = scope.timeFormat || "HH:mm"; + scope.autoSwitch = scope.autoSwitch || false; + + scope.$watch(function() { return ngModel.$error }, function(newValue, oldValue) { + inputContainerCtrl.setInvalid(!ngModel.$pristine && !!Object.keys(ngModel.$error).length); + }, true); + + // update input element if model has changed + ngModel.$formatters.unshift(function(value) { + var time = angular.isDate(value) && moment(value); + if(time && time.isValid()) + updateInputElement(time.format(scope.timeFormat)); + else + updateInputElement(null); + }); + + ngModel.$validators.format = function(modelValue, viewValue) { + return !viewValue || angular.isDate(viewValue) || moment(viewValue, scope.timeFormat, true).isValid(); + }; + + ngModel.$validators.required = function(modelValue, viewValue) { + return angular.isUndefined(attrs.required) || !ngModel.$isEmpty(modelValue) || !ngModel.$isEmpty(viewValue); + }; + + ngModel.$parsers.unshift(function(value) { + var parsed = moment(value, scope.timeFormat, true); + if(parsed.isValid()) { + if(angular.isDate(ngModel.$modelValue)) { + var originalModel = moment(ngModel.$modelValue); + originalModel.minutes(parsed.minutes()); + originalModel.hours(parsed.hours()); + originalModel.seconds(parsed.seconds()); + + parsed = originalModel; + } + return parsed.toDate(); + } else + return null; + }); + + // update input element value + function updateInputElement(value) { + if (inputElement[0].value !== value) { inputElement[0].value = value; - inputContainerCtrl.setHasValue(!ngModel.$isEmpty(value)); } - - function updateDate(date) { - var value = moment(date, angular.isDate(date) ? null : scope.dateFormat, true), - strValue = value.format(scope.dateFormat); - - if(value.isValid()) { - updateInputElement(strValue); - ngModel.$setViewValue(strValue); - } else { - updateInputElement(date); - ngModel.$setViewValue(date); - } - - if(!ngModel.$pristine && - messages.hasClass("md-auto-hide") && - inputContainer.hasClass("md-input-invalid")) messages.removeClass("md-auto-hide"); - - ngModel.$render(); + inputContainerCtrl.setHasValue(!ngModel.$isEmpty(value)); + } + + function updateTime(time) { + var value = moment(time, angular.isDate(time) ? null : scope.timeFormat, true), + strValue = value.format(scope.timeFormat); + + if(value.isValid()) { + updateInputElement(strValue); + ngModel.$setViewValue(strValue); + } else { + updateInputElement(time); + ngModel.$setViewValue(time); } - - scope.showPicker = function(ev) { - $mdpDatePicker(ngModel.$modelValue, { - minDate: scope.minDate, - maxDate: scope.maxDate, - dateFilter: scope.dateFilter, - targetEvent: ev - }).then(updateDate); - }; - function onInputElementEvents(event) { - if(event.target.value !== ngModel.$viewVaue) - updateDate(event.target.value); - } + if(!ngModel.$pristine && + messages.hasClass("md-auto-hide") && + inputContainer.hasClass("md-input-invalid")) messages.removeClass("md-auto-hide"); - inputElement.on("reset input blur", onInputElementEvents); + ngModel.$render(); + } - scope.$on("$destroy", function() { - inputElement.off("reset input blur", onInputElementEvents); + scope.showPicker = function(ev) { + $mdpTimePicker(ngModel.$modelValue, { + targetEvent: ev, + autoSwitch: scope.autoSwitch + }).then(function(time) { + updateTime(time, true); }); + }; + + function onInputElementEvents(event) { + if(event.target.value !== ngModel.$viewVaue) + updateTime(event.target.value); } + + inputElement.on("reset input blur", onInputElementEvents); + + scope.$on("$destroy", function() { + inputElement.off("reset input blur", onInputElementEvents); + }) } }; }]); - -module.directive("mdpDatePicker", ["$mdpDatePicker", "$timeout", function($mdpDatePicker, $timeout) { +module.directive("mdpTimePicker", ["$mdpTimePicker", "$timeout", function($mdpTimePicker, $timeout) { return { restrict: 'A', require: 'ngModel', scope: { - "minDate": "@min", - "maxDate": "@max", - "dateFilter": "=mdpDateFilter", - "dateFormat": "@mdpFormat", + "timeFormat": "@mdpFormat", + "autoSwitch": "=?mdpAutoSwitch", }, link: function(scope, element, attrs, ngModel, $transclude) { - scope.dateFormat = scope.dateFormat || "YYYY-MM-DD"; - - ngModel.$validators.format = function(modelValue, viewValue) { - return formatValidator(viewValue, scope.format); - }; - - ngModel.$validators.minDate = function(modelValue, viewValue) { - return minDateValidator(viewValue, scope.format, scope.minDate); - }; - - ngModel.$validators.maxDate = function(modelValue, viewValue) { - return maxDateValidator(viewValue, scope.format, scope.maxDate); - }; - - ngModel.$validators.filter = function(modelValue, viewValue) { - return filterValidator(viewValue, scope.format, scope.dateFilter); - }; - + scope.format = scope.format || "HH:mm"; function showPicker(ev) { - $mdpDatePicker(ngModel.$modelValue, { - minDate: scope.minDate, - maxDate: scope.maxDate, - dateFilter: scope.dateFilter, - targetEvent: ev - }).then(function(time) { + $mdpTimePicker(ngModel.$modelValue, { + targetEvent: ev, + autoSwitch: scope.autoSwitch + }).then(function(time) { ngModel.$setViewValue(moment(time).format(scope.format)); ngModel.$render(); }); @@ -577,191 +456,111 @@ module.directive("mdpDatePicker", ["$mdpDatePicker", "$timeout", function($mdpDa } } }]); -/* global moment, angular */ - -function TimePickerCtrl($scope, $mdDialog, time, autoSwitch, $mdMedia) { - var self = this; - this.VIEW_HOURS = 1; - this.VIEW_MINUTES = 2; - this.currentView = this.VIEW_HOURS; - this.time = moment(time); - this.autoSwitch = !!autoSwitch; - - this.clockHours = parseInt(this.time.format("h")); - this.clockMinutes = parseInt(this.time.minutes()); - - $scope.$mdMedia = $mdMedia; - - this.switchView = function() { - self.currentView = self.currentView == self.VIEW_HOURS ? self.VIEW_MINUTES : self.VIEW_HOURS; - }; - - this.setAM = function() { - if(self.time.hours() >= 12) - self.time.hour(self.time.hour() - 12); - }; - - this.setPM = function() { - if(self.time.hours() < 12) - self.time.hour(self.time.hour() + 12); - }; - - this.cancel = function() { - $mdDialog.cancel(); - }; - this.confirm = function() { - $mdDialog.hide(this.time.toDate()); - }; -} +/* global moment, angular */ -function ClockCtrl($scope) { - var TYPE_HOURS = "hours"; - var TYPE_MINUTES = "minutes"; +function DatePickerCtrl($scope, $mdDialog, $mdMedia, $timeout, currentDate, options) { var self = this; + + this.date = moment(currentDate); + this.minDate = options.minDate && moment(options.minDate).isValid() ? moment(options.minDate) : null; + this.maxDate = options.maxDate && moment(options.maxDate).isValid() ? moment(options.maxDate) : null; + this.displayFormat = options.displayFormat || "ddd, MMM DD"; + this.dateFilter = angular.isFunction(options.dateFilter) ? options.dateFilter : null; + this.selectingYear = false; - this.STEP_DEG = 360 / 12; - this.steps = []; - - this.CLOCK_TYPES = { - "hours": { - range: 12, + // validate min and max date + if (this.minDate && this.maxDate) { + if (this.maxDate.isBefore(this.minDate)) { + this.maxDate = moment(this.minDate).add(1, 'days'); + } + } + + if (this.date) { + // check min date + if (this.minDate && this.date.isBefore(this.minDate)) { + this.date = moment(this.minDate); + } + + // check max date + if (this.maxDate && this.date.isAfter(this.maxDate)) { + this.date = moment(this.maxDate); + } + } + + this.yearItems = { + currentIndex_: 0, + PAGE_SIZE: 5, + START: (self.minDate ? self.minDate.year() : 1900), + END: (self.maxDate ? self.maxDate.year() : 0), + getItemAtIndex: function(index) { + if(this.currentIndex_ < index) + this.currentIndex_ = index; + + return this.START + index; }, - "minutes": { - range: 60, - } - } - - this.getPointerStyle = function() { - var divider = 1; - switch(self.type) { - case TYPE_HOURS: - divider = 12; - break; - case TYPE_MINUTES: - divider = 60; - break; - } - var degrees = Math.round(self.selected * (360 / divider)) - 180; - return { - "-webkit-transform": "rotate(" + degrees + "deg)", - "-ms-transform": "rotate(" + degrees + "deg)", - "transform": "rotate(" + degrees + "deg)" - } - }; - - this.setTimeByDeg = function(deg) { - deg = deg >= 360 ? 0 : deg; - var divider = 0; - switch(self.type) { - case TYPE_HOURS: - divider = 12; - break; - case TYPE_MINUTES: - divider = 60; - break; - } - - self.setTime( - Math.round(divider / 360 * deg) - ); - }; - - this.setTime = function(time, type) { - this.selected = time; - - switch(self.type) { - case TYPE_HOURS: - if(self.time.format("A") == "PM") time += 12; - this.time.hours(time); - break; - case TYPE_MINUTES: - if(time > 59) time -= 60; - this.time.minutes(time); - break; - } - - }; - - this.init = function() { - self.type = self.type || "hours"; - switch(self.type) { - case TYPE_HOURS: - for(var i = 1; i <= 12; i++) - self.steps.push(i); - self.selected = self.time.hours() || 0; - if(self.selected > 12) self.selected -= 12; - - break; - case TYPE_MINUTES: - for(var i = 5; i <= 55; i+=5) - self.steps.push(i); - self.steps.push(0); - self.selected = self.time.minutes() || 0; - - break; + getLength: function() { + return Math.min( + this.currentIndex_ + Math.floor(this.PAGE_SIZE / 2), + Math.abs(this.START - this.END) + 1 + ); } }; - - this.init(); -} - -module.directive("mdpClock", ["$animate", "$timeout", function($animate, $timeout) { - return { - restrict: 'E', - bindToController: { - 'type': '@?', - 'time': '=', - 'autoSwitch': '=?' - }, - replace: true, - template: '
' + - '
' + - '' + - '' + - '' + - '' + - '{{ step }}' + - '
' + - '
', - controller: ["$scope", ClockCtrl], - controllerAs: "clock", - link: function(scope, element, attrs, ctrl) { - var pointer = angular.element(element[0].querySelector(".mdp-pointer")), - timepickerCtrl = scope.$parent.timepicker; - - var onEvent = function(event) { - var containerCoords = event.currentTarget.getClientRects()[0]; - var x = ((event.currentTarget.offsetWidth / 2) - (event.pageX - containerCoords.left)), - y = ((event.pageY - containerCoords.top) - (event.currentTarget.offsetHeight / 2)); - var deg = Math.round((Math.atan2(x, y) * (180 / Math.PI))); - $timeout(function() { - ctrl.setTimeByDeg(deg + 180); - if(ctrl.autoSwitch && ["mouseup", "click"].indexOf(event.type) !== -1 && timepickerCtrl) timepickerCtrl.switchView(); - }); - }; - - element.on("mousedown", function() { - element.on("mousemove", onEvent); - }); - - element.on("mouseup", function(e) { - element.off("mousemove"); - }); - - element.on("click", onEvent); - scope.$on("$destroy", function() { - element.off("click", onEvent); - element.off("mousemove", onEvent); - }); - } - } -}]); + $scope.$mdMedia = $mdMedia; + $scope.year = this.date.year(); -module.provider("$mdpTimePicker", function() { + this.selectYear = function(year) { + self.date.year(year); + $scope.year = year; + self.selectingYear = false; + self.animate(); + }; + + this.showYear = function() { + self.yearTopIndex = (self.date.year() - self.yearItems.START) + Math.floor(self.yearItems.PAGE_SIZE / 2); + self.yearItems.currentIndex_ = (self.date.year() - self.yearItems.START) + 1; + self.selectingYear = true; + }; + + this.showCalendar = function() { + self.selectingYear = false; + }; + + this.cancel = function() { + $mdDialog.cancel(); + }; + + this.confirm = function() { + var date = this.date; + + if (this.minDate && this.date.isBefore(this.minDate)) { + date = moment(this.minDate); + } + + if (this.maxDate && this.date.isAfter(this.maxDate)) { + date = moment(this.maxDate); + } + + $mdDialog.hide(date.toDate()); + }; + + this.animate = function() { + self.animating = true; + $timeout(angular.noop).then(function() { + self.animating = false; + }) + }; +} + +module.provider("$mdpDatePicker", function() { var LABEL_OK = "OK", - LABEL_CANCEL = "Cancel"; + LABEL_CANCEL = "Cancel", + DISPLAY_FORMAT = "ddd, MMM DD"; + + this.setDisplayFormat = function(format) { + DISPLAY_FORMAT = format; + }; this.setOKButtonLabel = function(label) { LABEL_OK = label; @@ -772,54 +571,215 @@ module.provider("$mdpTimePicker", function() { }; this.$get = ["$mdDialog", function($mdDialog) { - var timePicker = function(time, options) { - if(!angular.isDate(time)) time = Date.now(); + var datePicker = function(currentDate, options) { + if (!angular.isDate(currentDate)) currentDate = Date.now(); if (!angular.isObject(options)) options = {}; + + options.displayFormat = DISPLAY_FORMAT; return $mdDialog.show({ - controller: ['$scope', '$mdDialog', 'time', 'autoSwitch', '$mdMedia', TimePickerCtrl], - controllerAs: 'timepicker', + controller: ['$scope', '$mdDialog', '$mdMedia', '$timeout', 'currentDate', 'options', DatePickerCtrl], + controllerAs: 'datepicker', clickOutsideToClose: true, - template: '' + - '' + - '' + - '
' + - '{{ timepicker.time.format("h") }}:' + - '{{ timepicker.time.format("mm") }}' + - '
' + - '
' + - 'AM' + - 'PM' + - '
' + - '
' + - '
' + - '
' + - '' + - '' + + template: '' + + '' + + '
' + + '' + + '{{ datepicker.date.format(\'YYYY\') }}' + + '{{ datepicker.date.format(datepicker.displayFormat) }} ' + + '' + + '
' + + '
' + + '
' + + '' + + '
' + + '{{ item }}' + + '
' + + '
' + '
' + - + '' + '' + - '' + - '' + LABEL_CANCEL + '' + - '' + LABEL_OK + '' + + '' + + '' + LABEL_CANCEL + '' + + '' + LABEL_OK + '' + '' + '
' + '
' + '
', targetEvent: options.targetEvent, locals: { - time: time, - autoSwitch: options.autoSwitch + currentDate: currentDate, + options: options }, skipHide: true }); }; - return timePicker; + return datePicker; }]; }); -module.directive("mdpTimePicker", ["$mdpTimePicker", "$timeout", function($mdpTimePicker, $timeout) { +function CalendarCtrl($scope) { + var self = this; + this.dow = moment.localeData().firstDayOfWeek(); + + this.weekDays = [].concat( + moment.weekdaysMin().slice( + this.dow + ), + moment.weekdaysMin().slice( + 0, + this.dow + ) + ); + + this.daysInMonth = []; + + this.getDaysInMonth = function() { + var days = self.date.daysInMonth(), + firstDay = moment(self.date).date(1).day() - this.dow; + + if(firstDay < 0) firstDay = this.weekDays.length - 1; + + + var arr = []; + for(var i = 1; i <= (firstDay + days); i++) { + var day = null; + if(i > firstDay) { + day = { + value: (i - firstDay), + enabled: self.isDayEnabled(moment(self.date).date(i - firstDay).toDate()) + }; + } + arr.push(day); + } + + return arr; + }; + + this.isDayEnabled = function(day) { + return (!this.minDate || this.minDate <= day) && + (!this.maxDate || this.maxDate >= day) && + (!self.dateFilter || !self.dateFilter(day)); + }; + + this.selectDate = function(dom) { + self.date.date(dom); + }; + + this.nextMonth = function() { + self.date.add(1, 'months'); + }; + + this.prevMonth = function() { + self.date.subtract(1, 'months'); + }; + + this.updateDaysInMonth = function() { + self.daysInMonth = self.getDaysInMonth(); + }; + + $scope.$watch(function() { return self.date.unix() }, function(newValue, oldValue) { + if(newValue && newValue !== oldValue) + self.updateDaysInMonth(); + }) + + self.updateDaysInMonth(); +} + +module.directive("mdpCalendar", ["$animate", function($animate) { + return { + restrict: 'E', + bindToController: { + "date": "=", + "minDate": "=", + "maxDate": "=", + "dateFilter": "=" + }, + template: '
' + + '
' + + '' + + '
{{ calendar.date.format("MMMM YYYY") }}
' + + '' + + '
' + + '
' + + '
{{ d }}
' + + '
' + + '
' + + '
' + + '{{ day.value }}' + + '
' + + '
' + + '
' + + '
', + controller: ["$scope", CalendarCtrl], + controllerAs: "calendar", + link: function(scope, element, attrs, ctrl) { + var animElements = [ + element[0].querySelector(".mdp-calendar-week-days"), + element[0].querySelector('.mdp-calendar-days'), + element[0].querySelector('.mdp-calendar-monthyear') + ].map(function(a) { + return angular.element(a); + }); + + scope.$watch(function() { return ctrl.date.format("YYYYMM") }, function(newValue, oldValue) { + var direction = null; + + if(newValue > oldValue) + direction = "mdp-animate-next"; + else if(newValue < oldValue) + direction = "mdp-animate-prev"; + + if(direction) { + for(var i in animElements) { + animElements[i].addClass(direction); + $animate.removeClass(animElements[i], direction); + } + } + }); + } + } +}]); + +function formatValidator(value, format) { + return !value || angular.isDate(value) || moment(value, format, true).isValid(); +} + +function minDateValidator(value, format, minDate) { + var minDate = moment(minDate, "YYYY-MM-DD", true); + var date = angular.isDate(value) ? moment(value) : moment(value, format, true); + + return !value || + angular.isDate(value) || + !minDate.isValid() || + date.isSameOrAfter(minDate); +} + +function maxDateValidator(value, format, maxDate) { + var maxDate = moment(maxDate, "YYYY-MM-DD", true); + var date = angular.isDate(value) ? moment(value) : moment(value, format, true); + + return !value || + angular.isDate(value) || + !maxDate.isValid() || + date.isSameOrBefore(maxDate); +} + +function filterValidator(value, format, filter) { + var date = angular.isDate(value) ? moment(value) : moment(value, format, true); + + return !value || + angular.isDate(value) || + !angular.isFunction(filter) || + !filter(date); +} + +function requiredValidator(value, ngModel) { + return value +} + +module.directive("mdpDatePicker", ["$mdpDatePicker", "$timeout", function($mdpDatePicker, $timeout) { return { restrict: 'E', require: 'ngModel', @@ -830,8 +790,8 @@ module.directive("mdpTimePicker", ["$mdpTimePicker", "$timeout", function($mdpTi openOnClick = angular.isDefined(attrs.mdpOpenOnClick) ? true : false; return '
' + - '' + - '' + + '' + + '' + '' + '' + '' + @@ -839,126 +799,169 @@ module.directive("mdpTimePicker", ["$mdpTimePicker", "$timeout", function($mdpTi '
'; }, scope: { - "timeFormat": "@mdpFormat", + "minDate": "=mdpMinDate", + "maxDate": "=mdpMaxDate", + "dateFilter": "=mdpDateFilter", + "dateFormat": "@mdpFormat", "placeholder": "@mdpPlaceholder", - "autoSwitch": "=?mdpAutoSwitch", + "noFloat": "=mdpNoFloat", + "openOnClick": "=mdpOpenOnClick", "disabled": "=?mdpDisabled" }, - link: function(scope, element, attrs, ngModel, $transclude) { - var inputElement = angular.element(element[0].querySelector('input')), - inputContainer = angular.element(element[0].querySelector('md-input-container')), - inputContainerCtrl = inputContainer.controller("mdInputContainer"); + link: { + pre: function(scope, element, attrs, ngModel, $transclude) { - $transclude(function(clone) { - inputContainer.append(clone); - }); - - var messages = angular.element(inputContainer[0].querySelector("[ng-messages]")); - - scope.type = scope.timeFormat ? "text" : "time" - scope.timeFormat = scope.timeFormat || "HH:mm"; - scope.autoSwitch = scope.autoSwitch || false; - - scope.$watch(function() { return ngModel.$error }, function(newValue, oldValue) { - inputContainerCtrl.setInvalid(!ngModel.$pristine && !!Object.keys(ngModel.$error).length); - }, true); - - // update input element if model has changed - ngModel.$formatters.unshift(function(value) { - var time = angular.isDate(value) && moment(value); - if(time && time.isValid()) - updateInputElement(time.format(scope.timeFormat)); - else - updateInputElement(null); - }); - - ngModel.$validators.format = function(modelValue, viewValue) { - return !viewValue || angular.isDate(viewValue) || moment(viewValue, scope.timeFormat, true).isValid(); - }; - - ngModel.$validators.required = function(modelValue, viewValue) { - return angular.isUndefined(attrs.required) || !ngModel.$isEmpty(modelValue) || !ngModel.$isEmpty(viewValue); - }; - - ngModel.$parsers.unshift(function(value) { - var parsed = moment(value, scope.timeFormat, true); - if(parsed.isValid()) { - if(angular.isDate(ngModel.$modelValue)) { - var originalModel = moment(ngModel.$modelValue); - originalModel.minutes(parsed.minutes()); - originalModel.hours(parsed.hours()); - originalModel.seconds(parsed.seconds()); - - parsed = originalModel; + }, + post: function(scope, element, attrs, ngModel, $transclude) { + var inputElement = angular.element(element[0].querySelector('input')), + inputContainer = angular.element(element[0].querySelector('md-input-container')), + inputContainerCtrl = inputContainer.controller("mdInputContainer"); + + $transclude(function(clone) { + inputContainer.append(clone); + }); + + var messages = angular.element(inputContainer[0].querySelector("[ng-messages]")); + + scope.type = scope.dateFormat ? "text" : "date" + scope.dateFormat = scope.dateFormat || "YYYY-MM-DD"; + scope.model = ngModel; + + scope.isError = function() { + return !ngModel.$pristine && !!ngModel.$invalid; + }; + + // update input element if model has changed + ngModel.$formatters.unshift(function(value) { + var date = angular.isDate(value) && moment(value); + if(date && date.isValid()) + updateInputElement(date.format(scope.dateFormat)); + else + updateInputElement(null); + }); + + ngModel.$validators.format = function(modelValue, viewValue) { + return formatValidator(viewValue, scope.dateFormat); + }; + + ngModel.$validators.minDate = function(modelValue, viewValue) { + return minDateValidator(viewValue, scope.dateFormat, scope.minDate); + }; + + ngModel.$validators.maxDate = function(modelValue, viewValue) { + return maxDateValidator(viewValue, scope.dateFormat, scope.maxDate); + }; + + ngModel.$validators.filter = function(modelValue, viewValue) { + return filterValidator(viewValue, scope.dateFormat, scope.dateFilter); + }; + + ngModel.$validators.required = function(modelValue, viewValue) { + return angular.isUndefined(attrs.required) || !ngModel.$isEmpty(modelValue) || !ngModel.$isEmpty(viewValue); + }; + + ngModel.$parsers.unshift(function(value) { + var parsed = moment(value, scope.dateFormat, true); + if(parsed.isValid()) { + if(angular.isDate(ngModel.$modelValue)) { + var originalModel = moment(ngModel.$modelValue); + originalModel.year(parsed.year()); + originalModel.month(parsed.month()); + originalModel.date(parsed.date()); + + parsed = originalModel; + } + return parsed.toDate(); + } else + return null; + }); + + // update input element value + function updateInputElement(value) { + inputElement[0].value = value; + inputContainerCtrl.setHasValue(!ngModel.$isEmpty(value)); + } + + function updateDate(date) { + var value = moment(date, angular.isDate(date) ? null : scope.dateFormat, true), + strValue = value.format(scope.dateFormat); + + if(value.isValid()) { + updateInputElement(strValue); + ngModel.$setViewValue(strValue); + } else { + updateInputElement(date); + ngModel.$setViewValue(date); } - return parsed.toDate(); - } else - return null; - }); - - // update input element value - function updateInputElement(value) { - inputElement[0].value = value; - inputContainerCtrl.setHasValue(!ngModel.$isEmpty(value)); - } - - function updateTime(time) { - var value = moment(time, angular.isDate(time) ? null : scope.timeFormat, true), - strValue = value.format(scope.timeFormat); - - if(value.isValid()) { - updateInputElement(strValue); - ngModel.$setViewValue(strValue); - } else { - updateInputElement(time); - ngModel.$setViewValue(time); + + if(!ngModel.$pristine && + messages.hasClass("md-auto-hide") && + inputContainer.hasClass("md-input-invalid")) messages.removeClass("md-auto-hide"); + + ngModel.$render(); } + + scope.showPicker = function(ev) { + $mdpDatePicker(ngModel.$modelValue, { + minDate: scope.minDate, + maxDate: scope.maxDate, + dateFilter: scope.dateFilter, + targetEvent: ev + }).then(updateDate); + }; - if(!ngModel.$pristine && - messages.hasClass("md-auto-hide") && - inputContainer.hasClass("md-input-invalid")) messages.removeClass("md-auto-hide"); + function onInputElementEvents(event) { + if(event.target.value !== ngModel.$viewVaue) + updateDate(event.target.value); + } - ngModel.$render(); - } + inputElement.on("reset input blur", onInputElementEvents); - scope.showPicker = function(ev) { - $mdpTimePicker(ngModel.$modelValue, { - targetEvent: ev, - autoSwitch: scope.autoSwitch - }).then(function(time) { - updateTime(time, true); + scope.$on("$destroy", function() { + inputElement.off("reset input blur", onInputElementEvents); }); - }; - - function onInputElementEvents(event) { - if(event.target.value !== ngModel.$viewVaue) - updateTime(event.target.value); } - - inputElement.on("reset input blur", onInputElementEvents); - - scope.$on("$destroy", function() { - inputElement.off("reset input blur", onInputElementEvents); - }) } }; }]); -module.directive("mdpTimePicker", ["$mdpTimePicker", "$timeout", function($mdpTimePicker, $timeout) { + +module.directive("mdpDatePicker", ["$mdpDatePicker", "$timeout", function($mdpDatePicker, $timeout) { return { restrict: 'A', require: 'ngModel', scope: { - "timeFormat": "@mdpFormat", - "autoSwitch": "=?mdpAutoSwitch", + "minDate": "@min", + "maxDate": "@max", + "dateFilter": "=mdpDateFilter", + "dateFormat": "@mdpFormat", }, link: function(scope, element, attrs, ngModel, $transclude) { - scope.format = scope.format || "HH:mm"; + scope.dateFormat = scope.dateFormat || "YYYY-MM-DD"; + + ngModel.$validators.format = function(modelValue, viewValue) { + return formatValidator(viewValue, scope.format); + }; + + ngModel.$validators.minDate = function(modelValue, viewValue) { + return minDateValidator(viewValue, scope.format, scope.minDate); + }; + + ngModel.$validators.maxDate = function(modelValue, viewValue) { + return maxDateValidator(viewValue, scope.format, scope.maxDate); + }; + + ngModel.$validators.filter = function(modelValue, viewValue) { + return filterValidator(viewValue, scope.format, scope.dateFilter); + }; + function showPicker(ev) { - $mdpTimePicker(ngModel.$modelValue, { - targetEvent: ev, - autoSwitch: scope.autoSwitch - }).then(function(time) { + $mdpDatePicker(ngModel.$modelValue, { + minDate: scope.minDate, + maxDate: scope.maxDate, + dateFilter: scope.dateFilter, + targetEvent: ev + }).then(function(time) { ngModel.$setViewValue(moment(time).format(scope.format)); ngModel.$render(); }); @@ -972,5 +975,4 @@ module.directive("mdpTimePicker", ["$mdpTimePicker", "$timeout", function($mdpTi } } }]); - })(); \ No newline at end of file diff --git a/dist/mdPickers.min.css b/dist/mdPickers.min.css index e9477885..7a866f2d 100644 --- a/dist/mdPickers.min.css +++ b/dist/mdPickers.min.css @@ -1 +1 @@ -.mdp-animate-next,.mdp-animate-next-remove{opacity:0;-webkit-transform:translate3d(50%,0,1px);transform:translate3d(50%,0,1px)}.mdp-animate-next-remove{-webkit-transition:all .5s cubic-bezier(.35,0,.25,1);transition:all .5s cubic-bezier(.35,0,.25,1)}.mdp-animate-next-remove-active{opacity:1;-webkit-transform:translateZ(1px);transform:translateZ(1px)}.mdp-animate-prev,.mdp-animate-prev-remove{opacity:0;-webkit-transform:translate3d(-50%,0,1px);transform:translate3d(-50%,0,1px)}.mdp-animate-prev-remove{-webkit-transition:all .3s cubic-bezier(.35,0,.25,1);transition:all .3s cubic-bezier(.35,0,.25,1)}.mdp-animate-prev-remove-active{opacity:1;-webkit-transform:translateZ(1px);transform:translateZ(1px)}@-webkit-keyframes a{0%{opacity:0;-webkit-transform:scale(.95);transform:scale(.95)}70%{opacity:1;-webkit-transform:scale(1.05);transform:scale(1.05)}to{-webkit-transform:scale(1);transform:scale(1)}}@keyframes a{0%{opacity:0;-webkit-transform:scale(.95);transform:scale(.95)}70%{opacity:1;-webkit-transform:scale(1.05);transform:scale(1.05)}to{-webkit-transform:scale(1);transform:scale(1)}}.mdp-animation-zoom.ng-enter{-webkit-transition:all .3s cubic-bezier(.35,0,.25,1);transition:all .3s cubic-bezier(.35,0,.25,1);-webkit-animation-duration:.3s;animation-duration:.3s;-webkit-animation-name:a;animation-name:a}.mdp-datepicker{max-height:initial;min-width:234px}.mdp-datepicker *{outline:0}.mdp-datepicker .md-actions{width:100%;padding:0 5px}.mdp-calendar-week-days{font-size:.75rem;opacity:.6}.mdp-calendar-week-days>*{width:32px;height:32px;line-height:32px;margin:0 5px;padding:0;min-width:0;min-height:0;box-shadow:none!important;background-color:transparent}.mdp-calendar-days{font-size:1rem;max-width:100%}.mdp-calendar-days .md-button,.mdp-calendar-days .mdp-day-placeholder{width:32px;height:32px;margin:0 5px}.mdp-calendar-days .md-button{cursor:pointer;border-radius:50%;font-size:12px;width:32px;height:32px;line-height:32px;padding:0;min-width:0;min-height:0;box-shadow:none!important;background-color:transparent}.mdp-calendar-days .md-button[disabled]:not(.md-accent){background-color:transparent!important}.mdp-calendar-monthyear{font-size:.8125rem;font-weight:700;line-height:32px;min-height:32px}.mdp-datepicker-date,.mdp-datepicker-day,.mdp-datepicker-dow,.mdp-datepicker-month{font-size:1.8rem;opacity:.6}.mdp-datepicker-date:not(.active),.mdp-datepicker-day:not(.active),.mdp-datepicker-dow:not(.active),.mdp-datepicker-month:not(.active){cursor:pointer}.mdp-datepicker-date.active,.mdp-datepicker-date:hover,.mdp-datepicker-day.active,.mdp-datepicker-day:hover,.mdp-datepicker-dow.active,.mdp-datepicker-dow:hover,.mdp-datepicker-month.active,.mdp-datepicker-month:hover{opacity:1}.mdp-datepicker-year{font-size:.9rem;opacity:.6;padding:0;margin:0}.mdp-datepicker-year:not(.active){cursor:pointer}.mdp-datepicker-year.active,.mdp-datepicker-year:hover{opacity:1}.mdp-datepicker-select-year{height:232px}.mdp-datepicker-select-year .repeated-year{text-align:center}.mdp-datepicker-select-year .repeated-year .md-button{width:100%;margin:0;border-radius:0;padding:0;font-size:1rem;line-height:42px}.mdp-datepicker-select-year .repeated-year .md-button.current{font-size:1.8rem;line-height:42px}.mdp-datepicker-select-year .md-virtual-repeat-container,.mdp-datepicker-select-year .md-virtual-repeat-offsetter,.mdp-datepicker-select-year .md-virtual-repeat-scroller{height:100%;width:100%}mdp-date-picker>md-input-container.md-has-icon{padding-left:40px}mdp-date-picker .md-button.md-icon-button{margin:18px 0 0}.mdp-datepicker:not(.portrait) .mdp-datepicker-select-year{width:309px}.mdp-datepicker:not(.portrait) .mdp-calendar{margin-right:5px;width:294px;margin-left:10px}.mdp-datepicker:not(.portrait) .mdp-datepicker-date-wrapper{width:150px}.mdp-datepicker:not(.portrait) .mdp-datepicker-dow{width:100%;display:block}.mdp-datepicker:not(.portrait) .mdp-calendar-days>*,.mdp-datepicker:not(.portrait) .mdp-calendar-week-days>*{width:42px}.mdp-datepicker .mdp-datepicker-date-wrapper{padding:16px 35px 16px 16px}.mdp-datepicker md-dialog-content{overflow:hidden;padding:0}.mdp-datepicker md-dialog-content .mdp-calendar{width:294px;overflow-x:hidden}.mdp-datepicker.portrait{max-width:234px}.mdp-datepicker.portrait .mdp-calendar{text-align:center;width:100%}.mdp-datepicker.portrait .mdp-datepicker-select-year{height:252px}.mdp-datepicker.portrait md-dialog-content>*{width:100%}.mdp-datepicker.portrait .md-actions,.mdp-datepicker.portrait .mdp-calendar-days,.mdp-datepicker.portrait .mdp-calendar-week-days{padding:0 5px}.mdp-datepicker.portrait .md-actions{margin-top:20px}.mdp-datepicker.portrait .mdp-calendar-days>*,.mdp-datepicker.portrait .mdp-calendar-week-days>*{width:32px}mdp-calendar{display:block}.mdp-calendar-week-days{width:100%}.mdp-calendar-days .md-button,.mdp-calendar-days .mdp-day-placeholder,.mdp-calendar-week-days>*{margin:0}.mdp-clock{width:200px;height:200px;border-radius:50%;cursor:pointer;padding:24px;background:#ededed}.mdp-clock .md-button{box-shadow:none!important;background-color:transparent;display:block;position:absolute;min-height:32px;width:32px;height:32px;font-size:12px;line-height:32px;margin:0;padding:0;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%)}.mdp-clock .mdp-clock-container{width:100%;height:100%;position:relative;display:block}.mdp-clock .mdp-pointer{width:1px;height:50%;margin:0 auto;-webkit-transform-origin:top center;transform-origin:top center;z-index:0;pointer-events:none}.mdp-clock .mdp-clock-center,.mdp-clock .mdp-pointer{min-height:0;position:absolute;left:0;right:0;bottom:0}.mdp-clock .mdp-clock-center{height:6px;width:6px;top:0;margin:auto;border-radius:50%}.mdp-clock .md-button.mdp-clock-selected{position:absolute;border-radius:50%;width:8px;height:8px;bottom:-8px;left:0;min-width:0;min-height:0;pointer-events:none}.mdp-timepicker .mdp-clock-switch-container{padding:20px;width:309px}.mdp-timepicker .mdp-timepicker-time{padding:15px}.mdp-timepicker .mdp-timepicker-selected-time{font-size:3rem}.mdp-timepicker:not(.portrait) .mdp-timepicker-time{width:138px}.mdp-timepicker.portrait .mdp-timepicker-selected-time{font-size:4rem;margin-right:1.5rem}mdp-time-picker md-input-container.md-has-icon{padding-left:40px}mdp-time-picker .md-button.md-icon-button{margin:18px 0 0}.mdp-timepicker-selected-ampm>span,.mdp-timepicker-selected-time>span{outline:0;opacity:.6}.mdp-timepicker-selected-ampm>span:not(.active),.mdp-timepicker-selected-time>span:not(.active){cursor:pointer}.mdp-timepicker-selected-ampm>span.active,.mdp-timepicker-selected-time>span.active{opacity:1}.mdp-clock-deg0{top:0;left:50%}.mdp-clock-deg30{top:6.69872981%;left:75%}.mdp-clock-deg60{top:25%;left:93.30127019%}.mdp-clock-deg90{top:50%;left:100%}.mdp-clock-deg120{top:75%;left:93.30127019%}.mdp-clock-deg150{top:93.30127019%;left:75%}.mdp-clock-deg180{top:100%;left:50%}.mdp-clock-deg210{top:93.30127019%;left:25%}.mdp-clock-deg240{top:75%;left:6.69872981%}.mdp-clock-deg270{top:50%;left:0}.mdp-clock-deg300{top:25%;left:6.69872981%}.mdp-clock-deg330{top:6.69872981%;left:25%}.mdp-clock-deg360{top:0;left:50%} \ No newline at end of file +.mdp-animate-next,.mdp-animate-next-remove{opacity:0;-webkit-transform:translate3d(50%,0,1px);transform:translate3d(50%,0,1px)}.mdp-animate-next-remove{-webkit-transition:all .5s cubic-bezier(.35,0,.25,1);transition:all .5s cubic-bezier(.35,0,.25,1)}.mdp-animate-next-remove-active{opacity:1;-webkit-transform:translateZ(1px);transform:translateZ(1px)}.mdp-animate-prev,.mdp-animate-prev-remove{opacity:0;-webkit-transform:translate3d(-50%,0,1px);transform:translate3d(-50%,0,1px)}.mdp-animate-prev-remove{-webkit-transition:all .3s cubic-bezier(.35,0,.25,1);transition:all .3s cubic-bezier(.35,0,.25,1)}.mdp-animate-prev-remove-active{opacity:1;-webkit-transform:translateZ(1px);transform:translateZ(1px)}@-webkit-keyframes a{0%{opacity:0;-webkit-transform:scale(.95);transform:scale(.95)}70%{opacity:1;-webkit-transform:scale(1.05);transform:scale(1.05)}to{-webkit-transform:scale(1);transform:scale(1)}}@keyframes a{0%{opacity:0;-webkit-transform:scale(.95);transform:scale(.95)}70%{opacity:1;-webkit-transform:scale(1.05);transform:scale(1.05)}to{-webkit-transform:scale(1);transform:scale(1)}}.mdp-animation-zoom.ng-enter{-webkit-transition:all .3s cubic-bezier(.35,0,.25,1);transition:all .3s cubic-bezier(.35,0,.25,1);-webkit-animation-duration:.3s;animation-duration:.3s;-webkit-animation-name:a;animation-name:a}.mdp-clock{width:200px;height:200px;border-radius:50%;cursor:pointer;padding:24px;background:#ededed}.mdp-clock .md-button{box-shadow:none!important;background-color:transparent;display:block;position:absolute;min-height:32px;width:32px;height:32px;font-size:12px;line-height:32px;margin:0;padding:0;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%)}.mdp-clock .mdp-clock-container{width:100%;height:100%;position:relative;display:block}.mdp-clock .mdp-pointer{width:1px;height:50%;margin:0 auto;-webkit-transform-origin:top center;transform-origin:top center;z-index:0;pointer-events:none}.mdp-clock .mdp-clock-center,.mdp-clock .mdp-pointer{min-height:0;position:absolute;left:0;right:0;bottom:0}.mdp-clock .mdp-clock-center{height:6px;width:6px;top:0;margin:auto;border-radius:50%}.mdp-clock .md-button.mdp-clock-selected{position:absolute;border-radius:50%;width:8px;height:8px;bottom:-8px;left:0;min-width:0;min-height:0;pointer-events:none}.mdp-timepicker .mdp-clock-switch-container{padding:20px;width:309px}.mdp-timepicker .mdp-timepicker-time{padding:15px}.mdp-timepicker .mdp-timepicker-selected-time{font-size:3rem}.mdp-timepicker:not(.portrait) .mdp-timepicker-time{width:138px}.mdp-timepicker.portrait .mdp-timepicker-selected-time{font-size:4rem;margin-right:1.5rem}mdp-time-picker md-input-container.md-has-icon{padding-left:40px}mdp-time-picker .md-button.md-icon-button{margin:18px 0 0}.mdp-timepicker-selected-ampm>span,.mdp-timepicker-selected-time>span{outline:0;opacity:.6}.mdp-timepicker-selected-ampm>span:not(.active),.mdp-timepicker-selected-time>span:not(.active){cursor:pointer}.mdp-timepicker-selected-ampm>span.active,.mdp-timepicker-selected-time>span.active{opacity:1}.mdp-clock-deg0{top:0;left:50%}.mdp-clock-deg30{top:6.69872981%;left:75%}.mdp-clock-deg60{top:25%;left:93.30127019%}.mdp-clock-deg90{top:50%;left:100%}.mdp-clock-deg120{top:75%;left:93.30127019%}.mdp-clock-deg150{top:93.30127019%;left:75%}.mdp-clock-deg180{top:100%;left:50%}.mdp-clock-deg210{top:93.30127019%;left:25%}.mdp-clock-deg240{top:75%;left:6.69872981%}.mdp-clock-deg270{top:50%;left:0}.mdp-clock-deg300{top:25%;left:6.69872981%}.mdp-clock-deg330{top:6.69872981%;left:25%}.mdp-clock-deg360{top:0;left:50%}.mdp-datepicker{max-height:none;min-width:234px}.mdp-datepicker *{outline:0}.mdp-datepicker .md-actions{width:100%;padding:0 5px}.mdp-calendar-week-days{font-size:.75rem;opacity:.6}.mdp-calendar-week-days>*{width:32px;height:32px;line-height:32px;margin:0 5px;padding:0;min-width:0;min-height:0;box-shadow:none!important;background-color:transparent}.mdp-calendar-days{font-size:1rem;max-width:100%}.mdp-calendar-days .md-button,.mdp-calendar-days .mdp-day-placeholder{width:32px;height:32px;margin:0 5px}.mdp-calendar-days .md-button{cursor:pointer;border-radius:50%;font-size:12px;width:32px;height:32px;line-height:32px;padding:0;min-width:0;min-height:0;box-shadow:none!important;background-color:transparent}.mdp-calendar-days .md-button[disabled]:not(.md-accent){background-color:transparent!important}.mdp-calendar-monthyear{font-size:.8125rem;font-weight:700;line-height:32px;min-height:32px}.mdp-datepicker-date,.mdp-datepicker-day,.mdp-datepicker-dow,.mdp-datepicker-month{font-size:1.8rem;opacity:.6}.mdp-datepicker-date:not(.active),.mdp-datepicker-day:not(.active),.mdp-datepicker-dow:not(.active),.mdp-datepicker-month:not(.active){cursor:pointer}.mdp-datepicker-date.active,.mdp-datepicker-date:hover,.mdp-datepicker-day.active,.mdp-datepicker-day:hover,.mdp-datepicker-dow.active,.mdp-datepicker-dow:hover,.mdp-datepicker-month.active,.mdp-datepicker-month:hover{opacity:1}.mdp-datepicker-year{font-size:.9rem;opacity:.6;padding:0;margin:0}.mdp-datepicker-year:not(.active){cursor:pointer}.mdp-datepicker-year.active,.mdp-datepicker-year:hover{opacity:1}.mdp-datepicker-select-year{height:232px}.mdp-datepicker-select-year .repeated-year{text-align:center}.mdp-datepicker-select-year .repeated-year .md-button{width:100%;margin:0;border-radius:0;padding:0;font-size:1rem;line-height:42px}.mdp-datepicker-select-year .repeated-year .md-button.current{font-size:1.8rem;line-height:42px}.mdp-datepicker-select-year .md-virtual-repeat-container,.mdp-datepicker-select-year .md-virtual-repeat-offsetter,.mdp-datepicker-select-year .md-virtual-repeat-scroller{height:100%;width:100%}mdp-date-picker>md-input-container.md-has-icon{padding-left:40px}mdp-date-picker .md-button.md-icon-button{margin:18px 0 0}.mdp-datepicker:not(.portrait) .mdp-datepicker-select-year{width:309px}.mdp-datepicker:not(.portrait) .mdp-calendar{margin-right:5px;width:294px;margin-left:10px}.mdp-datepicker:not(.portrait) .mdp-datepicker-date-wrapper{width:150px}.mdp-datepicker:not(.portrait) .mdp-datepicker-dow{width:100%;display:block}.mdp-datepicker:not(.portrait) .mdp-calendar-days>*,.mdp-datepicker:not(.portrait) .mdp-calendar-week-days>*{width:42px}.mdp-datepicker .mdp-datepicker-date-wrapper{padding:16px 35px 16px 16px}.mdp-datepicker md-dialog-content{overflow:hidden;padding:0}.mdp-datepicker md-dialog-content .mdp-calendar{width:294px;overflow-x:hidden}.mdp-datepicker.portrait{max-width:234px}.mdp-datepicker.portrait .mdp-calendar{text-align:center;width:100%}.mdp-datepicker.portrait .mdp-datepicker-select-year{height:252px}.mdp-datepicker.portrait md-dialog-content>*{width:100%}.mdp-datepicker.portrait .md-actions,.mdp-datepicker.portrait .mdp-calendar-days,.mdp-datepicker.portrait .mdp-calendar-week-days{padding:0 5px}.mdp-datepicker.portrait .md-actions{margin-top:20px}.mdp-datepicker.portrait .mdp-calendar-days>*,.mdp-datepicker.portrait .mdp-calendar-week-days>*{width:32px}mdp-calendar{display:block}.mdp-calendar-week-days{width:100%}.mdp-calendar-days .md-button,.mdp-calendar-days .mdp-day-placeholder,.mdp-calendar-week-days>*{margin:0} \ No newline at end of file diff --git a/dist/mdPickers.min.js b/dist/mdPickers.min.js index 28b299ec..4c5809ac 100644 --- a/dist/mdPickers.min.js +++ b/dist/mdPickers.min.js @@ -1,2 +1,2 @@ -!function(){"use strict";function t(t,e,a,i,n,r){var o=this;this.date=moment(n),this.minDate=r.minDate&&moment(r.minDate).isValid()?moment(r.minDate):null,this.maxDate=r.maxDate&&moment(r.maxDate).isValid()?moment(r.maxDate):null,this.displayFormat=r.displayFormat||"ddd, MMM DD",this.dateFilter=angular.isFunction(r.dateFilter)?r.dateFilter:null,this.selectingYear=!1,this.minDate&&this.maxDate&&this.maxDate.isBefore(this.minDate)&&(this.maxDate=moment(this.minDate).add(1,"days")),this.date&&(this.minDate&&this.date.isBefore(this.minDate)&&(this.date=moment(this.minDate)),this.maxDate&&this.date.isAfter(this.maxDate)&&(this.date=moment(this.maxDate))),this.yearItems={currentIndex_:0,PAGE_SIZE:5,START:o.minDate?o.minDate.year():1900,END:o.maxDate?o.maxDate.year():0,getItemAtIndex:function(t){return this.currentIndex_a&&(a=this.weekDays.length-1);for(var i=[],n=1;a+t>=n;n++){var r=null;n>a&&(r={value:n-a,enabled:e.isDayEnabled(moment(e.date).date(n-a).toDate())}),i.push(r)}return i},this.isDayEnabled=function(t){return!(this.minDate&&!(this.minDate<=t)||this.maxDate&&!(this.maxDate>=t)||e.dateFilter&&e.dateFilter(t))},this.selectDate=function(t){e.date.date(t)},this.nextMonth=function(){e.date.add(1,"months")},this.prevMonth=function(){e.date.subtract(1,"months")},this.updateDaysInMonth=function(){e.daysInMonth=e.getDaysInMonth()},t.$watch(function(){return e.date.unix()},function(t,a){t&&t!==a&&e.updateDaysInMonth()}),e.updateDaysInMonth()}function a(t,e){return!t||angular.isDate(t)||moment(t,e,!0).isValid()}function i(t,e,a){var a=moment(a,"YYYY-MM-DD",!0),i=angular.isDate(t)?moment(t):moment(t,e,!0);return!t||angular.isDate(t)||!a.isValid()||i.isSameOrAfter(a)}function n(t,e,a){var a=moment(a,"YYYY-MM-DD",!0),i=angular.isDate(t)?moment(t):moment(t,e,!0);return!t||angular.isDate(t)||!a.isValid()||i.isSameOrBefore(a)}function r(t,e,a){var i=angular.isDate(t)?moment(t):moment(t,e,!0);return!t||angular.isDate(t)||!angular.isFunction(a)||!a(i)}function o(t,e,a,i,n){var r=this;this.VIEW_HOURS=1,this.VIEW_MINUTES=2,this.currentView=this.VIEW_HOURS,this.time=moment(a),this.autoSwitch=!!i,this.clockHours=parseInt(this.time.format("h")),this.clockMinutes=parseInt(this.time.minutes()),t.$mdMedia=n,this.switchView=function(){r.currentView=r.currentView==r.VIEW_HOURS?r.VIEW_MINUTES:r.VIEW_HOURS},this.setAM=function(){r.time.hours()>=12&&r.time.hour(r.time.hour()-12)},this.setPM=function(){r.time.hours()<12&&r.time.hour(r.time.hour()+12)},this.cancel=function(){e.cancel()},this.confirm=function(){e.hide(this.time.toDate())}}function s(t){var e="hours",a="minutes",i=this;this.STEP_DEG=30,this.steps=[],this.CLOCK_TYPES={hours:{range:12},minutes:{range:60}},this.getPointerStyle=function(){var t=1;switch(i.type){case e:t=12;break;case a:t=60}var n=Math.round(i.selected*(360/t))-180;return{"-webkit-transform":"rotate("+n+"deg)","-ms-transform":"rotate("+n+"deg)",transform:"rotate("+n+"deg)"}},this.setTimeByDeg=function(t){t=t>=360?0:t;var n=0;switch(i.type){case e:n=12;break;case a:n=60}i.setTime(Math.round(n/360*t))},this.setTime=function(t,n){switch(this.selected=t,i.type){case e:"PM"==i.time.format("A")&&(t+=12),this.time.hours(t);break;case a:t>59&&(t-=60),this.time.minutes(t)}},this.init=function(){switch(i.type=i.type||"hours",i.type){case e:for(var t=1;12>=t;t++)i.steps.push(t);i.selected=i.time.hours()||0,i.selected>12&&(i.selected-=12);break;case a:for(var t=5;55>=t;t+=5)i.steps.push(t);i.steps.push(0),i.selected=i.time.minutes()||0}},this.init()}var d=angular.module("mdPickers",["ngMaterial","ngAnimate","ngAria"]);d.config(["$mdIconProvider","mdpIconsRegistry",function(t,e){angular.forEach(e,function(e,a){t.icon(e.id,e.url)})}]),d.run(["$templateCache","mdpIconsRegistry",function(t,e){angular.forEach(e,function(e,a){t.put(e.url,e.svg)})}]),d.constant("mdpIconsRegistry",[{id:"mdp-chevron-left",url:"mdp-chevron-left.svg",svg:''},{id:"mdp-chevron-right",url:"mdp-chevron-right.svg",svg:''},{id:"mdp-access-time",url:"mdp-access-time.svg",svg:''},{id:"mdp-event",url:"mdp-event.svg",svg:''}]),d.directive("ngMessage",["$mdUtil",function(t){return{restrict:"EA",priority:101,compile:function(e){var a=t.getClosest(e,"mdp-time-picker",!0)||t.getClosest(e,"mdp-date-picker",!0);if(a)return e.toggleClass("md-input-message-animation",!0),{}}}}]),d.provider("$mdpDatePicker",function(){var e="OK",a="Cancel",i="ddd, MMM DD";this.setDisplayFormat=function(t){i=t},this.setOKButtonLabel=function(t){e=t},this.setCancelButtonLabel=function(t){a=t},this.$get=["$mdDialog",function(n){var r=function(r,o){return angular.isDate(r)||(r=Date.now()),angular.isObject(o)||(o={}),o.displayFormat=i,n.show({controller:["$scope","$mdDialog","$mdMedia","$timeout","currentDate","options",t],controllerAs:"datepicker",clickOutsideToClose:!0,template:'
{{ datepicker.date.format(\'YYYY\') }}{{ datepicker.date.format(datepicker.displayFormat) }}
{{ item }}
'+a+''+e+"
",targetEvent:o.targetEvent,locals:{currentDate:r,options:o},skipHide:!0})};return r}]}),d.directive("mdpCalendar",["$animate",function(t){return{restrict:"E",bindToController:{date:"=",minDate:"=",maxDate:"=",dateFilter:"="},template:'
{{ calendar.date.format("MMMM YYYY") }}
{{ d }}
{{ day.value }}
',controller:["$scope",e],controllerAs:"calendar",link:function(e,a,i,n){var r=[a[0].querySelector(".mdp-calendar-week-days"),a[0].querySelector(".mdp-calendar-days"),a[0].querySelector(".mdp-calendar-monthyear")].map(function(t){return angular.element(t)});e.$watch(function(){return n.date.format("YYYYMM")},function(e,a){var i=null;if(e>a?i="mdp-animate-next":a>e&&(i="mdp-animate-prev"),i)for(var n in r)r[n].addClass(i),t.removeClass(r[n],i)})}}}]),d.directive("mdpDatePicker",["$mdpDatePicker","$timeout",function(t,e){return{restrict:"E",require:"ngModel",transclude:!0,template:function(t,e){var a=angular.isDefined(e.mdpNoFloat),i=angular.isDefined(e.mdpPlaceholder)?e.mdpPlaceholder:"",n=angular.isDefined(e.mdpOpenOnClick)?!0:!1;return'
"},scope:{minDate:"=mdpMinDate",maxDate:"=mdpMaxDate",dateFilter:"=mdpDateFilter",dateFormat:"@mdpFormat",placeholder:"@mdpPlaceholder",noFloat:"=mdpNoFloat",openOnClick:"=mdpOpenOnClick",disabled:"=?mdpDisabled"},link:{pre:function(t,e,a,i,n){},post:function(e,o,s,d,m){function c(t){p[0].value=t,g.setHasValue(!d.$isEmpty(t))}function l(t){var a=moment(t,angular.isDate(t)?null:e.dateFormat,!0),i=a.format(e.dateFormat);a.isValid()?(c(i),d.$setViewValue(i)):(c(t),d.$setViewValue(t)),!d.$pristine&&f.hasClass("md-auto-hide")&&h.hasClass("md-input-invalid")&&f.removeClass("md-auto-hide"),d.$render()}function u(t){t.target.value!==d.$viewVaue&&l(t.target.value)}var p=angular.element(o[0].querySelector("input")),h=angular.element(o[0].querySelector("md-input-container")),g=h.controller("mdInputContainer");m(function(t){h.append(t)});var f=angular.element(h[0].querySelector("[ng-messages]"));e.type=e.dateFormat?"text":"date",e.dateFormat=e.dateFormat||"YYYY-MM-DD",e.model=d,e.isError=function(){return!d.$pristine&&!!d.$invalid},d.$formatters.unshift(function(t){var a=angular.isDate(t)&&moment(t);c(a&&a.isValid()?a.format(e.dateFormat):null)}),d.$validators.format=function(t,i){return a(i,e.dateFormat)},d.$validators.minDate=function(t,a){return i(a,e.dateFormat,e.minDate)},d.$validators.maxDate=function(t,a){return n(a,e.dateFormat,e.maxDate)},d.$validators.filter=function(t,a){return r(a,e.dateFormat,e.dateFilter)},d.$validators.required=function(t,e){return angular.isUndefined(s.required)||!d.$isEmpty(t)||!d.$isEmpty(e)},d.$parsers.unshift(function(t){var a=moment(t,e.dateFormat,!0);if(a.isValid()){if(angular.isDate(d.$modelValue)){var i=moment(d.$modelValue);i.year(a.year()),i.month(a.month()),i.date(a.date()),a=i}return a.toDate()}return null}),e.showPicker=function(a){t(d.$modelValue,{minDate:e.minDate,maxDate:e.maxDate,dateFilter:e.dateFilter,targetEvent:a}).then(l)},p.on("reset input blur",u),e.$on("$destroy",function(){p.off("reset input blur",u)})}}}}]),d.directive("mdpDatePicker",["$mdpDatePicker","$timeout",function(t,e){return{restrict:"A",require:"ngModel",scope:{minDate:"@min",maxDate:"@max",dateFilter:"=mdpDateFilter",dateFormat:"@mdpFormat"},link:function(e,o,s,d,m){function c(a){t(d.$modelValue,{minDate:e.minDate,maxDate:e.maxDate,dateFilter:e.dateFilter,targetEvent:a}).then(function(t){d.$setViewValue(moment(t).format(e.format)),d.$render()})}e.dateFormat=e.dateFormat||"YYYY-MM-DD",d.$validators.format=function(t,i){return a(i,e.format)},d.$validators.minDate=function(t,a){return i(a,e.format,e.minDate)},d.$validators.maxDate=function(t,a){return n(a,e.format,e.maxDate)},d.$validators.filter=function(t,a){return r(a,e.format,e.dateFilter)},o.on("click",c),e.$on("$destroy",function(){o.off("click",c)})}}}]),d.directive("mdpClock",["$animate","$timeout",function(t,e){return{restrict:"E",bindToController:{type:"@?",time:"=",autoSwitch:"=?"},replace:!0,template:'
{{ step }}
',controller:["$scope",s],controllerAs:"clock",link:function(t,a,i,n){var r=(angular.element(a[0].querySelector(".mdp-pointer")),t.$parent.timepicker),o=function(t){var a=t.currentTarget.getClientRects()[0],i=t.currentTarget.offsetWidth/2-(t.pageX-a.left),o=t.pageY-a.top-t.currentTarget.offsetHeight/2,s=Math.round(Math.atan2(i,o)*(180/Math.PI));e(function(){n.setTimeByDeg(s+180),n.autoSwitch&&-1!==["mouseup","click"].indexOf(t.type)&&r&&r.switchView()})};a.on("mousedown",function(){a.on("mousemove",o)}),a.on("mouseup",function(t){a.off("mousemove")}),a.on("click",o),t.$on("$destroy",function(){a.off("click",o),a.off("mousemove",o)})}}}]),d.provider("$mdpTimePicker",function(){var t="OK",e="Cancel";this.setOKButtonLabel=function(e){t=e},this.setCancelButtonLabel=function(t){e=t},this.$get=["$mdDialog",function(a){var i=function(i,n){return angular.isDate(i)||(i=Date.now()),angular.isObject(n)||(n={}),a.show({controller:["$scope","$mdDialog","time","autoSwitch","$mdMedia",o],controllerAs:"timepicker",clickOutsideToClose:!0,template:'
{{ timepicker.time.format("h") }}:{{ timepicker.time.format("mm") }}
AMPM
'+e+''+t+"
",targetEvent:n.targetEvent,locals:{time:i,autoSwitch:n.autoSwitch},skipHide:!0})};return i}]}),d.directive("mdpTimePicker",["$mdpTimePicker","$timeout",function(t,e){return{restrict:"E",require:"ngModel",transclude:!0,template:function(t,e){var a=angular.isDefined(e.mdpNoFloat),i=angular.isDefined(e.mdpPlaceholder)?e.mdpPlaceholder:"",n=angular.isDefined(e.mdpOpenOnClick)?!0:!1;return'
"},scope:{timeFormat:"@mdpFormat",placeholder:"@mdpPlaceholder",autoSwitch:"=?mdpAutoSwitch",disabled:"=?mdpDisabled"},link:function(e,a,i,n,r){function o(t){m[0].value=t,l.setHasValue(!n.$isEmpty(t))}function s(t){var a=moment(t,angular.isDate(t)?null:e.timeFormat,!0),i=a.format(e.timeFormat);a.isValid()?(o(i),n.$setViewValue(i)):(o(t),n.$setViewValue(t)),!n.$pristine&&u.hasClass("md-auto-hide")&&c.hasClass("md-input-invalid")&&u.removeClass("md-auto-hide"),n.$render()}function d(t){t.target.value!==n.$viewVaue&&s(t.target.value)}var m=angular.element(a[0].querySelector("input")),c=angular.element(a[0].querySelector("md-input-container")),l=c.controller("mdInputContainer");r(function(t){c.append(t)});var u=angular.element(c[0].querySelector("[ng-messages]"));e.type=e.timeFormat?"text":"time",e.timeFormat=e.timeFormat||"HH:mm",e.autoSwitch=e.autoSwitch||!1,e.$watch(function(){return n.$error},function(t,e){l.setInvalid(!n.$pristine&&!!Object.keys(n.$error).length)},!0),n.$formatters.unshift(function(t){var a=angular.isDate(t)&&moment(t);o(a&&a.isValid()?a.format(e.timeFormat):null)}),n.$validators.format=function(t,a){return!a||angular.isDate(a)||moment(a,e.timeFormat,!0).isValid()},n.$validators.required=function(t,e){return angular.isUndefined(i.required)||!n.$isEmpty(t)||!n.$isEmpty(e)},n.$parsers.unshift(function(t){var a=moment(t,e.timeFormat,!0);if(a.isValid()){if(angular.isDate(n.$modelValue)){var i=moment(n.$modelValue);i.minutes(a.minutes()),i.hours(a.hours()),i.seconds(a.seconds()),a=i}return a.toDate()}return null}),e.showPicker=function(a){t(n.$modelValue,{targetEvent:a,autoSwitch:e.autoSwitch}).then(function(t){s(t,!0)})},m.on("reset input blur",d),e.$on("$destroy",function(){m.off("reset input blur",d)})}}}]),d.directive("mdpTimePicker",["$mdpTimePicker","$timeout",function(t,e){return{restrict:"A",require:"ngModel",scope:{timeFormat:"@mdpFormat",autoSwitch:"=?mdpAutoSwitch"},link:function(e,a,i,n,r){function o(a){t(n.$modelValue,{targetEvent:a,autoSwitch:e.autoSwitch}).then(function(t){n.$setViewValue(moment(t).format(e.format)),n.$render()})}e.format=e.format||"HH:mm",a.on("click",o),e.$on("$destroy",function(){a.off("click",o)})}}}])}(); +!function(){"use strict";function t(t,e,a,i,n){var r=this;this.VIEW_HOURS=1,this.VIEW_MINUTES=2,this.currentView=this.VIEW_HOURS,this.time=moment(a),this.autoSwitch=!!i,this.clockHours=parseInt(this.time.format("h")),this.clockMinutes=parseInt(this.time.minutes()),t.$mdMedia=n,this.switchView=function(){r.currentView=r.currentView==r.VIEW_HOURS?r.VIEW_MINUTES:r.VIEW_HOURS},this.setAM=function(){r.time.hours()>=12&&r.time.hour(r.time.hour()-12)},this.setPM=function(){r.time.hours()<12&&r.time.hour(r.time.hour()+12)},this.cancel=function(){e.cancel()},this.confirm=function(){e.hide(this.time.toDate())}}function e(t){var e="hours",a="minutes",i=this;this.STEP_DEG=30,this.steps=[],this.CLOCK_TYPES={hours:{range:12},minutes:{range:60}},this.getPointerStyle=function(){var t=1;switch(i.type){case e:t=12;break;case a:t=60}var n=Math.round(i.selected*(360/t))-180;return{"-webkit-transform":"rotate("+n+"deg)","-ms-transform":"rotate("+n+"deg)",transform:"rotate("+n+"deg)"}},this.setTimeByDeg=function(t){t=t>=360?0:t;var n=0;switch(i.type){case e:n=12;break;case a:n=60}i.setTime(Math.round(n/360*t))},this.setTime=function(t,n){switch(this.selected=t,i.type){case e:"PM"==i.time.format("A")&&(t+=12),this.time.hours(t);break;case a:t>59&&(t-=60),this.time.minutes(t)}},this.init=function(){switch(i.type=i.type||"hours",i.type){case e:for(var t=1;t<=12;t++)i.steps.push(t);i.selected=i.time.hours()||0,i.selected>12&&(i.selected-=12);break;case a:for(var t=5;t<=55;t+=5)i.steps.push(t);i.steps.push(0),i.selected=i.time.minutes()||0}},this.init()}function a(t,e,a,i,n,r){var o=this;this.date=moment(n),this.minDate=r.minDate&&moment(r.minDate).isValid()?moment(r.minDate):null,this.maxDate=r.maxDate&&moment(r.maxDate).isValid()?moment(r.maxDate):null,this.displayFormat=r.displayFormat||"ddd, MMM DD",this.dateFilter=angular.isFunction(r.dateFilter)?r.dateFilter:null,this.selectingYear=!1,this.minDate&&this.maxDate&&this.maxDate.isBefore(this.minDate)&&(this.maxDate=moment(this.minDate).add(1,"days")),this.date&&(this.minDate&&this.date.isBefore(this.minDate)&&(this.date=moment(this.minDate)),this.maxDate&&this.date.isAfter(this.maxDate)&&(this.date=moment(this.maxDate))),this.yearItems={currentIndex_:0,PAGE_SIZE:5,START:o.minDate?o.minDate.year():1900,END:o.maxDate?o.maxDate.year():0,getItemAtIndex:function(t){return this.currentIndex_a&&(r={value:n-a,enabled:e.isDayEnabled(moment(e.date).date(n-a).toDate())}),i.push(r)}return i},this.isDayEnabled=function(t){return!(this.minDate&&!(this.minDate<=t)||this.maxDate&&!(this.maxDate>=t)||e.dateFilter&&e.dateFilter(t))},this.selectDate=function(t){e.date.date(t)},this.nextMonth=function(){e.date.add(1,"months")},this.prevMonth=function(){e.date.subtract(1,"months")},this.updateDaysInMonth=function(){e.daysInMonth=e.getDaysInMonth()},t.$watch(function(){return e.date.unix()},function(t,a){t&&t!==a&&e.updateDaysInMonth()}),e.updateDaysInMonth()}function n(t,e){return!t||angular.isDate(t)||moment(t,e,!0).isValid()}function r(t,e,a){var a=moment(a,"YYYY-MM-DD",!0),i=angular.isDate(t)?moment(t):moment(t,e,!0);return!t||angular.isDate(t)||!a.isValid()||i.isSameOrAfter(a)}function o(t,e,a){var a=moment(a,"YYYY-MM-DD",!0),i=angular.isDate(t)?moment(t):moment(t,e,!0);return!t||angular.isDate(t)||!a.isValid()||i.isSameOrBefore(a)}function s(t,e,a){var i=angular.isDate(t)?moment(t):moment(t,e,!0);return!t||angular.isDate(t)||!angular.isFunction(a)||!a(i)}var d=angular.module("mdPickers",["ngMaterial","ngAnimate","ngAria"]);d.config(["$mdIconProvider","mdpIconsRegistry",function(t,e){angular.forEach(e,function(e,a){t.icon(e.id,e.url)})}]),d.run(["$templateCache","mdpIconsRegistry",function(t,e){angular.forEach(e,function(e,a){t.put(e.url,e.svg)})}]),d.constant("mdpIconsRegistry",[{id:"mdp-chevron-left",url:"mdp-chevron-left.svg",svg:''},{id:"mdp-chevron-right",url:"mdp-chevron-right.svg",svg:''},{id:"mdp-access-time",url:"mdp-access-time.svg",svg:''},{id:"mdp-event",url:"mdp-event.svg",svg:''}]),d.directive("ngMessage",["$mdUtil",function(t){return{restrict:"EA",priority:101,compile:function(e){var a=t.getClosest(e,"mdp-time-picker",!0)||t.getClosest(e,"mdp-date-picker",!0);if(a)return e.toggleClass("md-input-message-animation",!0),{}}}}]),d.directive("mdpClock",["$animate","$timeout",function(t,a){return{restrict:"E",bindToController:{type:"@?",time:"=",autoSwitch:"=?"},replace:!0,template:'
{{ step }}
',controller:["$scope",e],controllerAs:"clock",link:function(t,e,i,n){var r=(angular.element(e[0].querySelector(".mdp-pointer")),t.$parent.timepicker),o=function(t){var e=t.currentTarget.getClientRects()[0],i=t.currentTarget.offsetWidth/2-(t.pageX-e.left),o=t.pageY-e.top-t.currentTarget.offsetHeight/2,s=Math.round(Math.atan2(i,o)*(180/Math.PI));a(function(){n.setTimeByDeg(s+180),n.autoSwitch&&["mouseup","click"].indexOf(t.type)!==-1&&r&&r.switchView()})};e.on("mousedown",function(){e.on("mousemove",o)}),e.on("mouseup",function(t){e.off("mousemove")}),e.on("click",o),t.$on("$destroy",function(){e.off("click",o),e.off("mousemove",o)})}}}]),d.provider("$mdpTimePicker",function(){var e="OK",a="Cancel";this.setOKButtonLabel=function(t){e=t},this.setCancelButtonLabel=function(t){a=t},this.$get=["$mdDialog",function(i){var n=function(n,r){return angular.isDate(n)||(n=Date.now()),angular.isObject(r)||(r={}),i.show({controller:["$scope","$mdDialog","time","autoSwitch","$mdMedia",t],controllerAs:"timepicker",clickOutsideToClose:!0,template:'
{{ timepicker.time.format("h") }}:{{ timepicker.time.format("mm") }}
AMPM
'+a+''+e+"
",targetEvent:r.targetEvent,locals:{time:n,autoSwitch:r.autoSwitch},skipHide:!0})};return n}]}),d.directive("mdpTimePicker",["$mdpTimePicker","$timeout",function(t,e){return{restrict:"E",require:"ngModel",transclude:!0,template:function(t,e){var a=angular.isDefined(e.mdpNoFloat),i=angular.isDefined(e.mdpPlaceholder)?e.mdpPlaceholder:"",n=!!angular.isDefined(e.mdpOpenOnClick);return'
"},scope:{timeFormat:"@mdpFormat",placeholder:"@mdpPlaceholder",autoSwitch:"=?mdpAutoSwitch",disabled:"=?mdpDisabled"},link:function(e,a,i,n,r){function o(t){m[0].value!==t&&(m[0].value=t),l.setHasValue(!n.$isEmpty(t))}function s(t){var a=moment(t,angular.isDate(t)?null:e.timeFormat,!0),i=a.format(e.timeFormat);a.isValid()?(o(i),n.$setViewValue(i)):(o(t),n.$setViewValue(t)),!n.$pristine&&u.hasClass("md-auto-hide")&&c.hasClass("md-input-invalid")&&u.removeClass("md-auto-hide"),n.$render()}function d(t){t.target.value!==n.$viewVaue&&s(t.target.value)}var m=angular.element(a[0].querySelector("input")),c=angular.element(a[0].querySelector("md-input-container")),l=c.controller("mdInputContainer");r(function(t){c.append(t)});var u=angular.element(c[0].querySelector("[ng-messages]"));e.type=e.timeFormat?"text":"time",e.timeFormat=e.timeFormat||"HH:mm",e.autoSwitch=e.autoSwitch||!1,e.$watch(function(){return n.$error},function(t,e){l.setInvalid(!n.$pristine&&!!Object.keys(n.$error).length)},!0),n.$formatters.unshift(function(t){var a=angular.isDate(t)&&moment(t);o(a&&a.isValid()?a.format(e.timeFormat):null)}),n.$validators.format=function(t,a){return!a||angular.isDate(a)||moment(a,e.timeFormat,!0).isValid()},n.$validators.required=function(t,e){return angular.isUndefined(i.required)||!n.$isEmpty(t)||!n.$isEmpty(e)},n.$parsers.unshift(function(t){var a=moment(t,e.timeFormat,!0);if(a.isValid()){if(angular.isDate(n.$modelValue)){var i=moment(n.$modelValue);i.minutes(a.minutes()),i.hours(a.hours()),i.seconds(a.seconds()),a=i}return a.toDate()}return null}),e.showPicker=function(a){t(n.$modelValue,{targetEvent:a,autoSwitch:e.autoSwitch}).then(function(t){s(t,!0)})},m.on("reset input blur",d),e.$on("$destroy",function(){m.off("reset input blur",d)})}}}]),d.directive("mdpTimePicker",["$mdpTimePicker","$timeout",function(t,e){return{restrict:"A",require:"ngModel",scope:{timeFormat:"@mdpFormat",autoSwitch:"=?mdpAutoSwitch"},link:function(e,a,i,n,r){function o(a){t(n.$modelValue,{targetEvent:a,autoSwitch:e.autoSwitch}).then(function(t){n.$setViewValue(moment(t).format(e.format)),n.$render()})}e.format=e.format||"HH:mm",a.on("click",o),e.$on("$destroy",function(){a.off("click",o)})}}}]),d.provider("$mdpDatePicker",function(){var t="OK",e="Cancel",i="ddd, MMM DD";this.setDisplayFormat=function(t){i=t},this.setOKButtonLabel=function(e){t=e},this.setCancelButtonLabel=function(t){e=t},this.$get=["$mdDialog",function(n){var r=function(r,o){return angular.isDate(r)||(r=Date.now()),angular.isObject(o)||(o={}),o.displayFormat=i,n.show({controller:["$scope","$mdDialog","$mdMedia","$timeout","currentDate","options",a],controllerAs:"datepicker",clickOutsideToClose:!0,template:'
{{ datepicker.date.format(\'YYYY\') }}{{ datepicker.date.format(datepicker.displayFormat) }}
{{ item }}
'+e+''+t+"
",targetEvent:o.targetEvent,locals:{currentDate:r,options:o},skipHide:!0})};return r}]}),d.directive("mdpCalendar",["$animate",function(t){return{restrict:"E",bindToController:{date:"=",minDate:"=",maxDate:"=",dateFilter:"="},template:'
{{ calendar.date.format("MMMM YYYY") }}
{{ d }}
{{ day.value }}
',controller:["$scope",i],controllerAs:"calendar",link:function(e,a,i,n){var r=[a[0].querySelector(".mdp-calendar-week-days"),a[0].querySelector(".mdp-calendar-days"),a[0].querySelector(".mdp-calendar-monthyear")].map(function(t){return angular.element(t)});e.$watch(function(){return n.date.format("YYYYMM")},function(e,a){var i=null;if(e>a?i="mdp-animate-next":e
"},scope:{minDate:"=mdpMinDate",maxDate:"=mdpMaxDate",dateFilter:"=mdpDateFilter",dateFormat:"@mdpFormat",placeholder:"@mdpPlaceholder",noFloat:"=mdpNoFloat",openOnClick:"=mdpOpenOnClick",disabled:"=?mdpDisabled"},link:{pre:function(t,e,a,i,n){},post:function(e,a,i,d,m){function c(t){p[0].value=t,g.setHasValue(!d.$isEmpty(t))}function l(t){var a=moment(t,angular.isDate(t)?null:e.dateFormat,!0),i=a.format(e.dateFormat);a.isValid()?(c(i),d.$setViewValue(i)):(c(t),d.$setViewValue(t)),!d.$pristine&&f.hasClass("md-auto-hide")&&h.hasClass("md-input-invalid")&&f.removeClass("md-auto-hide"),d.$render()}function u(t){t.target.value!==d.$viewVaue&&l(t.target.value)}var p=angular.element(a[0].querySelector("input")),h=angular.element(a[0].querySelector("md-input-container")),g=h.controller("mdInputContainer");m(function(t){h.append(t)});var f=angular.element(h[0].querySelector("[ng-messages]"));e.type=e.dateFormat?"text":"date",e.dateFormat=e.dateFormat||"YYYY-MM-DD",e.model=d,e.isError=function(){return!d.$pristine&&!!d.$invalid},d.$formatters.unshift(function(t){var a=angular.isDate(t)&&moment(t);c(a&&a.isValid()?a.format(e.dateFormat):null)}),d.$validators.format=function(t,a){return n(a,e.dateFormat)},d.$validators.minDate=function(t,a){return r(a,e.dateFormat,e.minDate)},d.$validators.maxDate=function(t,a){return o(a,e.dateFormat,e.maxDate)},d.$validators.filter=function(t,a){return s(a,e.dateFormat,e.dateFilter)},d.$validators.required=function(t,e){return angular.isUndefined(i.required)||!d.$isEmpty(t)||!d.$isEmpty(e)},d.$parsers.unshift(function(t){var a=moment(t,e.dateFormat,!0);if(a.isValid()){if(angular.isDate(d.$modelValue)){var i=moment(d.$modelValue);i.year(a.year()),i.month(a.month()),i.date(a.date()),a=i}return a.toDate()}return null}),e.showPicker=function(a){t(d.$modelValue,{minDate:e.minDate,maxDate:e.maxDate,dateFilter:e.dateFilter,targetEvent:a}).then(l)},p.on("reset input blur",u),e.$on("$destroy",function(){p.off("reset input blur",u)})}}}}]),d.directive("mdpDatePicker",["$mdpDatePicker","$timeout",function(t,e){return{restrict:"A",require:"ngModel",scope:{minDate:"@min",maxDate:"@max",dateFilter:"=mdpDateFilter",dateFormat:"@mdpFormat"},link:function(e,a,i,d,m){function c(a){t(d.$modelValue,{minDate:e.minDate,maxDate:e.maxDate,dateFilter:e.dateFilter,targetEvent:a}).then(function(t){d.$setViewValue(moment(t).format(e.format)),d.$render()})}e.dateFormat=e.dateFormat||"YYYY-MM-DD",d.$validators.format=function(t,a){return n(a,e.format)},d.$validators.minDate=function(t,a){return r(a,e.format,e.minDate)},d.$validators.maxDate=function(t,a){return o(a,e.format,e.maxDate)},d.$validators.filter=function(t,a){return s(a,e.format,e.dateFilter)},a.on("click",c),e.$on("$destroy",function(){a.off("click",c)})}}}])}(); //# sourceMappingURL=mdPickers.min.js.map diff --git a/dist/mdPickers.min.js.map b/dist/mdPickers.min.js.map index 99e5a176..178a24ad 100644 --- a/dist/mdPickers.min.js.map +++ b/dist/mdPickers.min.js.map @@ -1 +1 @@ -{"version":3,"sources":["mdPickers.min.js"],"names":["DatePickerCtrl","$scope","$mdDialog","$mdMedia","$timeout","currentDate","options","self","this","date","moment","minDate","isValid","maxDate","displayFormat","dateFilter","angular","isFunction","selectingYear","isBefore","add","isAfter","yearItems","currentIndex_","PAGE_SIZE","START","year","END","getItemAtIndex","index","getLength","Math","min","floor","abs","selectYear","animate","showYear","yearTopIndex","showCalendar","cancel","confirm","hide","toDate","animating","noop","then","CalendarCtrl","dow","localeData","firstDayOfWeek","weekDays","concat","weekdaysMin","slice","daysInMonth","getDaysInMonth","days","firstDay","day","length","arr","i","value","enabled","isDayEnabled","push","selectDate","dom","nextMonth","prevMonth","subtract","updateDaysInMonth","$watch","unix","newValue","oldValue","formatValidator","format","isDate","minDateValidator","isSameOrAfter","maxDateValidator","isSameOrBefore","filterValidator","filter","TimePickerCtrl","time","autoSwitch","VIEW_HOURS","VIEW_MINUTES","currentView","clockHours","parseInt","clockMinutes","minutes","switchView","setAM","hours","hour","setPM","ClockCtrl","TYPE_HOURS","TYPE_MINUTES","STEP_DEG","steps","CLOCK_TYPES","range","getPointerStyle","divider","type","degrees","round","selected","-webkit-transform","-ms-transform","transform","setTimeByDeg","deg","setTime","init","module","config","$mdIconProvider","mdpIconsRegistry","forEach","icon","id","url","run","$templateCache","put","svg","constant","directive","$mdUtil","restrict","priority","compile","element","inputContainer","getClosest","toggleClass","provider","LABEL_OK","LABEL_CANCEL","DISPLAY_FORMAT","setDisplayFormat","setOKButtonLabel","label","setCancelButtonLabel","$get","datePicker","Date","now","isObject","show","controller","controllerAs","clickOutsideToClose","template","targetEvent","locals","skipHide","$animate","bindToController","link","scope","attrs","ctrl","animElements","querySelector","map","a","direction","addClass","removeClass","$mdpDatePicker","require","transclude","noFloat","isDefined","mdpNoFloat","placeholder","mdpPlaceholder","openOnClick","mdpOpenOnClick","mdpDisabled","dateFormat","disabled","pre","ngModel","$transclude","post","updateInputElement","inputElement","inputContainerCtrl","setHasValue","$isEmpty","updateDate","strValue","$setViewValue","$pristine","messages","hasClass","$render","onInputElementEvents","event","target","$viewVaue","clone","append","model","isError","$invalid","$formatters","unshift","$validators","modelValue","viewValue","required","isUndefined","$parsers","parsed","$modelValue","originalModel","month","showPicker","ev","on","$on","off","replace","timepickerCtrl","$parent","timepicker","onEvent","containerCoords","currentTarget","getClientRects","x","offsetWidth","pageX","left","y","pageY","top","offsetHeight","atan2","PI","indexOf","e","timePicker","$mdpTimePicker","timeFormat","updateTime","$error","setInvalid","Object","keys","seconds"],"mappings":"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","file":"mdPickers.min.js","sourcesContent":["(function() {\n\"use strict\";\n/* global moment, angular */\n\nvar module = angular.module(\"mdPickers\", [\n\t\"ngMaterial\",\n\t\"ngAnimate\",\n\t\"ngAria\"\n]);\n\nmodule.config([\"$mdIconProvider\", \"mdpIconsRegistry\", function($mdIconProvider, mdpIconsRegistry) {\n\tangular.forEach(mdpIconsRegistry, function(icon, index) {\n\t\t$mdIconProvider.icon(icon.id, icon.url);\n\t});\n}]);\n\nmodule.run([\"$templateCache\", \"mdpIconsRegistry\", function($templateCache, mdpIconsRegistry) {\n\tangular.forEach(mdpIconsRegistry, function(icon, index) {\n\t\t$templateCache.put(icon.url, icon.svg);\n\t});\n}]);\nmodule.constant(\"mdpIconsRegistry\", [\n {\n id: 'mdp-chevron-left',\n url: 'mdp-chevron-left.svg',\n svg: ''\n },\n {\n id: 'mdp-chevron-right',\n url: 'mdp-chevron-right.svg',\n svg: ''\n },\n {\n id: 'mdp-access-time',\n url: 'mdp-access-time.svg',\n svg: ''\n },\n {\n id: 'mdp-event',\n url: 'mdp-event.svg',\n svg: ''\n }\n]);\nmodule.directive(\"ngMessage\", [\"$mdUtil\", function($mdUtil) {\n return {\n restrict: \"EA\",\n priority: 101,\n compile: function(element) {\n var inputContainer = $mdUtil.getClosest(element, \"mdp-time-picker\", true) ||\n $mdUtil.getClosest(element, \"mdp-date-picker\", true);\n \n // If we are not a child of an input container, don't do anything\n if (!inputContainer) return;\n \n // Add our animation class\n element.toggleClass('md-input-message-animation', true);\n \n return {};\n }\n } \n}]);\n/* global moment, angular */\n\nfunction DatePickerCtrl($scope, $mdDialog, $mdMedia, $timeout, currentDate, options) {\n var self = this;\n\n this.date = moment(currentDate);\n this.minDate = options.minDate && moment(options.minDate).isValid() ? moment(options.minDate) : null;\n this.maxDate = options.maxDate && moment(options.maxDate).isValid() ? moment(options.maxDate) : null;\n this.displayFormat = options.displayFormat || \"ddd, MMM DD\";\n this.dateFilter = angular.isFunction(options.dateFilter) ? options.dateFilter : null;\n this.selectingYear = false;\n \n // validate min and max date\n\tif (this.minDate && this.maxDate) {\n\t\tif (this.maxDate.isBefore(this.minDate)) {\n\t\t\tthis.maxDate = moment(this.minDate).add(1, 'days');\n\t\t}\n\t}\n\t\n\tif (this.date) {\n\t\t// check min date\n \tif (this.minDate && this.date.isBefore(this.minDate)) {\n\t\t\tthis.date = moment(this.minDate);\n \t}\n \t\n \t// check max date\n \tif (this.maxDate && this.date.isAfter(this.maxDate)) {\n\t\t\tthis.date = moment(this.maxDate);\n \t}\n\t}\n\t\n\tthis.yearItems = {\n currentIndex_: 0,\n PAGE_SIZE: 5,\n START: (self.minDate ? self.minDate.year() : 1900),\n END: (self.maxDate ? self.maxDate.year() : 0),\n getItemAtIndex: function(index) {\n \tif(this.currentIndex_ < index)\n this.currentIndex_ = index;\n \t\n \treturn this.START + index;\n },\n getLength: function() {\n return Math.min(\n this.currentIndex_ + Math.floor(this.PAGE_SIZE / 2),\n Math.abs(this.START - this.END) + 1\n );\n }\n };\n\n $scope.$mdMedia = $mdMedia;\n $scope.year = this.date.year();\n\n\tthis.selectYear = function(year) {\n self.date.year(year);\n $scope.year = year;\n self.selectingYear = false;\n self.animate();\n };\n \n this.showYear = function() { \n self.yearTopIndex = (self.date.year() - self.yearItems.START) + Math.floor(self.yearItems.PAGE_SIZE / 2);\n self.yearItems.currentIndex_ = (self.date.year() - self.yearItems.START) + 1;\n self.selectingYear = true;\n };\n \n this.showCalendar = function() {\n self.selectingYear = false;\n };\n\n this.cancel = function() {\n $mdDialog.cancel();\n };\n\n this.confirm = function() {\n \tvar date = this.date;\n \t\n \tif (this.minDate && this.date.isBefore(this.minDate)) {\n \t\tdate = moment(this.minDate);\n \t}\n \t\n \tif (this.maxDate && this.date.isAfter(this.maxDate)) {\n \t\tdate = moment(this.maxDate);\n \t} \t\n \t\n $mdDialog.hide(date.toDate());\n };\n \n this.animate = function() {\n self.animating = true;\n $timeout(angular.noop).then(function() {\n self.animating = false;\n }) \n };\n}\n\nmodule.provider(\"$mdpDatePicker\", function() {\n var LABEL_OK = \"OK\",\n LABEL_CANCEL = \"Cancel\",\n DISPLAY_FORMAT = \"ddd, MMM DD\";\n \n this.setDisplayFormat = function(format) {\n DISPLAY_FORMAT = format; \n };\n \n this.setOKButtonLabel = function(label) {\n LABEL_OK = label;\n };\n \n this.setCancelButtonLabel = function(label) {\n LABEL_CANCEL = label;\n };\n \n this.$get = [\"$mdDialog\", function($mdDialog) {\n var datePicker = function(currentDate, options) {\n if (!angular.isDate(currentDate)) currentDate = Date.now();\n if (!angular.isObject(options)) options = {};\n \n options.displayFormat = DISPLAY_FORMAT;\n \n return $mdDialog.show({\n controller: ['$scope', '$mdDialog', '$mdMedia', '$timeout', 'currentDate', 'options', DatePickerCtrl],\n controllerAs: 'datepicker',\n clickOutsideToClose: true,\n template: '' +\n '' +\n '
' +\n '' +\n '{{ datepicker.date.format(\\'YYYY\\') }}' +\n '{{ datepicker.date.format(datepicker.displayFormat) }} ' +\n '' + \n '
' + \n '
' + \n '
' +\n '' +\n '
' +\n '{{ item }}' +\n '
' +\n '
' +\n '
' +\n '' +\n '' +\n \t'' +\n '' + LABEL_CANCEL + '' +\n '' + LABEL_OK + '' +\n '' +\n '
' +\n '
' +\n '
',\n targetEvent: options.targetEvent,\n locals: {\n currentDate: currentDate,\n options: options\n },\n skipHide: true\n });\n };\n \n return datePicker;\n }];\n});\n\nfunction CalendarCtrl($scope) {\n\tvar self = this;\n\tthis.dow = moment.localeData().firstDayOfWeek();\n\t\n this.weekDays = [].concat(\n moment.weekdaysMin().slice(\n this.dow\n ),\n moment.weekdaysMin().slice(\n 0, \n this.dow\n )\n );\n \n this.daysInMonth = [];\n \n this.getDaysInMonth = function() {\n var days = self.date.daysInMonth(),\n firstDay = moment(self.date).date(1).day() - this.dow;\n \n if(firstDay < 0) firstDay = this.weekDays.length - 1;\n \n\n var arr = [];\n for(var i = 1; i <= (firstDay + days); i++) {\n var day = null;\n if(i > firstDay) {\n day = {\n value: (i - firstDay),\n enabled: self.isDayEnabled(moment(self.date).date(i - firstDay).toDate())\n };\n }\n arr.push(day);\n }\n \n return arr;\n };\n \n this.isDayEnabled = function(day) {\n return (!this.minDate || this.minDate <= day) && \n (!this.maxDate || this.maxDate >= day) && \n (!self.dateFilter || !self.dateFilter(day));\n };\n \n this.selectDate = function(dom) {\n self.date.date(dom);\n };\n\n this.nextMonth = function() {\n self.date.add(1, 'months');\n };\n\n this.prevMonth = function() {\n self.date.subtract(1, 'months');\n };\n \n this.updateDaysInMonth = function() {\n self.daysInMonth = self.getDaysInMonth();\n };\n \n $scope.$watch(function() { return self.date.unix() }, function(newValue, oldValue) {\n if(newValue && newValue !== oldValue)\n self.updateDaysInMonth();\n })\n \n self.updateDaysInMonth();\n}\n\nmodule.directive(\"mdpCalendar\", [\"$animate\", function($animate) {\n return {\n restrict: 'E',\n bindToController: {\n \"date\": \"=\",\n \"minDate\": \"=\",\n \"maxDate\": \"=\",\n \"dateFilter\": \"=\"\n },\n template: '
' +\n '
' +\n '' +\n '
{{ calendar.date.format(\"MMMM YYYY\") }}
' +\n '' +\n '
' +\n '
' +\n '
{{ d }}
' +\n '
' +\n '
' +\n '
' +\n '{{ day.value }}' +\n '
' +\n '
' +\n '
' +\n '
',\n controller: [\"$scope\", CalendarCtrl],\n controllerAs: \"calendar\",\n link: function(scope, element, attrs, ctrl) {\n var animElements = [\n element[0].querySelector(\".mdp-calendar-week-days\"),\n element[0].querySelector('.mdp-calendar-days'),\n element[0].querySelector('.mdp-calendar-monthyear')\n ].map(function(a) {\n return angular.element(a); \n });\n \n scope.$watch(function() { return ctrl.date.format(\"YYYYMM\") }, function(newValue, oldValue) {\n var direction = null;\n \n if(newValue > oldValue)\n direction = \"mdp-animate-next\";\n else if(newValue < oldValue)\n direction = \"mdp-animate-prev\";\n \n if(direction) {\n for(var i in animElements) {\n animElements[i].addClass(direction);\n $animate.removeClass(animElements[i], direction);\n }\n }\n });\n }\n }\n}]);\n\nfunction formatValidator(value, format) {\n return !value || angular.isDate(value) || moment(value, format, true).isValid();\n}\n\nfunction minDateValidator(value, format, minDate) {\n var minDate = moment(minDate, \"YYYY-MM-DD\", true);\n var date = angular.isDate(value) ? moment(value) : moment(value, format, true);\n \n return !value || \n angular.isDate(value) || \n !minDate.isValid() || \n date.isSameOrAfter(minDate);\n}\n\nfunction maxDateValidator(value, format, maxDate) {\n var maxDate = moment(maxDate, \"YYYY-MM-DD\", true);\n var date = angular.isDate(value) ? moment(value) : moment(value, format, true);\n \n return !value || \n angular.isDate(value) || \n !maxDate.isValid() || \n date.isSameOrBefore(maxDate);\n}\n\nfunction filterValidator(value, format, filter) {\n var date = angular.isDate(value) ? moment(value) : moment(value, format, true);\n \n return !value || \n angular.isDate(value) || \n !angular.isFunction(filter) || \n !filter(date);\n}\n\nfunction requiredValidator(value, ngModel) {\n return value\n}\n\nmodule.directive(\"mdpDatePicker\", [\"$mdpDatePicker\", \"$timeout\", function($mdpDatePicker, $timeout) {\n return {\n restrict: 'E',\n require: 'ngModel',\n transclude: true,\n template: function(element, attrs) {\n var noFloat = angular.isDefined(attrs.mdpNoFloat),\n placeholder = angular.isDefined(attrs.mdpPlaceholder) ? attrs.mdpPlaceholder : \"\",\n openOnClick = angular.isDefined(attrs.mdpOpenOnClick) ? true : false;\n \n return '
' +\n '' +\n '' +\n '' +\n '' +\n '' +\n '' +\n '
';\n },\n scope: {\n \"minDate\": \"=mdpMinDate\",\n \"maxDate\": \"=mdpMaxDate\",\n \"dateFilter\": \"=mdpDateFilter\",\n \"dateFormat\": \"@mdpFormat\",\n \"placeholder\": \"@mdpPlaceholder\",\n \"noFloat\": \"=mdpNoFloat\",\n \"openOnClick\": \"=mdpOpenOnClick\",\n \"disabled\": \"=?mdpDisabled\"\n },\n link: {\n pre: function(scope, element, attrs, ngModel, $transclude) {\n \n },\n post: function(scope, element, attrs, ngModel, $transclude) {\n var inputElement = angular.element(element[0].querySelector('input')),\n inputContainer = angular.element(element[0].querySelector('md-input-container')),\n inputContainerCtrl = inputContainer.controller(\"mdInputContainer\");\n \n $transclude(function(clone) {\n inputContainer.append(clone); \n }); \n \n var messages = angular.element(inputContainer[0].querySelector(\"[ng-messages]\"));\n \n scope.type = scope.dateFormat ? \"text\" : \"date\"\n scope.dateFormat = scope.dateFormat || \"YYYY-MM-DD\";\n scope.model = ngModel;\n \n scope.isError = function() {\n return !ngModel.$pristine && !!ngModel.$invalid;\n };\n \n // update input element if model has changed\n ngModel.$formatters.unshift(function(value) {\n var date = angular.isDate(value) && moment(value);\n if(date && date.isValid()) \n updateInputElement(date.format(scope.dateFormat));\n else\n updateInputElement(null);\n });\n \n ngModel.$validators.format = function(modelValue, viewValue) {\n return formatValidator(viewValue, scope.dateFormat);\n };\n \n ngModel.$validators.minDate = function(modelValue, viewValue) {\n return minDateValidator(viewValue, scope.dateFormat, scope.minDate);\n };\n \n ngModel.$validators.maxDate = function(modelValue, viewValue) {\n return maxDateValidator(viewValue, scope.dateFormat, scope.maxDate);\n };\n \n ngModel.$validators.filter = function(modelValue, viewValue) {\n return filterValidator(viewValue, scope.dateFormat, scope.dateFilter);\n };\n \n ngModel.$validators.required = function(modelValue, viewValue) {\n return angular.isUndefined(attrs.required) || !ngModel.$isEmpty(modelValue) || !ngModel.$isEmpty(viewValue);\n };\n \n ngModel.$parsers.unshift(function(value) {\n var parsed = moment(value, scope.dateFormat, true);\n if(parsed.isValid()) {\n if(angular.isDate(ngModel.$modelValue)) {\n var originalModel = moment(ngModel.$modelValue);\n originalModel.year(parsed.year());\n originalModel.month(parsed.month());\n originalModel.date(parsed.date());\n \n parsed = originalModel;\n }\n return parsed.toDate(); \n } else\n return null;\n });\n \n // update input element value\n function updateInputElement(value) {\n inputElement[0].value = value;\n inputContainerCtrl.setHasValue(!ngModel.$isEmpty(value));\n }\n \n function updateDate(date) {\n var value = moment(date, angular.isDate(date) ? null : scope.dateFormat, true),\n strValue = value.format(scope.dateFormat);\n \n if(value.isValid()) {\n updateInputElement(strValue);\n ngModel.$setViewValue(strValue);\n } else {\n updateInputElement(date);\n ngModel.$setViewValue(date);\n }\n \n if(!ngModel.$pristine && \n messages.hasClass(\"md-auto-hide\") && \n inputContainer.hasClass(\"md-input-invalid\")) messages.removeClass(\"md-auto-hide\");\n \n ngModel.$render();\n }\n \n scope.showPicker = function(ev) {\n $mdpDatePicker(ngModel.$modelValue, {\n \t minDate: scope.minDate, \n \t maxDate: scope.maxDate,\n \t dateFilter: scope.dateFilter,\n \t targetEvent: ev\n \t }).then(updateDate);\n };\n \n function onInputElementEvents(event) {\n if(event.target.value !== ngModel.$viewVaue)\n updateDate(event.target.value);\n }\n \n inputElement.on(\"reset input blur\", onInputElementEvents);\n \n scope.$on(\"$destroy\", function() {\n inputElement.off(\"reset input blur\", onInputElementEvents);\n });\n }\n }\n };\n}]);\n\n\nmodule.directive(\"mdpDatePicker\", [\"$mdpDatePicker\", \"$timeout\", function($mdpDatePicker, $timeout) {\n return {\n restrict: 'A',\n require: 'ngModel',\n scope: {\n \"minDate\": \"@min\",\n \"maxDate\": \"@max\",\n \"dateFilter\": \"=mdpDateFilter\",\n \"dateFormat\": \"@mdpFormat\",\n },\n link: function(scope, element, attrs, ngModel, $transclude) {\n scope.dateFormat = scope.dateFormat || \"YYYY-MM-DD\";\n \n ngModel.$validators.format = function(modelValue, viewValue) {\n return formatValidator(viewValue, scope.format);\n };\n \n ngModel.$validators.minDate = function(modelValue, viewValue) {\n return minDateValidator(viewValue, scope.format, scope.minDate);\n };\n \n ngModel.$validators.maxDate = function(modelValue, viewValue) {\n return maxDateValidator(viewValue, scope.format, scope.maxDate);\n };\n \n ngModel.$validators.filter = function(modelValue, viewValue) {\n return filterValidator(viewValue, scope.format, scope.dateFilter);\n };\n \n function showPicker(ev) {\n $mdpDatePicker(ngModel.$modelValue, {\n \t minDate: scope.minDate, \n \t maxDate: scope.maxDate,\n \t dateFilter: scope.dateFilter,\n \t targetEvent: ev\n \t }).then(function(time) {\n ngModel.$setViewValue(moment(time).format(scope.format));\n ngModel.$render();\n });\n };\n \n element.on(\"click\", showPicker);\n \n scope.$on(\"$destroy\", function() {\n element.off(\"click\", showPicker);\n });\n }\n }\n}]);\n/* global moment, angular */\n\nfunction TimePickerCtrl($scope, $mdDialog, time, autoSwitch, $mdMedia) {\n\tvar self = this;\n this.VIEW_HOURS = 1;\n this.VIEW_MINUTES = 2;\n this.currentView = this.VIEW_HOURS;\n this.time = moment(time);\n this.autoSwitch = !!autoSwitch;\n \n this.clockHours = parseInt(this.time.format(\"h\"));\n this.clockMinutes = parseInt(this.time.minutes());\n \n\t$scope.$mdMedia = $mdMedia;\n\t\n\tthis.switchView = function() {\n\t self.currentView = self.currentView == self.VIEW_HOURS ? self.VIEW_MINUTES : self.VIEW_HOURS;\n\t};\n \n\tthis.setAM = function() {\n if(self.time.hours() >= 12)\n self.time.hour(self.time.hour() - 12);\n\t};\n \n this.setPM = function() {\n if(self.time.hours() < 12)\n self.time.hour(self.time.hour() + 12);\n\t};\n \n this.cancel = function() {\n $mdDialog.cancel();\n };\n\n this.confirm = function() {\n $mdDialog.hide(this.time.toDate());\n };\n}\n\nfunction ClockCtrl($scope) {\n var TYPE_HOURS = \"hours\";\n var TYPE_MINUTES = \"minutes\";\n var self = this;\n \n this.STEP_DEG = 360 / 12;\n this.steps = [];\n \n this.CLOCK_TYPES = {\n \"hours\": {\n range: 12,\n },\n \"minutes\": {\n range: 60,\n }\n }\n \n this.getPointerStyle = function() {\n var divider = 1;\n switch(self.type) {\n case TYPE_HOURS:\n divider = 12;\n break;\n case TYPE_MINUTES:\n divider = 60;\n break;\n } \n var degrees = Math.round(self.selected * (360 / divider)) - 180;\n return { \n \"-webkit-transform\": \"rotate(\" + degrees + \"deg)\",\n \"-ms-transform\": \"rotate(\" + degrees + \"deg)\",\n \"transform\": \"rotate(\" + degrees + \"deg)\"\n }\n };\n \n this.setTimeByDeg = function(deg) {\n deg = deg >= 360 ? 0 : deg;\n var divider = 0;\n switch(self.type) {\n case TYPE_HOURS:\n divider = 12;\n break;\n case TYPE_MINUTES:\n divider = 60;\n break;\n } \n \n self.setTime(\n Math.round(divider / 360 * deg)\n );\n };\n \n this.setTime = function(time, type) {\n this.selected = time;\n \n switch(self.type) {\n case TYPE_HOURS:\n if(self.time.format(\"A\") == \"PM\") time += 12;\n this.time.hours(time);\n break;\n case TYPE_MINUTES:\n if(time > 59) time -= 60;\n this.time.minutes(time);\n break;\n }\n \n };\n \n this.init = function() {\n self.type = self.type || \"hours\";\n switch(self.type) {\n case TYPE_HOURS:\n for(var i = 1; i <= 12; i++)\n self.steps.push(i);\n self.selected = self.time.hours() || 0;\n if(self.selected > 12) self.selected -= 12;\n \n break;\n case TYPE_MINUTES:\n for(var i = 5; i <= 55; i+=5)\n self.steps.push(i);\n self.steps.push(0);\n self.selected = self.time.minutes() || 0;\n \n break;\n }\n };\n \n this.init();\n}\n\nmodule.directive(\"mdpClock\", [\"$animate\", \"$timeout\", function($animate, $timeout) {\n return {\n restrict: 'E',\n bindToController: {\n 'type': '@?',\n 'time': '=',\n 'autoSwitch': '=?'\n },\n replace: true,\n template: '
' +\n '
' +\n '' +\n '' +\n '' +\n '' +\n '{{ step }}' +\n '
' +\n '
',\n controller: [\"$scope\", ClockCtrl],\n controllerAs: \"clock\",\n link: function(scope, element, attrs, ctrl) {\n var pointer = angular.element(element[0].querySelector(\".mdp-pointer\")),\n timepickerCtrl = scope.$parent.timepicker;\n \n var onEvent = function(event) {\n var containerCoords = event.currentTarget.getClientRects()[0];\n var x = ((event.currentTarget.offsetWidth / 2) - (event.pageX - containerCoords.left)),\n y = ((event.pageY - containerCoords.top) - (event.currentTarget.offsetHeight / 2));\n\n var deg = Math.round((Math.atan2(x, y) * (180 / Math.PI)));\n $timeout(function() {\n ctrl.setTimeByDeg(deg + 180);\n if(ctrl.autoSwitch && [\"mouseup\", \"click\"].indexOf(event.type) !== -1 && timepickerCtrl) timepickerCtrl.switchView();\n });\n }; \n \n element.on(\"mousedown\", function() {\n element.on(\"mousemove\", onEvent);\n });\n \n element.on(\"mouseup\", function(e) {\n element.off(\"mousemove\");\n });\n \n element.on(\"click\", onEvent);\n scope.$on(\"$destroy\", function() {\n element.off(\"click\", onEvent);\n element.off(\"mousemove\", onEvent); \n });\n }\n }\n}]);\n\nmodule.provider(\"$mdpTimePicker\", function() {\n var LABEL_OK = \"OK\",\n LABEL_CANCEL = \"Cancel\";\n \n this.setOKButtonLabel = function(label) {\n LABEL_OK = label;\n };\n \n this.setCancelButtonLabel = function(label) {\n LABEL_CANCEL = label;\n };\n \n this.$get = [\"$mdDialog\", function($mdDialog) {\n var timePicker = function(time, options) {\n if(!angular.isDate(time)) time = Date.now();\n if (!angular.isObject(options)) options = {};\n \n return $mdDialog.show({\n controller: ['$scope', '$mdDialog', 'time', 'autoSwitch', '$mdMedia', TimePickerCtrl],\n controllerAs: 'timepicker',\n clickOutsideToClose: true,\n template: '' +\n '' +\n '' +\n '
' +\n '{{ timepicker.time.format(\"h\") }}:' + \n '{{ timepicker.time.format(\"mm\") }}' +\n '
' +\n '
' + \n 'AM' +\n '= 12 }\">PM' +\n '
' + \n '
' +\n '
' +\n '
' +\n\t '' +\n\t '' +\n '
' +\n \n '' +\n\t \t'' +\n '' + LABEL_CANCEL + '' +\n '' + LABEL_OK + '' +\n '' +\n '
' +\n '
' +\n '
',\n targetEvent: options.targetEvent,\n locals: {\n time: time,\n autoSwitch: options.autoSwitch\n },\n skipHide: true\n });\n };\n \n return timePicker;\n }];\n});\n\nmodule.directive(\"mdpTimePicker\", [\"$mdpTimePicker\", \"$timeout\", function($mdpTimePicker, $timeout) {\n return {\n restrict: 'E',\n require: 'ngModel',\n transclude: true,\n template: function(element, attrs) {\n var noFloat = angular.isDefined(attrs.mdpNoFloat),\n placeholder = angular.isDefined(attrs.mdpPlaceholder) ? attrs.mdpPlaceholder : \"\",\n openOnClick = angular.isDefined(attrs.mdpOpenOnClick) ? true : false;\n \n return '
' +\n '' +\n '' +\n '' +\n '' +\n '' +\n '' +\n '
';\n },\n scope: {\n \"timeFormat\": \"@mdpFormat\",\n \"placeholder\": \"@mdpPlaceholder\",\n \"autoSwitch\": \"=?mdpAutoSwitch\",\n \"disabled\": \"=?mdpDisabled\"\n },\n link: function(scope, element, attrs, ngModel, $transclude) {\n var inputElement = angular.element(element[0].querySelector('input')),\n inputContainer = angular.element(element[0].querySelector('md-input-container')),\n inputContainerCtrl = inputContainer.controller(\"mdInputContainer\");\n \n $transclude(function(clone) {\n inputContainer.append(clone); \n });\n \n var messages = angular.element(inputContainer[0].querySelector(\"[ng-messages]\"));\n \n scope.type = scope.timeFormat ? \"text\" : \"time\"\n scope.timeFormat = scope.timeFormat || \"HH:mm\";\n scope.autoSwitch = scope.autoSwitch || false;\n \n scope.$watch(function() { return ngModel.$error }, function(newValue, oldValue) {\n inputContainerCtrl.setInvalid(!ngModel.$pristine && !!Object.keys(ngModel.$error).length);\n }, true);\n \n // update input element if model has changed\n ngModel.$formatters.unshift(function(value) {\n var time = angular.isDate(value) && moment(value);\n if(time && time.isValid()) \n updateInputElement(time.format(scope.timeFormat));\n else\n updateInputElement(null);\n });\n \n ngModel.$validators.format = function(modelValue, viewValue) {\n return !viewValue || angular.isDate(viewValue) || moment(viewValue, scope.timeFormat, true).isValid();\n };\n \n ngModel.$validators.required = function(modelValue, viewValue) {\n return angular.isUndefined(attrs.required) || !ngModel.$isEmpty(modelValue) || !ngModel.$isEmpty(viewValue);\n };\n \n ngModel.$parsers.unshift(function(value) {\n var parsed = moment(value, scope.timeFormat, true);\n if(parsed.isValid()) {\n if(angular.isDate(ngModel.$modelValue)) {\n var originalModel = moment(ngModel.$modelValue);\n originalModel.minutes(parsed.minutes());\n originalModel.hours(parsed.hours());\n originalModel.seconds(parsed.seconds());\n \n parsed = originalModel;\n }\n return parsed.toDate(); \n } else\n return null;\n });\n \n // update input element value\n function updateInputElement(value) {\n inputElement[0].value = value;\n inputContainerCtrl.setHasValue(!ngModel.$isEmpty(value));\n }\n \n function updateTime(time) {\n var value = moment(time, angular.isDate(time) ? null : scope.timeFormat, true),\n strValue = value.format(scope.timeFormat);\n\n if(value.isValid()) {\n updateInputElement(strValue);\n ngModel.$setViewValue(strValue);\n } else {\n updateInputElement(time);\n ngModel.$setViewValue(time);\n }\n \n if(!ngModel.$pristine && \n messages.hasClass(\"md-auto-hide\") && \n inputContainer.hasClass(\"md-input-invalid\")) messages.removeClass(\"md-auto-hide\");\n \n ngModel.$render();\n }\n \n scope.showPicker = function(ev) {\n $mdpTimePicker(ngModel.$modelValue, {\n targetEvent: ev,\n autoSwitch: scope.autoSwitch\n }).then(function(time) {\n updateTime(time, true);\n });\n };\n \n function onInputElementEvents(event) {\n if(event.target.value !== ngModel.$viewVaue)\n updateTime(event.target.value);\n }\n \n inputElement.on(\"reset input blur\", onInputElementEvents);\n \n scope.$on(\"$destroy\", function() {\n inputElement.off(\"reset input blur\", onInputElementEvents);\n })\n }\n };\n}]);\n\nmodule.directive(\"mdpTimePicker\", [\"$mdpTimePicker\", \"$timeout\", function($mdpTimePicker, $timeout) {\n return {\n restrict: 'A',\n require: 'ngModel',\n scope: {\n \"timeFormat\": \"@mdpFormat\",\n \"autoSwitch\": \"=?mdpAutoSwitch\",\n },\n link: function(scope, element, attrs, ngModel, $transclude) {\n scope.format = scope.format || \"HH:mm\";\n function showPicker(ev) {\n $mdpTimePicker(ngModel.$modelValue, {\n targetEvent: ev,\n autoSwitch: scope.autoSwitch\n }).then(function(time) {\n ngModel.$setViewValue(moment(time).format(scope.format));\n ngModel.$render();\n });\n };\n \n element.on(\"click\", showPicker);\n \n scope.$on(\"$destroy\", function() {\n element.off(\"click\", showPicker);\n });\n }\n }\n}]);\n\n})();"],"sourceRoot":"/source/"} \ No newline at end of file +{"version":3,"sources":["mdPickers.min.js"],"names":["TimePickerCtrl","$scope","$mdDialog","time","autoSwitch","$mdMedia","self","this","VIEW_HOURS","VIEW_MINUTES","currentView","moment","clockHours","parseInt","format","clockMinutes","minutes","switchView","setAM","hours","hour","setPM","cancel","confirm","hide","toDate","ClockCtrl","TYPE_HOURS","TYPE_MINUTES","STEP_DEG","steps","CLOCK_TYPES","range","getPointerStyle","divider","type","degrees","Math","round","selected","-webkit-transform","-ms-transform","transform","setTimeByDeg","deg","setTime","init","i","push","DatePickerCtrl","$timeout","currentDate","options","date","minDate","isValid","maxDate","displayFormat","dateFilter","angular","isFunction","selectingYear","isBefore","add","isAfter","yearItems","currentIndex_","PAGE_SIZE","START","year","END","getItemAtIndex","index","getLength","min","floor","abs","selectYear","animate","showYear","yearTopIndex","showCalendar","animating","noop","then","CalendarCtrl","dow","localeData","firstDayOfWeek","weekDays","concat","weekdaysMin","slice","daysInMonth","getDaysInMonth","days","firstDay","day","length","arr","value","enabled","isDayEnabled","selectDate","dom","nextMonth","prevMonth","subtract","updateDaysInMonth","$watch","unix","newValue","oldValue","formatValidator","isDate","minDateValidator","isSameOrAfter","maxDateValidator","isSameOrBefore","filterValidator","filter","module","config","$mdIconProvider","mdpIconsRegistry","forEach","icon","id","url","run","$templateCache","put","svg","constant","directive","$mdUtil","restrict","priority","compile","element","inputContainer","getClosest","toggleClass","$animate","bindToController","replace","template","controller","controllerAs","link","scope","attrs","ctrl","timepickerCtrl","querySelector","$parent","timepicker","onEvent","event","containerCoords","currentTarget","getClientRects","x","offsetWidth","pageX","left","y","pageY","top","offsetHeight","atan2","PI","indexOf","on","e","off","$on","provider","LABEL_OK","LABEL_CANCEL","setOKButtonLabel","label","setCancelButtonLabel","$get","timePicker","Date","now","isObject","show","clickOutsideToClose","targetEvent","locals","skipHide","$mdpTimePicker","require","transclude","noFloat","isDefined","mdpNoFloat","placeholder","mdpPlaceholder","openOnClick","mdpOpenOnClick","mdpDisabled","timeFormat","disabled","ngModel","$transclude","updateInputElement","inputElement","inputContainerCtrl","setHasValue","$isEmpty","updateTime","strValue","$setViewValue","$pristine","messages","hasClass","removeClass","$render","onInputElementEvents","target","$viewVaue","clone","append","$error","setInvalid","Object","keys","$formatters","unshift","$validators","modelValue","viewValue","required","isUndefined","$parsers","parsed","$modelValue","originalModel","seconds","showPicker","ev","DISPLAY_FORMAT","setDisplayFormat","datePicker","animElements","map","a","direction","addClass","$mdpDatePicker","dateFormat","pre","post","updateDate","model","isError","$invalid","month"],"mappings":"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","file":"mdPickers.min.js","sourcesContent":["(function() {\n\"use strict\";\n/* global moment, angular */\r\n\r\nvar module = angular.module(\"mdPickers\", [\r\n\t\"ngMaterial\",\r\n\t\"ngAnimate\",\r\n\t\"ngAria\"\r\n]);\r\n\r\nmodule.config([\"$mdIconProvider\", \"mdpIconsRegistry\", function($mdIconProvider, mdpIconsRegistry) {\r\n\tangular.forEach(mdpIconsRegistry, function(icon, index) {\r\n\t\t$mdIconProvider.icon(icon.id, icon.url);\r\n\t});\r\n}]);\r\n\r\nmodule.run([\"$templateCache\", \"mdpIconsRegistry\", function($templateCache, mdpIconsRegistry) {\r\n\tangular.forEach(mdpIconsRegistry, function(icon, index) {\r\n\t\t$templateCache.put(icon.url, icon.svg);\r\n\t});\r\n}]);\nmodule.constant(\"mdpIconsRegistry\", [\r\n {\r\n id: 'mdp-chevron-left',\r\n url: 'mdp-chevron-left.svg',\r\n svg: ''\r\n },\r\n {\r\n id: 'mdp-chevron-right',\r\n url: 'mdp-chevron-right.svg',\r\n svg: ''\r\n },\r\n {\r\n id: 'mdp-access-time',\r\n url: 'mdp-access-time.svg',\r\n svg: ''\r\n },\r\n {\r\n id: 'mdp-event',\r\n url: 'mdp-event.svg',\r\n svg: ''\r\n }\r\n]);\nmodule.directive(\"ngMessage\", [\"$mdUtil\", function($mdUtil) {\r\n return {\r\n restrict: \"EA\",\r\n priority: 101,\r\n compile: function(element) {\r\n var inputContainer = $mdUtil.getClosest(element, \"mdp-time-picker\", true) ||\r\n $mdUtil.getClosest(element, \"mdp-date-picker\", true);\r\n \r\n // If we are not a child of an input container, don't do anything\r\n if (!inputContainer) return;\r\n \r\n // Add our animation class\r\n element.toggleClass('md-input-message-animation', true);\r\n \r\n return {};\r\n }\r\n } \r\n}]);\n/* global moment, angular */\r\n\r\nfunction TimePickerCtrl($scope, $mdDialog, time, autoSwitch, $mdMedia) {\r\n\tvar self = this;\r\n this.VIEW_HOURS = 1;\r\n this.VIEW_MINUTES = 2;\r\n this.currentView = this.VIEW_HOURS;\r\n this.time = moment(time);\r\n this.autoSwitch = !!autoSwitch;\r\n \r\n this.clockHours = parseInt(this.time.format(\"h\"));\r\n this.clockMinutes = parseInt(this.time.minutes());\r\n \r\n\t$scope.$mdMedia = $mdMedia;\r\n\t\r\n\tthis.switchView = function() {\r\n\t self.currentView = self.currentView == self.VIEW_HOURS ? self.VIEW_MINUTES : self.VIEW_HOURS;\r\n\t};\r\n \r\n\tthis.setAM = function() {\r\n if(self.time.hours() >= 12)\r\n self.time.hour(self.time.hour() - 12);\r\n\t};\r\n \r\n this.setPM = function() {\r\n if(self.time.hours() < 12)\r\n self.time.hour(self.time.hour() + 12);\r\n\t};\r\n \r\n this.cancel = function() {\r\n $mdDialog.cancel();\r\n };\r\n\r\n this.confirm = function() {\r\n $mdDialog.hide(this.time.toDate());\r\n };\r\n}\r\n\r\nfunction ClockCtrl($scope) {\r\n var TYPE_HOURS = \"hours\";\r\n var TYPE_MINUTES = \"minutes\";\r\n var self = this;\r\n \r\n this.STEP_DEG = 360 / 12;\r\n this.steps = [];\r\n \r\n this.CLOCK_TYPES = {\r\n \"hours\": {\r\n range: 12,\r\n },\r\n \"minutes\": {\r\n range: 60,\r\n }\r\n }\r\n \r\n this.getPointerStyle = function() {\r\n var divider = 1;\r\n switch(self.type) {\r\n case TYPE_HOURS:\r\n divider = 12;\r\n break;\r\n case TYPE_MINUTES:\r\n divider = 60;\r\n break;\r\n } \r\n var degrees = Math.round(self.selected * (360 / divider)) - 180;\r\n return { \r\n \"-webkit-transform\": \"rotate(\" + degrees + \"deg)\",\r\n \"-ms-transform\": \"rotate(\" + degrees + \"deg)\",\r\n \"transform\": \"rotate(\" + degrees + \"deg)\"\r\n }\r\n };\r\n \r\n this.setTimeByDeg = function(deg) {\r\n deg = deg >= 360 ? 0 : deg;\r\n var divider = 0;\r\n switch(self.type) {\r\n case TYPE_HOURS:\r\n divider = 12;\r\n break;\r\n case TYPE_MINUTES:\r\n divider = 60;\r\n break;\r\n } \r\n \r\n self.setTime(\r\n Math.round(divider / 360 * deg)\r\n );\r\n };\r\n \r\n this.setTime = function(time, type) {\r\n this.selected = time;\r\n \r\n switch(self.type) {\r\n case TYPE_HOURS:\r\n if(self.time.format(\"A\") == \"PM\") time += 12;\r\n this.time.hours(time);\r\n break;\r\n case TYPE_MINUTES:\r\n if(time > 59) time -= 60;\r\n this.time.minutes(time);\r\n break;\r\n }\r\n \r\n };\r\n \r\n this.init = function() {\r\n self.type = self.type || \"hours\";\r\n switch(self.type) {\r\n case TYPE_HOURS:\r\n for(var i = 1; i <= 12; i++)\r\n self.steps.push(i);\r\n self.selected = self.time.hours() || 0;\r\n if(self.selected > 12) self.selected -= 12;\r\n \r\n break;\r\n case TYPE_MINUTES:\r\n for(var i = 5; i <= 55; i+=5)\r\n self.steps.push(i);\r\n self.steps.push(0);\r\n self.selected = self.time.minutes() || 0;\r\n \r\n break;\r\n }\r\n };\r\n \r\n this.init();\r\n}\r\n\r\nmodule.directive(\"mdpClock\", [\"$animate\", \"$timeout\", function($animate, $timeout) {\r\n return {\r\n restrict: 'E',\r\n bindToController: {\r\n 'type': '@?',\r\n 'time': '=',\r\n 'autoSwitch': '=?'\r\n },\r\n replace: true,\r\n template: '
' +\r\n '
' +\r\n '' +\r\n '' +\r\n '' +\r\n '' +\r\n '{{ step }}' +\r\n '
' +\r\n '
',\r\n controller: [\"$scope\", ClockCtrl],\r\n controllerAs: \"clock\",\r\n link: function(scope, element, attrs, ctrl) {\r\n var pointer = angular.element(element[0].querySelector(\".mdp-pointer\")),\r\n timepickerCtrl = scope.$parent.timepicker;\r\n \r\n var onEvent = function(event) {\r\n var containerCoords = event.currentTarget.getClientRects()[0];\r\n var x = ((event.currentTarget.offsetWidth / 2) - (event.pageX - containerCoords.left)),\r\n y = ((event.pageY - containerCoords.top) - (event.currentTarget.offsetHeight / 2));\r\n\r\n var deg = Math.round((Math.atan2(x, y) * (180 / Math.PI)));\r\n $timeout(function() {\r\n ctrl.setTimeByDeg(deg + 180);\r\n if(ctrl.autoSwitch && [\"mouseup\", \"click\"].indexOf(event.type) !== -1 && timepickerCtrl) timepickerCtrl.switchView();\r\n });\r\n }; \r\n \r\n element.on(\"mousedown\", function() {\r\n element.on(\"mousemove\", onEvent);\r\n });\r\n \r\n element.on(\"mouseup\", function(e) {\r\n element.off(\"mousemove\");\r\n });\r\n \r\n element.on(\"click\", onEvent);\r\n scope.$on(\"$destroy\", function() {\r\n element.off(\"click\", onEvent);\r\n element.off(\"mousemove\", onEvent); \r\n });\r\n }\r\n }\r\n}]);\r\n\r\nmodule.provider(\"$mdpTimePicker\", function() {\r\n var LABEL_OK = \"OK\",\r\n LABEL_CANCEL = \"Cancel\";\r\n \r\n this.setOKButtonLabel = function(label) {\r\n LABEL_OK = label;\r\n };\r\n \r\n this.setCancelButtonLabel = function(label) {\r\n LABEL_CANCEL = label;\r\n };\r\n \r\n this.$get = [\"$mdDialog\", function($mdDialog) {\r\n var timePicker = function(time, options) {\r\n if(!angular.isDate(time)) time = Date.now();\r\n if (!angular.isObject(options)) options = {};\r\n \r\n return $mdDialog.show({\r\n controller: ['$scope', '$mdDialog', 'time', 'autoSwitch', '$mdMedia', TimePickerCtrl],\r\n controllerAs: 'timepicker',\r\n clickOutsideToClose: true,\r\n template: '' +\r\n '' +\r\n '' +\r\n '
' +\r\n '{{ timepicker.time.format(\"h\") }}:' + \r\n '{{ timepicker.time.format(\"mm\") }}' +\r\n '
' +\r\n '
' + \r\n 'AM' +\r\n '= 12 }\">PM' +\r\n '
' + \r\n '
' +\r\n '
' +\r\n '
' +\r\n\t '' +\r\n\t '' +\r\n '
' +\r\n \r\n '' +\r\n\t \t'' +\r\n '' + LABEL_CANCEL + '' +\r\n '' + LABEL_OK + '' +\r\n '' +\r\n '
' +\r\n '
' +\r\n '
',\r\n targetEvent: options.targetEvent,\r\n locals: {\r\n time: time,\r\n autoSwitch: options.autoSwitch\r\n },\r\n skipHide: true\r\n });\r\n };\r\n \r\n return timePicker;\r\n }];\r\n});\r\n\r\nmodule.directive(\"mdpTimePicker\", [\"$mdpTimePicker\", \"$timeout\", function($mdpTimePicker, $timeout) {\r\n return {\r\n restrict: 'E',\r\n require: 'ngModel',\r\n transclude: true,\r\n template: function(element, attrs) {\r\n var noFloat = angular.isDefined(attrs.mdpNoFloat),\r\n placeholder = angular.isDefined(attrs.mdpPlaceholder) ? attrs.mdpPlaceholder : \"\",\r\n openOnClick = angular.isDefined(attrs.mdpOpenOnClick) ? true : false;\r\n \r\n return '
' +\r\n '' +\r\n '' +\r\n '' +\r\n '' +\r\n '' +\r\n '' +\r\n '
';\r\n },\r\n scope: {\r\n \"timeFormat\": \"@mdpFormat\",\r\n \"placeholder\": \"@mdpPlaceholder\",\r\n \"autoSwitch\": \"=?mdpAutoSwitch\",\r\n \"disabled\": \"=?mdpDisabled\"\r\n },\r\n link: function(scope, element, attrs, ngModel, $transclude) {\r\n var inputElement = angular.element(element[0].querySelector('input')),\r\n inputContainer = angular.element(element[0].querySelector('md-input-container')),\r\n inputContainerCtrl = inputContainer.controller(\"mdInputContainer\");\r\n \r\n $transclude(function(clone) {\r\n inputContainer.append(clone); \r\n });\r\n \r\n var messages = angular.element(inputContainer[0].querySelector(\"[ng-messages]\"));\r\n \r\n scope.type = scope.timeFormat ? \"text\" : \"time\"\r\n scope.timeFormat = scope.timeFormat || \"HH:mm\";\r\n scope.autoSwitch = scope.autoSwitch || false;\r\n \r\n scope.$watch(function() { return ngModel.$error }, function(newValue, oldValue) {\r\n inputContainerCtrl.setInvalid(!ngModel.$pristine && !!Object.keys(ngModel.$error).length);\r\n }, true);\r\n \r\n // update input element if model has changed\r\n ngModel.$formatters.unshift(function(value) {\r\n var time = angular.isDate(value) && moment(value);\r\n if(time && time.isValid()) \r\n updateInputElement(time.format(scope.timeFormat));\r\n else\r\n updateInputElement(null);\r\n });\r\n \r\n ngModel.$validators.format = function(modelValue, viewValue) {\r\n return !viewValue || angular.isDate(viewValue) || moment(viewValue, scope.timeFormat, true).isValid();\r\n };\r\n \r\n ngModel.$validators.required = function(modelValue, viewValue) {\r\n return angular.isUndefined(attrs.required) || !ngModel.$isEmpty(modelValue) || !ngModel.$isEmpty(viewValue);\r\n };\r\n \r\n ngModel.$parsers.unshift(function(value) {\r\n var parsed = moment(value, scope.timeFormat, true);\r\n if(parsed.isValid()) {\r\n if(angular.isDate(ngModel.$modelValue)) {\r\n var originalModel = moment(ngModel.$modelValue);\r\n originalModel.minutes(parsed.minutes());\r\n originalModel.hours(parsed.hours());\r\n originalModel.seconds(parsed.seconds());\r\n \r\n parsed = originalModel;\r\n }\r\n return parsed.toDate(); \r\n } else\r\n return null;\r\n });\r\n \r\n // update input element value\r\n function updateInputElement(value) {\r\n if (inputElement[0].value !== value) {\r\n inputElement[0].value = value;\r\n }\r\n inputContainerCtrl.setHasValue(!ngModel.$isEmpty(value));\r\n }\r\n \r\n function updateTime(time) {\r\n var value = moment(time, angular.isDate(time) ? null : scope.timeFormat, true),\r\n strValue = value.format(scope.timeFormat);\r\n\r\n if(value.isValid()) {\r\n updateInputElement(strValue);\r\n ngModel.$setViewValue(strValue);\r\n } else {\r\n updateInputElement(time);\r\n ngModel.$setViewValue(time);\r\n }\r\n \r\n if(!ngModel.$pristine && \r\n messages.hasClass(\"md-auto-hide\") && \r\n inputContainer.hasClass(\"md-input-invalid\")) messages.removeClass(\"md-auto-hide\");\r\n \r\n ngModel.$render();\r\n }\r\n \r\n scope.showPicker = function(ev) {\r\n $mdpTimePicker(ngModel.$modelValue, {\r\n targetEvent: ev,\r\n autoSwitch: scope.autoSwitch\r\n }).then(function(time) {\r\n updateTime(time, true);\r\n });\r\n };\r\n \r\n function onInputElementEvents(event) {\r\n if(event.target.value !== ngModel.$viewVaue)\r\n updateTime(event.target.value);\r\n }\r\n \r\n inputElement.on(\"reset input blur\", onInputElementEvents);\r\n \r\n scope.$on(\"$destroy\", function() {\r\n inputElement.off(\"reset input blur\", onInputElementEvents);\r\n })\r\n }\r\n };\r\n}]);\r\n\r\nmodule.directive(\"mdpTimePicker\", [\"$mdpTimePicker\", \"$timeout\", function($mdpTimePicker, $timeout) {\r\n return {\r\n restrict: 'A',\r\n require: 'ngModel',\r\n scope: {\r\n \"timeFormat\": \"@mdpFormat\",\r\n \"autoSwitch\": \"=?mdpAutoSwitch\",\r\n },\r\n link: function(scope, element, attrs, ngModel, $transclude) {\r\n scope.format = scope.format || \"HH:mm\";\r\n function showPicker(ev) {\r\n $mdpTimePicker(ngModel.$modelValue, {\r\n targetEvent: ev,\r\n autoSwitch: scope.autoSwitch\r\n }).then(function(time) {\r\n ngModel.$setViewValue(moment(time).format(scope.format));\r\n ngModel.$render();\r\n });\r\n };\r\n \r\n element.on(\"click\", showPicker);\r\n \r\n scope.$on(\"$destroy\", function() {\r\n element.off(\"click\", showPicker);\r\n });\r\n }\r\n }\r\n}]);\r\n\n/* global moment, angular */\r\n\r\nfunction DatePickerCtrl($scope, $mdDialog, $mdMedia, $timeout, currentDate, options) {\r\n var self = this;\r\n\r\n this.date = moment(currentDate);\r\n this.minDate = options.minDate && moment(options.minDate).isValid() ? moment(options.minDate) : null;\r\n this.maxDate = options.maxDate && moment(options.maxDate).isValid() ? moment(options.maxDate) : null;\r\n this.displayFormat = options.displayFormat || \"ddd, MMM DD\";\r\n this.dateFilter = angular.isFunction(options.dateFilter) ? options.dateFilter : null;\r\n this.selectingYear = false;\r\n \r\n // validate min and max date\r\n\tif (this.minDate && this.maxDate) {\r\n\t\tif (this.maxDate.isBefore(this.minDate)) {\r\n\t\t\tthis.maxDate = moment(this.minDate).add(1, 'days');\r\n\t\t}\r\n\t}\r\n\t\r\n\tif (this.date) {\r\n\t\t// check min date\r\n \tif (this.minDate && this.date.isBefore(this.minDate)) {\r\n\t\t\tthis.date = moment(this.minDate);\r\n \t}\r\n \t\r\n \t// check max date\r\n \tif (this.maxDate && this.date.isAfter(this.maxDate)) {\r\n\t\t\tthis.date = moment(this.maxDate);\r\n \t}\r\n\t}\r\n\t\r\n\tthis.yearItems = {\r\n currentIndex_: 0,\r\n PAGE_SIZE: 5,\r\n START: (self.minDate ? self.minDate.year() : 1900),\r\n END: (self.maxDate ? self.maxDate.year() : 0),\r\n getItemAtIndex: function(index) {\r\n \tif(this.currentIndex_ < index)\r\n this.currentIndex_ = index;\r\n \t\r\n \treturn this.START + index;\r\n },\r\n getLength: function() {\r\n return Math.min(\r\n this.currentIndex_ + Math.floor(this.PAGE_SIZE / 2),\r\n Math.abs(this.START - this.END) + 1\r\n );\r\n }\r\n };\r\n\r\n $scope.$mdMedia = $mdMedia;\r\n $scope.year = this.date.year();\r\n\r\n\tthis.selectYear = function(year) {\r\n self.date.year(year);\r\n $scope.year = year;\r\n self.selectingYear = false;\r\n self.animate();\r\n };\r\n \r\n this.showYear = function() { \r\n self.yearTopIndex = (self.date.year() - self.yearItems.START) + Math.floor(self.yearItems.PAGE_SIZE / 2);\r\n self.yearItems.currentIndex_ = (self.date.year() - self.yearItems.START) + 1;\r\n self.selectingYear = true;\r\n };\r\n \r\n this.showCalendar = function() {\r\n self.selectingYear = false;\r\n };\r\n\r\n this.cancel = function() {\r\n $mdDialog.cancel();\r\n };\r\n\r\n this.confirm = function() {\r\n \tvar date = this.date;\r\n \t\r\n \tif (this.minDate && this.date.isBefore(this.minDate)) {\r\n \t\tdate = moment(this.minDate);\r\n \t}\r\n \t\r\n \tif (this.maxDate && this.date.isAfter(this.maxDate)) {\r\n \t\tdate = moment(this.maxDate);\r\n \t} \t\r\n \t\r\n $mdDialog.hide(date.toDate());\r\n };\r\n \r\n this.animate = function() {\r\n self.animating = true;\r\n $timeout(angular.noop).then(function() {\r\n self.animating = false;\r\n }) \r\n };\r\n}\r\n\r\nmodule.provider(\"$mdpDatePicker\", function() {\r\n var LABEL_OK = \"OK\",\r\n LABEL_CANCEL = \"Cancel\",\r\n DISPLAY_FORMAT = \"ddd, MMM DD\";\r\n \r\n this.setDisplayFormat = function(format) {\r\n DISPLAY_FORMAT = format; \r\n };\r\n \r\n this.setOKButtonLabel = function(label) {\r\n LABEL_OK = label;\r\n };\r\n \r\n this.setCancelButtonLabel = function(label) {\r\n LABEL_CANCEL = label;\r\n };\r\n \r\n this.$get = [\"$mdDialog\", function($mdDialog) {\r\n var datePicker = function(currentDate, options) {\r\n if (!angular.isDate(currentDate)) currentDate = Date.now();\r\n if (!angular.isObject(options)) options = {};\r\n \r\n options.displayFormat = DISPLAY_FORMAT;\r\n \r\n return $mdDialog.show({\r\n controller: ['$scope', '$mdDialog', '$mdMedia', '$timeout', 'currentDate', 'options', DatePickerCtrl],\r\n controllerAs: 'datepicker',\r\n clickOutsideToClose: true,\r\n template: '' +\r\n '' +\r\n '
' +\r\n '' +\r\n '{{ datepicker.date.format(\\'YYYY\\') }}' +\r\n '{{ datepicker.date.format(datepicker.displayFormat) }} ' +\r\n '' + \r\n '
' + \r\n '
' + \r\n '
' +\r\n '' +\r\n '
' +\r\n '{{ item }}' +\r\n '
' +\r\n '
' +\r\n '
' +\r\n '' +\r\n '' +\r\n \t'' +\r\n '' + LABEL_CANCEL + '' +\r\n '' + LABEL_OK + '' +\r\n '' +\r\n '
' +\r\n '
' +\r\n '
',\r\n targetEvent: options.targetEvent,\r\n locals: {\r\n currentDate: currentDate,\r\n options: options\r\n },\r\n skipHide: true\r\n });\r\n };\r\n \r\n return datePicker;\r\n }];\r\n});\r\n\r\nfunction CalendarCtrl($scope) {\r\n\tvar self = this;\r\n\tthis.dow = moment.localeData().firstDayOfWeek();\r\n\t\r\n this.weekDays = [].concat(\r\n moment.weekdaysMin().slice(\r\n this.dow\r\n ),\r\n moment.weekdaysMin().slice(\r\n 0, \r\n this.dow\r\n )\r\n );\r\n \r\n this.daysInMonth = [];\r\n \r\n this.getDaysInMonth = function() {\r\n var days = self.date.daysInMonth(),\r\n firstDay = moment(self.date).date(1).day() - this.dow;\r\n \r\n if(firstDay < 0) firstDay = this.weekDays.length - 1;\r\n \r\n\r\n var arr = [];\r\n for(var i = 1; i <= (firstDay + days); i++) {\r\n var day = null;\r\n if(i > firstDay) {\r\n day = {\r\n value: (i - firstDay),\r\n enabled: self.isDayEnabled(moment(self.date).date(i - firstDay).toDate())\r\n };\r\n }\r\n arr.push(day);\r\n }\r\n \r\n return arr;\r\n };\r\n \r\n this.isDayEnabled = function(day) {\r\n return (!this.minDate || this.minDate <= day) && \r\n (!this.maxDate || this.maxDate >= day) && \r\n (!self.dateFilter || !self.dateFilter(day));\r\n };\r\n \r\n this.selectDate = function(dom) {\r\n self.date.date(dom);\r\n };\r\n\r\n this.nextMonth = function() {\r\n self.date.add(1, 'months');\r\n };\r\n\r\n this.prevMonth = function() {\r\n self.date.subtract(1, 'months');\r\n };\r\n \r\n this.updateDaysInMonth = function() {\r\n self.daysInMonth = self.getDaysInMonth();\r\n };\r\n \r\n $scope.$watch(function() { return self.date.unix() }, function(newValue, oldValue) {\r\n if(newValue && newValue !== oldValue)\r\n self.updateDaysInMonth();\r\n })\r\n \r\n self.updateDaysInMonth();\r\n}\r\n\r\nmodule.directive(\"mdpCalendar\", [\"$animate\", function($animate) {\r\n return {\r\n restrict: 'E',\r\n bindToController: {\r\n \"date\": \"=\",\r\n \"minDate\": \"=\",\r\n \"maxDate\": \"=\",\r\n \"dateFilter\": \"=\"\r\n },\r\n template: '
' +\r\n '
' +\r\n '' +\r\n '
{{ calendar.date.format(\"MMMM YYYY\") }}
' +\r\n '' +\r\n '
' +\r\n '
' +\r\n '
{{ d }}
' +\r\n '
' +\r\n '
' +\r\n '
' +\r\n '{{ day.value }}' +\r\n '
' +\r\n '
' +\r\n '
' +\r\n '
',\r\n controller: [\"$scope\", CalendarCtrl],\r\n controllerAs: \"calendar\",\r\n link: function(scope, element, attrs, ctrl) {\r\n var animElements = [\r\n element[0].querySelector(\".mdp-calendar-week-days\"),\r\n element[0].querySelector('.mdp-calendar-days'),\r\n element[0].querySelector('.mdp-calendar-monthyear')\r\n ].map(function(a) {\r\n return angular.element(a); \r\n });\r\n \r\n scope.$watch(function() { return ctrl.date.format(\"YYYYMM\") }, function(newValue, oldValue) {\r\n var direction = null;\r\n \r\n if(newValue > oldValue)\r\n direction = \"mdp-animate-next\";\r\n else if(newValue < oldValue)\r\n direction = \"mdp-animate-prev\";\r\n \r\n if(direction) {\r\n for(var i in animElements) {\r\n animElements[i].addClass(direction);\r\n $animate.removeClass(animElements[i], direction);\r\n }\r\n }\r\n });\r\n }\r\n }\r\n}]);\r\n\r\nfunction formatValidator(value, format) {\r\n return !value || angular.isDate(value) || moment(value, format, true).isValid();\r\n}\r\n\r\nfunction minDateValidator(value, format, minDate) {\r\n var minDate = moment(minDate, \"YYYY-MM-DD\", true);\r\n var date = angular.isDate(value) ? moment(value) : moment(value, format, true);\r\n \r\n return !value || \r\n angular.isDate(value) || \r\n !minDate.isValid() || \r\n date.isSameOrAfter(minDate);\r\n}\r\n\r\nfunction maxDateValidator(value, format, maxDate) {\r\n var maxDate = moment(maxDate, \"YYYY-MM-DD\", true);\r\n var date = angular.isDate(value) ? moment(value) : moment(value, format, true);\r\n \r\n return !value || \r\n angular.isDate(value) || \r\n !maxDate.isValid() || \r\n date.isSameOrBefore(maxDate);\r\n}\r\n\r\nfunction filterValidator(value, format, filter) {\r\n var date = angular.isDate(value) ? moment(value) : moment(value, format, true);\r\n \r\n return !value || \r\n angular.isDate(value) || \r\n !angular.isFunction(filter) || \r\n !filter(date);\r\n}\r\n\r\nfunction requiredValidator(value, ngModel) {\r\n return value\r\n}\r\n\r\nmodule.directive(\"mdpDatePicker\", [\"$mdpDatePicker\", \"$timeout\", function($mdpDatePicker, $timeout) {\r\n return {\r\n restrict: 'E',\r\n require: 'ngModel',\r\n transclude: true,\r\n template: function(element, attrs) {\r\n var noFloat = angular.isDefined(attrs.mdpNoFloat),\r\n placeholder = angular.isDefined(attrs.mdpPlaceholder) ? attrs.mdpPlaceholder : \"\",\r\n openOnClick = angular.isDefined(attrs.mdpOpenOnClick) ? true : false;\r\n \r\n return '
' +\r\n '' +\r\n '' +\r\n '' +\r\n '' +\r\n '' +\r\n '' +\r\n '
';\r\n },\r\n scope: {\r\n \"minDate\": \"=mdpMinDate\",\r\n \"maxDate\": \"=mdpMaxDate\",\r\n \"dateFilter\": \"=mdpDateFilter\",\r\n \"dateFormat\": \"@mdpFormat\",\r\n \"placeholder\": \"@mdpPlaceholder\",\r\n \"noFloat\": \"=mdpNoFloat\",\r\n \"openOnClick\": \"=mdpOpenOnClick\",\r\n \"disabled\": \"=?mdpDisabled\"\r\n },\r\n link: {\r\n pre: function(scope, element, attrs, ngModel, $transclude) {\r\n \r\n },\r\n post: function(scope, element, attrs, ngModel, $transclude) {\r\n var inputElement = angular.element(element[0].querySelector('input')),\r\n inputContainer = angular.element(element[0].querySelector('md-input-container')),\r\n inputContainerCtrl = inputContainer.controller(\"mdInputContainer\");\r\n \r\n $transclude(function(clone) {\r\n inputContainer.append(clone); \r\n }); \r\n \r\n var messages = angular.element(inputContainer[0].querySelector(\"[ng-messages]\"));\r\n \r\n scope.type = scope.dateFormat ? \"text\" : \"date\"\r\n scope.dateFormat = scope.dateFormat || \"YYYY-MM-DD\";\r\n scope.model = ngModel;\r\n \r\n scope.isError = function() {\r\n return !ngModel.$pristine && !!ngModel.$invalid;\r\n };\r\n \r\n // update input element if model has changed\r\n ngModel.$formatters.unshift(function(value) {\r\n var date = angular.isDate(value) && moment(value);\r\n if(date && date.isValid()) \r\n updateInputElement(date.format(scope.dateFormat));\r\n else\r\n updateInputElement(null);\r\n });\r\n \r\n ngModel.$validators.format = function(modelValue, viewValue) {\r\n return formatValidator(viewValue, scope.dateFormat);\r\n };\r\n \r\n ngModel.$validators.minDate = function(modelValue, viewValue) {\r\n return minDateValidator(viewValue, scope.dateFormat, scope.minDate);\r\n };\r\n \r\n ngModel.$validators.maxDate = function(modelValue, viewValue) {\r\n return maxDateValidator(viewValue, scope.dateFormat, scope.maxDate);\r\n };\r\n \r\n ngModel.$validators.filter = function(modelValue, viewValue) {\r\n return filterValidator(viewValue, scope.dateFormat, scope.dateFilter);\r\n };\r\n \r\n ngModel.$validators.required = function(modelValue, viewValue) {\r\n return angular.isUndefined(attrs.required) || !ngModel.$isEmpty(modelValue) || !ngModel.$isEmpty(viewValue);\r\n };\r\n \r\n ngModel.$parsers.unshift(function(value) {\r\n var parsed = moment(value, scope.dateFormat, true);\r\n if(parsed.isValid()) {\r\n if(angular.isDate(ngModel.$modelValue)) {\r\n var originalModel = moment(ngModel.$modelValue);\r\n originalModel.year(parsed.year());\r\n originalModel.month(parsed.month());\r\n originalModel.date(parsed.date());\r\n \r\n parsed = originalModel;\r\n }\r\n return parsed.toDate(); \r\n } else\r\n return null;\r\n });\r\n \r\n // update input element value\r\n function updateInputElement(value) {\r\n inputElement[0].value = value;\r\n inputContainerCtrl.setHasValue(!ngModel.$isEmpty(value));\r\n }\r\n \r\n function updateDate(date) {\r\n var value = moment(date, angular.isDate(date) ? null : scope.dateFormat, true),\r\n strValue = value.format(scope.dateFormat);\r\n \r\n if(value.isValid()) {\r\n updateInputElement(strValue);\r\n ngModel.$setViewValue(strValue);\r\n } else {\r\n updateInputElement(date);\r\n ngModel.$setViewValue(date);\r\n }\r\n \r\n if(!ngModel.$pristine && \r\n messages.hasClass(\"md-auto-hide\") && \r\n inputContainer.hasClass(\"md-input-invalid\")) messages.removeClass(\"md-auto-hide\");\r\n \r\n ngModel.$render();\r\n }\r\n \r\n scope.showPicker = function(ev) {\r\n $mdpDatePicker(ngModel.$modelValue, {\r\n \t minDate: scope.minDate, \r\n \t maxDate: scope.maxDate,\r\n \t dateFilter: scope.dateFilter,\r\n \t targetEvent: ev\r\n \t }).then(updateDate);\r\n };\r\n \r\n function onInputElementEvents(event) {\r\n if(event.target.value !== ngModel.$viewVaue)\r\n updateDate(event.target.value);\r\n }\r\n \r\n inputElement.on(\"reset input blur\", onInputElementEvents);\r\n \r\n scope.$on(\"$destroy\", function() {\r\n inputElement.off(\"reset input blur\", onInputElementEvents);\r\n });\r\n }\r\n }\r\n };\r\n}]);\r\n\r\n\r\nmodule.directive(\"mdpDatePicker\", [\"$mdpDatePicker\", \"$timeout\", function($mdpDatePicker, $timeout) {\r\n return {\r\n restrict: 'A',\r\n require: 'ngModel',\r\n scope: {\r\n \"minDate\": \"@min\",\r\n \"maxDate\": \"@max\",\r\n \"dateFilter\": \"=mdpDateFilter\",\r\n \"dateFormat\": \"@mdpFormat\",\r\n },\r\n link: function(scope, element, attrs, ngModel, $transclude) {\r\n scope.dateFormat = scope.dateFormat || \"YYYY-MM-DD\";\r\n \r\n ngModel.$validators.format = function(modelValue, viewValue) {\r\n return formatValidator(viewValue, scope.format);\r\n };\r\n \r\n ngModel.$validators.minDate = function(modelValue, viewValue) {\r\n return minDateValidator(viewValue, scope.format, scope.minDate);\r\n };\r\n \r\n ngModel.$validators.maxDate = function(modelValue, viewValue) {\r\n return maxDateValidator(viewValue, scope.format, scope.maxDate);\r\n };\r\n \r\n ngModel.$validators.filter = function(modelValue, viewValue) {\r\n return filterValidator(viewValue, scope.format, scope.dateFilter);\r\n };\r\n \r\n function showPicker(ev) {\r\n $mdpDatePicker(ngModel.$modelValue, {\r\n \t minDate: scope.minDate, \r\n \t maxDate: scope.maxDate,\r\n \t dateFilter: scope.dateFilter,\r\n \t targetEvent: ev\r\n \t }).then(function(time) {\r\n ngModel.$setViewValue(moment(time).format(scope.format));\r\n ngModel.$render();\r\n });\r\n };\r\n \r\n element.on(\"click\", showPicker);\r\n \r\n scope.$on(\"$destroy\", function() {\r\n element.off(\"click\", showPicker);\r\n });\r\n }\r\n }\r\n}]);\n})();"]} \ No newline at end of file diff --git a/src/components/mdpTimePicker/mdpTimePicker.js b/src/components/mdpTimePicker/mdpTimePicker.js index 249ea008..16bb7dcd 100644 --- a/src/components/mdpTimePicker/mdpTimePicker.js +++ b/src/components/mdpTimePicker/mdpTimePicker.js @@ -319,7 +319,9 @@ module.directive("mdpTimePicker", ["$mdpTimePicker", "$timeout", function($mdpTi // update input element value function updateInputElement(value) { - inputElement[0].value = value; + if (inputElement[0].value !== value) { + inputElement[0].value = value; + } inputContainerCtrl.setHasValue(!ngModel.$isEmpty(value)); }