combined = _.cloneDeep(params),
filter = $.extend({}, $el.data('user-filter') || {});
if (filter.key && filter.value) {
+ // Fieldname may be prefixed with joins
+ var fieldName = _.last(filter.key.split('.'));
// Special case for contact type/sub-type combo
- if (filter.key === 'contact_type' && (filter.value.indexOf('__') > 0)) {
- combined.params.contact_type = filter.value.split('__')[0];
- combined.params.contact_sub_type = filter.value.split('__')[1];
+ if (fieldName === 'contact_type' && (filter.value.indexOf('__') > 0)) {
+ combined.params[filter.key] = filter.value.split('__')[0];
+ combined.params[filter.key.replace('contact_type', 'contact_sub_type')] = filter.value.split('__')[1];
} else {
// Allow json-encoded api filters e.g. {"BETWEEN":[123,456]}
combined.params[filter.key] = filter.value.charAt(0) === '{' ? $.parseJSON(filter.value) : filter.value;
function copyAttributes($source, $target, attributes) {
_.each(attributes, function(name) {
- if ($source.attr(name)) {
+ if ($source.attr(name) !== undefined) {
$target.attr(name, $source.attr(name));
}
});
$.fn.crmDatepicker = function(options) {
return $(this).each(function() {
if ($(this).is('.crm-form-date-wrapper .crm-hidden-date')) {
- // Already initialized
+ // Already initialized - destroy
+ $(this)
+ .off('.crmDatepicker')
+ .css('display', '')
+ .removeClass('crm-hidden-date')
+ .siblings().remove();
+ $(this).unwrap();
+ }
+ if (options === 'destroy') {
return;
}
var
$dataField = $(this).wrap('<span class="crm-form-date-wrapper" />'),
- settings = $.extend({}, $dataField.data('datepicker') || {}, options || {}),
+ settings = _.cloneDeep(options || {}),
$dateField = $(),
$timeField = $(),
- $clearLink = $();
+ $clearLink = $(),
+ hasDatepicker = settings.date !== false && settings.date !== 'yy',
+ type = hasDatepicker ? 'text' : 'number';
if (settings.allowClear !== undefined ? settings.allowClear : !$dataField.is('.required, [required]')) {
$clearLink = $('<a class="crm-hover-button crm-clear-link" title="'+ ts('Clear') +'"><i class="crm-i fa-times"></i></a>')
});
}
if (settings.date !== false) {
- $dateField = $('<input>').insertAfter($dataField);
+ // Render "number" field for year-only format, calendar popup for all other formats
+ $dateField = $('<input type="' + type + '">').insertAfter($dataField);
copyAttributes($dataField, $dateField, ['placeholder', 'style', 'class', 'disabled']);
- $dateField.addClass('crm-form-text crm-form-date');
- settings.date = typeof settings.date === 'string' ? settings.date : CRM.config.dateInputFormat;
- settings.changeMonth = _.includes('m', settings.date);
- settings.changeYear = _.includes('y', settings.date);
- $dateField.datepicker(settings).change(updateDataField);
+ $dateField.addClass('crm-form-' + type);
+ settings.minDate = settings.minDate ? CRM.utils.makeDate(settings.minDate) : null;
+ settings.maxDate = settings.maxDate ? CRM.utils.makeDate(settings.maxDate) : null;
+ if (hasDatepicker) {
+ settings.dateFormat = typeof settings.date === 'string' ? settings.date : CRM.config.dateInputFormat;
+ settings.changeMonth = _.includes(settings.dateFormat, 'm');
+ settings.changeYear = _.includes(settings.dateFormat, 'y');
+ $dateField.addClass('crm-form-date').datepicker(settings);
+ } else {
+ $dateField.attr('min', settings.minDate ? CRM.utils.formatDate(settings.minDate, 'yy') : '1000');
+ $dateField.attr('max', settings.maxDate ? CRM.utils.formatDate(settings.maxDate, 'yy') : '4000');
+ }
+ $dateField.change(updateDataField);
}
// Rudimentary validation. TODO: Roll into use of jQUery validate and ui.datepicker.validation
function isValidDate() {
+ // FIXME: parseDate doesn't work with incomplete date formats; skip validation if no month, day or year in format
+ var lowerFormat = settings.dateFormat.toLowerCase();
+ if (lowerFormat.indexOf('y') < 0 || lowerFormat.indexOf('m') < 0 || lowerFormat.indexOf('d') < 0) {
+ return true;
+ }
try {
- $.datepicker.parseDate(settings.date, $dateField.val());
+ $.datepicker.parseDate(settings.dateFormat, $dateField.val());
return true;
} catch (e) {
return false;
var val = $dataField.val(),
time = null;
if (context !== 'userInput' && context !== 'crmClear') {
- if ($dateField.length) {
+ if (hasDatepicker) {
$dateField.datepicker('setDate', _.includes(val, '-') ? $.datepicker.parseDate('yy-mm-dd', val) : null);
+ } else if ($dateField.length) {
+ $dateField.val(val.slice(0, 4));
}
if ($timeField.length) {
if (val.length === 8) {
if (context !== 'crmClear') {
var val = '';
if ($dateField.val()) {
- if (isValidDate()) {
+ if (hasDatepicker && isValidDate()) {
val = $.datepicker.formatDate('yy-mm-dd', $dateField.datepicker('getDate'));
$dateField.removeClass('crm-error');
+ } else if (!hasDatepicker) {
+ val = $dateField.val() + '-01-01';
} else {
$dateField.addClass('crm-error');
}
$dataField.val(val).trigger('change', ['userInput']);
}
}
- $dataField.hide().addClass('crm-hidden-date').on('change', updateInputFields);
+ $dataField.hide().addClass('crm-hidden-date').on('change.crmDatepicker', updateInputFields);
updateInputFields();
});
};
var defaults = {
"processing": true,
"serverSide": true,
+ "aaSorting": [],
"dom": '<"crm-datatable-pager-top"lfp>rt<"crm-datatable-pager-bottom"ip>',
"pageLength": 25,
"drawCallback": function(settings) {
CRM.utils.setOptions($valField, filterSpec.options, false, filter.value);
} else {
$valField.prop('disabled', true);
- CRM.api3(filterSpec.entity || $el.data('api-entity'), 'getoptions', {field: filter.key, context: 'search', sequential: 1})
+ // Fieldname may be prefixed with joins - strip those out
+ var fieldName = _.last(filter.key.split('.'));
+ CRM.api3(filterSpec.entity || $el.data('api-entity'), 'getoptions', {field: fieldName, context: 'search', sequential: 1})
.done(function(result) {
var entity = $el.data('api-entity').toLowerCase(),
globalFilterSpec = _.find(CRM.config.entityRef.filters[entity], {key: filter.key}) || {};
})
// Allow normal clicking of links within accordions
- .on('click.crmAccordions', 'div.crm-accordion-header a', function (e) {
+ .on('click.crmAccordions', 'div.crm-accordion-header a, .collapsible-title a', function (e) {
e.stopPropagation();
})
// Handle accordions