Skip to content

Instantly share code, notes, and snippets.

@grownseed
Created February 7, 2013 20:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save grownseed/4733922 to your computer and use it in GitHub Desktop.
Save grownseed/4733922 to your computer and use it in GitHub Desktop.
//adapted from https://github.com/mgcrea/angular-strap/blob/master/src/directives/datepicker.js
app.directive('datetime', ['$timeout', function($timeout) {
'use strict';
var DATE_REGEXP_MAP = {
'/' : '[\\/]',
'-' : '[-]',
'.' : '[.]',
dd: '(0?[1-9]|[1-2][0-9]|3[0-1])\\b',
MM: '(0?[1-9]|1[0-2])\\b',
yyyy: '(\\d{4})\\b',
yy: '(\\d{2})\\b',
HH: '(0?[0-9]|1[0-9]|2[0-3])\\b',
mm: '(0?[0-9]|[1-5][0-9])\\b',
ss: '(0?[0-9]|[1-5][0-9])\\b',
ms: '([0-9]{1,3})\\b',
hh: '(0?[1-9]|1[0-2])\\b',
PP: '(AM|PM|am|pm|Am|aM|Pm|pM)\\b'
};
return {
restrict: 'A',
require: '?ngModel',
link: function postLink(scope, element, attrs, controller) {
var regexpForDateFormat = function(dateFormat, options) {
options || (options = {});
var re = dateFormat, regexpMap = DATE_REGEXP_MAP;
angular.forEach(regexpMap, function(v, k) { re = re.split(k).join(v); });
return new RegExp('^' + re + '$', ['i']);
};
var dateFormat = attrs['datetime'] || 'dd/MM/yyyy HH:mm',
dateFormatRegexp = regexpForDateFormat(dateFormat);
//datetime picker hours format reversed from angular
var pickerFormat = dateFormat.split('HH');
for (var i = 0; i < pickerFormat.length; i++) {
pickerFormat[i] = pickerFormat[i].replace(/h/g, 'H');
}
pickerFormat = pickerFormat.join('hh');
// Handle date validity according to dateFormat
if(controller) {
controller.$parsers.unshift(function(viewValue) {
var min = true,
max = true,
current_date = $(element).parent().data('datetimepicker').getDate();
current_date.setSeconds(0);
current_date.setMilliseconds(0);
scope.$emit('$validate');
if (attrs['min']) {
var min_date = $(element).parent().data('datetimepicker').parseDate(attrs['min']);
min_date.setSeconds(0);
min_date.setMilliseconds(0);
if (min_date.getTime() >= current_date.getTime()) {
controller.$setValidity('datetime_min', false);
return undefined;
}else{
controller.$setValidity('datetime_min', true);
}
}
if (attrs['max']) {
var max_date = $(element).parent().data('datetimepicker').parseDate(attrs['max']);
max_date.setSeconds(0);
max_date.setMilliseconds(0);
if (max_date.getTime() <= current_date.getTime()) {
controller.$setValidity('datetime_max', false);
return undefined;
}else{
controller.$setValidity('datetime_max', true);
}
}
if ((!viewValue || dateFormatRegexp.test(viewValue)) && min && max) {
controller.$setValidity('datetime', true);
return viewValue;
} else {
controller.$setValidity('datetime', false);
return undefined;
}
});
}
var once = false;
scope.$watch($(element).attr('ng-model'), function(v) {
if (!v || once)
return;
once = true;
$(element).parent().data('datetimepicker').setLocalDate(new Date(v));
});
// If we have a controller (i.e. ngModelController) then wire it up
if(controller) {
$(element).parent().on('changeDate', function(ev) {
scope.$apply(function () {
controller.$setViewValue($(element).val());
});
});
}
// Popover GarbageCollection
var $popover = $(element).closest('.popover');
if($popover) {
$popover.on('hide', function(e) {
var datetimepicker = $(element).parent().data('datetimepicker');
if(datetimepicker) {
datetimepicker.picker.remove();
$(element).parent().data('datetimepicker', null);
}
});
}
// Create datetimepicker
$(element).parent().datetimepicker({
language: attrs.language || 'en',
format: pickerFormat
});
}
};
}]);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment