Skip to content
Snippets Groups Projects
Commit 24893775 authored by colemanw's avatar colemanw
Browse files

Merge pull request #1242 from colemanw/searchBuilderJs

Refactor search builder js to better handle different operators
parents 95d68223 057428a0
No related branches found
No related tags found
No related merge requests found
// http://civicrm.org/licensing
(function($, CRM) {
// @var: default select operator options
var operators, operatorCount;
'use strict';
/**
* Handle Field Selection
* Handle user input - field or operator selection.
*
* Decide whether to display select drop down, regular text or date
* field for the given field and row.
*/
function handleFieldSelection() {
var field = $(this).val();
function handleUserInputField() {
var row = $(this).closest('tr');
var field = $('select[id^=mapper][id$="_1"]', row).val();
var op = $('select[id^=operator]', row).val();
// These Ops don't get any input field.
var noFieldOps = ['', 'IS EMPTY', 'IS NOT EMPTY', 'IS NULL', 'IS NOT NULL'];
if ($.inArray(op, noFieldOps) > -1) {
// Hide the fields and return.
$('.crm-search-value', row).hide().find('input, select').val('');
return;
}
$('.crm-search-value', row).show();
if (!CRM.searchBuilder.fieldOptions[field]) {
removeSelect(row);
}
if ($.inArray(field, CRM.searchBuilder.dateFields) < 0) {
removeDate(row);
if (CRM.searchBuilder.fieldOptions[field]) {
buildSelect(row, field);
}
}
else {
buildDate(row);
buildSelect(row, field, op);
}
}
/**
* Handle Search Operator Selection
*/
function handleOperatorSelection() {
var noValue = ['', 'IS EMPTY', 'IS NOT EMPTY', 'IS NULL', 'IS NOT NULL'];
var row = $(this).closest('tr');
if ($.inArray($(this).val(), noValue) < 0) {
$('.crm-search-value', row).show();
// Change between multiselect and select when using "IN" operator
var select = $('.crm-search-value select', row);
if (select.length) {
var value = select.val() || '';
var multi = ($(this).val() == 'IN' || $(this).val() == 'NOT IN');
select.attr('multiple', multi);
if (multi) {
$('option[value=""]', select).remove();
}
else if ($('option[value=""]', select).length < 1) {
$(select).prepend('<option value="">' + ts('- select -') + '</option>');
}
select.val(value).change();
}
if ($.inArray(field, CRM.searchBuilder.dateFields) < 0) {
removeDate(row);
}
// Hide value field if the operator doesn't take a value
else {
$('.crm-search-value', row).hide().find('input, select').val('');
buildDate(row, op);
}
}
/**
* Give user a list of options to choose from
* Add select list if appropriate for this operation
* @param row: jQuery object
* @param field: string
*/
function buildSelect(row, field) {
// Remove operators that can't be used with a select
removeOperators(row, ['LIKE', 'RLIKE']);
var op = $('select[id^=operator]', row);
if (op.val() == 'IN' || op.val() == 'NOT IN') {
var multiSelect = 'multiple="multiple">';
function buildSelect(row, field, op) {
var multiSelect = '';
// Operators that will get a single drop down list of choices.
var dropDownSingleOps = ['=', '!='];
// Multiple select drop down list.
var dropDownMultipleOps = ['IN', 'NOT IN'];
if ($.inArray(op, dropDownMultipleOps) > -1) {
multiSelect = 'multiple="multiple"';
}
else {
var multiSelect = '><option value="">' + ts('- select -') + '</option>';
else if ($.inArray(op, dropDownSingleOps) < 0) {
// If this op is neither supported by single or multiple selects, then we should not render a select list.
removeSelect(row);
return;
}
$('.crm-search-value select', row).remove();
$('input[id^=value]', row).hide().after('<select class="form-select required" ' + multiSelect + '</select>');
$('input[id^=value]', row)
.hide()
.after('<select class="form-select required" ' + multiSelect + '><option value="">' + ts('Loading') + '...</option></select>');
fetchOptions(row, field);
}
......@@ -117,9 +112,14 @@
value = value.slice(1, -1);
}
var options = value.split(',');
var op = $('select[id^=operator]', row);
if (op.val() != 'IN' && op.val() != 'NOT IN' && options.length > 1) {
options = [options[0]];
if (select.attr('multiple') == 'multiple') {
select.find('option').remove();
}
else {
select.find('option').text(ts('- select -'));
if (options.length > 1) {
options = [options[0]];
}
}
$.each(CRM.searchBuilder.fieldOptions[field], function(value, label) {
var selected = ($.inArray(value, options) > -1) ? 'selected="selected"' : '';
......@@ -135,18 +135,20 @@
function removeSelect(row) {
$('.crm-search-value input', row).show();
$('.crm-search-value select', row).remove();
restoreOperators(row);
}
/**
* Add a datepicker
* Add a datepicker if appropriate for this operation
* @param row: jQuery object
*/
function buildDate(row) {
function buildDate(row, op) {
var input = $('.crm-search-value input', row);
if (!input.hasClass('hasDatepicker')) {
// Remove operators that can't be used with a date
removeOperators(row, ['IN', 'NOT IN', 'LIKE', 'RLIKE', 'IS EMPTY', 'IS NOT EMPTY']);
// These are operations that should not get a datepicker
var datePickerOp = ($.inArray(op, ['IN', 'NOT IN', 'LIKE', 'RLIKE']) < 0);
if (!datePickerOp) {
removeDate(row);
}
else if (!input.hasClass('hasDatepicker')) {
input.addClass('dateplugin').datepicker({
dateFormat: 'yymmdd',
changeMonth: true,
......@@ -163,115 +165,78 @@
function removeDate(row) {
var input = $('.crm-search-value input', row);
if (input.hasClass('hasDatepicker')) {
restoreOperators(row);
input.removeClass('dateplugin').val('').datepicker('destroy');
}
}
/**
* Remove operators from a row
* @param row: jQuery object
* @param illegal: array
*/
function removeOperators(row, illegal) {
var value = $('select[id^=operator]').val();
$('select[id^=operator] option', row).each(function() {
if ($.inArray($(this).attr('value'), illegal) > -1) {
$(this).remove();
}
});
if (value !== $('select[id^=operator]').val()) {
$('select[id^=operator]').change();
}
}
/**
* Restore operators to the default
* @param row: jQuery object
*/
function restoreOperators(row) {
var op = $('select[id^=operator]', row);
if ($('option', op).length != operatorCount) {
var value = op.val();
op.html(operators).val(value).change();
}
}
$('document').ready(function() {
operators = $('#operator_1_0').html();
operatorCount = $('#operator_1_0 option').length;
// Hide empty blocks & fields
var newBlock = CRM.searchBuilder && CRM.searchBuilder.newBlock || 0;
$('#Builder .crm-search-block').each(function(blockNo) {
var block = $(this);
var empty = blockNo + 1 > newBlock;
var skippedRow = false;
$('tr:not(.crm-search-builder-add-row)', block).each(function(rowNo) {
var row = $(this);
if ($('select:first', row).val() === '') {
if (!skippedRow && (rowNo == 0 || blockNo + 1 == newBlock)) {
skippedRow = true;
}
else {
row.hide();
}
// Initialize display: Hide empty blocks & fields
var newBlock = CRM.searchBuilder && CRM.searchBuilder.newBlock || 0;
$('.crm-search-block', '#Builder').each(function(blockNo) {
var block = $(this);
var empty = blockNo + 1 > newBlock;
var skippedRow = false;
$('tr:not(.crm-search-builder-add-row)', block).each(function(rowNo) {
var row = $(this);
if ($('select:first', row).val() === '') {
if (!skippedRow && (rowNo == 0 || blockNo + 1 == newBlock)) {
skippedRow = true;
}
else {
empty = false;
row.hide();
}
});
if (empty) {
block.hide();
}
else {
empty = false;
}
});
if (empty) {
block.hide();
}
});
$('#Builder')
// Reset and hide row
.on('click', '.crm-reset-builder-row', function() {
var row = $(this).closest('tr');
$('input, select', row).val('').change();
row.hide();
// Hide entire block if this is the only visible row
if (row.siblings(':visible').length < 2) {
row.closest('.crm-search-block').hide();
}
$('#Builder')
// Reset and hide row
.on('click', '.crm-reset-builder-row', function() {
var row = $(this).closest('tr');
$('input, select', row).val('').change();
row.hide();
// Hide entire block if this is the only visible row
if (row.siblings(':visible').length < 2) {
row.closest('.crm-search-block').hide();
}
return false;
})
// Add new field - if there's a hidden one, show it
// Otherwise allow form to submit and fetch more from the server
.on('click', 'input[name^=addMore]', function() {
var table = $(this).closest('table');
if ($('tr:hidden', table).length) {
$('tr:hidden', table).first().show();
return false;
})
// Add new field - if there's a hidden one, show it
// Otherwise we submit form to fetch more from the server
.on('click', 'input[name^=addMore]', function() {
var table = $(this).closest('table');
if ($('tr:hidden', table).length) {
$('tr:hidden', table).first().show();
return false;
}
})
// Add new block - if there's a hidden one, show it
// Otherwise we submit form to fetch more from the server
.on('click', '#addBlock', function() {
if ($('.crm-search-block:hidden', '#Builder').length) {
var block = $('.crm-search-block:hidden', '#Builder').first();
block.show();
$('tr:first-child, tr.crm-search-builder-add-row', block).show();
return false;
}
})
// Handle field selection
.on('change', 'select[id^=mapper][id$="_1"]', handleFieldSelection)
// Handle operator selection
.on('change', 'select[id^=operator]', handleOperatorSelection)
// Handle option selection - update hidden value field
.on('change', '.crm-search-value select', function() {
var value = $(this).val() || '';
if ($(this).attr('multiple') == 'multiple' && value.length) {
value = '(' + value.join(',') + ')';
}
$(this).siblings('input').val(value);
})
;
$('select[id^=operator]', '#Builder').each(handleOperatorSelection);
$().crmAccordions();
$('select[id^=mapper][id$="_1"] option[selected=selected]:not([value=""])', '#Builder').parent().each(handleFieldSelection);
});
}
})
// Add new block - if there's a hidden one, show it
// Otherwise allow form to submit and fetch more from the server
.on('click', '#addBlock', function() {
if ($('.crm-search-block:hidden', '#Builder').length) {
var block = $('.crm-search-block:hidden', '#Builder').first();
block.show();
$('tr:first-child, tr.crm-search-builder-add-row', block).show();
return false;
}
})
// Handle field and operator selection
.on('change', 'select[id^=mapper][id$="_1"], select[id^=operator]', handleUserInputField)
// Handle option selection - update hidden value field
.on('change', '.crm-search-value select', function() {
var value = $(this).val() || '';
if ($(this).attr('multiple') == 'multiple' && value.length) {
value = '(' + value.join(',') + ')';
}
$(this).siblings('input').val(value);
})
;
$().crmAccordions();
$('select[id^=mapper][id$="_1"]', '#Builder').each(handleUserInputField);
})(cj, CRM);
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment