maidr 2.23.0 → 2.23.2
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.
- package/dist/maidr.js +692 -616
- package/dist/maidr.min.js +1 -1
- package/package.json +1 -1
package/dist/maidr.js
CHANGED
|
@@ -12,77 +12,77 @@ class Constants {
|
|
|
12
12
|
* @memberof HtmlIds
|
|
13
13
|
* @default 'chart-container'
|
|
14
14
|
*/
|
|
15
|
-
chart_container_id =
|
|
15
|
+
chart_container_id = 'chart-container';
|
|
16
16
|
/**
|
|
17
17
|
* HTML id of the main container div.
|
|
18
18
|
* @type {string}
|
|
19
19
|
* @memberof HtmlIds
|
|
20
20
|
* @default 'maidr-container'
|
|
21
21
|
*/
|
|
22
|
-
main_container_id =
|
|
22
|
+
main_container_id = 'maidr-container';
|
|
23
23
|
/**
|
|
24
24
|
* HTML id of the div containing the braille display input
|
|
25
25
|
* @type {string}
|
|
26
26
|
* @memberof HtmlIds
|
|
27
27
|
* @default 'braille-div'
|
|
28
28
|
*/
|
|
29
|
-
braille_container_id =
|
|
29
|
+
braille_container_id = 'braille-div';
|
|
30
30
|
/**
|
|
31
31
|
* HTML id of the actual braille input element.
|
|
32
32
|
* @type {string}
|
|
33
33
|
* @memberof HtmlIds
|
|
34
34
|
* @default 'braille-input'
|
|
35
35
|
*/
|
|
36
|
-
braille_input_id =
|
|
36
|
+
braille_input_id = 'braille-input';
|
|
37
37
|
/**
|
|
38
38
|
* HTML id of the div containing the info box.
|
|
39
39
|
* @type {string}
|
|
40
40
|
* @memberof HtmlIds
|
|
41
41
|
* @default 'info'
|
|
42
42
|
*/
|
|
43
|
-
info_id =
|
|
43
|
+
info_id = 'info';
|
|
44
44
|
/**
|
|
45
45
|
* HTML id of the div containing announcements that hook directly into the screen reader via aria-live.
|
|
46
46
|
* @type {string}
|
|
47
47
|
* @memberof HtmlIds
|
|
48
48
|
* @default 'announcements'
|
|
49
49
|
*/
|
|
50
|
-
announcement_container_id =
|
|
50
|
+
announcement_container_id = 'announcements';
|
|
51
51
|
/**
|
|
52
52
|
* HTML id of the div containing the end chime. To be implemented in the future.
|
|
53
53
|
* @type {string}
|
|
54
54
|
* @memberof HtmlIds
|
|
55
55
|
* @default 'end_chime'
|
|
56
56
|
*/
|
|
57
|
-
end_chime_id =
|
|
57
|
+
end_chime_id = 'end_chime';
|
|
58
58
|
/**
|
|
59
59
|
* HTML id of the main container div.
|
|
60
60
|
* @type {string}
|
|
61
61
|
* @memberof HtmlIds
|
|
62
62
|
* @default 'container'
|
|
63
63
|
*/
|
|
64
|
-
container_id =
|
|
64
|
+
container_id = 'container';
|
|
65
65
|
/**
|
|
66
66
|
* The main project id, used throughout the application.
|
|
67
67
|
* @type {string}
|
|
68
68
|
* @memberof HtmlIds
|
|
69
69
|
* @default 'maidr'
|
|
70
70
|
*/
|
|
71
|
-
project_id =
|
|
71
|
+
project_id = 'maidr';
|
|
72
72
|
/**
|
|
73
73
|
* HTML id of the div containing the review text.
|
|
74
74
|
* @type {string}
|
|
75
75
|
* @memberof HtmlIds
|
|
76
76
|
* @default 'review_container'
|
|
77
77
|
*/
|
|
78
|
-
review_id_container =
|
|
78
|
+
review_id_container = 'review_container';
|
|
79
79
|
/**
|
|
80
80
|
* HTML id of the review input element.
|
|
81
81
|
* @type {string}
|
|
82
82
|
* @memberof HtmlIds
|
|
83
83
|
* @default 'review'
|
|
84
84
|
*/
|
|
85
|
-
review_id =
|
|
85
|
+
review_id = 'review';
|
|
86
86
|
/**
|
|
87
87
|
* Storage element, used to store the last focused element before moving to the review input so we can switch back to it easily.
|
|
88
88
|
* @type {HTMLElement}
|
|
@@ -99,7 +99,7 @@ class Constants {
|
|
|
99
99
|
* @type {string}
|
|
100
100
|
* @memberof HtmlIds
|
|
101
101
|
*/
|
|
102
|
-
chartId =
|
|
102
|
+
chartId = '';
|
|
103
103
|
/**
|
|
104
104
|
* @typedef {Object} EventListenerSetupObject
|
|
105
105
|
* @property {HTMLElement} element - The element to attach the event listener to.
|
|
@@ -128,7 +128,7 @@ class Constants {
|
|
|
128
128
|
* @memberof BTSModes
|
|
129
129
|
* @default 'verbose'
|
|
130
130
|
*/
|
|
131
|
-
textMode =
|
|
131
|
+
textMode = 'verbose';
|
|
132
132
|
|
|
133
133
|
/**
|
|
134
134
|
* The current braille mode. Can be 'off' or 'on'.
|
|
@@ -136,7 +136,7 @@ class Constants {
|
|
|
136
136
|
* @memberof BTSModes
|
|
137
137
|
* @default 'off'
|
|
138
138
|
*/
|
|
139
|
-
brailleMode =
|
|
139
|
+
brailleMode = 'off';
|
|
140
140
|
|
|
141
141
|
/**
|
|
142
142
|
* We lock the selection so we don't pick up programatic selection changes
|
|
@@ -151,14 +151,14 @@ class Constants {
|
|
|
151
151
|
* @memberof BTSModes
|
|
152
152
|
* @default 'on'
|
|
153
153
|
*/
|
|
154
|
-
sonifMode =
|
|
154
|
+
sonifMode = 'on';
|
|
155
155
|
/**
|
|
156
156
|
* The current review mode. Can be 'on' or 'off'.
|
|
157
157
|
* @type {("on"|"off")}
|
|
158
158
|
* @memberof BTSModes
|
|
159
159
|
* @default 'off'
|
|
160
160
|
*/
|
|
161
|
-
reviewMode =
|
|
161
|
+
reviewMode = 'off';
|
|
162
162
|
|
|
163
163
|
// basic chart properties
|
|
164
164
|
/**
|
|
@@ -199,14 +199,14 @@ class Constants {
|
|
|
199
199
|
* @memberof HtmlIds
|
|
200
200
|
* @default ''
|
|
201
201
|
*/
|
|
202
|
-
plotId =
|
|
202
|
+
plotId = ''; // update with id in chart specific js
|
|
203
203
|
/**
|
|
204
204
|
* The chart type, sort of a short name of the chart such as 'box', 'bar', 'line', etc.
|
|
205
205
|
* @type {string}
|
|
206
206
|
* @default ''
|
|
207
207
|
* @memberof BasicChartProperties
|
|
208
208
|
*/
|
|
209
|
-
chartType =
|
|
209
|
+
chartType = '';
|
|
210
210
|
/**
|
|
211
211
|
* The navigation orientation of the chart. 0 = row navigation (up/down), 1 = col navigation (left/right).
|
|
212
212
|
* @type {number}
|
|
@@ -220,7 +220,7 @@ class Constants {
|
|
|
220
220
|
* @default 'horz'
|
|
221
221
|
* @memberof BasicChartProperties
|
|
222
222
|
*/
|
|
223
|
-
plotOrientation =
|
|
223
|
+
plotOrientation = 'horz';
|
|
224
224
|
|
|
225
225
|
/**
|
|
226
226
|
* @namespace AudioProperties
|
|
@@ -330,7 +330,7 @@ class Constants {
|
|
|
330
330
|
* @default '#03C809' (green)
|
|
331
331
|
* @memberof UserSettings
|
|
332
332
|
*/
|
|
333
|
-
colorSelected =
|
|
333
|
+
colorSelected = '#03C809';
|
|
334
334
|
/**
|
|
335
335
|
* The length of the braille display in characters. Braille displays have a variety of sizes; 40 is pretty common, 32 is quite reliable. Set this to your actual display length so that the system can scale and display braille properly for you (where possible).
|
|
336
336
|
* @type {number}
|
|
@@ -398,7 +398,7 @@ class Constants {
|
|
|
398
398
|
* @default 50
|
|
399
399
|
* @memberof AdvancedUserSettings
|
|
400
400
|
*/
|
|
401
|
-
colorUnselected =
|
|
401
|
+
colorUnselected = '#595959'; // deprecated, todo: find all instances replace with storing old color method
|
|
402
402
|
/**
|
|
403
403
|
* Whether or not we're logging user data. This is off by default, but is used for research purposes.
|
|
404
404
|
* @type {boolean}
|
|
@@ -419,33 +419,34 @@ class Constants {
|
|
|
419
419
|
* @default 'assertive'
|
|
420
420
|
* @memberof AdvancedUserSettings
|
|
421
421
|
*/
|
|
422
|
-
ariaMode =
|
|
422
|
+
ariaMode = 'assertive';
|
|
423
423
|
|
|
424
424
|
/**
|
|
425
425
|
* Full list of user settings, used internally to save and load settings.
|
|
426
426
|
* @type {string[]}
|
|
427
427
|
*/
|
|
428
428
|
userSettingsKeys = [
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
429
|
+
'vol',
|
|
430
|
+
'autoPlayRate',
|
|
431
|
+
'brailleDisplayLength',
|
|
432
|
+
'colorSelected',
|
|
433
|
+
'MIN_FREQUENCY',
|
|
434
|
+
'MAX_FREQUENCY',
|
|
435
|
+
'AUTOPLAY_DURATION',
|
|
436
|
+
'ariaMode',
|
|
437
|
+
'openAIAuthKey',
|
|
438
|
+
'geminiAuthKey',
|
|
439
|
+
'claudeAuthKey',
|
|
440
|
+
'emailAuthKey',
|
|
441
|
+
'skillLevel',
|
|
442
|
+
'skillLevelOther',
|
|
443
|
+
'LLMModel',
|
|
444
|
+
'LLMPreferences',
|
|
445
|
+
'LLMOpenAiMulti',
|
|
446
|
+
'LLMGeminiMulti',
|
|
447
|
+
'LLMModels',
|
|
448
|
+
'autoInitLLM',
|
|
449
|
+
'clientToken',
|
|
449
450
|
];
|
|
450
451
|
|
|
451
452
|
// LLM settings
|
|
@@ -486,14 +487,14 @@ class Constants {
|
|
|
486
487
|
* @default 'high'
|
|
487
488
|
* @memberof LLMSettings
|
|
488
489
|
*/
|
|
489
|
-
LLMDetail =
|
|
490
|
+
LLMDetail = 'high'; // low (default for testing, like 100 tokens) / high (default for real, like 1000 tokens)
|
|
490
491
|
/**
|
|
491
492
|
* Current LLM model in use. Can be 'openai' (default) or 'gemini' or 'multi'. More to be added.
|
|
492
493
|
* @type {("openai"|"gemini"|"multi")}
|
|
493
494
|
* @default 'openai'
|
|
494
495
|
* @memberof LLMSettings
|
|
495
496
|
*/
|
|
496
|
-
LLMModel =
|
|
497
|
+
LLMModel = 'openai';
|
|
497
498
|
/**
|
|
498
499
|
* Current LLM model in use. Can be 'openai' (default) or 'gemini' or 'claude'. More to be added.
|
|
499
500
|
* @type {("openai"|"gemini"|"claude")}
|
|
@@ -508,21 +509,21 @@ class Constants {
|
|
|
508
509
|
* @memberof LLMSettings
|
|
509
510
|
*/
|
|
510
511
|
LLMSystemMessage =
|
|
511
|
-
|
|
512
|
+
'You are a helpful assistant describing the chart to a blind person. ';
|
|
512
513
|
/**
|
|
513
514
|
* The level of skill the user has with statistical charts. Can be 'basic', 'intermediate', 'expert', or 'other'. This is passed to the LLM on the initial message to help it speak correctly to the user. If 'other' is selected, the user can provide a custom skill level.
|
|
514
515
|
* @type {("basic"|"intermediate"|"expert"|"other")}
|
|
515
516
|
* @default 'basic'
|
|
516
517
|
* @memberof LLMSettings
|
|
517
518
|
*/
|
|
518
|
-
skillLevel =
|
|
519
|
+
skillLevel = 'basic'; // basic / intermediate / expert
|
|
519
520
|
/**
|
|
520
521
|
* Custom skill level, used if the user selects 'other' as their skill level.
|
|
521
522
|
* @type {string}
|
|
522
523
|
* @default ''
|
|
523
524
|
* @memberof LLMSettings
|
|
524
525
|
*/
|
|
525
|
-
skillLevelOther =
|
|
526
|
+
skillLevelOther = ''; // custom skill level
|
|
526
527
|
/**
|
|
527
528
|
* The LLM can send the first default message containing the chart image on initialization, so when the user opens the chat window the LLM already has an initial response and is ready for a conversation.
|
|
528
529
|
* @type {boolean}
|
|
@@ -536,7 +537,7 @@ class Constants {
|
|
|
536
537
|
* @default ''
|
|
537
538
|
* @memberof LLMSettings
|
|
538
539
|
*/
|
|
539
|
-
verboseText =
|
|
540
|
+
verboseText = '';
|
|
540
541
|
/**
|
|
541
542
|
* An internal variable used to turn the waiting beep on and off.
|
|
542
543
|
* @type {number}
|
|
@@ -584,31 +585,31 @@ class Constants {
|
|
|
584
585
|
* @type {boolean}
|
|
585
586
|
* @memberof PlatformControls
|
|
586
587
|
*/
|
|
587
|
-
isMac = navigator.userAgent.toLowerCase().includes(
|
|
588
|
+
isMac = navigator.userAgent.toLowerCase().includes('mac'); // true if macOS
|
|
588
589
|
/**
|
|
589
590
|
* The control key for the user's platform. Can be 'Cmd' or 'Ctrl'. Used in keyboard shortcut display in help.
|
|
590
591
|
* @type {"Cmd"|"Ctrl"}
|
|
591
592
|
* @memberof PlatformControls
|
|
592
593
|
*/
|
|
593
|
-
control = this.isMac ?
|
|
594
|
+
control = this.isMac ? 'Cmd' : 'Ctrl';
|
|
594
595
|
/**
|
|
595
596
|
* The alt key for the user's platform. Can be 'option' or 'Alt'. Used in keyboard shortcut display in help.
|
|
596
597
|
* @type {"option"|"Alt"}
|
|
597
598
|
* @memberof PlatformControls
|
|
598
599
|
*/
|
|
599
|
-
alt = this.isMac ?
|
|
600
|
+
alt = this.isMac ? 'option' : 'Alt';
|
|
600
601
|
/**
|
|
601
602
|
* The home key for the user's platform. Can be 'fn + Left arrow' or 'Home'. Used in keyboard shortcut display in help.
|
|
602
603
|
* @type {"fn + Left arrow"|"Home"}
|
|
603
604
|
* @memberof PlatformControls
|
|
604
605
|
*/
|
|
605
|
-
home = this.isMac ?
|
|
606
|
+
home = this.isMac ? 'fn + Left arrow' : 'Home';
|
|
606
607
|
/**
|
|
607
608
|
* The end key for the user's platform. Can be 'fn + Right arrow' or 'End'. Used in keyboard shortcut display in help.
|
|
608
609
|
* @type {"fn + Right arrow"|"End"}
|
|
609
610
|
* @memberof PlatformControls
|
|
610
611
|
*/
|
|
611
|
-
end = this.isMac ?
|
|
612
|
+
end = this.isMac ? 'fn + Right arrow' : 'End';
|
|
612
613
|
/**
|
|
613
614
|
* The interval we wait for an L + X prefix event
|
|
614
615
|
*/
|
|
@@ -644,6 +645,15 @@ class Constants {
|
|
|
644
645
|
*/
|
|
645
646
|
manualData = true; // pull from manual data like chart2music (true), or do the old method where we pull from the chart (false)
|
|
646
647
|
|
|
648
|
+
/**
|
|
649
|
+
* Base URL for the API calls to backend services.
|
|
650
|
+
*/
|
|
651
|
+
baseURL = 'https://maidr-service.azurewebsites.net/api/';
|
|
652
|
+
|
|
653
|
+
code = '?code=I8Aa2PlPspjQ8Hks0QzGyszP8_i2-XJ3bq7Xh8-ykEe4AzFuYn_QWA%3D%3D';
|
|
654
|
+
|
|
655
|
+
clientToken = null;
|
|
656
|
+
|
|
647
657
|
/**
|
|
648
658
|
* Stops the autoplay if it is currently running.
|
|
649
659
|
*
|
|
@@ -704,13 +714,13 @@ class Constants {
|
|
|
704
714
|
*/
|
|
705
715
|
ConvertHexToRGBString(hexColorString) {
|
|
706
716
|
return (
|
|
707
|
-
|
|
717
|
+
'rgb(' +
|
|
708
718
|
parseInt(hexColorString.slice(1, 3), 16) +
|
|
709
|
-
|
|
719
|
+
',' +
|
|
710
720
|
parseInt(hexColorString.slice(3, 5), 16) +
|
|
711
|
-
|
|
721
|
+
',' +
|
|
712
722
|
parseInt(hexColorString.slice(5, 7), 16) +
|
|
713
|
-
|
|
723
|
+
')'
|
|
714
724
|
);
|
|
715
725
|
}
|
|
716
726
|
|
|
@@ -720,12 +730,12 @@ class Constants {
|
|
|
720
730
|
* @returns {string} - hexadecimal color (e.g., "#595959").
|
|
721
731
|
*/
|
|
722
732
|
ConvertRGBStringToHex(rgbColorString) {
|
|
723
|
-
let rgb = rgbColorString.replace(/[^\d,]/g,
|
|
733
|
+
let rgb = rgbColorString.replace(/[^\d,]/g, '').split(',');
|
|
724
734
|
return (
|
|
725
|
-
|
|
726
|
-
rgb[0].toString(16).padStart(2,
|
|
727
|
-
rgb[1].toString(16).padStart(2,
|
|
728
|
-
rgb[2].toString(16).padStart(2,
|
|
735
|
+
'#' +
|
|
736
|
+
rgb[0].toString(16).padStart(2, '0') +
|
|
737
|
+
rgb[1].toString(16).padStart(2, '0') +
|
|
738
|
+
rgb[2].toString(16).padStart(2, '0')
|
|
729
739
|
);
|
|
730
740
|
}
|
|
731
741
|
|
|
@@ -737,11 +747,11 @@ class Constants {
|
|
|
737
747
|
*/
|
|
738
748
|
ColorInvert(color) {
|
|
739
749
|
// invert an rgb color
|
|
740
|
-
let rgb = color.replace(/[^\d,]/g,
|
|
750
|
+
let rgb = color.replace(/[^\d,]/g, '').split(',');
|
|
741
751
|
let r = 255 - rgb[0];
|
|
742
752
|
let g = 255 - rgb[1];
|
|
743
753
|
let b = 255 - rgb[2];
|
|
744
|
-
return
|
|
754
|
+
return 'rgb(' + r + ',' + g + ',' + b + ')';
|
|
745
755
|
}
|
|
746
756
|
|
|
747
757
|
/**
|
|
@@ -750,11 +760,11 @@ class Constants {
|
|
|
750
760
|
* @returns {string} The better color
|
|
751
761
|
*/
|
|
752
762
|
GetBetterColor(oldColor) {
|
|
753
|
-
if (oldColor.indexOf(
|
|
763
|
+
if (oldColor.indexOf('#') !== -1) {
|
|
754
764
|
oldColor = this.ConvertHexToRGBString(oldColor);
|
|
755
765
|
}
|
|
756
766
|
let newColor = this.ColorInvert(oldColor);
|
|
757
|
-
let rgb = newColor.replace(/[^\d,]/g,
|
|
767
|
+
let rgb = newColor.replace(/[^\d,]/g, '').split(',');
|
|
758
768
|
if (
|
|
759
769
|
rgb[1] < rgb[0] + 10 &&
|
|
760
770
|
rgb[1] > rgb[0] - 10 &&
|
|
@@ -776,7 +786,7 @@ class Constants {
|
|
|
776
786
|
*/
|
|
777
787
|
GetStyleArrayFromString(styleString) {
|
|
778
788
|
// Get an array of CSS style attributes and values from a style string
|
|
779
|
-
return styleString.replaceAll(
|
|
789
|
+
return styleString.replaceAll(' ', '').split(/[:;]/);
|
|
780
790
|
}
|
|
781
791
|
|
|
782
792
|
/**
|
|
@@ -786,16 +796,16 @@ class Constants {
|
|
|
786
796
|
*/
|
|
787
797
|
GetStyleStringFromArray(styleArray) {
|
|
788
798
|
// Get CSS style string from an array of style attributes and values
|
|
789
|
-
let styleString =
|
|
799
|
+
let styleString = '';
|
|
790
800
|
for (let i = 0; i < styleArray.length; i++) {
|
|
791
801
|
if (i % 2 === 0) {
|
|
792
802
|
if (i !== styleArray.length - 1) {
|
|
793
|
-
styleString += styleArray[i] +
|
|
803
|
+
styleString += styleArray[i] + ': ';
|
|
794
804
|
} else {
|
|
795
805
|
styleString += styleArray[i];
|
|
796
806
|
}
|
|
797
807
|
} else {
|
|
798
|
-
styleString += styleArray[i] +
|
|
808
|
+
styleString += styleArray[i] + '; ';
|
|
799
809
|
}
|
|
800
810
|
}
|
|
801
811
|
return styleString;
|
|
@@ -808,36 +818,36 @@ class Constants {
|
|
|
808
818
|
class Resources {
|
|
809
819
|
constructor() {}
|
|
810
820
|
|
|
811
|
-
language =
|
|
812
|
-
knowledgeLevel =
|
|
821
|
+
language = 'en'; // Current language, 2 char lang code
|
|
822
|
+
knowledgeLevel = 'basic'; // basic, intermediate, expert
|
|
813
823
|
|
|
814
824
|
// language strings, per 2 char language code
|
|
815
825
|
strings = {
|
|
816
826
|
en: {
|
|
817
827
|
basic: {
|
|
818
|
-
upper_outlier:
|
|
819
|
-
lower_outlier:
|
|
820
|
-
min:
|
|
821
|
-
max:
|
|
822
|
-
25:
|
|
823
|
-
50:
|
|
824
|
-
75:
|
|
825
|
-
q1:
|
|
826
|
-
q2:
|
|
827
|
-
q3:
|
|
828
|
-
son_on:
|
|
829
|
-
son_off:
|
|
830
|
-
son_des:
|
|
831
|
-
son_comp:
|
|
832
|
-
son_ch:
|
|
833
|
-
son_sep:
|
|
834
|
-
son_same:
|
|
835
|
-
empty:
|
|
836
|
-
openai:
|
|
837
|
-
gemini:
|
|
838
|
-
claude:
|
|
839
|
-
multi:
|
|
840
|
-
processing:
|
|
828
|
+
upper_outlier: 'Upper Outlier',
|
|
829
|
+
lower_outlier: 'Lower Outlier',
|
|
830
|
+
min: 'Minimum',
|
|
831
|
+
max: 'Maximum',
|
|
832
|
+
25: '25%',
|
|
833
|
+
50: '50%',
|
|
834
|
+
75: '75%',
|
|
835
|
+
q1: '25%',
|
|
836
|
+
q2: '50%',
|
|
837
|
+
q3: '75%',
|
|
838
|
+
son_on: 'Sonification on',
|
|
839
|
+
son_off: 'Sonification off',
|
|
840
|
+
son_des: 'Sonification descrete',
|
|
841
|
+
son_comp: 'Sonification compare',
|
|
842
|
+
son_ch: 'Sonification chord',
|
|
843
|
+
son_sep: 'Sonification separate',
|
|
844
|
+
son_same: 'Sonification combined',
|
|
845
|
+
empty: 'Empty',
|
|
846
|
+
openai: 'OpenAI Vision',
|
|
847
|
+
gemini: 'Gemini Pro Vision',
|
|
848
|
+
claude: 'Claude',
|
|
849
|
+
multi: 'Multiple AI',
|
|
850
|
+
processing: 'Processing Chart...',
|
|
841
851
|
},
|
|
842
852
|
},
|
|
843
853
|
};
|
|
@@ -1007,12 +1017,12 @@ class Menu {
|
|
|
1007
1017
|
<div><fieldset>
|
|
1008
1018
|
<legend>Aria Mode</legend>
|
|
1009
1019
|
<p><input type="radio" id="aria_mode_assertive" name="aria_mode" value="assertive" ${
|
|
1010
|
-
constants.ariaMode ==
|
|
1011
|
-
?
|
|
1012
|
-
:
|
|
1020
|
+
constants.ariaMode == 'assertive'
|
|
1021
|
+
? 'checked'
|
|
1022
|
+
: ''
|
|
1013
1023
|
}><label for="aria_mode_assertive">Assertive</label></p>
|
|
1014
1024
|
<p><input type="radio" id="aria_mode_polite" name="aria_mode" value="polite" ${
|
|
1015
|
-
constants.ariaMode ==
|
|
1025
|
+
constants.ariaMode == 'polite' ? 'checked' : ''
|
|
1016
1026
|
}><label for="aria_mode_polite">Polite</label></p>
|
|
1017
1027
|
</fieldset></div>
|
|
1018
1028
|
<p class="hidden">
|
|
@@ -1051,7 +1061,7 @@ class Menu {
|
|
|
1051
1061
|
<input type="password" size="50" id="claude_auth_key"><button aria-label="Delete Claude key" title="Delete Claude key" id="delete_claude_key" class="invis_button">×</button><label for="claude_auth_key">Claude Authentication Key</label>
|
|
1052
1062
|
</p>
|
|
1053
1063
|
<p><input type="checkbox" ${
|
|
1054
|
-
constants.autoInitLLM ?
|
|
1064
|
+
constants.autoInitLLM ? 'checked' : ''
|
|
1055
1065
|
} id="init_llm_on_load" name="init_llm_on_load"><label for="init_llm_on_load">Start LLM right away</label></p>
|
|
1056
1066
|
<p>
|
|
1057
1067
|
<select id="skill_level">
|
|
@@ -1088,40 +1098,40 @@ class Menu {
|
|
|
1088
1098
|
CreateMenu() {
|
|
1089
1099
|
// menu element creation
|
|
1090
1100
|
document
|
|
1091
|
-
.querySelector(
|
|
1092
|
-
.insertAdjacentHTML(
|
|
1101
|
+
.querySelector('body')
|
|
1102
|
+
.insertAdjacentHTML('beforeend', this.menuHtml);
|
|
1093
1103
|
|
|
1094
1104
|
// menu close events
|
|
1095
|
-
let allClose = document.querySelectorAll(
|
|
1105
|
+
let allClose = document.querySelectorAll('#close_menu, #menu .close');
|
|
1096
1106
|
for (let i = 0; i < allClose.length; i++) {
|
|
1097
1107
|
constants.events.push([
|
|
1098
1108
|
allClose[i],
|
|
1099
|
-
|
|
1109
|
+
'click',
|
|
1100
1110
|
function (e) {
|
|
1101
1111
|
menu.Toggle(false);
|
|
1102
1112
|
},
|
|
1103
1113
|
]);
|
|
1104
1114
|
}
|
|
1105
1115
|
constants.events.push([
|
|
1106
|
-
document.getElementById(
|
|
1107
|
-
|
|
1116
|
+
document.getElementById('save_and_close_menu'),
|
|
1117
|
+
'click',
|
|
1108
1118
|
function (e) {
|
|
1109
1119
|
menu.SaveData();
|
|
1110
1120
|
menu.Toggle(false);
|
|
1111
1121
|
},
|
|
1112
1122
|
]);
|
|
1113
1123
|
constants.events.push([
|
|
1114
|
-
document.getElementById(
|
|
1115
|
-
|
|
1124
|
+
document.getElementById('verify'),
|
|
1125
|
+
'click',
|
|
1116
1126
|
function (e) {
|
|
1117
1127
|
menu.VerifyEmail();
|
|
1118
1128
|
},
|
|
1119
1129
|
]);
|
|
1120
1130
|
constants.events.push([
|
|
1121
|
-
document.getElementById(
|
|
1122
|
-
|
|
1131
|
+
document.getElementById('menu'),
|
|
1132
|
+
'keyup',
|
|
1123
1133
|
function (e) {
|
|
1124
|
-
if (e.key ==
|
|
1134
|
+
if (e.key == 'Esc') {
|
|
1125
1135
|
// esc
|
|
1126
1136
|
menu.Toggle(false);
|
|
1127
1137
|
}
|
|
@@ -1131,15 +1141,15 @@ class Menu {
|
|
|
1131
1141
|
// Menu open events
|
|
1132
1142
|
constants.events.push([
|
|
1133
1143
|
document,
|
|
1134
|
-
|
|
1144
|
+
'keyup',
|
|
1135
1145
|
function (e) {
|
|
1136
1146
|
// don't fire on input elements
|
|
1137
1147
|
if (
|
|
1138
|
-
e.target.tagName.toLowerCase() ==
|
|
1139
|
-
e.target.tagName.toLowerCase() ==
|
|
1148
|
+
e.target.tagName.toLowerCase() == 'input' ||
|
|
1149
|
+
e.target.tagName.toLowerCase() == 'textarea'
|
|
1140
1150
|
) {
|
|
1141
1151
|
return;
|
|
1142
|
-
} else if (e.key ==
|
|
1152
|
+
} else if (e.key == 'h') {
|
|
1143
1153
|
menu.Toggle(true);
|
|
1144
1154
|
}
|
|
1145
1155
|
},
|
|
@@ -1147,119 +1157,150 @@ class Menu {
|
|
|
1147
1157
|
|
|
1148
1158
|
// toggle auth key fields
|
|
1149
1159
|
constants.events.push([
|
|
1150
|
-
document.getElementById(
|
|
1151
|
-
|
|
1160
|
+
document.getElementById('LLM_model'),
|
|
1161
|
+
'change',
|
|
1152
1162
|
function (e) {
|
|
1153
|
-
if (e.target.value ==
|
|
1163
|
+
if (e.target.value == 'openai') {
|
|
1154
1164
|
document
|
|
1155
|
-
.getElementById(
|
|
1156
|
-
.classList.remove(
|
|
1165
|
+
.getElementById('openai_auth_key_container')
|
|
1166
|
+
.classList.remove('hidden');
|
|
1157
1167
|
document
|
|
1158
|
-
.getElementById(
|
|
1159
|
-
.classList.add(
|
|
1168
|
+
.getElementById('gemini_auth_key_container')
|
|
1169
|
+
.classList.add('hidden');
|
|
1160
1170
|
document
|
|
1161
|
-
.getElementById(
|
|
1162
|
-
.classList.add(
|
|
1171
|
+
.getElementById('openai_multi_container')
|
|
1172
|
+
.classList.add('hidden');
|
|
1163
1173
|
document
|
|
1164
|
-
.getElementById(
|
|
1165
|
-
.classList.add(
|
|
1166
|
-
document.getElementById(
|
|
1167
|
-
document.getElementById(
|
|
1168
|
-
} else if (e.target.value ==
|
|
1174
|
+
.getElementById('gemini_multi_container')
|
|
1175
|
+
.classList.add('hidden');
|
|
1176
|
+
document.getElementById('openai_multi').checked = true;
|
|
1177
|
+
document.getElementById('gemini_multi').checked = false;
|
|
1178
|
+
} else if (e.target.value == 'gemini') {
|
|
1169
1179
|
document
|
|
1170
|
-
.getElementById(
|
|
1171
|
-
.classList.add(
|
|
1180
|
+
.getElementById('openai_auth_key_container')
|
|
1181
|
+
.classList.add('hidden');
|
|
1172
1182
|
document
|
|
1173
|
-
.getElementById(
|
|
1174
|
-
.classList.remove(
|
|
1183
|
+
.getElementById('gemini_auth_key_container')
|
|
1184
|
+
.classList.remove('hidden');
|
|
1175
1185
|
document
|
|
1176
|
-
.getElementById(
|
|
1177
|
-
.classList.add(
|
|
1186
|
+
.getElementById('openai_multi_container')
|
|
1187
|
+
.classList.add('hidden');
|
|
1178
1188
|
document
|
|
1179
|
-
.getElementById(
|
|
1180
|
-
.classList.add(
|
|
1181
|
-
document.getElementById(
|
|
1182
|
-
document.getElementById(
|
|
1183
|
-
} else if (e.target.value ==
|
|
1189
|
+
.getElementById('gemini_multi_container')
|
|
1190
|
+
.classList.add('hidden');
|
|
1191
|
+
document.getElementById('openai_multi').checked = false;
|
|
1192
|
+
document.getElementById('gemini_multi').checked = true;
|
|
1193
|
+
} else if (e.target.value == 'multi') {
|
|
1184
1194
|
document
|
|
1185
|
-
.getElementById(
|
|
1186
|
-
.classList.remove(
|
|
1195
|
+
.getElementById('openai_auth_key_container')
|
|
1196
|
+
.classList.remove('hidden');
|
|
1187
1197
|
document
|
|
1188
|
-
.getElementById(
|
|
1189
|
-
.classList.remove(
|
|
1198
|
+
.getElementById('gemini_auth_key_container')
|
|
1199
|
+
.classList.remove('hidden');
|
|
1190
1200
|
document
|
|
1191
|
-
.getElementById(
|
|
1192
|
-
.classList.remove(
|
|
1201
|
+
.getElementById('openai_multi_container')
|
|
1202
|
+
.classList.remove('hidden');
|
|
1193
1203
|
document
|
|
1194
|
-
.getElementById(
|
|
1195
|
-
.classList.remove(
|
|
1196
|
-
document.getElementById(
|
|
1197
|
-
document.getElementById(
|
|
1204
|
+
.getElementById('gemini_multi_container')
|
|
1205
|
+
.classList.remove('hidden');
|
|
1206
|
+
document.getElementById('openai_multi').checked = true;
|
|
1207
|
+
document.getElementById('gemini_multi').checked = true;
|
|
1198
1208
|
}
|
|
1199
1209
|
},
|
|
1200
1210
|
]);
|
|
1201
1211
|
|
|
1202
1212
|
constants.events.push([
|
|
1203
|
-
document.getElementById(
|
|
1204
|
-
|
|
1213
|
+
document.getElementById('LLM_model_openai'),
|
|
1214
|
+
'change',
|
|
1205
1215
|
function (e) {
|
|
1206
|
-
if (
|
|
1207
|
-
|
|
1208
|
-
.getElementById("openai_auth_key_container")
|
|
1209
|
-
.classList.remove("hidden");
|
|
1216
|
+
if (constants.clientToken && constants.emailAuthKey) {
|
|
1217
|
+
console.log('Client token and email auth key already set');
|
|
1210
1218
|
} else {
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1219
|
+
if (e.target.checked) {
|
|
1220
|
+
document
|
|
1221
|
+
.getElementById('openai_auth_key_container')
|
|
1222
|
+
.classList.remove('hidden');
|
|
1223
|
+
} else {
|
|
1224
|
+
document
|
|
1225
|
+
.getElementById('openai_auth_key_container')
|
|
1226
|
+
.classList.add('hidden');
|
|
1227
|
+
}
|
|
1214
1228
|
}
|
|
1215
1229
|
},
|
|
1216
1230
|
]);
|
|
1217
1231
|
|
|
1218
1232
|
constants.events.push([
|
|
1219
|
-
document.getElementById(
|
|
1220
|
-
|
|
1233
|
+
document.getElementById('LLM_model_gemini'),
|
|
1234
|
+
'change',
|
|
1221
1235
|
function (e) {
|
|
1222
|
-
if (
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1236
|
+
if (constants.clientToken && constants.emailAuthKey) {
|
|
1237
|
+
console.log('Client token and email auth key already set');
|
|
1238
|
+
} else {
|
|
1239
|
+
if (e.target.checked) {
|
|
1240
|
+
document
|
|
1241
|
+
.getElementById('gemini_auth_key_container')
|
|
1242
|
+
.classList.remove('hidden');
|
|
1243
|
+
} else {
|
|
1244
|
+
document
|
|
1245
|
+
.getElementById('gemini_auth_key_container')
|
|
1246
|
+
.classList.add('hidden');
|
|
1247
|
+
}
|
|
1248
|
+
}
|
|
1249
|
+
},
|
|
1250
|
+
]);
|
|
1251
|
+
|
|
1252
|
+
constants.events.push([
|
|
1253
|
+
document.getElementById('LLM_model_claude'),
|
|
1254
|
+
'change',
|
|
1255
|
+
function (e) {
|
|
1256
|
+
if (constants.clientToken && constants.emailAuthKey) {
|
|
1257
|
+
console.log('Client token and email auth key already set');
|
|
1226
1258
|
} else {
|
|
1227
1259
|
document
|
|
1228
|
-
.getElementById(
|
|
1229
|
-
.classList.add(
|
|
1260
|
+
.getElementById('claude_auth_key_container')
|
|
1261
|
+
.classList.add('hidden');
|
|
1230
1262
|
}
|
|
1231
1263
|
},
|
|
1232
1264
|
]);
|
|
1233
1265
|
|
|
1234
1266
|
constants.events.push([
|
|
1235
|
-
document
|
|
1236
|
-
|
|
1267
|
+
document
|
|
1268
|
+
.getElementById('email_auth_key')
|
|
1269
|
+
.addEventListener('keydown', function (event) {
|
|
1270
|
+
if (event.key === 'Enter') {
|
|
1271
|
+
document.getElementById('verify').click();
|
|
1272
|
+
}
|
|
1273
|
+
}),
|
|
1274
|
+
]);
|
|
1275
|
+
|
|
1276
|
+
// if email_auth_key has a value, show the delete button
|
|
1277
|
+
constants.events.push([
|
|
1278
|
+
document.getElementById('email_auth_key'),
|
|
1279
|
+
'input',
|
|
1237
1280
|
function (e) {
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
// .classList.add('hidden');
|
|
1246
|
-
// }
|
|
1281
|
+
if (e.target.value) {
|
|
1282
|
+
document
|
|
1283
|
+
.getElementById('delete_email_key')
|
|
1284
|
+
.classList.remove('hidden');
|
|
1285
|
+
} else {
|
|
1286
|
+
document.getElementById('delete_email_key').classList.add('hidden');
|
|
1287
|
+
}
|
|
1247
1288
|
},
|
|
1248
1289
|
]);
|
|
1249
1290
|
|
|
1250
1291
|
// Skill level other events
|
|
1251
1292
|
constants.events.push([
|
|
1252
|
-
document.getElementById(
|
|
1253
|
-
|
|
1293
|
+
document.getElementById('skill_level'),
|
|
1294
|
+
'change',
|
|
1254
1295
|
function (e) {
|
|
1255
|
-
if (e.target.value ==
|
|
1296
|
+
if (e.target.value == 'other') {
|
|
1256
1297
|
document
|
|
1257
|
-
.getElementById(
|
|
1258
|
-
.classList.remove(
|
|
1298
|
+
.getElementById('skill_level_other_container')
|
|
1299
|
+
.classList.remove('hidden');
|
|
1259
1300
|
} else {
|
|
1260
1301
|
document
|
|
1261
|
-
.getElementById(
|
|
1262
|
-
.classList.add(
|
|
1302
|
+
.getElementById('skill_level_other_container')
|
|
1303
|
+
.classList.add('hidden');
|
|
1263
1304
|
}
|
|
1264
1305
|
},
|
|
1265
1306
|
]);
|
|
@@ -1267,16 +1308,16 @@ class Menu {
|
|
|
1267
1308
|
// trigger notification that LLM will be reset
|
|
1268
1309
|
// this is done on change of LLM model, multi settings, or skill level
|
|
1269
1310
|
let LLMResetIds = [
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1311
|
+
'LLM_model',
|
|
1312
|
+
'openai_multi',
|
|
1313
|
+
'gemini_multi',
|
|
1314
|
+
'skill_level',
|
|
1315
|
+
'LLM_preferences',
|
|
1275
1316
|
];
|
|
1276
1317
|
for (let i = 0; i < LLMResetIds.length; i++) {
|
|
1277
1318
|
constants.events.push([
|
|
1278
1319
|
document.getElementById(LLMResetIds[i]),
|
|
1279
|
-
|
|
1320
|
+
'change',
|
|
1280
1321
|
function (e) {
|
|
1281
1322
|
menu.NotifyOfLLMReset();
|
|
1282
1323
|
},
|
|
@@ -1286,13 +1327,16 @@ class Menu {
|
|
|
1286
1327
|
// Limit selections to 2 AI models
|
|
1287
1328
|
const llmCheckboxes = document.querySelectorAll('input[name="LLM_model"]');
|
|
1288
1329
|
llmCheckboxes.forEach((checkbox) => {
|
|
1289
|
-
checkbox.addEventListener(
|
|
1330
|
+
checkbox.addEventListener('change', () => {
|
|
1290
1331
|
const checked = document.querySelectorAll(
|
|
1291
1332
|
'input[name="LLM_model"]:checked'
|
|
1292
1333
|
);
|
|
1293
1334
|
if (checked.length > 2) {
|
|
1294
1335
|
checkbox.checked = false;
|
|
1295
|
-
alert(
|
|
1336
|
+
alert('You can select up to 2 AI models.');
|
|
1337
|
+
} else if (checked.length === 0) {
|
|
1338
|
+
checkbox.checked = true;
|
|
1339
|
+
alert('You must select at least one AI model.');
|
|
1296
1340
|
}
|
|
1297
1341
|
});
|
|
1298
1342
|
});
|
|
@@ -1304,11 +1348,11 @@ class Menu {
|
|
|
1304
1348
|
*/
|
|
1305
1349
|
Destroy() {
|
|
1306
1350
|
// menu element destruction
|
|
1307
|
-
let menu = document.getElementById(
|
|
1351
|
+
let menu = document.getElementById('menu');
|
|
1308
1352
|
if (menu) {
|
|
1309
1353
|
menu.remove();
|
|
1310
1354
|
}
|
|
1311
|
-
let backdrop = document.getElementById(
|
|
1355
|
+
let backdrop = document.getElementById('menu_modal_backdrop');
|
|
1312
1356
|
if (backdrop) {
|
|
1313
1357
|
backdrop.remove();
|
|
1314
1358
|
}
|
|
@@ -1320,16 +1364,16 @@ class Menu {
|
|
|
1320
1364
|
* @return {void}
|
|
1321
1365
|
*/
|
|
1322
1366
|
Toggle(onoff = false) {
|
|
1323
|
-
if (typeof onoff ==
|
|
1324
|
-
if (document.getElementById(
|
|
1367
|
+
if (typeof onoff == 'undefined') {
|
|
1368
|
+
if (document.getElementById('menu').classList.contains('hidden')) {
|
|
1325
1369
|
onoff = true;
|
|
1326
1370
|
} else {
|
|
1327
1371
|
onoff = false;
|
|
1328
1372
|
}
|
|
1329
1373
|
}
|
|
1330
1374
|
// don't open if we have another modal open already
|
|
1331
|
-
if (onoff && document.getElementById(
|
|
1332
|
-
if (!document.getElementById(
|
|
1375
|
+
if (onoff && document.getElementById('chatLLM')) {
|
|
1376
|
+
if (!document.getElementById('chatLLM').classList.contains('hidden')) {
|
|
1333
1377
|
return;
|
|
1334
1378
|
}
|
|
1335
1379
|
}
|
|
@@ -1338,13 +1382,13 @@ class Menu {
|
|
|
1338
1382
|
this.whereWasMyFocus = document.activeElement;
|
|
1339
1383
|
this.PopulateData();
|
|
1340
1384
|
constants.tabMovement = 0;
|
|
1341
|
-
document.getElementById(
|
|
1342
|
-
document.getElementById(
|
|
1343
|
-
document.querySelector(
|
|
1385
|
+
document.getElementById('menu').classList.remove('hidden');
|
|
1386
|
+
document.getElementById('menu_modal_backdrop').classList.remove('hidden');
|
|
1387
|
+
document.querySelector('#menu .close').focus();
|
|
1344
1388
|
} else {
|
|
1345
1389
|
// close
|
|
1346
|
-
document.getElementById(
|
|
1347
|
-
document.getElementById(
|
|
1390
|
+
document.getElementById('menu').classList.add('hidden');
|
|
1391
|
+
document.getElementById('menu_modal_backdrop').classList.add('hidden');
|
|
1348
1392
|
this.whereWasMyFocus.focus();
|
|
1349
1393
|
this.whereWasMyFocus = null;
|
|
1350
1394
|
}
|
|
@@ -1355,68 +1399,73 @@ class Menu {
|
|
|
1355
1399
|
* @return {void}
|
|
1356
1400
|
*/
|
|
1357
1401
|
PopulateData() {
|
|
1358
|
-
document.getElementById(
|
|
1359
|
-
document.getElementById(
|
|
1402
|
+
document.getElementById('vol').value = constants.vol;
|
|
1403
|
+
document.getElementById('braille_display_length').value =
|
|
1360
1404
|
constants.brailleDisplayLength;
|
|
1361
|
-
document.getElementById(
|
|
1362
|
-
document.getElementById(
|
|
1363
|
-
document.getElementById(
|
|
1364
|
-
document.getElementById(
|
|
1405
|
+
document.getElementById('color_selected').value = constants.colorSelected;
|
|
1406
|
+
document.getElementById('min_freq').value = constants.MIN_FREQUENCY;
|
|
1407
|
+
document.getElementById('max_freq').value = constants.MAX_FREQUENCY;
|
|
1408
|
+
document.getElementById('AUTOPLAY_DURATION').value =
|
|
1365
1409
|
constants.AUTOPLAY_DURATION;
|
|
1366
|
-
if (typeof constants.openAIAuthKey ==
|
|
1367
|
-
document.getElementById(
|
|
1410
|
+
if (typeof constants.openAIAuthKey == 'string') {
|
|
1411
|
+
document.getElementById('openai_auth_key').value =
|
|
1368
1412
|
constants.openAIAuthKey;
|
|
1369
1413
|
}
|
|
1370
|
-
if (typeof constants.emailAuthKey ==
|
|
1371
|
-
document.getElementById(
|
|
1414
|
+
if (typeof constants.emailAuthKey == 'string') {
|
|
1415
|
+
document.getElementById('email_auth_key').value = constants.emailAuthKey;
|
|
1372
1416
|
}
|
|
1373
|
-
if (typeof constants.geminiAuthKey ==
|
|
1374
|
-
document.getElementById(
|
|
1417
|
+
if (typeof constants.geminiAuthKey == 'string') {
|
|
1418
|
+
document.getElementById('gemini_auth_key').value =
|
|
1375
1419
|
constants.geminiAuthKey;
|
|
1376
1420
|
}
|
|
1377
|
-
if (typeof constants.claudeAuthKey ==
|
|
1378
|
-
document.getElementById(
|
|
1421
|
+
if (typeof constants.claudeAuthKey == 'string') {
|
|
1422
|
+
document.getElementById('claude_auth_key').value =
|
|
1379
1423
|
constants.claudeAuthKey;
|
|
1380
1424
|
}
|
|
1381
|
-
document.getElementById(
|
|
1425
|
+
document.getElementById('skill_level').value = constants.skillLevel;
|
|
1382
1426
|
if (constants.skillLevelOther) {
|
|
1383
|
-
document.getElementById(
|
|
1427
|
+
document.getElementById('skill_level_other').value =
|
|
1384
1428
|
constants.skillLevelOther;
|
|
1385
1429
|
}
|
|
1386
1430
|
|
|
1387
1431
|
// aria mode
|
|
1388
|
-
if (constants.ariaMode ==
|
|
1389
|
-
document.getElementById(
|
|
1390
|
-
document.getElementById(
|
|
1432
|
+
if (constants.ariaMode == 'assertive') {
|
|
1433
|
+
document.getElementById('aria_mode_assertive').checked = true;
|
|
1434
|
+
document.getElementById('aria_mode_polite').checked = false;
|
|
1391
1435
|
} else {
|
|
1392
|
-
document.getElementById(
|
|
1393
|
-
document.getElementById(
|
|
1436
|
+
document.getElementById('aria_mode_polite').checked = true;
|
|
1437
|
+
document.getElementById('aria_mode_assertive').checked = false;
|
|
1394
1438
|
}
|
|
1395
1439
|
|
|
1396
|
-
|
|
1397
|
-
|
|
1440
|
+
if (constants.emailAuthKey && constants.clientToken) {
|
|
1441
|
+
console.log('email auth key and client token found');
|
|
1442
|
+
this.DisableLLMAPIKeys();
|
|
1443
|
+
} else {
|
|
1444
|
+
for (let model in constants.LLMModels) {
|
|
1445
|
+
document.getElementById(`LLM_model_${model}`).checked = true;
|
|
1398
1446
|
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1447
|
+
document
|
|
1448
|
+
.getElementById(`${model}_auth_key_container`)
|
|
1449
|
+
.classList.remove('hidden');
|
|
1450
|
+
}
|
|
1402
1451
|
}
|
|
1403
1452
|
document
|
|
1404
1453
|
.getElementById(`claude_auth_key_container`)
|
|
1405
|
-
.classList.add(
|
|
1454
|
+
.classList.add('hidden');
|
|
1406
1455
|
|
|
1407
1456
|
// skill level other
|
|
1408
|
-
if (constants.skillLevel ==
|
|
1457
|
+
if (constants.skillLevel == 'other') {
|
|
1409
1458
|
document
|
|
1410
|
-
.getElementById(
|
|
1411
|
-
.classList.remove(
|
|
1459
|
+
.getElementById('skill_level_other_container')
|
|
1460
|
+
.classList.remove('hidden');
|
|
1412
1461
|
}
|
|
1413
1462
|
// LLM preferences
|
|
1414
1463
|
if (constants.LLMPreferences) {
|
|
1415
|
-
document.getElementById(
|
|
1464
|
+
document.getElementById('LLM_preferences').value =
|
|
1416
1465
|
constants.LLMPreferences;
|
|
1417
1466
|
}
|
|
1418
|
-
if (document.getElementById(
|
|
1419
|
-
document.getElementById(
|
|
1467
|
+
if (document.getElementById('LLM_reset_notification')) {
|
|
1468
|
+
document.getElementById('LLM_reset_notification').remove();
|
|
1420
1469
|
}
|
|
1421
1470
|
}
|
|
1422
1471
|
|
|
@@ -1427,23 +1476,23 @@ class Menu {
|
|
|
1427
1476
|
SaveData() {
|
|
1428
1477
|
let shouldReset = this.ShouldLLMReset();
|
|
1429
1478
|
|
|
1430
|
-
constants.vol = document.getElementById(
|
|
1479
|
+
constants.vol = document.getElementById('vol').value;
|
|
1431
1480
|
constants.brailleDisplayLength = document.getElementById(
|
|
1432
|
-
|
|
1481
|
+
'braille_display_length'
|
|
1433
1482
|
).value;
|
|
1434
|
-
constants.colorSelected = document.getElementById(
|
|
1435
|
-
constants.MIN_FREQUENCY = document.getElementById(
|
|
1436
|
-
constants.MAX_FREQUENCY = document.getElementById(
|
|
1483
|
+
constants.colorSelected = document.getElementById('color_selected').value;
|
|
1484
|
+
constants.MIN_FREQUENCY = document.getElementById('min_freq').value;
|
|
1485
|
+
constants.MAX_FREQUENCY = document.getElementById('max_freq').value;
|
|
1437
1486
|
constants.AUTOPLAY_DURATION =
|
|
1438
|
-
document.getElementById(
|
|
1487
|
+
document.getElementById('AUTOPLAY_DURATION').value;
|
|
1439
1488
|
|
|
1440
|
-
constants.openAIAuthKey = document.getElementById(
|
|
1441
|
-
constants.geminiAuthKey = document.getElementById(
|
|
1442
|
-
constants.claudeAuthKey = document.getElementById(
|
|
1443
|
-
constants.emailAuthKey = document.getElementById(
|
|
1444
|
-
constants.skillLevel = document.getElementById(
|
|
1489
|
+
constants.openAIAuthKey = document.getElementById('openai_auth_key').value;
|
|
1490
|
+
constants.geminiAuthKey = document.getElementById('gemini_auth_key').value;
|
|
1491
|
+
constants.claudeAuthKey = document.getElementById('claude_auth_key').value;
|
|
1492
|
+
constants.emailAuthKey = document.getElementById('email_auth_key').value;
|
|
1493
|
+
constants.skillLevel = document.getElementById('skill_level').value;
|
|
1445
1494
|
constants.skillLevelOther =
|
|
1446
|
-
document.getElementById(
|
|
1495
|
+
document.getElementById('skill_level_other').value;
|
|
1447
1496
|
// constants.LLMModel = document.getElementById('LLM_model').value;
|
|
1448
1497
|
|
|
1449
1498
|
const llmCheckboxes = document.querySelectorAll('input[name="LLM_model"]');
|
|
@@ -1455,16 +1504,16 @@ class Menu {
|
|
|
1455
1504
|
}
|
|
1456
1505
|
});
|
|
1457
1506
|
|
|
1458
|
-
constants.LLMPreferences = document.getElementById(
|
|
1459
|
-
constants.LLMOpenAiMulti = document.getElementById(
|
|
1460
|
-
constants.LLMGeminiMulti = document.getElementById(
|
|
1461
|
-
constants.autoInitLLM = document.getElementById(
|
|
1507
|
+
constants.LLMPreferences = document.getElementById('LLM_preferences').value;
|
|
1508
|
+
constants.LLMOpenAiMulti = document.getElementById('openai_multi').checked;
|
|
1509
|
+
constants.LLMGeminiMulti = document.getElementById('gemini_multi').checked;
|
|
1510
|
+
constants.autoInitLLM = document.getElementById('init_llm_on_load').checked;
|
|
1462
1511
|
|
|
1463
1512
|
// aria
|
|
1464
|
-
if (document.getElementById(
|
|
1465
|
-
constants.ariaMode =
|
|
1466
|
-
} else if (document.getElementById(
|
|
1467
|
-
constants.ariaMode =
|
|
1513
|
+
if (document.getElementById('aria_mode_assertive').checked) {
|
|
1514
|
+
constants.ariaMode = 'assertive';
|
|
1515
|
+
} else if (document.getElementById('aria_mode_polite').checked) {
|
|
1516
|
+
constants.ariaMode = 'polite';
|
|
1468
1517
|
}
|
|
1469
1518
|
|
|
1470
1519
|
this.SaveDataToLocalStorage();
|
|
@@ -1477,38 +1526,66 @@ class Menu {
|
|
|
1477
1526
|
}
|
|
1478
1527
|
}
|
|
1479
1528
|
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
if (email && email.indexOf("@") !== -1) {
|
|
1483
|
-
let url = `https://maidr-service.azurewebsites.net/api/send_email?code=I8Aa2PlPspjQ8Hks0QzGyszP8_i2-XJ3bq7Xh8-ykEe4AzFuYn_QWA%3D%3D`;
|
|
1529
|
+
DisableLLMAPIKeys() {
|
|
1530
|
+
document.getElementById('email_auth_key').disabled = true;
|
|
1484
1531
|
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1532
|
+
// hide verify button
|
|
1533
|
+
document.getElementById('verify').classList.add('hidden');
|
|
1534
|
+
}
|
|
1488
1535
|
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
.
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1536
|
+
isEmailTriggered = false;
|
|
1537
|
+
|
|
1538
|
+
VerifyEmail() {
|
|
1539
|
+
console.log('verify email');
|
|
1540
|
+
if (!this.isEmailTriggered) {
|
|
1541
|
+
this.isEmailTriggered = true;
|
|
1542
|
+
let email = document.getElementById('email_auth_key').value;
|
|
1543
|
+
if (email && email.indexOf('@') !== -1) {
|
|
1544
|
+
let url = constants.baseURL + `send_email` + constants.code;
|
|
1545
|
+
|
|
1546
|
+
let requestJson = {
|
|
1547
|
+
email: email,
|
|
1548
|
+
};
|
|
1549
|
+
|
|
1550
|
+
fetch(url, {
|
|
1551
|
+
method: 'POST',
|
|
1552
|
+
headers: {
|
|
1553
|
+
'Content-Type': 'application/json',
|
|
1554
|
+
Authentication: constants.emailAuthKey,
|
|
1555
|
+
},
|
|
1556
|
+
body: JSON.stringify(requestJson),
|
|
1505
1557
|
})
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1558
|
+
.then((response) => response.json())
|
|
1559
|
+
.then((data) => {
|
|
1560
|
+
if (data && data.message && data.client_token) {
|
|
1561
|
+
alert(data.message);
|
|
1562
|
+
constants.clientToken = data.client_token;
|
|
1563
|
+
|
|
1564
|
+
this.DisableLLMAPIKeys();
|
|
1565
|
+
|
|
1566
|
+
for (let model in constants.LLMModels) {
|
|
1567
|
+
document
|
|
1568
|
+
.getElementById(`${model}_auth_key_container`)
|
|
1569
|
+
.classList.add('hidden');
|
|
1570
|
+
}
|
|
1571
|
+
|
|
1572
|
+
this.SaveDataToLocalStorage();
|
|
1573
|
+
this.isEmailTriggered = false;
|
|
1574
|
+
} else {
|
|
1575
|
+
console.log(data);
|
|
1576
|
+
alert(data.data);
|
|
1577
|
+
this.isEmailTriggered = false;
|
|
1578
|
+
}
|
|
1579
|
+
})
|
|
1580
|
+
.catch((error) => {
|
|
1581
|
+
console.log(error);
|
|
1582
|
+
alert(error.data);
|
|
1583
|
+
this.isEmailTriggered = false;
|
|
1584
|
+
});
|
|
1585
|
+
} else {
|
|
1586
|
+
alert('Please enter a valid email address.');
|
|
1587
|
+
this.isEmailTriggered = false;
|
|
1588
|
+
}
|
|
1512
1589
|
}
|
|
1513
1590
|
}
|
|
1514
1591
|
|
|
@@ -1518,29 +1595,29 @@ class Menu {
|
|
|
1518
1595
|
*/
|
|
1519
1596
|
UpdateHtml() {
|
|
1520
1597
|
// set aria attributes
|
|
1521
|
-
constants.infoDiv.setAttribute(
|
|
1598
|
+
constants.infoDiv.setAttribute('aria-live', constants.ariaMode);
|
|
1522
1599
|
document
|
|
1523
1600
|
.getElementById(constants.announcement_container_id)
|
|
1524
|
-
.setAttribute(
|
|
1601
|
+
.setAttribute('aria-live', constants.ariaMode);
|
|
1525
1602
|
|
|
1526
|
-
document.getElementById(
|
|
1527
|
-
const scatter = document.getElementsByClassName(
|
|
1528
|
-
const heatmap = document.getElementById(
|
|
1529
|
-
const line = document.getElementById(
|
|
1603
|
+
document.getElementById('init_llm_on_load').checked = constants.autoInitLLM;
|
|
1604
|
+
const scatter = document.getElementsByClassName('highlight_point');
|
|
1605
|
+
const heatmap = document.getElementById('highlight_rect');
|
|
1606
|
+
const line = document.getElementById('highlight_point');
|
|
1530
1607
|
|
|
1531
1608
|
if (scatter !== null && scatter.length > 0) {
|
|
1532
1609
|
for (let i = 0; i < scatter.length; i++) {
|
|
1533
|
-
scatter[i].setAttribute(
|
|
1534
|
-
scatter[i].setAttribute(
|
|
1610
|
+
scatter[i].setAttribute('stroke', constants.colorSelected);
|
|
1611
|
+
scatter[i].setAttribute('fill', constants.colorSelected);
|
|
1535
1612
|
}
|
|
1536
1613
|
}
|
|
1537
1614
|
|
|
1538
1615
|
if (heatmap !== null) {
|
|
1539
|
-
heatmap.setAttribute(
|
|
1616
|
+
heatmap.setAttribute('stroke', constants.colorSelected);
|
|
1540
1617
|
}
|
|
1541
1618
|
|
|
1542
1619
|
if (line !== null) {
|
|
1543
|
-
line.setAttribute(
|
|
1620
|
+
line.setAttribute('stroke', constants.colorSelected);
|
|
1544
1621
|
}
|
|
1545
1622
|
}
|
|
1546
1623
|
|
|
@@ -1552,19 +1629,19 @@ class Menu {
|
|
|
1552
1629
|
let html =
|
|
1553
1630
|
'<p id="LLM_reset_notification">Note: Changes in LLM settings will reset any existing conversation.</p>';
|
|
1554
1631
|
|
|
1555
|
-
if (document.getElementById(
|
|
1556
|
-
document.getElementById(
|
|
1632
|
+
if (document.getElementById('LLM_reset_notification')) {
|
|
1633
|
+
document.getElementById('LLM_reset_notification').remove();
|
|
1557
1634
|
}
|
|
1558
1635
|
document
|
|
1559
|
-
.getElementById(
|
|
1560
|
-
.parentElement.insertAdjacentHTML(
|
|
1636
|
+
.getElementById('save_and_close_menu')
|
|
1637
|
+
.parentElement.insertAdjacentHTML('afterend', html);
|
|
1561
1638
|
|
|
1562
1639
|
// add to aria button text
|
|
1563
1640
|
document
|
|
1564
|
-
.getElementById(
|
|
1641
|
+
.getElementById('save_and_close_menu')
|
|
1565
1642
|
.setAttribute(
|
|
1566
|
-
|
|
1567
|
-
|
|
1643
|
+
'aria-labelledby',
|
|
1644
|
+
'save_and_close_text LLM_reset_notification'
|
|
1568
1645
|
);
|
|
1569
1646
|
}
|
|
1570
1647
|
/**
|
|
@@ -1576,20 +1653,20 @@ class Menu {
|
|
|
1576
1653
|
let shouldReset = false;
|
|
1577
1654
|
if (
|
|
1578
1655
|
!shouldReset &&
|
|
1579
|
-
constants.skillLevel != document.getElementById(
|
|
1656
|
+
constants.skillLevel != document.getElementById('skill_level').value
|
|
1580
1657
|
) {
|
|
1581
1658
|
shouldReset = true;
|
|
1582
1659
|
}
|
|
1583
1660
|
if (
|
|
1584
1661
|
!shouldReset &&
|
|
1585
1662
|
constants.LLMPreferences !=
|
|
1586
|
-
document.getElementById(
|
|
1663
|
+
document.getElementById('LLM_preferences').value
|
|
1587
1664
|
) {
|
|
1588
1665
|
shouldReset = true;
|
|
1589
1666
|
}
|
|
1590
1667
|
if (
|
|
1591
1668
|
!shouldReset &&
|
|
1592
|
-
constants.LLMModel != document.getElementById(
|
|
1669
|
+
constants.LLMModel != document.getElementById('LLM_model').value
|
|
1593
1670
|
) {
|
|
1594
1671
|
shouldReset = true;
|
|
1595
1672
|
}
|
|
@@ -1618,24 +1695,24 @@ class Menu {
|
|
|
1618
1695
|
data[constants.userSettingsKeys[i]] =
|
|
1619
1696
|
constants[constants.userSettingsKeys[i]];
|
|
1620
1697
|
}
|
|
1621
|
-
localStorage.setItem(
|
|
1698
|
+
localStorage.setItem('settings_data', JSON.stringify(data));
|
|
1622
1699
|
|
|
1623
1700
|
// also save to tracking if we're doing that
|
|
1624
1701
|
if (constants.canTrack) {
|
|
1625
1702
|
// but not auth keys
|
|
1626
|
-
data.openAIAuthKey =
|
|
1627
|
-
data.geminiAuthKey =
|
|
1628
|
-
data.claudeAuthKey =
|
|
1703
|
+
data.openAIAuthKey = 'hidden';
|
|
1704
|
+
data.geminiAuthKey = 'hidden';
|
|
1705
|
+
data.claudeAuthKey = 'hidden';
|
|
1629
1706
|
// and need a timestamp
|
|
1630
1707
|
data.timestamp = new Date().toISOString();
|
|
1631
|
-
tracker.SetData(
|
|
1708
|
+
tracker.SetData('settings', data);
|
|
1632
1709
|
}
|
|
1633
1710
|
}
|
|
1634
1711
|
/**
|
|
1635
1712
|
* Loads data from 'settings_data' localStorage, and updates contants variables
|
|
1636
1713
|
*/
|
|
1637
1714
|
LoadDataFromLocalStorage() {
|
|
1638
|
-
let data = JSON.parse(localStorage.getItem(
|
|
1715
|
+
let data = JSON.parse(localStorage.getItem('settings_data'));
|
|
1639
1716
|
if (data) {
|
|
1640
1717
|
for (let i = 0; i < constants.userSettingsKeys.length; i++) {
|
|
1641
1718
|
const key = constants.userSettingsKeys[i];
|
|
@@ -1663,9 +1740,9 @@ class ChatLLM {
|
|
|
1663
1740
|
if (constants.autoInitLLM) {
|
|
1664
1741
|
// only run if we have API keys set
|
|
1665
1742
|
if (
|
|
1666
|
-
(
|
|
1667
|
-
(
|
|
1668
|
-
(
|
|
1743
|
+
('gemini' in constants.LLMModels && constants.geminiAuthKey) ||
|
|
1744
|
+
('openai' in constants.LLMModels && constants.openAIAuthKey) ||
|
|
1745
|
+
('claude' in constants.LLMModels && constants.claudeAuthKey)
|
|
1669
1746
|
) {
|
|
1670
1747
|
this.InitChatMessage();
|
|
1671
1748
|
}
|
|
@@ -1718,7 +1795,7 @@ class ChatLLM {
|
|
|
1718
1795
|
</div>
|
|
1719
1796
|
<div id="chatLLM_modal_backdrop" class="modal-backdrop hidden"></div>
|
|
1720
1797
|
`;
|
|
1721
|
-
document.querySelector(
|
|
1798
|
+
document.querySelector('body').insertAdjacentHTML('beforeend', html);
|
|
1722
1799
|
}
|
|
1723
1800
|
|
|
1724
1801
|
/**
|
|
@@ -1727,21 +1804,21 @@ class ChatLLM {
|
|
|
1727
1804
|
*/
|
|
1728
1805
|
SetEvents() {
|
|
1729
1806
|
// chatLLM close events
|
|
1730
|
-
let allClose = document.querySelectorAll(
|
|
1807
|
+
let allClose = document.querySelectorAll('#close_chatLLM, #chatLLM .close');
|
|
1731
1808
|
for (let i = 0; i < allClose.length; i++) {
|
|
1732
1809
|
constants.events.push([
|
|
1733
1810
|
allClose[i],
|
|
1734
|
-
|
|
1811
|
+
'click',
|
|
1735
1812
|
function (e) {
|
|
1736
1813
|
chatLLM.Toggle(false);
|
|
1737
1814
|
},
|
|
1738
1815
|
]);
|
|
1739
1816
|
}
|
|
1740
1817
|
constants.events.push([
|
|
1741
|
-
document.getElementById(
|
|
1742
|
-
|
|
1818
|
+
document.getElementById('chatLLM'),
|
|
1819
|
+
'keyup',
|
|
1743
1820
|
function (e) {
|
|
1744
|
-
if (e.key ==
|
|
1821
|
+
if (e.key == 'Esc') {
|
|
1745
1822
|
// esc
|
|
1746
1823
|
chatLLM.Toggle(false);
|
|
1747
1824
|
}
|
|
@@ -1751,9 +1828,9 @@ class ChatLLM {
|
|
|
1751
1828
|
// ChatLLM open/close toggle
|
|
1752
1829
|
constants.events.push([
|
|
1753
1830
|
document,
|
|
1754
|
-
|
|
1831
|
+
'keyup',
|
|
1755
1832
|
function (e) {
|
|
1756
|
-
if ((e.key ==
|
|
1833
|
+
if ((e.key == '?' && (e.ctrlKey || e.metaKey)) || e.key == '¿') {
|
|
1757
1834
|
chatLLM.Toggle();
|
|
1758
1835
|
}
|
|
1759
1836
|
},
|
|
@@ -1761,21 +1838,21 @@ class ChatLLM {
|
|
|
1761
1838
|
|
|
1762
1839
|
// ChatLLM request events
|
|
1763
1840
|
constants.events.push([
|
|
1764
|
-
document.getElementById(
|
|
1765
|
-
|
|
1841
|
+
document.getElementById('chatLLM_submit'),
|
|
1842
|
+
'click',
|
|
1766
1843
|
function (e) {
|
|
1767
|
-
let text = document.getElementById(
|
|
1768
|
-
chatLLM.DisplayChatMessage(
|
|
1844
|
+
let text = document.getElementById('chatLLM_input').value;
|
|
1845
|
+
chatLLM.DisplayChatMessage('User', text);
|
|
1769
1846
|
chatLLM.Submit(text);
|
|
1770
1847
|
},
|
|
1771
1848
|
]);
|
|
1772
1849
|
constants.events.push([
|
|
1773
|
-
document.getElementById(
|
|
1774
|
-
|
|
1850
|
+
document.getElementById('chatLLM_input'),
|
|
1851
|
+
'keyup',
|
|
1775
1852
|
function (e) {
|
|
1776
|
-
if (e.key ==
|
|
1777
|
-
let text = document.getElementById(
|
|
1778
|
-
chatLLM.DisplayChatMessage(
|
|
1853
|
+
if (e.key == 'Enter' && !e.shiftKey) {
|
|
1854
|
+
let text = document.getElementById('chatLLM_input').value;
|
|
1855
|
+
chatLLM.DisplayChatMessage('User', text);
|
|
1779
1856
|
chatLLM.Submit(text);
|
|
1780
1857
|
}
|
|
1781
1858
|
},
|
|
@@ -1784,15 +1861,15 @@ class ChatLLM {
|
|
|
1784
1861
|
// ChatLLM suggestion events
|
|
1785
1862
|
// actual suggestions:
|
|
1786
1863
|
let suggestions = document.querySelectorAll(
|
|
1787
|
-
|
|
1864
|
+
'#chatLLM .LLM_suggestions button:not(#more_suggestions)'
|
|
1788
1865
|
);
|
|
1789
1866
|
for (let i = 0; i < suggestions.length; i++) {
|
|
1790
1867
|
constants.events.push([
|
|
1791
1868
|
suggestions[i],
|
|
1792
|
-
|
|
1869
|
+
'click',
|
|
1793
1870
|
function (e) {
|
|
1794
1871
|
let text = e.target.innerHTML;
|
|
1795
|
-
chatLLM.DisplayChatMessage(
|
|
1872
|
+
chatLLM.DisplayChatMessage('User', text);
|
|
1796
1873
|
chatLLM.Submit(text);
|
|
1797
1874
|
},
|
|
1798
1875
|
]);
|
|
@@ -1800,31 +1877,35 @@ class ChatLLM {
|
|
|
1800
1877
|
|
|
1801
1878
|
// Delete OpenAI and Gemini keys
|
|
1802
1879
|
constants.events.push([
|
|
1803
|
-
document.getElementById(
|
|
1804
|
-
|
|
1880
|
+
document.getElementById('delete_openai_key'),
|
|
1881
|
+
'click',
|
|
1805
1882
|
function (e) {
|
|
1806
|
-
document.getElementById(
|
|
1883
|
+
document.getElementById('openai_auth_key').value = '';
|
|
1807
1884
|
},
|
|
1808
1885
|
]);
|
|
1809
1886
|
constants.events.push([
|
|
1810
|
-
document.getElementById(
|
|
1811
|
-
|
|
1887
|
+
document.getElementById('delete_email_key'),
|
|
1888
|
+
'click',
|
|
1812
1889
|
function (e) {
|
|
1813
|
-
document.getElementById(
|
|
1890
|
+
document.getElementById('email_auth_key').value = '';
|
|
1891
|
+
document.getElementById('email_auth_key').disabled = false;
|
|
1892
|
+
document.getElementById('delete_email_key').classList.add('hidden');
|
|
1893
|
+
constants.clientToken = '';
|
|
1894
|
+
document.getElementById('verify').classList.remove('hidden');
|
|
1814
1895
|
},
|
|
1815
1896
|
]);
|
|
1816
1897
|
constants.events.push([
|
|
1817
|
-
document.getElementById(
|
|
1818
|
-
|
|
1898
|
+
document.getElementById('delete_gemini_key'),
|
|
1899
|
+
'click',
|
|
1819
1900
|
function (e) {
|
|
1820
|
-
document.getElementById(
|
|
1901
|
+
document.getElementById('gemini_auth_key').value = '';
|
|
1821
1902
|
},
|
|
1822
1903
|
]);
|
|
1823
1904
|
|
|
1824
1905
|
// Reset chatLLM
|
|
1825
1906
|
constants.events.push([
|
|
1826
|
-
document.getElementById(
|
|
1827
|
-
|
|
1907
|
+
document.getElementById('reset_chatLLM'),
|
|
1908
|
+
'click',
|
|
1828
1909
|
function (e) {
|
|
1829
1910
|
chatLLM.ResetLLM();
|
|
1830
1911
|
},
|
|
@@ -1832,15 +1913,15 @@ class ChatLLM {
|
|
|
1832
1913
|
|
|
1833
1914
|
// copy to clipboard
|
|
1834
1915
|
constants.events.push([
|
|
1835
|
-
document.getElementById(
|
|
1836
|
-
|
|
1916
|
+
document.getElementById('chatLLM'),
|
|
1917
|
+
'click',
|
|
1837
1918
|
function (e) {
|
|
1838
1919
|
chatLLM.CopyChatHistory(e);
|
|
1839
1920
|
},
|
|
1840
1921
|
]);
|
|
1841
1922
|
constants.events.push([
|
|
1842
|
-
document.getElementById(
|
|
1843
|
-
|
|
1923
|
+
document.getElementById('chatLLM'),
|
|
1924
|
+
'keyup',
|
|
1844
1925
|
function (e) {
|
|
1845
1926
|
chatLLM.CopyChatHistory(e);
|
|
1846
1927
|
},
|
|
@@ -1858,96 +1939,96 @@ class ChatLLM {
|
|
|
1858
1939
|
* @param {Event|undefined} e - The event that triggered the copy action. If undefined, the entire chat history is copied.
|
|
1859
1940
|
*/
|
|
1860
1941
|
CopyChatHistory(e) {
|
|
1861
|
-
let text =
|
|
1862
|
-
if (typeof e ==
|
|
1942
|
+
let text = '';
|
|
1943
|
+
if (typeof e == 'undefined') {
|
|
1863
1944
|
// check for passthrough
|
|
1864
1945
|
// get html of the full chat history
|
|
1865
|
-
text = document.getElementById(
|
|
1866
|
-
} else if (e.type ==
|
|
1946
|
+
text = document.getElementById('chatLLM_chat_history').innerHTML;
|
|
1947
|
+
} else if (e.type == 'click') {
|
|
1867
1948
|
// check for buttons
|
|
1868
|
-
if (e.target.id ==
|
|
1949
|
+
if (e.target.id == 'chatLLM_copy_all') {
|
|
1869
1950
|
// get html of the full chat history
|
|
1870
|
-
text = document.getElementById(
|
|
1871
|
-
} else if (e.target.classList.contains(
|
|
1951
|
+
text = document.getElementById('chatLLM_chat_history').innerHTML;
|
|
1952
|
+
} else if (e.target.classList.contains('chatLLM_message_copy_button')) {
|
|
1872
1953
|
// get the text of the element before the button
|
|
1873
|
-
text = e.target.closest(
|
|
1954
|
+
text = e.target.closest('p').previousElementSibling.innerHTML;
|
|
1874
1955
|
}
|
|
1875
|
-
} else if (e.type ==
|
|
1956
|
+
} else if (e.type == 'keyup') {
|
|
1876
1957
|
// check for alt shift c or ctrl shift c
|
|
1877
|
-
if (e.key ==
|
|
1958
|
+
if (e.key == 'C' && (e.ctrlKey || e.metaKey || e.altKey) && e.shiftKey) {
|
|
1878
1959
|
e.preventDefault();
|
|
1879
1960
|
// get the last message
|
|
1880
1961
|
let elem = document.querySelector(
|
|
1881
|
-
|
|
1962
|
+
'#chatLLM_chat_history > .chatLLM_message_other:last-of-type'
|
|
1882
1963
|
);
|
|
1883
1964
|
if (elem) {
|
|
1884
1965
|
text = elem.innerHTML;
|
|
1885
1966
|
}
|
|
1886
1967
|
} else if (
|
|
1887
|
-
e.key ==
|
|
1968
|
+
e.key == 'A' &&
|
|
1888
1969
|
(e.ctrlKey || e.metaKey || e.altKey) &&
|
|
1889
1970
|
e.shiftKey
|
|
1890
1971
|
) {
|
|
1891
1972
|
e.preventDefault();
|
|
1892
1973
|
// get html of the full chat history
|
|
1893
|
-
text = document.getElementById(
|
|
1974
|
+
text = document.getElementById('chatLLM_chat_history').innerHTML;
|
|
1894
1975
|
}
|
|
1895
1976
|
}
|
|
1896
1977
|
|
|
1897
|
-
if (text ==
|
|
1978
|
+
if (text == '') {
|
|
1898
1979
|
return;
|
|
1899
1980
|
} else {
|
|
1900
1981
|
// clear the html, removing buttons etc
|
|
1901
|
-
let cleanElems = document.createElement(
|
|
1982
|
+
let cleanElems = document.createElement('div');
|
|
1902
1983
|
cleanElems.innerHTML = text;
|
|
1903
|
-
let removeThese = cleanElems.querySelectorAll(
|
|
1984
|
+
let removeThese = cleanElems.querySelectorAll('.chatLLM_message_copy');
|
|
1904
1985
|
removeThese.forEach((elem) => elem.remove());
|
|
1905
1986
|
|
|
1906
1987
|
// convert from html to markdown
|
|
1907
1988
|
let markdown = this.htmlToMarkdown(cleanElems);
|
|
1908
1989
|
// this messes up a bit with spacing, so kill more than 2 newlines in a row
|
|
1909
|
-
markdown = markdown.replace(/\n{3,}/g,
|
|
1990
|
+
markdown = markdown.replace(/\n{3,}/g, '\n\n');
|
|
1910
1991
|
|
|
1911
1992
|
try {
|
|
1912
1993
|
navigator.clipboard.writeText(markdown); // note: this fails if you're on the inspector. That's fine as it'll never happen to real users
|
|
1913
1994
|
} catch (err) {
|
|
1914
|
-
console.error(
|
|
1995
|
+
console.error('Failed to copy: ', err);
|
|
1915
1996
|
}
|
|
1916
1997
|
return markdown;
|
|
1917
1998
|
}
|
|
1918
1999
|
}
|
|
1919
2000
|
|
|
1920
2001
|
htmlToMarkdown(element) {
|
|
1921
|
-
let markdown =
|
|
2002
|
+
let markdown = '';
|
|
1922
2003
|
|
|
1923
2004
|
const convertElementToMarkdown = (element) => {
|
|
1924
2005
|
switch (element.tagName) {
|
|
1925
|
-
case
|
|
2006
|
+
case 'H1':
|
|
1926
2007
|
return `# ${element.textContent}`;
|
|
1927
|
-
case
|
|
2008
|
+
case 'H2':
|
|
1928
2009
|
return `## ${element.textContent}`;
|
|
1929
|
-
case
|
|
2010
|
+
case 'H3':
|
|
1930
2011
|
return `### ${element.textContent}`;
|
|
1931
|
-
case
|
|
2012
|
+
case 'H4':
|
|
1932
2013
|
return `#### ${element.textContent}`;
|
|
1933
|
-
case
|
|
2014
|
+
case 'H5':
|
|
1934
2015
|
return `##### ${element.textContent}`;
|
|
1935
|
-
case
|
|
2016
|
+
case 'H6':
|
|
1936
2017
|
return `###### ${element.textContent}`;
|
|
1937
|
-
case
|
|
2018
|
+
case 'P':
|
|
1938
2019
|
return element.textContent;
|
|
1939
|
-
case
|
|
2020
|
+
case 'DIV':
|
|
1940
2021
|
// For divs, process each child and add newlines as needed
|
|
1941
2022
|
return (
|
|
1942
2023
|
Array.from(element.childNodes)
|
|
1943
2024
|
.map((child) => convertElementToMarkdown(child))
|
|
1944
|
-
.join(
|
|
2025
|
+
.join('\n') + '\n\n'
|
|
1945
2026
|
);
|
|
1946
2027
|
default:
|
|
1947
2028
|
// For any other element, process its children recursively
|
|
1948
2029
|
return Array.from(element.childNodes)
|
|
1949
2030
|
.map((child) => convertElementToMarkdown(child))
|
|
1950
|
-
.join(
|
|
2031
|
+
.join('');
|
|
1951
2032
|
}
|
|
1952
2033
|
};
|
|
1953
2034
|
|
|
@@ -1955,7 +2036,7 @@ class ChatLLM {
|
|
|
1955
2036
|
markdown += convertElementToMarkdown(element);
|
|
1956
2037
|
} else if (
|
|
1957
2038
|
element.nodeType === Node.TEXT_NODE &&
|
|
1958
|
-
element.textContent.trim() !==
|
|
2039
|
+
element.textContent.trim() !== ''
|
|
1959
2040
|
) {
|
|
1960
2041
|
markdown += element.textContent.trim();
|
|
1961
2042
|
}
|
|
@@ -1980,14 +2061,14 @@ class ChatLLM {
|
|
|
1980
2061
|
|
|
1981
2062
|
// if this is the user's first message (or we're gemini, in which case we need to send every time), prepend prompt with user position
|
|
1982
2063
|
if (
|
|
1983
|
-
(this.firstOpen ||
|
|
2064
|
+
(this.firstOpen || 'gemini' in constants.LLMModels) &&
|
|
1984
2065
|
!firsttime &&
|
|
1985
2066
|
constants.verboseText.length > 0
|
|
1986
2067
|
) {
|
|
1987
2068
|
text =
|
|
1988
2069
|
"Here is the current position in the chart; no response necessarily needed, use this info only if it's relevant to future questions: " +
|
|
1989
2070
|
constants.verboseText +
|
|
1990
|
-
|
|
2071
|
+
'. My question is: ' +
|
|
1991
2072
|
text;
|
|
1992
2073
|
|
|
1993
2074
|
this.firstOpen = false;
|
|
@@ -1998,9 +2079,9 @@ class ChatLLM {
|
|
|
1998
2079
|
this.WaitingSound(true);
|
|
1999
2080
|
}
|
|
2000
2081
|
|
|
2001
|
-
if (
|
|
2082
|
+
if ('openai' in constants.LLMModels) {
|
|
2002
2083
|
if (firsttime) {
|
|
2003
|
-
img = await this.ConvertSVGtoJPG(singleMaidr.id,
|
|
2084
|
+
img = await this.ConvertSVGtoJPG(singleMaidr.id, 'openai');
|
|
2004
2085
|
}
|
|
2005
2086
|
if (constants.openAIAuthKey) {
|
|
2006
2087
|
chatLLM.OpenAIPrompt(text, img);
|
|
@@ -2008,9 +2089,9 @@ class ChatLLM {
|
|
|
2008
2089
|
chatLLM.OpenAIPromptAPI(text, img);
|
|
2009
2090
|
}
|
|
2010
2091
|
}
|
|
2011
|
-
if (
|
|
2092
|
+
if ('gemini' in constants.LLMModels) {
|
|
2012
2093
|
if (firsttime) {
|
|
2013
|
-
img = await this.ConvertSVGtoJPG(singleMaidr.id,
|
|
2094
|
+
img = await this.ConvertSVGtoJPG(singleMaidr.id, 'gemini');
|
|
2014
2095
|
}
|
|
2015
2096
|
if (constants.geminiAuthKey) {
|
|
2016
2097
|
chatLLM.GeminiPrompt(text, img);
|
|
@@ -2019,9 +2100,9 @@ class ChatLLM {
|
|
|
2019
2100
|
}
|
|
2020
2101
|
}
|
|
2021
2102
|
|
|
2022
|
-
if (
|
|
2103
|
+
if ('claude' in constants.LLMModels) {
|
|
2023
2104
|
if (firsttime) {
|
|
2024
|
-
img = await this.ConvertSVGtoJPG(singleMaidr.id,
|
|
2105
|
+
img = await this.ConvertSVGtoJPG(singleMaidr.id, 'claude');
|
|
2025
2106
|
}
|
|
2026
2107
|
if (constants.claudeAuthKey) {
|
|
2027
2108
|
chatLLM.ClaudePrompt(text, img);
|
|
@@ -2086,7 +2167,7 @@ class ChatLLM {
|
|
|
2086
2167
|
}, 30000);
|
|
2087
2168
|
|
|
2088
2169
|
// set queue for multi
|
|
2089
|
-
if (constants.LLMModel !=
|
|
2170
|
+
if (constants.LLMModel != 'multi') {
|
|
2090
2171
|
constants.waitingQueue = 1;
|
|
2091
2172
|
} else {
|
|
2092
2173
|
constants.waitingQueue = 0;
|
|
@@ -2118,7 +2199,7 @@ class ChatLLM {
|
|
|
2118
2199
|
// get name from resource]
|
|
2119
2200
|
let LLMName = resources.GetString(constants.LLMModel);
|
|
2120
2201
|
this.firstTime = false;
|
|
2121
|
-
this.DisplayChatMessage(LLMName, resources.GetString(
|
|
2202
|
+
this.DisplayChatMessage(LLMName, resources.GetString('processing'), true);
|
|
2122
2203
|
let defaultPrompt = this.GetDefaultPrompt();
|
|
2123
2204
|
this.Submit(defaultPrompt, true);
|
|
2124
2205
|
}
|
|
@@ -2130,47 +2211,47 @@ class ChatLLM {
|
|
|
2130
2211
|
*/
|
|
2131
2212
|
ProcessLLMResponse(data, model) {
|
|
2132
2213
|
chatLLM.WaitingSound(false);
|
|
2133
|
-
let text =
|
|
2214
|
+
let text = '';
|
|
2134
2215
|
let LLMName = resources.GetString(model);
|
|
2135
2216
|
|
|
2136
|
-
if (model ==
|
|
2217
|
+
if (model == 'openai') {
|
|
2137
2218
|
text = data.choices[0].message.content;
|
|
2138
2219
|
let i = this.requestJson.messages.length;
|
|
2139
2220
|
this.requestJson.messages[i] = {};
|
|
2140
|
-
this.requestJson.messages[i].role =
|
|
2221
|
+
this.requestJson.messages[i].role = 'assistant';
|
|
2141
2222
|
this.requestJson.messages[i].content = text;
|
|
2142
2223
|
|
|
2143
2224
|
if (data.error) {
|
|
2144
|
-
chatLLM.DisplayChatMessage(LLMName,
|
|
2225
|
+
chatLLM.DisplayChatMessage(LLMName, 'Error processing request.', true);
|
|
2145
2226
|
chatLLM.WaitingSound(false);
|
|
2146
2227
|
} else {
|
|
2147
2228
|
chatLLM.DisplayChatMessage(LLMName, text);
|
|
2148
2229
|
}
|
|
2149
|
-
} else if (model ==
|
|
2230
|
+
} else if (model == 'gemini') {
|
|
2150
2231
|
if (data.text()) {
|
|
2151
2232
|
text = data.text();
|
|
2152
2233
|
chatLLM.DisplayChatMessage(LLMName, text);
|
|
2153
2234
|
} else {
|
|
2154
2235
|
if (!data.error) {
|
|
2155
|
-
data.error =
|
|
2236
|
+
data.error = 'Error processing request.';
|
|
2156
2237
|
chatLLM.WaitingSound(false);
|
|
2157
2238
|
}
|
|
2158
2239
|
}
|
|
2159
2240
|
if (data.error) {
|
|
2160
|
-
chatLLM.DisplayChatMessage(LLMName,
|
|
2241
|
+
chatLLM.DisplayChatMessage(LLMName, 'Error processing request.', true);
|
|
2161
2242
|
chatLLM.WaitingSound(false);
|
|
2162
2243
|
} else {
|
|
2163
2244
|
// todo: display actual response
|
|
2164
2245
|
}
|
|
2165
2246
|
}
|
|
2166
|
-
if (model ==
|
|
2167
|
-
console.log(
|
|
2247
|
+
if (model == 'claude') {
|
|
2248
|
+
console.log('Claude response: ', data);
|
|
2168
2249
|
if (data.text()) {
|
|
2169
2250
|
text = data.text();
|
|
2170
2251
|
chatLLM.DisplayChatMessage(LLMName, text);
|
|
2171
2252
|
}
|
|
2172
2253
|
if (data.error) {
|
|
2173
|
-
chatLLM.DisplayChatMessage(LLMName,
|
|
2254
|
+
chatLLM.DisplayChatMessage(LLMName, 'Error processing request.', true);
|
|
2174
2255
|
chatLLM.WaitingSound(false);
|
|
2175
2256
|
}
|
|
2176
2257
|
}
|
|
@@ -2178,7 +2259,7 @@ class ChatLLM {
|
|
|
2178
2259
|
// if we're tracking, log the data
|
|
2179
2260
|
if (constants.canTrack) {
|
|
2180
2261
|
let chatHist = chatLLM.CopyChatHistory();
|
|
2181
|
-
tracker.SetData(
|
|
2262
|
+
tracker.SetData('ChatHistory', chatHist);
|
|
2182
2263
|
}
|
|
2183
2264
|
}
|
|
2184
2265
|
|
|
@@ -2192,11 +2273,11 @@ class ChatLLM {
|
|
|
2192
2273
|
if (this.requestJson.messages.length > 2) {
|
|
2193
2274
|
// subsequent responses
|
|
2194
2275
|
responseText = {
|
|
2195
|
-
id:
|
|
2196
|
-
object:
|
|
2276
|
+
id: 'chatcmpl-8Y44iRCRrohYbAqm8rfBbJqTUADC7',
|
|
2277
|
+
object: 'chat.completion',
|
|
2197
2278
|
created: 1703129508,
|
|
2198
2279
|
//model: 'gpt-4-1106-vision-preview',
|
|
2199
|
-
model:
|
|
2280
|
+
model: 'gpt4-o',
|
|
2200
2281
|
usage: {
|
|
2201
2282
|
prompt_tokens: 451,
|
|
2202
2283
|
completion_tokens: 16,
|
|
@@ -2205,10 +2286,10 @@ class ChatLLM {
|
|
|
2205
2286
|
choices: [
|
|
2206
2287
|
{
|
|
2207
2288
|
message: {
|
|
2208
|
-
role:
|
|
2209
|
-
content:
|
|
2289
|
+
role: 'assistant',
|
|
2290
|
+
content: 'A fake response from the LLM. Nice.',
|
|
2210
2291
|
},
|
|
2211
|
-
finish_reason:
|
|
2292
|
+
finish_reason: 'length',
|
|
2212
2293
|
index: 0,
|
|
2213
2294
|
},
|
|
2214
2295
|
],
|
|
@@ -2216,10 +2297,10 @@ class ChatLLM {
|
|
|
2216
2297
|
} else {
|
|
2217
2298
|
// first response
|
|
2218
2299
|
responseText = {
|
|
2219
|
-
id:
|
|
2220
|
-
object:
|
|
2300
|
+
id: 'chatcmpl-8Y44iRCRrohYbAqm8rfBbJqTUADC7',
|
|
2301
|
+
object: 'chat.completion',
|
|
2221
2302
|
created: 1703129508,
|
|
2222
|
-
model:
|
|
2303
|
+
model: 'gpt-4-1106-vision-preview',
|
|
2223
2304
|
usage: {
|
|
2224
2305
|
prompt_tokens: 451,
|
|
2225
2306
|
completion_tokens: 16,
|
|
@@ -2228,11 +2309,11 @@ class ChatLLM {
|
|
|
2228
2309
|
choices: [
|
|
2229
2310
|
{
|
|
2230
2311
|
message: {
|
|
2231
|
-
role:
|
|
2312
|
+
role: 'assistant',
|
|
2232
2313
|
content:
|
|
2233
|
-
|
|
2314
|
+
'The chart you\'re referring to is a bar graph titled "The Number of Diamonds',
|
|
2234
2315
|
},
|
|
2235
|
-
finish_reason:
|
|
2316
|
+
finish_reason: 'length',
|
|
2236
2317
|
index: 0,
|
|
2237
2318
|
},
|
|
2238
2319
|
],
|
|
@@ -2243,7 +2324,7 @@ class ChatLLM {
|
|
|
2243
2324
|
}
|
|
2244
2325
|
|
|
2245
2326
|
ClaudeJson(text, img = null) {
|
|
2246
|
-
const anthropicVersion =
|
|
2327
|
+
const anthropicVersion = 'vertex-2023-10-16';
|
|
2247
2328
|
const maxTokens = 256;
|
|
2248
2329
|
|
|
2249
2330
|
const payload = {
|
|
@@ -2254,7 +2335,7 @@ class ChatLLM {
|
|
|
2254
2335
|
|
|
2255
2336
|
// Construct the user message object
|
|
2256
2337
|
const userMessage = {
|
|
2257
|
-
role:
|
|
2338
|
+
role: 'user',
|
|
2258
2339
|
content: [],
|
|
2259
2340
|
};
|
|
2260
2341
|
|
|
@@ -2262,22 +2343,22 @@ class ChatLLM {
|
|
|
2262
2343
|
if (img) {
|
|
2263
2344
|
userMessage.content.push(
|
|
2264
2345
|
{
|
|
2265
|
-
type:
|
|
2346
|
+
type: 'image',
|
|
2266
2347
|
source: {
|
|
2267
|
-
type:
|
|
2268
|
-
media_type:
|
|
2348
|
+
type: 'base64',
|
|
2349
|
+
media_type: 'image/jpeg', // Update if other formats are supported
|
|
2269
2350
|
data: img,
|
|
2270
2351
|
},
|
|
2271
2352
|
},
|
|
2272
2353
|
{
|
|
2273
|
-
type:
|
|
2354
|
+
type: 'text',
|
|
2274
2355
|
text: text,
|
|
2275
2356
|
}
|
|
2276
2357
|
);
|
|
2277
2358
|
} else {
|
|
2278
2359
|
// Add only the text content if no image is provided
|
|
2279
2360
|
userMessage.content.push({
|
|
2280
|
-
type:
|
|
2361
|
+
type: 'text',
|
|
2281
2362
|
text: text,
|
|
2282
2363
|
});
|
|
2283
2364
|
}
|
|
@@ -2289,16 +2370,15 @@ class ChatLLM {
|
|
|
2289
2370
|
}
|
|
2290
2371
|
|
|
2291
2372
|
ClaudePromptAPI(text, imgBase64 = null) {
|
|
2292
|
-
console.log(
|
|
2293
|
-
let url =
|
|
2294
|
-
"https://maidr-service.azurewebsites.net/api/claude?code=I8Aa2PlPspjQ8Hks0QzGyszP8_i2-XJ3bq7Xh8-ykEe4AzFuYn_QWA%3D%3D";
|
|
2373
|
+
console.log('Claude prompt API');
|
|
2374
|
+
let url = constants.baseURL + 'claude' + constants.code;
|
|
2295
2375
|
|
|
2296
2376
|
// Create the prompt
|
|
2297
2377
|
let prompt = constants.LLMSystemMessage;
|
|
2298
2378
|
if (constants.LLMPreferences) {
|
|
2299
2379
|
prompt += constants.LLMPreferences;
|
|
2300
2380
|
}
|
|
2301
|
-
prompt +=
|
|
2381
|
+
prompt += '\n\n' + text; // Use the text parameter as the prompt
|
|
2302
2382
|
|
|
2303
2383
|
if (imgBase64 == null) {
|
|
2304
2384
|
imgBase64 = constants.LLMImage;
|
|
@@ -2310,10 +2390,10 @@ class ChatLLM {
|
|
|
2310
2390
|
let requestJson = chatLLM.ClaudeJson(prompt, imgBase64);
|
|
2311
2391
|
|
|
2312
2392
|
fetch(url, {
|
|
2313
|
-
method:
|
|
2393
|
+
method: 'POST',
|
|
2314
2394
|
headers: {
|
|
2315
|
-
|
|
2316
|
-
Authentication: constants.emailAuthKey,
|
|
2395
|
+
'Content-Type': 'application/json',
|
|
2396
|
+
Authentication: constants.emailAuthKey + ' ' + constants.clientToken,
|
|
2317
2397
|
},
|
|
2318
2398
|
body: JSON.stringify(requestJson),
|
|
2319
2399
|
})
|
|
@@ -2322,12 +2402,12 @@ class ChatLLM {
|
|
|
2322
2402
|
data.text = function () {
|
|
2323
2403
|
return data.content[0].text;
|
|
2324
2404
|
};
|
|
2325
|
-
chatLLM.ProcessLLMResponse(data,
|
|
2405
|
+
chatLLM.ProcessLLMResponse(data, 'claude');
|
|
2326
2406
|
})
|
|
2327
2407
|
.catch((error) => {
|
|
2328
2408
|
chatLLM.WaitingSound(false);
|
|
2329
|
-
console.error(
|
|
2330
|
-
chatLLM.DisplayChatMessage(
|
|
2409
|
+
console.error('Error:', error);
|
|
2410
|
+
chatLLM.DisplayChatMessage('Claude', 'Error processing request.', true);
|
|
2331
2411
|
// also todo: handle errors somehow
|
|
2332
2412
|
});
|
|
2333
2413
|
}
|
|
@@ -2341,55 +2421,53 @@ class ChatLLM {
|
|
|
2341
2421
|
*/
|
|
2342
2422
|
OpenAIPrompt(text, img = null) {
|
|
2343
2423
|
// request init
|
|
2344
|
-
let url =
|
|
2424
|
+
let url = 'https://api.openai.com/v1/chat/completions';
|
|
2345
2425
|
let auth = constants.openAIAuthKey;
|
|
2346
2426
|
let requestJson = chatLLM.OpenAIJson(text, img);
|
|
2347
2427
|
//console.log('LLM request: ', requestJson);
|
|
2348
2428
|
|
|
2349
2429
|
fetch(url, {
|
|
2350
|
-
method:
|
|
2430
|
+
method: 'POST',
|
|
2351
2431
|
headers: {
|
|
2352
|
-
|
|
2353
|
-
Authorization:
|
|
2432
|
+
'Content-Type': 'application/json',
|
|
2433
|
+
Authorization: 'Bearer ' + auth,
|
|
2354
2434
|
},
|
|
2355
2435
|
body: JSON.stringify(requestJson),
|
|
2356
2436
|
})
|
|
2357
2437
|
.then((response) => response.json())
|
|
2358
2438
|
.then((data) => {
|
|
2359
|
-
chatLLM.ProcessLLMResponse(data,
|
|
2439
|
+
chatLLM.ProcessLLMResponse(data, 'openai');
|
|
2360
2440
|
})
|
|
2361
2441
|
.catch((error) => {
|
|
2362
2442
|
chatLLM.WaitingSound(false);
|
|
2363
|
-
console.error(
|
|
2364
|
-
chatLLM.DisplayChatMessage(
|
|
2443
|
+
console.error('Error:', error);
|
|
2444
|
+
chatLLM.DisplayChatMessage('OpenAI', 'Error processing request.', true);
|
|
2365
2445
|
// also todo: handle errors somehow
|
|
2366
2446
|
});
|
|
2367
2447
|
}
|
|
2368
2448
|
|
|
2369
2449
|
OpenAIPromptAPI(text, img = null) {
|
|
2370
2450
|
// request init
|
|
2371
|
-
let url =
|
|
2372
|
-
"https://maidr-service.azurewebsites.net/api/openai?code=I8Aa2PlPspjQ8Hks0QzGyszP8_i2-XJ3bq7Xh8-ykEe4AzFuYn_QWA%3D%3D";
|
|
2451
|
+
let url = constants.baseURL + 'openai' + constants.code;
|
|
2373
2452
|
let auth = constants.openAIAuthKey;
|
|
2374
2453
|
let requestJson = chatLLM.OpenAIJson(text, img);
|
|
2375
|
-
console.log("LLM request: ", requestJson);
|
|
2376
2454
|
|
|
2377
2455
|
fetch(url, {
|
|
2378
|
-
method:
|
|
2456
|
+
method: 'POST',
|
|
2379
2457
|
headers: {
|
|
2380
|
-
|
|
2381
|
-
Authentication: constants.emailAuthKey,
|
|
2458
|
+
'Content-Type': 'application/json',
|
|
2459
|
+
Authentication: constants.emailAuthKey + ' ' + constants.clientToken,
|
|
2382
2460
|
},
|
|
2383
2461
|
body: JSON.stringify(requestJson),
|
|
2384
2462
|
})
|
|
2385
2463
|
.then((response) => response.json())
|
|
2386
2464
|
.then((data) => {
|
|
2387
|
-
chatLLM.ProcessLLMResponse(data,
|
|
2465
|
+
chatLLM.ProcessLLMResponse(data, 'openai');
|
|
2388
2466
|
})
|
|
2389
2467
|
.catch((error) => {
|
|
2390
2468
|
chatLLM.WaitingSound(false);
|
|
2391
|
-
console.error(
|
|
2392
|
-
chatLLM.DisplayChatMessage(
|
|
2469
|
+
console.error('Error:', error);
|
|
2470
|
+
chatLLM.DisplayChatMessage('OpenAI', 'Error processing request.', true);
|
|
2393
2471
|
// also todo: handle errors somehow
|
|
2394
2472
|
});
|
|
2395
2473
|
}
|
|
@@ -2397,22 +2475,22 @@ class ChatLLM {
|
|
|
2397
2475
|
OpenAIJson(text, img = null) {
|
|
2398
2476
|
let sysMessage = constants.LLMSystemMessage;
|
|
2399
2477
|
let backupMessage =
|
|
2400
|
-
|
|
2478
|
+
'Describe ' + singleMaidr.type + ' charts to a blind person';
|
|
2401
2479
|
// headers and sys message
|
|
2402
2480
|
if (!this.requestJson) {
|
|
2403
2481
|
this.requestJson = {};
|
|
2404
2482
|
//this.requestJson.model = 'gpt-4-vision-preview';
|
|
2405
|
-
this.requestJson.model =
|
|
2483
|
+
this.requestJson.model = 'gpt-4o-2024-11-20';
|
|
2406
2484
|
this.requestJson.max_tokens = constants.LLMmaxResponseTokens; // note: if this is too short (tested with less than 200), the response gets cut off
|
|
2407
2485
|
|
|
2408
2486
|
// sys message
|
|
2409
2487
|
this.requestJson.messages = [];
|
|
2410
2488
|
this.requestJson.messages[0] = {};
|
|
2411
|
-
this.requestJson.messages[0].role =
|
|
2489
|
+
this.requestJson.messages[0].role = 'system';
|
|
2412
2490
|
this.requestJson.messages[0].content = sysMessage;
|
|
2413
2491
|
if (constants.LLMPreferences) {
|
|
2414
2492
|
this.requestJson.messages[1] = {};
|
|
2415
|
-
this.requestJson.messages[1].role =
|
|
2493
|
+
this.requestJson.messages[1].role = 'system';
|
|
2416
2494
|
this.requestJson.messages[1].content = constants.LLMPreferences;
|
|
2417
2495
|
}
|
|
2418
2496
|
}
|
|
@@ -2421,16 +2499,16 @@ class ChatLLM {
|
|
|
2421
2499
|
// if we have an image (first time only), send the image and the text, otherwise just the text
|
|
2422
2500
|
let i = this.requestJson.messages.length;
|
|
2423
2501
|
this.requestJson.messages[i] = {};
|
|
2424
|
-
this.requestJson.messages[i].role =
|
|
2502
|
+
this.requestJson.messages[i].role = 'user';
|
|
2425
2503
|
if (img) {
|
|
2426
2504
|
// first message, include the img
|
|
2427
2505
|
this.requestJson.messages[i].content = [
|
|
2428
2506
|
{
|
|
2429
|
-
type:
|
|
2507
|
+
type: 'text',
|
|
2430
2508
|
text: text,
|
|
2431
2509
|
},
|
|
2432
2510
|
{
|
|
2433
|
-
type:
|
|
2511
|
+
type: 'image_url',
|
|
2434
2512
|
image_url: { url: img },
|
|
2435
2513
|
},
|
|
2436
2514
|
];
|
|
@@ -2445,7 +2523,7 @@ class ChatLLM {
|
|
|
2445
2523
|
GeminiJson(text, img = null) {
|
|
2446
2524
|
let sysMessage = constants.LLMSystemMessage;
|
|
2447
2525
|
let backupMessage =
|
|
2448
|
-
|
|
2526
|
+
'Describe ' + singleMaidr.type + ' charts to a blind person';
|
|
2449
2527
|
|
|
2450
2528
|
let payload = {
|
|
2451
2529
|
generationConfig: {},
|
|
@@ -2455,7 +2533,7 @@ class ChatLLM {
|
|
|
2455
2533
|
|
|
2456
2534
|
// System message as the initial "role" and "text" content for context
|
|
2457
2535
|
let sysContent = {
|
|
2458
|
-
role:
|
|
2536
|
+
role: 'user',
|
|
2459
2537
|
parts: [
|
|
2460
2538
|
{
|
|
2461
2539
|
text: sysMessage || backupMessage, // Fallback if sysMessage is unavailable
|
|
@@ -2474,7 +2552,7 @@ class ChatLLM {
|
|
|
2474
2552
|
|
|
2475
2553
|
// Add user input content, including image if available
|
|
2476
2554
|
let userContent = {
|
|
2477
|
-
role:
|
|
2555
|
+
role: 'user',
|
|
2478
2556
|
parts: [],
|
|
2479
2557
|
};
|
|
2480
2558
|
|
|
@@ -2487,7 +2565,7 @@ class ChatLLM {
|
|
|
2487
2565
|
{
|
|
2488
2566
|
inlineData: {
|
|
2489
2567
|
data: img, // Expecting base64-encoded image data
|
|
2490
|
-
mimeType:
|
|
2568
|
+
mimeType: 'image/png', // Adjust if different image formats are possible
|
|
2491
2569
|
},
|
|
2492
2570
|
}
|
|
2493
2571
|
);
|
|
@@ -2505,15 +2583,14 @@ class ChatLLM {
|
|
|
2505
2583
|
}
|
|
2506
2584
|
|
|
2507
2585
|
async GeminiPromptAPI(text, imgBase64 = null) {
|
|
2508
|
-
let url =
|
|
2509
|
-
"https://maidr-service.azurewebsites.net/api/gemini?code=I8Aa2PlPspjQ8Hks0QzGyszP8_i2-XJ3bq7Xh8-ykEe4AzFuYn_QWA%3D%3D";
|
|
2586
|
+
let url = constants.baseURL + 'gemini' + constants.code;
|
|
2510
2587
|
|
|
2511
2588
|
// Create the prompt
|
|
2512
2589
|
let prompt = constants.LLMSystemMessage;
|
|
2513
2590
|
if (constants.LLMPreferences) {
|
|
2514
2591
|
prompt += constants.LLMPreferences;
|
|
2515
2592
|
}
|
|
2516
|
-
prompt +=
|
|
2593
|
+
prompt += '\n\n' + text; // Use the text parameter as the prompt
|
|
2517
2594
|
|
|
2518
2595
|
if (imgBase64 == null) {
|
|
2519
2596
|
imgBase64 = constants.LLMImage;
|
|
@@ -2525,10 +2602,10 @@ class ChatLLM {
|
|
|
2525
2602
|
let requestJson = chatLLM.GeminiJson(prompt, imgBase64);
|
|
2526
2603
|
|
|
2527
2604
|
const response = await fetch(url, {
|
|
2528
|
-
method:
|
|
2605
|
+
method: 'POST',
|
|
2529
2606
|
headers: {
|
|
2530
|
-
|
|
2531
|
-
Authentication: constants.emailAuthKey,
|
|
2607
|
+
'Content-Type': 'application/json',
|
|
2608
|
+
Authentication: constants.emailAuthKey + ' ' + constants.clientToken,
|
|
2532
2609
|
},
|
|
2533
2610
|
body: JSON.stringify(requestJson),
|
|
2534
2611
|
});
|
|
@@ -2537,11 +2614,11 @@ class ChatLLM {
|
|
|
2537
2614
|
responseJson.text = () => {
|
|
2538
2615
|
return responseJson.candidates[0].content.parts[0].text;
|
|
2539
2616
|
};
|
|
2540
|
-
chatLLM.ProcessLLMResponse(responseJson,
|
|
2617
|
+
chatLLM.ProcessLLMResponse(responseJson, 'gemini');
|
|
2541
2618
|
} else {
|
|
2542
2619
|
chatLLM.WaitingSound(false);
|
|
2543
|
-
console.error(
|
|
2544
|
-
chatLLM.DisplayChatMessage(
|
|
2620
|
+
console.error('Error:', error);
|
|
2621
|
+
chatLLM.DisplayChatMessage('OpenAI', 'Error processing request.', true);
|
|
2545
2622
|
// also todo: handle errors somehow
|
|
2546
2623
|
}
|
|
2547
2624
|
}
|
|
@@ -2559,12 +2636,12 @@ class ChatLLM {
|
|
|
2559
2636
|
|
|
2560
2637
|
// Import the module
|
|
2561
2638
|
const { GoogleGenerativeAI } = await import(
|
|
2562
|
-
|
|
2639
|
+
'https://esm.run/@google/generative-ai'
|
|
2563
2640
|
);
|
|
2564
2641
|
const API_KEY = constants.geminiAuthKey;
|
|
2565
2642
|
const genAI = new GoogleGenerativeAI(API_KEY);
|
|
2566
2643
|
const model = genAI.getGenerativeModel({
|
|
2567
|
-
model:
|
|
2644
|
+
model: 'gemini-1.5-pro-latest',
|
|
2568
2645
|
}); // old model was 'gemini-pro-vision'
|
|
2569
2646
|
|
|
2570
2647
|
// Create the prompt
|
|
@@ -2572,11 +2649,11 @@ class ChatLLM {
|
|
|
2572
2649
|
if (constants.LLMPreferences) {
|
|
2573
2650
|
prompt += constants.LLMPreferences;
|
|
2574
2651
|
}
|
|
2575
|
-
prompt +=
|
|
2652
|
+
prompt += '\n\n' + text; // Use the text parameter as the prompt
|
|
2576
2653
|
const image = {
|
|
2577
2654
|
inlineData: {
|
|
2578
2655
|
data: imgBase64, // Use the base64 image string
|
|
2579
|
-
mimeType:
|
|
2656
|
+
mimeType: 'image/png', // Or the appropriate mime type of your image
|
|
2580
2657
|
},
|
|
2581
2658
|
};
|
|
2582
2659
|
|
|
@@ -2586,11 +2663,11 @@ class ChatLLM {
|
|
|
2586
2663
|
//console.log(result.response.text());
|
|
2587
2664
|
|
|
2588
2665
|
// Process the response
|
|
2589
|
-
chatLLM.ProcessLLMResponse(result.response,
|
|
2666
|
+
chatLLM.ProcessLLMResponse(result.response, 'gemini');
|
|
2590
2667
|
} catch (error) {
|
|
2591
2668
|
chatLLM.WaitingSound(false);
|
|
2592
|
-
chatLLM.DisplayChatMessage(
|
|
2593
|
-
console.error(
|
|
2669
|
+
chatLLM.DisplayChatMessage('Gemini', 'Error processing request.', true);
|
|
2670
|
+
console.error('Error in GeminiPrompt:', error);
|
|
2594
2671
|
throw error; // Rethrow the error for further handling if necessary
|
|
2595
2672
|
}
|
|
2596
2673
|
}
|
|
@@ -2602,11 +2679,11 @@ class ChatLLM {
|
|
|
2602
2679
|
* @memberof module:constants
|
|
2603
2680
|
* @returns {void}
|
|
2604
2681
|
*/
|
|
2605
|
-
DisplayChatMessage(user =
|
|
2606
|
-
let hLevel =
|
|
2607
|
-
if (!isSystem && constants.LLMModel ==
|
|
2682
|
+
DisplayChatMessage(user = 'User', text = '', isSystem = false) {
|
|
2683
|
+
let hLevel = 'h3';
|
|
2684
|
+
if (!isSystem && constants.LLMModel == 'multi' && user != 'User') {
|
|
2608
2685
|
if (this.firstMulti) {
|
|
2609
|
-
let multiAIName = resources.GetString(
|
|
2686
|
+
let multiAIName = resources.GetString('multi');
|
|
2610
2687
|
let titleHtml = `
|
|
2611
2688
|
<div class="chatLLM_message chatLLM_message_other">
|
|
2612
2689
|
<h3 class="chatLLM_message_user">${multiAIName} Responses</h3>
|
|
@@ -2615,20 +2692,20 @@ class ChatLLM {
|
|
|
2615
2692
|
this.RenderChatMessage(titleHtml);
|
|
2616
2693
|
this.firstMulti = false;
|
|
2617
2694
|
}
|
|
2618
|
-
hLevel =
|
|
2695
|
+
hLevel = 'h4';
|
|
2619
2696
|
}
|
|
2620
2697
|
let html = `
|
|
2621
2698
|
<div class="chatLLM_message ${
|
|
2622
|
-
user ==
|
|
2699
|
+
user == 'User' ? 'chatLLM_message_self' : 'chatLLM_message_other'
|
|
2623
2700
|
}">`;
|
|
2624
|
-
if (text != resources.GetString(
|
|
2701
|
+
if (text != resources.GetString('processing')) {
|
|
2625
2702
|
html += `<${hLevel} class="chatLLM_message_user">${user}</${hLevel}>`;
|
|
2626
2703
|
}
|
|
2627
2704
|
html += `<p class="chatLLM_message_text">${text}</p>
|
|
2628
2705
|
</div>
|
|
2629
2706
|
`;
|
|
2630
2707
|
// add a copy button to actual messages
|
|
2631
|
-
if (user !=
|
|
2708
|
+
if (user != 'User' && text != resources.GetString('processing')) {
|
|
2632
2709
|
html += `
|
|
2633
2710
|
<p class="chatLLM_message_copy"><button class="chatLLM_message_copy_button">Copy</button></p>
|
|
2634
2711
|
`;
|
|
@@ -2638,13 +2715,13 @@ class ChatLLM {
|
|
|
2638
2715
|
}
|
|
2639
2716
|
RenderChatMessage(html) {
|
|
2640
2717
|
document
|
|
2641
|
-
.getElementById(
|
|
2642
|
-
.insertAdjacentHTML(
|
|
2643
|
-
document.getElementById(
|
|
2718
|
+
.getElementById('chatLLM_chat_history')
|
|
2719
|
+
.insertAdjacentHTML('beforeend', html);
|
|
2720
|
+
document.getElementById('chatLLM_input').value = '';
|
|
2644
2721
|
|
|
2645
2722
|
// scroll to bottom
|
|
2646
|
-
document.getElementById(
|
|
2647
|
-
document.getElementById(
|
|
2723
|
+
document.getElementById('chatLLM_chat_history').scrollTop =
|
|
2724
|
+
document.getElementById('chatLLM_chat_history').scrollHeight;
|
|
2648
2725
|
}
|
|
2649
2726
|
|
|
2650
2727
|
/**
|
|
@@ -2652,7 +2729,7 @@ class ChatLLM {
|
|
|
2652
2729
|
*/
|
|
2653
2730
|
ResetLLM() {
|
|
2654
2731
|
// clear the main chat history
|
|
2655
|
-
document.getElementById(
|
|
2732
|
+
document.getElementById('chatLLM_chat_history').innerHTML = '';
|
|
2656
2733
|
|
|
2657
2734
|
// reset the data
|
|
2658
2735
|
this.requestJson = null;
|
|
@@ -2673,11 +2750,11 @@ class ChatLLM {
|
|
|
2673
2750
|
*/
|
|
2674
2751
|
Destroy() {
|
|
2675
2752
|
// chatLLM element destruction
|
|
2676
|
-
let chatLLM = document.getElementById(
|
|
2753
|
+
let chatLLM = document.getElementById('chatLLM');
|
|
2677
2754
|
if (chatLLM) {
|
|
2678
2755
|
chatLLM.remove();
|
|
2679
2756
|
}
|
|
2680
|
-
let backdrop = document.getElementById(
|
|
2757
|
+
let backdrop = document.getElementById('chatLLM_modal_backdrop');
|
|
2681
2758
|
if (backdrop) {
|
|
2682
2759
|
backdrop.remove();
|
|
2683
2760
|
}
|
|
@@ -2688,8 +2765,8 @@ class ChatLLM {
|
|
|
2688
2765
|
* @param {boolean} [onoff=false] - Whether to turn the chatLLM on or off. Defaults to false (close).
|
|
2689
2766
|
*/
|
|
2690
2767
|
Toggle(onoff) {
|
|
2691
|
-
if (typeof onoff ==
|
|
2692
|
-
if (document.getElementById(
|
|
2768
|
+
if (typeof onoff == 'undefined') {
|
|
2769
|
+
if (document.getElementById('chatLLM').classList.contains('hidden')) {
|
|
2693
2770
|
onoff = true;
|
|
2694
2771
|
} else {
|
|
2695
2772
|
onoff = false;
|
|
@@ -2700,19 +2777,19 @@ class ChatLLM {
|
|
|
2700
2777
|
// open
|
|
2701
2778
|
this.whereWasMyFocus = document.activeElement;
|
|
2702
2779
|
constants.tabMovement = 0;
|
|
2703
|
-
document.getElementById(
|
|
2780
|
+
document.getElementById('chatLLM').classList.remove('hidden');
|
|
2704
2781
|
document
|
|
2705
|
-
.getElementById(
|
|
2706
|
-
.classList.remove(
|
|
2707
|
-
document.querySelector(
|
|
2782
|
+
.getElementById('chatLLM_modal_backdrop')
|
|
2783
|
+
.classList.remove('hidden');
|
|
2784
|
+
document.querySelector('#chatLLM .close').focus();
|
|
2708
2785
|
|
|
2709
2786
|
if (this.firstTime) {
|
|
2710
2787
|
this.InitChatMessage();
|
|
2711
2788
|
}
|
|
2712
2789
|
} else {
|
|
2713
2790
|
// close
|
|
2714
|
-
document.getElementById(
|
|
2715
|
-
document.getElementById(
|
|
2791
|
+
document.getElementById('chatLLM').classList.add('hidden');
|
|
2792
|
+
document.getElementById('chatLLM_modal_backdrop').classList.add('hidden');
|
|
2716
2793
|
this.whereWasMyFocus.focus();
|
|
2717
2794
|
this.whereWasMyFocus = null;
|
|
2718
2795
|
this.firstOpen = true;
|
|
@@ -2726,11 +2803,11 @@ class ChatLLM {
|
|
|
2726
2803
|
async ConvertSVGtoJPG(id, model) {
|
|
2727
2804
|
let svgElement = document.getElementById(id);
|
|
2728
2805
|
return new Promise((resolve, reject) => {
|
|
2729
|
-
var canvas = document.createElement(
|
|
2730
|
-
var ctx = canvas.getContext(
|
|
2806
|
+
var canvas = document.createElement('canvas');
|
|
2807
|
+
var ctx = canvas.getContext('2d');
|
|
2731
2808
|
|
|
2732
2809
|
var svgData = new XMLSerializer().serializeToString(svgElement);
|
|
2733
|
-
if (!svgData.startsWith(
|
|
2810
|
+
if (!svgData.startsWith('<svg xmlns')) {
|
|
2734
2811
|
svgData = `<svg xmlns="http://www.w3.org/2000/svg" ${svgData.slice(4)}`;
|
|
2735
2812
|
}
|
|
2736
2813
|
|
|
@@ -2742,11 +2819,11 @@ class ChatLLM {
|
|
|
2742
2819
|
var img = new Image();
|
|
2743
2820
|
img.onload = function () {
|
|
2744
2821
|
ctx.drawImage(img, 0, 0, svgSize.width, svgSize.height);
|
|
2745
|
-
var jpegData = canvas.toDataURL(
|
|
2746
|
-
if (model ==
|
|
2822
|
+
var jpegData = canvas.toDataURL('image/jpeg', 0.9); // 0.9 is the quality parameter
|
|
2823
|
+
if (model == 'openai') {
|
|
2747
2824
|
resolve(jpegData);
|
|
2748
|
-
} else if (model ==
|
|
2749
|
-
let base64Data = jpegData.split(
|
|
2825
|
+
} else if (model == 'gemini' || model == 'claude') {
|
|
2826
|
+
let base64Data = jpegData.split(',')[1];
|
|
2750
2827
|
resolve(base64Data);
|
|
2751
2828
|
//resolve(jpegData);
|
|
2752
2829
|
}
|
|
@@ -2754,11 +2831,11 @@ class ChatLLM {
|
|
|
2754
2831
|
};
|
|
2755
2832
|
|
|
2756
2833
|
img.onerror = function () {
|
|
2757
|
-
reject(new Error(
|
|
2834
|
+
reject(new Error('Error loading SVG'));
|
|
2758
2835
|
};
|
|
2759
2836
|
|
|
2760
2837
|
var svgBlob = new Blob([svgData], {
|
|
2761
|
-
type:
|
|
2838
|
+
type: 'image/svg+xml;charset=utf-8',
|
|
2762
2839
|
});
|
|
2763
2840
|
var url = URL.createObjectURL(svgBlob);
|
|
2764
2841
|
img.src = url;
|
|
@@ -2771,25 +2848,25 @@ class ChatLLM {
|
|
|
2771
2848
|
* The prompt includes information about the blind person's skill level and the chart's image and raw data, if available.
|
|
2772
2849
|
*/
|
|
2773
2850
|
GetDefaultPrompt() {
|
|
2774
|
-
let text =
|
|
2851
|
+
let text = 'Describe this chart to a blind person';
|
|
2775
2852
|
if (constants.skillLevel) {
|
|
2776
|
-
if (constants.skillLevel ==
|
|
2853
|
+
if (constants.skillLevel == 'other' && constants.skillLevelOther) {
|
|
2777
2854
|
text +=
|
|
2778
|
-
|
|
2855
|
+
' who has a ' +
|
|
2779
2856
|
constants.skillLevelOther +
|
|
2780
|
-
|
|
2857
|
+
' understanding of statistical charts. ';
|
|
2781
2858
|
} else {
|
|
2782
2859
|
text +=
|
|
2783
|
-
|
|
2860
|
+
' who has a ' +
|
|
2784
2861
|
constants.skillLevel +
|
|
2785
|
-
|
|
2862
|
+
' understanding of statistical charts. ';
|
|
2786
2863
|
}
|
|
2787
2864
|
} else {
|
|
2788
|
-
text +=
|
|
2865
|
+
text += ' who has a basic understanding of statistical charts. ';
|
|
2789
2866
|
}
|
|
2790
|
-
text +=
|
|
2867
|
+
text += 'Here is a chart in image format';
|
|
2791
2868
|
if (singleMaidr) {
|
|
2792
|
-
text +=
|
|
2869
|
+
text += ' and raw data in json format: \n';
|
|
2793
2870
|
text += JSON.stringify(singleMaidr);
|
|
2794
2871
|
}
|
|
2795
2872
|
|
|
@@ -2844,26 +2921,26 @@ class Description {
|
|
|
2844
2921
|
|
|
2845
2922
|
`;
|
|
2846
2923
|
|
|
2847
|
-
document.querySelector(
|
|
2924
|
+
document.querySelector('body').insertAdjacentHTML('beforeend', html);
|
|
2848
2925
|
|
|
2849
2926
|
// close events
|
|
2850
2927
|
let allClose = document.querySelectorAll(
|
|
2851
|
-
|
|
2928
|
+
'#close_desc, #description .close'
|
|
2852
2929
|
);
|
|
2853
2930
|
for (let i = 0; i < allClose.length; i++) {
|
|
2854
2931
|
constants.events.push([
|
|
2855
2932
|
allClose[i],
|
|
2856
|
-
|
|
2933
|
+
'click',
|
|
2857
2934
|
function (e) {
|
|
2858
2935
|
description.Toggle(false);
|
|
2859
2936
|
},
|
|
2860
2937
|
]);
|
|
2861
2938
|
}
|
|
2862
2939
|
constants.events.push([
|
|
2863
|
-
document.getElementById(
|
|
2864
|
-
|
|
2940
|
+
document.getElementById('description'),
|
|
2941
|
+
'keyup',
|
|
2865
2942
|
function (e) {
|
|
2866
|
-
if (e.key ==
|
|
2943
|
+
if (e.key == 'Esc') {
|
|
2867
2944
|
// esc
|
|
2868
2945
|
description.Toggle(false);
|
|
2869
2946
|
}
|
|
@@ -2873,9 +2950,9 @@ class Description {
|
|
|
2873
2950
|
// open events
|
|
2874
2951
|
constants.events.push([
|
|
2875
2952
|
document,
|
|
2876
|
-
|
|
2953
|
+
'keyup',
|
|
2877
2954
|
function (e) {
|
|
2878
|
-
if (e.key ==
|
|
2955
|
+
if (e.key == 'd') {
|
|
2879
2956
|
description.Toggle(true);
|
|
2880
2957
|
}
|
|
2881
2958
|
},
|
|
@@ -2887,11 +2964,11 @@ class Description {
|
|
|
2887
2964
|
*/
|
|
2888
2965
|
Destroy() {
|
|
2889
2966
|
// description element destruction
|
|
2890
|
-
let description = document.getElementById(
|
|
2967
|
+
let description = document.getElementById('menu');
|
|
2891
2968
|
if (description) {
|
|
2892
2969
|
description.remove();
|
|
2893
2970
|
}
|
|
2894
|
-
let backdrop = document.getElementById(
|
|
2971
|
+
let backdrop = document.getElementById('desc_modal_backdrop');
|
|
2895
2972
|
if (backdrop) {
|
|
2896
2973
|
backdrop.remove();
|
|
2897
2974
|
}
|
|
@@ -2902,8 +2979,8 @@ class Description {
|
|
|
2902
2979
|
* @param {boolean} [onoff=false] - Whether to turn the description element on or off.
|
|
2903
2980
|
*/
|
|
2904
2981
|
Toggle(onoff = false) {
|
|
2905
|
-
if (typeof onoff ==
|
|
2906
|
-
if (document.getElementById(
|
|
2982
|
+
if (typeof onoff == 'undefined') {
|
|
2983
|
+
if (document.getElementById('description').classList.contains('hidden')) {
|
|
2907
2984
|
onoff = true;
|
|
2908
2985
|
} else {
|
|
2909
2986
|
onoff = false;
|
|
@@ -2914,13 +2991,13 @@ class Description {
|
|
|
2914
2991
|
this.whereWasMyFocus = document.activeElement;
|
|
2915
2992
|
constants.tabMovement = 0;
|
|
2916
2993
|
this.PopulateData();
|
|
2917
|
-
document.getElementById(
|
|
2918
|
-
document.getElementById(
|
|
2919
|
-
document.querySelector(
|
|
2994
|
+
document.getElementById('description').classList.remove('hidden');
|
|
2995
|
+
document.getElementById('desc_modal_backdrop').classList.remove('hidden');
|
|
2996
|
+
document.querySelector('#description .close').focus();
|
|
2920
2997
|
} else {
|
|
2921
2998
|
// close
|
|
2922
|
-
document.getElementById(
|
|
2923
|
-
document.getElementById(
|
|
2999
|
+
document.getElementById('description').classList.add('hidden');
|
|
3000
|
+
document.getElementById('desc_modal_backdrop').classList.add('hidden');
|
|
2924
3001
|
this.whereWasMyFocus.focus();
|
|
2925
3002
|
this.whereWasMyFocus = null;
|
|
2926
3003
|
}
|
|
@@ -2930,22 +3007,22 @@ class Description {
|
|
|
2930
3007
|
* Populates the data for the chart and table based on the chart type and plot data.
|
|
2931
3008
|
*/
|
|
2932
3009
|
PopulateData() {
|
|
2933
|
-
let descHtml =
|
|
3010
|
+
let descHtml = '';
|
|
2934
3011
|
|
|
2935
3012
|
// chart labels and descriptions
|
|
2936
|
-
let descType =
|
|
2937
|
-
if (constants.chartType ==
|
|
2938
|
-
descType =
|
|
2939
|
-
} else if (constants.chartType ==
|
|
2940
|
-
descType =
|
|
2941
|
-
} else if (constants.chartType ==
|
|
2942
|
-
descType =
|
|
2943
|
-
} else if (constants.chartType ==
|
|
2944
|
-
descType =
|
|
2945
|
-
} else if (constants.chartType ==
|
|
2946
|
-
descType =
|
|
2947
|
-
} else if (constants.chartType ==
|
|
2948
|
-
descType =
|
|
3013
|
+
let descType = '';
|
|
3014
|
+
if (constants.chartType == 'bar') {
|
|
3015
|
+
descType = 'Bar chart';
|
|
3016
|
+
} else if (constants.chartType == 'heat') {
|
|
3017
|
+
descType = 'Heatmap';
|
|
3018
|
+
} else if (constants.chartType == 'box') {
|
|
3019
|
+
descType = 'Box plot';
|
|
3020
|
+
} else if (constants.chartType == 'scatter') {
|
|
3021
|
+
descType = 'Scatter plot';
|
|
3022
|
+
} else if (constants.chartType == 'line') {
|
|
3023
|
+
descType = 'Line chart';
|
|
3024
|
+
} else if (constants.chartType == 'hist') {
|
|
3025
|
+
descType = 'Histogram';
|
|
2949
3026
|
}
|
|
2950
3027
|
|
|
2951
3028
|
if (descType) {
|
|
@@ -2962,7 +3039,7 @@ class Description {
|
|
|
2962
3039
|
}
|
|
2963
3040
|
|
|
2964
3041
|
// table of data, prep
|
|
2965
|
-
let descTableHtml =
|
|
3042
|
+
let descTableHtml = '';
|
|
2966
3043
|
let descLabelX = null;
|
|
2967
3044
|
let descLabelY = null;
|
|
2968
3045
|
let descTickX = null;
|
|
@@ -2972,7 +3049,7 @@ class Description {
|
|
|
2972
3049
|
let descNumColsWithLabels = 0;
|
|
2973
3050
|
let descNumRows = 0;
|
|
2974
3051
|
let descNumRowsWithLabels = 0;
|
|
2975
|
-
if (constants.chartType ==
|
|
3052
|
+
if (constants.chartType == 'bar') {
|
|
2976
3053
|
if (plot.plotLegend.x != null) {
|
|
2977
3054
|
descLabelX = plot.plotLegend.x;
|
|
2978
3055
|
descNumColsWithLabels += 1;
|
|
@@ -2997,43 +3074,43 @@ class Description {
|
|
|
2997
3074
|
|
|
2998
3075
|
// table of data, create
|
|
2999
3076
|
if (descData != null) {
|
|
3000
|
-
descTableHtml +=
|
|
3077
|
+
descTableHtml += '<table>';
|
|
3001
3078
|
|
|
3002
3079
|
// header rows
|
|
3003
3080
|
if (descLabelX != null || descTickX != null) {
|
|
3004
|
-
descTableHtml +=
|
|
3081
|
+
descTableHtml += '<thead>';
|
|
3005
3082
|
if (descLabelX != null) {
|
|
3006
|
-
descTableHtml +=
|
|
3083
|
+
descTableHtml += '<tr>';
|
|
3007
3084
|
if (descLabelY != null) {
|
|
3008
|
-
descTableHtml +=
|
|
3085
|
+
descTableHtml += '<td></td>';
|
|
3009
3086
|
}
|
|
3010
3087
|
if (descTickY != null) {
|
|
3011
|
-
descTableHtml +=
|
|
3088
|
+
descTableHtml += '<td></td>';
|
|
3012
3089
|
}
|
|
3013
3090
|
descTableHtml += `<th scope="col" colspan="${descNumCols}">${descLabelX}</th>`;
|
|
3014
|
-
descTableHtml +=
|
|
3091
|
+
descTableHtml += '</tr>';
|
|
3015
3092
|
}
|
|
3016
3093
|
if (descTickX != null) {
|
|
3017
|
-
descTableHtml +=
|
|
3094
|
+
descTableHtml += '<tr>';
|
|
3018
3095
|
if (descLabelY != null) {
|
|
3019
|
-
descTableHtml +=
|
|
3096
|
+
descTableHtml += '<td></td>';
|
|
3020
3097
|
}
|
|
3021
3098
|
if (descTickY != null) {
|
|
3022
|
-
descTableHtml +=
|
|
3099
|
+
descTableHtml += '<td></td>';
|
|
3023
3100
|
}
|
|
3024
3101
|
for (let i = 0; i < descNumCols; i++) {
|
|
3025
3102
|
descTableHtml += `<th scope="col">${descTickX[i]}</th>`;
|
|
3026
3103
|
}
|
|
3027
|
-
descTableHtml +=
|
|
3104
|
+
descTableHtml += '</tr>';
|
|
3028
3105
|
}
|
|
3029
|
-
descTableHtml +=
|
|
3106
|
+
descTableHtml += '</thead>';
|
|
3030
3107
|
}
|
|
3031
3108
|
|
|
3032
3109
|
// body rows
|
|
3033
3110
|
if (descNumRows > 0) {
|
|
3034
|
-
descTableHtml +=
|
|
3111
|
+
descTableHtml += '<tbody>';
|
|
3035
3112
|
for (let i = 0; i < descNumRows; i++) {
|
|
3036
|
-
descTableHtml +=
|
|
3113
|
+
descTableHtml += '<tr>';
|
|
3037
3114
|
if (descLabelY != null && i == 0) {
|
|
3038
3115
|
descTableHtml += `<th scope="row" rowspan="${descNumRows}">${descLabelY}</th>`;
|
|
3039
3116
|
}
|
|
@@ -3043,19 +3120,19 @@ class Description {
|
|
|
3043
3120
|
for (let j = 0; j < descNumCols; j++) {
|
|
3044
3121
|
descTableHtml += `<td>${descData[i][j]}</td>`;
|
|
3045
3122
|
}
|
|
3046
|
-
descTableHtml +=
|
|
3123
|
+
descTableHtml += '</tr>';
|
|
3047
3124
|
}
|
|
3048
|
-
descTableHtml +=
|
|
3125
|
+
descTableHtml += '</tbody>';
|
|
3049
3126
|
}
|
|
3050
3127
|
|
|
3051
|
-
descTableHtml +=
|
|
3128
|
+
descTableHtml += '</table>';
|
|
3052
3129
|
}
|
|
3053
3130
|
|
|
3054
3131
|
// bar: don't need colspan or rowspan stuff, put legendX and Y as headers
|
|
3055
3132
|
|
|
3056
|
-
document.getElementById(
|
|
3057
|
-
document.getElementById(
|
|
3058
|
-
document.getElementById(
|
|
3133
|
+
document.getElementById('desc_title').innerHTML = descType + ' description';
|
|
3134
|
+
document.getElementById('desc_content').innerHTML = descHtml;
|
|
3135
|
+
document.getElementById('desc_table').innerHTML = descTableHtml;
|
|
3059
3136
|
}
|
|
3060
3137
|
}
|
|
3061
3138
|
|
|
@@ -3096,8 +3173,7 @@ class Helper {
|
|
|
3096
3173
|
*/
|
|
3097
3174
|
class Tracker {
|
|
3098
3175
|
// URL
|
|
3099
|
-
logUrl =
|
|
3100
|
-
"https://maidr-service.azurewebsites.net/api/log?code=I8Aa2PlPspjQ8Hks0QzGyszP8_i2-XJ3bq7Xh8-ykEe4AzFuYn_QWA%3D%3D"; // TODO Replace
|
|
3176
|
+
logUrl = constants.baseURL + 'log' + constants.code; // TODO Replace
|
|
3101
3177
|
isLocal = false;
|
|
3102
3178
|
|
|
3103
3179
|
constructor() {
|
|
@@ -3116,7 +3192,7 @@ class Tracker {
|
|
|
3116
3192
|
data.language = Object.assign(navigator.language);
|
|
3117
3193
|
data.platform = Object.assign(navigator.platform);
|
|
3118
3194
|
data.geolocation = Object.assign(navigator.geolocation);
|
|
3119
|
-
data.log_type =
|
|
3195
|
+
data.log_type = 'system_data';
|
|
3120
3196
|
data.events = [];
|
|
3121
3197
|
data.settings = [];
|
|
3122
3198
|
|
|
@@ -3129,11 +3205,11 @@ class Tracker {
|
|
|
3129
3205
|
* Downloads the tracker data as a JSON file.
|
|
3130
3206
|
*/
|
|
3131
3207
|
DownloadTrackerData() {
|
|
3132
|
-
let link = document.createElement(
|
|
3208
|
+
let link = document.createElement('a');
|
|
3133
3209
|
let data = this.GetTrackerData();
|
|
3134
|
-
let fileStr = new Blob([JSON.stringify(data)], { type:
|
|
3210
|
+
let fileStr = new Blob([JSON.stringify(data)], { type: 'text/plain' });
|
|
3135
3211
|
link.href = URL.createObjectURL(fileStr);
|
|
3136
|
-
link.download =
|
|
3212
|
+
link.download = 'tracking.json';
|
|
3137
3213
|
link.click();
|
|
3138
3214
|
}
|
|
3139
3215
|
|
|
@@ -3142,16 +3218,16 @@ class Tracker {
|
|
|
3142
3218
|
* @param {Object} data - The data to be saved.
|
|
3143
3219
|
*/
|
|
3144
3220
|
async SaveTrackerData(data) {
|
|
3145
|
-
console.log(
|
|
3221
|
+
console.log('about to save data', data);
|
|
3146
3222
|
if (this.isLocal) {
|
|
3147
3223
|
localStorage.setItem(constants.project_id, JSON.stringify(data));
|
|
3148
3224
|
} else {
|
|
3149
3225
|
// test this first
|
|
3150
3226
|
try {
|
|
3151
3227
|
const response = await fetch(this.logUrl, {
|
|
3152
|
-
method:
|
|
3228
|
+
method: 'POST',
|
|
3153
3229
|
headers: {
|
|
3154
|
-
|
|
3230
|
+
'Content-Type': 'application/json',
|
|
3155
3231
|
},
|
|
3156
3232
|
body: JSON.stringify(data),
|
|
3157
3233
|
});
|
|
@@ -3161,10 +3237,10 @@ class Tracker {
|
|
|
3161
3237
|
}
|
|
3162
3238
|
|
|
3163
3239
|
const result = await response.json();
|
|
3164
|
-
console.log(
|
|
3240
|
+
console.log('Data saved successfully:', result);
|
|
3165
3241
|
return result;
|
|
3166
3242
|
} catch (error) {
|
|
3167
|
-
console.error(
|
|
3243
|
+
console.error('Error saving data:', error);
|
|
3168
3244
|
return null;
|
|
3169
3245
|
}
|
|
3170
3246
|
}
|
|
@@ -3187,7 +3263,7 @@ class Tracker {
|
|
|
3187
3263
|
this.data = null;
|
|
3188
3264
|
|
|
3189
3265
|
if (constants.debugLevel > 0) {
|
|
3190
|
-
console.log(
|
|
3266
|
+
console.log('tracking data cleared');
|
|
3191
3267
|
}
|
|
3192
3268
|
|
|
3193
3269
|
this.DataSetup();
|
|
@@ -3195,16 +3271,16 @@ class Tracker {
|
|
|
3195
3271
|
|
|
3196
3272
|
SaveSettings() {
|
|
3197
3273
|
// fetch all settings, push to data.settings
|
|
3198
|
-
let settings = JSON.parse(localStorage.getItem(
|
|
3274
|
+
let settings = JSON.parse(localStorage.getItem('settings_data'));
|
|
3199
3275
|
if (settings) {
|
|
3200
3276
|
// don't store their auth keys
|
|
3201
|
-
settings.openAIAuthKey =
|
|
3202
|
-
settings.geminiAuthKey =
|
|
3277
|
+
settings.openAIAuthKey = 'hidden';
|
|
3278
|
+
settings.geminiAuthKey = 'hidden';
|
|
3203
3279
|
if (constants.emailAuthKey) {
|
|
3204
3280
|
settings.username = constants.emailAuthKey;
|
|
3205
3281
|
}
|
|
3206
3282
|
settings;
|
|
3207
|
-
this.SetData(
|
|
3283
|
+
this.SetData('settings', settings);
|
|
3208
3284
|
}
|
|
3209
3285
|
}
|
|
3210
3286
|
|
|
@@ -3301,7 +3377,7 @@ class Tracker {
|
|
|
3301
3377
|
}
|
|
3302
3378
|
if (!this.isUndefinedOrNull(constants.infoDiv.innerHTML)) {
|
|
3303
3379
|
let textDisplay = Object.assign(constants.infoDiv.innerHTML);
|
|
3304
|
-
textDisplay = textDisplay.replaceAll(/<[^>]*>?/gm,
|
|
3380
|
+
textDisplay = textDisplay.replaceAll(/<[^>]*>?/gm, '');
|
|
3305
3381
|
eventToLog.text_display = textDisplay;
|
|
3306
3382
|
}
|
|
3307
3383
|
if (!this.isUndefinedOrNull(location.href)) {
|
|
@@ -3309,13 +3385,13 @@ class Tracker {
|
|
|
3309
3385
|
}
|
|
3310
3386
|
|
|
3311
3387
|
// chart specific values
|
|
3312
|
-
let x_tickmark =
|
|
3313
|
-
let y_tickmark =
|
|
3314
|
-
let x_label =
|
|
3315
|
-
let y_label =
|
|
3316
|
-
let value =
|
|
3317
|
-
let fill_value =
|
|
3318
|
-
if (constants.chartType ==
|
|
3388
|
+
let x_tickmark = '';
|
|
3389
|
+
let y_tickmark = '';
|
|
3390
|
+
let x_label = '';
|
|
3391
|
+
let y_label = '';
|
|
3392
|
+
let value = '';
|
|
3393
|
+
let fill_value = '';
|
|
3394
|
+
if (constants.chartType == 'bar') {
|
|
3319
3395
|
if (!this.isUndefinedOrNull(plot.columnLabels[position.x])) {
|
|
3320
3396
|
x_tickmark = plot.columnLabels[position.x];
|
|
3321
3397
|
}
|
|
@@ -3328,7 +3404,7 @@ class Tracker {
|
|
|
3328
3404
|
if (!this.isUndefinedOrNull(plot.plotData[position.x])) {
|
|
3329
3405
|
value = plot.plotData[position.x];
|
|
3330
3406
|
}
|
|
3331
|
-
} else if (constants.chartType ==
|
|
3407
|
+
} else if (constants.chartType == 'heat') {
|
|
3332
3408
|
if (!this.isUndefinedOrNull(plot.x_labels[position.x])) {
|
|
3333
3409
|
x_tickmark = plot.x_labels[position.x].trim();
|
|
3334
3410
|
}
|
|
@@ -3349,11 +3425,11 @@ class Tracker {
|
|
|
3349
3425
|
if (!this.isUndefinedOrNull(plot.group_labels[2])) {
|
|
3350
3426
|
fill_value = plot.group_labels[2];
|
|
3351
3427
|
}
|
|
3352
|
-
} else if (constants.chartType ==
|
|
3428
|
+
} else if (constants.chartType == 'box') {
|
|
3353
3429
|
let plotPos =
|
|
3354
|
-
constants.plotOrientation ==
|
|
3430
|
+
constants.plotOrientation == 'vert' ? position.x : position.y;
|
|
3355
3431
|
let sectionPos =
|
|
3356
|
-
constants.plotOrientation ==
|
|
3432
|
+
constants.plotOrientation == 'vert' ? position.y : position.x;
|
|
3357
3433
|
let sectionLabel = plot.sections[sectionPos];
|
|
3358
3434
|
|
|
3359
3435
|
if (!this.isUndefinedOrNull(plot.x_group_label)) {
|
|
@@ -3362,7 +3438,7 @@ class Tracker {
|
|
|
3362
3438
|
if (!this.isUndefinedOrNull(plot.y_group_label)) {
|
|
3363
3439
|
y_label = plot.y_group_label;
|
|
3364
3440
|
}
|
|
3365
|
-
if (constants.plotOrientation ==
|
|
3441
|
+
if (constants.plotOrientation == 'vert') {
|
|
3366
3442
|
if (plotPos > -1 && sectionPos > -1) {
|
|
3367
3443
|
if (!this.isUndefinedOrNull(sectionLabel)) {
|
|
3368
3444
|
y_tickmark = sectionLabel;
|
|
@@ -3387,7 +3463,7 @@ class Tracker {
|
|
|
3387
3463
|
}
|
|
3388
3464
|
}
|
|
3389
3465
|
}
|
|
3390
|
-
} else if (constants.chartType ==
|
|
3466
|
+
} else if (constants.chartType == 'point') {
|
|
3391
3467
|
if (!this.isUndefinedOrNull(plot.x_group_label)) {
|
|
3392
3468
|
x_label = plot.x_group_label;
|
|
3393
3469
|
}
|
|
@@ -3414,7 +3490,7 @@ class Tracker {
|
|
|
3414
3490
|
|
|
3415
3491
|
//console.log("x_tickmark: '", x_tickmark, "', y_tickmark: '", y_tickmark, "', x_label: '", x_label, "', y_label: '", y_label, "', value: '", value, "', fill_value: '", fill_value);
|
|
3416
3492
|
|
|
3417
|
-
this.SetData(
|
|
3493
|
+
this.SetData('events', eventToLog);
|
|
3418
3494
|
//console.log('logged an event');
|
|
3419
3495
|
}
|
|
3420
3496
|
|
|
@@ -3427,7 +3503,7 @@ class Tracker {
|
|
|
3427
3503
|
SetData(key, value) {
|
|
3428
3504
|
if (this.isLocal) {
|
|
3429
3505
|
let data = this.GetTrackerData();
|
|
3430
|
-
let arrayKeys = [
|
|
3506
|
+
let arrayKeys = ['events', 'ChatHistory', 'settings'];
|
|
3431
3507
|
if (!arrayKeys.includes(key)) {
|
|
3432
3508
|
data[key] = value;
|
|
3433
3509
|
} else {
|
|
@@ -3438,7 +3514,7 @@ class Tracker {
|
|
|
3438
3514
|
}
|
|
3439
3515
|
this.SaveTrackerData(data);
|
|
3440
3516
|
} else {
|
|
3441
|
-
value[
|
|
3517
|
+
value['log_type'] = key;
|
|
3442
3518
|
this.SaveTrackerData(value);
|
|
3443
3519
|
}
|
|
3444
3520
|
}
|
|
@@ -3472,20 +3548,20 @@ class Review {
|
|
|
3472
3548
|
// true means on or show
|
|
3473
3549
|
if (onoff) {
|
|
3474
3550
|
constants.reviewSaveSpot = document.activeElement;
|
|
3475
|
-
constants.review_container.classList.remove(
|
|
3551
|
+
constants.review_container.classList.remove('hidden');
|
|
3476
3552
|
constants.reviewSaveBrailleMode = constants.brailleMode;
|
|
3477
3553
|
constants.review.focus();
|
|
3478
3554
|
|
|
3479
|
-
display.announceText(
|
|
3555
|
+
display.announceText('Review on');
|
|
3480
3556
|
} else {
|
|
3481
|
-
constants.review_container.classList.add(
|
|
3482
|
-
if (constants.reviewSaveBrailleMode ==
|
|
3557
|
+
constants.review_container.classList.add('hidden');
|
|
3558
|
+
if (constants.reviewSaveBrailleMode == 'on') {
|
|
3483
3559
|
// we have to turn braille mode back on
|
|
3484
|
-
display.toggleBrailleMode(
|
|
3560
|
+
display.toggleBrailleMode('on');
|
|
3485
3561
|
} else {
|
|
3486
3562
|
constants.reviewSaveSpot.focus();
|
|
3487
3563
|
}
|
|
3488
|
-
display.announceText(
|
|
3564
|
+
display.announceText('Review off');
|
|
3489
3565
|
}
|
|
3490
3566
|
}
|
|
3491
3567
|
}
|
|
@@ -3502,7 +3578,7 @@ class LogError {
|
|
|
3502
3578
|
* @param {string} a - The absent element to log.
|
|
3503
3579
|
*/
|
|
3504
3580
|
LogAbsentElement(a) {
|
|
3505
|
-
console.log(a,
|
|
3581
|
+
console.log(a, 'not found. Visual highlighting is turned off.');
|
|
3506
3582
|
}
|
|
3507
3583
|
|
|
3508
3584
|
/**
|
|
@@ -3510,7 +3586,7 @@ class LogError {
|
|
|
3510
3586
|
* @param {string} a - The critical element to log.
|
|
3511
3587
|
*/
|
|
3512
3588
|
LogCriticalElement(a) {
|
|
3513
|
-
consolelog(a,
|
|
3589
|
+
consolelog(a, 'is critical. MAIDR unable to run');
|
|
3514
3590
|
}
|
|
3515
3591
|
|
|
3516
3592
|
/**
|
|
@@ -3521,9 +3597,9 @@ class LogError {
|
|
|
3521
3597
|
LogDifferentLengths(a, b) {
|
|
3522
3598
|
console.log(
|
|
3523
3599
|
a,
|
|
3524
|
-
|
|
3600
|
+
'and',
|
|
3525
3601
|
b,
|
|
3526
|
-
|
|
3602
|
+
'do not have the same length. Visual highlighting is turned off.'
|
|
3527
3603
|
);
|
|
3528
3604
|
}
|
|
3529
3605
|
|
|
@@ -3534,11 +3610,11 @@ class LogError {
|
|
|
3534
3610
|
*/
|
|
3535
3611
|
LogTooManyElements(a, b) {
|
|
3536
3612
|
console.log(
|
|
3537
|
-
|
|
3613
|
+
'Too many',
|
|
3538
3614
|
a,
|
|
3539
|
-
|
|
3615
|
+
'elements. Only the first',
|
|
3540
3616
|
b,
|
|
3541
|
-
|
|
3617
|
+
'will be highlighted.'
|
|
3542
3618
|
);
|
|
3543
3619
|
}
|
|
3544
3620
|
|
|
@@ -3547,7 +3623,7 @@ class LogError {
|
|
|
3547
3623
|
* @param {*} a - The parameter that is not an array.
|
|
3548
3624
|
*/
|
|
3549
3625
|
LogNotArray(a) {
|
|
3550
|
-
console.log(a,
|
|
3626
|
+
console.log(a, 'is not an array. Visual highlighting is turned off.');
|
|
3551
3627
|
}
|
|
3552
3628
|
}
|
|
3553
3629
|
|
|
@@ -11800,13 +11876,13 @@ function SetEvents() {
|
|
|
11800
11876
|
for (let i = 0; i < constants.events.length; i++) {
|
|
11801
11877
|
if (Array.isArray(constants.events[i][0])) {
|
|
11802
11878
|
for (let j = 0; j < constants.events[i][0].length; j++) {
|
|
11803
|
-
constants.events[i][0][j]
|
|
11879
|
+
constants.events[i][0][j]?.addEventListener(
|
|
11804
11880
|
constants.events[i][1],
|
|
11805
11881
|
constants.events[i][2]
|
|
11806
11882
|
);
|
|
11807
11883
|
}
|
|
11808
11884
|
} else {
|
|
11809
|
-
constants.events[i][0]
|
|
11885
|
+
constants.events[i][0]?.addEventListener(
|
|
11810
11886
|
constants.events[i][1],
|
|
11811
11887
|
constants.events[i][2]
|
|
11812
11888
|
);
|