*/
function ts(text, params) {
"use strict";
- text = CRM.strings[text] || text;
+ var d = (params && params.domain) ? ('strings::' + params.domain) : null;
+ if (d && CRM[d] && CRM[d][text]) {
+ text = CRM[d][text];
+ }
+ else if (CRM['strings'][text]) {
+ text = CRM['strings'][text];
+ }
if (typeof(params) === 'object') {
for (var i in params) {
if (typeof(params[i]) === 'string' || typeof(params[i]) === 'number') {
*/
function on_load_init_blocks(showBlocks, hideBlocks, elementType) {
if (elementType == null) {
- var elementType = 'block';
+ elementType = 'block';
}
+ var myElement, i;
+
/* This loop is used to display the blocks whose IDs are present within the showBlocks array */
- for (var i = 0; i < showBlocks.length; i++) {
- var myElement = document.getElementById(showBlocks[i]);
+ for (i = 0; i < showBlocks.length; i++) {
+ myElement = document.getElementById(showBlocks[i]);
/* getElementById returns null if element id doesn't exist in the document */
if (myElement != null) {
myElement.style.display = elementType;
}
/* This loop is used to hide the blocks whose IDs are present within the hideBlocks array */
- for (var i = 0; i < hideBlocks.length; i++) {
- var myElement = document.getElementById(hideBlocks[i]);
+ for (i = 0; i < hideBlocks.length; i++) {
+ myElement = document.getElementById(hideBlocks[i]);
/* getElementById returns null if element id doesn't exist in the document */
if (myElement != null) {
myElement.style.display = 'none';
* @param invert Boolean - if true, we HIDE target on value match; if false, we SHOW target on value match
*/
function showHideByValue(trigger_field_id, trigger_value, target_element_id, target_element_type, field_type, invert) {
+ var target, j;
if (field_type == 'select') {
var trigger = trigger_value.split("|");
var selectedOptionValue = cj('#' + trigger_field_id).val();
- var target = target_element_id.split("|");
- for (var j = 0; j < target.length; j++) {
+ target = target_element_id.split("|");
+ for (j = 0; j < target.length; j++) {
if (invert) {
cj('#' + target[j]).show();
}
}
else {
if (field_type == 'radio') {
- var target = target_element_id.split("|");
- for (var j = 0; j < target.length; j++) {
+ target = target_element_id.split("|");
+ for (j = 0; j < target.length; j++) {
if (cj('[name="' + trigger_field_id + '"]:first').is(':checked')) {
if (invert) {
cj('#' + target[j]).hide();
/**
* Render an option list
- * @param options array
- * @param val default value
- * @internal param rendered
+ * @param options {array}
+ * @param val {string} default value
+ * @param escapeHtml {bool}
* @return string
*/
- CRM.utils.renderOptions = function(options, val) {
- var rendered = arguments[2] || '';
+ CRM.utils.renderOptions = function(options, val, escapeHtml) {
+ var rendered = '',
+ esc = escapeHtml === false ? _.identity : _.escape;
if (!$.isArray(val)) {
val = [val];
}
_.each(options, function(option) {
if (option.children) {
- rendered += '<optgroup label="' + option.value + '">' +
- CRM.utils.renderOptions(option.children, val, rendered) +
+ rendered += '<optgroup label="' + esc(option.value) + '">' +
+ CRM.utils.renderOptions(option.children, val) +
'</optgroup>';
} else {
var selected = ($.inArray('' + option.key, val) > -1) ? 'selected="selected"' : '';
- rendered += '<option value="' + option.key + '"' + selected + '>' + option.value + '</option>';
+ rendered += '<option value="' + esc(option.key) + '"' + selected + '>' + esc(option.value) + '</option>';
}
});
return rendered;
$(this).nextUntil('option[value^=crm_optgroup]').wrapAll('<optgroup label="' + $(this).text() + '" />');
$(this).remove();
});
+
+ // quickform does not support disabled option, so yet another hack to
+ // add disabled property for option values
+ $('option[value^=crm_disabled_opt]', this).attr('disabled', 'disabled');
+
// Defaults for single-selects
if ($el.is('select:not([multiple])')) {
settings.minimumResultsForSearch = 10;
else {
selectParams.formatInputTooShort = function() {
var txt = $el.data('select-params').formatInputTooShort || $.fn.select2.defaults.formatInputTooShort.call(this);
- txt += renderEntityRefFilters($el);
- txt += renderEntityRefCreateLinks($el);
+ txt += renderEntityRefFilters($el) + renderEntityRefCreateLinks($el);
return txt;
};
selectParams.formatNoMatches = function() {
var txt = $el.data('select-params').formatNoMatches || $.fn.select2.defaults.formatNoMatches;
- txt += renderEntityRefFilters($el);
- txt += renderEntityRefCreateLinks($el);
+ txt += renderEntityRefFilters($el) + renderEntityRefCreateLinks($el);
return txt;
};
$el.on('select2-open.crmEntity', function() {
filter = $.extend({}, $el.data('user-filter') || {});
if (filter.key && filter.value) {
// 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 (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];
} else {
- combined.params[filter.key] = filter.value;
+ // Allow json-encoded api filters e.g. {"BETWEEN":[123,456]}
+ combined.params[filter.key] = filter.value.charAt(0) === '{' ? $.parseJSON(filter.value) : filter.value;
}
}
return combined;
}
else if (this.key == 'contact_type' && typeof params.contact_sub_type === 'undefined') {
this.options = _.remove(this.options, function(option) {
- return option.key.indexOf(params.contact_type + '.') === 0;
+ return option.key.indexOf(params.contact_type + '__') === 0;
});
result.push(this);
}
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, sequential: 1})
+ CRM.api3(filterSpec.entity || $el.data('api-entity'), 'getoptions', {field: filter.key, context: 'search', sequential: 1})
.done(function(result) {
var entity = $el.data('api-entity').toLowerCase(),
globalFilterSpec = _.find(CRM.config.entityRef.filters[entity], {key: filter.key}) || {};
}
}
+ //CRM-15598 - Override url validator method to allow relative url's (e.g. /index.htm)
+ $.validator.addMethod("url", function(value, element) {
+ if (/^\//.test(value)) {
+ // Relative url: prepend dummy path for validation.
+ value = 'http://domain.tld' + value;
+ }
+ // From jQuery Validation Plugin v1.12.0
+ return this.optional(element) || /^(https?|s?ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(value);
+ });
+
/**
* Wrapper for jQuery validate initialization function; supplies defaults
*/
var opts = $.extend({
start: ts('Saving...'),
success: ts('Saved'),
- error: function() {
- CRM.alert(ts('Sorry an error occurred and your information was not saved'), ts('Error'));
+ error: function(data) {
+ var msg = $.isPlainObject(data) && data.error_message;
+ CRM.alert(msg || ts('Sorry an error occurred and your information was not saved'), ts('Error'), 'error');
}
}, options || {});
var $msg = $('<div class="crm-status-box-outer status-start"><div class="crm-status-box-inner"><div class="crm-status-box-msg">' + opts.start + '</div></div></div>')
if (endMsg) {
$msg.removeClass('status-start').addClass('status-' + status).find('.crm-status-box-msg').html(endMsg);
window.setTimeout(function() {
- $msg.fadeOut('slow', function() {$msg.remove()});
+ $msg.fadeOut('slow', function() {
+ $msg.remove();
+ });
}, 2000);
} else {
$msg.remove();
});
};
+ // Convert an Angular promise to a jQuery promise
+ CRM.toJqPromise = function(aPromise) {
+ var jqDeferred = $.Deferred();
+ aPromise.then(
+ function(data) { jqDeferred.resolve(data); },
+ function(data) { jqDeferred.reject(data); }
+ // should we also handle progress events?
+ );
+ return jqDeferred.promise();
+ };
+
+ CRM.toAPromise = function($q, jqPromise) {
+ var aDeferred = $q.defer();
+ jqPromise.then(
+ function(data) { aDeferred.resolve(data); },
+ function(data) { aDeferred.reject(data); }
+ // should we also handle progress events?
+ );
+ return aDeferred.promise;
+ };
+
/**
* @see https://wiki.civicrm.org/confluence/display/CRMDOC/Notification+Reference
*/
};
};
+ CRM.addStrings = function(domain, strings) {
+ var bucket = (domain == 'civicrm' ? 'strings' : 'strings::' + domain);
+ CRM[bucket] = CRM[bucket] || {};
+ _.extend(CRM[bucket], strings);
+ };
+
/**
* @see https://wiki.civicrm.org/confluence/display/CRMDOC/Notification+Reference
*/
title = $label.text();
}
}
- $(this).addClass('error');
+ $(this).addClass('crm-error');
}
var msg = CRM.alert(text, title, 'error', $.extend(extra, options));
if ($(this).length) {
var ele = $(this);
setTimeout(function () {
ele.one('change', function () {
- msg && msg.close && msg.close();
+ if (msg && msg.close) msg.close();
ele.removeClass('error');
label.removeClass('crm-error');
});
if (typeof(response.crmMessages) == 'object') {
$.each(response.crmMessages, function(n, msg) {
CRM.alert(msg.text, msg.title, msg.type, msg.options);
- })
+ });
}
if (response.backtrace) {
CRM.console('log', response.backtrace);
/**
* @deprecated
*/
- $.fn.crmAccordions = function () {};
+ $.fn.crmAccordions = function () {
+ CRM.console('warn', 'Warning: $.crmAccordions was called. This function is deprecated and should not be used.');
+ };
/**
* Collapse or expand an accordion
* @param speed