maidr 2.7.1 → 2.8.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();
@@ -1157,7 +1159,11 @@ class ChatLLM {
1157
1159
  // kill more than 2 newlines in a row
1158
1160
  markdown = markdown.replace(/\n{3,}/g, '\n\n');
1159
1161
 
1160
- navigator.clipboard.writeText(markdown);
1162
+ try {
1163
+ navigator.clipboard.writeText(markdown);
1164
+ } catch (err) {
1165
+ console.error('Failed to copy: ', err);
1166
+ }
1161
1167
  return markdown;
1162
1168
  }
1163
1169
  }
@@ -1219,14 +1225,30 @@ class ChatLLM {
1219
1225
  * @returns {void}
1220
1226
  */
1221
1227
  async Submit(text, firsttime = false) {
1228
+ // misc init
1229
+ let img = null;
1230
+ this.firstMulti = true;
1231
+
1232
+ // 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
1233
+ if (
1234
+ (this.firstOpen || constants.LLMModel == 'gemini') &&
1235
+ !firsttime &&
1236
+ constants.verboseText.length > 0
1237
+ ) {
1238
+ text =
1239
+ "Here is the current position in the chart; no response necessarily needed, use this info only if it's relevant to future questions: " +
1240
+ constants.verboseText +
1241
+ '. My question is: ' +
1242
+ text;
1243
+
1244
+ this.firstOpen = false;
1245
+ }
1246
+
1222
1247
  // start waiting sound
1223
1248
  if (constants.playLLMWaitingSound) {
1224
1249
  this.WaitingSound(true);
1225
1250
  }
1226
1251
 
1227
- let img = null;
1228
- this.firstMulti = true;
1229
-
1230
1252
  if (constants.LLMOpenAiMulti || constants.LLMModel == 'openai') {
1231
1253
  if (firsttime) {
1232
1254
  img = await this.ConvertSVGtoJPG(singleMaidr.id, 'openai');
@@ -1640,6 +1662,7 @@ class ChatLLM {
1640
1662
  document.getElementById('chatLLM_modal_backdrop').classList.add('hidden');
1641
1663
  this.whereWasMyFocus.focus();
1642
1664
  this.whereWasMyFocus = null;
1665
+ this.firstOpen = true;
1643
1666
  }
1644
1667
  }
1645
1668
 
@@ -2305,7 +2328,7 @@ class Tracker {
2305
2328
  //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
2329
 
2307
2330
  this.SetData('events', eventToLog);
2308
- console.log('logged an event');
2331
+ //console.log('logged an event');
2309
2332
  }
2310
2333
 
2311
2334
  SetData(key, value) {
@@ -3306,9 +3329,10 @@ class Display {
3306
3329
 
3307
3330
  let output = '';
3308
3331
  let verboseText = '';
3332
+ let terseText = '';
3309
3333
  let reviewText = '';
3310
3334
  if (constants.chartType == 'bar') {
3311
- // {legend x} is {colname x}, {legend y} is {value y}
3335
+ // verbose: {legend x} is {colname x}, {legend y} is {value y}
3312
3336
  if (plot.columnLabels[position.x]) {
3313
3337
  if (plot.plotLegend.x.length > 0) {
3314
3338
  verboseText += plot.plotLegend.x + ' is ';
@@ -3321,20 +3345,16 @@ class Display {
3321
3345
  }
3322
3346
  verboseText += plot.plotData[position.x];
3323
3347
  }
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
- }
3348
+ // terse: {colname} {value}
3349
+ terseText +=
3350
+ '<p>' +
3351
+ plot.columnLabels[position.x] +
3352
+ ' ' +
3353
+ plot.plotData[position.x] +
3354
+ '</p>\n';
3355
+ verboseText = '<p>' + verboseText + '</p>\n';
3337
3356
  } else if (constants.chartType == 'heat') {
3357
+ // verbose
3338
3358
  // col name and value
3339
3359
  if (constants.navigation == 1) {
3340
3360
  verboseText +=
@@ -3367,31 +3387,25 @@ class Display {
3367
3387
  verboseText += plot.data[position.y][position.x];
3368
3388
  // }
3369
3389
  }
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';
3390
+ // terse: value only
3391
+ if (constants.navigation == 1) {
3392
+ // column navigation
3393
+ terseText +=
3394
+ '<p>' +
3395
+ plot.x_labels[position.x] +
3396
+ ', ' +
3397
+ plot.data[position.y][position.x] +
3398
+ '</p>\n';
3399
+ } else {
3400
+ // row navigation
3401
+ terseText +=
3402
+ '<p>' +
3403
+ plot.y_labels[position.y] +
3404
+ ', ' +
3405
+ plot.data[position.y][position.x] +
3406
+ '</p>\n';
3394
3407
  }
3408
+ verboseText = '<p>' + verboseText + '</p>\n';
3395
3409
  } else if (constants.chartType == 'box') {
3396
3410
  // setup
3397
3411
  let val = 0;
@@ -3402,8 +3416,6 @@ class Display {
3402
3416
  let sectionKey = plot.GetSectionKey(
3403
3417
  constants.plotOrientation == 'vert' ? position.y : position.x
3404
3418
  );
3405
- let textTerse = '';
3406
- let textVerbose = '';
3407
3419
 
3408
3420
  if (sectionKey == 'lower_outlier' || sectionKey == 'upper_outlier') {
3409
3421
  isOutlier = true;
@@ -3422,67 +3434,64 @@ class Display {
3422
3434
 
3423
3435
  // group label for verbose
3424
3436
  if (constants.navigation) {
3425
- if (plot.x_group_label) textVerbose += plot.x_group_label;
3437
+ if (plot.x_group_label) verboseText += plot.x_group_label;
3426
3438
  } else if (!constants.navigation) {
3427
- if (plot.y_group_label) textVerbose += plot.y_group_label;
3439
+ if (plot.y_group_label) verboseText += plot.y_group_label;
3428
3440
  }
3429
3441
  // and axes label
3430
3442
  if (constants.navigation) {
3431
3443
  if (plot.x_labels[plotPos]) {
3432
- textVerbose += ' is ';
3433
- textTerse += plot.x_labels[plotPos] + ', ';
3434
- textVerbose += plot.x_labels[plotPos] + ', ';
3444
+ verboseText += ' is ';
3445
+ terseText += plot.x_labels[plotPos] + ', ';
3446
+ verboseText += plot.x_labels[plotPos] + ', ';
3435
3447
  } else {
3436
- textVerbose += ', ';
3448
+ verboseText += ', ';
3437
3449
  }
3438
3450
  } else if (!constants.navigation) {
3439
3451
  if (plot.y_labels[plotPos]) {
3440
- textVerbose += ' is ';
3441
- textTerse += plot.y_labels[plotPos] + ', ';
3442
- textVerbose += plot.y_labels[plotPos] + ', ';
3452
+ verboseText += ' is ';
3453
+ terseText += plot.y_labels[plotPos] + ', ';
3454
+ verboseText += plot.y_labels[plotPos] + ', ';
3443
3455
  } else {
3444
- textVerbose += ', ';
3456
+ verboseText += ', ';
3445
3457
  }
3446
3458
  }
3447
3459
  // outliers
3448
3460
  if (isOutlier) {
3449
- textTerse += numPoints + ' ';
3450
- textVerbose += numPoints + ' ';
3461
+ terseText += numPoints + ' ';
3462
+ verboseText += numPoints + ' ';
3451
3463
  }
3452
3464
  // label
3453
- textVerbose += resources.GetString(sectionKey);
3454
- if (numPoints == 1) textVerbose += ' is ';
3465
+ verboseText += resources.GetString(sectionKey);
3466
+ if (numPoints == 1) verboseText += ' is ';
3455
3467
  else {
3456
- textVerbose += 's ';
3457
- if (numPoints > 1) textVerbose += ' are ';
3468
+ verboseText += 's ';
3469
+ if (numPoints > 1) verboseText += ' are ';
3458
3470
  }
3459
3471
  if (
3460
3472
  isOutlier ||
3461
3473
  (constants.navigation && constants.plotOrientation == 'horz') ||
3462
3474
  (!constants.navigation && constants.plotOrientation == 'vert')
3463
3475
  ) {
3464
- textTerse += resources.GetString(sectionKey);
3476
+ terseText += resources.GetString(sectionKey);
3465
3477
 
3466
3478
  // grammar
3467
3479
  if (numPoints != 1) {
3468
- textTerse += 's';
3480
+ terseText += 's';
3469
3481
  }
3470
- textTerse += ' ';
3482
+ terseText += ' ';
3471
3483
  }
3472
3484
  // val
3473
3485
  if (plot.plotData[plotPos][sectionKey] == null && !isOutlier) {
3474
- textTerse += 'empty';
3475
- textVerbose += 'empty';
3486
+ terseText += 'empty';
3487
+ verboseText += 'empty';
3476
3488
  } else {
3477
- textTerse += val;
3478
- textVerbose += val;
3489
+ terseText += val;
3490
+ verboseText += val;
3479
3491
  }
3480
3492
 
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';
3493
+ verboseText = '<p>' + verboseText + '</p>\n';
3494
+ terseText = '<p>' + terseText + '</p>\n';
3486
3495
  } else if (
3487
3496
  [].concat(singleMaidr.type).includes('point') ||
3488
3497
  [].concat(singleMaidr.type).includes('smooth')
@@ -3499,20 +3508,15 @@ class Display {
3499
3508
  plot.y[position.x].join(', ') +
3500
3509
  ']';
3501
3510
 
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
- }
3511
+ // terse
3512
+ terseText +=
3513
+ '<p>' +
3514
+ plot.x[position.x] +
3515
+ ', ' +
3516
+ '[' +
3517
+ plot.y[position.x].join(', ') +
3518
+ ']' +
3519
+ '</p>\n';
3516
3520
  } else if (constants.chartType == 'smooth') {
3517
3521
  // best fit smooth layer
3518
3522
  verboseText +=
@@ -3524,42 +3528,31 @@ class Display {
3524
3528
  ' ' +
3525
3529
  plot.curvePoints[positionL1.x]; // verbose mode: x and y values
3526
3530
 
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';
3531
+ // terse mode: gradient trend
3532
3532
 
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
- }
3533
+ // display absolute gradient of the graph
3534
+ terseText += '<p>' + plot.curvePoints[positionL1.x] + '<p>\n';
3538
3535
  }
3539
- if (constants.textMode == 'verbose')
3540
- output = '<p>' + verboseText + '</p>\n';
3536
+ verboseText = '<p>' + verboseText + '</p>\n';
3541
3537
  } 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
- }
3538
+ // terse: {x}, {y}
3539
+ terseText =
3540
+ '<p>' +
3541
+ plot.plotData[position.x].x +
3542
+ ', ' +
3543
+ plot.plotData[position.x].y +
3544
+ '</p>\n';
3545
+ // verbose: {xlabel} is xmin through xmax, {ylabel} is y
3546
+ verboseText = '<p>';
3547
+ if (plot.legendX) {
3548
+ verboseText = plot.legendX + ' is ';
3549
+ }
3550
+ verboseText += plot.plotData[position.x].xmin;
3551
+ verboseText += ' through ' + plot.plotData[position.x].xmax + ', ';
3552
+ if (plot.legendY) {
3553
+ verboseText += plot.legendY + ' is ';
3554
+ }
3555
+ verboseText += plot.plotData[position.x].y;
3563
3556
  } else if (constants.chartType == 'line') {
3564
3557
  // line layer
3565
3558
  if (plot.plotLegend) {
@@ -3571,19 +3564,15 @@ class Display {
3571
3564
  }
3572
3565
  verboseText += plot.pointValuesY[position.x];
3573
3566
 
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
- }
3567
+ // terse
3568
+ terseText +=
3569
+ '<p>' +
3570
+ plot.pointValuesX[position.x] +
3571
+ ', ' +
3572
+ plot.pointValuesY[position.x] +
3573
+ '</p>\n';
3574
+
3575
+ verboseText = '<p>' + verboseText + '</p>\n';
3587
3576
  } else if (
3588
3577
  constants.chartType == 'stacked_bar' ||
3589
3578
  constants.chartType == 'stacked_normalized_bar' ||
@@ -3600,30 +3589,33 @@ class Display {
3600
3589
  verboseText += plot.fill[position.y] + ', ';
3601
3590
  verboseText += 'value is ' + plot.plotData[position.x][position.y];
3602
3591
 
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
- }
3592
+ // navigation == 1 ? {colname x} : {colname y} is {plotData[x][y]}
3593
+ if (constants.navigation == 1) {
3594
+ terseText +=
3595
+ '<p>' +
3596
+ plot.level[position.x] +
3597
+ ' is ' +
3598
+ plot.plotData[position.x][position.y] +
3599
+ '</p>\n';
3622
3600
  } else {
3623
- output += '<p>' + verboseText + '</p>\n';
3601
+ terseText +=
3602
+ '<p>' +
3603
+ plot.fill[position.y] +
3604
+ ' is ' +
3605
+ plot.plotData[position.x][position.y] +
3606
+ '</p>\n';
3624
3607
  }
3608
+ verboseText = '<p>' + verboseText + '</p>\n';
3625
3609
  }
3626
3610
 
3611
+ // set outout text
3612
+ if (constants.textMode == 'verbose') {
3613
+ output = verboseText;
3614
+ } else if (constants.textMode == 'terse') {
3615
+ output = terseText;
3616
+ }
3617
+ constants.verboseText = verboseText;
3618
+
3627
3619
  if (constants.infoDiv) constants.infoDiv.innerHTML = output;
3628
3620
  if (constants.review) {
3629
3621
  if (output.length > 0) {
@@ -7571,6 +7563,9 @@ class Control {
7571
7563
  // caption
7572
7564
  display.displayInfo('caption', plot.caption);
7573
7565
  pressedL = false;
7566
+ } else if (e.key == 'f') {
7567
+ display.displayInfo('fill', plot.fill);
7568
+ pressedL = false;
7574
7569
  } else if (e.key != 'l') {
7575
7570
  pressedL = false;
7576
7571
  }