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