var app = angular.module('plunker', ['ngMaterial', 'ngMaterialDatePicker']);
app.controller('MainCtrl', function($scope) {
var ctrl = this;
ctrl.$onInit = function() {
ctrl.maxDate = moment().hours(12).minutes(50).seconds(0);
ctrl.secondDate = moment().hours(11).minutes(0).seconds(0);
};
});
<!DOCTYPE html>
<html ng-app="plunker">
<head>
<meta charset="utf-8" />
<title>AngularJS Plunker</title>
<script>document.write('<base href="' + document.location + '" />');</script>
<link rel="stylesheet" href="style.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.2/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.2/angular-animate.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.2/angular-aria.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/angular-material/1.1.10/angular-material.min.css" rel="stylesheet" type="text/css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-material/1.1.10/angular-material.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.22.2/moment-with-locales.min.js"></script>
<script src="https://unpkg.com/ng-material-datetimepicker@1.17.1/dist/angular-material-datetimepicker.min.js"></script>
<script src="https://unpkg.com/ng-material-datetimepicker@1.17.1/dist/angular-material-datetimepicker.min.js.map"></script>
<link href="https://unpkg.com/ng-material-datetimepicker@1.17.1/dist/material-datetimepicker.min.css" rel="stylesheet" type="text/css">
<script src="app.js"></script>
</head>
<body ng-controller="MainCtrl as $ctrl">
<h1>Max Date Broken</h1>
<p>In this example, the "Second Date" input has a max-date of the "Max Date." You cannot set the value of the second date to 12pm, even though it is a valid value and less than the max-date. You can change the hour to 12, but then the PM button continues to be disabled.</p>
<div
layout-gt-sm="row"
layout="column"
layout-align-gt-sm="start center"
layout-wrap>
<div flex-gt-sm="50">
<md-input-container class="md-block">
<label>Max Date</label>
<input mdc-datetime-picker
date="false"
time="true"
short-time="true"
type="text"
id="timez"
format="MMM D, YYYY h:mm a Z"
ng-model="$ctrl.maxDate">
</md-input-container>
</div>
<div flex-gt-sm="50">
<md-input-container class="md-block">
<label>Second Date</label>
<input mdc-datetime-picker
date="false"
time="true"
short-time="true"
type="text"
id="timez"
format="MMM D, YYYY h:mm a Z"
ng-model="$ctrl.secondDate"
max-date="$ctrl.maxDate">
</md-input-container>
</div>
</div>
</body>
</html>
/* Put your css in here */
(function () {
'use strict';
function ngMaterialDatePicker(moment) {
var moduleName = "ngMaterialDatePicker";
var mdAccesTime = 'data:image/svg+xml;base64,PHN2ZyBmaWxsPSIjMDAwMDAwIiBoZWlnaHQ9IjI0IiB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4gICAgPHBhdGggZD0iTTExLjk5IDJDNi40NyAyIDIgNi40OCAyIDEyczQuNDcgMTAgOS45OSAxMEMxNy41MiAyMiAyMiAxNy41MiAyMiAxMlMxNy41MiAyIDExLjk5IDJ6TTEyIDIwYy00LjQyIDAtOC0zLjU4LTgtOHMzLjU4LTggOC04IDggMy41OCA4IDgtMy41OCA4LTggOHoiLz4gICAgPHBhdGggZD0iTTAgMGgyNHYyNEgweiIgZmlsbD0ibm9uZSIvPiAgICA8cGF0aCBkPSJNMTIuNSA3SDExdjZsNS4yNSAzLjE1Ljc1LTEuMjMtNC41LTIuNjd6Ii8+PC9zdmc+',
mdCalendar = 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0Ij48cGF0aCBkPSJNMTkgM2gtMVYxaC0ydjJIOFYxSDZ2Mkg1Yy0xLjExIDAtMS45OS45LTEuOTkgMkwzIDE5YzAgMS4xLjg5IDIgMiAyaDE0YzEuMSAwIDItLjkgMi0yVjVjMC0xLjEtLjktMi0yLTJ6bTAgMTZINVY4aDE0djExek03IDEwaDV2NUg3eiIvPjwvc3ZnPg==';
var VIEW_STATES = {DATE: 0, HOUR: 1, MINUTE: 2};
var css = function (el, name) {
el = angular.element(el);
return ('getComputedStyle' in window) ? window.getComputedStyle(el[0])[name] : el.css(name);
};
var template =
'<md-dialog class="dtp" layout="column">' +
' <md-dialog-content class="dtp-content">' +
' <div class="dtp-date-view">' +
' <header class="dtp-header">' +
' <div class="dtp-actual-day" ng-if="picker.dateMode">{{picker.currentNearestMinute().format("dddd")}}</div>' +
' <div class="dtp-actual-day" ng-if="!picker.timeMode">{{picker.params.shortTime ? picker.currentDate.format("A"):" "}}</div>' +
' <div class="dtp-close text-right noselect">' +
' <a href="#" mdc-dtp-noclick ng-click="picker.hide()">×</a>' +
' </div>' +
' </header>' +
' <div class="dtp-date" ng-if="picker.params.date">' +
' <div layout="row">' +
' <div ng-click="picker.incrementMonth(-1)" class="dtp-month-btn dtp-month-btn-prev noselect" flex="30"><span ng-if="picker.isPreviousMonthVisible()">◄</span></div>' +
' <md-menu md-offset="8 10" flex>' +
' <div class="dtp-actual-month" flex ng-click="picker.openMenu($mdMenu, $event)">{{picker.currentDate.format("MMM") | uppercase}}</div>' +
' <md-menu-content>' +
' <md-menu-item ng-repeat="itemMonth in picker.monthsAvailable() track by $index">' +
' <md-button ng-click="picker.selectMonth(itemMonth)">{{itemMonth}}</md-button>' +
' </md-menu-item>' +
' </md-menu-content>' +
' </md-menu>' +
' <div ng-click="picker.incrementMonth(1)" class="dtp-month-btn dtp-month-btn-next noselect" flex="30"><span ng-if="picker.isNextMonthVisible()">►</span></div>' +
' </div>' +
' <div class="dtp-actual-num">{{picker.currentDate.format("DD")}}</div>' +
' <div layout="row">' +
' <div ng-click="picker.incrementYear(-1)" class="dtp-year-btn dtp-year-btn-prev noselect" flex="30"><span ng-if="picker.isPreviousYearVisible()">◄</span></div>' +
' <md-menu md-offset="8 10" flex>' +
' <div class="dtp-actual-year" flex ng-click="picker.openMenu($mdMenu, $event)">{{picker.currentDate.format("YYYY")}}</div>' +
' <md-menu-content>' +
' <md-menu-item ng-repeat="itemYear in picker.yearsAvailable() track by $index">' +
' <md-button ng-click="picker.selectYear(itemYear)">{{itemYear}}</md-button>' +
' </md-menu-item>' +
' </md-menu-content>' +
' </md-menu>' +
' <div ng-click="picker.incrementYear(1)" class="dtp-year-btn dtp-year-btn-next noselect" flex="30"><span ng-if="picker.isNextYearVisible()">►</span></div>' +
' </div>'+
' </div>' + //start time
' <div class="dtp-time" ng-if="picker.params.time && !picker.params.date">' +
' <div class="dtp-actual-maxtime">' +
' <span ng-if="!picker.params.seconds"><span ng-class="{selected: picker.currentView===picker.VIEWS.HOUR}">{{picker.currentNearestMinute().format(picker.params.shortTime ? "hh":"HH")}}</span>:<span ng-class="{selected: picker.currentView===picker.VIEWS.MINUTE}">{{picker.currentNearestMinute().format("mm")}}</span></span>'+
' <span ng-if="picker.params.seconds"><span ng-class="{selected: picker.currentView===picker.VIEWS.HOUR}">{{picker.currentNearestMinute().format(picker.params.shortTime ? "hh":"HH")}}</span>:<span ng-class="{selected: picker.currentView===picker.VIEWS.MINUTE}">{{picker.currentNearestMinute().format("mm")}}</span>:<span ng-class="{selected: picker.currentView===picker.VIEWS.SECOND}">{{picker.currentNearestMinute().format("ss")}}</span></span>'+
' <span class="dtp-actual-meridien" ng-if="picker.params.shortTime">{{picker.currentDate.format("A")}}</span>'+
' </div>' +
' </div>' +
' <div class="dtp-picker">' +
' <mdc-datetime-picker-calendar date="picker.currentDate" picker="picker" class="dtp-picker-calendar" ng-if="picker.currentView === picker.VIEWS.DATE"></mdc-datetime-picker-calendar>' +
' <div class="dtp-picker-datetime" ng-cloak ng-if="picker.currentView !== picker.VIEWS.DATE">' +
' <div class="dtp-actual-meridien">' +
' <div ng-if="picker.params.shortTime" class="left p20">' +
' <a id="time-periods-am" href="#" mdc-dtp-noclick class="dtp-meridien-am" ng-class="{selected: picker.meridien===\'AM\'}" ng-click="picker.selectAM()">{{picker.params.amText}}</a>' +
' </div>' +
' <div ng-if="!picker.timeMode && !picker.params.seconds" class="dtp-actual-time p60">' +
' <span ng-class="{selected: picker.currentView===picker.VIEWS.HOUR}">{{picker.currentNearestMinute().format(picker.params.shortTime ? "hh":"HH")}}</span>:<span ng-class="{selected: picker.currentView===picker.VIEWS.MINUTE}">{{picker.currentNearestMinute().format("mm")}}</span>' +
' </div>' +
' <div ng-if="!picker.timeMode && picker.params.seconds" class="dtp-actual-time p60">' +
' <span ng-class="{selected: picker.currentView===picker.VIEWS.HOUR}">{{picker.currentNearestMinute().format(picker.params.shortTime ? "hh":"HH")}}</span>:<span ng-class="{selected: picker.currentView===picker.VIEWS.MINUTE}">{{picker.currentNearestMinute().format("mm")}}</span>:<span ng-class="{selected: picker.currentView===picker.VIEWS.SECOND}">{{picker.currentNearestMinute().format("ss")}}</span>' +
' </div>' +
' <div ng-if="picker.params.shortTime" class="right p20">' +
' <a id="time-periods-pm" href="#" mdc-dtp-noclick class="dtp-meridien-pm" ng-class="{selected: picker.meridien===\'PM\'}" ng-click="picker.selectPM()">{{picker.params.pmText}}</a>' +
' </div>' +
' <div class="clearfix"></div>' +
' </div>' +
' <mdc-datetime-picker-clock mode="hours" ng-if="picker.currentView===picker.VIEWS.HOUR"></mdc-datetime-picker-clock>' +
' <mdc-datetime-picker-clock mode="minutes" ng-if="picker.currentView===picker.VIEWS.MINUTE"></mdc-datetime-picker-clock>' +
' <mdc-datetime-picker-clock mode="seconds" ng-if="picker.currentView===picker.VIEWS.SECOND"></mdc-datetime-picker-clock>' +
' </div>' +
' </div>' +
' </div>' +
' </md-dialog-content>' +
' <md-dialog-actions class="dtp-buttons">' +
' <md-button class="dtp-btn-today md-button" ng-click="picker.today()"> {{picker.params.todayText}}</md-button>' +
' <md-button class="dtp-btn-cancel md-button" ng-click="picker.cancel()"> {{picker.params.cancelText}}</md-button>' +
' <md-button class="dtp-btn-ok md-button" ng-click="picker.ok()"> {{picker.params.okText}}</md-button>' +
' </md-dialog-actions>' +
'</md-dialog>';
angular.module(moduleName, ['ngMaterial'])
.service('mdcDatetimePickerDefaultLocale', ['mdcDefaultParams', function (mdcDefaultParams) {
this.$get = function () {
console.log("mdcDatetimePickerDefaultLocale deprecated!");
return mdcDefaultParams().lang;
};
this.setDefaultLocale = function (localeString) {
console.log("mdcDatetimePickerDefaultLocale deprecated!");
mdcDefaultParams({ lang: localeString });
};
}])
.factory('mdcDefaultParams', function () {
var default_params = {
date: true,
time: true,
minutes: true,
seconds: false,
format: 'YYYY-MM-DD',
minDate: null,
maxDate: null,
currentDate: null,
lang: window.navigator.userLanguage || window.navigator.language || 'en',
weekStart: 0,
shortTime: false,
cancelText: 'Cancel',
okText: 'OK',
amText: 'AM',
pmText: 'PM',
todayText: 'Today',
disableDates: [],
weekDays: false,
disableParentScroll: false,
autoOk: false,
editInput: false,
clickOutsideToClose: false,
minuteSteps: 5,
showIcon: false,
template: template,
templateUrl: '',
};
return function (params) {
if (params) {
for (var i in params) {
if (default_params.hasOwnProperty(i) && params.hasOwnProperty(i)) {
default_params[i] = params[i];
}
}
}
return default_params;
};
})
.directive('mdcDatetimePicker', ['$mdDialog', '$timeout', '$compile',
function ($mdDialog, $timeout, $compile) {
return {
restrict: 'A',
require: 'ngModel',
scope: {
currentDate: '=ngModel',
ngChange: '&',
time: '=',
date: '=',
minutes: '=',
seconds: '=',
minDate: '=',
maxDate: '=',
disableDates: '=',
weekDays: '=',
shortTime: '=',
weekStart: '=',
format: '@',
cancelText: '@',
okText: '@',
lang: '@',
amText: '@',
pmText: '@',
showTodaysDate: '@',
todayText: '@',
disableParentScroll: '=',
autoOk: '=',
editInput: '=',
clickOutsideToClose: '=',
minuteSteps: '=',
showIcon: '=',
templateUrl: '@',
},
link: function (scope, element, attrs, ngModel) {
var isOn = false;
if (!scope.format) {
if (scope.date && scope.time && scope.seconds) {
scope.format = 'YYYY-MM-DD HH:mm:ss';
} else if (scope.date && scope.time) {
scope.format = 'YYYY-MM-DD HH:mm';
} else if (scope.date) {
scope.format = 'YYYY-MM-DD';
} else {
scope.format = 'HH:mm';
}
}
var dateOfTheDay = null;
if (scope.showTodaysDate !== undefined && scope.showTodaysDate !== "false") {
dateOfTheDay = moment();
}
if (angular.isString(scope.currentDate) && scope.currentDate !== '') {
scope.currentDate = moment(scope.currentDate, scope.format);
}
if (ngModel) {
var ngModelOptions = {'*': '$inherit', debounce: 500};
ngModel.$options = ngModel.$options ? ngModel.$options.createChild(ngModelOptions) : ngModelOptions;
ngModel.$formatters.push(function (value) {
if (typeof value === 'undefined') return;
var m = moment(value);
return m.isValid() ? m.format(scope.format) : '';
});
ngModel.$parsers.push(function (value) {
if (typeof value === 'undefined') return;
var m = moment(value, scope.format);
return m.isValid() ? m.toDate() : '';
});
}
function openCalendar(e) {
e.preventDefault();
element.blur();
element.parent().removeClass('md-input-focused');
if (isOn) {
return;
}
isOn = true;
var options = {};
for (var i in attrs) {
if (scope.hasOwnProperty(i) && !angular.isUndefined(scope[i])) {
options[i] = scope[i];
}
}
options.currentDate = scope.currentDate;
options.showTodaysDate = dateOfTheDay;
var dialogOptions = {
controller: PluginController,
controllerAs: 'picker',
locals: {options: options},
openFrom: element,
parent: angular.element(document.body),
bindToController: true,
clickOutsideToClose: options.clickOutsideToClose || false,
disableParentScroll: options.disableParentScroll || false,
hasBackDrop: false,
skipHide: true,
multiple: true,
};
if (!options.templateUrl) dialogOptions.template = template;
else dialogOptions.templateUrl = options.templateUrl;
$mdDialog.show(dialogOptions).then(function(v) {
if (ngModel.$options.$$options.timezone) {
var offset = ngModel.$options.getOption('timezone');
if (offset === 'utc' || offset === 'UTC') offset = 0;
v.utcOffset(offset, true);
}
scope.currentDate = v && !v._isUTC ? v.toDate() : v;
isOn = false;
if (!moment(scope.currentDate).isSame(options.currentDate)) {
$timeout(scope.ngChange, 0);
}
element.parent().removeClass('md-input-focused');
}, function () {
isOn = false;
element.parent().removeClass('md-input-focused');
});
}
if (!scope.editInput) {
if (scope.showIcon) {
element.on('click', openCalendar);
} else {
element.on('focus', openCalendar);
}
}
if (scope.showIcon) {
element.addClass('dtp-no-msclear dtp-input');
var calendarButton =
'<md-button class="dtp-btn-calendar md-icon-button" type="button"' +
'tabindex="-1" aria-hidden="true" ' +
'ng-click="openCalendarDiag($event)">' +
'<md-icon aria-label="md-calendar" md-svg-src="' + (scope.date ? mdCalendar : mdAccesTime) + '"></md-icon>' +
'</md-button>',
clearButton = '<md-button ng-show="currentDate" class="md-icon-button dtp-clear" aria-hidden="true" ng-click="clear()">✕</md-button>';
element.after($compile(calendarButton + clearButton)(scope));
scope.openCalendarDiag = function(e) {
openCalendar(e);
};
scope.clear = function() {
ngModel.$setViewValue(null);
scope.currentDate = null;
ngModel.$render();
$timeout(function() {
scope.ngChange();
element[0].focus();
}, 0, false);
};
}
}
};
}])
// Returns a service that opens a dialog when the attribute shown is called
.factory('mdcDateTimeDialog', ["$mdDialog", "$q", "mdcDefaultParams", function ($mdDialog, $q, mdcDefaultParams) {
var defaultParams = mdcDefaultParams();
var accepted_options = Object.keys(defaultParams);
var service = {
show: function (options) {
var deferred = $q.defer();
var params = angular.copy(defaultParams);
for (var i in options) {
if (accepted_options.indexOf[i] != -1 && options.hasOwnProperty(i)) {
params = options[i];
}
}
var dateOfTheDay = null;
if (options.showTodaysDate !== undefined && options.showTodaysDate !== "false") {
dateOfTheDay = moment();
}
options.showTodaysDate = dateOfTheDay;
var dialogOptions = {
controller: PluginController,
controllerAs: 'picker',
locals: {options: options},
parent: angular.element(document.body),
bindToController: true,
clickOutsideToClose: options.clickOutsideToClose || false,
disableParentScroll: options.disableParentScroll || false,
skipHide: true,
multiple: true,
};
if (!options.templateUrl) dialogOptions.template = template;
else dialogOptions.templateUrl = options.templateUrl;
$mdDialog.show(dialogOptions).then(function (v) {
deferred.resolve(v && !v._isUTC ? v.toDate() : v);
}, function () {
deferred.reject();
});
return deferred.promise;
}
};
return service;
}])
;
var PluginController = function ($scope, $mdDialog, mdcDefaultParams) {
this.currentView = VIEW_STATES.DATE;
this._dialog = $mdDialog;
this._attachedEvents = [];
this.VIEWS = VIEW_STATES;
this.params = angular.copy(mdcDefaultParams());
this.meridien = 'AM';
this.params = angular.extend(this.params, this.options);
this.init();
};
PluginController.$inject = ['$scope', '$mdDialog', 'mdcDefaultParams'];
PluginController.prototype = {
init: function () {
this.timeMode = this.params.time && !this.params.date;
this.dateMode = this.params.date;
this.initDates();
this.start();
},
currentNearestMinute: function () {
var nearestMin = this.params.minuteSteps;
if (nearestMin < 1 || nearestMin > 59) nearestMin = 1;
var date = this.currentDate || moment();
var minutes = (nearestMin * Math.round(date.minute() / nearestMin));
if (minutes >= 60) {
minutes = 60 - nearestMin; //always push down
}
var seconds = date.second();
if (seconds >= 60) {
seconds = 60 - 1; //always push down
}
return moment(date).minutes(minutes).seconds(seconds);
},
initDates: function () {
var that = this;
var _dateParam = function (input, fallback) {
var ret = null;
if (angular.isDefined(input) && input !== null && input !== '') {
if (angular.isString(input)) {
if (typeof(that.params.format) !== 'undefined' && that.params.format !== null) {
ret = moment(input, that.params.format).locale(that.params.lang);
}
else {
ret = moment(input).locale(that.params.lang);
}
} else if (typeof input === 'number') {
ret = moment(input).locale(that.params.lang);
} else {
if (angular.isDate(input)) {
var x = input.getTime();
ret = moment(x, "x").locale(that.params.lang);
} else if (input._isAMomentObject) {
ret = input;
}
}
}
else {
ret = fallback;
}
return ret;
};
this.currentDate = _dateParam(this.params.currentDate, moment());
this.currentDate = this.currentNearestMinute();
this.minDate = _dateParam(this.params.minDate);
this.maxDate = _dateParam(this.params.maxDate);
this.disableDates = this.params.disableDates.map(function (x) {
return moment(x).format('MMMM Do YYYY');
});
this.selectDate(this.currentDate);
this.weekDays = this.params.weekDays;
},
initDate: function () {
this.currentView = VIEW_STATES.DATE;
},
initHours: function () {
this.currentView = VIEW_STATES.HOUR;
},
initMinutes: function () {
this.currentView = VIEW_STATES.MINUTE;
},
initSeconds: function () {
this.currentView = VIEW_STATES.SECOND;
},
isAfterMinDate: function (date, checkHour, checkMinute) {
var _return = true;
if (typeof(this.minDate) !== 'undefined' && this.minDate !== null) {
var _minDate = moment(this.minDate);
var _date = moment(date);
if (!checkHour && !checkMinute) {
_minDate.hour(0);
_minDate.minute(0);
_date.hour(0);
_date.minute(0);
}
_minDate.second(0);
_date.second(0);
_minDate.millisecond(0);
_date.millisecond(0);
if (!checkMinute) {
_date.minute(0);
_minDate.minute(0);
_return = (parseInt(_date.format("X")) >= parseInt(_minDate.format("X")));
}
else {
_return = (parseInt(_date.format("X")) >= parseInt(_minDate.format("X")));
}
}
return _return;
},
isBeforeMaxDate: function (date, checkTime, checkMinute) {
var _return = true;
if (typeof(this.maxDate) !== 'undefined' && this.maxDate !== null) {
var _maxDate = moment(this.maxDate);
var _date = moment(date);
if (!checkTime && !checkMinute) {
_maxDate.hour(0);
_maxDate.minute(0);
_date.hour(0);
_date.minute(0);
}
_maxDate.second(0);
_date.second(0);
_maxDate.millisecond(0);
_date.millisecond(0);
if (!checkMinute) {
_date.minute(0);
_maxDate.minute(0);
_return = (parseInt(_date.format("X")) <= parseInt(_maxDate.format("X")));
}
else {
_return = (parseInt(_date.format("X")) <= parseInt(_maxDate.format("X")));
}
}
return _return;
},
isInDisableDates: function (date) {
var dut = date.format('MMMM Do YYYY');
if (this.disableDates.indexOf(dut) > -1) {
return false;
}
return true;
},
isWeekDay: function(date) {
if (this.weekDays) {
if (date.isoWeekday() <= 5) {
return true;
}
return false;
}
return true;
},
selectDate: function (date) {
if (date) {
this.currentDate = moment(date);
if (!this.isAfterMinDate(this.currentDate)) {
this.currentDate = moment(this.minDate);
}
if (!this.isBeforeMaxDate(this.currentDate)) {
this.currentDate = moment(this.maxDate);
}
this.currentDate.locale(this.params.lang);
this.calendarStart = moment(this.currentDate);
this.meridien = this.currentDate.hour() >= 12 ? 'PM' : 'AM';
}
},
isPM: function () {
return this.meridien === 'PM';
},
incrementMonth: function (amount) {
if (amount === 1 && this.isNextMonthVisible()) {
this.selectDate(this.currentDate.add(amount, 'month'));
}
if (amount === -1 && this.isPreviousMonthVisible()) {
this.selectDate(this.currentDate.add(amount, 'month'));
}
},
incrementYear: function (amount) {
if (amount === 1 && this.isNextYearVisible()) {
this.selectDate(this.currentDate.add(amount, 'year'));
}
if (amount === -1 && this.isPreviousYearVisible()) {
this.selectDate(this.currentDate.add(amount, 'year'));
}
},
openMenu: function ($mdMenu, ev) {
$mdMenu.open(ev);
},
monthsAvailable: function () {
var monthsArr = [],
_date = moment(this.currentDate);
for (var m = 0; m < 12; m++) {
var curMonth = _date.month(m);
if (this.isAfterMinDate(curMonth.endOf('month')) && this.isBeforeMaxDate(curMonth.startOf('month'))) {
monthsArr.push(curMonth.format('MMMM'));
}
}
return monthsArr;
},
selectMonth: function (month) {
this.selectDate(this.currentDate.month(month));
},
yearsAvailable: function () {
var _minDate, _maxDate, len, startYear, yearsArr = [],
_date = this.currentDate.year();
if (typeof(this.minDate) !== 'undefined' && this.minDate !== null) {
_minDate = moment(this.minDate).year();
}
if (typeof(this.maxDate) !== 'undefined' && this.maxDate !== null) {
_maxDate = moment(this.maxDate).year();
}
if (_maxDate && _minDate) {
len = _maxDate - _minDate;
startYear = _minDate;
} else if (_minDate) {
len = 115;
startYear = _minDate;
} else if (_maxDate) {
len = 30;
startYear = _maxDate - len;
} else {
len = 60;
startYear = _date - len/2;
}
for (var i=0; i < len; i++) {
yearsArr.push(startYear+i);
}
return yearsArr;
},
selectYear: function (year) {
this.selectDate(this.currentDate.year(year));
},
isPreviousMonthVisible: function () {
return this.calendarStart && this.isAfterMinDate(moment(this.calendarStart).startOf('month'), false, false);
},
isNextMonthVisible: function () {
return this.calendarStart && this.isBeforeMaxDate(moment(this.calendarStart).endOf('month'), false, false);
},
isPreviousYearVisible: function () {
return this.calendarStart && this.isAfterMinDate(moment(this.calendarStart).startOf('year'), false, false);
},
isNextYearVisible: function () {
return this.calendarStart && this.isBeforeMaxDate(moment(this.calendarStart).endOf('year'), false, false);
},
isHourAvailable: function (hour) {
var _date = moment(this.currentDate);
if (this.params.shortTime) {
_date.hour(this.convertHours(hour)).minute(0).second(0);
} else {
_date.hour(hour).minute(0).second(0);
}
return this.isAfterMinDate(_date, true, false) && this.isBeforeMaxDate(_date, true, false);
},
isMinuteAvailable: function (minute) {
var _date = moment(this.currentDate);
_date.minute(minute).second(0);
return this.isAfterMinDate(_date, true, true) && this.isBeforeMaxDate(_date, true, true);
},
isSecondAvailable: function (second) {
return true;
},
start: function () {
this.currentView = VIEW_STATES.DATE;
if (this.params.date) {
this.initDate();
} else {
if (this.params.time) {
this.initHours();
}
}
},
today: function () {
var nearestMin = this.params.minuteSteps;
var date = moment();
var minutes = (nearestMin * Math.round(date.minute() / nearestMin));
if (minutes >= 60) {
minutes = 60 - nearestMin; //always push down
}
this.selectDate(moment(date).minutes(minutes));
},
ok: function () {
switch (this.currentView) {
case VIEW_STATES.DATE:
if (this.params.time === true) {
this.initHours();
} else {
this.hide(true);
}
break;
case VIEW_STATES.HOUR:
if (this.params.minutes === true) {
this.initMinutes();
} else {
this.hide(true);
}
break;
case VIEW_STATES.MINUTE:
if (this.params.seconds === true) {
this.initSeconds();
} else {
this.hide(true);
}
break;
case VIEW_STATES.SECOND:
this.hide(true);
break;
}
},
cancel: function () {
if (this.params.time) {
switch (this.currentView) {
case VIEW_STATES.DATE:
this.hide();
break;
case VIEW_STATES.HOUR:
if (this.params.date) {
this.initDate();
}
else {
this.hide();
}
break;
case VIEW_STATES.MINUTE:
this.initHours();
break;
case VIEW_STATES.SECOND:
this.initMinutes();
break;
}
}
else {
this.hide();
}
},
selectMonthBefore: function () {
this.calendarStart.subtract(1, 'months');
},
selectMonthAfter: function () {
this.calendarStart.add(1, 'months');
},
selectYearBefore: function () {
this.calendarStart.subtract(1, 'years');
},
selectYearAfter: function () {
this.calendarStart.add(1, 'years');
},
selectAM: function () {
if (this.isHourAvailable(0) || this.isHourAvailable(12)) {
if (this.currentDate.hour() >= 12) {
this.selectDate(this.currentDate.subtract(12, 'hours'));
}
if (!this.isHourAvailable(this.currentDate.hour())) {
this.selectDate(this.currentDate.hour(this.minDate.hour()));
}
if (!this.isMinuteAvailable(this.currentDate.minute())) {
this.selectDate(this.currentDate.minute(this.minDate.minute()));
}
}
},
selectPM: function () {
if (this.isHourAvailable(13) || this.isHourAvailable(24)) {
if (this.currentDate.hour() < 12) {
this.selectDate(this.currentDate.add(12, 'hours'));
}
if (!this.isHourAvailable(this.currentDate.hour())) {
this.selectDate(this.currentDate.hour(this.maxDate.hour()));
}
if (!this.isMinuteAvailable(this.currentDate.minute())) {
this.selectDate(this.currentDate.minute(this.maxDate.minute()));
}
}
},
convertHours: function (h) {
var _return = h;
if ((h < 12) && this.isPM())
_return += 12;
return _return;
},
hide: function (okBtn) {
if (okBtn) {
this._dialog.hide(this.currentDate);
} else {
this._dialog.cancel();
}
}
};
angular.module(moduleName)
.directive('mdcDatetimePickerCalendar', [
function () {
var YEAR_MIN = 1920,
YEAR_MAX = new Date().getFullYear() + 30,
MONTHS_IN_ALL = (YEAR_MAX - YEAR_MIN + 1) * 12,
ITEM_HEIGHT = 240,
MONTHS = [];
for (var i = 0; i < MONTHS_IN_ALL; i++) {
MONTHS.push(i);
}
var currentMonthIndex = function (date, low) {
low = low ? low : 0;
var year = date.year();
var month = date.month();
return (((year - YEAR_MIN) * 12) + month - 1 ) - low;
};
return {
restrict: 'E',
scope: {
picker: '=',
date: '='
},
bindToController: true,
controllerAs: 'cal',
controller: ['$scope', function ($scope) {
var calendar = this, picker;
this.$onInit = function () {
picker = this.picker;
var days = [];
for (var i = picker.params.weekStart; days.length < 7; i++) {
if (i > 6) {
i = 0;
}
days.push(i.toString());
}
calendar.week = days;
if (!picker.maxDate && !picker.minDate) {
calendar.months = MONTHS;
} else {
var low = picker.minDate ? currentMonthIndex(picker.minDate) : 0;
var high = picker.maxDate ? (currentMonthIndex(picker.maxDate) + 1) : MONTHS_IN_ALL;
calendar.months = MONTHS.slice(low, high);
}
calendar.topIndex = currentMonthIndex(picker.currentDate) - calendar.months[0];
};
if (angular.version.major === 1 && angular.version.minor < 5) {
this.$onInit();
}
calendar.getItemAtIndex = function (index) {
var month = ((index + 1) % 12) || 12;
var year = YEAR_MIN + Math.floor(index / 12);
var monthObj = moment(picker.currentDate).year(year).month(month);
return generateMonthCalendar(monthObj);
};
$scope.$watch(function () {
return picker.currentDate ? picker.currentDate.format('YYYY-MM') : '';
}, function (val2, val1) {
if (val2 != val1) {
var nDate = moment(val2, 'YYYY-MM');
var low = picker.minDate ? currentMonthIndex(picker.minDate) : 0;
var index = currentMonthIndex(nDate, low);
if (calendar.topIndex != index) {
calendar.topIndex = index;
}
}
});
var generateMonthCalendar = function (date) {
var month = {};
if (date !== null) {
month.name = date.format('MMMM YYYY');
var startOfMonth = moment(date).locale(picker.params.lang).startOf('month')
.hour(date.hour())
.minute(date.minute());
var iNumDay = startOfMonth.format('d');
month.days = [];
for (var i = startOfMonth.date(); i <= startOfMonth.daysInMonth(); i++) {
if (i === startOfMonth.date()) {
var iWeek = calendar.week.indexOf(iNumDay.toString());
if (iWeek > 0) {
for (var x = 0; x < iWeek; x++) {
month.days.push(0);
}
}
}
month.days.push(moment(startOfMonth).locale(picker.params.lang).date(i));
}
var daysInAWeek = 7, daysTmp = [], slices = Math.ceil(month.days.length / daysInAWeek);
for (var j = 0; j < slices; j++) {
daysTmp.push(month.days.slice(j * daysInAWeek, (j + 1) * daysInAWeek));
}
month.days = daysTmp;
return month;
}
};
calendar.toDay = function (i) {
return moment(parseInt(i), "d")
.locale(picker.params.lang)
.format("dd")
.substring(0, 1);
};
calendar.isInRange = function (date) {
return picker.isAfterMinDate(moment(date), false, false) &&
picker.isBeforeMaxDate(moment(date), false, false) &&
picker.isWeekDay(moment(date)) &&
picker.isInDisableDates(moment(date));
};
calendar.selectDate = function (date) {
if (date) {
if (calendar.isSelectedDay(date)) {
return picker.ok();
}
picker.selectDate(moment(date).hour(calendar.date.hour()).minute(calendar.date.minute()));
if (picker.params.autoOk) {
picker.ok();
}
}
};
calendar.isSelectedDay = function (m) {
return m && calendar.date.date() === m.date() && calendar.date.month() === m.month() && calendar.date.year() === m.year();
};
calendar.isDateOfTheDay = function (m) {
var today = calendar.picker.options.showTodaysDate;
if (!today) {
return false;
}
return m && today.date() === m.date() && today.month() === m.month() && today.year() === m.year();
};
}],
template:
'<md-virtual-repeat-container md-top-index="cal.topIndex" class="months">' +
'<div md-virtual-repeat="idx in ::cal.months" md-auto-shrink md-item-size="' + ITEM_HEIGHT + '">' +
' <div mdc-datetime-picker-calendar-month idx="idx"></div>' +
'</div>' +
'</md-virtual-repeat-container>'
};
}])
.directive('mdcDatetimePickerCalendarMonth', ['$compile',
function ($compile) {
var buildCalendarContent = function (element, scope) {
var tbody = angular.element(element[0].querySelector('tbody'));
var calendar = scope.cal, month = scope.month;
var tbodyHtml = [];
month.days.forEach(function (weekDays, i) {
tbodyHtml.push('<tr>');
weekDays.forEach(function (weekDay, j) {
tbodyHtml.push('<td>');
if (weekDay) {
if (calendar.isInRange(weekDay)) {
//build a
var scopeRef = 'month[\'days\'][' + i + '][' + j + ']';
tbodyHtml.push('<a id="date-' + weekDay.format('YYYY-MM-DD') + '" href="#" mdc-dtp-noclick class="dtp-select-day" ng-class="{selected: cal.isSelectedDay(' + scopeRef + '), hilite: cal.isDateOfTheDay(' + scopeRef + ')}" ng-click="cal.selectDate(' + scopeRef + ')">');
tbodyHtml.push(weekDay.format('D'));
tbodyHtml.push('</a>');
} else {
tbodyHtml.push('<span class="dtp-select-day">');
tbodyHtml.push(weekDay.format('D'));
tbodyHtml.push('</span>');
}
}
tbodyHtml.push('</td>');
});
tbodyHtml.push('</tr>');
});
tbody.html(tbodyHtml.join(''));
$compile(tbody)(scope);
};
return {
scope: {
idx: '='
},
require: '^mdcDatetimePickerCalendar',
restrict: 'AE',
template:
'<div class="dtp-picker-month">{{month.name}}</div>' +
'<table class="table dtp-picker-days">' +
' <thead>' +
' <tr>' +
' <th ng-repeat="day in cal.week track by $index">{{cal.toDay(day)}}</th>' +
' </tr>' +
' </thead>' +
' <tbody>' +
' </tbody>' +
'</table>',
link: function (scope, element, attrs, calendar) {
scope.cal = calendar;
scope.month = calendar.getItemAtIndex(parseInt(scope.idx));
buildCalendarContent(element, scope);
scope.$watch(function () {
return scope.idx;
}, function (idx, oldIdx) {
if (idx != oldIdx) {
scope.month = calendar.getItemAtIndex(parseInt(scope.idx));
buildCalendarContent(element, scope);
}
});
}
};
}
])
;
angular.module(moduleName)
.directive('mdcDtpNoclick', function () {
return {
link: function (scope, el) {
el.on('click', function (e) {
e.preventDefault();
});
}
};
});
angular.module(moduleName)
.directive('mdcDatetimePickerClock', ['$timeout',
function ($timeout) {
var template =
'<div id="timePicker" class="dtp-picker-clock"><span ng-if="!points || points.length < 1"> </span>' +
'<div ng-repeat="point in points" class="dtp-picker-time noselect" ng-style="point.style">' +
' <a href="#" id="time-{{mode}}-{{point.display}}" mdc-dtp-noclick ng-class="{selected: point.value===currentValue}" class="dtp-select-hour" ng-click="setTime(point.value)" ng-if="pointAvailable(point)">{{point.display}}</a>' +
' <a href="#" mdc-dtp-noclick class="disabled dtp-select-hour" ng-if="!pointAvailable(point)">{{point.display}}</a>' +
'</div>' +
'<div ng-if="points24.length" ng-repeat="point24 in points24" class="dtp-picker-time noselect" ng-style="point24.style">' +
' <a href="#" id="time-24hours-{{point24.display}}" mdc-dtp-noclick ng-class="{selected: point24.value===currentValue}" class="dtp-select-hour" ng-click="setTime(point24.value)" ng-if="pointAvailable(point24)">{{point24.display}}</a>' +
' <a href="#" mdc-dtp-noclick class="disabled dtp-select-hour" ng-if="!pointAvailable(point24)">{{point24.display}}</a>' +
'</div>' +
'<div class="dtp-hand dtp-hour-hand"></div>' +
'<div class="dtp-hand dtp-minute-hand"></div>' +
'<div ng-if="picker.params.seconds" class="dtp-hand dtp-second-hand"></div>' +
'<div class="dtp-clock-center"></div>' +
'</div>';
return {
restrict: 'E',
template: template,
link: function (scope, element, attrs) {
var minuteMode = attrs.mode === 'minutes';
var secondMode = attrs.mode === 'seconds';
var picker = scope.picker;
//banking on the fact that there will only be one at a time
var componentRoot = document.querySelector('md-dialog.dtp');
var setTimeDegRay = function(deg, ray) {
var val = 0;
deg = deg >= 360 ? 0 : deg;
if (deg !== 0) {
var divider = minuteMode||secondMode ? 60 : 12;
val = Math.round(divider / 360 * deg);
}
if (minuteMode) {
var nearestMin = picker.params.minuteSteps;
if (nearestMin < 1 || nearestMin > 59) nearestMin = 1;
var minutes = (nearestMin * Math.round(val / nearestMin));
if (minutes >= 60) {
minutes = 60 - nearestMin; //always push down
}
if (!scope.pointAvailable({value: val})) return;
picker.currentDate.minute(minutes);
} else if (!secondMode){
if (val === 12) val = 0;
if (!picker.params.shortTime) picker.meridien = ray > 84 ? 'AM' : 'PM';
if (picker.isPM()) val += 12;
if (!scope.pointAvailable({value: val})) return;
picker.currentDate.hour(val);
} else {
if (val >= 60) val = 0;
if (!scope.pointAvailable({value: val})) return;
picker.currentDate.second(val);
}
};
var isTouchSupported = ('ontouchstart' in window) ? true : false,
EVENTS = {
POINTER_DOWN : isTouchSupported ? 'touchstart' : 'mousedown',
POINTER_UP : isTouchSupported ? 'touchend' : 'mouseup',
POINTER_MOVE : isTouchSupported ? 'touchmove' : 'mousemove'
};
var onMoveEvent = function(e) {
e.preventDefault();
var closestTarget = e.currentTarget.closest('div'),
clientRect = closestTarget.getClientRects()[0];
if (isTouchSupported) e = e.changedTouches[0];
var x = ((closestTarget.offsetWidth / 2) - (e.pageX - clientRect.left)),
y = ((e.pageY - clientRect.top) - (closestTarget.offsetHeight / 2));
var ray = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
var deg = Math.round((Math.atan2(x, y) * (180 / Math.PI)));
$timeout(function() {
setTimeDegRay(deg+180, ray);
});
};
element.on(EVENTS.POINTER_DOWN, function() {
element.on(EVENTS.POINTER_MOVE, onMoveEvent);
});
element.on(EVENTS.POINTER_UP, function() {
element.off(EVENTS.POINTER_MOVE);
});
scope.$on("$destroy", function() {
element.off(EVENTS.POINTER_MOVE, onMoveEvent);
});
var exec = function () {
var clock = angular.element(element[0].querySelector('.dtp-picker-clock')),
pickerEl = angular.element(componentRoot.querySelector('.dtp-picker'));
var w = componentRoot.querySelector('.dtp-content').offsetWidth;
var pl = parseInt(css(pickerEl, 'paddingLeft').replace('px', '')) || 0;
var pr = parseInt(css(pickerEl, 'paddingRight').replace('px', '')) || 0;
var ml = parseInt(css(clock, 'marginLeft').replace('px', '')) || 0;
var mr = parseInt(css(clock, 'marginRight').replace('px', '')) || 0;
//set width
var clockWidth = (w - (ml + mr + pl + pr));
clock.css('width', (clockWidth) + 'px');
var pL = parseInt(css(pickerEl, 'paddingLeft').replace('px', '')) || 0;
var pT = parseInt(css(pickerEl, 'paddingTop').replace('px', '')) || 0;
var mL = parseInt(css(clock, 'marginLeft').replace('px', '')) || 0;
var mT = parseInt(css(clock, 'marginTop').replace('px', '')) || 0;
var r = (clockWidth / 2);
var j = r / 1.2; // radius for low number
var points = [];
for (var h = 0; h < 12; ++h) {
var x = j * Math.sin(Math.PI * 2 * (h / 12));
var y = j * Math.cos(Math.PI * 2 * (h / 12));
var left = (r + x + pL / 2) - (pL + mL);
var top = (r - y - mT / 2) - (pT + mT);
var hour = {
left: left,
top: top,
value: (minuteMode||secondMode ? (h * 5) : h), //5 for minute 60/12
style: {'margin-left': left + 'px', 'margin-top': top + 'px'}
};
if (minuteMode || secondMode) {
hour.display = hour.value < 10 ? ('0' + hour.value) : hour.value;
} else {
if (picker.params.shortTime) {
hour.display = (h === 0) ? 12 : h;
} else {
hour.display = h;
}
}
points.push(hour);
}
scope.points = points;
if (!picker.params.shortTime && !minuteMode && !secondMode) {
var points24 = [];
var j24 = r / 1.8; // radius for high number
for (var h24 = 12; h24 < 24; ++h24) {
var x24 = j24 * Math.sin(Math.PI * 2 * (h24 / 12));
var y24 = j24 * Math.cos(Math.PI * 2 * (h24 / 12));
var left24 = (r + x24 + pL / 2) - (pL + mL);
var top24 = (r - y24 - mT / 2) - (pT + mT);
points24.push({
left: left24,
top: top24,
value: h24,
display: h24,
style: {'margin-left': left24 + 'px', 'margin-top': top24 + 'px'}
});
}
scope.points24 = points24;
}
scope.mode = attrs.mode;
setCurrentValue();
clock.css('height', clockWidth + 'px');
var clockCenter = element[0].querySelector('.dtp-clock-center');
var centerWidth = (clockCenter.offsetWidth / 2) || 7.5,
centerHeight = (clockCenter.offsetHeight / 2) || 7.5;
var _hL = r / (picker.params.shortTime ? 1.8 : 2.3);
var _mL = r / 1.4;
var _sL = r / 1;
angular.element(element[0].querySelector('.dtp-hour-hand')).css({
left: r + (mL * 1.5) + 'px',
height: _hL + 'px',
marginTop: (r - _hL - pL) + 'px'
}).addClass(!minuteMode && !secondMode ? 'on' : '');
angular.element(element[0].querySelector('.dtp-minute-hand')).css
({
left: r + (mL * 1.5) + 'px',
height: _mL + 'px',
marginTop: (r - _mL - pL) + 'px'
}).addClass(minuteMode ? 'on' : '');
angular.element(element[0].querySelector('.dtp-second-hand')).css
({
left: r + (mL * 1.5) + 'px',
height: _sL + 'px',
marginTop: (r - _sL - pL) + 'px'
}).addClass(secondMode ? 'on' : '');
angular.element(clockCenter).css({
left: (r + pL + mL - centerWidth) + 'px',
marginTop: (r - (mL / 2)) - centerHeight + 'px'
});
animateHands();
};
var animateHands = function () {
var _date = picker.currentNearestMinute();
var h = _date.hour();
var m = _date.minute();
var s = _date.second();
rotateElement(angular.element(element[0].querySelector('.dtp-hour-hand')), 30 * h);
rotateElement(angular.element(element[0].querySelector('.dtp-minute-hand')), 6 * m);
rotateElement(angular.element(element[0].querySelector('.dtp-second-hand')), 6 * s);
};
var rotateElement = function (el, deg) {
angular.element(el).css({
WebkitTransform: 'rotate(' + deg + 'deg)',
'-moz-transform': 'rotate(' + deg + 'deg)',
'-ms-transform': 'rotate(' + deg + 'deg)',
'transform': 'rotate(' + deg + 'deg)'
});
};
var setCurrentValue = function () {
var date = picker.currentNearestMinute();
var nbH = picker.params.shortTime ? 12 : 24;
if (minuteMode) {
scope.currentValue = date.minute();
} else if (secondMode) {
scope.currentValue = date.second();
} else {
scope.currentValue = date.hour() % nbH;
}
};
scope.$watch(function () {
var tmp = picker.currentNearestMinute();
return tmp ? tmp.format('HH:mm:ss') : '';
}, function () {
setCurrentValue();
animateHands();
});
scope.setTime = function (val) {
if (!minuteMode && !secondMode) {
if (val === scope.currentValue && !picker.params.autoOk) picker.ok(); // double click
if (picker.params.shortTime) {
picker.currentDate.hour(picker.isPM() ? (val + 12) : val);
} else {
picker.currentDate.hour(val);
if (val >= 12) picker.meridien = 'PM';
else picker.meridien = 'AM';
}
if (picker.params.autoOk) picker.ok(); // single click
} else if (!secondMode) {
if (val === scope.currentValue && !picker.params.seconds) {
picker.ok(); // double click
}
picker.currentDate.minute(val);
if (!picker.params.seconds) {
picker.currentDate.second(0);
} else if (picker.params.autoOk) picker.ok(); // single click
} else {
if (val === scope.currentValue) picker.ok(); // double click
picker.currentDate.second(val);
}
};
scope.pointAvailable = function (point) {
if (minuteMode) {
return picker.isMinuteAvailable(point.value);
} else if (secondMode) {
return picker.isSecondAvailable(point.value);
} else {
return picker.isHourAvailable(point.value);
}
};
var unWatcher = scope.$watch(function () {
return element[0].querySelectorAll('div').length;
}, function () {
exec();
unWatcher();
});
}
};
}]);
return moduleName;
}
var isElectron = window && window.process && window.process.type;
if (typeof define === 'function' && define.amd) {
define(['moment'], ngMaterialDatePicker);
} else if (typeof module !== 'undefined' && module && module.exports && (typeof require === 'function') && !isElectron) {
module.exports = ngMaterialDatePicker(require('moment'));
} else {
ngMaterialDatePicker((typeof global !== 'undefined' ? global : window).moment);
}
})();
md-dialog.dtp {
font-size: 14px;
line-height: 1.42857143;
color: #333;
background-color: #fff;
max-height: none;
min-width: 300px;
width: 300px;
}
.noselect {
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.dtp *:focus {
outline: none !important;
}
.dtp table {
border-spacing: 0;
border-collapse: collapse;
width: 100%;
}
.dtp .table > tbody > tr > td,
.dtp .table > tbody > tr > th,
.dtp .table > tfoot > tr > td,
.dtp .table > tfoot > tr > th,
.dtp .table > thead > tr > td,
.dtp .table > thead > tr > th {
padding: 8px;
line-height: 1.42857143;
vertical-align: top;
border-top: 1px solid #ddd;
}
.dtp, .dtp * {
box-sizing: border-box !important;
}
.dtp > .dtp-content {
max-width: 300px;
max-height: 500px;
}
.dtp > .dtp-content > .dtp-date-view > header.dtp-header {
background: #689F38;
color: #fff;
text-align: center;
}
.dtp div.dtp-date, .dtp div.dtp-time {
background: #8BC34A;
text-align: center;
color: #fff;
padding: 10px;
}
.dtp div.dtp-date > div {
padding: 0;
margin: 0;
}
.dtp div.dtp-actual-month {
font-size: 1.5em;
cursor: pointer;
}
.dtp div.dtp-actual-num {
font-size: 2em;
line-height: 0.9;
}
.dtp div.dtp-actual-maxtime {
font-size: 2em;
line-height: 0.9;
color: #DCEDC8;
}
.dtp div.dtp-actual-maxtime span.selected {
color: #fff;
}
.dtp div.dtp-actual-year {
font-size: 1.6em;
color: #DCEDC8;
cursor: pointer;
}
.dtp div.dtp-month-btn {
font-size: 1.4em;
line-height: 30px;
cursor: pointer;
}
.dtp div.dtp-month-btn-prev {
text-align: right;
}
.dtp div.dtp-month-btn-next {
text-align: left;
}
.dtp div.dtp-year-btn {
font-size: 1.4em;
line-height: 30px;
cursor: pointer;
color: #DCEDC8;
}
.dtp div.dtp-year-btn-prev {
text-align: right;
}
.dtp div.dtp-year-btn-next {
text-align: left;
}
.dtp div.dtp-picker {
padding: 10px 10px 0 10px;
text-align: center;
/* Prevent dialog resizing when switcing between date/time */
overflow: hidden;
}
.dtp div.dtp-picker-month, .dtp div.dtp-actual-time {
font-size: 1.2em;
font-weight: 500;
text-align: center;
}
.dtp div.dtp-actual-time.p60 span.selected {
color: #689F38;
}
.dtp .dtp-close {
position: absolute;
top: 0;
right: 5px;
font-size: 16px;
}
.dtp .dtp-close > a {
color: #fff;
text-decoration: none;
}
.dtp .dtp-close > a > i {
font-size: 1em;
}
.dtp table.dtp-picker-days {
margin: 0;
min-height: 220px;
}
.dtp md-virtual-repeat-container.months {
height: 260px;
}
.dtp table.dtp-picker-days, .dtp table.dtp-picker-days tr, .dtp table.dtp-picker-days tr > td {
border: none;
}
.dtp table.dtp-picker-days tr > td {
font-size: 11px;
text-align: center;
padding: 0;
}
.dtp table.dtp-picker-days tr > td > span.dtp-select-day {
color: #BDBDBD !important;
}
.dtp table.dtp-picker-days tr > td, .dtp table.dtp-picker-days tr > td > .dtp-select-day {
width: 36px;
height: 36px;
}
.dtp table.dtp-picker-days tr > td > .dtp-select-day {
display: inline-block;
}
.dtp table.dtp-picker-days tr > td > .dtp-select-day, .dtp .dtp-picker-time > a {
color: #212121;
text-decoration: none;
padding: 10px;
border-radius: 50% !important;
}
.dtp table.dtp-picker-days tr > td > a.selected {
background: #8BC34A;
color: #fff;
}
.dtp table.dtp-picker-days tr > td > a.selected.hilite {
padding: 6px;
font-size: 16px;
font-weight: 500;
background: #8BC34A;
color: #fff;
}
.dtp table.dtp-picker-days tr > td > a.hilite:not(.selected) {
padding: 6px;
font-size: 16px;
font-weight: 500;
color: #8BC34A;
}
.dtp table.dtp-picker-days tr > td > a:hover:not(.selected) {
background: #dddddd;
}
.dtp table.dtp-picker-days tr > th {
color: #757575;
text-align: center;
font-weight: 700;
padding: 4px 3px;
width: 38px;
height: 28px;
}
.dtp .p10 > a {
color: #689F38;
text-decoration: none;
}
.dtp .p10 {
width: 10%;
display: inline-block;
}
.dtp .p20 {
width: 20%;
display: inline-block;
}
.dtp .p60 {
width: 60%;
display: inline-block;
}
.dtp .p80 {
width: 80%;
display: inline-block;
}
.dtp div.dtp-picker-datetime {
padding-bottom: 25px;
}
.dtp span.dtp-actual-meridien {
font-size: 0.6em;
}
.dtp div.dtp-actual-meridien {
height: 20px;
}
.dtp a.dtp-meridien-am, .dtp a.dtp-meridien-pm {
position: relative;
color: #212121;
font-weight: 500;
padding: 7px 5px;
border-radius: 50% !important;
text-decoration: none;
background: #eee;
font-size: 10px;
}
.dtp .dtp-actual-meridien a.selected {
background: #689F38;
color: #fff;
}
.dtp .dtp-picker-time > a {
display: block;
line-height: 23px;
padding: 3px 3px 3px 3px;
}
.dtp .dtp-picker-time {
position: absolute;
width: 30px;
height: 30px;
font-size: 1.1em;
border-radius: 50%;
cursor: pointer;
text-align: center !important;
}
.dtp .dtp-picker-time > a.dtp-select-hour.selected {
background: #689F38;
color: #fff;
}
.dtp .dtp-picker-time > a.dtp-select-hour.disabled, .dtp .dtp-picker-time > a.dtp-select-minute.disabled {
color: #757575;
}
.dtp .dtp-picker-time > a.dtp-select-minute.selected {
background: #8BC34A;
color: #fff;
}
.dtp div.dtp-picker-clock {
margin: 10px 20px 0 20px;
padding: 10px;
border-radius: 50% !important;
background: #eee;
direction: ltr;
cursor: default;
}
.dtp-clock-center {
width: 15px;
height: 15px;
background: #757575;
border-radius: 50%;
position: absolute;
z-index: 50;
}
.dtp .dtp-hand, .dtp .dtp-hour-hand {
position: absolute;
width: 4px;
margin-left: -2px;
background: #BDBDBD;
-moz-transform: rotate(0deg);
-ms-transform: rotate(0deg);
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
-moz-transform-origin: bottom;
-ms-transform-origin: bottom;
-webkit-transform-origin: bottom;
transform-origin: bottom;
z-index: 1;
}
.dtp .dtp-minute-hand {
width: 2px;
margin-left: -1px;
}
.dtp .dtp-second-hand {
width: 1px;
margin-left: -1px;
}
.dtp .dtp-hand.on {
background: #8BC34A;
}
.dtp .dtp-buttons {
padding-bottom: 10px;
text-align: right;
}
.dtp.hidden, .dtp .hidden {
display: none;
}
.dtp .invisible {
visibility: hidden;
}
.dtp .left {
float: left;
}
.dtp .right {
float: right;
}
.dtp .clearfix {
clear: both;
}
.dtp .center {
text-align: center;
}
[dir=rtl] .dtp div.dtp-year-btn-next, [dir=rtl] .dtp div.dtp-month-btn-next,
[dir=rtl] .dtp div.dtp-year-btn-prev, [dir=rtl] .dtp div.dtp-month-btn-prev {
-ms-transform: rotate(180deg);
-webkit-transform: rotate(180deg);
transform: rotate(180deg);
}
.dtp-btn-today, .dtp-btn-ok, .dtp-btn-cancel {
min-width: 70px;
}
.dtp-clear {
position: absolute;
top: 0;
right: -10px;
}
/* Remove IE clear button */
.dtp-no-msclear::-ms-clear {
display: none;
width : 0;
height: 0;
}
.dtp-btn-calendar {
position: absolute;
top: -3px;
left: -10px;
}
.dtp-input {
margin-left: 30px;
max-width: calc(100% - 30px);
}