<commit_before>import { claimsTooltipElement } from '../dom-elements.js';
import { stringifyIndentSpaces } from './utils.js';
import strings from '../strings.js';
import { 
  payloadElement,
  headerElement,
  decodedElement
} from '../dom-elements.js';

import tippy from 'tippy.js';

const timeClaims = ['exp', 'nbf', 'iat', 'auth_time', 'updated_at'];

function hideTooltip() {
  decodedElement._tippy.hide();
}

function showTooltip(text) {
  decodedElement.title = text;
  decodedElement._tippy.show();
}

function getTimeText(timeStr) {
  return (new Date(parseInt(timeStr, 10) * 1000)).toString();
}

function tooltipHandler(event) {
  const editor = event.currentTarget.querySelector('.CodeMirror').CodeMirror;

  if(!editor) {
    return;
  }

  const result = editor.coordsChar({
    left: event.pageX,
    top: event.pageY
  }, 'page');

  const line = editor.getLine(result.line);
  const matches = /"(.*)":\s*"?(.*)"?/.exec(line);

  if(!matches) {
    hideTooltip();
    return;
  }

  const claim = matches[1];  

  // If this is a time claim and the mouse cursor is on top of the time,
  // let the time tooltip handle this, do nothing.
  // TODO: merge both tooltip handlers?
  const claimEnd = line.indexOf(':');
  if(result.ch >= claimEnd && timeClaims.includes(claim)) {
    showTooltip(getTimeText(matches[2]));
    return;
  }

  const claimText = strings.common.claims[claim];
  if(!claimText) {
    hideTooltip();
    return;
  }

  showTooltip(claimText);
}

export function setupClaimsTooltip() {
  tippy(decodedElement, {    
    placement: 'left',
    arrow: true,
    followCursor: true,
    performance: true,
    size: 'large',
    dynamicTitle: true,
    arrowTransform: 'scale(0.75)',
    distance: 20
  });

  payloadElement.addEventListener('mousemove', tooltipHandler);
  headerElement.addEventListener('mousemove', tooltipHandler);<commit_msg>Improve behavior of claims tooltips, especially in Firefox.<commit_after>import { claimsTooltipElement } from '../dom-elements.js';
import { stringifyIndentSpaces } from './utils.js';
import strings from '../strings.js';
import { 
  payloadElement,
  headerElement,
  decodedElement
} from '../dom-elements.js';

import tippy from 'tippy.js';

const timeClaims = ['exp', 'nbf', 'iat', 'auth_time', 'updated_at'];

function hideTooltip() {
  decodedElement._tippy.popper.style.opacity = 0;
}

function showTooltip(text) {
  decodedElement._tippy.popper.querySelector('.tippy-content')
                .textContent = text;
  decodedElement._tippy.popperInstance.update();
  decodedElement._tippy.popper.style.opacity = 1;
}

function getTimeText(timeStr) {
  return (new Date(parseInt(timeStr, 10) * 1000)).toString();
}

function tooltipHandler(event) {
  const editor = event.currentTarget.querySelector('.CodeMirror').CodeMirror;

  if(!editor) {
    hideTooltip();
    return;
  }

  const result = editor.coordsChar({
    left: event.pageX,
    top: event.pageY
  }, 'page');

  const line = editor.getLine(result.line);
  const matches = /"(.*)":\s*"?(.*)"?/.exec(line);

  if(!matches) {
    hideTooltip();
    return;
  }

  const claim = matches[1];  

  // If this is a time claim and the mouse cursor is on top of the time,
  // let the time tooltip handle this, do nothing.
  // TODO: merge both tooltip handlers?
  const claimEnd = line.indexOf(':');
  if(result.ch >= claimEnd && timeClaims.includes(claim)) {
    showTooltip(getTimeText(matches[2]));
    return;
  }

  const claimText = strings.common.claims[claim];
  if(!claimText) {
    hideTooltip();
    return;
  }

  showTooltip(claimText);
}

export function setupClaimsTooltip() {  
  tippy(decodedElement, {
    placement: 'left',
    arrow: true,
    followCursor: true,
    performance: true,
    size: 'large',
    dynamicTitle: true,
    arrowTransform: 'scale(0.75)',
    distance: 20,
    sticky: true,
    updateDuration: 100
  });  

  decodedElement._tippy.popper.style.opacity = 0;

  payloadElement.addEventListener('mousemove', tooltipHandler);
  headerElement.addEventListener('mousemove', tooltipHandler);
{'fraction_non_alphanumeric': 0.14583844831819298, 'fraction_numerical': 0.007856616744414437, 'mean_word_length': 3.8270142180094786, 'pattern_counts': {'":': 2, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2461982', 'n_tokens_mistral': 1332, 'n_tokens_neox': 1295, 'n_words': 295}