Tag documents to procedures (#4465)
[openemr.git] / interface / patient_file / encounter / find_code_dynamic.php
blob75cfafd53fb4543a521454a9698f189e3c2b7c55
1 <?php
3 /**
4 * Interactive code finder.
5 * For DataTables documentation see: http://legacy.datatables.net/
7 * @package OpenEMR
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;
26 $info_msg = "";
28 // What we are picking from: codes, fields, lists or groups
29 $what = empty($_GET['what']) ? 'codes' : $_GET['what'];
31 // For what == codes
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'];
39 // For what == fields
40 $source = empty($_GET['source']) ? 'D' : $_GET['source'];
42 // For what == groups
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']);
49 <!DOCTYPE html>
50 <html>
51 <head>
52 <title><?php echo xlt('Code Finder'); ?></title>
54 <?php Header::setupHeader(['opener', 'datatables', 'datatables-bs', 'datatables-colreorder']); ?>
56 <script>
58 var oTable;
60 // Keeps track of which items have been selected during this session.
61 var oChosenIDs = {};
63 $(function () {
65 // Initializing the DataTable.
66 oTable = $('#my_data_table').dataTable({
67 "bProcessing": true,
68 // Next 2 lines invoke server side processing
69 "bServerSide": true,
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 ],
73 "iDisplayLength": 50,
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); ?>});
86 <?php } ?>
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
95 "oLanguage": {
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'); ?> + ")",
102 "oPaginate" : {
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') { ?>
128 selectField(jobj);
129 <?php } elseif ($what == 'lists') { ?>
130 SelectList(jobj);
131 <?php } elseif ($what == 'groups') { ?>
132 SelectItem(jobj);
133 <?php } ?>
136 } );
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]);
148 else {
149 sel.style.display = 'none';
152 <?php } ?>
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.'); ?>);
165 else {
166 if(target_element!=''){
167 var msg = opener.set_related_target(codetype, code, selector, codedesc, target_element, limit);
168 } else {
169 var msg = opener.set_related(codetype, code, selector, codedesc);
171 if (msg) alert(msg);
172 // window.close();
173 return false;
176 // Function to call the opener to delete all or one related code. Specific to billing/product codes.
177 function delcode() {
178 if (opener.closed || ! opener.del_related) {
179 alert(<?php echo xlj('The destination form was closed; I cannot act on your selection.'); ?>);
181 else {
182 var sel = document.forms[0].form_delcodes;
183 opener.del_related(sel.value);
184 oChosenIDs = {};
185 oTable.fnDraw();
186 // window.close();
187 return false;
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.');
196 else {
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']);
201 dlgclose();
202 return false;
204 function newField() {
205 return selectField({
206 "field_id" : document.forms[0].new_field_id.value,
207 "title" : '',
208 "data_type" : 2,
209 "uor" : 1,
210 "fld_length" : 10,
211 "max_length" : 255,
212 "list_id" : '',
213 "titlecols" : 1,
214 "datacols" : 3,
215 "edit_options": '',
216 "description" : '',
217 "fld_rows" : 0
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.');
225 else
226 opener.SetList(jobj['code']);
227 dlgclose();
228 return false;
231 <?php } elseif ($what == 'groups') { ?>
232 var SelectItem = function(jobj) {
233 if (opener.closed)
234 alert('The destination form was closed; I cannot act on your selection.');
235 else
236 opener.MoveFields(jobj['code']);
237 dlgclose();
238 return false;
241 <?php } ?>
243 </script>
245 </head>
247 <body id="codes_search">
248 <div class="container-fluid">
249 <?php
250 $string_target_element = empty($target_element) ? '?' : "?target_element=" . attr_url($target_element) . "&";
253 <form method='post' name='theform'>
254 <?php
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";
260 } else {
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";
267 } else {
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";
277 echo "\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";
281 echo "\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";
285 echo "</select>\n";
286 echo "\n";
287 echo "<button class='btn btn-secondary btn-sm btn-cancel' value='" . xla('Close') . "' onclick='dlgclose()'>" . xla('Close') . "</button>\n";
288 echo "</div>";
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";
293 echo "</div>\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">
298 <thead>
299 <tr>
300 <th><?php echo xlt('Code'); ?></th>
301 <th><?php echo xlt('Description'); ?></th>
302 </tr>
303 </thead>
304 <tbody>
305 <tr>
306 <!-- Class "dataTables_empty" is defined in jquery.dataTables.css -->
307 <td colspan="2" class="dataTables_empty">...</td>
308 </tr>
309 </tbody>
310 </table>
312 <?php if ($what == 'fields' && $source == 'E') { ?>
313 <div class="row">
314 <div class="col">
315 <input type='text' class="form-control" name='new_field_id' size='20' />
316 </div>
317 <div class="col">
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') ?>
320 </button>
321 </div>
322 </div>
323 <?php } ?>
325 </form>
326 </div>
327 </body>
328 </html>