maidr 1.0.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 (206) hide show
  1. package/.Rbuildignore +1 -0
  2. package/.eslintignore +3 -0
  3. package/.eslintrc.json +6 -0
  4. package/.github/workflows/build.yml +20 -0
  5. package/.prettierignore +3 -0
  6. package/.prettierrc.json +7 -0
  7. package/.vscode/extensions.json +25 -0
  8. package/.vscode/settings.json +30 -0
  9. package/.vscode/tasks.json +57 -0
  10. package/CHANGELOG.md +7 -0
  11. package/CITATION.cff +21 -0
  12. package/CONTRIBUTING.md +87 -0
  13. package/LICENSE.md +595 -0
  14. package/README.md +341 -0
  15. package/dist/maidr.js +8851 -0
  16. package/dist/maidr.min.js +1 -0
  17. package/dist/styles.css +244 -0
  18. package/dist/styles.min.css +1 -0
  19. package/docs/Audio.html +1398 -0
  20. package/docs/Constants.html +256 -0
  21. package/docs/Description.html +582 -0
  22. package/docs/Helper.html +364 -0
  23. package/docs/LogError.html +905 -0
  24. package/docs/Menu.html +665 -0
  25. package/docs/Position.html +174 -0
  26. package/docs/Resources.html +338 -0
  27. package/docs/Review.html +333 -0
  28. package/docs/Tracker.html +965 -0
  29. package/docs/audio.js.html +635 -0
  30. package/docs/constants.js.html +1242 -0
  31. package/docs/display.js.html +1184 -0
  32. package/docs/fonts/OpenSans-Bold-webfont.eot +0 -0
  33. package/docs/fonts/OpenSans-Bold-webfont.svg +1830 -0
  34. package/docs/fonts/OpenSans-Bold-webfont.woff +0 -0
  35. package/docs/fonts/OpenSans-BoldItalic-webfont.eot +0 -0
  36. package/docs/fonts/OpenSans-BoldItalic-webfont.svg +1830 -0
  37. package/docs/fonts/OpenSans-BoldItalic-webfont.woff +0 -0
  38. package/docs/fonts/OpenSans-Italic-webfont.eot +0 -0
  39. package/docs/fonts/OpenSans-Italic-webfont.svg +1830 -0
  40. package/docs/fonts/OpenSans-Italic-webfont.woff +0 -0
  41. package/docs/fonts/OpenSans-Light-webfont.eot +0 -0
  42. package/docs/fonts/OpenSans-Light-webfont.svg +1831 -0
  43. package/docs/fonts/OpenSans-Light-webfont.woff +0 -0
  44. package/docs/fonts/OpenSans-LightItalic-webfont.eot +0 -0
  45. package/docs/fonts/OpenSans-LightItalic-webfont.svg +1835 -0
  46. package/docs/fonts/OpenSans-LightItalic-webfont.woff +0 -0
  47. package/docs/fonts/OpenSans-Regular-webfont.eot +0 -0
  48. package/docs/fonts/OpenSans-Regular-webfont.svg +1831 -0
  49. package/docs/fonts/OpenSans-Regular-webfont.woff +0 -0
  50. package/docs/fonts/OpenSans-Semibold-webfont.eot +0 -0
  51. package/docs/fonts/OpenSans-Semibold-webfont.svg +1830 -0
  52. package/docs/fonts/OpenSans-Semibold-webfont.ttf +0 -0
  53. package/docs/fonts/OpenSans-Semibold-webfont.woff +0 -0
  54. package/docs/fonts/OpenSans-SemiboldItalic-webfont.eot +0 -0
  55. package/docs/fonts/OpenSans-SemiboldItalic-webfont.svg +1830 -0
  56. package/docs/fonts/OpenSans-SemiboldItalic-webfont.ttf +0 -0
  57. package/docs/fonts/OpenSans-SemiboldItalic-webfont.woff +0 -0
  58. package/docs/index.html +66 -0
  59. package/docs/scripts/linenumber.js +25 -0
  60. package/docs/scripts/prettify/Apache-License-2.0.txt +202 -0
  61. package/docs/scripts/prettify/lang-css.js +2 -0
  62. package/docs/scripts/prettify/prettify.js +28 -0
  63. package/docs/styles/jsdoc-default.css +692 -0
  64. package/docs/styles/prettify-jsdoc.css +111 -0
  65. package/docs/styles/prettify-tomorrow.css +132 -0
  66. package/examples/dev_charts/barplot.html +1056 -0
  67. package/examples/dev_charts/boxplot.html +1856 -0
  68. package/examples/dev_charts/boxplot_flipped.svg +727 -0
  69. package/examples/dev_charts/heatmap.html +1217 -0
  70. package/examples/dev_charts/scatterplot/displ.js +18 -0
  71. package/examples/dev_charts/scatterplot/histogram_for_residual.svg +595 -0
  72. package/examples/dev_charts/scatterplot/hwy.js +15 -0
  73. package/examples/dev_charts/scatterplot/layers/point_layer.json +938 -0
  74. package/examples/dev_charts/scatterplot/layers/smooth_layer.json +322 -0
  75. package/examples/dev_charts/scatterplot/point_layer.js +938 -0
  76. package/examples/dev_charts/scatterplot/prediction_array.js +31 -0
  77. package/examples/dev_charts/scatterplot/prediction_array.json +31 -0
  78. package/examples/dev_charts/scatterplot/residual_array.js +29 -0
  79. package/examples/dev_charts/scatterplot/residual_array.json +29 -0
  80. package/examples/dev_charts/scatterplot/scatterplot.svg +1428 -0
  81. package/examples/dev_charts/scatterplot/scatterplot_data.html +2838 -0
  82. package/examples/dev_charts/scatterplot/scatterplot_no_jitter_point_only.svg +1393 -0
  83. package/examples/dev_charts/scatterplot/scatterplot_no_jitter_with_bestfit.svg +1424 -0
  84. package/examples/dev_charts/scatterplot/scatterplot_no_jitter_with_loess_curve.svg +1402 -0
  85. package/examples/dev_charts/scatterplot/smooth_layer.js +322 -0
  86. package/examples/dev_charts/scatterplot.html +4560 -0
  87. package/examples/dodged_bar/dodged_bar.png +0 -0
  88. package/examples/dodged_bar/dodged_bar.svg +198 -0
  89. package/examples/dodged_bar/schema.json +41 -0
  90. package/examples/histogram/histogram_tutorial.svg +482 -0
  91. package/examples/histogram/histogram_tutorial_raw_data.json +362 -0
  92. package/examples/histogram/histogram_user_study.svg +578 -0
  93. package/examples/histogram/histogram_user_study_raw_data.json +362 -0
  94. package/examples/lineplot/lineplot_sample.svg +126 -0
  95. package/examples/lineplot/lineplot_sample_raw_data.json +1 -0
  96. package/examples/lineplot/point+lineplot_sample.svg +700 -0
  97. package/examples/other/audio_oscillator_boxplot.js +95 -0
  98. package/examples/other/barplot_labels.svg +314 -0
  99. package/examples/other/barplot_user_study.svg +313 -0
  100. package/examples/other/boxplot.html +927 -0
  101. package/examples/other/boxplot_data_frame.html +568 -0
  102. package/examples/other/boxplot_label.svg +751 -0
  103. package/examples/other/braille-display_boxplot.js +79 -0
  104. package/examples/other/control_boxplot.js +55 -0
  105. package/examples/other/draft.js +56 -0
  106. package/examples/other/getData.html +400 -0
  107. package/examples/other/getData.js +41 -0
  108. package/examples/other/ggplot_to_svg.R +371 -0
  109. package/examples/other/heatmap.svg +582 -0
  110. package/examples/other/heatmap_label.svg +608 -0
  111. package/examples/other/multiple_barplot.html +2250 -0
  112. package/examples/other/new_scatterplot_user_study_point_layer.json +122 -0
  113. package/examples/other/py_binder_output.html +1167 -0
  114. package/examples/other/scatterplot_label.svg +1429 -0
  115. package/examples/other/seaborn_plot.py +9 -0
  116. package/examples/other/svglite_bar.svg +136 -0
  117. package/examples/other/tutorial_boxplot.svg +727 -0
  118. package/examples/other/tutorial_boxplot_data.json +72 -0
  119. package/examples/other/user_study_boxplot.svg +676 -0
  120. package/examples/stacked_bar/schema.json +41 -0
  121. package/examples/stacked_bar/stack_bar.png +0 -0
  122. package/examples/stacked_bar/stacked_bar.svg +180 -0
  123. package/examples/stacked_normalized_bar/stacked_normalized_bar.png +0 -0
  124. package/examples/stacked_normalized_bar/stacked_normalized_bar.svg +189 -0
  125. package/examples/static/barplot.svg +263 -0
  126. package/examples/static/barplot_diamonds_gridSVG.svg +254 -0
  127. package/examples/static/boxplot.svg +424 -0
  128. package/examples/static/heatmap.svg +373 -0
  129. package/examples/static/heatmap_penguins_table.html +486 -0
  130. package/examples/static/scatterplot.svg +530 -0
  131. package/examples/svglite/task_heatmap.html +802 -0
  132. package/examples/svglite/task_heatmap.svg +111 -0
  133. package/examples/svglite/tutorial_bar.svg +136 -0
  134. package/examples/svglite/tutorial_bar_plot.html +504 -0
  135. package/examples/svglite/tutorial_boxplot.html +1850 -0
  136. package/examples/svglite/tutorial_boxplot.svg +727 -0
  137. package/examples/svglite/tutorial_scatterplot.html +3135 -0
  138. package/examples/svglite/tutorial_scatterplot.svg +311 -0
  139. package/gulpfile.js +49 -0
  140. package/index.html +40 -0
  141. package/jsconfig.json +10 -0
  142. package/jsdoc.json +19 -0
  143. package/package.json +47 -0
  144. package/src/css/styles.css +241 -0
  145. package/src/js/__tests__/audio.test.js +49 -0
  146. package/src/js/__tests__/constants.test.js +622 -0
  147. package/src/js/audio.js +575 -0
  148. package/src/js/barplot.js +254 -0
  149. package/src/js/boxplot.js +682 -0
  150. package/src/js/constants.js +1182 -0
  151. package/src/js/controls.js +3182 -0
  152. package/src/js/display.js +1124 -0
  153. package/src/js/heatmap.js +411 -0
  154. package/src/js/histogram.js +134 -0
  155. package/src/js/init.js +427 -0
  156. package/src/js/lineplot.js +219 -0
  157. package/src/js/scatterplot.js +619 -0
  158. package/src/js/segmented.js +268 -0
  159. package/user_study_pilot/binder_test.html +526 -0
  160. package/user_study_pilot/data/barplot_user_study.svg +492 -0
  161. package/user_study_pilot/data/barplot_user_study_raw_data.json +22 -0
  162. package/user_study_pilot/data/boxplot_tutorial.json +72 -0
  163. package/user_study_pilot/data/boxplot_tutorial_horizontal.svg +727 -0
  164. package/user_study_pilot/data/boxplot_user_study.json +52 -0
  165. package/user_study_pilot/data/boxplot_user_study_vertical.svg +675 -0
  166. package/user_study_pilot/data/boxplot_user_study_vertical_horizontal.svg +676 -0
  167. package/user_study_pilot/data/heatmap_user_study.svg +719 -0
  168. package/user_study_pilot/data/heatmap_user_study_raw_data.json +127 -0
  169. package/user_study_pilot/data/new_barplot_user_study.svg +269 -0
  170. package/user_study_pilot/data/new_heatmap_user_study.svg +367 -0
  171. package/user_study_pilot/data/new_scatterplot_user_study.svg +603 -0
  172. package/user_study_pilot/data/new_scatterplot_user_study_point_layer.json +122 -0
  173. package/user_study_pilot/data/scatterplot_user_study (1).svg +321 -0
  174. package/user_study_pilot/data/scatterplot_user_study.svg +603 -0
  175. package/user_study_pilot/data/scatterplot_user_study_point_layer.json +122 -0
  176. package/user_study_pilot/data/scatterplot_user_study_smooth_layer.json +322 -0
  177. package/user_study_pilot/intro.html +215 -0
  178. package/user_study_pilot/jaws_settings/Chrome.JDF +10 -0
  179. package/user_study_pilot/jaws_settings/Firefox.JDF +10 -0
  180. package/user_study_pilot/jaws_settings/backup_utf8/Chrome.JDF +10 -0
  181. package/user_study_pilot/jaws_settings/backup_utf8/Firefox.JDF +10 -0
  182. package/user_study_pilot/jaws_settings/backup_utf8/msedge.JDF +10 -0
  183. package/user_study_pilot/jaws_settings/msedge.JDF +10 -0
  184. package/user_study_pilot/nvda_settings/chrome.dic +10 -0
  185. package/user_study_pilot/nvda_settings/default.dic +10 -0
  186. package/user_study_pilot/nvda_settings/firefox.dic +10 -0
  187. package/user_study_pilot/nvda_settings/msedge.dic +10 -0
  188. package/user_study_pilot/scatterplot.html +4560 -0
  189. package/user_study_pilot/seaborn_test.html +1059 -0
  190. package/user_study_pilot/svglite_test.html +534 -0
  191. package/user_study_pilot/task1_bar_plot.html +1111 -0
  192. package/user_study_pilot/task2_heatmap.html +1661 -0
  193. package/user_study_pilot/task3_boxplot_horizontal.html +1690 -0
  194. package/user_study_pilot/task3_boxplot_vertical.html +1689 -0
  195. package/user_study_pilot/task4_scatterplot.html +2091 -0
  196. package/user_study_pilot/tutorial1_bar_plot.html +1159 -0
  197. package/user_study_pilot/tutorial2_heatmap.html +1276 -0
  198. package/user_study_pilot/tutorial3_boxplot_horizontal.html +1861 -0
  199. package/user_study_pilot/tutorial3_boxplot_vertical.html +1807 -0
  200. package/user_study_pilot/tutorial4_scatterplot.html +5893 -0
  201. package/user_study_pilot/tutorial5_histogram.html +1553 -0
  202. package/user_study_pilot/tutorial6_lineplot.html +1011 -0
  203. package/user_study_pilot/tutorial7_stacked.html +763 -0
  204. package/user_study_pilot/tutorial8_stacked_normalized.html +796 -0
  205. package/user_study_pilot/tutorial9_dodged_bar.html +831 -0
  206. package/user_study_pilot/voiceover_settings/user_study_VoiceOver Archive.voprefs +573 -0
