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,3182 @@
1
+ class Control {
2
+ constructor() {
3
+ this.SetControls();
4
+ }
5
+
6
+ SetControls() {
7
+ // global controls
8
+
9
+ // variable initialization
10
+ let controlElements = [
11
+ constants.chart,
12
+ constants.brailleInput,
13
+ constants.review_container,
14
+ ];
15
+ let pressedL = false;
16
+ let pressedTimeout = null;
17
+
18
+ // main BTS controls
19
+ for (let i = 0; i < controlElements.length; i++) {
20
+ constants.events.push([
21
+ controlElements[i],
22
+ 'keydown',
23
+ function (e) {
24
+ // init
25
+ let lastPlayed = '';
26
+
27
+ // if we're awaiting an L + X prefix, we don't want to do anything else
28
+ if (pressedL) {
29
+ return;
30
+ }
31
+
32
+ // B: braille mode
33
+ if (e.key == 'b') {
34
+ constants.tabMovement = 0;
35
+ e.preventDefault();
36
+ display.toggleBrailleMode();
37
+ }
38
+
39
+ // T: aria live text output mode
40
+ if (e.key == 't') {
41
+ display.toggleTextMode();
42
+ }
43
+
44
+ // S: sonification mode
45
+ if (e.key == 's') {
46
+ display.toggleSonificationMode();
47
+ }
48
+
49
+ // R: review mode
50
+ if (e.key == 'r' && !e.ctrlKey && !e.shiftKey) {
51
+ // r, but let Ctrl and Shift R go through cause I use that to refresh
52
+ constants.tabMovement = 0;
53
+ e.preventDefault();
54
+ if (constants.review_container.classList.contains('hidden')) {
55
+ review.ToggleReviewMode(true);
56
+ } else {
57
+ review.ToggleReviewMode(false);
58
+ }
59
+ }
60
+
61
+ if (e.key == ' ') {
62
+ // space 32, replay info but no other changes
63
+ if (constants.showDisplay) {
64
+ display.displayValues();
65
+ }
66
+ if (constants.sonifMode != 'off') {
67
+ plot.PlayTones();
68
+ }
69
+ }
70
+
71
+ // switch layer controls
72
+ if (Array.isArray(singleMaidr.type)) {
73
+ // page down /(fn+down arrow): change chart type (layer)
74
+ if (e.key == 'PageDown' && constants.brailleMode == 'off') {
75
+ display.changeChartLayer('down');
76
+ }
77
+
78
+ // page up / (fn+up arrow): change chart type (layer)
79
+ if (e.key == 'PageUp' && constants.brailleMode == 'off') {
80
+ display.changeChartLayer('up');
81
+ }
82
+ }
83
+ },
84
+ ]);
85
+ }
86
+
87
+ // We want to tab or shift tab past the chart,
88
+ // but we delay adding this eventlistener for a moment so the chart loads first
89
+ for (let i = 0; i < controlElements.length; i++) {
90
+ constants.events.push([
91
+ controlElements[i],
92
+ 'keydown',
93
+ function (e) {
94
+ if (e.key == 'Tab') {
95
+ // save key to be used on blur event later
96
+ if (e.shiftKey) {
97
+ constants.tabDirection = -1;
98
+ } else {
99
+ constants.tabDirection = 1;
100
+ }
101
+ }
102
+ },
103
+ ]);
104
+ }
105
+
106
+ // prefix events
107
+ constants.events.push([
108
+ document,
109
+ 'keydown',
110
+ function (e) {
111
+ // init
112
+ let lastPlayed = '';
113
+
114
+ // enable / disable prefix mode
115
+ if (e.key == 'l') {
116
+ pressedL = true;
117
+ if (pressedTimeout != null) {
118
+ clearTimeout(pressedTimeout);
119
+ pressedTimeout = null;
120
+ }
121
+ pressedTimeout = setTimeout(function () {
122
+ pressedL = false;
123
+ }, constants.keypressInterval);
124
+ }
125
+
126
+ // ctrl/cmd: stop autoplay
127
+ if (constants.isMac ? e.metaKey : e.ctrlKey) {
128
+ // (ctrl/cmd)+(home/fn+left arrow): first element
129
+ if (e.key == 'Home') {
130
+ // chart types
131
+ if (constants.chartType == 'bar' || constants.chartType == 'hist') {
132
+ position.x = 0;
133
+ } else if (constants.chartType == 'box') {
134
+ position.x = 0;
135
+ position.y = plot.sections.length - 1;
136
+ } else if (constants.chartType == 'heat') {
137
+ position.x = 0;
138
+ position.y = 0;
139
+ } else if (constants.chartType == 'point') {
140
+ position.x = 0;
141
+ } else if (constants.chartType == 'smooth') {
142
+ positionL1.x = 0;
143
+ }
144
+
145
+ UpdateAllBraille();
146
+ }
147
+
148
+ // (ctrl/cmd)+(end/fn+right arrow): last element
149
+ else if (e.key == 'End') {
150
+ // chart types
151
+ if (constants.chartType == 'bar' || constants.chartType == 'hist') {
152
+ position.x = plot.bars.length - 1;
153
+ } else if (constants.chartType == 'box') {
154
+ position.x = plot.sections.length - 1;
155
+ position.y = 0;
156
+ } else if (constants.chartType == 'heat') {
157
+ position.x = plot.num_cols - 1;
158
+ position.y = plot.num_rows - 1;
159
+ } else if (constants.chartType == 'point') {
160
+ position.x = plot.y.length - 1;
161
+ } else if (constants.chartType == 'smooth') {
162
+ positionL1.x = plot.curvePoints.length - 1;
163
+ }
164
+
165
+ UpdateAllBraille();
166
+ }
167
+ }
168
+
169
+ // Prefix mode stuff: L is enabled, look for these keys
170
+ if (pressedL) {
171
+ if (e.key == 'x') {
172
+ // X: x label
173
+ let xlabel = '';
174
+ if (constants.chartType == 'bar') {
175
+ xlabel = plot.plotLegend.x;
176
+ } else if (
177
+ constants.chartType == 'heat' ||
178
+ constants.chartType == 'box' ||
179
+ singleMaidr.type == 'point' ||
180
+ singleMaidr.type == 'line' ||
181
+ singleMaidr.type.includes('point')
182
+ ) {
183
+ xlabel = plot.x_group_label;
184
+ }
185
+ display.displayInfo('x label', xlabel);
186
+ pressedL = false;
187
+ } else if (e.key == 'y') {
188
+ // Y: y label
189
+ let ylabel = '';
190
+ if (constants.chartType == 'bar') {
191
+ ylabel = plot.plotLegend.y;
192
+ } else if (
193
+ constants.chartType == 'heat' ||
194
+ constants.chartType == 'box' ||
195
+ singleMaidr.type == 'point' ||
196
+ singleMaidr.type == 'line' ||
197
+ singleMaidr.type.includes('point')
198
+ ) {
199
+ ylabel = plot.y_group_label;
200
+ }
201
+ display.displayInfo('y label', ylabel);
202
+ pressedL = false;
203
+ } else if (e.key == 't') {
204
+ // T: title
205
+ display.displayInfo('title', plot.title);
206
+ pressedL = false;
207
+ } else if (e.key == 's') {
208
+ // subtitle
209
+ display.displayInfo('subtitle', plot.subtitle);
210
+ pressedL = false;
211
+ } else if (e.key == 'c') {
212
+ // caption
213
+ display.displayInfo('caption', plot.caption);
214
+ pressedL = false;
215
+ } else if (e.key != 'l') {
216
+ pressedL = false;
217
+ }
218
+ }
219
+
220
+ // // period: speed up
221
+ // if (e.key == '.') {
222
+ // constants.SpeedUp();
223
+ // display.announceText('Speed up');
224
+ // }
225
+
226
+ // // comma: speed down
227
+ // if (e.key == ',') {
228
+ // constants.SpeedDown();
229
+ // display.announceText('Speed down');
230
+ // }
231
+ // // /: reset speed
232
+ // if (e.key == '/') {
233
+ // constants.SpeedReset();
234
+ // display.announceText('Speed reset');
235
+ // }
236
+ },
237
+ ]);
238
+
239
+ if ([].concat(singleMaidr.type).includes('bar')) {
240
+ window.position = new Position(-1, -1);
241
+ window.plot = new BarChart();
242
+
243
+ // global variables
244
+ constants.lastx = 0;
245
+ let lastPlayed = '';
246
+
247
+ // control eventlisteners
248
+ constants.events.push([
249
+ constants.chart,
250
+ 'keydown',
251
+ function (e) {
252
+ let updateInfoThisRound = false; // we only update info and play tones on certain keys
253
+ let isAtEnd = false;
254
+
255
+ if (e.key == 'ArrowRight') {
256
+ if (constants.isMac ? e.metaKey : e.ctrlKey) {
257
+ if (e.shiftKey) {
258
+ position.x -= 1;
259
+ Autoplay('right', position.x, plot.plotData.length);
260
+ } else {
261
+ position.x = plot.plotData.length - 1; // go all the way
262
+ updateInfoThisRound = true;
263
+ isAtEnd = lockPosition();
264
+ }
265
+ } else if (
266
+ e.altKey &&
267
+ e.shiftKey &&
268
+ position.x != plot.bars.length - 1
269
+ ) {
270
+ constants.lastx = position.x;
271
+ Autoplay('reverse-right', plot.bars.length, position.x);
272
+ } else {
273
+ position.x += 1;
274
+ updateInfoThisRound = true;
275
+ isAtEnd = lockPosition();
276
+ }
277
+ } else if (e.key == 'ArrowLeft') {
278
+ // var prevLink = document.getElementById('prev'); // what is prev in the html?
279
+ // if (prevLink) {
280
+ // left arrow 37
281
+ if (constants.isMac ? e.metaKey : e.ctrlKey) {
282
+ if (e.shiftKey) {
283
+ position.x += 1;
284
+ Autoplay('left', position.x, -1);
285
+ } else {
286
+ position.x = 0; // go all the way
287
+ updateInfoThisRound = true;
288
+ isAtEnd = lockPosition();
289
+ }
290
+ } else if (e.altKey && e.shiftKey && position.x != 0) {
291
+ constants.lastx = position.x;
292
+ Autoplay('reverse-left', -1, position.x);
293
+ } else {
294
+ position.x += -1;
295
+ updateInfoThisRound = true;
296
+ isAtEnd = lockPosition();
297
+ }
298
+ // }
299
+ }
300
+
301
+ // update display / text / audio
302
+ if (updateInfoThisRound && !isAtEnd) {
303
+ UpdateAll();
304
+ }
305
+ if (isAtEnd) {
306
+ audio.playEnd();
307
+ }
308
+ },
309
+ ]);
310
+
311
+ constants.events.push([
312
+ constants.brailleInput,
313
+ 'keydown',
314
+ function (e) {
315
+ let updateInfoThisRound = false; // we only update info and play tones on certain keys
316
+ let isAtEnd = false;
317
+
318
+ if (e.key == 'ArrowRight') {
319
+ // right arrow
320
+ e.preventDefault();
321
+ if (e.target.selectionStart > e.target.value.length - 2) {
322
+ } else if (constants.isMac ? e.metaKey : e.ctrlKey) {
323
+ if (e.shiftKey) {
324
+ position.x -= 1;
325
+ Autoplay('right', position.x, plot.plotData.length);
326
+ } else {
327
+ position.x = plot.bars.length - 1; // go all the way
328
+ updateInfoThisRound = true;
329
+ isAtEnd = lockPosition();
330
+ }
331
+ } else if (
332
+ e.altKey &&
333
+ e.shiftKey &&
334
+ position.x != plot.bars.length - 1
335
+ ) {
336
+ constants.lastx = position.x;
337
+ Autoplay('reverse-right', plot.bars.length, position.x);
338
+ } else {
339
+ position.x += 1;
340
+ updateInfoThisRound = true;
341
+ isAtEnd = lockPosition();
342
+ }
343
+ } else if (e.key == 'ArrowLeft') {
344
+ // left arrow
345
+ e.preventDefault();
346
+ if (constants.isMac ? e.metaKey : e.ctrlKey) {
347
+ if (e.shiftKey) {
348
+ position.x += 1;
349
+ Autoplay('left', position.x, -1);
350
+ } else {
351
+ position.x = 0; // go all the way
352
+ updateInfoThisRound = true;
353
+ isAtEnd = lockPosition();
354
+ }
355
+ } else if (e.altKey && e.shiftKey && position.x != 0) {
356
+ constants.lastx = position.x;
357
+ Autoplay('reverse-left', -1, position.x);
358
+ } else {
359
+ position.x += -1;
360
+ updateInfoThisRound = true;
361
+ isAtEnd = lockPosition();
362
+ }
363
+ } else if (e.key == 'Tab') {
364
+ // do nothing, we handle this in global events
365
+ } else {
366
+ e.preventDefault();
367
+ }
368
+
369
+ // update display / text / audio
370
+ if (updateInfoThisRound && !isAtEnd) {
371
+ UpdateAllBraille();
372
+ }
373
+ if (isAtEnd) {
374
+ audio.playEnd();
375
+ }
376
+ },
377
+ ]);
378
+
379
+ let controlElements = [constants.chart, constants.brailleInput];
380
+ let lastx = 0;
381
+ for (let i = 0; i < controlElements.length; i++) {
382
+ constants.events.push([
383
+ controlElements[i],
384
+ 'keydown',
385
+ function (e) {
386
+ // period: speed up
387
+ if (e.key == '.') {
388
+ constants.SpeedUp();
389
+ PlayDuringSpeedChange();
390
+ display.announceText('Speed up');
391
+ }
392
+
393
+ // comma: speed down
394
+ if (e.key == ',') {
395
+ constants.SpeedDown();
396
+ PlayDuringSpeedChange();
397
+ display.announceText('Speed down');
398
+ }
399
+
400
+ // /: reset speed
401
+ if (e.key == '/') {
402
+ constants.SpeedReset();
403
+ PlayDuringSpeedChange();
404
+ display.announceText('Speed reset');
405
+ }
406
+ },
407
+ ]);
408
+ }
409
+ function PlayDuringSpeedChange() {
410
+ if (constants.autoplayId != null) {
411
+ constants.KillAutoplay();
412
+ if (lastPlayed == 'reverse-left') {
413
+ Autoplay('right', position.x, lastx);
414
+ } else if (lastPlayed == 'reverse-right') {
415
+ Autoplay('left', position.x, lastx);
416
+ } else {
417
+ Autoplay(lastPlayed, position.x, lastx);
418
+ }
419
+ }
420
+ }
421
+ function lockPosition() {
422
+ // lock to min / max postions
423
+ let didLockHappen = false;
424
+ // if (!constants.hasRect) {
425
+ // return didLockHappen;
426
+ // }
427
+
428
+ if (position.x < 0) {
429
+ position.x = 0;
430
+ didLockHappen = true;
431
+ }
432
+ if (position.x > plot.plotData.length - 1) {
433
+ position.x = plot.plotData.length - 1;
434
+ didLockHappen = true;
435
+ }
436
+
437
+ return didLockHappen;
438
+ }
439
+ function UpdateAll() {
440
+ if (constants.showDisplay) {
441
+ display.displayValues();
442
+ }
443
+ if (constants.showRect && constants.hasRect) {
444
+ plot.Select();
445
+ }
446
+ if (constants.sonifMode != 'off') {
447
+ plot.PlayTones();
448
+ }
449
+ }
450
+ function UpdateAllAutoplay() {
451
+ if (constants.showDisplayInAutoplay) {
452
+ display.displayValues();
453
+ }
454
+ if (constants.showRect && constants.hasRect) {
455
+ plot.Select();
456
+ }
457
+ if (constants.sonifMode != 'off') {
458
+ plot.PlayTones();
459
+ }
460
+
461
+ if (constants.brailleMode != 'off') {
462
+ display.UpdateBraillePos();
463
+ }
464
+ }
465
+ function UpdateAllBraille() {
466
+ if (constants.showDisplayInBraille) {
467
+ display.displayValues();
468
+ }
469
+ if (constants.showRect && constants.hasRect) {
470
+ plot.Select();
471
+ }
472
+ if (constants.sonifMode != 'off') {
473
+ plot.PlayTones();
474
+ }
475
+ display.UpdateBraillePos();
476
+ }
477
+ function Autoplay(dir, start, end) {
478
+ lastPlayed = dir;
479
+ let step = 1; // default right and reverse-left
480
+ if (dir == 'left' || dir == 'reverse-right') {
481
+ step = -1;
482
+ }
483
+
484
+ // clear old autoplay if exists
485
+ if (constants.autoplayId != null) {
486
+ constants.KillAutoplay();
487
+ }
488
+
489
+ if (dir == 'reverse-right' || dir == 'reverse-left') {
490
+ position.x = start;
491
+ }
492
+
493
+ constants.autoplayId = setInterval(function () {
494
+ position.x += step;
495
+ if (position.x < 0 || plot.plotData.length - 1 < position.x) {
496
+ constants.KillAutoplay();
497
+ lockPosition();
498
+ } else if (position.x == end) {
499
+ constants.KillAutoplay();
500
+ UpdateAllAutoplay();
501
+ } else {
502
+ UpdateAllAutoplay();
503
+ }
504
+ }, constants.autoPlayRate);
505
+ }
506
+ } else if ([].concat(singleMaidr.type).includes('box')) {
507
+ // variable initialization
508
+ constants.plotId = 'geom_boxplot.gTree.78.1';
509
+ window.plot = new BoxPlot();
510
+ if (constants.plotOrientation == 'vert') {
511
+ window.position = new Position(0, 6); // always 6
512
+ } else {
513
+ window.position = new Position(-1, plot.plotData.length);
514
+ }
515
+ let rect;
516
+ constants.hasRect = false;
517
+ if ('elements' in singleMaidr) {
518
+ rect = new BoxplotRect();
519
+ constants.hasRect = true;
520
+ }
521
+ let lastPlayed = '';
522
+
523
+ // control eventlisteners
524
+ constants.events.push([
525
+ constants.chart,
526
+ 'keydown',
527
+ function (e) {
528
+ let updateInfoThisRound = false; // we only update info and play tones on certain keys
529
+ let isAtEnd = false;
530
+
531
+ // right arrow
532
+ if (e.key == 'ArrowRight') {
533
+ if (constants.isMac ? e.metaKey : e.ctrlKey) {
534
+ if (e.shiftKey) {
535
+ if (constants.plotOrientation == 'vert') {
536
+ Autoplay('right', position.x, plot.plotData.length - 1);
537
+ } else {
538
+ Autoplay('right', position.x, plot.sections.length - 1);
539
+ }
540
+ } else {
541
+ isAtEnd = lockPosition();
542
+ if (constants.plotOrientation == 'vert') {
543
+ position.x = plot.plotData.length - 1;
544
+ } else {
545
+ position.x = plot.sections.length - 1;
546
+ }
547
+ updateInfoThisRound = true;
548
+ isAtEnd = lockPosition();
549
+ }
550
+ } else if (constants.plotOrientation == 'vert') {
551
+ if (
552
+ e.altKey &&
553
+ e.shiftKey &&
554
+ plot.sections.length - 1 != position.x
555
+ ) {
556
+ lastY = position.y;
557
+ Autoplay('reverse-right', plot.plotData.length - 1, position.x);
558
+ } else {
559
+ if (position.x == -1 && position.y == plot.sections.length) {
560
+ position.y -= 1;
561
+ }
562
+ position.x += 1;
563
+ updateInfoThisRound = true;
564
+ isAtEnd = lockPosition();
565
+ }
566
+ } else {
567
+ if (
568
+ e.altKey &&
569
+ e.shiftKey &&
570
+ plot.sections.length - 1 != position.x
571
+ ) {
572
+ constants.lastx = position.x;
573
+ Autoplay('reverse-right', plot.sections.length - 1, position.x);
574
+ } else {
575
+ if (position.x == -1 && position.y == plot.plotData.length) {
576
+ position.y -= 1;
577
+ }
578
+ position.x += 1;
579
+ updateInfoThisRound = true;
580
+ isAtEnd = lockPosition();
581
+ }
582
+ }
583
+ constants.navigation = 1;
584
+ }
585
+ // left arrow
586
+ if (e.key == 'ArrowLeft') {
587
+ if (constants.isMac ? e.metaKey : e.ctrlKey) {
588
+ if (e.shiftKey) {
589
+ Autoplay('left', position.x, -1);
590
+ } else {
591
+ position.x = 0;
592
+ updateInfoThisRound = true;
593
+ isAtEnd = lockPosition();
594
+ }
595
+ } else if (e.altKey && e.shiftKey && position.x > 0) {
596
+ if (constants.plotOrientation == 'vert') {
597
+ lastY = position.y;
598
+ } else {
599
+ constants.lastx = position.x;
600
+ }
601
+ Autoplay('reverse-left', 0, position.x);
602
+ } else {
603
+ position.x += -1;
604
+ updateInfoThisRound = true;
605
+ isAtEnd = lockPosition();
606
+ }
607
+ constants.navigation = 1;
608
+ }
609
+ // up arrow
610
+ if (e.key == 'ArrowUp') {
611
+ let oldY = position.y;
612
+ if (constants.isMac ? e.metaKey : e.ctrlKey) {
613
+ if (e.shiftKey) {
614
+ if (constants.plotOrientation == 'vert') {
615
+ Autoplay('up', position.y, plot.sections.length);
616
+ } else {
617
+ Autoplay('up', position.y, plot.plotData.length);
618
+ }
619
+ } else {
620
+ if (constants.plotOrientation == 'vert') {
621
+ position.y = plot.sections.length - 1;
622
+ } else {
623
+ position.y = plot.plotData.length - 1;
624
+ }
625
+ updateInfoThisRound = true;
626
+ isAtEnd = lockPosition();
627
+ }
628
+ } else if (constants.plotOrientation == 'vert') {
629
+ if (
630
+ e.altKey &&
631
+ e.shiftKey &&
632
+ position.y != plot.sections.length - 1
633
+ ) {
634
+ lastY = position.y;
635
+ Autoplay('reverse-up', plot.sections.length - 1, position.y);
636
+ } else {
637
+ position.y += 1;
638
+ updateInfoThisRound = true;
639
+ isAtEnd = lockPosition();
640
+ }
641
+ } else {
642
+ if (
643
+ e.altKey &&
644
+ e.shiftKey &&
645
+ position.y != plot.sections.length - 1
646
+ ) {
647
+ constants.lastx = position.x;
648
+ Autoplay('reverse-up', plot.plotData.length - 1, position.y);
649
+ } else {
650
+ position.y += 1;
651
+ updateInfoThisRound = true;
652
+ isAtEnd = lockPosition();
653
+ }
654
+ }
655
+ constants.navigation = 0;
656
+ }
657
+ // down arrow
658
+ if (e.key == 'ArrowDown') {
659
+ let oldY = position.y;
660
+ if (constants.isMac ? e.metaKey : e.ctrlKey) {
661
+ if (e.shiftKey) {
662
+ Autoplay('down', position.y, -1);
663
+ } else {
664
+ position.y = 0;
665
+ updateInfoThisRound = true;
666
+ isAtEnd = lockPosition();
667
+ }
668
+ } else if (e.altKey && e.shiftKey && position.y != 0) {
669
+ if (constants.plotOrientation == 'vert') {
670
+ lastY = position.y;
671
+ } else {
672
+ constants.lastx = position.x;
673
+ }
674
+ Autoplay('reverse-down', 0, position.y);
675
+ } else {
676
+ if (constants.plotOrientation == 'vert') {
677
+ if (position.x == -1 && position.y == plot.sections.length) {
678
+ position.x += 1;
679
+ }
680
+ } else {
681
+ if (position.x == -1 && position.y == plot.plotData.length) {
682
+ position.x += 1;
683
+ }
684
+ }
685
+ position.y += -1;
686
+ updateInfoThisRound = true;
687
+ isAtEnd = lockPosition();
688
+ }
689
+ //position.x = GetRelativeBoxPosition(oldY, position.y);
690
+ constants.navigation = 0;
691
+ }
692
+
693
+ // update display / text / audio
694
+ if (updateInfoThisRound && !isAtEnd) {
695
+ UpdateAll();
696
+ }
697
+ if (isAtEnd) {
698
+ audio.playEnd();
699
+ }
700
+ },
701
+ ]);
702
+
703
+ constants.events.push([
704
+ constants.brailleInput,
705
+ 'keydown',
706
+ function (e) {
707
+ let updateInfoThisRound = false; // we only update info and play tones on certain keys
708
+ let setBrailleThisRound = false;
709
+ let isAtEnd = false;
710
+
711
+ if (e.key == 'ArrowRight') {
712
+ // right arrow
713
+ e.preventDefault();
714
+ if (constants.isMac ? e.metaKey : e.ctrlKey) {
715
+ if (e.shiftKey) {
716
+ if (constants.plotOrientation == 'vert') {
717
+ Autoplay('right', position.x, plot.plotData.length - 1);
718
+ } else {
719
+ Autoplay('right', position.x, plot.sections.length);
720
+ }
721
+ } else {
722
+ if (constants.plotOrientation == 'vert') {
723
+ position.x = plot.plotData.length - 1;
724
+ } else {
725
+ position.x = plot.sections.length - 1;
726
+ }
727
+ updateInfoThisRound = true;
728
+ isAtEnd = lockPosition();
729
+ }
730
+ } else if (constants.plotOrientation == 'vert') {
731
+ if (
732
+ e.altKey &&
733
+ e.shiftKey &&
734
+ plot.plotData.length - 1 != position.x
735
+ ) {
736
+ lastY = position.y;
737
+ Autoplay('reverse-right', plot.plotData.length - 1, position.x);
738
+ } else {
739
+ if (
740
+ position.x == -1 &&
741
+ position.y == plot.plotData[position.x].length
742
+ ) {
743
+ position.y -= 1;
744
+ }
745
+ position.x += 1;
746
+ updateInfoThisRound = true;
747
+ isAtEnd = lockPosition();
748
+ }
749
+ } else {
750
+ if (
751
+ e.altKey &&
752
+ e.shiftKey &&
753
+ plot.sections.length - 1 != position.x
754
+ ) {
755
+ constants.lastx = position.x;
756
+ Autoplay('reverse-right', plot.sections.length - 1, position.x);
757
+ } else {
758
+ if (position.x == -1 && position.y == plot.plotData.length) {
759
+ position.y -= 1;
760
+ }
761
+ position.x += 1;
762
+ updateInfoThisRound = true;
763
+ isAtEnd = lockPosition();
764
+ }
765
+ }
766
+ setBrailleThisRound = true;
767
+ constants.navigation = 1;
768
+ } else if (e.key == 'ArrowLeft') {
769
+ // left arrow
770
+ e.preventDefault();
771
+ if (constants.isMac ? e.metaKey : e.ctrlKey) {
772
+ if (e.shiftKey) {
773
+ Autoplay('left', position.x, -1);
774
+ } else {
775
+ position.x = 0;
776
+ updateInfoThisRound = true;
777
+ isAtEnd = lockPosition();
778
+ }
779
+ } else if (e.altKey && e.shiftKey && position.x > 0) {
780
+ if (constants.plotOrientation == 'vert') {
781
+ lastY = position.y;
782
+ } else {
783
+ constants.lastx = position.x;
784
+ }
785
+ Autoplay('reverse-left', 0, position.x);
786
+ } else {
787
+ position.x += -1;
788
+ updateInfoThisRound = true;
789
+ isAtEnd = lockPosition();
790
+ }
791
+ setBrailleThisRound = true;
792
+ constants.navigation = 1;
793
+ } else if (e.key == 'ArrowUp') {
794
+ // up arrow
795
+ let oldY = position.y;
796
+ if (constants.isMac ? e.metaKey : e.ctrlKey) {
797
+ if (e.shiftKey) {
798
+ if (constants.plotOrientation == 'vert') {
799
+ if (position.x < 0) position.x = 0;
800
+ Autoplay('up', position.y, plot.sections.length);
801
+ } else {
802
+ Autoplay('up', position.y, plot.plotData.length);
803
+ }
804
+ } else if (constants.plotOrientation == 'vert') {
805
+ position.y = plot.sections.length - 1;
806
+ updateInfoThisRound = true;
807
+ } else {
808
+ position.y = plot.plotData.length - 1;
809
+ updateInfoThisRound = true;
810
+ }
811
+ } else if (constants.plotOrientation == 'vert') {
812
+ if (
813
+ e.altKey &&
814
+ e.shiftKey &&
815
+ position.y != plot.sections.length - 1
816
+ ) {
817
+ lasY = position.y;
818
+ Autoplay('reverse-up', plot.sections.length - 1, position.y);
819
+ } else {
820
+ position.y += 1;
821
+ updateInfoThisRound = true;
822
+ isAtEnd = lockPosition();
823
+ }
824
+ } else {
825
+ if (
826
+ e.altKey &&
827
+ e.shiftKey &&
828
+ position.y != plot.plotData.length - 1
829
+ ) {
830
+ constants.lastx = position.x;
831
+ Autoplay('reverse-up', plot.plotData.length - 1, position.y);
832
+ } else {
833
+ position.y += 1;
834
+ updateInfoThisRound = true;
835
+ isAtEnd = lockPosition();
836
+ }
837
+ }
838
+ if (constants.plotOrientation == 'vert') {
839
+ } else {
840
+ setBrailleThisRound = true;
841
+ }
842
+ constants.navigation = 0;
843
+ } else if (e.key == 'ArrowDown') {
844
+ // down arrow
845
+ let oldY = position.y;
846
+ if (constants.isMac ? e.metaKey : e.ctrlKey) {
847
+ if (e.shiftKey) {
848
+ Autoplay('down', position.y, -1);
849
+ } else {
850
+ position.y = 0;
851
+ updateInfoThisRound = true;
852
+ isAtEnd = lockPosition();
853
+ }
854
+ } else if (e.altKey && e.shiftKey && position.y != 0) {
855
+ if (constants.plotOrientation == 'vert') {
856
+ lastY = position.y;
857
+ } else {
858
+ constants.lastx = position.x;
859
+ }
860
+ Autoplay('reverse-down', 0, position.y);
861
+ } else {
862
+ if (constants.plotOrientation == 'vert') {
863
+ if (position.x == -1 && position.y == plot.sections.length) {
864
+ position.x += 1;
865
+ }
866
+ } else {
867
+ if (position.x == -1 && position.y == plot.plotData.length) {
868
+ position.x += 1;
869
+ }
870
+ }
871
+ position.y += -1;
872
+ updateInfoThisRound = true;
873
+ isAtEnd = lockPosition();
874
+ }
875
+ constants.navigation = 0;
876
+ if (constants.plotOrientation == 'vert') {
877
+ } else {
878
+ setBrailleThisRound = true;
879
+ }
880
+ constants.navigation = 0;
881
+ } else if (e.key == 'Tab') {
882
+ // do nothing, we handle this in global events
883
+ } else {
884
+ e.preventDefault();
885
+ // todo: allow some controls through like page refresh
886
+ }
887
+
888
+ // update audio. todo: add a setting for this later
889
+ if (updateInfoThisRound && !isAtEnd) {
890
+ if (setBrailleThisRound) display.SetBraille(plot);
891
+ setTimeout(UpdateAllBraille, 50); // we delay this by just a moment as otherwise the cursor position doesn't get set
892
+ }
893
+ if (isAtEnd) {
894
+ audio.playEnd();
895
+ }
896
+ },
897
+ ]);
898
+
899
+ let controlElements = [constants.chart, constants.brailleInput];
900
+ let lastx = 0;
901
+ for (let i = 0; i < controlElements.length; i++) {
902
+ constants.events.push([
903
+ controlElements[i],
904
+ 'keydown',
905
+ function (e) {
906
+ // period: speed up
907
+ if (e.key == '.') {
908
+ constants.SpeedUp();
909
+ PlayDuringSpeedChange();
910
+ display.announceText('Speed up');
911
+ }
912
+
913
+ // comma: speed down
914
+ if (e.key == ',') {
915
+ constants.SpeedDown();
916
+ PlayDuringSpeedChange();
917
+ display.announceText('Speed down');
918
+ }
919
+
920
+ // /: reset speed
921
+ if (e.key == '/') {
922
+ constants.SpeedReset();
923
+ PlayDuringSpeedChange();
924
+ display.announceText('Speed reset');
925
+ }
926
+ },
927
+ ]);
928
+ }
929
+ function PlayDuringSpeedChange() {
930
+ if (constants.autoplayId != null) {
931
+ constants.KillAutoplay();
932
+ if (lastPlayed == 'reverse-left') {
933
+ if (constants.plotOrientation == 'vert') {
934
+ Autoplay('right', position.y, lastY);
935
+ } else {
936
+ Autoplay('right', position.x, lastx);
937
+ }
938
+ } else if (lastPlayed == 'reverse-right') {
939
+ if (constants.plotOrientation == 'vert') {
940
+ Autoplay('left', position.y, lastY);
941
+ } else {
942
+ Autoplay('left', position.x, lastx);
943
+ }
944
+ } else if (lastPlayed == 'reverse-up') {
945
+ if (constants.plotOrientation == 'vert') {
946
+ Autoplay('down', position.y, lastY);
947
+ } else {
948
+ Autoplay('down', position.x, lastx);
949
+ }
950
+ } else if (lastPlayed == 'reverse-down') {
951
+ if (constants.plotOrientation == 'vert') {
952
+ Autoplay('up', position.y, lastY);
953
+ } else {
954
+ Autoplay('up', position.x, lastx);
955
+ }
956
+ } else {
957
+ if (constants.plotOrientation == 'vert') {
958
+ Autoplay(lastPlayed, position.y, lastY);
959
+ } else {
960
+ Autoplay(lastPlayed, position.x, lastx);
961
+ }
962
+ }
963
+ }
964
+ }
965
+
966
+ function UpdateAll() {
967
+ if (constants.showDisplay) {
968
+ display.displayValues();
969
+ }
970
+ if (constants.showRect && constants.hasRect) {
971
+ rect.UpdateRect();
972
+ }
973
+ if (constants.sonifMode != 'off') {
974
+ plot.PlayTones();
975
+ }
976
+ }
977
+ function UpdateAllAutoplay() {
978
+ if (constants.showDisplayInAutoplay) {
979
+ display.displayValues();
980
+ }
981
+ if (constants.showRect && constants.hasRect) {
982
+ rect.UpdateRect();
983
+ }
984
+ if (constants.sonifMode != 'off') {
985
+ plot.PlayTones();
986
+ }
987
+ if (constants.brailleMode != 'off') {
988
+ display.UpdateBraillePos();
989
+ }
990
+ }
991
+ function UpdateAllBraille() {
992
+ if (constants.showDisplayInBraille) {
993
+ display.displayValues();
994
+ }
995
+ if (constants.showRect && constants.hasRect) {
996
+ rect.UpdateRect();
997
+ }
998
+ if (constants.sonifMode != 'off') {
999
+ plot.PlayTones();
1000
+ }
1001
+ display.UpdateBraillePos();
1002
+ }
1003
+ function lockPosition() {
1004
+ // lock to min / max postions
1005
+ let didLockHappen = false;
1006
+ if (position.y < 0) {
1007
+ position.y = 0;
1008
+ didLockHappen = true;
1009
+ }
1010
+ if (position.x < 0) {
1011
+ position.x = 0;
1012
+ didLockHappen = true;
1013
+ }
1014
+ if (constants.plotOrientation == 'vert') {
1015
+ if (position.x > plot.plotData.length - 1) {
1016
+ position.x = plot.plotData.length - 1;
1017
+ didLockHappen = true;
1018
+ }
1019
+ if (position.y > plot.sections.length - 1) {
1020
+ position.y = plot.sections.length - 1;
1021
+ didLockHappen = true;
1022
+ }
1023
+ } else {
1024
+ if (position.y > plot.plotData.length - 1) {
1025
+ position.y = plot.plotData.length - 1;
1026
+ didLockHappen = true;
1027
+ }
1028
+ if (position.x > plot.sections.length - 1) {
1029
+ position.x = plot.sections.length - 1;
1030
+ didLockHappen = true;
1031
+ }
1032
+ }
1033
+
1034
+ return didLockHappen;
1035
+ }
1036
+
1037
+ function Autoplay(dir, start, end) {
1038
+ lastPlayed = dir;
1039
+ let step = 1; // default right / up / reverse-left / reverse-down
1040
+ if (
1041
+ dir == 'left' ||
1042
+ dir == 'down' ||
1043
+ dir == 'reverse-right' ||
1044
+ dir == 'reverse-up'
1045
+ ) {
1046
+ step = -1;
1047
+ }
1048
+
1049
+ // clear old autoplay if exists
1050
+ if (constants.autoplayId != null) {
1051
+ constants.KillAutoplay();
1052
+ }
1053
+
1054
+ if (dir == 'reverse-left' || dir == 'reverse-right') {
1055
+ position.x = start;
1056
+ } else if (dir == 'reverse-up' || dir == 'reverse-down') {
1057
+ position.y = start;
1058
+ }
1059
+
1060
+ if (constants.debugLevel > 0) {
1061
+ console.log('starting autoplay', dir, start, end);
1062
+ }
1063
+
1064
+ UpdateAllAutoplay(); // play current tone before we move
1065
+ constants.autoplayId = setInterval(function () {
1066
+ let doneNext = false;
1067
+ if (dir == 'left' || dir == 'right' || dir == 'up' || dir == 'down') {
1068
+ if (
1069
+ (position.x < 1 && dir == 'left') ||
1070
+ (constants.plotOrientation == 'vert' &&
1071
+ dir == 'up' &&
1072
+ position.y > plot.sections.length - 2) ||
1073
+ (constants.plotOrientation == 'horz' &&
1074
+ dir == 'up' &&
1075
+ position.y > plot.plotData.length - 2) ||
1076
+ (constants.plotOrientation == 'horz' &&
1077
+ dir == 'right' &&
1078
+ position.x > plot.sections.length - 2) ||
1079
+ (constants.plotOrientation == 'vert' &&
1080
+ dir == 'right' &&
1081
+ position.x > plot.plotData.length - 2) ||
1082
+ (constants.plotOrientation == 'horz' &&
1083
+ dir == 'down' &&
1084
+ position.y < 1) ||
1085
+ (constants.plotOrientation == 'vert' &&
1086
+ dir == 'down' &&
1087
+ position.y < 1)
1088
+ ) {
1089
+ doneNext = true;
1090
+ }
1091
+ } else {
1092
+ if (
1093
+ (dir == 'reverse-left' && position.x >= end) ||
1094
+ (dir == 'reverse-right' && position.x <= end) ||
1095
+ (dir == 'reverse-up' && position.y <= end) ||
1096
+ (dir == 'reverse-down' && position.y >= end)
1097
+ ) {
1098
+ doneNext = true;
1099
+ }
1100
+ }
1101
+
1102
+ if (doneNext) {
1103
+ constants.KillAutoplay();
1104
+ } else {
1105
+ if (
1106
+ dir == 'left' ||
1107
+ dir == 'right' ||
1108
+ dir == 'reverse-left' ||
1109
+ dir == 'reverse-right'
1110
+ ) {
1111
+ position.x += step;
1112
+ } else {
1113
+ position.y += step;
1114
+ }
1115
+ UpdateAllAutoplay();
1116
+ }
1117
+ if (constants.debugLevel > 5) {
1118
+ console.log('autoplay pos', position);
1119
+ }
1120
+ }, constants.autoPlayRate);
1121
+ }
1122
+ } else if ([].concat(singleMaidr.type).includes('heat')) {
1123
+ // variable initialization
1124
+ constants.plotId = 'geom_rect.rect.2.1';
1125
+ window.position = new Position(-1, -1);
1126
+ window.plot = new HeatMap();
1127
+ let rect = new HeatMapRect();
1128
+ let lastPlayed = '';
1129
+ constants.lastx = 0;
1130
+
1131
+ // control eventlisteners
1132
+ constants.events.push([
1133
+ constants.chart,
1134
+ 'keydown',
1135
+ function (e) {
1136
+ let updateInfoThisRound = false;
1137
+ let isAtEnd = false;
1138
+
1139
+ // right arrow 39
1140
+ if (e.key == 'ArrowRight') {
1141
+ if (constants.isMac ? e.metaKey : e.ctrlKey) {
1142
+ if (e.shiftKey) {
1143
+ position.x -= 1;
1144
+ Autoplay('right', position.x, plot.num_cols);
1145
+ } else {
1146
+ position.x = plot.num_cols - 1;
1147
+ updateInfoThisRound = true;
1148
+ }
1149
+ } else if (
1150
+ e.altKey &&
1151
+ e.shiftKey &&
1152
+ position.x != plot.num_cols - 1
1153
+ ) {
1154
+ constants.lastx = position.x;
1155
+ Autoplay('reverse-right', plot.num_cols, position.x);
1156
+ } else {
1157
+ if (position.x == -1 && position.y == -1) {
1158
+ position.y += 1;
1159
+ }
1160
+ position.x += 1;
1161
+ updateInfoThisRound = true;
1162
+ isAtEnd = lockPosition();
1163
+ }
1164
+ constants.navigation = 1;
1165
+ }
1166
+
1167
+ // left arrow 37
1168
+ if (e.key == 'ArrowLeft') {
1169
+ if (constants.isMac ? e.metaKey : e.ctrlKey) {
1170
+ if (e.shiftKey) {
1171
+ position.x += 1;
1172
+ Autoplay('left', position.x, -1);
1173
+ } else {
1174
+ position.x = 0;
1175
+ updateInfoThisRound = true;
1176
+ }
1177
+ } else if (e.altKey && e.shiftKey && position.x != 0) {
1178
+ constants.lastx = position.x;
1179
+ Autoplay('reverse-left', -1, position.x);
1180
+ } else {
1181
+ position.x -= 1;
1182
+ updateInfoThisRound = true;
1183
+ isAtEnd = lockPosition();
1184
+ }
1185
+ constants.navigation = 1;
1186
+ }
1187
+
1188
+ // up arrow 38
1189
+ if (e.key == 'ArrowUp') {
1190
+ if (constants.isMac ? e.metaKey : e.ctrlKey) {
1191
+ if (e.shiftKey) {
1192
+ position.y += 1;
1193
+ Autoplay('up', position.y, -1);
1194
+ } else {
1195
+ position.y = 0;
1196
+ updateInfoThisRound = true;
1197
+ }
1198
+ } else if (e.altKey && e.shiftKey && position.y != 0) {
1199
+ constants.lastx = position.x;
1200
+ Autoplay('reverse-up', -1, position.y);
1201
+ } else {
1202
+ position.y -= 1;
1203
+ updateInfoThisRound = true;
1204
+ isAtEnd = lockPosition();
1205
+ }
1206
+ constants.navigation = 0;
1207
+ }
1208
+
1209
+ // down arrow 40
1210
+ if (e.key == 'ArrowDown') {
1211
+ if (constants.isMac ? e.metaKey : e.ctrlKey) {
1212
+ if (e.shiftKey) {
1213
+ position.y -= 1;
1214
+ Autoplay('down', position.y, plot.num_rows);
1215
+ } else {
1216
+ position.y = plot.num_rows - 1;
1217
+ updateInfoThisRound = true;
1218
+ }
1219
+ } else if (
1220
+ e.altKey &&
1221
+ e.shiftKey &&
1222
+ position.y != plot.num_rows - 1
1223
+ ) {
1224
+ constants.lastx = position.x;
1225
+ Autoplay('reverse-down', plot.num_rows, position.y);
1226
+ } else {
1227
+ if (position.x == -1 && position.y == -1) {
1228
+ position.x += 1;
1229
+ }
1230
+ position.y += 1;
1231
+ updateInfoThisRound = true;
1232
+ isAtEnd = lockPosition();
1233
+ }
1234
+ constants.navigation = 0;
1235
+ }
1236
+
1237
+ // update text, display, and audio
1238
+ if (updateInfoThisRound && !isAtEnd) {
1239
+ UpdateAll();
1240
+ }
1241
+ if (isAtEnd) {
1242
+ audio.playEnd();
1243
+ }
1244
+ },
1245
+ ]);
1246
+
1247
+ let controlElements = [constants.chart, constants.brailleInput];
1248
+ let lastx = 0;
1249
+ for (let i = 0; i < controlElements.length; i++) {
1250
+ constants.events.push([
1251
+ controlElements[i],
1252
+ 'keydown',
1253
+ function (e) {
1254
+ // period: speed up
1255
+ if (e.key == '.') {
1256
+ constants.SpeedUp();
1257
+ PlayDuringSpeedChange();
1258
+ display.announceText('Speed up');
1259
+ }
1260
+
1261
+ // comma: speed down
1262
+ if (e.key == ',') {
1263
+ constants.SpeedDown();
1264
+ PlayDuringSpeedChange();
1265
+ display.announceText('Speed down');
1266
+ }
1267
+
1268
+ // /: reset speed
1269
+ if (e.key == '/') {
1270
+ constants.SpeedReset();
1271
+ PlayDuringSpeedChange();
1272
+ display.announceText('Speed reset');
1273
+ }
1274
+ },
1275
+ ]);
1276
+ }
1277
+ function PlayDuringSpeedChange() {
1278
+ if (constants.autoplayId != null) {
1279
+ constants.KillAutoplay();
1280
+ if (lastPlayed == 'reverse-left') {
1281
+ Autoplay('right', position.x, lastx);
1282
+ } else if (lastPlayed == 'reverse-right') {
1283
+ Autoplay('left', position.x, lastx);
1284
+ } else if (lastPlayed == 'reverse-up') {
1285
+ Autoplay('down', position.x, lastx);
1286
+ } else if (lastPlayed == 'reverse-down') {
1287
+ Autoplay('up', position.x, lastx);
1288
+ } else {
1289
+ Autoplay(lastPlayed, position.x, lastx);
1290
+ }
1291
+ }
1292
+ }
1293
+
1294
+ constants.events.push([
1295
+ constants.brailleInput,
1296
+ 'keydown',
1297
+ function (e) {
1298
+ let updateInfoThisRound = false;
1299
+ let isAtEnd = false;
1300
+
1301
+ if (e.key == 'ArrowRight') {
1302
+ // right arrow
1303
+ if (
1304
+ e.target.selectionStart > e.target.value.length - 3 ||
1305
+ e.target.value.substring(
1306
+ e.target.selectionStart + 1,
1307
+ e.target.selectionStart + 2
1308
+ ) == '⠳'
1309
+ ) {
1310
+ // already at the end, do nothing
1311
+ e.preventDefault();
1312
+ } else {
1313
+ if (constants.isMac ? e.metaKey : e.ctrlKey) {
1314
+ if (position.x == -1 && position.y == -1) {
1315
+ position.x += 1;
1316
+ position.y += 1;
1317
+ }
1318
+ if (e.shiftKey) {
1319
+ position.x -= 1;
1320
+ Autoplay('right', position.x, plot.num_cols);
1321
+ } else {
1322
+ position.x = plot.num_cols - 1;
1323
+ updateInfoThisRound = true;
1324
+ }
1325
+ } else if (
1326
+ e.altKey &&
1327
+ e.shiftKey &&
1328
+ position.x != plot.num_cols - 1
1329
+ ) {
1330
+ constants.lastx = position.x;
1331
+ Autoplay('reverse-right', plot.num_cols, position.x);
1332
+ } else {
1333
+ if (position.x == -1 && position.y == -1) {
1334
+ position.y += 1;
1335
+ }
1336
+ position.x += 1;
1337
+ updateInfoThisRound = true;
1338
+ isAtEnd = lockPosition();
1339
+ }
1340
+
1341
+ // we need pos to be y*(num_cols+1), (and num_cols+1 because there's a spacer character)
1342
+ let pos = position.y * (plot.num_cols + 1) + position.x;
1343
+ e.target.setSelectionRange(pos, pos);
1344
+ e.preventDefault();
1345
+
1346
+ constants.navigation = 1;
1347
+ }
1348
+ } else if (e.key == 'ArrowLeft') {
1349
+ // left
1350
+ if (
1351
+ e.target.selectionStart == 0 ||
1352
+ e.target.value.substring(
1353
+ e.target.selectionStart - 1,
1354
+ e.target.selectionStart
1355
+ ) == '⠳'
1356
+ ) {
1357
+ e.preventDefault();
1358
+ } else {
1359
+ if (constants.isMac ? e.metaKey : e.ctrlKey) {
1360
+ if (e.shiftKey) {
1361
+ position.x += 1;
1362
+ Autoplay('left', position.x, -1);
1363
+ } else {
1364
+ position.x = 0;
1365
+ updateInfoThisRound = true;
1366
+ }
1367
+ } else if (e.altKey && e.shiftKey && position.x != 0) {
1368
+ constants.lastx = position.x;
1369
+ Autoplay('reverse-left', -1, position.x);
1370
+ } else {
1371
+ position.x += -1;
1372
+ updateInfoThisRound = true;
1373
+ isAtEnd = lockPosition();
1374
+ }
1375
+
1376
+ let pos = position.y * (plot.num_cols + 1) + position.x;
1377
+ e.target.setSelectionRange(pos, pos);
1378
+ e.preventDefault();
1379
+
1380
+ constants.navigation = 1;
1381
+ }
1382
+ } else if (e.key == 'ArrowDown') {
1383
+ // down
1384
+ if (position.y + 1 == plot.num_rows) {
1385
+ e.preventDefault();
1386
+ } else {
1387
+ if (constants.isMac ? e.metaKey : e.ctrlKey) {
1388
+ if (position.x == -1 && position.y == -1) {
1389
+ position.x += 1;
1390
+ position.y += 1;
1391
+ }
1392
+ if (e.shiftKey) {
1393
+ position.y -= 1;
1394
+ Autoplay('down', position.y, plot.num_rows);
1395
+ } else {
1396
+ position.y = plot.num_rows - 1;
1397
+ updateInfoThisRound = true;
1398
+ }
1399
+ } else if (
1400
+ e.altKey &&
1401
+ e.shiftKey &&
1402
+ position.y != plot.num_rows - 1
1403
+ ) {
1404
+ constants.lastx = position.x;
1405
+ Autoplay('reverse-down', plot.num_rows, position.y);
1406
+ } else {
1407
+ if (position.x == -1 && position.y == -1) {
1408
+ position.x += 1;
1409
+ }
1410
+ position.y += 1;
1411
+ updateInfoThisRound = true;
1412
+ isAtEnd = lockPosition();
1413
+ }
1414
+
1415
+ let pos = position.y * (plot.num_cols + 1) + position.x;
1416
+ e.target.setSelectionRange(pos, pos);
1417
+ e.preventDefault();
1418
+
1419
+ constants.navigation = 0;
1420
+ }
1421
+ } else if (e.key == 'ArrowUp') {
1422
+ // up
1423
+ if (e.target.selectionStart - plot.num_cols - 1 < 0) {
1424
+ e.preventDefault();
1425
+ } else {
1426
+ if (constants.isMac ? e.metaKey : e.ctrlKey) {
1427
+ if (e.shiftKey) {
1428
+ position.y += 1;
1429
+ Autoplay('up', position.y, -1);
1430
+ } else {
1431
+ position.y = 0;
1432
+ updateInfoThisRound = true;
1433
+ }
1434
+ } else if (e.altKey && e.shiftKey && position.y != 0) {
1435
+ constants.lastx = position.x;
1436
+ Autoplay('reverse-up', -1, position.y);
1437
+ } else {
1438
+ position.y += -1;
1439
+ updateInfoThisRound = true;
1440
+ isAtEnd = lockPosition();
1441
+ }
1442
+
1443
+ let pos = position.y * (plot.num_cols + 1) + position.x;
1444
+ e.target.setSelectionRange(pos, pos);
1445
+ e.preventDefault();
1446
+
1447
+ constants.navigation = 0;
1448
+ }
1449
+ } else if (e.key == 'Tab') {
1450
+ // do nothing, we handle this in global events
1451
+ } else {
1452
+ e.preventDefault();
1453
+ }
1454
+
1455
+ if (updateInfoThisRound && !isAtEnd) {
1456
+ UpdateAllBraille();
1457
+ }
1458
+ if (isAtEnd) {
1459
+ audio.playEnd();
1460
+ }
1461
+ },
1462
+ ]);
1463
+
1464
+ function sleep(time) {
1465
+ return new Promise((resolve) => setTimeout(resolve, time));
1466
+ }
1467
+
1468
+ // helper functions
1469
+ function lockPosition() {
1470
+ // lock to min / max postions
1471
+ let didLockHappen = false;
1472
+
1473
+ if (position.x < 0) {
1474
+ position.x = 0;
1475
+ didLockHappen = true;
1476
+ }
1477
+ if (position.x > plot.num_cols - 1) {
1478
+ position.x = plot.num_cols - 1;
1479
+ didLockHappen = true;
1480
+ }
1481
+ if (position.y < 0) {
1482
+ position.y = 0;
1483
+ didLockHappen = true;
1484
+ }
1485
+ if (position.y > plot.num_rows - 1) {
1486
+ position.y = plot.num_rows - 1;
1487
+ didLockHappen = true;
1488
+ }
1489
+
1490
+ return didLockHappen;
1491
+ }
1492
+
1493
+ function UpdateAll() {
1494
+ if (constants.showDisplay) {
1495
+ display.displayValues();
1496
+ }
1497
+ if (constants.showRect && constants.hasRect) {
1498
+ rect.UpdateRectDisplay();
1499
+ }
1500
+ if (constants.sonifMode != 'off') {
1501
+ plot.PlayTones();
1502
+ }
1503
+ }
1504
+ function UpdateAllAutoplay() {
1505
+ if (constants.showDisplayInAutoplay) {
1506
+ display.displayValues();
1507
+ }
1508
+ if (constants.showRect && constants.hasRect) {
1509
+ rect.UpdateRectDisplay();
1510
+ }
1511
+ if (constants.sonifMode != 'off') {
1512
+ plot.PlayTones();
1513
+ }
1514
+ if (constants.brailleMode != 'off') {
1515
+ display.UpdateBraillePos();
1516
+ }
1517
+ }
1518
+ function UpdateAllBraille() {
1519
+ if (constants.showDisplayInBraille) {
1520
+ display.displayValues();
1521
+ }
1522
+ if (constants.showRect && constants.hasRect) {
1523
+ rect.UpdateRectDisplay();
1524
+ }
1525
+ if (constants.sonifMode != 'off') {
1526
+ plot.PlayTones();
1527
+ }
1528
+ display.UpdateBraillePos();
1529
+ }
1530
+
1531
+ function Autoplay(dir, start, end) {
1532
+ lastPlayed = dir;
1533
+ let step = 1; // default right, down, reverse-left, and reverse-up
1534
+ if (
1535
+ dir == 'left' ||
1536
+ dir == 'up' ||
1537
+ dir == 'reverse-right' ||
1538
+ dir == 'reverse-down'
1539
+ ) {
1540
+ step = -1;
1541
+ }
1542
+
1543
+ // clear old autoplay if exists
1544
+ if (constants.autoplayId != null) {
1545
+ constants.KillAutoplay();
1546
+ }
1547
+
1548
+ if (dir == 'reverse-left' || dir == 'reverse-right') {
1549
+ position.x = start;
1550
+ } else if (dir == 'reverse-up' || dir == 'reverse-down') {
1551
+ position.y = start;
1552
+ }
1553
+
1554
+ constants.autoplayId = setInterval(function () {
1555
+ if (
1556
+ dir == 'left' ||
1557
+ dir == 'right' ||
1558
+ dir == 'reverse-left' ||
1559
+ dir == 'reverse-right'
1560
+ ) {
1561
+ position.x += step;
1562
+ if (position.x < 0 || plot.num_cols - 1 < position.x) {
1563
+ constants.KillAutoplay();
1564
+ lockPosition();
1565
+ } else if (position.x == end) {
1566
+ constants.KillAutoplay();
1567
+ UpdateAllAutoplay();
1568
+ } else {
1569
+ UpdateAllAutoplay();
1570
+ }
1571
+ } else {
1572
+ // up or down
1573
+ position.y += step;
1574
+ if (position.y < 0 || plot.num_rows - 1 < position.y) {
1575
+ constants.KillAutoplay();
1576
+ lockPosition();
1577
+ } else if (position.y == end) {
1578
+ constants.KillAutoplay();
1579
+ UpdateAllAutoplay();
1580
+ } else {
1581
+ UpdateAllAutoplay();
1582
+ }
1583
+ }
1584
+ }, constants.autoPlayRate);
1585
+ }
1586
+ } else if (
1587
+ [].concat(singleMaidr.type).includes('point') ||
1588
+ singleMaidr.type == 'point'
1589
+ ) {
1590
+ // variable initialization
1591
+ constants.plotId = 'geom_point.points.12.1';
1592
+ window.position = new Position(-1, -1);
1593
+ window.plot = new ScatterPlot();
1594
+ let layer0Point = new Layer0Point();
1595
+ let layer1Point = new Layer1Point();
1596
+
1597
+ let lastPlayed = ''; // for autoplay use
1598
+ constants.lastx = 0; // for scatter point layer autoplay use
1599
+ let lastx1 = 0; // for smooth layer autoplay use
1600
+
1601
+ window.positionL1 = new Position(lastx1, lastx1);
1602
+
1603
+ // control eventlisteners
1604
+ constants.events.push([
1605
+ [constants.chart, constants.brailleInput],
1606
+ 'keydown',
1607
+ function (e) {
1608
+ let updateInfoThisRound = false;
1609
+ let isAtEnd = false;
1610
+
1611
+ // left and right arrows are enabled only at point layer
1612
+ if (constants.chartType == 'point') {
1613
+ // right arrow 39
1614
+ if (e.key == 'ArrowRight') {
1615
+ if (constants.isMac ? e.metaKey : e.ctrlKey) {
1616
+ if (e.shiftKey) {
1617
+ position.x -= 1;
1618
+ Autoplay('right', position.x, plot.x.length);
1619
+ } else {
1620
+ position.x = plot.x.length - 1;
1621
+ updateInfoThisRound = true;
1622
+ isAtEnd = lockPosition();
1623
+ }
1624
+ } else if (
1625
+ e.altKey &&
1626
+ e.shiftKey &&
1627
+ position.x != plot.x.length - 1
1628
+ ) {
1629
+ constants.lastx = position.x;
1630
+ Autoplay('reverse-right', plot.x.length, position.x);
1631
+ } else {
1632
+ position.x += 1;
1633
+ updateInfoThisRound = true;
1634
+ isAtEnd = lockPosition();
1635
+ }
1636
+ }
1637
+
1638
+ // left arrow 37
1639
+ if (e.key == 'ArrowLeft') {
1640
+ if (constants.isMac ? e.metaKey : e.ctrlKey) {
1641
+ if (e.shiftKey) {
1642
+ position.x += 1;
1643
+ Autoplay('left', position.x, -1);
1644
+ } else {
1645
+ position.x = 0;
1646
+ updateInfoThisRound = true;
1647
+ isAtEnd = lockPosition();
1648
+ }
1649
+ } else if (e.altKey && e.shiftKey && position.x != 0) {
1650
+ constants.lastx = position.x;
1651
+ Autoplay('reverse-left', -1, position.x);
1652
+ } else {
1653
+ position.x -= 1;
1654
+ updateInfoThisRound = true;
1655
+ isAtEnd = lockPosition();
1656
+ }
1657
+ }
1658
+ } else if (constants.chartType == 'smooth') {
1659
+ if (!positionL1.x) {
1660
+ positionL1.x = lastx1;
1661
+ }
1662
+
1663
+ if (e.key == 'ArrowRight' && e.shiftKey) {
1664
+ if (
1665
+ (constants.isMac ? e.metaKey : e.ctrlKey) &&
1666
+ constants.sonifMode != 'off'
1667
+ ) {
1668
+ PlayLine('right');
1669
+ } else if (e.altKey && constants.sonifMode != 'off') {
1670
+ PlayLine('reverse-right');
1671
+ }
1672
+ }
1673
+
1674
+ if (e.key == 'ArrowLeft' && e.shiftKey) {
1675
+ if (
1676
+ (constants.isMac ? e.metaKey : e.ctrlKey) &&
1677
+ constants.sonifMode != 'off'
1678
+ ) {
1679
+ PlayLine('left');
1680
+ } else if (e.altKey && constants.sonifMode != 'off') {
1681
+ PlayLine('reverse-left');
1682
+ }
1683
+ }
1684
+ }
1685
+
1686
+ // update text, display, and audio
1687
+ if (
1688
+ updateInfoThisRound &&
1689
+ constants.chartType == 'point' &&
1690
+ !isAtEnd
1691
+ ) {
1692
+ UpdateAll();
1693
+ }
1694
+ if (isAtEnd) {
1695
+ audio.playEnd();
1696
+ }
1697
+ },
1698
+ ]);
1699
+
1700
+ let controlElements = [constants.chart, constants.brailleInput];
1701
+ let lastx = 0;
1702
+ for (let i = 0; i < controlElements.length; i++) {
1703
+ constants.events.push([
1704
+ controlElements[i],
1705
+ 'keydown',
1706
+ function (e) {
1707
+ // period: speed up
1708
+ if (e.key == '.') {
1709
+ constants.SpeedUp();
1710
+ PlayDuringSpeedChange();
1711
+ display.announceText('Speed up');
1712
+ }
1713
+
1714
+ // comma: speed down
1715
+ if (e.key == ',') {
1716
+ constants.SpeedDown();
1717
+ PlayDuringSpeedChange();
1718
+ display.announceText('Speed down');
1719
+ }
1720
+
1721
+ // /: reset speed
1722
+ if (e.key == '/') {
1723
+ constants.SpeedReset();
1724
+ PlayDuringSpeedChange();
1725
+ display.announceText('Speed reset');
1726
+ }
1727
+ },
1728
+ ]);
1729
+ }
1730
+ function PlayDuringSpeedChange() {
1731
+ if (constants.autoplayId != null) {
1732
+ constants.KillAutoplay();
1733
+ audio.KillSmooth();
1734
+ if (lastPlayed == 'reverse-left') {
1735
+ if (constants.chartType == 'point') {
1736
+ Autoplay('right', position.x, lastx);
1737
+ } else if (constants.chartType == 'smooth') {
1738
+ Autoplay('right', positionL1.x, lastx1);
1739
+ }
1740
+ } else if (lastPlayed == 'reverse-right') {
1741
+ if (constants.chartType == 'point') {
1742
+ Autoplay('left', position.x, lastx);
1743
+ } else if (constants.chartType == 'smooth') {
1744
+ Autoplay('left', positionL1.x, lastx1);
1745
+ }
1746
+ } else {
1747
+ if (constants.chartType == 'point') {
1748
+ Autoplay(lastPlayed, position.x, lastx);
1749
+ } else if (constants.chartType == 'smooth') {
1750
+ Autoplay(lastPlayed, positionL1.x, lastx1);
1751
+ }
1752
+ }
1753
+ }
1754
+ }
1755
+
1756
+ constants.events.push([
1757
+ constants.brailleInput,
1758
+ 'keydown',
1759
+ function (e) {
1760
+ let updateInfoThisRound = false;
1761
+ let isAtEnd = false;
1762
+
1763
+ // @TODO
1764
+ // only smooth layer can access to braille display
1765
+ if (constants.chartType == 'smooth') {
1766
+ lockPosition();
1767
+ if (e.key == 'ArrowRight') {
1768
+ // right arrow
1769
+ e.preventDefault();
1770
+ constants.brailleInput.setSelectionRange(
1771
+ positionL1.x,
1772
+ positionL1.x
1773
+ );
1774
+ if (e.target.selectionStart > e.target.value.length - 2) {
1775
+ e.preventDefault();
1776
+ } else if (constants.isMac ? e.metaKey : e.ctrlKey) {
1777
+ if (e.shiftKey) {
1778
+ positionL1.x -= 1;
1779
+ Autoplay('right', positionL1.x, plot.curvePoints.length);
1780
+ } else {
1781
+ positionL1.x = plot.curvePoints.length - 1;
1782
+ updateInfoThisRound = true;
1783
+ isAtEnd = lockPosition();
1784
+ }
1785
+ } else if (
1786
+ e.altKey &&
1787
+ e.shiftKey &&
1788
+ positionL1.x != plot.curvePoints.length - 1
1789
+ ) {
1790
+ lastx1 = positionL1.x;
1791
+ Autoplay(
1792
+ 'reverse-right',
1793
+ plot.curvePoints.length,
1794
+ positionL1.x
1795
+ );
1796
+ } else {
1797
+ positionL1.x += 1;
1798
+ updateInfoThisRound = true;
1799
+ isAtEnd = lockPosition();
1800
+ }
1801
+ } else if (e.key == 'ArrowLeft') {
1802
+ // left
1803
+ e.preventDefault();
1804
+ if (constants.isMac ? e.metaKey : e.ctrlKey) {
1805
+ if (e.shiftKey) {
1806
+ positionL1.x += 1;
1807
+ Autoplay('left', positionL1.x, -1);
1808
+ } else {
1809
+ positionL1.x = 0; // go all the way
1810
+ updateInfoThisRound = true;
1811
+ isAtEnd = lockPosition();
1812
+ }
1813
+ } else if (e.altKey && e.shiftKey && positionL1.x != 0) {
1814
+ Autoplay('reverse-left', -1, positionL1.x);
1815
+ } else {
1816
+ positionL1.x -= 1;
1817
+ updateInfoThisRound = true;
1818
+ isAtEnd = lockPosition();
1819
+ }
1820
+ } else {
1821
+ e.preventDefault();
1822
+ }
1823
+ } else if (e.key == 'Tab') {
1824
+ // do nothing, we handle this in global events
1825
+ } else {
1826
+ e.preventDefault();
1827
+ }
1828
+
1829
+ lastx1 = positionL1.x;
1830
+
1831
+ if (updateInfoThisRound && !isAtEnd) {
1832
+ UpdateAllBraille();
1833
+ }
1834
+ if (isAtEnd) {
1835
+ audio.playEnd();
1836
+ }
1837
+ },
1838
+ ]);
1839
+
1840
+ // helper functions
1841
+ function lockPosition() {
1842
+ // lock to min / max positions
1843
+ let didLockHappen = false;
1844
+ if (constants.chartType == 'point') {
1845
+ if (position.x < 0) {
1846
+ position.x = 0;
1847
+ didLockHappen = true;
1848
+ }
1849
+ if (position.x > plot.x.length - 1) {
1850
+ position.x = plot.x.length - 1;
1851
+ didLockHappen = true;
1852
+ }
1853
+ } else if (constants.chartType == 'smooth') {
1854
+ if (positionL1.x < 0) {
1855
+ positionL1.x = 0;
1856
+ didLockHappen = true;
1857
+ }
1858
+ if (positionL1.x > plot.curvePoints.length - 1) {
1859
+ positionL1.x = plot.curvePoints.length - 1;
1860
+ didLockHappen = true;
1861
+ }
1862
+ }
1863
+
1864
+ return didLockHappen;
1865
+ }
1866
+
1867
+ function UpdateAll() {
1868
+ if (constants.showDisplay) {
1869
+ display.displayValues();
1870
+ }
1871
+ if (constants.showRect) {
1872
+ layer0Point.UpdatePointDisplay();
1873
+ }
1874
+ if (constants.sonifMode != 'off') {
1875
+ plot.PlayTones();
1876
+ }
1877
+ }
1878
+
1879
+ function UpdateAllAutoplay() {
1880
+ if (constants.showDisplayInAutoplay) {
1881
+ display.displayValues();
1882
+ }
1883
+ if (constants.showRect) {
1884
+ if (constants.chartType == 'point') {
1885
+ layer0Point.UpdatePointDisplay();
1886
+ } else {
1887
+ layer1Point.UpdatePointDisplay();
1888
+ }
1889
+ }
1890
+ if (constants.sonifMode != 'off') {
1891
+ plot.PlayTones();
1892
+ }
1893
+ if (constants.brailleMode != 'off') {
1894
+ display.UpdateBraillePos();
1895
+ }
1896
+ }
1897
+ function UpdateAllBraille() {
1898
+ if (constants.showDisplayInBraille) {
1899
+ display.displayValues();
1900
+ }
1901
+ if (constants.showRect) {
1902
+ layer1Point.UpdatePointDisplay();
1903
+ }
1904
+ if (constants.sonifMode != 'off') {
1905
+ plot.PlayTones();
1906
+ }
1907
+ display.UpdateBraillePos();
1908
+ }
1909
+
1910
+ function Autoplay(dir, start, end) {
1911
+ lastPlayed = dir;
1912
+ let step = 1; // default right and reverse left
1913
+ if (dir == 'left' || dir == 'reverse-right') {
1914
+ step = -1;
1915
+ }
1916
+
1917
+ // clear old autoplay if exists
1918
+ if (constants.autoplayId) {
1919
+ constants.KillAutoplay();
1920
+ }
1921
+ if (constants.isSmoothAutoplay) {
1922
+ audio.KillSmooth();
1923
+ }
1924
+
1925
+ if (dir == 'reverse-left' || dir == 'reverse-right') {
1926
+ position.x = start;
1927
+ position.L1x = start;
1928
+ }
1929
+
1930
+ if (constants.chartType == 'point') {
1931
+ constants.autoplayId = setInterval(function () {
1932
+ position.x += step;
1933
+ // autoplay for two layers: point layer & smooth layer in braille
1934
+ // plot.numPoints is not available anymore
1935
+ if (position.x < 0 || position.x > plot.y.length - 1) {
1936
+ constants.KillAutoplay();
1937
+ lockPosition();
1938
+ } else if (position.x == end) {
1939
+ constants.KillAutoplay();
1940
+ UpdateAllAutoplay();
1941
+ } else {
1942
+ UpdateAllAutoplay();
1943
+ }
1944
+ }, constants.autoPlayRate);
1945
+ } else if (constants.chartType == 'smooth') {
1946
+ constants.autoplayId = setInterval(function () {
1947
+ positionL1.x += step;
1948
+ // autoplay for two layers: point layer & smooth layer in braille
1949
+ // plot.numPoints is not available anymore
1950
+ if (
1951
+ positionL1.x < 0 ||
1952
+ positionL1.x > plot.curvePoints.length - 1
1953
+ ) {
1954
+ constants.KillAutoplay();
1955
+ lockPosition();
1956
+ } else if (positionL1.x == end) {
1957
+ constants.KillAutoplay();
1958
+ UpdateAllAutoplay();
1959
+ } else {
1960
+ UpdateAllAutoplay();
1961
+ }
1962
+ }, constants.autoPlayRate);
1963
+ }
1964
+ }
1965
+
1966
+ function PlayLine(dir) {
1967
+ lastPlayed = dir;
1968
+
1969
+ let freqArr = [];
1970
+ let panningArr = [];
1971
+ let panPoint = audio.SlideBetween(
1972
+ positionL1.x,
1973
+ 0,
1974
+ plot.curvePoints.length - 1,
1975
+ -1,
1976
+ 1
1977
+ );
1978
+ let x = positionL1.x < 0 ? 0 : positionL1.x;
1979
+ let duration = 0;
1980
+ if (dir == 'right') {
1981
+ for (let i = x; i < plot.curvePoints.length; i++) {
1982
+ freqArr.push(
1983
+ audio.SlideBetween(
1984
+ plot.curvePoints[i],
1985
+ plot.curveMinY,
1986
+ plot.curveMaxY,
1987
+ constants.MIN_FREQUENCY,
1988
+ constants.MAX_FREQUENCY
1989
+ )
1990
+ );
1991
+ }
1992
+ panningArr = [panPoint, 1];
1993
+ duration =
1994
+ (Math.abs(plot.curvePoints.length - x) / plot.curvePoints.length) *
1995
+ 3;
1996
+ } else if (dir == 'left') {
1997
+ for (let i = x; i >= 0; i--) {
1998
+ freqArr.push(
1999
+ audio.SlideBetween(
2000
+ plot.curvePoints[i],
2001
+ plot.curveMinY,
2002
+ plot.curveMaxY,
2003
+ constants.MIN_FREQUENCY,
2004
+ constants.MAX_FREQUENCY
2005
+ )
2006
+ );
2007
+ }
2008
+ panningArr = [panPoint, -1];
2009
+ duration = (Math.abs(x) / plot.curvePoints.length) * 3;
2010
+ } else if (dir == 'reverse-right') {
2011
+ for (let i = plot.curvePoints.length - 1; i >= x; i--) {
2012
+ freqArr.push(
2013
+ audio.SlideBetween(
2014
+ plot.curvePoints[i],
2015
+ plot.curveMinY,
2016
+ plot.curveMaxY,
2017
+ constants.MIN_FREQUENCY,
2018
+ constants.MAX_FREQUENCY
2019
+ )
2020
+ );
2021
+ }
2022
+ panningArr = [1, panPoint];
2023
+ duration =
2024
+ (Math.abs(plot.curvePoints.length - x) / plot.curvePoints.length) *
2025
+ 3;
2026
+ } else if (dir == 'reverse-left') {
2027
+ for (let i = 0; i <= x; i++) {
2028
+ freqArr.push(
2029
+ audio.SlideBetween(
2030
+ plot.curvePoints[i],
2031
+ plot.curveMinY,
2032
+ plot.curveMaxY,
2033
+ constants.MIN_FREQUENCY,
2034
+ constants.MAX_FREQUENCY
2035
+ )
2036
+ );
2037
+ }
2038
+ panningArr = [-1, panPoint];
2039
+ duration = (Math.abs(x) / plot.curvePoints.length) * 3;
2040
+ }
2041
+
2042
+ if (constants.isSmoothAutoplay) {
2043
+ audio.KillSmooth();
2044
+ }
2045
+
2046
+ // audio.playSmooth(freqArr, 2, panningArr, constants.vol, 'sine');
2047
+ audio.playSmooth(freqArr, duration, panningArr, constants.vol, 'sine');
2048
+ }
2049
+ } else if ([].concat(singleMaidr.type).includes('hist')) {
2050
+ window.position = new Position(-1, -1);
2051
+ window.plot = new Histogram();
2052
+
2053
+ // global variables
2054
+ let lastPlayed = '';
2055
+ constants.lastx = 0;
2056
+
2057
+ // control eventlisteners
2058
+ constants.events.push([
2059
+ [constants.chart, constants.brailleInput],
2060
+ 'keydown',
2061
+ function (e) {
2062
+ let updateInfoThisRound = false; // we only update info and play tones on certain keys
2063
+ let isAtEnd = false;
2064
+
2065
+ // Right
2066
+ if (
2067
+ e.key == 'ArrowRight' &&
2068
+ !(constants.isMac ? e.metaKey : e.ctrlKey) &&
2069
+ !e.shiftKey
2070
+ ) {
2071
+ // just right arrow, move right
2072
+ e.preventDefault();
2073
+ position.x += 1;
2074
+ updateInfoThisRound = true;
2075
+ isAtEnd = lockPosition();
2076
+ } else if (
2077
+ e.key == 'ArrowRight' &&
2078
+ (constants.isMac ? e.metaKey : e.ctrlKey) &&
2079
+ e.shiftKey
2080
+ ) {
2081
+ // ctrl shift right arrow, autoplay right
2082
+ e.preventDefault();
2083
+ position.x -= 1;
2084
+ Autoplay('right', position.x, plot.plotData.length);
2085
+ } else if (
2086
+ e.key == 'ArrowRight' &&
2087
+ !(constants.isMac ? e.metaKey : e.ctrlKey) &&
2088
+ e.altKey &&
2089
+ e.shiftKey
2090
+ ) {
2091
+ // alt shift right, autoplay from right
2092
+ e.preventDefault();
2093
+ constants.lastx = position.x;
2094
+ Autoplay('reverse-right', plot.bars.length, position.x);
2095
+ } else if (
2096
+ e.key == 'ArrowRight' &&
2097
+ (constants.isMac ? e.metaKey : e.ctrlKey) &&
2098
+ !e.shiftKey
2099
+ ) {
2100
+ // ctrl right arrow, go to end
2101
+ e.preventDefault();
2102
+ position.x = plot.plotData.length - 1;
2103
+ updateInfoThisRound = true;
2104
+ isAtEnd = lockPosition();
2105
+ }
2106
+
2107
+ // Left
2108
+ if (
2109
+ e.key == 'ArrowLeft' &&
2110
+ !(constants.isMac ? e.metaKey : e.ctrlKey) &&
2111
+ !e.shiftKey
2112
+ ) {
2113
+ // just left arrow, move left
2114
+ e.preventDefault();
2115
+ position.x += -1;
2116
+ updateInfoThisRound = true;
2117
+ isAtEnd = lockPosition();
2118
+ } else if (
2119
+ e.key == 'ArrowLeft' &&
2120
+ (constants.isMac ? e.metaKey : e.ctrlKey) &&
2121
+ e.shiftKey
2122
+ ) {
2123
+ // ctrl shift left arrow, autoplay left
2124
+ e.preventDefault();
2125
+ position.x += 1;
2126
+ Autoplay('left', position.x, -1);
2127
+ } else if (
2128
+ e.key == 'ArrowLeft' &&
2129
+ !(constants.isMac ? e.metaKey : e.ctrlKey) &&
2130
+ e.altKey &&
2131
+ e.shiftKey
2132
+ ) {
2133
+ // alt shift left, autoplay from left
2134
+ e.preventDefault();
2135
+ constants.lastx = position.x;
2136
+ Autoplay('reverse-left', -1, position.x);
2137
+ } else if (
2138
+ e.key == 'ArrowLeft' &&
2139
+ (constants.isMac ? e.metaKey : e.ctrlKey) &&
2140
+ !e.shiftKey
2141
+ ) {
2142
+ // ctrl left arrow, go to beginning
2143
+ e.preventDefault();
2144
+ position.x = 0;
2145
+ updateInfoThisRound = true;
2146
+ isAtEnd = lockPosition();
2147
+ }
2148
+
2149
+ // update display / text / audio
2150
+ if (updateInfoThisRound && !isAtEnd) {
2151
+ if (constants.brailleMode == 'off') {
2152
+ UpdateAll();
2153
+ } else {
2154
+ UpdateAllBraille();
2155
+ }
2156
+ }
2157
+ if (isAtEnd) {
2158
+ audio.playEnd();
2159
+ }
2160
+ },
2161
+ ]);
2162
+
2163
+ let controlElements = [constants.chart, constants.brailleInput];
2164
+ let lastx = 0;
2165
+ for (let i = 0; i < controlElements.length; i++) {
2166
+ constants.events.push([
2167
+ controlElements[i],
2168
+ 'keydown',
2169
+ function (e) {
2170
+ // period: speed up
2171
+ if (e.key == '.') {
2172
+ e.preventDefault();
2173
+ constants.SpeedUp();
2174
+ PlayDuringSpeedChange();
2175
+ display.announceText('Speed up');
2176
+ }
2177
+
2178
+ // comma: speed down
2179
+ if (e.key == ',') {
2180
+ e.preventDefault();
2181
+ constants.SpeedDown();
2182
+ PlayDuringSpeedChange();
2183
+ display.announceText('Speed down');
2184
+ }
2185
+
2186
+ // /: reset speed
2187
+ if (e.key == '/') {
2188
+ e.preventDefault();
2189
+ constants.SpeedReset();
2190
+ PlayDuringSpeedChange();
2191
+ display.announceText('Speed reset');
2192
+ }
2193
+ },
2194
+ ]);
2195
+ }
2196
+ function PlayDuringSpeedChange() {
2197
+ if (constants.autoplayId != null) {
2198
+ constants.KillAutoplay();
2199
+ if (lastPlayed == 'reverse-left') {
2200
+ Autoplay('right', position.x, lastx);
2201
+ } else if (lastPlayed == 'reverse-right') {
2202
+ Autoplay('left', position.x, lastx);
2203
+ } else {
2204
+ Autoplay(lastPlayed, position.x, lastx);
2205
+ }
2206
+ }
2207
+ }
2208
+
2209
+ // lock to min / max postions
2210
+ function lockPosition() {
2211
+ let didLockHappen = false;
2212
+
2213
+ if (position.x < 0) {
2214
+ position.x = 0;
2215
+ didLockHappen = true;
2216
+ }
2217
+ if (position.x > plot.plotData.length - 1) {
2218
+ position.x = plot.plotData.length - 1;
2219
+ didLockHappen = true;
2220
+ }
2221
+
2222
+ return didLockHappen;
2223
+ }
2224
+ function UpdateAll() {
2225
+ if (constants.showDisplay) {
2226
+ display.displayValues();
2227
+ }
2228
+ if (constants.showRect && constants.hasRect) {
2229
+ plot.Select();
2230
+ }
2231
+ if (constants.sonifMode != 'off') {
2232
+ plot.PlayTones();
2233
+ }
2234
+ }
2235
+ function UpdateAllAutoplay() {
2236
+ if (constants.showDisplayInAutoplay) {
2237
+ display.displayValues();
2238
+ }
2239
+ if (constants.showRect && constants.hasRect) {
2240
+ plot.Select();
2241
+ }
2242
+ if (constants.sonifMode != 'off') {
2243
+ plot.PlayTones();
2244
+ }
2245
+
2246
+ if (constants.brailleMode != 'off') {
2247
+ display.UpdateBraillePos();
2248
+ }
2249
+ }
2250
+ function UpdateAllBraille() {
2251
+ if (constants.showDisplayInBraille) {
2252
+ display.displayValues();
2253
+ }
2254
+ if (constants.showRect && constants.hasRect) {
2255
+ plot.Select();
2256
+ }
2257
+ if (constants.sonifMode != 'off') {
2258
+ plot.PlayTones();
2259
+ }
2260
+ display.UpdateBraillePos();
2261
+ }
2262
+ function Autoplay(dir, start, end) {
2263
+ lastPlayed = dir;
2264
+ let step = 1; // default right and reverse-left
2265
+ if (dir == 'left' || dir == 'reverse-right') {
2266
+ step = -1;
2267
+ }
2268
+
2269
+ // clear old autoplay if exists
2270
+ if (constants.autoplayId != null) {
2271
+ constants.KillAutoplay();
2272
+ }
2273
+
2274
+ if (dir == 'reverse-right' || dir == 'reverse-left') {
2275
+ position.x = start;
2276
+ }
2277
+
2278
+ constants.autoplayId = setInterval(function () {
2279
+ position.x += step;
2280
+ if (position.x < 0 || plot.plotData.length - 1 < position.x) {
2281
+ constants.KillAutoplay();
2282
+ lockPosition();
2283
+ } else if (position.x == end) {
2284
+ constants.KillAutoplay();
2285
+ UpdateAllAutoplay();
2286
+ } else {
2287
+ UpdateAllAutoplay();
2288
+ }
2289
+ }, constants.autoPlayRate);
2290
+ }
2291
+ } else if (
2292
+ [].concat(singleMaidr.type).includes('stacked_bar') ||
2293
+ [].concat(singleMaidr.type).includes('stacked_normalized_bar') ||
2294
+ [].concat(singleMaidr.type).includes('dodged_bar')
2295
+ ) {
2296
+ window.position = new Position(-1, -1);
2297
+ window.plot = new Segmented();
2298
+
2299
+ // global variables
2300
+ let lastPlayed = '';
2301
+ constants.lastx = 0;
2302
+
2303
+ // control eventlisteners
2304
+ constants.events.push([
2305
+ [constants.chart, constants.brailleInput],
2306
+ 'keydown',
2307
+ function (e) {
2308
+ let updateInfoThisRound = false; // we only update info and play tones on certain keys
2309
+ let isAtEnd = false;
2310
+ constants.navigation = 0; // 0 for up/down, 1 for left/right
2311
+
2312
+ if (constants.brailleMode == 'on') {
2313
+ if (e.key == 'Tab') {
2314
+ // allow
2315
+ } else {
2316
+ e.preventDefault();
2317
+ }
2318
+ }
2319
+
2320
+ // Right
2321
+ if (
2322
+ e.key == 'ArrowRight' &&
2323
+ !(constants.isMac ? e.metaKey : e.ctrlKey) &&
2324
+ !e.shiftKey
2325
+ ) {
2326
+ // just right arrow, move right
2327
+ position.x += 1;
2328
+ updateInfoThisRound = true;
2329
+ constants.navigation = 1;
2330
+ isAtEnd = lockPosition();
2331
+ } else if (
2332
+ e.key == 'ArrowRight' &&
2333
+ (constants.isMac ? e.metaKey : e.ctrlKey) &&
2334
+ e.shiftKey
2335
+ ) {
2336
+ // ctrl shift right arrow, autoplay right
2337
+ position.x -= 1;
2338
+ Autoplay('right', position.x, plot.plotData.length);
2339
+ } else if (
2340
+ e.key == 'ArrowRight' &&
2341
+ !(constants.isMac ? e.metaKey : e.ctrlKey) &&
2342
+ e.altKey &&
2343
+ e.shiftKey
2344
+ ) {
2345
+ // alt shift right, autoplay from right
2346
+ constants.lastx = position.x;
2347
+ Autoplay('reverse-right', plot.plotData.length, position.x);
2348
+ } else if (
2349
+ e.key == 'ArrowRight' &&
2350
+ (constants.isMac ? e.metaKey : e.ctrlKey) &&
2351
+ !e.shiftKey
2352
+ ) {
2353
+ // ctrl right arrow, go to end
2354
+ position.x = plot.plotData.length - 1;
2355
+ updateInfoThisRound = true;
2356
+ isAtEnd = lockPosition();
2357
+ }
2358
+
2359
+ // Left
2360
+ if (
2361
+ e.key == 'ArrowLeft' &&
2362
+ !(constants.isMac ? e.metaKey : e.ctrlKey) &&
2363
+ !e.shiftKey
2364
+ ) {
2365
+ // just left arrow, move left
2366
+ position.x += -1;
2367
+ updateInfoThisRound = true;
2368
+ constants.navigation = 1;
2369
+ isAtEnd = lockPosition();
2370
+ } else if (
2371
+ e.key == 'ArrowLeft' &&
2372
+ (constants.isMac ? e.metaKey : e.ctrlKey) &&
2373
+ e.shiftKey
2374
+ ) {
2375
+ // ctrl shift left arrow, autoplay left
2376
+ position.x += 1;
2377
+ Autoplay('left', position.x, -1);
2378
+ } else if (
2379
+ e.key == 'ArrowLeft' &&
2380
+ !(constants.isMac ? e.metaKey : e.ctrlKey) &&
2381
+ e.altKey &&
2382
+ e.shiftKey
2383
+ ) {
2384
+ // alt shift left, autoplay from left
2385
+ constants.lastx = position.x;
2386
+ Autoplay('reverse-left', -1, position.x);
2387
+ } else if (
2388
+ e.key == 'ArrowLeft' &&
2389
+ (constants.isMac ? e.metaKey : e.ctrlKey) &&
2390
+ !e.shiftKey
2391
+ ) {
2392
+ // ctrl left arrow, go to beginning
2393
+ position.x = 0;
2394
+ updateInfoThisRound = true;
2395
+ isAtEnd = lockPosition();
2396
+ }
2397
+
2398
+ // Up
2399
+ if (
2400
+ e.key == 'ArrowUp' &&
2401
+ !(constants.isMac ? e.metaKey : e.ctrlKey) &&
2402
+ !e.shiftKey
2403
+ ) {
2404
+ // just up arrow, move up
2405
+ position.y += 1;
2406
+ updateInfoThisRound = true;
2407
+ constants.navigation = 0;
2408
+ isAtEnd = lockPosition();
2409
+ } else if (
2410
+ e.key == 'ArrowUp' &&
2411
+ (constants.isMac ? e.metaKey : e.ctrlKey) &&
2412
+ e.shiftKey
2413
+ ) {
2414
+ // ctrl shift up arrow, autoplay up
2415
+ Autoplay('up', position.y, plot.plotData[0].length);
2416
+ } else if (
2417
+ e.key == 'ArrowUp' &&
2418
+ !(constants.isMac ? e.metaKey : e.ctrlKey) &&
2419
+ e.altKey &&
2420
+ e.shiftKey
2421
+ ) {
2422
+ // alt shift up, autoplay from up
2423
+ constants.lastx = position.x;
2424
+ Autoplay('reverse-up', -1, plot.plotData[0].length);
2425
+ } else if (
2426
+ e.key == 'ArrowUp' &&
2427
+ (constants.isMac ? e.metaKey : e.ctrlKey) &&
2428
+ !e.shiftKey
2429
+ ) {
2430
+ // ctrl up arrow, go to top
2431
+ position.y = plot.plotData[0].length - 1;
2432
+ updateInfoThisRound = true;
2433
+ }
2434
+
2435
+ // Down
2436
+ if (
2437
+ e.key == 'ArrowDown' &&
2438
+ !(constants.isMac ? e.metaKey : e.ctrlKey) &&
2439
+ !e.shiftKey
2440
+ ) {
2441
+ // just down arrow, move down
2442
+ position.y += -1;
2443
+ updateInfoThisRound = true;
2444
+ constants.navigation = 0;
2445
+ isAtEnd = lockPosition();
2446
+ } else if (
2447
+ e.key == 'ArrowDown' &&
2448
+ (constants.isMac ? e.metaKey : e.ctrlKey) &&
2449
+ e.shiftKey
2450
+ ) {
2451
+ // ctrl shift down arrow, autoplay down
2452
+ Autoplay('down', position.y, -1);
2453
+ } else if (
2454
+ e.key == 'ArrowDown' &&
2455
+ !(constants.isMac ? e.metaKey : e.ctrlKey) &&
2456
+ e.altKey &&
2457
+ e.shiftKey
2458
+ ) {
2459
+ // alt shift down, autoplay from down
2460
+ constants.lastx = position.x;
2461
+ Autoplay('reverse-down', -1, position.y);
2462
+ } else if (
2463
+ e.key == 'ArrowDown' &&
2464
+ (constants.isMac ? e.metaKey : e.ctrlKey) &&
2465
+ !e.shiftKey
2466
+ ) {
2467
+ // ctrl down arrow, go to bottom
2468
+ position.y = 0;
2469
+ updateInfoThisRound = true;
2470
+ }
2471
+
2472
+ // update display / text / audio
2473
+ if (updateInfoThisRound && !isAtEnd) {
2474
+ if (constants.brailleMode == 'off') {
2475
+ UpdateAll();
2476
+ } else {
2477
+ UpdateAllBraille();
2478
+ }
2479
+ }
2480
+ if (isAtEnd) {
2481
+ audio.playEnd();
2482
+ }
2483
+ },
2484
+ ]);
2485
+
2486
+ let controlElements = [constants.chart, constants.brailleInput];
2487
+ let lastx = 0;
2488
+ for (let i = 0; i < controlElements.length; i++) {
2489
+ constants.events.push([
2490
+ controlElements[i],
2491
+ 'keydown',
2492
+ function (e) {
2493
+ // period: speed up
2494
+ if (e.key == '.') {
2495
+ constants.SpeedUp();
2496
+ PlayDuringSpeedChange();
2497
+ display.announceText('Speed up');
2498
+ }
2499
+
2500
+ // comma: speed down
2501
+ if (e.key == ',') {
2502
+ constants.SpeedDown();
2503
+ PlayDuringSpeedChange();
2504
+ display.announceText('Speed down');
2505
+ }
2506
+
2507
+ // /: reset speed
2508
+ if (e.key == '/') {
2509
+ constants.SpeedReset();
2510
+ PlayDuringSpeedChange();
2511
+ display.announceText('Speed reset');
2512
+ }
2513
+ },
2514
+ ]);
2515
+ }
2516
+ function PlayDuringSpeedChange() {
2517
+ if (constants.autoplayId != null) {
2518
+ constants.KillAutoplay();
2519
+ if (lastPlayed == 'reverse-left') {
2520
+ Autoplay('right', position.x, lastx);
2521
+ } else if (lastPlayed == 'reverse-right') {
2522
+ Autoplay('left', position.x, lastx);
2523
+ } else if (lastPlayed == 'reverse-up') {
2524
+ Autoplay('down', position.x, lastx);
2525
+ } else if (lastPlayed == 'reverse-down') {
2526
+ Autoplay('up', position.x, lastx);
2527
+ } else {
2528
+ Autoplay(lastPlayed, position.x, lastx);
2529
+ }
2530
+ }
2531
+ }
2532
+
2533
+ // lock to min / max postions
2534
+ function lockPosition() {
2535
+ let didLockHappen = false;
2536
+
2537
+ if (position.x < 0) {
2538
+ position.x = 0;
2539
+ didLockHappen = true;
2540
+ }
2541
+ if (position.x > plot.level.length - 1) {
2542
+ position.x = plot.plotData.length - 1;
2543
+ didLockHappen = true;
2544
+ }
2545
+ if (position.y < 0) {
2546
+ position.y = 0;
2547
+ didLockHappen = true;
2548
+ }
2549
+ if (position.y > plot.fill.length - 1) {
2550
+ position.y = plot.fill.length - 1;
2551
+ didLockHappen = true;
2552
+ }
2553
+
2554
+ return didLockHappen;
2555
+ }
2556
+ function UpdateAll() {
2557
+ if (constants.showDisplay) {
2558
+ display.displayValues();
2559
+ }
2560
+ if (constants.showRect && constants.hasRect) {
2561
+ plot.Select();
2562
+ }
2563
+ if (constants.sonifMode != 'off') {
2564
+ plot.PlayTones();
2565
+ }
2566
+ }
2567
+ function UpdateAllAutoplay() {
2568
+ if (constants.showDisplayInAutoplay) {
2569
+ display.displayValues();
2570
+ }
2571
+ if (constants.showRect && constants.hasRect) {
2572
+ plot.Select();
2573
+ }
2574
+ if (constants.sonifMode != 'off') {
2575
+ plot.PlayTones();
2576
+ }
2577
+
2578
+ if (constants.brailleMode != 'off') {
2579
+ display.UpdateBraillePos();
2580
+ }
2581
+ }
2582
+ function UpdateAllBraille() {
2583
+ if (constants.showDisplayInBraille) {
2584
+ display.SetBraille();
2585
+ display.displayValues();
2586
+ }
2587
+ if (constants.showRect && constants.hasRect) {
2588
+ plot.Select();
2589
+ }
2590
+ if (constants.sonifMode != 'off') {
2591
+ plot.PlayTones();
2592
+ }
2593
+
2594
+ display.UpdateBraillePos();
2595
+ }
2596
+ function Autoplay(dir, start, end) {
2597
+ lastPlayed = dir;
2598
+ let step = 1; // default right, up, reverse-left, and reverse-down
2599
+ if (
2600
+ dir == 'left' ||
2601
+ dir == 'down' ||
2602
+ dir == 'reverse-right' ||
2603
+ dir == 'reverse-up'
2604
+ ) {
2605
+ step = -1;
2606
+ }
2607
+
2608
+ // clear old autoplay if exists
2609
+ if (constants.autoplayId != null) {
2610
+ constants.KillAutoplay();
2611
+ }
2612
+
2613
+ if (dir == 'reverse-left' || dir == 'reverse-right') {
2614
+ position.x = start;
2615
+ } else if (dir == 'reverse-up' || dir == 'reverse-down') {
2616
+ position.y = start;
2617
+ }
2618
+
2619
+ constants.autoplayId = setInterval(function () {
2620
+ if (
2621
+ dir == 'left' ||
2622
+ dir == 'right' ||
2623
+ dir == 'reverse-left' ||
2624
+ dir == 'reverse-right'
2625
+ ) {
2626
+ position.x += step;
2627
+ if (position.x < 0 || plot.plotData.length - 1 < position.x) {
2628
+ constants.KillAutoplay();
2629
+ lockPosition();
2630
+ } else if (position.x == end) {
2631
+ constants.KillAutoplay();
2632
+ UpdateAllAutoplay();
2633
+ } else {
2634
+ UpdateAllAutoplay();
2635
+ }
2636
+ } else {
2637
+ // up or down
2638
+ position.y += step;
2639
+ if (position.y < 0 || plot.plotData[0].length - 1 < position.y) {
2640
+ constants.KillAutoplay();
2641
+ lockPosition();
2642
+ } else if (position.y == end) {
2643
+ constants.KillAutoplay();
2644
+ UpdateAllAutoplay();
2645
+ } else {
2646
+ UpdateAllAutoplay();
2647
+ }
2648
+ }
2649
+ }, constants.autoPlayRate);
2650
+ }
2651
+ } else if (singleMaidr.type == 'line') {
2652
+ window.position = new Position(-1, -1);
2653
+ window.plot = new LinePlot();
2654
+ let point = new Point();
2655
+
2656
+ // global variables
2657
+ let lastPlayed = '';
2658
+ constants.lastx = 0;
2659
+
2660
+ // control eventlisteners
2661
+ constants.events.push([
2662
+ constants.chart,
2663
+ 'keydown',
2664
+ function (e) {
2665
+ let updateInfoThisRound = false; // we only update info and play tones on certain keys
2666
+ let isAtEnd = false;
2667
+
2668
+ if (e.key == 'ArrowRight') {
2669
+ if (constants.isMac ? e.metaKey : e.ctrlKey) {
2670
+ if (e.shiftKey) {
2671
+ position.x -= 1;
2672
+ Autoplay('right', position.x, plot.pointValuesY.length);
2673
+ } else {
2674
+ position.x = plot.pointValuesY.length - 1; // go all the way
2675
+ updateInfoThisRound = true;
2676
+ isAtEnd = lockPosition();
2677
+ }
2678
+ } else if (
2679
+ e.altKey &&
2680
+ e.shiftKey &&
2681
+ position.x != plot.pointValuesY.length - 1
2682
+ ) {
2683
+ constants.lastx = position.x;
2684
+ Autoplay('reverse-right', plot.pointValuesY.length, position.x);
2685
+ } else {
2686
+ position.x += 1;
2687
+ updateInfoThisRound = true;
2688
+ isAtEnd = lockPosition();
2689
+ }
2690
+ } else if (e.key == 'ArrowLeft') {
2691
+ // var prevLink = document.getElementById('prev'); // what is prev in the html?
2692
+ // if (prevLink) {
2693
+ // left arrow 37
2694
+ if (constants.isMac ? e.metaKey : e.ctrlKey) {
2695
+ if (e.shiftKey) {
2696
+ position.x += 1;
2697
+ Autoplay('left', position.x, -1);
2698
+ } else {
2699
+ position.x = 0; // go all the way
2700
+ updateInfoThisRound = true;
2701
+ isAtEnd = lockPosition();
2702
+ }
2703
+ } else if (e.altKey && e.shiftKey && position.x != 0) {
2704
+ constants.lastx = position.x;
2705
+ Autoplay('reverse-left', -1, position.x);
2706
+ } else {
2707
+ position.x += -1;
2708
+ updateInfoThisRound = true;
2709
+ isAtEnd = lockPosition();
2710
+ }
2711
+ // }
2712
+ }
2713
+
2714
+ // update display / text / audio
2715
+ if (updateInfoThisRound && !isAtEnd) {
2716
+ UpdateAll();
2717
+ }
2718
+ if (isAtEnd) {
2719
+ audio.playEnd();
2720
+ }
2721
+ },
2722
+ ]);
2723
+
2724
+ constants.events.push([
2725
+ constants.brailleInput,
2726
+ 'keydown',
2727
+ function (e) {
2728
+ let updateInfoThisRound = false; // we only update info and play tones on certain keys
2729
+ let isAtEnd = false;
2730
+
2731
+ if (e.key == 'ArrowRight') {
2732
+ // right arrow
2733
+ e.preventDefault();
2734
+ if (e.target.selectionStart > e.target.value.length - 2) {
2735
+ } else if (constants.isMac ? e.metaKey : e.ctrlKey) {
2736
+ if (e.shiftKey) {
2737
+ position.x -= 1;
2738
+ Autoplay('right', position.x, plot.pointValuesY.length);
2739
+ } else {
2740
+ position.x = plot.pointValuesY.length - 1; // go all the way
2741
+ updateInfoThisRound = true;
2742
+ isAtEnd = lockPosition();
2743
+ }
2744
+ } else if (
2745
+ e.altKey &&
2746
+ e.shiftKey &&
2747
+ position.x != plot.pointValues.length - 1
2748
+ ) {
2749
+ constants.lastx = position.x;
2750
+ Autoplay('reverse-right', plot.pointValuesY.length, position.x);
2751
+ } else {
2752
+ position.x += 1;
2753
+ updateInfoThisRound = true;
2754
+ isAtEnd = lockPosition();
2755
+ }
2756
+ } else if (e.key == 'ArrowLeft') {
2757
+ // left arrow
2758
+ e.preventDefault();
2759
+ if (constants.isMac ? e.metaKey : e.ctrlKey) {
2760
+ if (e.shiftKey) {
2761
+ position.x += 1;
2762
+ Autoplay('left', position.x, -1);
2763
+ } else {
2764
+ position.x = 0; // go all the way
2765
+ updateInfoThisRound = true;
2766
+ isAtEnd = lockPosition();
2767
+ }
2768
+ } else if (e.altKey && e.shiftKey && position.x != 0) {
2769
+ constants.lastx = position.x;
2770
+ Autoplay('reverse-left', -1, position.x);
2771
+ } else {
2772
+ position.x += -1;
2773
+ updateInfoThisRound = true;
2774
+ isAtEnd = lockPosition();
2775
+ }
2776
+ } else if (e.key == 'Tab') {
2777
+ // do nothing, we handle this in global events
2778
+ } else {
2779
+ e.preventDefault();
2780
+ }
2781
+
2782
+ // update display / text / audio
2783
+ if (updateInfoThisRound && !isAtEnd) {
2784
+ UpdateAllBraille();
2785
+ }
2786
+ if (isAtEnd) {
2787
+ audio.playEnd();
2788
+ }
2789
+ },
2790
+ ]);
2791
+
2792
+ // control eventlisteners
2793
+ // constants.events.push([
2794
+ // [constants.chart, constants.brailleInput],
2795
+ // 'keydown',
2796
+ // function (e) {
2797
+ // let updateInfoThisRound = false; // we only update info and play tones on certain keys
2798
+ // let isAtEnd = false;
2799
+
2800
+ // if (e.key == 'ArrowRight') {
2801
+ // // right arrow
2802
+ // e.preventDefault();
2803
+ // if (e.target.selectionStart > e.target.value.length - 2) {
2804
+ // } else if (constants.isMac ? e.metaKey : e.ctrlKey) {
2805
+ // if (e.shiftKey) {
2806
+ // position.x -= 1;
2807
+ // Autoplay('right', position.x, plot.pointValuesY.length);
2808
+ // } else {
2809
+ // position.x = plot.pointValuesY.length - 1; // go all the way
2810
+ // updateInfoThisRound = true;
2811
+ // isAtEnd = lockPosition();
2812
+ // }
2813
+ // } else if (
2814
+ // e.altKey &&
2815
+ // e.shiftKey &&
2816
+ // position.x != plot.pointValuesY.length - 1
2817
+ // ) {
2818
+ // constants.lastx = position.x;
2819
+ // Autoplay('reverse-right', plot.pointValuesY.length, position.x);
2820
+ // } else {
2821
+ // position.x += 1;
2822
+ // updateInfoThisRound = true;
2823
+ // isAtEnd = lockPosition();
2824
+ // }
2825
+ // } else if (e.key == 'ArrowLeft') {
2826
+ // // left arrow
2827
+ // e.preventDefault();
2828
+ // if (constants.isMac ? e.metaKey : e.ctrlKey) {
2829
+ // if (e.shiftKey) {
2830
+ // position.x += 1;
2831
+ // Autoplay('left', position.x, -1);
2832
+ // } else {
2833
+ // position.x = 0; // go all the way
2834
+ // updateInfoThisRound = true;
2835
+ // isAtEnd = lockPosition();
2836
+ // }
2837
+ // } else if (e.altKey && e.shiftKey && position.x != 0) {
2838
+ // constants.lastx = position.x;
2839
+ // Autoplay('reverse-left', -1, position.x);
2840
+ // } else {
2841
+ // position.x += -1;
2842
+ // updateInfoThisRound = true;
2843
+ // isAtEnd = lockPosition();
2844
+ // }
2845
+ // } else if (e.key == 'Tab') {
2846
+ // // do nothing, we handle this in global events
2847
+ // } else {
2848
+ // e.preventDefault();
2849
+ // // Right
2850
+ // if (
2851
+ // e.key == 'ArrowRight' &&
2852
+ // !(constants.isMac ? e.metaKey : e.ctrlKey) &&
2853
+ // !e.shiftKey
2854
+ // ) {
2855
+ // // just right arrow, move right
2856
+ // position.x += 1;
2857
+ // updateInfoThisRound = true;
2858
+ // isAtEnd = lockPosition();
2859
+ // } else if (
2860
+ // e.key == 'ArrowRight' &&
2861
+ // (constants.isMac ? e.metaKey : e.ctrlKey) &&
2862
+ // e.shiftKey
2863
+ // ) {
2864
+ // // ctrl shift right arrow, autoplay right
2865
+ // position.x += -1;
2866
+ // Autoplay('outward_right', position.x, plot.pointValuesY.length);
2867
+ // } else if (
2868
+ // e.key == 'ArrowRight' &&
2869
+ // !(constants.isMac ? e.metaKey : e.ctrlKey) &&
2870
+ // e.altKey &&
2871
+ // e.shiftKey &&
2872
+ // position.x != plot.pointValuesY.length - 1
2873
+ // ) {
2874
+ // // alt shift right, autoplay from right
2875
+ // constants.lastx = position.x;
2876
+ // Autoplay('inward_right', plot.pointValues.length, position.x);
2877
+ // } else if (
2878
+ // e.key == 'ArrowRight' &&
2879
+ // (constants.isMac ? e.metaKey : e.ctrlKey) &&
2880
+ // !e.shiftKey
2881
+ // ) {
2882
+ // // ctrl right arrow, go to end
2883
+ // position.x = plot.pointValuesY.length - 1; // go all the way
2884
+ // updateInfoThisRound = true;
2885
+ // isAtEnd = lockPosition();
2886
+ // }
2887
+
2888
+ // // Left
2889
+ // if (
2890
+ // e.key == 'ArrowLeft' &&
2891
+ // !(constants.isMac ? e.metaKey : e.ctrlKey) &&
2892
+ // !e.shiftKey
2893
+ // ) {
2894
+ // // just left arrow, move left
2895
+ // position.x += -1;
2896
+ // updateInfoThisRound = true;
2897
+ // isAtEnd = lockPosition();
2898
+ // } else if (
2899
+ // e.key == 'ArrowLeft' &&
2900
+ // (constants.isMac ? e.metaKey : e.ctrlKey) &&
2901
+ // e.shiftKey
2902
+ // ) {
2903
+ // // ctrl shift left arrow, autoplay left
2904
+ // position.x += 1;
2905
+ // Autoplay('outward_left', position.x, -1);
2906
+ // } else if (
2907
+ // e.key == 'ArrowLeft' &&
2908
+ // !(constants.isMac ? e.metaKey : e.ctrlKey) &&
2909
+ // e.altKey &&
2910
+ // e.shiftKey
2911
+ // ) {
2912
+ // // alt shift left, autoplay from left
2913
+ // constants.lastx = position.x;
2914
+ // Autoplay('inward_left', -1, position.x);
2915
+ // } else if (
2916
+ // e.key == 'ArrowLeft' &&
2917
+ // (constants.isMac ? e.metaKey : e.ctrlKey) &&
2918
+ // !e.shiftKey
2919
+ // ) {
2920
+ // // ctrl left arrow, go to beginning
2921
+ // position.x = 0; // go all the way
2922
+ // updateInfoThisRound = true;
2923
+ // isAtEnd = lockPosition();
2924
+ // }
2925
+
2926
+ // // update display / text / audio
2927
+ // if (updateInfoThisRound && !isAtEnd) {
2928
+ // if (constants.brailleMode == 'off') {
2929
+ // UpdateAll();
2930
+ // } else {
2931
+ // UpdateAllBraille();
2932
+ // }
2933
+ // }
2934
+ // if (isAtEnd) {
2935
+ // audio.playEnd();
2936
+ // }
2937
+ // }
2938
+ // },
2939
+ // ]);
2940
+
2941
+ let controlElements = [constants.chart, constants.brailleInput];
2942
+ let lastx = 0;
2943
+ for (let i = 0; i < controlElements.length; i++) {
2944
+ constants.events.push([
2945
+ controlElements[i],
2946
+ 'keydown',
2947
+ function (e) {
2948
+ // period: speed up
2949
+ if (e.key == '.') {
2950
+ constants.SpeedUp();
2951
+ PlayDuringSpeedChange();
2952
+ display.announceText('Speed up');
2953
+ }
2954
+
2955
+ // comma: speed down
2956
+ if (e.key == ',') {
2957
+ constants.SpeedDown();
2958
+ PlayDuringSpeedChange();
2959
+ display.announceText('Speed down');
2960
+ }
2961
+
2962
+ // /: reset speed
2963
+ if (e.key == '/') {
2964
+ constants.SpeedReset();
2965
+ PlayDuringSpeedChange();
2966
+ display.announceText('Speed reset');
2967
+ }
2968
+ },
2969
+ ]);
2970
+ }
2971
+ function PlayDuringSpeedChange() {
2972
+ if (constants.autoplayId != null) {
2973
+ constants.KillAutoplay();
2974
+ if (lastPlayed == 'reverse-left') {
2975
+ Autoplay('right', position.x, lastx);
2976
+ } else if (lastPlayed == 'reverse-right') {
2977
+ Autoplay('left', position.x, lastx);
2978
+ } else {
2979
+ Autoplay(lastPlayed, position.x, lastx);
2980
+ }
2981
+ }
2982
+ }
2983
+
2984
+ function lockPosition() {
2985
+ // lock to min / max postions
2986
+ let didLockHappen = false;
2987
+ // if (!constants.hasRect) {
2988
+ // return didLockHappen;
2989
+ // }
2990
+
2991
+ if (position.x < 0) {
2992
+ position.x = 0;
2993
+ didLockHappen = true;
2994
+ }
2995
+ if (position.x > plot.pointValuesY.length - 1) {
2996
+ position.x = plot.pointValuesY.length - 1;
2997
+ didLockHappen = true;
2998
+ }
2999
+
3000
+ return didLockHappen;
3001
+ }
3002
+ function UpdateAll() {
3003
+ if (constants.showDisplay) {
3004
+ display.displayValues();
3005
+ }
3006
+ if (constants.showRect) {
3007
+ point.UpdatePointDisplay();
3008
+ }
3009
+ if (constants.sonifMode != 'off') {
3010
+ plot.PlayTones();
3011
+ }
3012
+ }
3013
+ function UpdateAllAutoplay() {
3014
+ if (constants.showDisplayInAutoplay) {
3015
+ display.displayValues();
3016
+ }
3017
+ if (constants.showRect) {
3018
+ point.UpdatePointDisplay();
3019
+ }
3020
+ if (constants.sonifMode != 'off') {
3021
+ plot.PlayTones();
3022
+ }
3023
+
3024
+ if (constants.brailleMode != 'off') {
3025
+ display.UpdateBraillePos();
3026
+ }
3027
+ }
3028
+ function UpdateAllBraille() {
3029
+ if (constants.showDisplayInBraille) {
3030
+ display.displayValues();
3031
+ }
3032
+ if (constants.showRect) {
3033
+ point.UpdatePointDisplay();
3034
+ }
3035
+ if (constants.sonifMode != 'off') {
3036
+ plot.PlayTones();
3037
+ }
3038
+ display.UpdateBraillePos();
3039
+ }
3040
+ function Autoplay(dir, start, end) {
3041
+ lastPlayed = dir;
3042
+ let step = 1; // default right and reverse-left
3043
+ if (dir == 'left' || dir == 'reverse-right') {
3044
+ step = -1;
3045
+ }
3046
+
3047
+ // clear old autoplay if exists
3048
+ if (constants.autoplayId != null) {
3049
+ constants.KillAutoplay();
3050
+ }
3051
+
3052
+ if (dir == 'reverse-right' || dir == 'reverse-left') {
3053
+ position.x = start;
3054
+ }
3055
+
3056
+ constants.autoplayId = setInterval(function () {
3057
+ position.x += step;
3058
+ if (position.x < 0 || plot.pointValuesY.length - 1 < position.x) {
3059
+ constants.KillAutoplay();
3060
+ lockPosition();
3061
+ } else if (position.x == end) {
3062
+ constants.KillAutoplay();
3063
+ UpdateAllAutoplay();
3064
+ } else {
3065
+ UpdateAllAutoplay();
3066
+ }
3067
+ }, constants.autoPlayRate);
3068
+ }
3069
+ function PlayLine(dir) {
3070
+ lastPlayed = dir;
3071
+
3072
+ let freqArr = [];
3073
+ let panningArr = [];
3074
+ let panPoint = audio.SlideBetween(
3075
+ positionL1.x,
3076
+ 0,
3077
+ plot.curvePoints.length - 1,
3078
+ -1,
3079
+ 1
3080
+ );
3081
+ let x = positionL1.x < 0 ? 0 : positionL1.x;
3082
+ let duration = 0;
3083
+ if (dir == 'right') {
3084
+ for (let i = x; i < plot.curvePoints.length; i++) {
3085
+ freqArr.push(
3086
+ audio.SlideBetween(
3087
+ plot.curvePoints[i],
3088
+ plot.curveMinY,
3089
+ plot.curveMaxY,
3090
+ constants.MIN_FREQUENCY,
3091
+ constants.MAX_FREQUENCY
3092
+ )
3093
+ );
3094
+ }
3095
+ panningArr = [panPoint, 1];
3096
+ duration =
3097
+ (Math.abs(plot.curvePoints.length - x) / plot.curvePoints.length) *
3098
+ 3;
3099
+ } else if (dir == 'left') {
3100
+ for (let i = x; i >= 0; i--) {
3101
+ freqArr.push(
3102
+ audio.SlideBetween(
3103
+ plot.curvePoints[i],
3104
+ plot.curveMinY,
3105
+ plot.curveMaxY,
3106
+ constants.MIN_FREQUENCY,
3107
+ constants.MAX_FREQUENCY
3108
+ )
3109
+ );
3110
+ }
3111
+ panningArr = [panPoint, -1];
3112
+ duration = (Math.abs(x) / plot.curvePoints.length) * 3;
3113
+ } else if (dir == 'reverse-right') {
3114
+ for (let i = plot.curvePoints.length - 1; i >= x; i--) {
3115
+ freqArr.push(
3116
+ audio.SlideBetween(
3117
+ plot.curvePoints[i],
3118
+ plot.curveMinY,
3119
+ plot.curveMaxY,
3120
+ constants.MIN_FREQUENCY,
3121
+ constants.MAX_FREQUENCY
3122
+ )
3123
+ );
3124
+ }
3125
+ panningArr = [1, panPoint];
3126
+ duration =
3127
+ (Math.abs(plot.curvePoints.length - x) / plot.curvePoints.length) *
3128
+ 3;
3129
+ } else if (dir == 'reverse-left') {
3130
+ for (let i = 0; i <= x; i++) {
3131
+ freqArr.push(
3132
+ audio.SlideBetween(
3133
+ plot.curvePoints[i],
3134
+ plot.curveMinY,
3135
+ plot.curveMaxY,
3136
+ constants.MIN_FREQUENCY,
3137
+ constants.MAX_FREQUENCY
3138
+ )
3139
+ );
3140
+ }
3141
+ panningArr = [-1, panPoint];
3142
+ duration = (Math.abs(x) / plot.curvePoints.length) * 3;
3143
+ }
3144
+
3145
+ if (constants.isSmoothAutoplay) {
3146
+ audio.KillSmooth();
3147
+ }
3148
+
3149
+ // audio.playSmooth(freqArr, 2, panningArr, constants.vol, 'sine');
3150
+ audio.playSmooth(freqArr, duration, panningArr, constants.vol, 'sine');
3151
+ }
3152
+ }
3153
+ }
3154
+
3155
+ GetNextPrevFocusable(nextprev = 'next') {
3156
+ // store all focusable elements for future tabbing away from chart
3157
+ let focusableSelectors =
3158
+ 'a[href], button:not([disabled]), textarea:not([disabled]), input[type="text"]:not([disabled]), input[type="radio"]:not([disabled]), input[type="checkbox"]:not([disabled]), select:not([disabled]), [tabindex]:not([tabindex="-1"])';
3159
+ constants.focusables = Array.from(
3160
+ document.querySelectorAll(focusableSelectors)
3161
+ );
3162
+
3163
+ // get index of chart in focusables
3164
+ let chartIndex = constants.focusables.indexOf(constants.chart);
3165
+
3166
+ // remove all the stuff we add manually from focusables
3167
+ let maidrFocusables =
3168
+ constants.main_container.querySelectorAll(focusableSelectors);
3169
+ for (let i = 0; i < maidrFocusables.length; i++) {
3170
+ let index = constants.focusables.indexOf(maidrFocusables[i]);
3171
+ if (index > -1) {
3172
+ constants.focusables.splice(index, 1);
3173
+ }
3174
+ // and adjust chartIndex
3175
+ if (chartIndex > index) {
3176
+ chartIndex--;
3177
+ }
3178
+ }
3179
+
3180
+ // now we get next / prev based on chartIndex. If DNE, return null
3181
+ }
3182
+ }