minor change to prior commit
[openemr.git] / library / options.js.php
bloba5ce4c691855abdcff411bc942cc4bcecf35d508
1 <?php
3 /**
4 * This is the place to put JavaScript functions that are needed to support
5 * options.inc.php. Include this in the <head> section of relevant modules.
6 * It's a .php module so that translation can be supported.
8 * @package OpenEMR
9 * @link https://www.open-emr.org
10 * @author Rod Roark <rod@sunsetsystems.com>
11 * @author Brady Miller <brady.g.miller@gmail.com>
12 * @copyright Copyright (c) 2014-2019 Rod Roark <rod@sunsetsystems.com>
13 * @copyright Copyright (c) 2018 Brady Miller <brady.g.miller@gmail.com>
14 * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3
18 <script>
20 // JavaScript support for date types when the A or B edit option is used.
21 // Called to recompute displayed age dynamically when the corresponding date is
22 // changed. Must generate the same age formats as the oeFormatAge() function.
24 function updateAgeString(fieldid, asof, format, description) {
25 var datefld = document.getElementById('form_' + fieldid);
26 var f = datefld.form;
27 var age = '';
28 var date1 = new Date(datefld.value);
29 var date2 = asof ? new Date(asof) : new Date();
30 if (format == 3) {
31 // Gestational age.
32 var msecs = date2.getTime() - date1.getTime();
33 var days = Math.round(msecs / (24 * 60 * 60 * 1000));
34 var weeks = Math.floor(days / 7);
35 days = days % 7;
36 if (description == '') description = <?php echo xlj('Gest age') ?>;
37 age = description + ' ' +
38 weeks + (weeks == 1 ? ' ' + <?php echo xlj('week') ?> : ' ' + <?php echo xlj('weeks') ?>) + ' ' +
39 days + (days == 1 ? ' ' + <?php echo xlj('day') ?> : ' ' + <?php echo xlj('days') ?>);
41 else {
42 // Years or months.
43 var dayDiff = date2.getDate() - date1.getDate();
44 var monthDiff = date2.getMonth() - date1.getMonth();
45 var yearDiff = date2.getFullYear() - date1.getFullYear();
46 var ageInMonths = yearDiff * 12 + monthDiff;
47 if (dayDiff < 0) --ageInMonths;
48 if (format == 1 || (format == 0 && ageInMonths >= 24)) {
49 age = yearDiff;
50 if (monthDiff < 0 || (monthDiff == 0 && dayDiff < 0)) --age;
51 age = '' + age;
53 else {
54 age = '' + ageInMonths;
55 if (format == 0) {
56 age = age + ' ' + (ageInMonths == 1 ? <?php echo xlj('month') ?> : <?php echo xlj('months') ?>);
59 if (description == '') description = <?php echo xlj('Age') ?>;
60 if (age != '') age = description + ' ' + age;
62 document.getElementById('span_' + fieldid).innerHTML = age;
65 // Function to show or hide form fields (and their labels) depending on "skip conditions"
66 // defined in the layout.
68 var cskerror = false; // to avoid repeating error messages
69 function checkSkipConditions() {
70 var myerror = cskerror;
71 var prevandor = '';
72 var prevcond = false;
73 for (var i = 0; i < skipArray.length; ++i) {
74 var target = skipArray[i].target;
75 var id = skipArray[i].id;
76 var itemid = skipArray[i].itemid;
77 var operator = skipArray[i].operator;
78 var value = skipArray[i].value;
79 var is_radio = false;
80 var action = skipArray[i].action;
81 var tofind = id;
83 if (itemid) tofind += '[' + itemid + ']';
84 // Some different source IDs are possible depending on the data type.
85 var srcelem = document.getElementById('check_' + tofind);
86 var radio_id='form_' + tofind + '[' + value + ']';
87 if(typeof document.getElementById(radio_id)!=="undefined"){
88 srcelem = document.getElementById(radio_id);
89 if(srcelem != null){
90 is_radio = true;
93 if (srcelem == null) srcelem = document.getElementById('radio_' + tofind);
94 if (srcelem == null) srcelem = document.getElementById('form_' + tofind) ;
95 if (srcelem == null) srcelem = document.getElementById('text_' + tofind);
97 if (srcelem == null) {
98 // This caters to radio buttons which we treat like droplists.
99 var tmp = document.getElementById('form_' + tofind + '[' + value + ']');
100 if (tmp != null) {
101 srcelem = tmp;
102 if (operator == 'eq') operator = 'se';
103 if (operator == 'ne') operator = 'ns';
107 if (srcelem == null) {
108 if (!cskerror) alert(<?php echo xlj('Cannot find a skip source field for'); ?> + ' "' + tofind + '"');
109 myerror = true;
110 continue;
113 var condition = false;
114 var is_multiple = false;
115 var elem_val;
116 if ( is_radio){
117 for (var k = 0; k < document.getElementsByName('form_' + tofind).length; k++){
118 if (document.getElementsByName('form_' + tofind)[k].checked){
119 elem_val= document.getElementsByName('form_' + tofind)[k].value;
122 }else if( typeof srcelem.options!=="undefined" && srcelem.type == 'select-one' ){
123 elem_val=srcelem.options[srcelem.selectedIndex].value;
125 }else if( srcelem.type == 'select-multiple' ) {
126 elem_val = new Array();
127 is_multiple = true;
128 for (var k = 0; k < srcelem.length; k++) {
129 if (srcelem.options[k].selected) {
130 if( elem_val.indexOf(srcelem.options[k].value)<0) {
131 elem_val.push(srcelem.options[k].value);
135 } else {
136 elem_val=srcelem.value;
138 if(elem_val == null) {
139 elem_val = srcelem.getAttribute("data-value");
140 if( elem_val !== null && elem_val.indexOf("|") !== -1 ) {
141 elem_val = elem_val.split("|");
142 is_multiple = true;
145 if(elem_val == null) elem_val = srcelem.innerText;
147 //this is a feature fix for the multiple select list option
148 //collect all the multiselect control values:
149 if( is_multiple ) {
150 switch(operator) {
151 case 'eq':
152 condition = (-1 !== elem_val.indexOf(value));break;
153 case 'ne':
154 condition = (-1 == elem_val.indexOf(value)); break;
155 case 'se':
156 condition = srcelem.checked ; break; // doesn't make sense?
157 case 'ns':
158 condition = !srcelem.checked; break;
161 } else {
162 if (operator == 'eq') condition = elem_val == value; else
163 if (operator == 'ne') condition = elem_val != value; else
164 if (operator == 'se') condition = srcelem.checked ; else
165 if (operator == 'ns') condition = !srcelem.checked;
168 // Logic to accumulate multiple conditions for the same target.
169 // alert('target = ' + target + ' prevandor = ' + prevandor + ' prevcond = ' + prevcond); // debugging
170 if (prevandor == 'and') condition = condition && prevcond; else
171 if (prevandor == 'or' ) condition = condition || prevcond;
172 prevandor = skipArray[i].andor;
173 prevcond = condition;
174 var j = i + 1;
175 if (j < skipArray.length && skipArray[j].target == target) continue;
177 // At this point condition indicates the target should be hidden or have its value set.
179 if (action == 'skip') {
180 var trgelem1 = document.getElementById('label_id_' + target);
181 var trgelem2 = document.getElementById('value_id_text_' + target);
182 if (trgelem2 == null) {
183 trgelem2 = document.getElementById('value_id_' + target);
186 if (trgelem1 == null && trgelem2 == null) {
187 var trgelem1 = document.getElementById('label_' + target);
188 var trgelem2 = document.getElementById('text_' + target);
189 if(trgelem2 == null){
190 trgelem2 = document.getElementById('form_' + target);
192 if (trgelem1 == null && trgelem2 == null) {
193 if (!cskerror) alert(<?php echo xlj('Cannot find a skip target field for'); ?> + ' "' + target + '"');
194 myerror = true;
195 continue;
199 // Find the target row and count its cells, accounting for colspans.
200 var trgrow = trgelem1 ? trgelem1.parentNode : trgelem2.parentNode;
201 var rowcells = 0;
202 for (var itmp = 0; itmp < trgrow.cells.length; ++itmp) {
203 rowcells += trgrow.cells[itmp].colSpan;
206 // If the item occupies a whole row then undisplay its row, otherwise hide its cells.
207 var colspan = 0;
208 if (trgelem1) colspan += trgelem1.colSpan;
209 if (trgelem2) colspan += trgelem2.colSpan;
210 if (colspan < rowcells) {
211 if (trgelem1) trgelem1.style.visibility = condition ? 'hidden' : 'visible';
212 if (trgelem2) trgelem2.style.visibility = condition ? 'hidden' : 'visible';
214 else {
215 trgrow.style.display = condition ? 'none' : '';
218 else if (condition) { // action starts with "value="
219 var trgelem = document.getElementById('form_' + target);
220 if (trgelem == null) {
221 if (!cskerror) alert('Cannot find a value target field "' + trgelem + '"');
222 myerror = true;
223 continue;
225 var action_value = action.substring(6);
226 if (trgelem.type == 'checkbox') {
227 trgelem.checked = !(action_value == '0' || action_value == '');
229 else {
230 trgelem.value = action_value;
234 // If any errors, all show in the first pass and none in subsequent passes.
235 cskerror = cskerror || myerror;
238 ///////////////////////////////////////////////////////////////////////
239 // Image canvas support starts here.
240 ///////////////////////////////////////////////////////////////////////
242 var lbfCanvases = {}; // contains the LC instance for each canvas.
244 // Initialize the drawing widget.
245 // canid is the id of the div that will contain the canvas, and the image
246 // element used for initialization should have an id of canid + '_img'.
248 function lbfCanvasSetup(canid, canWidth, canHeight) {
249 LC.localize({
250 "stroke" : <?php echo xlj('stroke'); ?>,
251 "fill" : <?php echo xlj('fill'); ?>,
252 "bg" : <?php echo xlj('bg{{image canvas label}}'); ?>,
253 "Clear" : <?php echo xlj('Clear'); ?>,
254 // The following are tooltip translations, however they do not work due to
255 // a bug in LiterallyCanvas 0.4.13. We'll leave them here pending a fix.
256 "Eraser" : <?php echo xlj('Eraser'); ?>,
257 "Pencil" : <?php echo xlj('Pencil'); ?>,
258 "Line" : <?php echo xlj('Line'); ?>,
259 "Rectangle" : <?php echo xlj('Rectangle'); ?>,
260 "Ellipse" : <?php echo xlj('Ellipse'); ?>,
261 "Text" : <?php echo xlj('Text'); ?>,
262 "Polygon" : <?php echo xlj('Polygon'); ?>,
263 "Pan" : <?php echo xlj('Pan'); ?>,
264 "Eyedropper": <?php echo xlj('Eyedropper'); ?>,
265 "Undo" : <?php echo xlj('Undo'); ?>,
266 "Redo" : <?php echo xlj('Redo'); ?>,
267 "Zoom out" : <?php echo xlj('Zoom out'); ?>,
268 "Zoom in" : <?php echo xlj('Zoom in'); ?>,
270 var tmpImage = document.getElementById(canid + '_img');
271 var shape = LC.createShape('Image', {x: 0, y: 0, image: tmpImage});
272 var lc = LC.init(document.getElementById(canid), {
273 imageSize: {width: canWidth, height: canHeight},
274 strokeWidths: [1, 2, 3, 5, 8, 12],
275 defaultStrokeWidth: 2,
276 backgroundShapes: [shape],
277 imageURLPrefix: '<?php echo $GLOBALS['assets_static_relative'] ?>/literallycanvas/img'
279 if (canHeight > 261) {
280 // TBD: Do something to make the widget bigger?
281 // Look for some help with this in the next LC release.
283 // lc.saveShape(shape); // alternative to the above backgroundShapes
284 lbfCanvases[canid] = lc;
287 // This returns a standard "Data URL" string representing the image data.
288 // It will typically be a few kilobytes. Here's a truncated example:
289 // data:image/png;base64,iVBORw0K ...
291 function lbfCanvasGetData(canid) {
292 return lbfCanvases[canid].getImage().toDataURL();
294 // set signture to hidden element for this img
295 function lbfSetSignature(el) {
296 let imgel = el + "_img";
297 let sign = $("#"+ imgel).attr('src');
298 $("#"+ el).val(sign);
299 return true;
301 // This is invoked when a field with edit option M is changed.
302 // Its purpose is to make the corresponding change to the member fields (edit option m).
304 function checkGroupMembers(elem, groupnumber) {
305 var i = elem.id.indexOf('[');
306 if (i < 0) {
307 alert(<?php echo xlj('Field not suitable for edit option M') ?> + ': ' + elem.name);
308 return;
310 var suffix = elem.id.substring(i);
311 var members = document.getElementsByClassName('lbf_memgroup_' + groupnumber);
312 if (members.length == 0) {
313 alert(<?php echo xlj('No member fields found for') ?> + ': ' + elem.name);
314 return;
316 for (var i = 0; i < members.length; ++i) {
317 if (members[i].id.indexOf(suffix) > 1) {
318 members[i].checked = true;
323 </script>