maidr 2.21.0 → 2.22.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 +553 -129
- package/dist/maidr.min.js +1 -1
- package/package.json +1 -1
package/dist/maidr.js
CHANGED
|
@@ -406,13 +406,6 @@ class Constants {
|
|
|
406
406
|
* @memberof AdvancedUserSettings
|
|
407
407
|
*/
|
|
408
408
|
canTrack = 0; // 0 / 1, can we track user data
|
|
409
|
-
/**
|
|
410
|
-
* Whether or not we're currently tracking user data.
|
|
411
|
-
* @type {boolean}
|
|
412
|
-
* @default 1
|
|
413
|
-
* @memberof AdvancedUserSettings
|
|
414
|
-
*/
|
|
415
|
-
isTracking = 0;
|
|
416
409
|
/**
|
|
417
410
|
* How are we representing braille? like, is it 1:1 with the chart, or do we do some compression and try to represent as accuratly as we can? Not currently in use.
|
|
418
411
|
* @type {boolean}
|
|
@@ -443,12 +436,15 @@ class Constants {
|
|
|
443
436
|
'ariaMode',
|
|
444
437
|
'openAIAuthKey',
|
|
445
438
|
'geminiAuthKey',
|
|
439
|
+
'claudeAuthKey',
|
|
440
|
+
'emailAuthKey',
|
|
446
441
|
'skillLevel',
|
|
447
442
|
'skillLevelOther',
|
|
448
443
|
'LLMModel',
|
|
449
444
|
'LLMPreferences',
|
|
450
445
|
'LLMOpenAiMulti',
|
|
451
446
|
'LLMGeminiMulti',
|
|
447
|
+
'LLMModels',
|
|
452
448
|
'autoInitLLM',
|
|
453
449
|
];
|
|
454
450
|
|
|
@@ -498,6 +494,13 @@ class Constants {
|
|
|
498
494
|
* @memberof LLMSettings
|
|
499
495
|
*/
|
|
500
496
|
LLMModel = 'openai';
|
|
497
|
+
/**
|
|
498
|
+
* Current LLM model in use. Can be 'openai' (default) or 'gemini' or 'claude'. More to be added.
|
|
499
|
+
* @type {("openai"|"gemini"|"claude")}
|
|
500
|
+
* @default 'openai'
|
|
501
|
+
* @memberof LLMSettings
|
|
502
|
+
*/
|
|
503
|
+
LLMModels = { openai: true };
|
|
501
504
|
/**
|
|
502
505
|
* The default system message for the LLM. Helps the LLM understand the context of the chart and its role.
|
|
503
506
|
* @type {string}
|
|
@@ -832,6 +835,7 @@ class Resources {
|
|
|
832
835
|
empty: 'Empty',
|
|
833
836
|
openai: 'OpenAI Vision',
|
|
834
837
|
gemini: 'Gemini Pro Vision',
|
|
838
|
+
claude: 'Claude',
|
|
835
839
|
multi: 'Multiple AI',
|
|
836
840
|
processing: 'Processing Chart...',
|
|
837
841
|
},
|
|
@@ -1011,8 +1015,7 @@ class Menu {
|
|
|
1011
1015
|
constants.ariaMode == 'polite' ? 'checked' : ''
|
|
1012
1016
|
}><label for="aria_mode_polite">Polite</label></p>
|
|
1013
1017
|
</fieldset></div>
|
|
1014
|
-
<
|
|
1015
|
-
<p>
|
|
1018
|
+
<p class="hidden">
|
|
1016
1019
|
<select id="LLM_model">
|
|
1017
1020
|
<option value="openai">OpenAI Vision</option>
|
|
1018
1021
|
<option value="gemini">Gemini Pro Vision</option>
|
|
@@ -1020,6 +1023,21 @@ class Menu {
|
|
|
1020
1023
|
</select>
|
|
1021
1024
|
<label for="LLM_model">LLM Model</label>
|
|
1022
1025
|
</p>
|
|
1026
|
+
<h5 class="modal-title">LLM Settings</h5>
|
|
1027
|
+
<p>
|
|
1028
|
+
<fieldset>
|
|
1029
|
+
<legend>LLM Models (select up to 2)</legend>
|
|
1030
|
+
<p><input type="checkbox" id="LLM_model_openai" name="LLM_model" value="openai"><label for="LLM_model_openai">OpenAI Vision</label></p>
|
|
1031
|
+
<p><input type="checkbox" id="LLM_model_gemini" name="LLM_model" value="gemini"><label for="LLM_model_gemini">Gemini Pro Vision</label></p>
|
|
1032
|
+
<p><input type="checkbox" id="LLM_model_claude" name="LLM_model" value="claude"><label for="LLM_model_claude">Claude</label></p>
|
|
1033
|
+
</fieldset>
|
|
1034
|
+
</p>
|
|
1035
|
+
<p id="email_auth_key_container" class="multi_container">
|
|
1036
|
+
<input type="email" size="50" id="email_auth_key" aria-label="Enter your email address">
|
|
1037
|
+
<button aria-label="Delete Email Address" title="Delete Email Address" id="delete_email_key" class="invis_button">×</button>
|
|
1038
|
+
<label for="gemini_auth_key">Email Authentication</label>
|
|
1039
|
+
<button type="button" id="verify">Verify</button>
|
|
1040
|
+
</p>
|
|
1023
1041
|
<p id="openai_auth_key_container" class="multi_container hidden">
|
|
1024
1042
|
<span id="openai_multi_container" class="hidden"><input type="checkbox" id="openai_multi" name="openai_multi" aria-label="Use OpenAI in Multi modal mode"></span>
|
|
1025
1043
|
<input type="password" size="50" id="openai_auth_key"><button aria-label="Delete OpenAI key" title="Delete OpenAI key" id="delete_openai_key" class="invis_button">×</button><label for="openai_auth_key">OpenAI Authentication Key</label>
|
|
@@ -1027,10 +1045,14 @@ class Menu {
|
|
|
1027
1045
|
<p id="gemini_auth_key_container" class="multi_container hidden">
|
|
1028
1046
|
<span id="gemini_multi_container" class="hidden"><input type="checkbox" id="gemini_multi" name="gemini_multi" aria-label="Use Gemini in Multi modal mode"></span>
|
|
1029
1047
|
<input type="password" size="50" id="gemini_auth_key"><button aria-label="Delete Gemini key" title="Delete Gemini key" id="delete_gemini_key" class="invis_button">×</button><label for="gemini_auth_key">Gemini Authentication Key</label>
|
|
1048
|
+
</p>
|
|
1049
|
+
<p id="claude_auth_key_container" class="multi_container hidden">
|
|
1050
|
+
<span id="claude_multi_container" class="hidden"><input type="checkbox" id="claude_multi" name="claude_multi" aria-label="Use Claude in Multi modal mode"></span>
|
|
1051
|
+
<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>
|
|
1030
1052
|
</p>
|
|
1031
1053
|
<p><input type="checkbox" ${
|
|
1032
1054
|
constants.autoInitLLM ? 'checked' : ''
|
|
1033
|
-
} id="init_llm_on_load" name="init_llm_on_load"><label for="init_llm_on_load">Start
|
|
1055
|
+
} id="init_llm_on_load" name="init_llm_on_load"><label for="init_llm_on_load">Start LLM right away</label></p>
|
|
1034
1056
|
<p>
|
|
1035
1057
|
<select id="skill_level">
|
|
1036
1058
|
<option value="basic">Basic</option>
|
|
@@ -1088,6 +1110,13 @@ class Menu {
|
|
|
1088
1110
|
menu.Toggle(false);
|
|
1089
1111
|
},
|
|
1090
1112
|
]);
|
|
1113
|
+
constants.events.push([
|
|
1114
|
+
document.getElementById('verify'),
|
|
1115
|
+
'click',
|
|
1116
|
+
function (e) {
|
|
1117
|
+
menu.VerifyEmail();
|
|
1118
|
+
},
|
|
1119
|
+
]);
|
|
1091
1120
|
constants.events.push([
|
|
1092
1121
|
document.getElementById('menu'),
|
|
1093
1122
|
'keyup',
|
|
@@ -1170,6 +1199,54 @@ class Menu {
|
|
|
1170
1199
|
},
|
|
1171
1200
|
]);
|
|
1172
1201
|
|
|
1202
|
+
constants.events.push([
|
|
1203
|
+
document.getElementById('LLM_model_openai'),
|
|
1204
|
+
'change',
|
|
1205
|
+
function (e) {
|
|
1206
|
+
if (e.target.checked) {
|
|
1207
|
+
document
|
|
1208
|
+
.getElementById('openai_auth_key_container')
|
|
1209
|
+
.classList.remove('hidden');
|
|
1210
|
+
} else {
|
|
1211
|
+
document
|
|
1212
|
+
.getElementById('openai_auth_key_container')
|
|
1213
|
+
.classList.add('hidden');
|
|
1214
|
+
}
|
|
1215
|
+
},
|
|
1216
|
+
]);
|
|
1217
|
+
|
|
1218
|
+
constants.events.push([
|
|
1219
|
+
document.getElementById('LLM_model_gemini'),
|
|
1220
|
+
'change',
|
|
1221
|
+
function (e) {
|
|
1222
|
+
if (e.target.checked) {
|
|
1223
|
+
document
|
|
1224
|
+
.getElementById('gemini_auth_key_container')
|
|
1225
|
+
.classList.remove('hidden');
|
|
1226
|
+
} else {
|
|
1227
|
+
document
|
|
1228
|
+
.getElementById('gemini_auth_key_container')
|
|
1229
|
+
.classList.add('hidden');
|
|
1230
|
+
}
|
|
1231
|
+
},
|
|
1232
|
+
]);
|
|
1233
|
+
|
|
1234
|
+
constants.events.push([
|
|
1235
|
+
document.getElementById('LLM_model_claude'),
|
|
1236
|
+
'change',
|
|
1237
|
+
function (e) {
|
|
1238
|
+
// if (e.target.checked) {
|
|
1239
|
+
document
|
|
1240
|
+
.getElementById('claude_auth_key_container')
|
|
1241
|
+
.classList.add('hidden');
|
|
1242
|
+
// } else {
|
|
1243
|
+
// document
|
|
1244
|
+
// .getElementById('claude_auth_key_container')
|
|
1245
|
+
// .classList.add('hidden');
|
|
1246
|
+
// }
|
|
1247
|
+
},
|
|
1248
|
+
]);
|
|
1249
|
+
|
|
1173
1250
|
// Skill level other events
|
|
1174
1251
|
constants.events.push([
|
|
1175
1252
|
document.getElementById('skill_level'),
|
|
@@ -1205,6 +1282,20 @@ class Menu {
|
|
|
1205
1282
|
},
|
|
1206
1283
|
]);
|
|
1207
1284
|
}
|
|
1285
|
+
|
|
1286
|
+
// Limit selections to 2 AI models
|
|
1287
|
+
const llmCheckboxes = document.querySelectorAll('input[name="LLM_model"]');
|
|
1288
|
+
llmCheckboxes.forEach((checkbox) => {
|
|
1289
|
+
checkbox.addEventListener('change', () => {
|
|
1290
|
+
const checked = document.querySelectorAll(
|
|
1291
|
+
'input[name="LLM_model"]:checked'
|
|
1292
|
+
);
|
|
1293
|
+
if (checked.length > 2) {
|
|
1294
|
+
checkbox.checked = false;
|
|
1295
|
+
alert('You can select up to 2 AI models.');
|
|
1296
|
+
}
|
|
1297
|
+
});
|
|
1298
|
+
});
|
|
1208
1299
|
}
|
|
1209
1300
|
|
|
1210
1301
|
/**
|
|
@@ -1276,16 +1367,22 @@ class Menu {
|
|
|
1276
1367
|
document.getElementById('openai_auth_key').value =
|
|
1277
1368
|
constants.openAIAuthKey;
|
|
1278
1369
|
}
|
|
1370
|
+
if (typeof constants.emailAuthKey == 'string') {
|
|
1371
|
+
document.getElementById('email_auth_key').value = constants.emailAuthKey;
|
|
1372
|
+
}
|
|
1279
1373
|
if (typeof constants.geminiAuthKey == 'string') {
|
|
1280
1374
|
document.getElementById('gemini_auth_key').value =
|
|
1281
1375
|
constants.geminiAuthKey;
|
|
1282
1376
|
}
|
|
1377
|
+
if (typeof constants.claudeAuthKey == 'string') {
|
|
1378
|
+
document.getElementById('claude_auth_key').value =
|
|
1379
|
+
constants.claudeAuthKey;
|
|
1380
|
+
}
|
|
1283
1381
|
document.getElementById('skill_level').value = constants.skillLevel;
|
|
1284
1382
|
if (constants.skillLevelOther) {
|
|
1285
1383
|
document.getElementById('skill_level_other').value =
|
|
1286
1384
|
constants.skillLevelOther;
|
|
1287
1385
|
}
|
|
1288
|
-
document.getElementById('LLM_model').value = constants.LLMModel;
|
|
1289
1386
|
|
|
1290
1387
|
// aria mode
|
|
1291
1388
|
if (constants.ariaMode == 'assertive') {
|
|
@@ -1295,44 +1392,18 @@ class Menu {
|
|
|
1295
1392
|
document.getElementById('aria_mode_polite').checked = true;
|
|
1296
1393
|
document.getElementById('aria_mode_assertive').checked = false;
|
|
1297
1394
|
}
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
document
|
|
1301
|
-
|
|
1302
|
-
.classList.remove('hidden');
|
|
1303
|
-
document
|
|
1304
|
-
.getElementById('gemini_auth_key_container')
|
|
1305
|
-
.classList.add('hidden');
|
|
1306
|
-
} else if (constants.LLMModel == 'gemini') {
|
|
1307
|
-
document
|
|
1308
|
-
.getElementById('openai_auth_key_container')
|
|
1309
|
-
.classList.add('hidden');
|
|
1310
|
-
document
|
|
1311
|
-
.getElementById('gemini_auth_key_container')
|
|
1312
|
-
.classList.remove('hidden');
|
|
1313
|
-
} else if (constants.LLMModel == 'multi') {
|
|
1314
|
-
// multi LLM mode
|
|
1315
|
-
document
|
|
1316
|
-
.getElementById('openai_auth_key_container')
|
|
1317
|
-
.classList.remove('hidden');
|
|
1318
|
-
document
|
|
1319
|
-
.getElementById('gemini_auth_key_container')
|
|
1320
|
-
.classList.remove('hidden');
|
|
1321
|
-
document
|
|
1322
|
-
.getElementById('openai_multi_container')
|
|
1323
|
-
.classList.remove('hidden');
|
|
1395
|
+
|
|
1396
|
+
for (let model in constants.LLMModels) {
|
|
1397
|
+
document.getElementById(`LLM_model_${model}`).checked = true;
|
|
1398
|
+
|
|
1324
1399
|
document
|
|
1325
|
-
.getElementById(
|
|
1400
|
+
.getElementById(`${model}_auth_key_container`)
|
|
1326
1401
|
.classList.remove('hidden');
|
|
1327
|
-
document.getElementById('openai_multi').checked = false;
|
|
1328
|
-
if (constants.LLMOpenAiMulti) {
|
|
1329
|
-
document.getElementById('openai_multi').checked = true;
|
|
1330
|
-
}
|
|
1331
|
-
document.getElementById('gemini_multi').checked = false;
|
|
1332
|
-
if (constants.LLMGeminiMulti) {
|
|
1333
|
-
document.getElementById('gemini_multi').checked = true;
|
|
1334
|
-
}
|
|
1335
1402
|
}
|
|
1403
|
+
document
|
|
1404
|
+
.getElementById(`claude_auth_key_container`)
|
|
1405
|
+
.classList.add('hidden');
|
|
1406
|
+
|
|
1336
1407
|
// skill level other
|
|
1337
1408
|
if (constants.skillLevel == 'other') {
|
|
1338
1409
|
document
|
|
@@ -1368,10 +1439,22 @@ class Menu {
|
|
|
1368
1439
|
|
|
1369
1440
|
constants.openAIAuthKey = document.getElementById('openai_auth_key').value;
|
|
1370
1441
|
constants.geminiAuthKey = document.getElementById('gemini_auth_key').value;
|
|
1442
|
+
constants.claudeAuthKey = document.getElementById('claude_auth_key').value;
|
|
1443
|
+
constants.emailAuthKey = document.getElementById('email_auth_key').value;
|
|
1371
1444
|
constants.skillLevel = document.getElementById('skill_level').value;
|
|
1372
1445
|
constants.skillLevelOther =
|
|
1373
1446
|
document.getElementById('skill_level_other').value;
|
|
1374
|
-
constants.LLMModel = document.getElementById('LLM_model').value;
|
|
1447
|
+
// constants.LLMModel = document.getElementById('LLM_model').value;
|
|
1448
|
+
|
|
1449
|
+
const llmCheckboxes = document.querySelectorAll('input[name="LLM_model"]');
|
|
1450
|
+
llmCheckboxes.forEach((checkbox) => {
|
|
1451
|
+
if (checkbox.checked) {
|
|
1452
|
+
constants.LLMModels[checkbox.value] = true;
|
|
1453
|
+
} else {
|
|
1454
|
+
delete constants.LLMModels[checkbox.value];
|
|
1455
|
+
}
|
|
1456
|
+
});
|
|
1457
|
+
|
|
1375
1458
|
constants.LLMPreferences = document.getElementById('LLM_preferences').value;
|
|
1376
1459
|
constants.LLMOpenAiMulti = document.getElementById('openai_multi').checked;
|
|
1377
1460
|
constants.LLMGeminiMulti = document.getElementById('gemini_multi').checked;
|
|
@@ -1394,6 +1477,41 @@ class Menu {
|
|
|
1394
1477
|
}
|
|
1395
1478
|
}
|
|
1396
1479
|
|
|
1480
|
+
VerifyEmail() {
|
|
1481
|
+
let email = document.getElementById('email_auth_key').value;
|
|
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`;
|
|
1484
|
+
|
|
1485
|
+
let requestJson = {
|
|
1486
|
+
email: email,
|
|
1487
|
+
};
|
|
1488
|
+
|
|
1489
|
+
fetch(url, {
|
|
1490
|
+
method: 'POST',
|
|
1491
|
+
headers: {
|
|
1492
|
+
'Content-Type': 'application/json',
|
|
1493
|
+
Authentication: constants.emailAuthKey,
|
|
1494
|
+
},
|
|
1495
|
+
body: JSON.stringify(requestJson),
|
|
1496
|
+
})
|
|
1497
|
+
.then((response) => response.json())
|
|
1498
|
+
.then((data) => {
|
|
1499
|
+
if (data && data.success) {
|
|
1500
|
+
alert('Link sent to email address: ' + email);
|
|
1501
|
+
} else {
|
|
1502
|
+
console.log(data);
|
|
1503
|
+
alert(data.data);
|
|
1504
|
+
}
|
|
1505
|
+
})
|
|
1506
|
+
.catch((error) => {
|
|
1507
|
+
console.log(error);
|
|
1508
|
+
alert(error.data);
|
|
1509
|
+
});
|
|
1510
|
+
} else {
|
|
1511
|
+
alert('Please enter a valid email address.');
|
|
1512
|
+
}
|
|
1513
|
+
}
|
|
1514
|
+
|
|
1397
1515
|
/**
|
|
1398
1516
|
* Sets the aria attributes on the HTML elements in the menu
|
|
1399
1517
|
* @returns {void}
|
|
@@ -1475,14 +1593,16 @@ class Menu {
|
|
|
1475
1593
|
) {
|
|
1476
1594
|
shouldReset = true;
|
|
1477
1595
|
}
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1596
|
+
|
|
1597
|
+
// check if LLMModels have changed
|
|
1598
|
+
let llmCheckboxes = document.querySelectorAll('input[name="LLM_model"]');
|
|
1599
|
+
for (let i = 0; i < llmCheckboxes.length; i++) {
|
|
1600
|
+
if (
|
|
1601
|
+
!shouldReset &&
|
|
1602
|
+
constants.LLMModels[llmCheckboxes[i].value] != llmCheckboxes[i].checked
|
|
1603
|
+
) {
|
|
1604
|
+
shouldReset = true;
|
|
1605
|
+
}
|
|
1486
1606
|
}
|
|
1487
1607
|
|
|
1488
1608
|
return shouldReset;
|
|
@@ -1501,10 +1621,11 @@ class Menu {
|
|
|
1501
1621
|
localStorage.setItem('settings_data', JSON.stringify(data));
|
|
1502
1622
|
|
|
1503
1623
|
// also save to tracking if we're doing that
|
|
1504
|
-
if (constants.
|
|
1624
|
+
if (constants.canTrack) {
|
|
1505
1625
|
// but not auth keys
|
|
1506
1626
|
data.openAIAuthKey = 'hidden';
|
|
1507
1627
|
data.geminiAuthKey = 'hidden';
|
|
1628
|
+
data.claudeAuthKey = 'hidden';
|
|
1508
1629
|
// and need a timestamp
|
|
1509
1630
|
data.timestamp = new Date().toISOString();
|
|
1510
1631
|
tracker.SetData('settings', data);
|
|
@@ -1517,9 +1638,10 @@ class Menu {
|
|
|
1517
1638
|
let data = JSON.parse(localStorage.getItem('settings_data'));
|
|
1518
1639
|
if (data) {
|
|
1519
1640
|
for (let i = 0; i < constants.userSettingsKeys.length; i++) {
|
|
1520
|
-
constants
|
|
1521
|
-
|
|
1522
|
-
constants[
|
|
1641
|
+
const key = constants.userSettingsKeys[i];
|
|
1642
|
+
if (key in data) {
|
|
1643
|
+
constants[key] = data[key];
|
|
1644
|
+
}
|
|
1523
1645
|
}
|
|
1524
1646
|
}
|
|
1525
1647
|
this.PopulateData();
|
|
@@ -1541,11 +1663,9 @@ class ChatLLM {
|
|
|
1541
1663
|
if (constants.autoInitLLM) {
|
|
1542
1664
|
// only run if we have API keys set
|
|
1543
1665
|
if (
|
|
1544
|
-
(constants.
|
|
1545
|
-
(constants.
|
|
1546
|
-
(constants.
|
|
1547
|
-
constants.openAIAuthKey &&
|
|
1548
|
-
constants.geminiAuthKey)
|
|
1666
|
+
('gemini' in constants.LLMModels && constants.geminiAuthKey) ||
|
|
1667
|
+
('openai' in constants.LLMModels && constants.openAIAuthKey) ||
|
|
1668
|
+
('claude' in constants.LLMModels && constants.claudeAuthKey)
|
|
1549
1669
|
) {
|
|
1550
1670
|
this.InitChatMessage();
|
|
1551
1671
|
}
|
|
@@ -1686,6 +1806,13 @@ class ChatLLM {
|
|
|
1686
1806
|
document.getElementById('openai_auth_key').value = '';
|
|
1687
1807
|
},
|
|
1688
1808
|
]);
|
|
1809
|
+
constants.events.push([
|
|
1810
|
+
document.getElementById('delete_email_key'),
|
|
1811
|
+
'click',
|
|
1812
|
+
function (e) {
|
|
1813
|
+
document.getElementById('email_auth_key').value = '';
|
|
1814
|
+
},
|
|
1815
|
+
]);
|
|
1689
1816
|
constants.events.push([
|
|
1690
1817
|
document.getElementById('delete_gemini_key'),
|
|
1691
1818
|
'click',
|
|
@@ -1853,7 +1980,7 @@ class ChatLLM {
|
|
|
1853
1980
|
|
|
1854
1981
|
// 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
|
|
1855
1982
|
if (
|
|
1856
|
-
(this.firstOpen ||
|
|
1983
|
+
(this.firstOpen || 'gemini' in constants.LLMModels) &&
|
|
1857
1984
|
!firsttime &&
|
|
1858
1985
|
constants.verboseText.length > 0
|
|
1859
1986
|
) {
|
|
@@ -1871,17 +1998,36 @@ class ChatLLM {
|
|
|
1871
1998
|
this.WaitingSound(true);
|
|
1872
1999
|
}
|
|
1873
2000
|
|
|
1874
|
-
if (
|
|
2001
|
+
if ('openai' in constants.LLMModels) {
|
|
1875
2002
|
if (firsttime) {
|
|
1876
2003
|
img = await this.ConvertSVGtoJPG(singleMaidr.id, 'openai');
|
|
1877
2004
|
}
|
|
1878
|
-
|
|
2005
|
+
if (constants.openAIAuthKey) {
|
|
2006
|
+
chatLLM.OpenAIPrompt(text, img);
|
|
2007
|
+
} else {
|
|
2008
|
+
chatLLM.OpenAIPromptAPI(text, img);
|
|
2009
|
+
}
|
|
1879
2010
|
}
|
|
1880
|
-
if (
|
|
2011
|
+
if ('gemini' in constants.LLMModels) {
|
|
1881
2012
|
if (firsttime) {
|
|
1882
2013
|
img = await this.ConvertSVGtoJPG(singleMaidr.id, 'gemini');
|
|
1883
2014
|
}
|
|
1884
|
-
|
|
2015
|
+
if (constants.geminiAuthKey) {
|
|
2016
|
+
chatLLM.GeminiPrompt(text, img);
|
|
2017
|
+
} else {
|
|
2018
|
+
chatLLM.GeminiPromptAPI(text, img);
|
|
2019
|
+
}
|
|
2020
|
+
}
|
|
2021
|
+
|
|
2022
|
+
if ('claude' in constants.LLMModels) {
|
|
2023
|
+
if (firsttime) {
|
|
2024
|
+
img = await this.ConvertSVGtoJPG(singleMaidr.id, 'claude');
|
|
2025
|
+
}
|
|
2026
|
+
if (constants.claudeAuthKey) {
|
|
2027
|
+
chatLLM.ClaudePrompt(text, img);
|
|
2028
|
+
} else {
|
|
2029
|
+
chatLLM.ClaudePromptAPI(text, img);
|
|
2030
|
+
}
|
|
1885
2031
|
}
|
|
1886
2032
|
}
|
|
1887
2033
|
|
|
@@ -1969,7 +2115,7 @@ class ChatLLM {
|
|
|
1969
2115
|
}
|
|
1970
2116
|
|
|
1971
2117
|
InitChatMessage() {
|
|
1972
|
-
// get name from resource
|
|
2118
|
+
// get name from resource]
|
|
1973
2119
|
let LLMName = resources.GetString(constants.LLMModel);
|
|
1974
2120
|
this.firstTime = false;
|
|
1975
2121
|
this.DisplayChatMessage(LLMName, resources.GetString('processing'), true);
|
|
@@ -1984,7 +2130,6 @@ class ChatLLM {
|
|
|
1984
2130
|
*/
|
|
1985
2131
|
ProcessLLMResponse(data, model) {
|
|
1986
2132
|
chatLLM.WaitingSound(false);
|
|
1987
|
-
//console.log('LLM response: ', data);
|
|
1988
2133
|
let text = '';
|
|
1989
2134
|
let LLMName = resources.GetString(model);
|
|
1990
2135
|
|
|
@@ -2018,9 +2163,20 @@ class ChatLLM {
|
|
|
2018
2163
|
// todo: display actual response
|
|
2019
2164
|
}
|
|
2020
2165
|
}
|
|
2166
|
+
if (model == 'claude') {
|
|
2167
|
+
console.log('Claude response: ', data);
|
|
2168
|
+
if (data.text()) {
|
|
2169
|
+
text = data.text();
|
|
2170
|
+
chatLLM.DisplayChatMessage(LLMName, text);
|
|
2171
|
+
}
|
|
2172
|
+
if (data.error) {
|
|
2173
|
+
chatLLM.DisplayChatMessage(LLMName, 'Error processing request.', true);
|
|
2174
|
+
chatLLM.WaitingSound(false);
|
|
2175
|
+
}
|
|
2176
|
+
}
|
|
2021
2177
|
|
|
2022
2178
|
// if we're tracking, log the data
|
|
2023
|
-
if (constants.
|
|
2179
|
+
if (constants.canTrack) {
|
|
2024
2180
|
let chatHist = chatLLM.CopyChatHistory();
|
|
2025
2181
|
tracker.SetData('ChatHistory', chatHist);
|
|
2026
2182
|
}
|
|
@@ -2086,6 +2242,96 @@ class ChatLLM {
|
|
|
2086
2242
|
return responseText;
|
|
2087
2243
|
}
|
|
2088
2244
|
|
|
2245
|
+
ClaudeJson(text, img = null) {
|
|
2246
|
+
const anthropicVersion = 'vertex-2023-10-16';
|
|
2247
|
+
const maxTokens = 256;
|
|
2248
|
+
|
|
2249
|
+
const payload = {
|
|
2250
|
+
anthropic_version: anthropicVersion,
|
|
2251
|
+
max_tokens: maxTokens,
|
|
2252
|
+
messages: [],
|
|
2253
|
+
};
|
|
2254
|
+
|
|
2255
|
+
// Construct the user message object
|
|
2256
|
+
const userMessage = {
|
|
2257
|
+
role: 'user',
|
|
2258
|
+
content: [],
|
|
2259
|
+
};
|
|
2260
|
+
|
|
2261
|
+
// Add the image content if provided
|
|
2262
|
+
if (img) {
|
|
2263
|
+
userMessage.content.push(
|
|
2264
|
+
{
|
|
2265
|
+
type: 'image',
|
|
2266
|
+
source: {
|
|
2267
|
+
type: 'base64',
|
|
2268
|
+
media_type: 'image/jpeg', // Update if other formats are supported
|
|
2269
|
+
data: img,
|
|
2270
|
+
},
|
|
2271
|
+
},
|
|
2272
|
+
{
|
|
2273
|
+
type: 'text',
|
|
2274
|
+
text: text,
|
|
2275
|
+
}
|
|
2276
|
+
);
|
|
2277
|
+
} else {
|
|
2278
|
+
// Add only the text content if no image is provided
|
|
2279
|
+
userMessage.content.push({
|
|
2280
|
+
type: 'text',
|
|
2281
|
+
text: text,
|
|
2282
|
+
});
|
|
2283
|
+
}
|
|
2284
|
+
|
|
2285
|
+
// Add the user message to the messages array
|
|
2286
|
+
payload.messages.push(userMessage);
|
|
2287
|
+
|
|
2288
|
+
return payload;
|
|
2289
|
+
}
|
|
2290
|
+
|
|
2291
|
+
ClaudePromptAPI(text, imgBase64 = null) {
|
|
2292
|
+
console.log('Claude prompt API');
|
|
2293
|
+
let url =
|
|
2294
|
+
'https://maidr-service.azurewebsites.net/api/claude?code=I8Aa2PlPspjQ8Hks0QzGyszP8_i2-XJ3bq7Xh8-ykEe4AzFuYn_QWA%3D%3D';
|
|
2295
|
+
|
|
2296
|
+
// Create the prompt
|
|
2297
|
+
let prompt = constants.LLMSystemMessage;
|
|
2298
|
+
if (constants.LLMPreferences) {
|
|
2299
|
+
prompt += constants.LLMPreferences;
|
|
2300
|
+
}
|
|
2301
|
+
prompt += '\n\n' + text; // Use the text parameter as the prompt
|
|
2302
|
+
|
|
2303
|
+
if (imgBase64 == null) {
|
|
2304
|
+
imgBase64 = constants.LLMImage;
|
|
2305
|
+
} else {
|
|
2306
|
+
constants.LLMImage = imgBase64;
|
|
2307
|
+
}
|
|
2308
|
+
constants.LLMImage = imgBase64;
|
|
2309
|
+
|
|
2310
|
+
let requestJson = chatLLM.ClaudeJson(prompt, imgBase64);
|
|
2311
|
+
|
|
2312
|
+
fetch(url, {
|
|
2313
|
+
method: 'POST',
|
|
2314
|
+
headers: {
|
|
2315
|
+
'Content-Type': 'application/json',
|
|
2316
|
+
Authentication: constants.emailAuthKey,
|
|
2317
|
+
},
|
|
2318
|
+
body: JSON.stringify(requestJson),
|
|
2319
|
+
})
|
|
2320
|
+
.then((response) => response.json())
|
|
2321
|
+
.then((data) => {
|
|
2322
|
+
data.text = function () {
|
|
2323
|
+
return data.content[0].text;
|
|
2324
|
+
};
|
|
2325
|
+
chatLLM.ProcessLLMResponse(data, 'claude');
|
|
2326
|
+
})
|
|
2327
|
+
.catch((error) => {
|
|
2328
|
+
chatLLM.WaitingSound(false);
|
|
2329
|
+
console.error('Error:', error);
|
|
2330
|
+
chatLLM.DisplayChatMessage('Claude', 'Error processing request.', true);
|
|
2331
|
+
// also todo: handle errors somehow
|
|
2332
|
+
});
|
|
2333
|
+
}
|
|
2334
|
+
|
|
2089
2335
|
/**
|
|
2090
2336
|
* Gets running prompt info, appends the latest request, and packages it into a JSON object for the LLM.
|
|
2091
2337
|
* @function
|
|
@@ -2119,6 +2365,35 @@ class ChatLLM {
|
|
|
2119
2365
|
// also todo: handle errors somehow
|
|
2120
2366
|
});
|
|
2121
2367
|
}
|
|
2368
|
+
|
|
2369
|
+
OpenAIPromptAPI(text, img = null) {
|
|
2370
|
+
// request init
|
|
2371
|
+
let url =
|
|
2372
|
+
'https://maidr-service.azurewebsites.net/api/openai?code=I8Aa2PlPspjQ8Hks0QzGyszP8_i2-XJ3bq7Xh8-ykEe4AzFuYn_QWA%3D%3D';
|
|
2373
|
+
let auth = constants.openAIAuthKey;
|
|
2374
|
+
let requestJson = chatLLM.OpenAIJson(text, img);
|
|
2375
|
+
console.log('LLM request: ', requestJson);
|
|
2376
|
+
|
|
2377
|
+
fetch(url, {
|
|
2378
|
+
method: 'POST',
|
|
2379
|
+
headers: {
|
|
2380
|
+
'Content-Type': 'application/json',
|
|
2381
|
+
Authentication: constants.emailAuthKey,
|
|
2382
|
+
},
|
|
2383
|
+
body: JSON.stringify(requestJson),
|
|
2384
|
+
})
|
|
2385
|
+
.then((response) => response.json())
|
|
2386
|
+
.then((data) => {
|
|
2387
|
+
chatLLM.ProcessLLMResponse(data, 'openai');
|
|
2388
|
+
})
|
|
2389
|
+
.catch((error) => {
|
|
2390
|
+
chatLLM.WaitingSound(false);
|
|
2391
|
+
console.error('Error:', error);
|
|
2392
|
+
chatLLM.DisplayChatMessage('OpenAI', 'Error processing request.', true);
|
|
2393
|
+
// also todo: handle errors somehow
|
|
2394
|
+
});
|
|
2395
|
+
}
|
|
2396
|
+
|
|
2122
2397
|
OpenAIJson(text, img = null) {
|
|
2123
2398
|
let sysMessage = constants.LLMSystemMessage;
|
|
2124
2399
|
let backupMessage =
|
|
@@ -2167,6 +2442,110 @@ class ChatLLM {
|
|
|
2167
2442
|
return this.requestJson;
|
|
2168
2443
|
}
|
|
2169
2444
|
|
|
2445
|
+
GeminiJson(text, img = null) {
|
|
2446
|
+
let sysMessage = constants.LLMSystemMessage;
|
|
2447
|
+
let backupMessage =
|
|
2448
|
+
'Describe ' + singleMaidr.type + ' charts to a blind person';
|
|
2449
|
+
|
|
2450
|
+
let payload = {
|
|
2451
|
+
generationConfig: {},
|
|
2452
|
+
safetySettings: [],
|
|
2453
|
+
contents: [],
|
|
2454
|
+
};
|
|
2455
|
+
|
|
2456
|
+
// System message as the initial "role" and "text" content for context
|
|
2457
|
+
let sysContent = {
|
|
2458
|
+
role: 'user',
|
|
2459
|
+
parts: [
|
|
2460
|
+
{
|
|
2461
|
+
text: sysMessage || backupMessage, // Fallback if sysMessage is unavailable
|
|
2462
|
+
},
|
|
2463
|
+
],
|
|
2464
|
+
};
|
|
2465
|
+
|
|
2466
|
+
// Add preferences if available
|
|
2467
|
+
if (constants.LLMPreferences) {
|
|
2468
|
+
sysContent.parts.push({
|
|
2469
|
+
text: constants.LLMPreferences,
|
|
2470
|
+
});
|
|
2471
|
+
}
|
|
2472
|
+
|
|
2473
|
+
payload.contents.push(sysContent);
|
|
2474
|
+
|
|
2475
|
+
// Add user input content, including image if available
|
|
2476
|
+
let userContent = {
|
|
2477
|
+
role: 'user',
|
|
2478
|
+
parts: [],
|
|
2479
|
+
};
|
|
2480
|
+
|
|
2481
|
+
if (img) {
|
|
2482
|
+
// If there’s an image, add both text and image data
|
|
2483
|
+
userContent.parts.push(
|
|
2484
|
+
{
|
|
2485
|
+
text: text,
|
|
2486
|
+
},
|
|
2487
|
+
{
|
|
2488
|
+
inlineData: {
|
|
2489
|
+
data: img, // Expecting base64-encoded image data
|
|
2490
|
+
mimeType: 'image/png', // Adjust if different image formats are possible
|
|
2491
|
+
},
|
|
2492
|
+
}
|
|
2493
|
+
);
|
|
2494
|
+
} else {
|
|
2495
|
+
// If no image, only add the text
|
|
2496
|
+
userContent.parts.push({
|
|
2497
|
+
text: text,
|
|
2498
|
+
});
|
|
2499
|
+
}
|
|
2500
|
+
|
|
2501
|
+
// Add user content to the contents array
|
|
2502
|
+
payload.contents.push(userContent);
|
|
2503
|
+
|
|
2504
|
+
return payload;
|
|
2505
|
+
}
|
|
2506
|
+
|
|
2507
|
+
async GeminiPromptAPI(text, imgBase64 = null) {
|
|
2508
|
+
let url =
|
|
2509
|
+
'https://maidr-service.azurewebsites.net/api/gemini?code=I8Aa2PlPspjQ8Hks0QzGyszP8_i2-XJ3bq7Xh8-ykEe4AzFuYn_QWA%3D%3D';
|
|
2510
|
+
|
|
2511
|
+
// Create the prompt
|
|
2512
|
+
let prompt = constants.LLMSystemMessage;
|
|
2513
|
+
if (constants.LLMPreferences) {
|
|
2514
|
+
prompt += constants.LLMPreferences;
|
|
2515
|
+
}
|
|
2516
|
+
prompt += '\n\n' + text; // Use the text parameter as the prompt
|
|
2517
|
+
|
|
2518
|
+
if (imgBase64 == null) {
|
|
2519
|
+
imgBase64 = constants.LLMImage;
|
|
2520
|
+
} else {
|
|
2521
|
+
constants.LLMImage = imgBase64;
|
|
2522
|
+
}
|
|
2523
|
+
constants.LLMImage = imgBase64;
|
|
2524
|
+
|
|
2525
|
+
let requestJson = chatLLM.GeminiJson(prompt, imgBase64);
|
|
2526
|
+
|
|
2527
|
+
const response = await fetch(url, {
|
|
2528
|
+
method: 'POST',
|
|
2529
|
+
headers: {
|
|
2530
|
+
'Content-Type': 'application/json',
|
|
2531
|
+
Authentication: constants.emailAuthKey,
|
|
2532
|
+
},
|
|
2533
|
+
body: JSON.stringify(requestJson),
|
|
2534
|
+
});
|
|
2535
|
+
if (response.ok) {
|
|
2536
|
+
const responseJson = await response.json();
|
|
2537
|
+
responseJson.text = () => {
|
|
2538
|
+
return responseJson.candidates[0].content.parts[0].text;
|
|
2539
|
+
};
|
|
2540
|
+
chatLLM.ProcessLLMResponse(responseJson, 'gemini');
|
|
2541
|
+
} else {
|
|
2542
|
+
chatLLM.WaitingSound(false);
|
|
2543
|
+
console.error('Error:', error);
|
|
2544
|
+
chatLLM.DisplayChatMessage('OpenAI', 'Error processing request.', true);
|
|
2545
|
+
// also todo: handle errors somehow
|
|
2546
|
+
}
|
|
2547
|
+
}
|
|
2548
|
+
|
|
2170
2549
|
async GeminiPrompt(text, imgBase64 = null) {
|
|
2171
2550
|
// https://ai.google.dev/docs/gemini_api_overview#node.js
|
|
2172
2551
|
try {
|
|
@@ -2366,7 +2745,7 @@ class ChatLLM {
|
|
|
2366
2745
|
var jpegData = canvas.toDataURL('image/jpeg', 0.9); // 0.9 is the quality parameter
|
|
2367
2746
|
if (model == 'openai') {
|
|
2368
2747
|
resolve(jpegData);
|
|
2369
|
-
} else if (model == 'gemini') {
|
|
2748
|
+
} else if (model == 'gemini' || model == 'claude') {
|
|
2370
2749
|
let base64Data = jpegData.split(',')[1];
|
|
2371
2750
|
resolve(base64Data);
|
|
2372
2751
|
//resolve(jpegData);
|
|
@@ -2716,9 +3095,13 @@ class Helper {
|
|
|
2716
3095
|
* @class
|
|
2717
3096
|
*/
|
|
2718
3097
|
class Tracker {
|
|
3098
|
+
// URL
|
|
3099
|
+
logUrl =
|
|
3100
|
+
'https://maidr-service.azurewebsites.net/api/log?code=I8Aa2PlPspjQ8Hks0QzGyszP8_i2-XJ3bq7Xh8-ykEe4AzFuYn_QWA%3D%3D'; // TODO Replace
|
|
3101
|
+
isLocal = false;
|
|
3102
|
+
|
|
2719
3103
|
constructor() {
|
|
2720
3104
|
this.DataSetup();
|
|
2721
|
-
constants.isTracking = true;
|
|
2722
3105
|
}
|
|
2723
3106
|
|
|
2724
3107
|
/**
|
|
@@ -2726,14 +3109,14 @@ class Tracker {
|
|
|
2726
3109
|
*/
|
|
2727
3110
|
DataSetup() {
|
|
2728
3111
|
let prevData = this.GetTrackerData();
|
|
2729
|
-
if (prevData) {
|
|
2730
|
-
// good to go already, do nothing, but make sure we have our containers
|
|
2731
|
-
} else {
|
|
3112
|
+
if (!this.isLocal || !prevData) {
|
|
2732
3113
|
let data = {};
|
|
2733
3114
|
data.userAgent = Object.assign(navigator.userAgent);
|
|
2734
3115
|
data.vendor = Object.assign(navigator.vendor);
|
|
2735
3116
|
data.language = Object.assign(navigator.language);
|
|
2736
3117
|
data.platform = Object.assign(navigator.platform);
|
|
3118
|
+
data.geolocation = Object.assign(navigator.geolocation);
|
|
3119
|
+
data.log_type = 'system_data';
|
|
2737
3120
|
data.events = [];
|
|
2738
3121
|
data.settings = [];
|
|
2739
3122
|
|
|
@@ -2758,8 +3141,33 @@ class Tracker {
|
|
|
2758
3141
|
* Saves the tracker data to local storage.
|
|
2759
3142
|
* @param {Object} data - The data to be saved.
|
|
2760
3143
|
*/
|
|
2761
|
-
SaveTrackerData(data) {
|
|
2762
|
-
|
|
3144
|
+
async SaveTrackerData(data) {
|
|
3145
|
+
console.log('about to save data', data);
|
|
3146
|
+
if (this.isLocal) {
|
|
3147
|
+
localStorage.setItem(constants.project_id, JSON.stringify(data));
|
|
3148
|
+
} else {
|
|
3149
|
+
// test this first
|
|
3150
|
+
try {
|
|
3151
|
+
const response = await fetch(this.logUrl, {
|
|
3152
|
+
method: 'POST',
|
|
3153
|
+
headers: {
|
|
3154
|
+
'Content-Type': 'application/json',
|
|
3155
|
+
},
|
|
3156
|
+
body: JSON.stringify(data),
|
|
3157
|
+
});
|
|
3158
|
+
|
|
3159
|
+
if (!response.ok) {
|
|
3160
|
+
throw new Error(`HTTP error! status: ${response.status}`);
|
|
3161
|
+
}
|
|
3162
|
+
|
|
3163
|
+
const result = await response.json();
|
|
3164
|
+
console.log('Data saved successfully:', result);
|
|
3165
|
+
return result;
|
|
3166
|
+
} catch (error) {
|
|
3167
|
+
console.error('Error saving data:', error);
|
|
3168
|
+
return null;
|
|
3169
|
+
}
|
|
3170
|
+
}
|
|
2763
3171
|
}
|
|
2764
3172
|
|
|
2765
3173
|
/**
|
|
@@ -2792,6 +3200,10 @@ class Tracker {
|
|
|
2792
3200
|
// don't store their auth keys
|
|
2793
3201
|
settings.openAIAuthKey = 'hidden';
|
|
2794
3202
|
settings.geminiAuthKey = 'hidden';
|
|
3203
|
+
if (constants.emailAuthKey) {
|
|
3204
|
+
settings.username = constants.emailAuthKey;
|
|
3205
|
+
}
|
|
3206
|
+
settings;
|
|
2795
3207
|
this.SetData('settings', settings);
|
|
2796
3208
|
}
|
|
2797
3209
|
}
|
|
@@ -2810,6 +3222,9 @@ class Tracker {
|
|
|
2810
3222
|
eventToLog.altKey = Object.assign(e.altKey);
|
|
2811
3223
|
eventToLog.ctrlKey = Object.assign(e.ctrlKey);
|
|
2812
3224
|
eventToLog.shiftKey = Object.assign(e.shiftKey);
|
|
3225
|
+
if (constants.emailAuthKey) {
|
|
3226
|
+
eventToLog.username = Object.assign(constants.emailAuthKey);
|
|
3227
|
+
}
|
|
2813
3228
|
if (e.path) {
|
|
2814
3229
|
eventToLog.focus = Object.assign(e.path[0].tagName);
|
|
2815
3230
|
}
|
|
@@ -3003,18 +3418,29 @@ class Tracker {
|
|
|
3003
3418
|
//console.log('logged an event');
|
|
3004
3419
|
}
|
|
3005
3420
|
|
|
3421
|
+
/**
|
|
3422
|
+
* Saves data to the server using a POST request.
|
|
3423
|
+
* @param {Object} logData - The data to be saved.
|
|
3424
|
+
* @returns {Promise<Object>} The result of the save operation.
|
|
3425
|
+
*/
|
|
3426
|
+
|
|
3006
3427
|
SetData(key, value) {
|
|
3007
|
-
|
|
3008
|
-
|
|
3009
|
-
|
|
3010
|
-
|
|
3011
|
-
|
|
3012
|
-
|
|
3013
|
-
data[key]
|
|
3428
|
+
if (this.isLocal) {
|
|
3429
|
+
let data = this.GetTrackerData();
|
|
3430
|
+
let arrayKeys = ['events', 'ChatHistory', 'settings'];
|
|
3431
|
+
if (!arrayKeys.includes(key)) {
|
|
3432
|
+
data[key] = value;
|
|
3433
|
+
} else {
|
|
3434
|
+
if (!data[key]) {
|
|
3435
|
+
data[key] = [];
|
|
3436
|
+
}
|
|
3437
|
+
data[key].push(value);
|
|
3014
3438
|
}
|
|
3015
|
-
|
|
3439
|
+
this.SaveTrackerData(data);
|
|
3440
|
+
} else {
|
|
3441
|
+
value['log_type'] = key;
|
|
3442
|
+
this.SaveTrackerData(value);
|
|
3016
3443
|
}
|
|
3017
|
-
this.SaveTrackerData(data);
|
|
3018
3444
|
}
|
|
3019
3445
|
|
|
3020
3446
|
/**
|
|
@@ -11121,47 +11547,6 @@ document.addEventListener('DOMContentLoaded', function (e) {
|
|
|
11121
11547
|
|
|
11122
11548
|
// init components like alt text on just the first chart
|
|
11123
11549
|
CreateChartComponents(firstMaidr, true);
|
|
11124
|
-
|
|
11125
|
-
// events etc for user study page
|
|
11126
|
-
// run tracker stuff only on user study page
|
|
11127
|
-
if (constants.canTrack) {
|
|
11128
|
-
window.tracker = new Tracker();
|
|
11129
|
-
if (document.getElementById('download_data_trigger')) {
|
|
11130
|
-
// we're on the intro page, so enable the download data button
|
|
11131
|
-
document
|
|
11132
|
-
.getElementById('download_data_trigger')
|
|
11133
|
-
.addEventListener('click', function (e) {
|
|
11134
|
-
tracker.DownloadTrackerData();
|
|
11135
|
-
});
|
|
11136
|
-
}
|
|
11137
|
-
|
|
11138
|
-
// general events
|
|
11139
|
-
document.addEventListener('keydown', function (e) {
|
|
11140
|
-
// reset tracking with Ctrl + F5 / command + F5, and Ctrl + Shift + R / command + Shift + R
|
|
11141
|
-
// future todo: this should probably be a button with a confirmation. This is dangerous
|
|
11142
|
-
if (
|
|
11143
|
-
(e.key == 'F5' && (constants.isMac ? e.metaKey : e.ctrlKey)) ||
|
|
11144
|
-
(e.key == 'R' && (constants.isMac ? e.metaKey : e.ctrlKey))
|
|
11145
|
-
) {
|
|
11146
|
-
e.preventDefault();
|
|
11147
|
-
tracker.Delete();
|
|
11148
|
-
location.reload(true);
|
|
11149
|
-
}
|
|
11150
|
-
|
|
11151
|
-
// main event tracker, built for individual charts
|
|
11152
|
-
if (e.key == 'F10') {
|
|
11153
|
-
tracker.DownloadTrackerData();
|
|
11154
|
-
} else {
|
|
11155
|
-
if (plot) {
|
|
11156
|
-
tracker.LogEvent(e);
|
|
11157
|
-
}
|
|
11158
|
-
}
|
|
11159
|
-
|
|
11160
|
-
// Stuff to only run if we're on a chart (so check if the info div exists?)
|
|
11161
|
-
if (document.getElementById('info')) {
|
|
11162
|
-
}
|
|
11163
|
-
});
|
|
11164
|
-
}
|
|
11165
11550
|
});
|
|
11166
11551
|
|
|
11167
11552
|
/**
|
|
@@ -11181,6 +11566,7 @@ function InitMaidr(thisMaidr) {
|
|
|
11181
11566
|
}
|
|
11182
11567
|
DestroyChartComponents(); // destroy so that we start fresh, in case we've created on the wrong chart
|
|
11183
11568
|
CreateChartComponents(singleMaidr);
|
|
11569
|
+
InitTracker();
|
|
11184
11570
|
|
|
11185
11571
|
window.menu = new Menu();
|
|
11186
11572
|
window.chatLLM = new ChatLLM();
|
|
@@ -11586,6 +11972,44 @@ function CreateChartComponents(thisMaidr, chartOnly = false) {
|
|
|
11586
11972
|
}
|
|
11587
11973
|
}
|
|
11588
11974
|
|
|
11975
|
+
function InitTracker() {
|
|
11976
|
+
// events etc for user study page
|
|
11977
|
+
// run tracker stuff only on user study page
|
|
11978
|
+
if (constants.canTrack) {
|
|
11979
|
+
window.tracker = new Tracker();
|
|
11980
|
+
if (document.getElementById('download_data_trigger')) {
|
|
11981
|
+
// we're on the intro page, so enable the download data button
|
|
11982
|
+
document
|
|
11983
|
+
.getElementById('download_data_trigger')
|
|
11984
|
+
.addEventListener('click', function (e) {
|
|
11985
|
+
tracker.DownloadTrackerData();
|
|
11986
|
+
});
|
|
11987
|
+
}
|
|
11988
|
+
|
|
11989
|
+
// general events
|
|
11990
|
+
document.addEventListener('keydown', function (e) {
|
|
11991
|
+
// reset tracking with Ctrl + F5 / command + F5, and Ctrl + Shift + R / command + Shift + R
|
|
11992
|
+
// future todo: this should probably be a button with a confirmation. This is dangerous
|
|
11993
|
+
if (
|
|
11994
|
+
(e.key == 'F5' && (constants.isMac ? e.metaKey : e.ctrlKey)) ||
|
|
11995
|
+
(e.key == 'R' && (constants.isMac ? e.metaKey : e.ctrlKey))
|
|
11996
|
+
) {
|
|
11997
|
+
e.preventDefault();
|
|
11998
|
+
tracker.Delete();
|
|
11999
|
+
location.reload(true);
|
|
12000
|
+
}
|
|
12001
|
+
|
|
12002
|
+
// main event tracker, built for individual charts
|
|
12003
|
+
if (e.key == 'F10') {
|
|
12004
|
+
tracker.DownloadTrackerData();
|
|
12005
|
+
} else {
|
|
12006
|
+
if (plot) {
|
|
12007
|
+
tracker.LogEvent(e);
|
|
12008
|
+
}
|
|
12009
|
+
}
|
|
12010
|
+
});
|
|
12011
|
+
}
|
|
12012
|
+
}
|
|
11589
12013
|
/**
|
|
11590
12014
|
* Removes all chart components from the DOM and resets related variables to null.
|
|
11591
12015
|
* @function
|