4 * Interactive code finder.
5 * For DataTables documentation see: http://legacy.datatables.net/
8 * @link http://www.open-emr.org
9 * @author Rod Roark <rod@sunsetsystems.com>
10 * @author Brady Miller <brady.g.miller@gmail.com>
11 * @copyright Copyright (c) 2015-2017 Rod Roark <rod@sunsetsystems.com>
12 * @copyright Copyright (c) 2018 Brady Miller <brady.g.miller@gmail.com>
13 * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3
16 // TODO: Make more intuitive
18 require_once('../../globals.php');
19 require_once($GLOBALS['srcdir'] . '/patient.inc');
20 require_once($GLOBALS['srcdir'] . '/csv_like_join.php');
21 require_once($GLOBALS['fileroot'] . '/custom/code_types.inc.php');
23 use OpenEMR\Common\Csrf\CsrfUtils
;
24 use OpenEMR\Core\Header
;
28 // What we are picking from: codes, fields, lists or groups
29 $what = empty($_GET['what']) ?
'codes' : $_GET['what'];
32 $codetype = empty($_GET['codetype']) ?
'' : $_GET['codetype'];
33 if (!empty($codetype)) {
34 $allowed_codes = split_csv_line($codetype);
36 // This is the html element of the target script where the selected code will be stored.
37 $target_element = empty($_GET['target_element']) ?
'' : $_GET['target_element'];
40 $source = empty($_GET['source']) ?
'D' : $_GET['source'];
43 $layout_id = empty($_GET['layout_id']) ?
'' : $_GET['layout_id'];
45 // For setting limit on selection
46 $limit = empty($_GET['limit']) ?
0 : intval($_GET['limit']);
52 <title
><?php
echo xlt('Code Finder'); ?
></title
>
54 <?php Header
::setupHeader(['opener', 'datatables', 'datatables-bs', 'datatables-colreorder']); ?
>
60 // Keeps track of which items have been selected during this session.
65 // Initializing the DataTable.
66 oTable
= $
('#my_data_table').dataTable({
68 // Next 2 lines invoke server side processing
70 "sAjaxSource": "find_code_dynamic_ajax.php?csrf_token_form=" +
<?php
echo js_url(CsrfUtils
::collectCsrfToken()); ?
>,
71 // Vertical length options and their default
72 "aLengthMenu": [ 15, 25, 50, 100 ],
74 // Specify a width for the first column.
75 "aoColumns": [{"sWidth":"10%"}, null],
76 // This callback function passes some form data on each call to the ajax handler.
77 "fnServerParams": function (aoData
) {
78 aoData
.push({"name": "what", "value": <?php
echo js_escape($what); ?
>});
79 <?php
if ($what == 'codes') { ?
>
80 aoData
.push({"name": "codetype", "value": document
.forms
[0].form_code_type
.value
});
81 aoData
.push({"name": "inactive", "value": (document
.forms
[0].form_include_inactive
.checked ?
1 : 0)});
82 <?php
} elseif ($what == 'fields') { ?
>
83 aoData
.push({"name": "source", "value": <?php
echo js_escape($source); ?
>});
84 <?php
} elseif ($what == 'groups') { ?
>
85 aoData
.push({"name": "layout_id", "value": <?php
echo js_escape($layout_id); ?
>});
88 // Drawing a row, apply styling if it is previously selected.
89 "fnCreatedRow": function (nRow
, aData
, iDataIndex
) {
90 if (oChosenIDs
[nRow
.id
]) {
91 nRow
.style
.fontWeight
= 'bold';
94 // Language strings are included so we can translate them
96 "sSearch" : <?php
echo xlj('Search for'); ?
> +
":",
97 "sLengthMenu" : <?php
echo xlj('Show'); ?
> +
" _MENU_ " +
<?php
echo xlj('entries'); ?
>,
98 "sZeroRecords" : <?php
echo xlj('No matching records found'); ?
>,
99 "sInfo" : <?php
echo xlj('Showing'); ?
> +
" _START_ " +
<?php
echo xlj('to{{range}}'); ?
> +
" _END_ " +
<?php
echo xlj('of'); ?
> +
" _TOTAL_ " +
<?php
echo xlj('entries'); ?
>,
100 "sInfoEmpty" : <?php
echo xlj('Nothing to show'); ?
>,
101 "sInfoFiltered": "(" +
<?php
echo xlj('filtered from'); ?
> +
" _MAX_ " +
<?php
echo xlj('total entries'); ?
> +
")",
103 "sFirst" : <?php
echo xlj('First'); ?
>,
104 "sPrevious" : <?php
echo xlj('Previous'); ?
>,
105 "sNext" : <?php
echo xlj('Next'); ?
>,
106 "sLast" : <?php
echo xlj('Last'); ?
>
111 // OnClick handler for the rows
112 $
('#my_data_table').on('click', 'tbody tr', function () {
113 var limit
= <?php
echo js_escape($limit); ?
>;
114 var target_element
= <?php
echo js_escape($target_element); ?
>;
116 if(Object.values(oChosenIDs
).length
<limit || limit
<=0){
117 var jobj
= JSON
.parse(this
.id
.substring(4));
119 this
.style
.fontWeight
= 'bold';
120 oChosenIDs
[this
.id
] = 1;
122 <?php
if ($what == 'codes') { ?
>
123 // this.id is of the form "CID|jsonstring".
124 var codesel
= jobj
['code'].split('|');
126 selcode(jobj
['codetype'], codesel
[0], codesel
[1], jobj
['description'], target_element
, limit
);
127 <?php
} elseif ($what == 'fields') { ?
>
129 <?php
} elseif ($what == 'lists') { ?
>
131 <?php
} elseif ($what == 'groups') { ?
>
138 <?php
if ($what == 'codes') { ?
>
139 // Initialize the selector of codes that can be deleted.
140 if (opener
.get_related
) {
141 var acodes
= opener
.get_related();
142 var sel
= document
.forms
[0].form_delcodes
;
143 if (acodes
.length
> 1) {
144 for (var i
= 0; i
< acodes
.length
; ++i
) {
145 sel
.options
[sel
.options
.length
] = new Option(acodes
[i
], acodes
[i
]);
149 sel
.style
.display
= 'none';
154 // Set focus to the Search field.
155 $
('#my_data_table_filter input').focus();
159 <?php
if ($what == 'codes') { ?
>
160 // Pass info back to the opener and close this window. Specific to billing/product codes.
161 function selcode(codetype
, code
, selector
, codedesc
, target_element
, limit
=0) {
162 if (opener
.closed ||
(! opener
.set_related
&& !opener
.set_related_target
)) {
163 alert(<?php
echo xlj('The destination form was closed; I cannot act on your selection.'); ?
>);
166 if(target_element
!=''){
167 var msg
= opener
.set_related_target(codetype
, code
, selector
, codedesc
, target_element
, limit
);
169 var msg
= opener
.set_related(codetype
, code
, selector
, codedesc
);
176 // Function to call the opener to delete all or one related code. Specific to billing/product codes.
178 if (opener
.closed ||
! opener
.del_related
) {
179 alert(<?php
echo xlj('The destination form was closed; I cannot act on your selection.'); ?
>);
182 var sel
= document
.forms
[0].form_delcodes
;
183 opener
.del_related(sel
.value
);
191 <?php
} elseif ($what == 'fields') { ?
>
192 function selectField(jobj
) {
193 if (opener
.closed ||
! opener
.SetField
) {
194 alert('The destination form was closed; I cannot act on your selection.');
197 opener
.SetField(jobj
['field_id'], jobj
['title'], jobj
['data_type'], jobj
['uor'], jobj
['fld_length'],
198 jobj
['max_length'], jobj
['list_id'], jobj
['titlecols'], jobj
['datacols'], jobj
['edit_options'],
199 jobj
['description'], jobj
['fld_rows']);
204 function newField() {
206 "field_id" : document
.forms
[0].new_field_id
.value
,
221 <?php
} elseif ($what == 'lists') { ?
>
222 function SelectList(jobj
) {
223 if (opener
.closed ||
! opener
.SetList
)
224 alert('The destination form was closed; I cannot act on your selection.');
226 opener
.SetList(jobj
['code']);
231 <?php
} elseif ($what == 'groups') { ?
>
232 var SelectItem
= function(jobj
) {
234 alert('The destination form was closed; I cannot act on your selection.');
236 opener
.MoveFields(jobj
['code']);
247 <body id
="codes_search">
248 <div
class="container-fluid">
250 $string_target_element = empty($target_element) ?
'?' : "?target_element=" . attr_url($target_element) . "&";
253 <form method
='post' name
='theform'>
255 echo "<div class='form-group row mb-3'>\n";
256 if ($what == 'codes') {
257 if (isset($allowed_codes)) {
258 if (count($allowed_codes) == 1) {
259 echo "<div class='col'><input type='text' class='form-control' name='form_code_type' value='" . attr($codetype) . "' size='5' readonly /></div>\n";
261 echo "<div class='col'><select name='form_code_type' onchange='oTable.fnDraw()'>\n";
262 foreach ($allowed_codes as $code) {
263 echo " <option value='" . attr($code) . "'>" . xlt($code_types[$code]['label']) . "</option>\n";
265 echo "</select></div>\n";
268 echo "<div class='col'><select class='form-control' name='form_code_type' onchange='oTable.fnDraw()'>\n";
269 foreach ($code_types as $key => $value) {
270 echo " <option value='" . attr($key) . "'";
271 echo ">" . xlt($value['label']) . "</option>\n";
273 echo " <option value='PROD'";
274 echo ">" . xlt("Product") . "</option>\n";
275 echo " </select></div>\n";
278 echo "<div class='col'>";
279 echo "<input type='checkbox' name='form_include_inactive' value='1' onclick='oTable.fnDraw()' />" .
280 xlt('Include Inactive') . "\n";
282 echo "<button class='btn btn-danger btn-sm btn-delete' value='" . xla('Delete') . "' onclick='delcode()'>" . xla('Delete') . "</button>\n";
283 echo "<select name='form_delcodes'>\n";
284 echo " <option value=''>" . xlt('All') . "</option>\n";
287 echo "<button class='btn btn-secondary btn-sm btn-cancel' value='" . xla('Close') . "' onclick='dlgclose()'>" . xla('Close') . "</button>\n";
290 if ($what == 'lists') {
291 echo "<button class='btn btn-secondary btn-sm btn-delete' value='" . xla('Delete') . "' onclick='SelectList({\"code\":\"\"})'>" . xla('Delete') . "</button>\n";
296 <!-- Exception here
: Do not
use table
-responsive
as it breaks datatables
!-->
297 <table id
="my_data_table" class="table table-striped table-hover table-sm">
300 <th
><?php
echo xlt('Code'); ?
></th
>
301 <th
><?php
echo xlt('Description'); ?
></th
>
306 <!-- Class "dataTables_empty" is defined in jquery
.dataTables
.css
-->
307 <td colspan
="2" class="dataTables_empty">...</td
>
312 <?php
if ($what == 'fields' && $source == 'E') { ?
>
315 <input type
='text' class="form-control" name
='new_field_id' size
='20' />
318 <button
class="btn btn-secondary" value
='<?php echo xla('Or create this
new field ID
') ?>' onclick
='newField()'>
319 <?php
echo xla('Or create this new field ID') ?
>