maidr 2.7.1 → 2.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/maidr.js CHANGED
@@ -88,6 +88,7 @@ class Constants {
88
88
  skillLevel = 'basic'; // basic / intermediate / expert
89
89
  skillLevelOther = ''; // custom skill level
90
90
  autoInitLLM = true; // auto initialize LLM on page load
91
+ verboseText = '';
91
92
 
92
93
  // user controls (not exposed to menu, with shortcuts usually)
93
94
  showDisplay = 1; // true / false
@@ -924,6 +925,7 @@ class ChatLLM {
924
925
  constructor() {
925
926
  this.firstTime = true;
926
927
  this.firstMulti = true;
928
+ this.firstOpen = true;
927
929
  this.shown = false;
928
930
  this.CreateComponent();
929
931
  this.SetEvents();
@@ -1132,7 +1134,8 @@ class ChatLLM {
1132
1134
  }
1133
1135
  } else if (e.type == 'keyup') {
1134
1136
  // check for alt shift c
1135
- if (e.key == 'C' && (e.altKey || e.metaKey) && e.shiftKey) {
1137
+ if (e.key == 'C' && (e.ctrlKey || e.metaKey) && e.shiftKey) {
1138
+ e.preventDefault();
1136
1139
  // get the last message
1137
1140
  let elem = document.querySelector(
1138
1141
  '#chatLLM_chat_history > .chatLLM_message_other:last-of-type'
@@ -1140,6 +1143,10 @@ class ChatLLM {
1140
1143
  if (elem) {
1141
1144
  text = elem.innerHTML;
1142
1145
  }
1146
+ } else if (e.key == 'A' && (e.ctrlKey || e.metaKey) && e.shiftKey) {
1147
+ e.preventDefault();
1148
+ // get html of the full chat history
1149
+ text = document.getElementById('chatLLM_chat_history').innerHTML;
1143
1150
  }
1144
1151
  }
1145
1152
 
@@ -1157,7 +1164,11 @@ class ChatLLM {
1157
1164
  // kill more than 2 newlines in a row
1158
1165
  markdown = markdown.replace(/\n{3,}/g, '\n\n');
1159
1166
 
1160
- navigator.clipboard.writeText(markdown);
1167
+ try {
1168
+ navigator.clipboard.writeText(markdown);
1169
+ } catch (err) {
1170
+ console.error('Failed to copy: ', err);
1171
+ }
1161
1172
  return markdown;
1162
1173
  }
1163
1174
  }
@@ -1219,14 +1230,30 @@ class ChatLLM {
1219
1230
  * @returns {void}
1220
1231
  */
1221
1232
  async Submit(text, firsttime = false) {
1233
+ // misc init
1234
+ let img = null;
1235
+ this.firstMulti = true;
1236
+
1237
+ // 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
1238
+ if (
1239
+ (this.firstOpen || constants.LLMModel == 'gemini') &&
1240
+ !firsttime &&
1241
+ constants.verboseText.length > 0
1242
+ ) {
1243
+ text =
1244
+ "Here is the current position in the chart; no response necessarily needed, use this info only if it's relevant to future questions: " +
1245
+ constants.verboseText +
1246
+ '. My question is: ' +
1247
+ text;
1248
+
1249
+ this.firstOpen = false;
1250
+ }
1251
+
1222
1252
  // start waiting sound
1223
1253
  if (constants.playLLMWaitingSound) {
1224
1254
  this.WaitingSound(true);
1225
1255
  }
1226
1256
 
1227
- let img = null;
1228
- this.firstMulti = true;
1229
-
1230
1257
  if (constants.LLMOpenAiMulti || constants.LLMModel == 'openai') {
1231
1258
  if (firsttime) {
1232
1259
  img = await this.ConvertSVGtoJPG(singleMaidr.id, 'openai');
@@ -1640,6 +1667,7 @@ class ChatLLM {
1640
1667
  document.getElementById('chatLLM_modal_backdrop').classList.add('hidden');
1641
1668
  this.whereWasMyFocus.focus();
1642
1669
  this.whereWasMyFocus = null;
1670
+ this.firstOpen = true;
1643
1671
  }
1644
1672
  }
1645
1673
 
@@ -2305,7 +2333,7 @@ class Tracker {
2305
2333
  //console.log("x_tickmark: '", x_tickmark, "', y_tickmark: '", y_tickmark, "', x_label: '", x_label, "', y_label: '", y_label, "', value: '", value, "', fill_value: '", fill_value);
2306
2334
 
2307
2335
  this.SetData('events', eventToLog);
2308
- console.log('logged an event');
2336
+ //console.log('logged an event');
2309
2337
  }
2310
2338
 
2311
2339
  SetData(key, value) {
@@ -3306,9 +3334,10 @@ class Display {
3306
3334
 
3307
3335
  let output = '';
3308
3336
  let verboseText = '';
3337
+ let terseText = '';
3309
3338
  let reviewText = '';
3310
3339
  if (constants.chartType == 'bar') {
3311
- // {legend x} is {colname x}, {legend y} is {value y}
3340
+ // verbose: {legend x} is {colname x}, {legend y} is {value y}
3312
3341
  if (plot.columnLabels[position.x]) {
3313
3342
  if (plot.plotLegend.x.length > 0) {
3314
3343
  verboseText += plot.plotLegend.x + ' is ';
@@ -3321,20 +3350,16 @@ class Display {
3321
3350
  }
3322
3351
  verboseText += plot.plotData[position.x];
3323
3352
  }
3324
- if (constants.textMode == 'off') {
3325
- // do nothing :D
3326
- } else if (constants.textMode == 'terse') {
3327
- // {colname} {value}
3328
- output +=
3329
- '<p>' +
3330
- plot.columnLabels[position.x] +
3331
- ' ' +
3332
- plot.plotData[position.x] +
3333
- '</p>\n';
3334
- } else if (constants.textMode == 'verbose') {
3335
- output += '<p>' + verboseText + '</p>\n';
3336
- }
3353
+ // terse: {colname} {value}
3354
+ terseText +=
3355
+ '<p>' +
3356
+ plot.columnLabels[position.x] +
3357
+ ' ' +
3358
+ plot.plotData[position.x] +
3359
+ '</p>\n';
3360
+ verboseText = '<p>' + verboseText + '</p>\n';
3337
3361
  } else if (constants.chartType == 'heat') {
3362
+ // verbose
3338
3363
  // col name and value
3339
3364
  if (constants.navigation == 1) {
3340
3365
  verboseText +=
@@ -3367,31 +3392,25 @@ class Display {
3367
3392
  verboseText += plot.data[position.y][position.x];
3368
3393
  // }
3369
3394
  }
3370
- // terse and verbose alternate between columns and rows
3371
- if (constants.textMode == 'off') {
3372
- // do nothing :D
3373
- } else if (constants.textMode == 'terse') {
3374
- // value only
3375
- if (constants.navigation == 1) {
3376
- // column navigation
3377
- output +=
3378
- '<p>' +
3379
- plot.x_labels[position.x] +
3380
- ', ' +
3381
- plot.data[position.y][position.x] +
3382
- '</p>\n';
3383
- } else {
3384
- // row navigation
3385
- output +=
3386
- '<p>' +
3387
- plot.y_labels[position.y] +
3388
- ', ' +
3389
- plot.data[position.y][position.x] +
3390
- '</p>\n';
3391
- }
3392
- } else if (constants.textMode == 'verbose') {
3393
- output += '<p>' + verboseText + '</p>\n';
3395
+ // terse: value only
3396
+ if (constants.navigation == 1) {
3397
+ // column navigation
3398
+ terseText +=
3399
+ '<p>' +
3400
+ plot.x_labels[position.x] +
3401
+ ', ' +
3402
+ plot.data[position.y][position.x] +
3403
+ '</p>\n';
3404
+ } else {
3405
+ // row navigation
3406
+ terseText +=
3407
+ '<p>' +
3408
+ plot.y_labels[position.y] +
3409
+ ', ' +
3410
+ plot.data[position.y][position.x] +
3411
+ '</p>\n';
3394
3412
  }
3413
+ verboseText = '<p>' + verboseText + '</p>\n';
3395
3414
  } else if (constants.chartType == 'box') {
3396
3415
  // setup
3397
3416
  let val = 0;
@@ -3402,8 +3421,6 @@ class Display {
3402
3421
  let sectionKey = plot.GetSectionKey(
3403
3422
  constants.plotOrientation == 'vert' ? position.y : position.x
3404
3423
  );
3405
- let textTerse = '';
3406
- let textVerbose = '';
3407
3424
 
3408
3425
  if (sectionKey == 'lower_outlier' || sectionKey == 'upper_outlier') {
3409
3426
  isOutlier = true;
@@ -3422,67 +3439,64 @@ class Display {
3422
3439
 
3423
3440
  // group label for verbose
3424
3441
  if (constants.navigation) {
3425
- if (plot.x_group_label) textVerbose += plot.x_group_label;
3442
+ if (plot.x_group_label) verboseText += plot.x_group_label;
3426
3443
  } else if (!constants.navigation) {
3427
- if (plot.y_group_label) textVerbose += plot.y_group_label;
3444
+ if (plot.y_group_label) verboseText += plot.y_group_label;
3428
3445
  }
3429
3446
  // and axes label
3430
3447
  if (constants.navigation) {
3431
3448
  if (plot.x_labels[plotPos]) {
3432
- textVerbose += ' is ';
3433
- textTerse += plot.x_labels[plotPos] + ', ';
3434
- textVerbose += plot.x_labels[plotPos] + ', ';
3449
+ verboseText += ' is ';
3450
+ terseText += plot.x_labels[plotPos] + ', ';
3451
+ verboseText += plot.x_labels[plotPos] + ', ';
3435
3452
  } else {
3436
- textVerbose += ', ';
3453
+ verboseText += ', ';
3437
3454
  }
3438
3455
  } else if (!constants.navigation) {
3439
3456
  if (plot.y_labels[plotPos]) {
3440
- textVerbose += ' is ';
3441
- textTerse += plot.y_labels[plotPos] + ', ';
3442
- textVerbose += plot.y_labels[plotPos] + ', ';
3457
+ verboseText += ' is ';
3458
+ terseText += plot.y_labels[plotPos] + ', ';
3459
+ verboseText += plot.y_labels[plotPos] + ', ';
3443
3460
  } else {
3444
- textVerbose += ', ';
3461
+ verboseText += ', ';
3445
3462
  }
3446
3463
  }
3447
3464
  // outliers
3448
3465
  if (isOutlier) {
3449
- textTerse += numPoints + ' ';
3450
- textVerbose += numPoints + ' ';
3466
+ terseText += numPoints + ' ';
3467
+ verboseText += numPoints + ' ';
3451
3468
  }
3452
3469
  // label
3453
- textVerbose += resources.GetString(sectionKey);
3454
- if (numPoints == 1) textVerbose += ' is ';
3470
+ verboseText += resources.GetString(sectionKey);
3471
+ if (numPoints == 1) verboseText += ' is ';
3455
3472
  else {
3456
- textVerbose += 's ';
3457
- if (numPoints > 1) textVerbose += ' are ';
3473
+ verboseText += 's ';
3474
+ if (numPoints > 1) verboseText += ' are ';
3458
3475
  }
3459
3476
  if (
3460
3477
  isOutlier ||
3461
3478
  (constants.navigation && constants.plotOrientation == 'horz') ||
3462
3479
  (!constants.navigation && constants.plotOrientation == 'vert')
3463
3480
  ) {
3464
- textTerse += resources.GetString(sectionKey);
3481
+ terseText += resources.GetString(sectionKey);
3465
3482
 
3466
3483
  // grammar
3467
3484
  if (numPoints != 1) {
3468
- textTerse += 's';
3485
+ terseText += 's';
3469
3486
  }
3470
- textTerse += ' ';
3487
+ terseText += ' ';
3471
3488
  }
3472
3489
  // val
3473
3490
  if (plot.plotData[plotPos][sectionKey] == null && !isOutlier) {
3474
- textTerse += 'empty';
3475
- textVerbose += 'empty';
3491
+ terseText += 'empty';
3492
+ verboseText += 'empty';
3476
3493
  } else {
3477
- textTerse += val;
3478
- textVerbose += val;
3494
+ terseText += val;
3495
+ verboseText += val;
3479
3496
  }
3480
3497
 
3481
- verboseText = textVerbose; // yeah it's an extra var, who cares
3482
- if (constants.textMode == 'verbose')
3483
- output = '<p>' + textVerbose + '</p>\n';
3484
- else if (constants.textMode == 'terse')
3485
- output = '<p>' + textTerse + '</p>\n';
3498
+ verboseText = '<p>' + verboseText + '</p>\n';
3499
+ terseText = '<p>' + terseText + '</p>\n';
3486
3500
  } else if (
3487
3501
  [].concat(singleMaidr.type).includes('point') ||
3488
3502
  [].concat(singleMaidr.type).includes('smooth')
@@ -3499,20 +3513,15 @@ class Display {
3499
3513
  plot.y[position.x].join(', ') +
3500
3514
  ']';
3501
3515
 
3502
- if (constants.textMode == 'off') {
3503
- // do nothing
3504
- } else if (constants.textMode == 'terse') {
3505
- output +=
3506
- '<p>' +
3507
- plot.x[position.x] +
3508
- ', ' +
3509
- '[' +
3510
- plot.y[position.x].join(', ') +
3511
- ']' +
3512
- '</p>\n';
3513
- } else if (constants.textMode == 'verbose') {
3514
- // set from verboseText
3515
- }
3516
+ // terse
3517
+ terseText +=
3518
+ '<p>' +
3519
+ plot.x[position.x] +
3520
+ ', ' +
3521
+ '[' +
3522
+ plot.y[position.x].join(', ') +
3523
+ ']' +
3524
+ '</p>\n';
3516
3525
  } else if (constants.chartType == 'smooth') {
3517
3526
  // best fit smooth layer
3518
3527
  verboseText +=
@@ -3524,42 +3533,31 @@ class Display {
3524
3533
  ' ' +
3525
3534
  plot.curvePoints[positionL1.x]; // verbose mode: x and y values
3526
3535
 
3527
- if (constants.textMode == 'off') {
3528
- // do nothing
3529
- } else if (constants.textMode == 'terse') {
3530
- // terse mode: gradient trend
3531
- // output += '<p>' + plot.gradient[positionL1.x] + '<p>\n';
3536
+ // terse mode: gradient trend
3532
3537
 
3533
- // display absolute gradient of the graph
3534
- output += '<p>' + plot.curvePoints[positionL1.x] + '<p>\n';
3535
- } else if (constants.textMode == 'verbose') {
3536
- // set from verboseText
3537
- }
3538
+ // display absolute gradient of the graph
3539
+ terseText += '<p>' + plot.curvePoints[positionL1.x] + '<p>\n';
3538
3540
  }
3539
- if (constants.textMode == 'verbose')
3540
- output = '<p>' + verboseText + '</p>\n';
3541
+ verboseText = '<p>' + verboseText + '</p>\n';
3541
3542
  } else if (constants.chartType == 'hist') {
3542
- if (constants.textMode == 'terse') {
3543
- // terse: {x}, {y}
3544
- output =
3545
- '<p>' +
3546
- plot.plotData[position.x].x +
3547
- ', ' +
3548
- plot.plotData[position.x].y +
3549
- '</p>\n';
3550
- } else if (constants.textMode == 'verbose') {
3551
- // verbose: {xlabel} is xmin through xmax, {ylabel} is y
3552
- output = '<p>';
3553
- if (plot.legendX) {
3554
- output = plot.legendX + ' is ';
3555
- }
3556
- output += plot.plotData[position.x].xmin;
3557
- output += ' through ' + plot.plotData[position.x].xmax + ', ';
3558
- if (plot.legendY) {
3559
- output += plot.legendY + ' is ';
3560
- }
3561
- output += plot.plotData[position.x].y;
3562
- }
3543
+ // terse: {x}, {y}
3544
+ terseText =
3545
+ '<p>' +
3546
+ plot.plotData[position.x].x +
3547
+ ', ' +
3548
+ plot.plotData[position.x].y +
3549
+ '</p>\n';
3550
+ // verbose: {xlabel} is xmin through xmax, {ylabel} is y
3551
+ verboseText = '<p>';
3552
+ if (plot.legendX) {
3553
+ verboseText = plot.legendX + ' is ';
3554
+ }
3555
+ verboseText += plot.plotData[position.x].xmin;
3556
+ verboseText += ' through ' + plot.plotData[position.x].xmax + ', ';
3557
+ if (plot.legendY) {
3558
+ verboseText += plot.legendY + ' is ';
3559
+ }
3560
+ verboseText += plot.plotData[position.x].y;
3563
3561
  } else if (constants.chartType == 'line') {
3564
3562
  // line layer
3565
3563
  if (plot.plotLegend) {
@@ -3571,19 +3569,15 @@ class Display {
3571
3569
  }
3572
3570
  verboseText += plot.pointValuesY[position.x];
3573
3571
 
3574
- if (constants.textMode == 'off') {
3575
- // do nothing
3576
- } else if (constants.textMode == 'terse') {
3577
- output +=
3578
- '<p>' +
3579
- plot.pointValuesX[position.x] +
3580
- ', ' +
3581
- plot.pointValuesY[position.x] +
3582
- '</p>\n';
3583
- } else if (constants.textMode == 'verbose') {
3584
- // set from verboseText
3585
- output += '<p>' + verboseText + '</p>\n';
3586
- }
3572
+ // terse
3573
+ terseText +=
3574
+ '<p>' +
3575
+ plot.pointValuesX[position.x] +
3576
+ ', ' +
3577
+ plot.pointValuesY[position.x] +
3578
+ '</p>\n';
3579
+
3580
+ verboseText = '<p>' + verboseText + '</p>\n';
3587
3581
  } else if (
3588
3582
  constants.chartType == 'stacked_bar' ||
3589
3583
  constants.chartType == 'stacked_normalized_bar' ||
@@ -3600,30 +3594,33 @@ class Display {
3600
3594
  verboseText += plot.fill[position.y] + ', ';
3601
3595
  verboseText += 'value is ' + plot.plotData[position.x][position.y];
3602
3596
 
3603
- if (constants.textMode == 'off') {
3604
- // do nothing
3605
- } else if (constants.textMode == 'terse') {
3606
- // navigation == 1 ? {colname x} : {colname y} is {plotData[x][y]}
3607
- if (constants.navigation == 1) {
3608
- output +=
3609
- '<p>' +
3610
- plot.level[position.x] +
3611
- ' is ' +
3612
- plot.plotData[position.x][position.y] +
3613
- '</p>\n';
3614
- } else {
3615
- output +=
3616
- '<p>' +
3617
- plot.fill[position.y] +
3618
- ' is ' +
3619
- plot.plotData[position.x][position.y] +
3620
- '</p>\n';
3621
- }
3597
+ // navigation == 1 ? {colname x} : {colname y} is {plotData[x][y]}
3598
+ if (constants.navigation == 1) {
3599
+ terseText +=
3600
+ '<p>' +
3601
+ plot.level[position.x] +
3602
+ ' is ' +
3603
+ plot.plotData[position.x][position.y] +
3604
+ '</p>\n';
3622
3605
  } else {
3623
- output += '<p>' + verboseText + '</p>\n';
3606
+ terseText +=
3607
+ '<p>' +
3608
+ plot.fill[position.y] +
3609
+ ' is ' +
3610
+ plot.plotData[position.x][position.y] +
3611
+ '</p>\n';
3624
3612
  }
3613
+ verboseText = '<p>' + verboseText + '</p>\n';
3625
3614
  }
3626
3615
 
3616
+ // set outout text
3617
+ if (constants.textMode == 'verbose') {
3618
+ output = verboseText;
3619
+ } else if (constants.textMode == 'terse') {
3620
+ output = terseText;
3621
+ }
3622
+ constants.verboseText = verboseText;
3623
+
3627
3624
  if (constants.infoDiv) constants.infoDiv.innerHTML = output;
3628
3625
  if (constants.review) {
3629
3626
  if (output.length > 0) {
@@ -7571,6 +7568,9 @@ class Control {
7571
7568
  // caption
7572
7569
  display.displayInfo('caption', plot.caption);
7573
7570
  pressedL = false;
7571
+ } else if (e.key == 'f') {
7572
+ display.displayInfo('fill', plot.fill);
7573
+ pressedL = false;
7574
7574
  } else if (e.key != 'l') {
7575
7575
  pressedL = false;
7576
7576
  }