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.
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
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
);
28 var date1
= new Date(datefld
.value
);
29 var date2
= asof ?
new Date(asof
) : new Date();
32 var msecs
= date2
.getTime() - date1
.getTime();
33 var days
= Math
.round(msecs
/ (24 * 60 * 60 * 1000));
34 var weeks
= Math
.floor(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') ?
>);
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)) {
50 if (monthDiff
< 0 ||
(monthDiff
== 0 && dayDiff
< 0)) --age
;
54 age
= '' + ageInMonths
;
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
;
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
;
80 var action
= skipArray
[i
].action
;
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
);
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 +
']');
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 +
'"');
113 var condition
= false;
114 var is_multiple
= false;
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();
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
);
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("|");
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:
152 condition
= (-1 !== elem_val
.indexOf(value
));break;
154 condition
= (-1 == elem_val
.indexOf(value
)); break;
156 condition
= srcelem
.checked
; break; // doesn't make sense?
158 condition
= !srcelem
.checked
; break;
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
;
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 +
'"');
199 // Find the target row and count its cells, accounting for colspans.
200 var trgrow
= trgelem1 ? trgelem1
.parentNode
: trgelem2
.parentNode
;
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.
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';
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 +
'"');
225 var action_value
= action
.substring(6);
226 if (trgelem
.type
== 'checkbox') {
227 trgelem
.checked
= !(action_value
== '0' || action_value
== '');
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
) {
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
);
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('[');
307 alert(<?php
echo xlj('Field not suitable for edit option M') ?
> +
': ' + elem
.name
);
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
);
316 for (var i
= 0; i
< members
.length
; ++i
) {
317 if (members
[i
].id
.indexOf(suffix
) > 1) {
318 members
[i
].checked
= true;