lforms 29.3.1 → 33.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (116) hide show
  1. package/CHANGELOG.md +256 -0
  2. package/README.md +97 -14
  3. package/changed-features.md +99 -0
  4. package/dist/lforms/LICENSE.md +70 -0
  5. package/dist/lforms/README.md +100 -0
  6. package/dist/lforms/fhir/R4/lformsFHIR.min.js +2 -0
  7. package/dist/lforms/fhir/R4/lformsFHIR.min.js.map +1 -0
  8. package/dist/lforms/fhir/STU3/lformsFHIR.min.js +2 -0
  9. package/dist/lforms/fhir/STU3/lformsFHIR.min.js.map +1 -0
  10. package/dist/lforms/fhir/lformsFHIRAll.min.js +2 -0
  11. package/dist/lforms/fhir/lformsFHIRAll.min.js.map +1 -0
  12. package/dist/lforms/webcomponent/assets/lib/zone.min.js +134 -0
  13. package/dist/lforms/webcomponent/down_arrow_gray_10_10.png +0 -0
  14. package/dist/lforms/webcomponent/favicon.ico +0 -0
  15. package/dist/lforms/webcomponent/index.html +9 -0
  16. package/dist/lforms/webcomponent/lhc-forms.js +2471 -0
  17. package/dist/lforms/webcomponent/magnifying_glass.png +0 -0
  18. package/dist/lforms/webcomponent/main.js +2464 -0
  19. package/dist/lforms/webcomponent/main.js.map +1 -0
  20. package/dist/lforms/webcomponent/polyfills.js +2 -0
  21. package/dist/lforms/webcomponent/polyfills.js.map +1 -0
  22. package/dist/lforms/webcomponent/runtime.js +2 -0
  23. package/dist/lforms/webcomponent/runtime.js.map +1 -0
  24. package/dist/lforms/webcomponent/scripts.js +3 -0
  25. package/dist/lforms/webcomponent/scripts.js.map +1 -0
  26. package/dist/lforms/webcomponent/styles.css +3 -0
  27. package/dist/lforms/webcomponent/styles.css.map +1 -0
  28. package/form_definition.md +382 -0
  29. package/lforms-33.2.0.tgz +0 -0
  30. package/package.json +94 -88
  31. package/r4-support.md +147 -0
  32. package/sdc-support.md +127 -0
  33. package/app/.npmignore +0 -3
  34. package/app/images/blank.gif +0 -0
  35. package/app/images/signal-stop.png +0 -0
  36. package/app/index.html +0 -10
  37. package/app/lforms.js +0 -56
  38. package/app/lforms.tpl.js +0 -964
  39. package/app/scripts/angular-packages.js +0 -11
  40. package/app/scripts/bootstrap-decorators.js +0 -31
  41. package/app/scripts/bower-index.js +0 -14
  42. package/app/scripts/fhir/R4/export.js +0 -33
  43. package/app/scripts/fhir/R4/fhirRequire.js +0 -36
  44. package/app/scripts/fhir/R4/lformsFHIR.js +0 -27260
  45. package/app/scripts/fhir/R4/sdc-export.js +0 -455
  46. package/app/scripts/fhir/R4/sdc-import.js +0 -483
  47. package/app/scripts/fhir/STU3/export.js +0 -27
  48. package/app/scripts/fhir/STU3/fhirRequire.js +0 -36
  49. package/app/scripts/fhir/STU3/lformsFHIR.js +0 -27291
  50. package/app/scripts/fhir/STU3/sdc-export.js +0 -493
  51. package/app/scripts/fhir/STU3/sdc-import.js +0 -494
  52. package/app/scripts/fhir/diagnostic-report.js +0 -707
  53. package/app/scripts/fhir/export-common.js +0 -209
  54. package/app/scripts/fhir/expression-processor.js +0 -670
  55. package/app/scripts/fhir/extensions/rendering-style.js +0 -23
  56. package/app/scripts/fhir/fhir-common.js +0 -3
  57. package/app/scripts/fhir/obs-prepop.mjs +0 -97
  58. package/app/scripts/fhir/runtime-common.js +0 -33
  59. package/app/scripts/fhir/sdc-common.js +0 -334
  60. package/app/scripts/fhir/sdc-export-common.js +0 -1046
  61. package/app/scripts/fhir/sdc-import-common.js +0 -1343
  62. package/app/scripts/fhir/versions.js +0 -8
  63. package/app/scripts/index.js +0 -20
  64. package/app/scripts/lforms-config.js +0 -12
  65. package/app/scripts/lforms-constants.js +0 -10
  66. package/app/scripts/lforms-controllers.js +0 -1196
  67. package/app/scripts/lforms-directives.js +0 -424
  68. package/app/scripts/lforms-index.js +0 -20
  69. package/app/scripts/lib/cross_browser.js +0 -21
  70. package/app/scripts/lib/lforms-data.js +0 -3591
  71. package/app/scripts/lib/lforms-hl7.js +0 -525
  72. package/app/scripts/lib/lforms-util.js +0 -1122
  73. package/app/scripts/lib/lforms-validate.js +0 -277
  74. package/app/scripts/lib/polyfill.js +0 -81
  75. package/app/scripts/themeList.js +0 -17
  76. package/app/styles/lforms.css +0 -1219
  77. package/app/styles/redmond-theme/README.txt +0 -2
  78. package/app/styles/redmond-theme/images/ui-bg_glass_75_d0e5f5_1x400.png +0 -0
  79. package/app/styles/redmond-theme/images/ui-bg_glass_85_dfeffc_1x400.png +0 -0
  80. package/app/styles/redmond-theme/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  81. package/app/styles/redmond-theme/images/ui-bg_gloss-wave_55_5c9ccc_500x100.png +0 -0
  82. package/app/styles/redmond-theme/images/ui-bg_inset-hard_100_f5f8f9_1x100.png +0 -0
  83. package/app/styles/redmond-theme/images/ui-bg_inset-hard_100_fcfdfd_1x100.png +0 -0
  84. package/app/styles/redmond-theme/images/ui-icons_217bc0_256x240.png +0 -0
  85. package/app/styles/redmond-theme/images/ui-icons_2e83ff_256x240.png +0 -0
  86. package/app/styles/redmond-theme/images/ui-icons_469bdd_256x240.png +0 -0
  87. package/app/styles/redmond-theme/images/ui-icons_6da8d5_256x240.png +0 -0
  88. package/app/styles/redmond-theme/images/ui-icons_cd0a0a_256x240.png +0 -0
  89. package/app/styles/redmond-theme/images/ui-icons_d8e7f3_256x240.png +0 -0
  90. package/app/styles/redmond-theme/images/ui-icons_f9bd01_256x240.png +0 -0
  91. package/app/styles/redmond-theme/jquery-ui.css +0 -1311
  92. package/app/styles/redmond-theme/jquery-ui.min.css +0 -7
  93. package/app/styles/redmond-theme/theme.css +0 -443
  94. package/app/styles/themes.css +0 -1541
  95. package/app/styles/themes.css.map +0 -9
  96. package/app/styles/themes.scss +0 -411
  97. package/app/version.json +0 -1
  98. package/app/views/partials/attachment.html +0 -38
  99. package/app/views/partials/field-answers.html +0 -67
  100. package/app/views/partials/field-units.html +0 -24
  101. package/app/views/partials/form-controls.html +0 -19
  102. package/app/views/partials/form-header.html +0 -35
  103. package/app/views/partials/form-options.html +0 -50
  104. package/app/views/partials/form-title.html +0 -20
  105. package/app/views/partials/form-view.html +0 -13
  106. package/app/views/partials/item-options.html +0 -48
  107. package/app/views/partials/item.html +0 -126
  108. package/app/views/partials/itemPrefixAndText.html +0 -4
  109. package/app/views/partials/layout-horizontal.html +0 -156
  110. package/app/views/partials/layout-matrix.html +0 -145
  111. package/app/views/partials/popover-content.html +0 -1
  112. package/app/views/partials/repeating-button.html +0 -16
  113. package/app/views/partials/table-item.html +0 -30
  114. package/app/views/partials/template-table.html +0 -69
  115. package/app/views/partials/uib-popover-templates/uib-popover-template.html +0 -13
  116. package/app/views/partials/uib-popover-templates/uib-popover.html +0 -11
