Mailing.gettokens api - Additional improvements
[civicrm-core.git] / templates / CRM / Admin / Page / APIExplorer.js
CommitLineData
e4176358 1(function($, _, undefined) {
89ee60d5
CW
2 "use strict";
3 /* jshint validthis: true */
e4176358
CW
4 var
5 entity,
6 action,
a14e9d08 7 actions = {values: ['get']},
e4176358 8 fields = [],
fc6a6a51 9 getFieldData = {},
e4176358
CW
10 options = {},
11 params = {},
2b6e1174 12 smartyStub,
8ffa1387 13 fieldTpl = _.template($('#api-param-tpl').html()),
c275764e 14 optionsTpl = _.template($('#api-options-tpl').html()),
b07af612 15 returnTpl = _.template($('#api-return-tpl').html()),
77099ee0 16 chainTpl = _.template($('#api-chain-tpl').html()),
bc4aa590 17 docCodeTpl = _.template($('#doc-code-tpl').html()),
77099ee0 18
f76eb8ae
CW
19 // These types of entityRef don't require any input to open
20 OPEN_IMMEDIATELY = ['RelationshipType', 'Event', 'Group', 'Tag'],
21
77099ee0
CW
22 // Operators with special properties
23 BOOL = ['IS NULL', 'IS NOT NULL'],
24 TEXT = ['LIKE', 'NOT LIKE'],
7b6c5043 25 SINGLE = ['>', '>=', '<', '<=', '<>', '!='],
77099ee0 26 MULTI = ['IN', 'NOT IN', 'BETWEEN', 'NOT BETWEEN'];
0c3a6e64 27
b07af612
CW
28 /**
29 * Add a "fields" row
30 * @param name
31 */
e4176358
CW
32 function addField(name) {
33 $('#api-params').append($(fieldTpl({name: name || ''})));
34 var $row = $('tr:last-child', '#api-params');
77099ee0 35 $('input.api-param-name', $row).crmSelect2({
b07af612
CW
36 data: fields.concat({id: '-', text: ts('Other') + '...'})
37 }).change();
8ffa1387
CW
38 }
39
c275764e
CW
40 /**
41 * Add a new "options" row
c275764e 42 */
cb6d8859 43 function addOptionField() {
c275764e
CW
44 if ($('.api-options-row', '#api-params').length) {
45 $('.api-options-row:last', '#api-params').after($(optionsTpl({})));
46 } else {
47 $('#api-params').append($(optionsTpl({})));
48 }
49 var $row = $('.api-options-row:last', '#api-params');
50 $('.api-option-name', $row).crmSelect2({data: [
51 {id: 'limit', text: 'limit'},
52 {id: 'offset', text: 'offset'},
53 {id: 'sort', text: 'sort'},
54 {id: 'metadata', text: 'metadata'},
55 {id: '-', text: ts('Other') + '...'}
56 ]});
57 }
58
b07af612
CW
59 /**
60 * Add an "api chain" row
61 */
8ffa1387
CW
62 function addChainField() {
63 $('#api-params').append($(chainTpl({})));
64 var $row = $('tr:last-child', '#api-params');
65 $('.api-chain-entity', $row).crmSelect2({
66 formatSelection: function(item) {
3d9f5b7f
CW
67 return '<span class="icon ui-icon-link"></span> API ' +
68 ($(item.element).hasClass('strikethrough') ? '<span class="strikethrough">' + item.text + '</span>' : item.text);
2b6e1174
CW
69 },
70 placeholder: '<span class="icon ui-icon-link"></span> ' + ts('Entity'),
ff887074 71 escapeMarkup: function(m) {return m;}
8ffa1387 72 });
0c3a6e64
CW
73 }
74
3d9f5b7f
CW
75 /**
76 * Fetch available actions for selected chained entity
77 */
78 function getChainedAction() {
79 var
80 $selector = $(this),
81 entity = $selector.val(),
82 $row = $selector.closest('tr');
83 if (entity) {
84 $selector.prop('disabled', true);
85 CRM.api3(entity, 'getactions')
86 .done(function(actions) {
87 $selector.prop('disabled', false);
ff887074 88 CRM.utils.setOptions($('.api-chain-action', $row), _.transform(actions.values, function(ret, item) {ret.push({value: item, key: item});}));
3d9f5b7f
CW
89 });
90 }
91 }
92
b07af612
CW
93 /**
94 * Fetch fields for entity+action
95 */
a14e9d08 96 function getFields(changedElement) {
e4176358
CW
97 var required = [];
98 fields = [];
fc6a6a51 99 options = getFieldData = {};
e4176358
CW
100 // Special case for getfields
101 if (action === 'getfields') {
102 fields.push({
103 id: 'api_action',
104 text: 'Action'
105 });
77d80c9f
CW
106 options.api_action = _.reduce(actions.values, function(ret, item) {
107 ret[item] = item;
108 return ret;
109 }, {});
e4176358 110 showFields(['api_action']);
0c3a6e64
CW
111 return;
112 }
fc6a6a51
CW
113 CRM.api3(entity, 'getFields', {'api_action': action, options: {get_options: 'all'}}).done(function(data) {
114 getFieldData = data.values;
e4176358
CW
115 _.each(data.values, function(field) {
116 if (field.name) {
117 fields.push({
118 id: field.name,
119 text: field.title || field.name,
7b6c5043
CW
120 multi: !!field['api.multiple'],
121 required: !(!field['api.required'] || field['api.required'] === '0')
e4176358 122 });
7b6c5043 123 if (field['api.required'] && field['api.required'] !== '0') {
e4176358
CW
124 required.push(field.name);
125 }
126 if (field.options) {
127 options[field.name] = field.options;
128 }
129 }
130 });
a14e9d08
CW
131 if ($(changedElement).is('#api-entity') && data.deprecated) {
132 CRM.alert(data.deprecated, entity + ' Deprecated');
133 }
e4176358 134 showFields(required);
b07af612
CW
135 if (action === 'get' || action === 'getsingle') {
136 showReturn();
137 }
0c3a6e64
CW
138 });
139 }
140
b07af612
CW
141 /**
142 * For "get" actions show the "return" options
143 */
144 function showReturn() {
145 $('#api-params').prepend($(returnTpl({})));
b07af612
CW
146 $('#api-return-value').crmSelect2({data: fields, multiple: true});
147 }
148
149 /**
150 * Fetch actions for entity
151 */
2b6e1174
CW
152 function getActions() {
153 if (entity) {
754927e4 154 $('#api-action').addClass('loading');
2b6e1174 155 CRM.api3(entity, 'getactions').done(function(data) {
a14e9d08 156 actions = data;
2b6e1174
CW
157 populateActions();
158 });
159 } else {
a14e9d08 160 actions = {values: ['get']};
2b6e1174
CW
161 populateActions();
162 }
163 }
164
7231faaf
CW
165 /**
166 * Test whether an action is deprecated
167 * @param action
168 * @returns {boolean}
169 */
15cbe793
CW
170 function isActionDeprecated(action) {
171 return !!(typeof actions.deprecated === 'object' && actions.deprecated[action]);
172 }
173
7231faaf
CW
174 /**
175 * Render action text depending on deprecation status
176 * @param option
177 * @returns {string}
178 */
a14e9d08 179 function renderAction(option) {
15cbe793 180 return isActionDeprecated(option.id) ? '<span class="strikethrough">' + option.text + '</span>' : option.text;
a14e9d08
CW
181 }
182
b07af612
CW
183 /**
184 * Called after getActions to populate action list
b07af612 185 */
cb6d8859 186 function populateActions() {
2f929504 187 var val = $('#api-action').val();
754927e4 188 $('#api-action').removeClass('loading').select2({
ff887074 189 data: _.transform(actions.values, function(ret, item) {ret.push({text: item, id: item});}),
a14e9d08
CW
190 formatSelection: renderAction,
191 formatResult: renderAction
2b6e1174 192 });
2f929504 193 // If previously selected action is not available, set it to 'get' if possible
a14e9d08
CW
194 if (_.indexOf(actions.values, val) < 0) {
195 $('#api-action').select2('val', _.indexOf(actions.values, 'get') < 0 ? actions.values[0] : 'get', true);
196 }
197 }
198
7231faaf
CW
199 /**
200 * Check for and display action-specific deprecation notices
201 * @param action
202 */
a14e9d08 203 function onChangeAction(action) {
15cbe793 204 if (isActionDeprecated(action)) {
a14e9d08 205 CRM.alert(actions.deprecated[action], action + ' deprecated');
2f929504 206 }
2b6e1174
CW
207 }
208
b07af612
CW
209 /**
210 * Called after getfields to show buttons and required fields
211 * @param required
212 */
e4176358 213 function showFields(required) {
e4176358 214 $('#api-params').empty();
8ffa1387 215 $('#api-param-buttons').show();
e4176358
CW
216 if (required.length) {
217 _.each(required, addField);
218 } else {
219 addField();
0c3a6e64
CW
220 }
221 }
222
7b6c5043
CW
223 function isMultiSelect(fieldName, operator) {
224 var field = fieldName && _.find(fields, 'id', fieldName);
225 return ($.inArray(operator, MULTI) > -1) || (field && field.multi);
226 }
227
c275764e 228 /**
fc6a6a51 229 * Render value input as a textfield, option list, entityRef, or hidden,
77099ee0 230 * Depending on selected param name and operator
c275764e 231 */
77099ee0
CW
232 function renderValueField() {
233 var $row = $(this).closest('tr'),
234 name = $('input.api-param-name', $row).val(),
235 operator = $('.api-param-op', $row).val(),
77099ee0 236 $valField = $('input.api-param-value', $row),
7b6c5043 237 multiSelect = isMultiSelect(name, operator),
77099ee0
CW
238 currentVal = $valField.val();
239 // Boolean fields only have 1 possible value
7b6c5043 240 if ($.inArray(operator, BOOL) > -1) {
77099ee0
CW
241 if ($valField.data('select2')) {
242 $valField.select2('destroy');
243 }
244 $valField.css('visibility', 'hidden').val('1');
245 return;
246 }
247 $valField.css('visibility', '');
fc6a6a51
CW
248 // Option list or entityRef input
249 if ((options[name] || (getFieldData[name] && getFieldData[name].FKApiName)) && $.inArray(operator, TEXT) < 0) {
77099ee0
CW
250 // Reset value before switching to a select from something else
251 if ($(this).is('.api-param-name') || !$valField.data('select2')) {
252 $valField.val('');
253 }
254 // When switching from multi-select to single select
7b6c5043 255 else if (!multiSelect && currentVal.indexOf(',') > -1) {
77099ee0
CW
256 $valField.val(currentVal.split(',')[0]);
257 }
fc6a6a51
CW
258 // Select options
259 if (options[name]) {
fc6a6a51 260 $valField.select2({
7b6c5043 261 multiple: multiSelect,
fc6a6a51
CW
262 data: _.map(options[name], function (value, key) {
263 return {id: key, text: value};
264 })
265 });
266 }
267 // EntityRef
268 else {
269 $valField.crmEntityRef({
270 entity: getFieldData[name].FKApiName,
f76eb8ae 271 select: {
7b6c5043 272 multiple: multiSelect,
f76eb8ae
CW
273 minimumInputLength: $.inArray(getFieldData[name].FKApiName, OPEN_IMMEDIATELY) > -1 ? 0 : 1
274 }
fc6a6a51
CW
275 });
276 }
77099ee0 277 return;
e4176358 278 }
77099ee0
CW
279 // Plain text input
280 if ($valField.data('select2')) {
e4176358
CW
281 $valField.select2('destroy');
282 }
e4176358 283 }
0c3a6e64 284
e4176358
CW
285 /**
286 * Attempt to parse a string into a value of the intended type
babf9678
CW
287 * @param val string
288 * @param makeArray bool
e4176358
CW
289 */
290 function evaluate(val, makeArray) {
291 try {
292 if (!val.length) {
77099ee0 293 return makeArray ? [] : '';
e4176358
CW
294 }
295 var first = val.charAt(0),
296 last = val.slice(-1);
297 // Simple types
51f197bf 298 if (val === 'true' || val === 'false' || val === 'null') {
cb6d8859 299 /* jshint evil: true */
e4176358
CW
300 return eval(val);
301 }
302 // Quoted strings
303 if ((first === '"' || first === "'") && last === first) {
304 return val.slice(1, -1);
0c3a6e64 305 }
7231faaf 306 // Parse json - use eval rather than $.parseJSON because it's less strict about formatting
e4176358
CW
307 if ((first === '[' && last === ']') || (first === '{' && last === '}')) {
308 return eval('(' + val + ')');
309 }
310 // Transform csv to array
77099ee0
CW
311 if (makeArray) {
312 var result = [];
313 $.each(val.split(','), function(k, v) {
314 result.push(evaluate($.trim(v)) || v);
315 });
316 return result;
317 }
7231faaf 318 // Integers - skip any multidigit number that starts with 0 to avoid oddities (it will be treated as a string below)
77099ee0
CW
319 if (!isNaN(val) && val.search(/[^\d]/) < 0 && (val.length === 1 || first !== '0')) {
320 return parseInt(val, 10);
e4176358
CW
321 }
322 // Ok ok it's really a string
323 return val;
324 } catch(e) {
325 // If eval crashed return undefined
326 return undefined;
0c3a6e64 327 }
e4176358 328 }
0c3a6e64 329
e4176358
CW
330 /**
331 * Format value to look like php code
332 * @param val
333 */
334 function phpFormat(val) {
335 var ret = '';
336 if ($.isPlainObject(val)) {
337 $.each(val, function(k, v) {
c275764e 338 ret += (ret ? ', ' : '') + "'" + k + "' => " + phpFormat(v);
e4176358
CW
339 });
340 return 'array(' + ret + ')';
0c3a6e64 341 }
e4176358
CW
342 if ($.isArray(val)) {
343 $.each(val, function(k, v) {
344 ret += (ret ? ', ' : '') + phpFormat(v);
345 });
346 return 'array(' + ret + ')';
347 }
54c512e0 348 return JSON.stringify(val).replace(/\$/g, '\\$');
e4176358
CW
349 }
350
351 /**
352 * Smarty doesn't support array literals so we provide a stub
353 * @param js string
354 */
355 function smartyFormat(js, key) {
356 if (js.indexOf('[') > -1 || js.indexOf('{') > -1) {
2b6e1174 357 smartyStub = true;
e4176358
CW
358 return '$' + key.replace(/[. -]/g, '_');
359 }
360 return js;
361 }
362
c275764e
CW
363 /**
364 * Create the params array from user input
365 * @param e
366 */
e4176358
CW
367 function buildParams(e) {
368 params = {};
369 $('.api-param-checkbox:checked').each(function() {
370 params[this.name] = 1;
371 });
c275764e 372 $('input.api-param-value, input.api-option-value').each(function() {
e4176358 373 var $row = $(this).closest('tr'),
77099ee0 374 op = $('select.api-param-op', $row).val() || '=',
e4176358 375 name = $('input.api-param-name', $row).val(),
7b6c5043 376 val = evaluate($(this).val(), isMultiSelect(name, op));
b07af612
CW
377
378 // Ignore blank values for the return field
379 if ($(this).is('#api-return-value') && !val) {
380 return;
381 }
8ffa1387
CW
382 // Special syntax for api chaining
383 if (!name && $('select.api-chain-entity', $row).val()) {
384 name = 'api.' + $('select.api-chain-entity', $row).val() + '.' + $('select.api-chain-action', $row).val();
385 }
c275764e
CW
386 // Special handling for options
387 if ($(this).is('.api-option-value')) {
388 op = $('input.api-option-name', $row).val();
389 if (op) {
390 name = 'options';
391 }
392 }
e4176358 393 if (name && val !== undefined) {
c275764e 394 params[name] = op === '=' ? val : (params[name] || {});
e4176358
CW
395 if (op !== '=') {
396 params[name][op] = val;
397 }
babf9678
CW
398 if ($(this).hasClass('crm-error')) {
399 clearError(this);
400 }
e4176358
CW
401 }
402 else if (name && (!e || e.type !== 'keyup')) {
403 setError(this);
404 }
405 });
406 if (entity && action) {
407 formatQuery();
0c3a6e64 408 }
e4176358 409 }
0c3a6e64 410
7231faaf
CW
411 /**
412 * Display error message on incorrectly-formatted params
413 * @param el
414 */
e4176358
CW
415 function setError(el) {
416 if (!$(el).hasClass('crm-error')) {
babf9678 417 var msg = ts('Syntax error: input should be valid JSON or a quoted string.');
e4176358
CW
418 $(el)
419 .addClass('crm-error')
2b6e1174 420 .css('width', '82%')
babf9678
CW
421 .attr('title', msg)
422 .before('<div class="icon red-icon ui-icon-alert" title="'+msg+'"/>')
423 .tooltip();
e4176358
CW
424 }
425 }
0c3a6e64 426
7231faaf
CW
427 /**
428 * Remove error message
429 * @param el
430 */
e4176358
CW
431 function clearError(el) {
432 $(el)
433 .removeClass('crm-error')
434 .attr('title', '')
2b6e1174 435 .css('width', '85%')
babf9678 436 .tooltip('destroy')
e4176358
CW
437 .siblings('.ui-icon-alert').remove();
438 }
0c3a6e64 439
7231faaf
CW
440 /**
441 * Render the api request in various formats
442 */
e4176358
CW
443 function formatQuery() {
444 var i = 0, q = {
445 smarty: "{crmAPI var='result' entity='" + entity + "' action='" + action + "'",
446 php: "$result = civicrm_api3('" + entity + "', '" + action + "'",
447 json: "CRM.api3('" + entity + "', '" + action + "'",
2dad2b26
TO
448 drush: "drush cvapi " + entity + '.' + action + ' ',
449 wpcli: "wp cv api " + entity + '.' + action + ' ',
d461a2ad 450 rest: CRM.config.resourceBase + "extern/rest.php?entity=" + entity + "&action=" + action + "&json=" + JSON.stringify(params) + "&api_key=yourkey&key=sitekey"
e4176358 451 };
2b6e1174 452 smartyStub = false;
e4176358
CW
453 $.each(params, function(key, value) {
454 var js = JSON.stringify(value);
cb6d8859 455 if (!(i++)) {
e4176358
CW
456 q.php += ", array(\n";
457 q.json += ", {\n";
458 } else {
459 q.json += ",\n";
460 }
461 q.php += " '" + key + "' => " + phpFormat(value) + ",\n";
462 q.json += " \"" + key + '": ' + js;
e4176358 463 q.smarty += ' ' + key + '=' + smartyFormat(js, key);
77099ee0 464 // FIXME: This is not totally correct cli syntax
555d256f 465 q.drush += key + '=' + js + ' ';
2dad2b26 466 q.wpcli += key + '=' + js + ' ';
e4176358
CW
467 });
468 if (i) {
469 q.php += ")";
470 q.json += "\n}";
471 }
472 q.php += ");";
473 q.json += ").done(function(result) {\n // do something\n});";
474 q.smarty += "}\n{foreach from=$result.values item=" + entity.toLowerCase() + "}\n {$" + entity.toLowerCase() + ".some_field}\n{/foreach}";
475 if (action.indexOf('get') < 0) {
476 q.smarty = '{* Smarty API only works with get actions *}';
2b6e1174 477 } else if (smartyStub) {
9405a07b 478 q.smarty = "{* Smarty does not have a syntax for array literals; assign complex variables from php *}\n" + q.smarty;
e4176358
CW
479 }
480 $.each(q, function(type, val) {
c8297314 481 $('#api-' + type).addClass('prettyprint').removeClass('prettyprinted').text(val);
e4176358 482 });
cd77ffa6 483 prettyPrint();
e4176358 484 }
0c3a6e64 485
7231faaf
CW
486 /**
487 * Submit button handler
488 * @param e
489 */
e4176358
CW
490 function submit(e) {
491 e.preventDefault();
492 if (!entity || !action) {
2b6e1174 493 alert(ts('Select an entity.'));
e4176358
CW
494 return;
495 }
2f929504 496 if (action.indexOf('get') < 0 && action != 'check') {
e4176358
CW
497 var msg = action === 'delete' ? ts('This will delete data from CiviCRM. Are you sure?') : ts('This will write to the database. Continue?');
498 CRM.confirm({title: ts('Confirm %1', {1: action}), message: msg}).on('crmConfirm:yes', execute);
0c3a6e64 499 } else {
e4176358 500 execute();
0c3a6e64 501 }
0c3a6e64
CW
502 }
503
77099ee0
CW
504 /**
505 * Execute api call and display the results
506 * Note: We have to manually execute the ajax in order to add the secret extra "prettyprint" param
507 */
e4176358
CW
508 function execute() {
509 $('#api-result').html('<div class="crm-loading-element"></div>');
510 $.ajax({
511 url: CRM.url('civicrm/ajax/rest'),
512 data: {
513 entity: entity,
514 action: action,
515 prettyprint: 1,
516 json: JSON.stringify(params)
517 },
518 type: action.indexOf('get') < 0 ? 'POST' : 'GET',
519 dataType: 'text'
520 }).done(function(text) {
2b6e1174 521 $('#api-result').addClass('prettyprint').removeClass('prettyprinted').text(text);
cd77ffa6 522 prettyPrint();
e4176358 523 });
0c3a6e64 524 }
e4176358 525
89ee60d5
CW
526 /**
527 * Fetch list of example files for a given entity
528 */
529 function getExamples() {
530 CRM.utils.setOptions($('#example-action').prop('disabled', true).addClass('loading'), []);
531 $.getJSON(CRM.url('civicrm/ajax/apiexample', {entity: $(this).val()}))
532 .done(function(result) {
533 CRM.utils.setOptions($('#example-action').prop('disabled', false).removeClass('loading'), result);
534 });
535 }
536
537 /**
538 * Fetch and display an example file
539 */
540 function getExample() {
541 var
542 entity = $('#example-entity').val(),
543 action = $('#example-action').val();
544 if (entity && action) {
545 $('#example-result').block();
546 $.get(CRM.url('civicrm/ajax/apiexample', {file: entity + '/' + action}))
547 .done(function(result) {
548 $('#example-result').unblock().addClass('prettyprint').removeClass('prettyprinted').text(result);
549 prettyPrint();
550 });
551 } else {
552 $('#example-result').text($('#example-result').attr('title'));
553 }
554 }
555
bc4aa590
CW
556 /**
557 * Fetch entity docs & actions
558 */
559 function getDocEntity() {
560 CRM.utils.setOptions($('#doc-action').prop('disabled', true).addClass('loading'), []);
561 $.getJSON(CRM.url('civicrm/ajax/apidoc', {entity: $(this).val()}))
562 .done(function(result) {
563 CRM.utils.setOptions($('#doc-action').prop('disabled', false).removeClass('loading'), result.actions);
564 $('#doc-result').html(result.doc);
565 prettyPrint();
566 });
567 }
568
569 /**
570 * Fetch entity+action docs & code
571 */
572 function getDocAction() {
573 var
574 entity = $('#doc-entity').val(),
575 action = $('#doc-action').val();
576 if (entity && action) {
577 $('#doc-result').block();
578 $.get(CRM.url('civicrm/ajax/apidoc', {entity: entity, action: action}))
579 .done(function(result) {
580 $('#doc-result').unblock().html(result.doc);
581 if (result.code) {
582 $('#doc-result').append(docCodeTpl(result));
583 }
584 prettyPrint();
585 });
586 } else {
587 $('#doc-result').html($('#doc-result').attr('title'));
588 }
589 }
590
e4176358 591 $(document).ready(function() {
89ee60d5
CW
592 // Set up tabs - bind active tab to document hash because... it's cool?
593 document.location.hash = document.location.hash || 'explorer';
594 $('#mainTabContainer')
595 .tabs({
596 active: $(document.location.hash + '-tab').index() - 1
597 })
598 .on('tabsactivate', function(e, ui) {
599 if (ui.newPanel) {
600 document.location.hash = ui.newPanel.attr('id').replace('-tab', '');
601 }
602 });
bc4aa590
CW
603 $(window).on('hashchange', function() {
604 $('#mainTabContainer').tabs('option', 'active', $(document.location.hash + '-tab').index() - 1);
605 });
89ee60d5
CW
606
607 // Initialize widgets
bc4aa590 608 $('#api-entity, #example-entity, #doc-entity').crmSelect2({
a14e9d08
CW
609 // Add strikethough class to selection to indicate deprecated apis
610 formatSelection: function(option) {
611 return $(option.element).hasClass('strikethrough') ? '<span class="strikethrough">' + option.text + '</span>' : option.text;
612 }
613 });
e4176358
CW
614 $('form#api-explorer')
615 .on('change', '#api-entity, #api-action', function() {
616 entity = $('#api-entity').val();
a14e9d08 617 action = $('#api-action').val();
2b6e1174 618 if ($(this).is('#api-entity')) {
2b6e1174 619 getActions();
a14e9d08
CW
620 } else {
621 onChangeAction(action);
2b6e1174 622 }
e4176358
CW
623 if (entity && action) {
624 $('#api-params').html('<tr><td colspan="4" class="crm-loading-element"></td></tr>');
625 $('#api-params-table thead').show();
a14e9d08 626 getFields(this);
e4176358
CW
627 buildParams();
628 } else {
629 $('#api-params, #api-generated pre').empty();
8ffa1387 630 $('#api-param-buttons, #api-params-table thead').hide();
e4176358
CW
631 }
632 })
2b6e1174 633 .on('change keyup', 'input.api-input, #api-params select', buildParams)
e4176358
CW
634 .on('submit', submit);
635 $('#api-params')
77099ee0
CW
636 .on('change', 'input.api-param-name, select.api-param-op', renderValueField)
637 .on('change', 'input.api-param-name, .api-option-name', function() {
f76eb8ae 638 if ($(this).val() === '-' && $(this).data('select2')) {
c275764e
CW
639 $(this).select2('destroy');
640 $(this).val('').focus();
641 }
642 })
e4176358
CW
643 .on('click', '.api-param-remove', function(e) {
644 e.preventDefault();
645 $(this).closest('tr').remove();
646 buildParams();
3d9f5b7f
CW
647 })
648 .on('change', 'select.api-chain-entity', getChainedAction);
89ee60d5
CW
649 $('#example-entity').on('change', getExamples);
650 $('#example-action').on('change', getExample);
bc4aa590
CW
651 $('#doc-entity').on('change', getDocEntity);
652 $('#doc-action').on('change', getDocAction);
e4176358 653 $('#api-params-add').on('click', function(e) {
8ffa1387 654 e.preventDefault();
e4176358 655 addField();
8ffa1387 656 });
c275764e
CW
657 $('#api-option-add').on('click', function(e) {
658 e.preventDefault();
659 addOptionField();
660 });
8ffa1387 661 $('#api-chain-add').on('click', function(e) {
e4176358 662 e.preventDefault();
8ffa1387 663 addChainField();
e4176358
CW
664 });
665 $('#api-entity').change();
0c3a6e64 666 });
e4176358 667}(CRM.$, CRM._));