github.com/pyroscope-io/pyroscope@v0.37.3-0.20230725203016-5f6947968bd0/webapp/javascript/components/TimelineChart/CrosshairSync.plugin.ts (about)

     1  const defaultOptions = {
     2    syncCrosshairsWith: [],
     3  };
     4  
     5  // Enhances the default Plot object with the API from the crosshair plugin
     6  // https://github.com/flot/flot/blob/de34ce947d8ebfb2cac0b682a130ba079d8d654b/source/jquery.flot.crosshair.js#L74
     7  type PlotWithCrosshairsSupport = jquery.flot.plot &
     8    jquery.flot.plotOptions & {
     9      setCrosshair(pos: { x: number; y: number }): void;
    10      clearCrosshair(): void;
    11    };
    12  
    13  (function ($) {
    14    function init(plot: PlotWithCrosshairsSupport) {
    15      function getOptions() {
    16        return plot.getOptions() as jquery.flot.plotOptions & {
    17          syncCrosshairsWith: typeof defaultOptions['syncCrosshairsWith'];
    18        };
    19      }
    20  
    21      function accessExternalInstance(id: string) {
    22        // Access another flotjs instance
    23        // https://github.com/flot/flot/blob/de34ce947d8ebfb2cac0b682a130ba079d8d654b/source/jquery.flot.js#L969
    24        const p: PlotWithCrosshairsSupport = $(`#${id}`).data('plot');
    25        return p;
    26      }
    27  
    28      function onPlotHover(
    29        syncCrosshairsWith: typeof defaultOptions['syncCrosshairsWith'],
    30        e: unknown,
    31        position: { x: number; y: number }
    32      ) {
    33        syncCrosshairsWith.forEach((id) =>
    34          accessExternalInstance(id).setCrosshair(position)
    35        );
    36      }
    37  
    38      function clearCrosshairs(
    39        syncCrosshairsWith: typeof defaultOptions['syncCrosshairsWith']
    40      ) {
    41        syncCrosshairsWith.forEach((id) =>
    42          accessExternalInstance(id).clearCrosshair()
    43        );
    44      }
    45  
    46      plot.hooks!.bindEvents!.push(() => {
    47        const options = getOptions();
    48  
    49        plot
    50          .getPlaceholder()
    51          .bind('plothover', onPlotHover.bind(null, options.syncCrosshairsWith));
    52  
    53        plot
    54          .getPlaceholder()
    55          .bind(
    56            'mouseleave',
    57            clearCrosshairs.bind(null, options.syncCrosshairsWith)
    58          );
    59      });
    60  
    61      plot.hooks!.shutdown!.push(() => {
    62        const options = getOptions();
    63  
    64        clearCrosshairs(options.syncCrosshairsWith);
    65  
    66        plot
    67          .getPlaceholder()
    68          .bind(
    69            'mouseleave',
    70            clearCrosshairs.bind(null, options.syncCrosshairsWith)
    71          );
    72  
    73        plot
    74          .getPlaceholder()
    75          .unbind(
    76            'plothover',
    77            onPlotHover.bind(null, options.syncCrosshairsWith)
    78          );
    79      });
    80    }
    81  
    82    $.plot.plugins.push({
    83      init,
    84      options: defaultOptions,
    85      name: 'crosshair-sync',
    86      version: '1.0',
    87    });
    88  })(jQuery);