-/*
- +--------------------------------------------------------------------+
- | CiviCRM version 4.4 |
- +--------------------------------------------------------------------+
- | Copyright CiviCRM LLC (c) 2004-2013 |
- +--------------------------------------------------------------------+
- | This file is a part of CiviCRM. |
- | |
- | CiviCRM is free software; you can copy, modify, and distribute it |
- | under the terms of the GNU Affero General Public License |
- | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
- | |
- | CiviCRM is distributed in the hope that it will be useful, but |
- | WITHOUT ANY WARRANTY; without even the implied warranty of |
- | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
- | See the GNU Affero General Public License for more details. |
- | |
- | You should have received a copy of the GNU Affero General Public |
- | License and the CiviCRM Licensing Exception along |
- | with this program; if not, contact CiviCRM LLC |
- | at info[AT]civicrm[DOT]org. If you have questions about the |
- | GNU Affero General Public License or the licensing of CiviCRM, |
- | see the CiviCRM license FAQ at http://civicrm.org/licensing |
- +--------------------------------------------------------------------+
- */
-
-/**
- * @file: global functions for CiviCRM
- * FIXME: We are moving away from using global functions. DO NOT ADD MORE.
- * @see CRM object - the better alternative to adding global functions
- */
-
+// https://civicrm.org/licensing
var CRM = CRM || {};
var cj = jQuery;
/**
* Short-named function for string translation, defined in global scope so it's available everywhere.
*
- * @param $text string string for translating
- * @param $params object key:value of additional parameters
+ * @param text string for translating
+ * @param params object key:value of additional parameters
*
- * @return string the translated string
+ * @return string
*/
function ts(text, params) {
"use strict";
* a list of 'blocks to show' and 'blocks to hide' and the template passes these parameters to
* this function.
*
- * @access public
+ * @deprecated
* @param showBlocks Array of element Id's to be displayed
* @param hideBlocks Array of element Id's to be hidden
* @param elementType Value to set display style to for showBlocks (e.g. 'block' or 'table-row' or ...)
- * @return none
*/
function on_load_init_blocks(showBlocks, hideBlocks, elementType) {
if (elementType == null) {
* This function is called when we need to show or hide a related form element (target_element)
* based on the value (trigger_value) of another form field (trigger_field).
*
- * @access public
+ * @deprecated
* @param trigger_field_id HTML id of field whose onchange is the trigger
* @param trigger_value List of integers - option value(s) which trigger show-element action for target_field
* @param target_element_id HTML id of element to be shown or hidden
* @param target_element_type Type of element to be shown or hidden ('block' or 'table-row')
* @param field_type Type of element radio/select
* @param invert Boolean - if true, we HIDE target on value match; if false, we SHOW target on value match
- * @return none
*/
function showHideByValue(trigger_field_id, trigger_value, target_element_id, target_element_type, field_type, invert) {
if (target_element_type == null) {
if (field_type == 'select') {
var trigger = trigger_value.split("|");
- var selectedOptionValue = document.getElementById(trigger_field_id).options[document.getElementById(trigger_field_id).selectedIndex].value;
+ var selectedOptionValue = cj('#' + trigger_field_id).val();
var target = target_element_id.split("|");
for (var j = 0; j < target.length; j++) {
if (field_type == 'radio') {
var target = target_element_id.split("|");
for (var j = 0; j < target.length; j++) {
- if (document.getElementsByName(trigger_field_id)[0].checked) {
+ if (cj('[name="' + trigger_field_id + '"]').is(':checked')) {
if (invert) {
cj('#' + target[j]).hide();
}
/**
* Function to change button text and disable one it is clicked
- *
+ * @deprecated
* @param obj object - the button clicked
* @param formID string - the id of the form being submitted
* @param string procText - button text after user clicks it
- * @return null
+ * @return bool
*/
var submitcount = 0;
/* Changes button label on submit, and disables button after submit for newer browsers.
}
}
}
-
+/**
+ * @deprecated
+ */
function popUp(URL) {
day = new Date();
id = day.getTime();
/**
* Function to show / hide the row in optionFields
- *
- * @param element name index, that whose innerHTML is to hide else will show the hidden row.
+ * @deprecated
+ * @param index string, element whose innerHTML is to hide else will show the hidden row.
*/
function showHideRow(index) {
if (index) {
(function ($, undefined) {
"use strict";
- // Set select2 defaults
- $.fn.select2.defaults.minimumResultsForSearch = 10;
+ $.fn.select2.defaults.dropdownCssClass = 'crm-container';
// https://github.com/ivaynberg/select2/pull/2090
$.fn.select2.defaults.width = 'resolve';
* Populate a select list, overwriting the existing options except for the placeholder.
* @param $el jquery collection - 1 or more select elements
* @param options array in format returned by api.getoptions
+ * @param removePlaceholder bool
*/
- CRM.utils.setOptions = function($el, options) {
+ CRM.utils.setOptions = function($el, options, removePlaceholder) {
$el.each(function() {
var
$elect = $(this),
- val = $elect.val() || [];
+ val = $elect.val() || [],
+ opts = removePlaceholder ? '' : '[value!=""]';
if (typeof(val) !== 'array') {
val = [val];
}
- $elect.find('option[value!=""]').remove();
- $.each(options, function(key, option) {
+ $elect.find('option' + opts).remove();
+ _.each(options, function(option) {
var selected = ($.inArray(''+option.key, val) > -1) ? 'selected="selected"' : '';
$elect.append('<option value="' + option.key + '"' + selected + '>' + option.value + '</option>');
});
- $elect.trigger('change');
- });
- };
-
- CRM.utils.formatSelect2Result = function(row) {
- var markup = '<table class="crm-select2-row"><tr>';
- if (row.image !== undefined) {
- markup += '<td class="crm-select2-image"><img src="' + row.image + '"/></td>';
- }
- markup += '<td><div class="crm-select2-row-label">' + row.label + '</div>';
- markup += '<div class="crm-select2-row-description">' + (row.description || '') + '</div>';
- markup += '</td></tr></table>';
- return markup;
- };
-
- CRM.utils.formatSelect2CreateLinks = function($el) {
- var markup = '';
- $.each($el.data('create-links'), function(k, link) {
- markup += ' <a class="crm-add-entity crm-hover-button" href="' + link.url + '">';
- if (link.name) {
- markup += '<span class="icon ' + link.name + '-icon"></span> ';
- }
- markup += link.label + '</a>';
+ $elect.trigger('crmOptionsUpdated', $.extend({}, options)).trigger('change');
});
- return markup;
};
- // Initialize widgets
- $(document).on('crmLoad', function(e) {
- $('table.row-highlight', e.target)
- .off('.rowHighlight')
- .on('change.rowHighlight', 'input.select-row, input.select-rows', function () {
- var target, table = $(this).closest('table');
- if ($(this).hasClass('select-rows')) {
- target = $('tbody tr', table);
- $('input.select-row', table).prop('checked', $(this).prop('checked'));
- }
- else {
- target = $(this).closest('tr');
- $('input.select-rows', table).prop('checked', $(".select-row:not(':checked')", table).length < 1);
- }
- target.toggleClass('crm-row-selected', $(this).is(':checked'));
- })
- .find('input.select-row:checked').parents('tr').addClass('crm-row-selected');
- $('.crm-select2', e.target).each(function() {
- var $el = $(this);
+ /**
+ * Wrapper for select2 initialization function; supplies defaults
+ * @param options object
+ */
+ $.fn.crmSelect2 = function(options) {
+ return $(this).each(function () {
+ var
+ $el = $(this),
+ defaults = {allowClear: !$el.hasClass('required')};
// quickform doesn't support optgroups so here's a hack :(
- $('option[value^=crm_optgroup]', this).each(function() {
+ $('option[value^=crm_optgroup]', this).each(function () {
$(this).nextUntil('option[value^=crm_optgroup]').wrapAll('<optgroup label="' + $(this).text() + '" />');
$(this).remove();
});
- // Get a copy of the data rather than a reference
- var options = $.extend({}, $el.data('select-params') || {});
- // Set placeholder from markup if not specified
+ // Defaults for single-selects
if ($el.is('select:not([multiple])')) {
- options.allowClear = options.allowClear !== undefined ? options.allowClear : !($el.hasClass('required'));
- if (options.placeHolder === undefined && $('option:first', this).val() === '') {
- options.placeholderOption = 'first';
+ defaults.minimumResultsForSearch = 10;
+ if ($('option:first', this).val() === '') {
+ defaults.placeholderOption = 'first';
}
}
- // Autocomplete using the getlist api
- if ($el.data('api-entity') && $el.hasClass('crm-form-entityref')) {
- $el.addClass('crm-ajax-select');
- var settings = {
- // Use select2 ajax helper instead of CRM.api because it provides more value
- ajax: {
- url: CRM.url('civicrm/ajax/rest'),
- data: function (input, page_num) {
- var params = $el.data('api-params') || {};
- params.input = input;
- params.page_num = page_num;
- return {
- entity: $el.data('api-entity'),
- action: 'getlist',
- json: JSON.stringify(params)
- };
- },
- results: function(data) {
- return {more: data.more_results, results: data.values || []};
- }
- },
- formatResult: CRM.utils.formatSelect2Result,
- formatSelection: function(row) {
- return row.label;
+ $el.select2($.extend(defaults, $el.data('select-params') || {}, options || {}));
+ });
+ };
+
+ /**
+ * @see CRM_Core_Form::addEntityRef for docs
+ * @param options object
+ */
+ $.fn.crmEntityRef = function(options) {
+ options = options || {};
+ options.select = options.select || {};
+ return $(this).each(function() {
+ var
+ $el = $(this),
+ entity = options.entity || $el.data('api-entity') || 'contact',
+ selectParams = {};
+ $el.data('api-entity', entity);
+ $el.data('select-params', $.extend({}, $el.data('select-params') || {}, options.select));
+ $el.data('api-params', $.extend({}, $el.data('api-params') || {}, options.api));
+ $el.data('create-links', options.create || $el.data('create-links'));
+ $el.addClass('crm-ajax-select crm-' + entity + '-ref');
+ var settings = {
+ // Use select2 ajax helper instead of CRM.api because it provides more value
+ ajax: {
+ url: CRM.url('civicrm/ajax/rest'),
+ data: function (input, page_num) {
+ var params = $el.data('api-params') || {};
+ params.input = input;
+ params.page_num = page_num;
+ return {
+ entity: $el.data('api-entity'),
+ action: 'getlist',
+ json: JSON.stringify(params)
+ };
},
- escapeMarkup: function (m) {return m;},
- initSelection: function(el, callback) {
- callback(el.data('entity-value'));
+ results: function(data) {
+ return {more: data.more_results, results: data.values || []};
+ }
+ },
+ minimumInputLength: 1,
+ formatResult: formatSelect2Result,
+ formatSelection: function(row) {
+ return row.label;
+ },
+ escapeMarkup: function (m) {return m;},
+ initSelection: function($el, callback) {
+ var
+ multiple = !!$el.data('select-params').multiple,
+ val = $el.val(),
+ stored = $el.data('entity-value') || [];
+ if (val === '') {
+ return;
+ }
+ // If we already have this data, just return it
+ if (!_.xor(val.split(','), _.pluck(stored, 'id')).length) {
+ callback(multiple ? stored : stored[0]);
+ } else {
+ var params = $.extend({}, $el.data('api-params') || {}, {id: val});
+ CRM.api3($el.data('api-entity'), 'getlist', params).done(function(result) {
+ callback(multiple ? result.values : result.values[0])
+ });
+ }
+ }
+ };
+ if ($el.data('create-links')) {
+ selectParams.formatInputTooShort = function() {
+ var txt = $el.data('select-params').formatInputTooShort || $.fn.select2.defaults.formatInputTooShort.call(this);
+ if ($el.data('create-links')) {
+ txt += ' ' + ts('or') + '<br />' + formatSelect2CreateLinks($el);
}
+ return txt;
};
- if ($el.data('create-links')) {
- options.formatInputTooShort = function() {
- return $el.data('select-params').formatInputTooShort + ' ' + ts('or') + '<br />' + CRM.utils.formatSelect2CreateLinks($el);
- };
- options.formatNoMatches = function() {
- return $el.data('select-params').formatNoMatches + '<br />' + CRM.utils.formatSelect2CreateLinks($el);
- };
- $el.on('select2-open', function() {
- var $el = $(this);
- $('#select2-drop').off('.crmEntity').on('click.crmEntity', 'a.crm-add-entity', function(e) {
- $el.select2('close');
- CRM.loadForm($(this).attr('href'), {
- dialog: {width: 500, height: 'auto'}
- }).on('crmFormSuccess', function(e, data) {
+ selectParams.formatNoMatches = function() {
+ var txt = $el.data('select-params').formatNoMatches || $.fn.select2.defaults.formatNoMatches;
+ return txt + '<br />' + formatSelect2CreateLinks($el);
+ };
+ $el.off('.createLinks').on('select2-open.createLinks', function() {
+ var $el = $(this);
+ $('#select2-drop').off('.crmEntity').on('click.crmEntity', 'a.crm-add-entity', function(e) {
+ $el.select2('close');
+ CRM.loadForm($(this).attr('href'), {
+ dialog: {width: 500, height: 'auto'}
+ }).on('crmFormSuccess', function(e, data) {
+ if (data.status === 'success' && data.id) {
if ($el.select2('container').hasClass('select2-container-multi')) {
var selection = $el.select2('data');
selection.push(data);
- $el.select2('data', selection);
+ $el.select2('data', selection, true);
} else {
- $el.select2('data', data);
+ $el.select2('data', data, true);
}
- });
- return false;
+ }
});
+ return false;
});
- }
- options = $.extend(settings, options);
+ });
+ }
+ $el.crmSelect2($.extend(settings, $el.data('select-params'), selectParams));
+ });
+ };
+
+ function formatSelect2Result(row) {
+ var markup = '<div class="crm-select2-row">';
+ if (row.image !== undefined) {
+ markup += '<div class="crm-select2-image"><img src="' + row.image + '"/></div>';
+ }
+ else if (row.icon_class) {
+ markup += '<div class="crm-select2-icon"><div class="crm-icon ' + row.icon_class + '-icon"></div></div>';
+ }
+ markup += '<div><div class="crm-select2-row-label">' + row.label + '</div>';
+ markup += '<div class="crm-select2-row-description">';
+ $.each(row.description || [], function(k, text) {
+ markup += '<p>' + text + '</p>';
+ });
+ markup += '</div></div></div>';
+ return markup;
+ }
+
+ function formatSelect2CreateLinks($el) {
+ var
+ createLinks = $el.data('create-links'),
+ api = $el.data('api-params') || {},
+ type = api.params ? api.params.contact_type : null;
+ if (createLinks === true) {
+ createLinks = type ? _.where(CRM.profile.contactCreate, {type: type}) : CRM.profile.contactCreate;
+ }
+ var markup = '';
+ _.each(createLinks, function(link) {
+ markup += ' <a class="crm-add-entity crm-hover-button" href="' + link.url + '">';
+ if (link.type) {
+ markup += '<span class="icon ' + link.type + '-profile-icon"></span> ';
+ }
+ markup += link.label + '</a>';
+ });
+ return markup;
+ }
+
+ // Initialize widgets
+ $(document)
+ .on('crmLoad', function(e) {
+ $('table.row-highlight', e.target)
+ .off('.rowHighlight')
+ .on('change.rowHighlight', 'input.select-row, input.select-rows', function () {
+ var target, table = $(this).closest('table');
+ if ($(this).hasClass('select-rows')) {
+ target = $('tbody tr', table);
+ $('input.select-row', table).prop('checked', $(this).prop('checked'));
+ }
+ else {
+ target = $(this).closest('tr');
+ $('input.select-rows', table).prop('checked', $(".select-row:not(':checked')", table).length < 1);
+ }
+ target.toggleClass('crm-row-selected', $(this).is(':checked'));
+ })
+ .find('input.select-row:checked').parents('tr').addClass('crm-row-selected');
+ $('.crm-select2:not(.select2-offscreen)', e.target).crmSelect2();
+ $('.crm-form-entityref:not(.select2-offscreen)', e.target).crmEntityRef();
+ })
+ // Modal dialogs should disable scrollbars
+ .on('dialogopen', function(e) {
+ if ($(e.target).dialog('option', 'modal')) {
+ $(e.target).addClass('modal-dialog');
+ $('body').css({overflow: 'hidden'});
+ }
+ })
+ .on('dialogclose', function(e) {
+ if ($('.ui-dialog .modal-dialog').not(e.target).length < 1) {
+ $('body').css({overflow: ''});
}
- options.dropdownCssClass = 'crm-container';
- $(this).select2(options).removeClass('crm-select2');
});
- });
/**
* Function to make multiselect boxes behave as fields in small screens
* passing in a function instead of an object is a shortcut for a sinlgle button labeled "Continue"
* @param options {object|void} Override defaults, keys include 'title', 'message',
* see jQuery.dialog for full list of available params
+ * @param cancelLabel {string}
*/
CRM.confirm = function (buttons, options, cancelLabel) {
var dialog, callbacks = {};
}
$.each(callbacks, function (label, callback) {
settings.buttons[label] = function () {
- callback.call(dialog);
- dialog.dialog('close');
+ if (callback.call(dialog) !== false) {
+ dialog.dialog('close');
+ }
};
});
dialog = $('<div class="crm-container crm-confirm-dialog"></div>')
settings.dialog = {
modal: true,
width: '65%',
- height: parseInt($(window).height() * .75),
- close: function() {
- $(this).dialog('destroy').remove();
- }
+ height: parseInt($(window).height() * .75)
};
}
options && $.extend(true, settings, options);
// Create new dialog
if (settings.dialog) {
$('<div id="'+ settings.target.substring(1) +'"><div class="crm-loading-element">' + ts('Loading') + '...</div></div>').dialog(settings.dialog);
+ $(settings.target).on('dialogclose', function() {
+ $(this).dialog('destroy').remove();
+ });
}
if (settings.dialog && !settings.dialog.title) {
- $(settings.target).on('crmLoad', function(event, data) {
- data.title && $(this).dialog('option', 'title', data.title);
+ $(settings.target).on('crmLoad', function(e, data) {
+ if (e.target === $(settings.target)[0] && data && data.title) {
+ $(this).dialog('option', 'title', data.title);
+ }
});
}
$(settings.target).crmSnippet(settings).crmSnippet('refresh');
return false;
});
}
+ // For convenience, focus the first field
+ $('input[type=text], textarea, select', this).filter(':visible').first().focus();
});
return widget;
};
}
})
- .on('click', 'a.crm-edit-optionvalue-link', function() {
- var url = $(this).data('option-group-url');
- CRM.loadForm(CRM.url(url, {reset: 1}), {openInline: 'a:not("[href=#], .no-popup")'})
+ .on('click', 'a.crm-option-edit-link', function() {
+ var
+ link = $(this),
+ optionsChanged = false;
+ CRM.loadForm(this.href, {openInline: 'a:not("[href=#], .no-popup")'})
+ .on('crmFormSuccess', function() {
+ optionsChanged = true;
+ })
.on('dialogclose', function() {
- var $elects = $('select[data-option-group-url="' + url + '"]');
- CRM.api3($elects.data('api-entity'), 'getoptions', {sequential: 1, field: $elects.data('api-field')})
- .done(function(data) {
- CRM.utils.setOptions($elects, data.values);
- });
+ if (optionsChanged) {
+ link.trigger('crmOptionsEdited');
+ var $elects = $('select[data-option-edit-path="' + link.data('option-edit-path') + '"]');
+ if ($elects.data('api-entity') && $elects.data('api-field')) {
+ CRM.api3($elects.data('api-entity'), 'getoptions', {sequential: 1, field: $elects.data('api-field')})
+ .done(function (data) {
+ CRM.utils.setOptions($elects, data.values);
+ });
+ }
+ }
});
return false;
})