@@ -0,0 +1,619 @@
1
+ document.addEventListener('DOMContentLoaded', function (e) {
2
+ // we wrap in DOMContentLoaded to make sure everything has loaded before we run anything
3
+ });
4
+
5
+ class ScatterPlot {
6
+ constructor() {
7
+ this.prefix = this.GetPrefix();
8
+ // this.SetVisualHighlight();
9
+ this.SetScatterLayer();
10
+ this.SetLineLayer();
11
+ this.SetAxes();
12
+ this.svgScaler = this.GetSVGScaler();
13
+ }
14
+
15
+ // SetVisualHighlight() {
16
+ // let point_index = this.GetElementIndex('point');
17
+ // let smooth_index = this.GetElementIndex('smooth');
18
+ // if (point_index && smooth_index && elements < 2) {
19
+ // logError.LogAbsentElement('point or/and smooth line elements');
20
+ // }
21
+ // if (point_index != -1) {
22
+ // this.CheckData(point_index);
23
+ // }
24
+
25
+ // if (smooth_index != -1) {
26
+ // this.CheckData(smooth_index);
27
+ // }
28
+ // }
29
+
30
+ // CheckData(i) {
31
+ // let elements = 'elements' in singleMaidr ? singleMaidr.elements : null;
32
+
33
+ // // elements does not exist at all
34
+ // if (elements == null) {
35
+ // logError.LogAbsentElement('elements');
36
+ // if (i == 0) constants.hasRect = 0;
37
+ // if (i == 1) constants.hasSmooth = 0;
38
+ // return;
39
+ // }
40
+
41
+ // // elements exists but is empty
42
+ // if (elements.length == 0) {
43
+ // logError.LogAbsentElement('elements');
44
+ // if (i == 0) constants.hasRect = 0;
45
+ // if (i == 1) constants.hasSmooth = 0;
46
+ // return;
47
+ // }
48
+
49
+ // // elements exists but is not an array
50
+ // if (!Array.isArray(elements)) {
51
+ // logError.LogNotArray('elements');
52
+ // if (i == 0) constants.hasRect = 0;
53
+ // if (i == 1) constants.hasSmooth = 0;
54
+ // return;
55
+ // }
56
+
57
+ // // elements.length is more than 2
58
+ // if (elements.length > 2) {
59
+ // logError.LogTooManyElements('elements', 2);
60
+ // }
61
+
62
+ // if ('data' in singleMaidr) {
63
+ // if (i == 0) {
64
+ // // check point elements
65
+ // if (
66
+ // singleMaidr.data[i] == null ||
67
+ // singleMaidr.data[i].length != singleMaidr.elements[i].length
68
+ // ) {
69
+ // constants.hasRect = 0;
70
+ // logError.LogDifferentLengths('point data', 'point elements');
71
+ // }
72
+ // } else if (i == 1) {
73
+ // // check smooth line elements
74
+ // if (
75
+ // singleMaidr.data[i] == null ||
76
+ // (!Array.isArray(singleMaidr.data[i]) &&
77
+ // singleMaidr.data[i].length != this.chartLineX.length)
78
+ // ) {
79
+ // constants.hasSmooth = 0;
80
+ // logError.LogDifferentLengths(
81
+ // 'smooth line data',
82
+ // 'smooth line elements'
83
+ // );
84
+ // }
85
+ // }
86
+ // }
87
+ // }
88
+
89
+ SetAxes() {
90
+ this.x_group_label = '';
91
+ this.y_group_label = '';
92
+ this.title = '';
93
+ if ('labels' in singleMaidr) {
94
+ if ('x' in singleMaidr.labels) {
95
+ this.x_group_label = singleMaidr.labels.x;
96
+ }
97
+ if ('y' in singleMaidr.labels) {
98
+ this.y_group_label = singleMaidr.labels.y;
99
+ }
100
+ if ('title' in singleMaidr.labels) {
101
+ this.title = singleMaidr.labels.title;
102
+ }
103
+ }
104
+ if ('axes' in singleMaidr) {
105
+ if ('x' in singleMaidr.axes) {
106
+ if (this.x_group_label == '') {
107
+ this.x_group_label = singleMaidr.axes.x.label;
108
+ }
109
+ }
110
+ if ('y' in singleMaidr.axes) {
111
+ if (this.y_group_label == '') {
112
+ this.y_group_label = singleMaidr.axes.y.label;
113
+ }
114
+ }
115
+ }
116
+ if ('title' in singleMaidr) {
117
+ if (this.title == '') {
118
+ this.title = singleMaidr.title;
119
+ }
120
+ }
121
+ }
122
+
123
+ SetScatterLayer() {
124
+ // initially set as smooth layer (layer 2), if possible
125
+ let elIndex = this.GetElementIndex('point');
126
+ if (elIndex != -1) {
127
+ this.plotPoints = singleMaidr.elements[elIndex];
128
+ } else if (singleMaidr.type == 'point') {
129
+ this.plotPoints = singleMaidr.elements;
130
+ }
131
+ if (typeof this.plotPoints !== 'undefined') {
132
+ let svgPointCoords = this.GetSvgPointCoords();
133
+ let pointValues = this.GetPointValues();
134
+
135
+ this.chartPointsX = svgPointCoords[0]; // x coordinates of points
136
+ this.chartPointsY = svgPointCoords[1]; // y coordinates of points
137
+
138
+ this.x = pointValues[0]; // actual values of x
139
+ this.y = pointValues[1]; // actual values of y
140
+
141
+ // for sound weight use
142
+ this.points_count = pointValues[2]; // number of each points
143
+ this.max_count = pointValues[3];
144
+ }
145
+ }
146
+
147
+ SetLineLayer() {
148
+ // layer = 2, smooth layer (from singleMaidr types)
149
+ let elIndex = this.GetElementIndex('smooth');
150
+ if (elIndex != -1) {
151
+ this.plotLine = singleMaidr.elements[elIndex];
152
+ } else if (singleMaidr.type == 'smooth') {
153
+ this.plotLine = singleMaidr.elements;
154
+ }
155
+ if (typeof this.plotLine !== 'undefined') {
156
+ let svgLineCoords = this.GetSvgLineCoords();
157
+ let smoothCurvePoints = this.GetSmoothCurvePoints();
158
+
159
+ this.chartLineX = svgLineCoords[0]; // x coordinates of curve
160
+ this.chartLineY = svgLineCoords[1]; // y coordinates of curve
161
+
162
+ this.curveX = smoothCurvePoints[0]; // actual values of x
163
+ this.curvePoints = smoothCurvePoints[1]; // actual values of y
164
+
165
+ this.curveMinY = Math.min(...this.curvePoints);
166
+ this.curveMaxY = Math.max(...this.curvePoints);
167
+ this.gradient = this.GetGradient();
168
+ }
169
+ }
170
+
171
+ GetSvgPointCoords() {
172
+ let points = new Map();
173
+
174
+ for (let i = 0; i < this.plotPoints.length; i++) {
175
+ let x = parseFloat(this.plotPoints[i].getAttribute(this.prefix + 'x')); // .toFixed(1);
176
+ let y = parseFloat(this.plotPoints[i].getAttribute(this.prefix + 'y'));
177
+ if (!points.has(x)) {
178
+ points.set(x, new Set([y]));
179
+ } else {
180
+ points.get(x).add(y);
181
+ }
182
+ }
183
+
184
+ points = new Map(
185
+ [...points].sort(function (a, b) {
186
+ return a[0] - b[0];
187
+ })
188
+ );
189
+
190
+ points.forEach(function (value, key) {
191
+ points[key] = Array.from(value).sort(function (a, b) {
192
+ return a - b;
193
+ });
194
+ });
195
+
196
+ let X = [...points.keys()];
197
+
198
+ let Y = [];
199
+ for (let i = 0; i < X.length; i++) {
200
+ Y.push(points[X[i]]);
201
+ }
202
+
203
+ return [X, Y];
204
+ }
205
+
206
+ GetElementIndex(elementName = 'point') {
207
+ let elIndex = -1;
208
+ if ('type' in singleMaidr) {
209
+ elIndex = singleMaidr.type.indexOf(elementName);
210
+ }
211
+ return elIndex;
212
+ }
213
+
214
+ GetDataXYFormat(dataIndex) {
215
+ // detect if data is in form [{x: 1, y: 2}, {x: 2, y: 3}] (object) or {x: [1, 2], y: [2, 3]]} (array)
216
+ let xyFormat = 'array';
217
+ if (singleMaidr.data[dataIndex]) {
218
+ if (Array.isArray(singleMaidr.data[dataIndex])) {
219
+ xyFormat = 'object';
220
+ }
221
+ }
222
+ return xyFormat;
223
+ }
224
+
225
+ GetSVGScaler() {
226
+ let scaleX = 1;
227
+ let scaleY = 1;
228
+ // start with some square (first), look all the way up the parents to the svg, and record any scales along the way
229
+
230
+ // but first, are we even in an svg that can be scaled?
231
+ let isSvg = false;
232
+ let element = this.plotPoints[0]; // a random start, may as well be the first
233
+ console.log(element);
234
+ while (element) {
235
+ if (element.tagName.toLowerCase() == 'body') {
236
+ break;
237
+ }
238
+ if (element.tagName && element.tagName.toLowerCase() === 'svg') {
239
+ isSvg = true;
240
+ }
241
+ element = element.parentNode;
242
+ }
243
+
244
+ if (isSvg) {
245
+ let element = this.plotPoints[0]; // a random start, may as well be the first
246
+ while (element) {
247
+ if (element.tagName.toLowerCase() == 'body') {
248
+ break;
249
+ }
250
+ if (element.getAttribute('transform')) {
251
+ let transform = element.getAttribute('transform');
252
+ let match = transform.match(
253
+ /scale\((-?\d+(\.\d+)?),\s*(-?\d+(\.\d+)?)\)/
254
+ );
255
+ if (match) {
256
+ if (!isNaN(match[1])) {
257
+ scaleX *= parseFloat(match[1]);
258
+ }
259
+ if (!isNaN(match[3])) {
260
+ scaleY *= parseFloat(match[3]);
261
+ }
262
+ }
263
+ }
264
+ element = element.parentNode;
265
+ }
266
+ }
267
+
268
+ return [scaleX, scaleY];
269
+ }
270
+
271
+ GetPrefix() {
272
+ let elIndex = this.GetElementIndex('point');
273
+ let element;
274
+ if (elIndex != -1) {
275
+ element = singleMaidr.elements[elIndex][0];
276
+ } else if (singleMaidr.type == 'point') {
277
+ element = singleMaidr.elements[0];
278
+ }
279
+ let prefix = '';
280
+ if ('element' in singleMaidr && element.tagName.toLowerCase() == 'circle') {
281
+ prefix = 'c';
282
+ }
283
+ return prefix;
284
+ }
285
+
286
+ GetPointValues() {
287
+ let points = new Map(); // keep track of x and y values
288
+
289
+ let xValues = [];
290
+ let yValues = [];
291
+
292
+ // prepare to fetch data from the correct index in the correct format
293
+ let elIndex = this.GetElementIndex('point');
294
+ let xyFormat = this.GetDataXYFormat(elIndex);
295
+
296
+ let data;
297
+ if (elIndex > -1) {
298
+ // data comes directly as an array, in a 'point' layer, so fetch directly as an array from that index
299
+ data = singleMaidr.data[elIndex];
300
+ } else if (singleMaidr.type == 'point') {
301
+ // data comes directly as an array, no 'point' layer, so fetch directly as an array
302
+ data = singleMaidr.data;
303
+ }
304
+ if (typeof data !== 'undefined') {
305
+ // assuming we got something, loop through the data and extract the x and y values
306
+
307
+ if (xyFormat == 'array') {
308
+ if ('x' in singleMaidr.data[elIndex]) {
309
+ xValues = singleMaidr.data[elIndex]['x'];
310
+ }
311
+ if ('y' in singleMaidr.data[elIndex]) {
312
+ yValues = singleMaidr.data[elIndex]['y'];
313
+ }
314
+ } else if (xyFormat == 'object') {
315
+ for (let i = 0; i < singleMaidr.data[elIndex].length; i++) {
316
+ let x = singleMaidr.data[elIndex][i]['x'];
317
+ let y = singleMaidr.data[elIndex][i]['y'];
318
+ xValues.push(x);
319
+ yValues.push(y);
320
+ }
321
+ }
322
+
323
+ for (let i = 0; i < xValues.length; i++) {
324
+ let x = xValues[i];
325
+ let y = yValues[i];
326
+ if (!points.has(x)) {
327
+ points.set(x, new Map([[y, 1]]));
328
+ } else {
329
+ if (points.get(x).has(y)) {
330
+ let mapy = points.get(x);
331
+ mapy.set(y, mapy.get(y) + 1);
332
+ } else {
333
+ points.get(x).set(y, 1);
334
+ }
335
+ }
336
+ }
337
+
338
+ constants.minX = 0;
339
+ constants.maxX = [...new Set(xValues)].length;
340
+
341
+ constants.minY = Math.min(...yValues);
342
+ constants.maxY = Math.max(...yValues);
343
+
344
+ constants.autoPlayRate = Math.min(
345
+ Math.ceil(constants.AUTOPLAY_DURATION / (constants.maxX + 1)),
346
+ constants.MAX_SPEED
347
+ );
348
+ constants.DEFAULT_SPEED = constants.autoPlayRate;
349
+ if (constants.autoPlayRate < constants.MIN_SPEED) {
350
+ constants.MIN_SPEED = constants.autoPlayRate;
351
+ }
352
+
353
+ points = new Map(
354
+ [...points].sort(function (a, b) {
355
+ return a[0] - b[0];
356
+ })
357
+ );
358
+
359
+ points.forEach(function (value, key) {
360
+ points[key] = Array.from(value).sort(function (a, b) {
361
+ return a[0] - b[0];
362
+ });
363
+ });
364
+
365
+ let X = [];
366
+ let Y = [];
367
+ let points_count = [];
368
+ for (const [x_val, y_val] of points) {
369
+ X.push(x_val);
370
+ let y_arr = [];
371
+ let y_count = [];
372
+ for (const [y, count] of y_val) {
373
+ y_arr.push(y);
374
+ y_count.push(count);
375
+ }
376
+ Y.push(y_arr.sort());
377
+ points_count.push(y_count);
378
+ }
379
+ let max_points = Math.max(...points_count.map((a) => Math.max(...a)));
380
+
381
+ return [X, Y, points_count, max_points];
382
+ } else {
383
+ return;
384
+ }
385
+ }
386
+
387
+ PlayTones() {
388
+ // kill the previous separate-points play before starting the next play
389
+ if (constants.sepPlayId) {
390
+ constants.KillSepPlay();
391
+ }
392
+ if (constants.chartType == 'point') {
393
+ // point layer
394
+ // we play a run of tones
395
+ position.z = 0;
396
+ constants.sepPlayId = setInterval(
397
+ function () {
398
+ // play this tone
399
+ audio.playTone();
400
+
401
+ // and then set up for the next one
402
+ position.z += 1;
403
+
404
+ // and kill if we're done
405
+ if (position.z + 1 > plot.y[position.x].length) {
406
+ constants.KillSepPlay();
407
+ position.z = -1;
408
+ }
409
+ },
410
+ constants.sonifMode == 'on' ? constants.autoPlayPointsRate : 0
411
+ ); // play all tones at the same time
412
+ } else if (constants.chartType == 'smooth') {
413
+ // best fit smooth layer
414
+ audio.playTone();
415
+ }
416
+ }
417
+
418
+ GetSvgLineCoords() {
419
+ // extract all the y coordinates from the point attribute of polyline
420
+ let str = this.plotLine.getAttribute('points');
421
+ let coords = str.split(' ');
422
+
423
+ let X = [];
424
+ let Y = [];
425
+
426
+ for (let i = 0; i < coords.length; i++) {
427
+ let coord = coords[i].split(',');
428
+ X.push(parseFloat(coord[0]));
429
+ Y.push(parseFloat(coord[1]));
430
+ }
431
+
432
+ return [X, Y];
433
+ }
434
+
435
+ GetSmoothCurvePoints() {
436
+ let x_points = [];
437
+ let y_points = [];
438
+
439
+ let elIndex = this.GetElementIndex('smooth');
440
+ let xyFormat = this.GetDataXYFormat(elIndex);
441
+
442
+ let data;
443
+ if (elIndex > -1) {
444
+ // data comes directly as an array, in a 'smooth' layer, so fetch directly as an array from that index
445
+ data = singleMaidr.data[elIndex];
446
+ } else if (singleMaidr.type == 'smooth') {
447
+ // data comes directly as an array, no 'smooth' layer, so fetch directly as an array
448
+ data = singleMaidr.data;
449
+ }
450
+ if (typeof data !== 'undefined') {
451
+ if (xyFormat == 'object') {
452
+ for (let i = 0; i < singleMaidr.data[elIndex].length; i++) {
453
+ x_points.push(singleMaidr.data[elIndex][i]['x']);
454
+ y_points.push(singleMaidr.data[elIndex][i]['y']);
455
+ }
456
+ } else if (xyFormat == 'array') {
457
+ if ('x' in singleMaidr.data[elIndex]) {
458
+ x_points = singleMaidr.data[elIndex]['x'];
459
+ }
460
+ if ('y' in singleMaidr.data[elIndex]) {
461
+ y_points = singleMaidr.data[elIndex]['y'];
462
+ }
463
+ }
464
+
465
+ return [x_points, y_points];
466
+ } else {
467
+ return;
468
+ }
469
+ }
470
+
471
+ GetGradient() {
472
+ let gradients = [];
473
+
474
+ for (let i = 0; i < this.curvePoints.length - 1; i++) {
475
+ let abs_grad = Math.abs(
476
+ (this.curvePoints[i + 1] - this.curvePoints[i]) /
477
+ (this.curveX[i + 1] - this.curveX[i])
478
+ ).toFixed(3);
479
+ gradients.push(abs_grad);
480
+ }
481
+
482
+ gradients.push('end');
483
+
484
+ return gradients;
485
+ }
486
+ }
487
+
488
+ class Layer0Point {
489
+ // circles
490
+
491
+ constructor() {
492
+ this.x = plot.chartPointsX[0];
493
+ this.y = plot.chartPointsY[0];
494
+ this.strokeWidth = 1.35;
495
+ this.circleIndex = [];
496
+ }
497
+
498
+ async UpdatePoints() {
499
+ await this.ClearPoints();
500
+ this.x = plot.chartPointsX[position.x];
501
+ this.y = plot.chartPointsY[position.x];
502
+ // find which circles we're on by searching for the x value
503
+ this.circleIndex = [];
504
+ for (let j = 0; j < this.y.length; j++) {
505
+ for (let i = 0; i < plot.plotPoints.length; i++) {
506
+ if (
507
+ plot.plotPoints[i].getAttribute(plot.prefix + 'x') == this.x &&
508
+ plot.plotPoints[i].getAttribute(plot.prefix + 'y') == this.y[j]
509
+ ) {
510
+ this.circleIndex.push(i);
511
+ break;
512
+ }
513
+ }
514
+ }
515
+ }
516
+
517
+ async PrintPoints() {
518
+ await this.ClearPoints();
519
+ await this.UpdatePoints();
520
+ for (let i = 0; i < this.circleIndex.length; i++) {
521
+ const svgns = 'http://www.w3.org/2000/svg';
522
+ var point = document.createElementNS(svgns, 'circle');
523
+ point.setAttribute('class', 'highlight_point');
524
+ point.setAttribute('cx', this.x);
525
+ if (plot.svgScaler[1] == -1) {
526
+ point.setAttribute(
527
+ 'cy',
528
+ constants.chart.getBoundingClientRect().height - this.y[i]
529
+ );
530
+ } else {
531
+ point.setAttribute(
532
+ 'cy',
533
+ plot.plotPoints[this.circleIndex[i]].getAttribute('cy')
534
+ );
535
+ }
536
+ point.setAttribute('r', 3.95);
537
+ point.setAttribute('stroke', constants.colorSelected);
538
+ point.setAttribute('stroke-width', this.strokeWidth);
539
+ point.setAttribute('fill', constants.colorSelected);
540
+ if (plot.svgScaler[1] == -1) {
541
+ constants.chart.appendChild(point);
542
+ } else {
543
+ plot.plotPoints[this.circleIndex[i]].parentNode.appendChild(point);
544
+ }
545
+ }
546
+ }
547
+
548
+ async ClearPoints() {
549
+ if (document.getElementById('highlight_point'))
550
+ document.getElementById('highlight_point').remove();
551
+ let points = document.getElementsByClassName('highlight_point');
552
+ for (let i = 0; i < points.length; i++) {
553
+ document.getElementsByClassName('highlight_point')[i].remove();
554
+ }
555
+ }
556
+
557
+ UpdatePointDisplay() {
558
+ this.ClearPoints();
559
+ this.UpdatePoints();
560
+ this.PrintPoints();
561
+ }
562
+ }
563
+
564
+ class Layer1Point {
565
+ // smooth segments
566
+
567
+ constructor() {
568
+ this.x = plot.chartLineX[0];
569
+ this.y = plot.chartLineY[0];
570
+ this.strokeWidth = 1.35;
571
+ }
572
+
573
+ async UpdatePoints() {
574
+ await this.ClearPoints();
575
+ this.x = plot.chartLineX[positionL1.x];
576
+ this.y = plot.chartLineY[positionL1.x];
577
+ }
578
+
579
+ async PrintPoints() {
580
+ await this.ClearPoints();
581
+ await this.UpdatePoints();
582
+ const svgns = 'http://www.w3.org/2000/svg';
583
+ var point = document.createElementNS(svgns, 'circle');
584
+ point.setAttribute('id', 'highlight_point');
585
+ point.setAttribute('cx', this.x);
586
+ if (plot.svgScaler[1] == -1) {
587
+ point.setAttribute(
588
+ 'cy',
589
+ constants.chart.getBoundingClientRect().height - this.y
590
+ );
591
+ } else {
592
+ point.setAttribute('cy', this.y);
593
+ }
594
+ point.setAttribute('r', 3.95);
595
+ point.setAttribute('stroke', constants.colorSelected);
596
+ point.setAttribute('stroke-width', this.strokeWidth);
597
+ point.setAttribute('fill', constants.colorSelected);
598
+ if (plot.svgScaler[1] == -1) {
599
+ constants.chart.appendChild(point);
600
+ } else {
601
+ plot.plotLine.parentNode.appendChild(point);
602
+ }
603
+ }
604
+
605
+ async ClearPoints() {
606
+ let points = document.getElementsByClassName('highlight_point');
607
+ for (let i = 0; i < points.length; i++) {
608
+ document.getElementsByClassName('highlight_point')[i].remove();
609
+ }
610
+ if (document.getElementById('highlight_point'))
611
+ document.getElementById('highlight_point').remove();
612
+ }
613
+
614
+ UpdatePointDisplay() {
615
+ this.ClearPoints();
616
+ this.UpdatePoints();
617
+ this.PrintPoints();
618
+ }
619
+ }