@@ -1,525 +0,0 @@
1
- /**
2
- * A package to generate HL7 messgages from LForms form data
3
- */
4
- var LForms = require('../../lforms.js');
5
- import {LOINC_URI} from '../fhir/fhir-common';
6
-
7
- LForms.HL7 = (function() {
8
- "use strict";
9
- return {
10
-
11
- LOINC_CS: 'LN',
12
- obrFieldNum: 43,
13
- obxFieldNum: 17,
14
-
15
- // HL7 V2 data types
16
- DataType : {
17
- //Alphanumeric
18
- "ST": "String",
19
- "TX": "Text data",
20
- "FT": "Formatted text",
21
- //Numerical
22
- "CQ": "Composite quantity with units",
23
- "MO": "Money",
24
- "NM": "Numeric",
25
- "SI": "Sequence ID",
26
- "SN": "Structured numeric",
27
- //Identifier
28
- "ID": "Coded values for HL7 tables",
29
- "IS": "Coded values for user-defined tables",
30
- "HD": "Hierarchic designator",
31
- "EI": "Entity identifier",
32
- "RP": "Reference pointer",
33
- "PL": "Person location",
34
- "PT": "Processing type",
35
- //Date/Time
36
- "DT": "Date",
37
- "DTM": "Date/Time",
38
- "TM": "Time",
39
- "TS": "Time stamp",
40
- //Code Values
41
- "CE": "Coded element",
42
- "CF": "Coded element with formatted values",
43
- "CK": "Composite ID with check digit",
44
- "CN": "Composite ID number and name",
45
- "CX": "Extended composite ID with check digit",
46
- "XCN": "Extended composite ID number and name",
47
- //Generic
48
- "CM": "Composite",
49
- //Demographics
50
- "AD": "Address",
51
- "PN": "Person name",
52
- "TN": "Telephone number",
53
- "XAD": "Extended address",
54
- "XPN": "Extended person name",
55
- "XON": "Extended composite name and ID number for organizations",
56
- "XTN": "Extended telecommunications number",
57
- //Specialty/Chapter specific
58
- "CD": "Channel definition",
59
- "MA": "Multiplexed array",
60
- "NA": "Numeric array",
61
- "ED": "Encapsulated data",
62
- "CP": "Composite price",
63
- "FC": "Financial class",
64
- //Extended Queries
65
- "QSC": "Query selection criteria",
66
- "QIP": "Query input parameter list",
67
- "RCD": "Row column definition",
68
- //Master Files
69
- "DLN": "Driver’s license number",
70
- "JCC": "Job code/class",
71
- "VH": "Visiting hours",
72
- //Medical Records/Info Mgmt
73
- "PPN": "Performing person time stamp",
74
- //Time Series
75
- "DR": "Date/time range",
76
- "RI": "Repeat interval",
77
- "SCV": "Scheduling class value pair",
78
- "TQ": "Timing/quantity"
79
- },
80
-
81
- // message delimiters
82
- delimiters : {
83
- segment: "\r", // "\r\n" for display
84
- field: "|",
85
- component: "^",
86
- subcomponent: "&",
87
- repetition: "~",
88
- escape: "\\"
89
- },
90
-
91
- // OBX segment
92
- OBX: [
93
- {"seq":1, "len":4, "dt":"SI", "opt":"O","name":"Set ID"},
94
- {"seq":2, "len":2, "dt":"ID", "opt":"R","name":"Value Type"},
95
- {"seq":3, "len":590, "dt":"CE", "opt":"R","name":"Observation Identifier"},
96
- {"seq":4, "len":20, "dt":"ST", "opt":"O","name":"Observation Sub-ID"},
97
- {"seq":5, "len":65536, "dt":"ST", "opt":"O","name":"Observation Value"},
98
- {"seq":6, "len":60, "dt":"CE", "opt":"O","name":"Units"},
99
- {"seq":7, "len":10, "dt":"ST", "opt":"O","name":"Reference Range"},
100
- {"seq":8, "len":5, "dt":"ID", "opt":"O","name":"Abnormal Flags"},
101
- {"seq":9, "len":5, "dt":"NM", "opt":"O","name":"Probability"},
102
- {"seq":10, "len":2, "dt":"ID", "opt":"O","name":"Nature of Abnormal Test"},
103
- {"seq":11, "len":1, "dt":"ID", "opt":"R","name":"Observation Result Status"},
104
- {"seq":12, "len":26, "dt":"TS", "opt":"O","name":"Date Last Obs Normal Values"},
105
- {"seq":13, "len":20, "dt":"ST", "opt":"O","name":"User Defined Access Checks"},
106
- {"seq":14, "len":26, "dt":"TS", "opt":"O","name":"Date/Time of the Observation"},
107
- {"seq":15, "len":60, "dt":"CE", "opt":"O","name":"Producer's ID"},
108
- {"seq":16, "len":80, "dt":"XCN", "opt":"O","name":"Responsible Observer"},
109
- {"seq":17, "len":80, "dt":"CE", "opt":"O","name":"Observation Method"}
110
- ],
111
-
112
- // OBR segment
113
- OBR: [
114
- {"seq":1, "len":4, "dt":"SI", "opt":"C","name":"Set ID - OBR"},
115
- {"seq":2, "len":75 , "dt":"EI", "opt":"C","name":"Placer Order Number"},
116
- {"seq":3, "len":75 , "dt":"EI", "opt":"C","name":"Filler Order Number"},
117
- {"seq":4, "len":200, "dt":"CE", "opt":"R","name":"Universal Service ID"},
118
- {"seq":5, "len":2, "dt":"ID", "opt":"B","name":"Priority"},
119
- {"seq":6, "len":26 , "dt":"TS", "opt":"B","name":"Requested Date/time"},
120
- {"seq":7, "len":26 , "dt":"TS", "opt":"C","name":"Observation Date/Time"},
121
- {"seq":8, "len":26 , "dt":"TS", "opt":"O","name":"Observation End Date/Time"},
122
- {"seq":9, "len":20 , "dt":"CQ", "opt":"O","name":"Collection Volume"},
123
- {"seq":10,"len":60 ,"dt":"XCN","opt":"O","name":"Collector Identifier"},
124
- {"seq":11,"len":1 ,"dt":"ID", "opt":"O","name":"Specimen Action Code"},
125
- {"seq":12,"len":60 ,"dt":"CE", "opt":"O","name":"Danger Code"},
126
- {"seq":13,"len":300 ,"dt":"ST", "opt":"O","name":"Relevant Clinical Info."},
127
- {"seq":14,"len":26 ,"dt":"TS", "opt":"C","name":"Specimen Received Date/Time"},
128
- {"seq":15,"len":300 ,"dt":"CM", "opt":"O","name":"Specimen Source"},
129
- {"seq":16,"len":80 ,"dt":"XCN","opt":"O","name":"Ordering Provider"},
130
- {"seq":17,"len":40 ,"dt":"XTN","opt":"O","name":"Order Callback Phone Number"},
131
- {"seq":18,"len":60 ,"dt":"ST", "opt":"O","name":"Placer field 1"},
132
- {"seq":19,"len":60 ,"dt":"ST", "opt":"O","name":"Placer field 2"},
133
- {"seq":20,"len":60 ,"dt":"ST", "opt":"O","name":"Filler Field 1"},
134
- {"seq":21,"len":60 ,"dt":"ST", "opt":"O","name":"Filler Field 2"},
135
- {"seq":22,"len":26 ,"dt":"TS", "opt":"C","name":"Results Rpt/Status Chng - Date/Time"},
136
- {"seq":23,"len":40 ,"dt":"CM", "opt":"O","name":"Charge to Practice"},
137
- {"seq":24,"len":10 ,"dt":"ID", "opt":"O","name":"Diagnostic Serv Sect ID"},
138
- {"seq":25,"len":1 ,"dt":"ID", "opt":"C","name":"Result Status"},
139
- {"seq":26,"len":400 ,"dt":"CM", "opt":"O","name":"Parent Result"},
140
- {"seq":27,"len":200 ,"dt":"TQ", "opt":"O","name":"Quantity/Timing"},
141
- {"seq":28,"len":150 ,"dt":"XCN","opt":"O","name":"Result Copies To"},
142
- {"seq":29,"len":150 ,"dt":"CM", "opt":"O","name":"Parent"},
143
- {"seq":30,"len":20 ,"dt":"ID", "opt":"O","name":"Transportation Mode"},
144
- {"seq":31,"len":300 ,"dt":"CE", "opt":"O","name":"Reason for Study"},
145
- {"seq":32,"len":200 ,"dt":"CM", "opt":"O","name":"Principal Result Interpreter"},
146
- {"seq":33,"len":200 ,"dt":"CM", "opt":"O","name":"Assistant Result Interpreter"},
147
- {"seq":34,"len":200 ,"dt":"CM", "opt":"O","name":"Technician"},
148
- {"seq":35,"len":200 ,"dt":"CM", "opt":"O","name":"Transcriptionist"},
149
- {"seq":36,"len":26 ,"dt":"TS", "opt":"O","name":"Scheduled Date/Time"},
150
- {"seq":37,"len":4 ,"dt":"NM", "opt":"O","name":"Number of Sample Containers"},
151
- {"seq":38,"len":60 ,"dt":"CE", "opt":"O","name":"Transport Logistics of Collected Sample"},
152
- {"seq":39,"len":200 ,"dt":"CE", "opt":"O","name":"Collector’s Comment"},
153
- {"seq":40,"len":60 ,"dt":"CE", "opt":"O","name":"Transport Arrangement Responsibility"},
154
- {"seq":41,"len":30 ,"dt":"ID", "opt":"O","name":"Transport Arranged"},
155
- {"seq":42,"len":1 ,"dt":"ID", "opt":"O","name":"Escort Required"},
156
- {"seq":43,"len":200 ,"dt":"CE", "opt":"O","name":"Planned Patient Transport Comment"}
157
- ],
158
-
159
- getHL7V2DataType: function(lformsDataType) {
160
-
161
- var ret;
162
- switch (lformsDataType) {
163
- case "INT":
164
- case "REAL":
165
- case "QTY":
166
- ret = "NM";
167
- break;
168
- case "NR":
169
- case "TX":
170
- case "DT":
171
- case "DTM":
172
- case "TM":
173
- case "CNE":
174
- case "CWE":
175
- ret = lformsDataType;
176
- break;
177
- // Commenting out these cases which are handled by the default, but
178
- // leaving them here for reference.
179
- /*
180
- case "BIN":
181
- case "RTO":
182
- case "YEAR":
183
- case "MONTH":
184
- case "DAY":
185
- case "URL":
186
- case "EMAIL":
187
- case "PHONE":
188
- case "BL":
189
- case "":
190
- case "ST":
191
- ret = "ST";
192
- break; */
193
- default:
194
- ret = "ST";
195
- }
196
-
197
- return ret;
198
- },
199
-
200
-
201
- // create HL7 OBR and OBX segments only
202
- /**
203
- * Convert LForms form data into HL7 OBR and OBX segments
204
- * @param lfData a LForms form data object
205
- * @returns {string}
206
- */
207
- toHL7Segments: function(lfData) {
208
- var hl7String = '';
209
- var formInfo = {
210
- obrIndex: 1,
211
- obxIndex: 1
212
- };
213
-
214
- // get form data with questions that have no values
215
- var formData = lfData.getFormData(false, true);
216
-
217
- this._generateOBX4(formData);
218
-
219
- // form level info
220
- var formObrArray = new Array(this.obrFieldNum); // initial value is undefined
221
- // index = seq - 1
222
- formObrArray[0] = "OBR";
223
- formObrArray[1] = "1";
224
- formObrArray[4] = formData.code + this.delimiters.component + formData.name + this.delimiters.component + this.LOINC_CS;
225
-
226
- if (formData.templateOptions.formHeaderItems &&
227
- formData.templateOptions.formHeaderItems.length > 0) {
228
- for (var i= 0, iLen=formData.templateOptions.formHeaderItems.length; i< iLen; i++) {
229
- if (formData.templateOptions.formHeaderItems[i].questionCode === "date_done" &&
230
- formData.templateOptions.formHeaderItems[i].value) {
231
- formObrArray[7] = LForms.Util.formatDate(formData.templateOptions.formHeaderItems[i].value, this._DTM_FMT);
232
- }
233
- else if (formData.templateOptions.formHeaderItems[i].questionCode === "where_done" &&
234
- formData.templateOptions.formHeaderItems[i].value) {
235
- formObrArray[13] = formData.templateOptions.formHeaderItems[i].value.text;
236
- }
237
- }
238
- }
239
-
240
- // ignore ending empty fields
241
- var foundValue = false;
242
- for(var i=this.obrFieldNum-1; i>=0; i--) {
243
- if (!foundValue && formObrArray[i] === undefined) {
244
- continue;
245
- }
246
- else if (formObrArray[i] !== undefined) {
247
- hl7String = formObrArray[i] + this.delimiters.field + hl7String;
248
- }
249
- else {
250
- hl7String += this.delimiters.field;
251
- }
252
- }
253
- hl7String += this.delimiters.segment;
254
-
255
- // process the questions/sections
256
- if (formData.items) {
257
- var obxIndex = 0;
258
- for (var j = 0, jLen = formData.items.length; j < jLen; j++) {
259
- if (formData.items[j].dataType !== "TITLE") {
260
- // Note: OBX1 value is not reset for sub panels in the current design.
261
- // if (formData.items[j].header) {
262
- // formInfo.obxIndex = 1;
263
- // }
264
- hl7String += this._itemToHL7v2(formData.items[j], formInfo);
265
- }
266
- }
267
- }
268
- return hl7String;
269
- },
270
-
271
-
272
- /**
273
- * Calculate OBX4 values of each item in the form
274
- * @param formData form data that also includes user data
275
- * @private
276
- */
277
- _generateOBX4: function(formData) {
278
-
279
- if (formData && formData.items) {
280
- this._precessOBX4AtOneLevel("", formData.items)
281
- }
282
- },
283
-
284
-
285
- /**
286
- * Calculate OBX4 values for questions/sections at one level
287
- * @param parentOBX4 the containing section item's obx4 value
288
- * @param items, the list of items at the level
289
- * @private
290
- */
291
- _precessOBX4AtOneLevel: function(parentOBX4, items) {
292
- var sectionSN = 0;
293
- var repeatingIndex = 1;
294
- var prevItem = null;
295
- // go through questions/sections from top to bottom
296
- for (var i=0, iLen=items.length; i<iLen; i++) {
297
- var item = items[i];
298
- // if it's a section
299
- if (item.dataType === "SECTION") {
300
-
301
- // if it repeats
302
- var max = item.questionCardinality.max;
303
- if (max && (max === "*" || parseInt(max) > 1)) {
304
- // skip if all questions within it have no values
305
- if (!this._isSectionEmpty(item)) {
306
- // get the repeating instance letter
307
- if (!prevItem || prevItem && prevItem.questionCode !== item.questionCode) {
308
- repeatingIndex = 1;
309
- sectionSN += 1;
310
- }
311
- else {
312
- repeatingIndex +=1;
313
- }
314
- var repeatingLetter = LForms.Util.getNextLetter(repeatingIndex);
315
- item._obx4 = parentOBX4 ? parentOBX4 + "." + sectionSN + repeatingLetter : sectionSN + repeatingLetter;
316
- this._precessOBX4AtOneLevel(item._obx4, item.items);
317
- }
318
- // skip if it is an empty section, not to set prevItem
319
- else {
320
- continue;
321
- }
322
- }
323
- // if it does not repeat
324
- // Note: not to skip even if all questions within is has no values,
325
- // because the SN still increases in this case.
326
- else {
327
- repeatingIndex = 1;
328
- sectionSN += 1;
329
- item._obx4 = parentOBX4 ? parentOBX4 + "." + sectionSN: sectionSN;
330
- this._precessOBX4AtOneLevel(item._obx4, item.items);
331
- }
332
- }
333
- // if it's a question
334
- else{
335
- // if it repeats
336
- var max = item.questionCardinality.max;
337
- if (max && (max === "*" || parseInt(max) > 1)) {
338
- // if it has value
339
- if (!LForms.Util.isItemValueEmpty(item.value)) {
340
- // get the repeating instance letter
341
- if (!prevItem || prevItem && prevItem.questionCode !== item.questionCode) {
342
- repeatingIndex = 1;
343
- }
344
- else {
345
- repeatingIndex += 1;
346
- }
347
- var repeatingLetter = LForms.Util.getNextLetter(repeatingIndex);
348
- item._obx4 = parentOBX4 ? parentOBX4 + "." + repeatingLetter : repeatingLetter;
349
- }
350
- // skip if it has no values, not to set prevItem
351
- else {
352
- continue;
353
- }
354
- }
355
- // if it does not repeat
356
- else {
357
- item._obx4 = parentOBX4 ? parentOBX4 : "";
358
- repeatingIndex = 1;
359
- }
360
-
361
- }
362
- prevItem = item;
363
- }
364
- },
365
-
366
-
367
- /**
368
- * Constructs an OBX5 for a list item (CNE/CWE)
369
- * @param itemVal a value for a list item
370
- * @param dataType the data type of the item (CNE or CWE)
371
- * @return the OBX5 field string
372
- */
373
- _generateOBX5: function(itemVal, dataType, answerCS) {
374
- var rtn;
375
- var code = itemVal.code;
376
- if (dataType === 'CWE' && !code && code !== 0) {
377
- // For non-coded values, the text goes in OBX 5.9
378
- rtn = this.delimiters.component.repeat(8) + itemVal.text;
379
- }
380
- else {
381
- var answerCS = !itemVal.system ? "" : (itemVal.system === 'LOINC' || itemVal.system === LOINC_URI) ?
382
- this.LOINC_CS : itemVal.system;
383
- rtn = code + this.delimiters.component +
384
- itemVal.text + this.delimiters.component + answerCS;
385
- }
386
- return rtn;
387
- },
388
-
389
- _DT_FMT: 'YYYYMMDD',
390
- _DTM_FMT: 'YYYYMMDDHHmmss',
391
- /**
392
- * Convert an item to one or more HL7 v2 OBX records.
393
- * @param item an item in LForms form data
394
- * @param formInfo index info of the form
395
- * @returns {string}
396
- */
397
- _itemToHL7v2: function(item, formInfo) {
398
- var hl7Seg = "";
399
- var questionCS = this.LOINC_CS;
400
-
401
- if (item.dataType !== "TITLE") {
402
- var itemObrArray = new Array(this.obrFieldNum);
403
-
404
- // a sub panel
405
- if (item.header) {
406
- var obrSeg = "";
407
- itemObrArray[0] = "OBR";
408
- itemObrArray[1] = ++formInfo.obrIndex;
409
-
410
- itemObrArray[4] = item.questionCode + this.delimiters.component +
411
- item.question + this.delimiters.component + questionCS;
412
-
413
- // ignore ending empty fields
414
- var foundValue = false;
415
- for(var i=this.obrFieldNum-1; i>=0; i--) {
416
- if (!foundValue && itemObrArray[i] === undefined) {
417
- continue;
418
- }
419
- else if (itemObrArray[i] !== undefined) {
420
- obrSeg = itemObrArray[i] + this.delimiters.field + obrSeg;
421
- }
422
- else {
423
- obrSeg += this.delimiters.field;
424
- }
425
- }
426
- obrSeg += this.delimiters.segment;
427
-
428
- //// Note: not to add obr segments for now.
429
- //hl7Seg += obrSeg;
430
-
431
- if(item.items) {
432
- var obxIndex = 0;
433
- for(var j=0, jLen=item.items.length; j<jLen; j++) {
434
- // Note: OBX1 value is not reset for sub panels in the current design.
435
- // if (item.items[j].header) {
436
- // //formInfo.obxIndex = 1;
437
- // }
438
- hl7Seg += this._itemToHL7v2(item.items[j], formInfo);
439
- }
440
- }
441
- }
442
- // a question, only when it has value
443
- else if (!LForms.Util.isItemValueEmpty(item.value)) {
444
- var isArrayVal = Array.isArray(item.value);
445
- var vals = isArrayVal ? item.value : [item.value];
446
-
447
- var itemObxArray = [];
448
- itemObxArray[0] = "OBX";
449
- itemObxArray[1] = formInfo.obxIndex++;
450
- itemObxArray[2] = this.getHL7V2DataType(item.dataType);
451
- itemObxArray[3] = item.questionCode + this.delimiters.component +
452
- item.question + this.delimiters.component + questionCS;
453
- // unit
454
- if (item.unit) {
455
- var unitName ="";
456
- if (item.unit.name !== undefined) {
457
- unitName = item.unit.name;
458
- }
459
- itemObxArray[6] = unitName + this.delimiters.component + unitName + this.delimiters.component + this.LOINC_CS;
460
- }
461
-
462
- for (var i=0, len=vals.length; i<len; ++i) {
463
- var val = vals[i];
464
- // OBX4 - sub id
465
- itemObxArray[4] = item._obx4;
466
- if (isArrayVal) {
467
- if (item._obx4 !== '')
468
- itemObxArray[4] += ".";
469
- itemObxArray[4] += LForms.Util.getNextLetter(i+1);
470
- }
471
-
472
- // OBX5 (answer value)
473
- if (item.dataType === 'CNE' || item.dataType === 'CWE') {
474
- itemObxArray[5] = this._generateOBX5(val, item.dataType);
475
- }
476
- else if (item.dataType === 'DT' || item.dataType === 'DTM') {
477
- var dv = (typeof val === 'string')? LForms.Util.stringToDate(val): val;
478
- itemObxArray[5] = LForms.Util.formatDate(dv, item.dataType === 'DT'? this._DT_FMT: this._DTM_FMT);
479
- }
480
- else {
481
- itemObxArray[5] = val.toString();
482
- }
483
- // ignore ending empty fields
484
- hl7Seg += itemObxArray.join(this.delimiters.field)
485
- + this.delimiters.field + this.delimiters.segment;
486
- }
487
-
488
- } // if value is not empty
489
- }
490
- return hl7Seg;
491
- },
492
-
493
-
494
- /**
495
- * Check if all questions within a section have no values
496
- * @param section a section item
497
- * @private
498
- */
499
- _isSectionEmpty: function(sectionItem) {
500
- var empty = true;
501
- if (sectionItem.items) {
502
- for(var i=0, iLen=sectionItem.items.length; i<iLen && empty; i++) {
503
- var item = sectionItem.items[i];
504
- // sub section
505
- if (item.dataType === "SECTION") {
506
- // has been checked already
507
- if (item._emptySection === true || item._emptySection === false) {
508
- empty = item._emptySection;
509
- }
510
- else {
511
- empty = this._isSectionEmpty(item);
512
- }
513
- }
514
- // questions
515
- else {
516
- empty = LForms.Util.isItemValueEmpty(item.value);
517
- }
518
- } // end of for loop
519
- }
520
- // set the flag
521
- sectionItem._emptySection = empty;
522
- return empty;
523
- }
524
- } // return
525
- })();