Disable recipient estimation on mailings
[civicrm-core.git] / js / crm.datepicker.js
CommitLineData
403c52ac 1(function($, CRM, _) {
2 "use strict";
3
4 /**
6f55e2a8 5 * @see https://docs.civicrm.org/dev/en/latest/framework/ui/#date-picker
403c52ac 6 */
7 $.fn.crmDatepicker = function(options) {
8 return $(this).each(function() {
9 if ($(this).is('.crm-form-date-wrapper .crm-hidden-date')) {
10 // Already initialized - destroy
11 $(this)
12 .off('.crmDatepicker')
13 .css('display', '')
14 .removeClass('crm-hidden-date')
15 .siblings().remove();
16 $(this).unwrap();
17 }
18 if (options === 'destroy') {
19 return;
20 }
21 var
22 $dataField = $(this).wrap('<span class="crm-form-date-wrapper" />'),
ff2eb9e8 23 settings = _.cloneDeep(options || {}),
403c52ac 24 $dateField = $(),
25 $timeField = $(),
26 $clearLink = $(),
351719bf 27 placeholder,
403c52ac 28 hasDatepicker = settings.date !== false && settings.date !== 'yy',
29 type = hasDatepicker ? 'text' : 'number';
30
31 if (settings.allowClear !== undefined ? settings.allowClear : !$dataField.is('.required, [required]')) {
13a3d214 32 $clearLink = $('<a class="crm-hover-button crm-clear-link" title="'+ _.escape(ts('Clear')) +'"><i class="crm-i fa-times" aria-hidden="true"></i></a>')
403c52ac 33 .insertAfter($dataField);
34 }
35 if (settings.time !== false) {
36 $timeField = $('<input>').insertAfter($dataField);
351719bf 37 placeholder = settings.timePlaceholder || $dataField.attr('time-placeholder');
403c52ac 38 CRM.utils.copyAttributes($dataField, $timeField, ['class', 'disabled']);
39 $timeField
40 .addClass('crm-form-text crm-form-time')
351719bf
CW
41 // Set default placeholder as clock icon (`fa-clock` is Unicode f017)
42 .attr('placeholder', placeholder === undefined ? '\uf017' : placeholder)
43 .attr('aria-label', placeholder === undefined ? ts('Time') : placeholder)
403c52ac 44 .change(updateDataField)
45 .timeEntry({
46 spinnerImage: '',
7f83fd31 47 useMouseWheel: false,
403c52ac 48 show24Hours: settings.time === true || settings.time === undefined ? CRM.config.timeIs24Hr : settings.time == '24'
49 });
351719bf
CW
50 if (!placeholder) {
51 $timeField.addClass('crm-placeholder-icon');
52 }
403c52ac 53 }
54 if (settings.date !== false) {
55 // Render "number" field for year-only format, calendar popup for all other formats
56 $dateField = $('<input type="' + type + '">').insertAfter($dataField);
351719bf
CW
57 CRM.utils.copyAttributes($dataField, $dateField, ['style', 'class', 'disabled', 'aria-label']);
58 placeholder = settings.placeholder || $dataField.attr('placeholder');
403c52ac 59 $dateField.addClass('crm-form-' + type);
95325b63 60 if (!settings.minDate && isInt(settings.start_date_years)) {
1c32ff27
CW
61 settings.minDate = '' + (new Date().getFullYear() - settings.start_date_years) + '-01-01';
62 }
95325b63 63 if (!settings.maxDate && isInt(settings.end_date_years)) {
1c32ff27
CW
64 settings.maxDate = '' + (new Date().getFullYear() + settings.end_date_years) + '-12-31';
65 }
403c52ac 66 if (hasDatepicker) {
67 settings.minDate = settings.minDate ? CRM.utils.makeDate(settings.minDate) : null;
68 settings.maxDate = settings.maxDate ? CRM.utils.makeDate(settings.maxDate) : null;
69 settings.dateFormat = typeof settings.date === 'string' ? settings.date : CRM.config.dateInputFormat;
ff2eb9e8
CW
70 settings.changeMonth = _.includes(settings.dateFormat, 'm');
71 settings.changeYear = _.includes(settings.dateFormat, 'y');
403c52ac 72 if (!settings.yearRange && settings.minDate !== null && settings.maxDate !== null) {
73 settings.yearRange = '' + CRM.utils.formatDate(settings.minDate, 'yy') + ':' + CRM.utils.formatDate(settings.maxDate, 'yy');
74 }
351719bf 75 $dateField.addClass('crm-form-date').datepicker(settings);
403c52ac 76 } else {
77 $dateField.attr('min', settings.minDate ? CRM.utils.formatDate(settings.minDate, 'yy') : '1000');
78 $dateField.attr('max', settings.maxDate ? CRM.utils.formatDate(settings.maxDate, 'yy') : '4000');
5b7dd006 79 placeholder = null;
403c52ac 80 }
351719bf
CW
81 // Set placeholder as calendar icon (`fa-calendar` is Unicode f073)
82 $dateField.attr({placeholder: placeholder === undefined ? '\uF073' : placeholder}).change(updateDataField);
83 if (!placeholder) {
84 $dateField.addClass('crm-placeholder-icon');
85 }
403c52ac 86 }
87 // Rudimentary validation. TODO: Roll into use of jQUery validate and ui.datepicker.validation
88 function isValidDate() {
89 // FIXME: parseDate doesn't work with incomplete date formats; skip validation if no month, day or year in format
90 var lowerFormat = settings.dateFormat.toLowerCase();
91 if (lowerFormat.indexOf('y') < 0 || lowerFormat.indexOf('m') < 0 || !dateHasDay()) {
92 return true;
93 }
94 try {
95 $.datepicker.parseDate(settings.dateFormat, $dateField.val());
96 return true;
97 } catch (e) {
98 return false;
99 }
100 }
101
102 /**
103 * Does the date format contain the day.
104 *
105 * @returns {boolean}
106 */
107 function dateHasDay() {
108 var lowerFormat = settings.dateFormat.toLowerCase();
95325b63 109 return lowerFormat.indexOf('d') >= 0;
403c52ac 110 }
111 function updateInputFields(e, context) {
112 var val = $dataField.val(),
113 time = null;
114 if (context !== 'userInput' && context !== 'crmClear') {
115 if (hasDatepicker) {
ff2eb9e8 116 $dateField.datepicker('setDate', _.includes(val, '-') ? $.datepicker.parseDate('yy-mm-dd', val) : null);
403c52ac 117 } else if ($dateField.length) {
118 $dateField.val(val.slice(0, 4));
119 }
120 if ($timeField.length) {
121 if (val.length === 8) {
122 time = val;
123 } else if (val.length === 19) {
124 time = val.split(' ')[1];
125 }
126 $timeField.timeEntry('setTime', time);
127 }
128 }
129 $clearLink.css('visibility', val ? 'visible' : 'hidden');
130 }
131 function updateDataField(e, context) {
132 // The crmClear event wipes all the field values anyway, so no need to respond
133 if (context !== 'crmClear') {
134 var val = '';
135 if ($dateField.val()) {
136 if (hasDatepicker && isValidDate() && dateHasDay()) {
137 val = $.datepicker.formatDate('yy-mm-dd', $dateField.datepicker('getDate'));
138 $dateField.removeClass('crm-error');
139 } else if (!hasDatepicker) {
140 val = $dateField.val() + '-01-01';
141 }
142 else if (!dateHasDay()) {
143 // This would be a Year-month date (yyyy-mm)
144 // it could be argued it should not use a datepicker....
145 val = $dateField.val() + '-01';
146 } else {
147 $dateField.addClass('crm-error');
148 }
149 }
150 if ($timeField.val()) {
151 val += (val ? ' ' : '') + $timeField.timeEntry('getTime').toTimeString().substr(0, 8);
152 }
153 $dataField.val(val).trigger('change', ['userInput']);
154 }
155 }
156 $dataField.hide().addClass('crm-hidden-date').on('change.crmDatepicker', updateInputFields);
157 updateInputFields();
158 });
159 };
95325b63
CW
160
161 function isInt(value) {
162 if (isNaN(value)) {
163 return false;
164 }
165 var x = parseFloat(value);
166 return (x | 0) === x;
167 }
168
403c52ac 169})(jQuery, CRM, CRM._);