>(function () { > 'use strict'; > > var app = angular.module('sysMgrApp'); > > app.directive('smDateTimePicker', [function () { > return { > require: 'ngModel', > restrict: 'E', > > scope: { > ngModel: '=',//the date being saved to the database > compareDate: '=',//either the start or end date of the range for validation (isDateRange attr must be set to true) > form: '=',//the name of the form (if a subform, this will be parent.subform), used for setting the form to dirty and validation > name: '@',//the input's name, used to manually outline invalid fields in red > placeholder: '@',//text of placeholder on input field, > showBod: '=',//if true, we display the Beginning of Day button (pickTime must be true) > showEod: '=',//if true, we display the End of Day button (pickTime must be true) > showNow: '=',//if true, we display the Now button > setBod: '&',//function defined in the directive that is called when clicking on the BOD button > setEod: '&',//function defined in the directive that is called when clicking on the EOD button > setNow: '&',//function defined in the directive that is called when clicking on the Now button > validStartDateRange: '&',//function defined in the directive that determines whether to show validation message > validEndDateRange: '&', > validRequired: '&', > validFutureDate: '&', > validPastDate: '&' > }, > templateUrl: "/app/templates/smDateTimePicker", > link: function (scope, element, attrs, controller) { > if (!controller) return undefined; > > var updateModel, onblur, datetimepicker, options; > > var pickTime = attrs.pickTime === "true" ? true : false; > var isDateRange = attrs.isDateRange === "true" ? true : false; //if true, we do range validation on start and end dates > var isRequired = attrs.isRequired === "true" ? true : false; //if true, we do required validation > scope.showBod = (scope.showBod && pickTime); //only display showBod button if pickTime is true > scope.showEod = (scope.showEod && pickTime); //only display showEod button if pickTime is true > var onlyFutureDates = attrs.onlyFutureDates === "true" ? true : false; > var onlyPastDates = attrs.onlyPastDates === "true" ? true : false; > var isEndDate = attrs.isEndDate === "true" ? true : false; > > var format = function (date) { > if (date) { > if (!pickTime) { > if (isEndDate && !onlyFutureDates) { > date = date.hours(23).minutes(59).seconds(59).milliseconds(997); > } else { > date = date.hours(0).minutes(0).seconds(0).milliseconds(0); > } > } > date = date.format("YYYY-MM-DD HH:mm:ss.SSS").toString(); > } > return date; > }; > > var setStartDateLimit = function () { > if (onlyFutureDates) { > return moment().add('days', 1); > } > return moment("1753 01 01", "YYYY MM DD"); > }; > > var setEndDateLimit = function () { > if (onlyPastDates) { > return moment().subtract('days', 1); > } > return moment("9999 12 31", "YYYY MM DD"); > }; > > var setCalendarPickerStartDate = function () { > if (onlyFutureDates) { > return moment().add('days', 1); > } else if (onlyPastDates) { > return moment().subtract('days', 1); > } else { > return moment(); > } > }; > var init = function () { > options = { > icons: { > time: "fa fa-clock-o icon-1x", > date: "fa fa-calendar icon-1x", > up: "fa fa-arrow-up", > down: "fa fa-arrow-down" > }, > //pickDate: true, > //pickTime: pickTime, > format: pickTime ? 'MM/DD/YYYY hh:mm:ss a' : 'MM/DD/YYYY', > //language: 'en', > locale: 'en', > //startDate: format(setStartDateLimit()), > //endDate: format(setEndDateLimit()), > minDate: format(setStartDateLimit()), > maxDate: format(setEndDateLimit()), > useStrict: true > }; > datetimepicker = element.find('.input-group').datetimepicker(options); > }; > > init(); > > controller.$render = function () { > var viewValue = controller.$viewValue; > if (viewValue) { > var date = moment(viewValue); > if (angular.isDefined(date) && date != null && moment.isMoment(date)) { > datetimepicker.data('DateTimePicker').date(date); > } > } else { > datetimepicker.data('DateTimePicker').date(setCalendarPickerStartDate()); > datetimepicker.data('DateTimePicker').date(); > } > return controller.$viewValue; > }; > > updateModel = function () { > //if (datetimepicker.data("DateTimePicker").minViewMode === datetimepicker.data("DateTimePicker").viewMode) { > datetimepicker.blur(); > //} > }; > > onblur = function () { > var newValue = datetimepicker.data("DateTimePicker").date(); > return scope.$evalAsync(function () { > scope.form.$setDirty(); > if (newValue) { > return controller.$setViewValue(format(moment(newValue))); > } else { > return controller.$setViewValue(); > } > }); > }; > > scope.$watch('compareDate', function () { > validate(); > }); > > scope.$watch('ngModel', function () { > validate(); > datetimepicker.on('dp.change', updateModel).on('blur', onblur); > }); > > scope.setBod = function () { > var viewValue = controller.$viewValue; > var bod = format(moment(viewValue).hours(0).minutes(0).seconds(0).milliseconds(0)); > datetimepicker.data("datetimepicker").date(bod); > scope.form.$setDirty(); > scope.ngModel = bod; > }; > > scope.setEod = function () { > var viewValue = controller.$viewValue; > var eod = format(moment(viewValue).hours(23).minutes(59).seconds(59).milliseconds(997)); > datetimepicker.data("DateTimePicker").date(eod); > scope.form.$setDirty(); > scope.ngModel = eod; > }; > > scope.setNow = function () { > var now = format(moment()); > datetimepicker.data("DateTimePicker").date(now); > scope.form.$setDirty(); > scope.ngModel = now; > }; > > //NOTE: We have to manually set these valid/invalid classes and required validation > //because we're not putting ng-model on the input field. > //We're not putting ng-model on the input field > //because two-way data-binding would prevent the user > //from being able to type in a date. > var validate = function () { > if (controller.$dirty || scope.form.$dirty) { > var input = $("#" + scope.name); > validateRequired(scope.ngModel); > validateFutureDate(input, scope.ngModel); > validatePastDate(input, scope.ngModel); > validateDateRange(scope.ngModel, scope.compareDate); > > if (controller.$error.daterange || > controller.$error.required || > controller.$error.futuredate || > controller.$error.pastdate) { > setInValid(input); > } else { > setValid(input); > } > } > }; > > var setValid = function (input) { > input.removeClass("ng-invalid"); > input.addClass("ng-valid"); > }; > > var setInValid = function (input) { > input.removeClass("ng-valid"); > input.addClass("ng-invalid"); > }; > > > var validateFutureDate = function (input, date) { > if (onlyFutureDates) { > var inputValue = element.find('input').val(); > if (!inputValue) { > setFutureDateValidity(true); > } else if (moment(date) <= moment()) { > setFutureDateValidity(false); > } else { > setFutureDateValidity(true); > } > } > }; > > var validatePastDate = function (input, date) { > if (onlyPastDates) { > var inputValue = element.find('input').val(); > if (!inputValue) { > setPastDateValidity(true); > } else if (moment(date) >= moment()) { > setPastDateValidity(false); > } else { > setPastDateValidity(true); > } > } > }; > > var validateDateRange = function (ngModel, compareDate) { > if (isDateRange && > !controller.$error.futuredate && > !controller.$error.pastdate) { > var inputValue = element.find('input').val(); > if (!ngModel && !compareDate) { > setDateRangeValidity(true); > } else if ((!ngModel || !compareDate) && > (ngModel || compareDate) && !inputValue) {//here we need to check the input value if we can > setDateRangeValidity(false); > } else { > var newStartDate; > var newEndDate; > if (isEndDate) { > newEndDate = moment(ngModel); > newStartDate = moment(compareDate); > } else { > newStartDate = moment(ngModel); > newEndDate = moment(compareDate); > } > if (newStartDate.isBefore(newEndDate) || > newStartDate.isSame(newEndDate)) { > setDateRangeValidity(true); > } else { > setDateRangeValidity(false); > } > } > } else { > setDateRangeValidity(true); > } > }; > > var validateRequired = function (input, date) { > if (isRequired) { > if (date) { > setRequiredValidity(true); > } else { > setRequiredValidity(false); > } > } > }; > > scope.validStartDateRange = function () { > if (isDateRange) { > return (!(controller.$error.daterange && (controller.$dirty || scope.form.$dirty) && !isEndDate)); > } > return true; > }; > > scope.validEndDateRange = function () { > if (isDateRange) { > return (!(controller.$error.daterange && (controller.$dirty || scope.form.$dirty) && isEndDate)); > } > return true; > }; > > scope.validRequired = function () { > if (isRequired) { > return (!(controller.$error.required && controller.$dirty)); > } > return true; > }; > > scope.validFutureDate = function () { > if (onlyFutureDates) { > return (!(controller.$error.futuredate && controller.$dirty)); > } > return true; > }; > > scope.validPastDate = function () { > if (onlyPastDates) { > return (!(controller.$error.pastdate && controller.$dirty)); > } > return true; > }; > > var setRequiredValidity = function (valid) { > controller.$setValidity('required', valid); > }; > > var setFutureDateValidity = function (valid) { > controller.$setValidity('futuredate', valid); > }; > > var setPastDateValidity = function (valid) { > controller.$setValidity('pastdate', valid); > }; > > var setDateRangeValidity = function (valid) { > controller.$setValidity('daterange', valid); > }; > > var hasInputValue = function (input) { > return input.length > 0; > }; > } > }; > }]); >})();How about the template ?