1 (function(angular
, $, _
) {
2 // "YYYY-MM-DD hh:mm:ss" => Date()
3 function parseYmdHms(d
) {
4 var parts
= d
.split(/[\-: ]/);
5 return new Date(parts
[0], parts
[1]-1, parts
[2], parts
[3], parts
[4], parts
[5]);
8 function isDateBefore(tgt
, cutoff
, tolerance
) {
9 var ad
= parseYmdHms(tgt
), bd
= parseYmdHms(cutoff
);
10 // We'll allow a little leeway, where tgt is considered before cutoff
11 // even if technically misses the cutoff by a little.
12 return ad
< bd
-tolerance
;
15 // Represent a datetime field as if it were a radio ('schedule.mode') and a datetime ('schedule.datetime').
16 // example: <div crm-mailing-radio-date="mySchedule" ng-model="mailing.scheduled_date">...</div>
17 angular
.module('crmMailing').directive('crmMailingRadioDate', function(crmUiAlert
) {
20 link: function($scope
, element
, attrs
, ngModel
) {
23 var schedule
= $scope
[attrs
.crmMailingRadioDate
] = {
28 ngModel
.$render
= function $render() {
29 var sched
= ngModel
.$viewValue
;
30 if (!_
.isEmpty(sched
)) {
32 schedule
.datetime
= sched
;
35 schedule
.mode
= 'now';
36 schedule
.datetime
= '';
40 var updateParent
= (function() {
41 switch (schedule
.mode
) {
43 ngModel
.$setViewValue(null);
44 schedule
.datetime
= '';
47 schedule
.datetime
= schedule
.datetime
|| '?';
48 ngModel
.$setViewValue(schedule
.datetime
);
51 throw 'Unrecognized schedule mode: ' + schedule
.mode
;
56 // Open datepicker when clicking "At" radio
57 .on('click', ':radio[value=at]', function() {
58 $('.crm-form-date', element
).focus();
60 // Reset mode if user entered an invalid date
61 .on('change', '.crm-hidden-date', function(e
, context
) {
62 if (context
=== 'userInput' && $(this).val() === '' && $(this).siblings('.crm-form-date').val().length
) {
64 schedule
.datetime
= '?';
67 month
= '' + (d
.getMonth() + 1),
68 day
= '' + d
.getDate(),
69 year
= d
.getFullYear(),
70 hours
= '' + d
.getHours(),
71 minutes
= '' + d
.getMinutes();
72 var submittedDate
= $(this).val();
73 if (month
.length
< 2) month
= '0' + month
;
74 if (day
.length
< 2) day
= '0' + day
;
75 if (hours
.length
< 2) hours
= '0' + hours
;
76 if (minutes
.length
< 2) minutes
= '0' + minutes
;
77 date
= [year
, month
, day
].join('-');
78 time
= [hours
, minutes
, "00"].join(':');
79 currentDate
= date
+ ' ' + time
;
80 var isInPast
= (submittedDate
.length
&& submittedDate
.match(/^[0-9\-]+ [0-9\:]+$/) && isDateBefore(submittedDate
, currentDate
, 4*60*60*1000));
81 ngModel
.$setValidity('dateTimeInThePast', !isInPast
);
82 if (lastAlert
&& lastAlert
.isOpen
) {
86 lastAlert
= crmUiAlert({
87 text
: ts('The scheduled date and time is in the past'),
94 $scope
.$watch(attrs
.crmMailingRadioDate
+ '.mode', updateParent
);
95 $scope
.$watch(attrs
.crmMailingRadioDate
+ '.datetime', function(newValue
, oldValue
) {
96 // automatically switch mode based on datetime entry
97 if (typeof oldValue
=== 'undefined') {
100 if (typeof newValue
=== 'undefined') {
103 if (oldValue
!== newValue
) {
104 if (_
.isEmpty(newValue
)) {
105 schedule
.mode
= 'now';
108 schedule
.mode
= 'at';
116 })(angular
, CRM
.$, CRM
._
);