github.com/grafana/pyroscope@v1.18.0/public/app/components/TimelineChart/TimelineChartPlugin.ts (about)

     1  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
     2  // @ts-nocheck
     3  import getFormatLabel from './getFormatLabel';
     4  
     5  (function ($) {
     6    const options = {}; // no options
     7  
     8    function init(plot) {
     9      const plotOptions = plot.getOptions();
    10  
    11      this.selecting = false;
    12      this.tooltipY = 0;
    13      this.selectingFrom = {
    14        label: '',
    15        x: 0,
    16        pageX: 0,
    17        width: 0,
    18      };
    19      this.selectingTo = {
    20        label: '',
    21        x: 0,
    22        pageX: 0,
    23        width: 0,
    24      };
    25  
    26      const onPlotHover = (target, position) => {
    27        const { xaxis } = plot.getAxes();
    28  
    29        this.tooltipY = target.currentTarget.getBoundingClientRect().bottom - 28;
    30        if (!position.x) {
    31          return;
    32        }
    33        if (!this.selecting) {
    34          this.selectingFrom = {
    35            label: getFormatLabel({
    36              date: position.x,
    37              xaxis,
    38              timezone: plotOptions.xaxis.timezone,
    39            }),
    40            x: position.x,
    41            pageX: position.pageX,
    42          };
    43        } else {
    44          this.selectingTo = {
    45            label: getFormatLabel({
    46              date: position.x,
    47              xaxis,
    48              timezone: plotOptions.xaxis.timezone,
    49            }),
    50            x: position.x,
    51            pageX: position.pageX,
    52          };
    53        }
    54        updateTooltips();
    55      };
    56  
    57      const updateTooltips = () => {
    58        const { xaxis } = plot.getAxes();
    59  
    60        if (!this.selecting) {
    61          // If we arn't in selection mode
    62          this.$tooltip.html(this.selectingFrom.label).show();
    63          this.selectingFrom.width = $(this.$tooltip).outerWidth();
    64          setTooltipPosition(this.$tooltip, {
    65            x: this.selectingFrom.pageX,
    66            y: this.tooltipY,
    67          });
    68        } else {
    69          // Render Intersection
    70          this.$tooltip.html(
    71            `${getFormatLabel({
    72              date: Math.min(this.selectingFrom.x, this.selectingTo.x),
    73              xaxis,
    74              timezone: plotOptions.xaxis.timezone,
    75            })} - 
    76               ${getFormatLabel({
    77                 date: Math.max(this.selectingFrom.x, this.selectingTo.x),
    78                 xaxis,
    79                 timezone: plotOptions.xaxis.timezone,
    80               })}`
    81          );
    82  
    83          // Stick to left selection
    84          setTooltipPosition(this.$tooltip, {
    85            x: this.selectingTo.pageX,
    86            y: this.tooltipY,
    87          });
    88        }
    89      };
    90  
    91      const onLeave = () => {
    92        // Save tooltips while selecting
    93        if (!this.selecting) {
    94          this.$tooltip.hide();
    95        }
    96      };
    97  
    98      function onMove() {}
    99  
   100      const setTooltipPosition = ($tip, pos, center = true) => {
   101        const totalTipWidth = $tip.outerWidth();
   102        const totalTipHeight = $tip.outerHeight();
   103        if (
   104          pos.x - $(window).scrollLeft() >
   105          $(window).innerWidth() - totalTipWidth
   106        ) {
   107          pos.x -= center ? totalTipWidth / 2 : totalTipWidth;
   108          pos.x = Math.max(pos.x, 0);
   109          $tip.css({
   110            left: 'auto',
   111            right: `0px`,
   112            top: `${pos.y}px`,
   113          });
   114          return;
   115        }
   116        if (
   117          pos.y - $(window).scrollTop() >
   118          $(window).innerWidth() - totalTipHeight
   119        ) {
   120          pos.y -= totalTipHeight;
   121        }
   122  
   123        $tip.css({
   124          left: `${pos.x - (center ? Math.floor(totalTipWidth / 2) : 0)}px`,
   125          top: `${pos.y}px`,
   126          right: 'auto',
   127        });
   128      };
   129  
   130      const onSelected = () => {
   131        // Clean up selection state and hide tooltips
   132        this.selecting = false;
   133        this.$tooltip.hide();
   134      };
   135  
   136      // Trying to mimic flot.selection.js
   137      const onMouseDown = () => {
   138        // Save selection state
   139        this.selecting = true;
   140      };
   141  
   142      const onMouseUp = () => {
   143        this.selecting = false;
   144      };
   145  
   146      const createDomElement = () => {
   147        if (this.$tooltip) {
   148          return;
   149        }
   150        const tooltipStyle = {
   151          background: '#fff',
   152          color: 'black',
   153          'z-index': '1040',
   154          padding: '0.4em 0.6em',
   155          'border-radius': '0.5em',
   156          'font-size': '0.8em',
   157          border: '1px solid #111',
   158          'white-space': 'nowrap',
   159        };
   160        const $tip = $('<div data-testid="timeline-tooltip1"></div>');
   161  
   162        $tip.appendTo('body').hide();
   163        $tip.css({ position: 'absolute', left: 0, top: 0 });
   164        $tip.css(tooltipStyle);
   165        this.$tooltip = $tip;
   166      };
   167  
   168      function bindEvents(plot, eventHolder) {
   169        const o = plot.getOptions();
   170  
   171        if (o.onHoverDisplayTooltip) {
   172          return;
   173        }
   174  
   175        plot.getPlaceholder().bind('plothover', onPlotHover);
   176        plot.getPlaceholder().bind('plotselected', onSelected);
   177  
   178        $(eventHolder).bind('mousemove', onMove);
   179        $(eventHolder).bind('mouseout', onLeave);
   180        $(eventHolder).bind('mouseleave', onLeave);
   181  
   182        $(eventHolder).bind('mouseup', onMouseUp);
   183        $(eventHolder).bind('mousedown', onMouseDown);
   184      }
   185  
   186      function shutdown(plot, eventHolder) {
   187        const o = plot.getOptions();
   188  
   189        if (o.onHoverDisplayTooltip) {
   190          return;
   191        }
   192  
   193        plot.getPlaceholder().unbind('plothover', onPlotHover);
   194        // plot.getPlaceholder().unbind('plotselecting', onSelecting);
   195        plot.getPlaceholder().unbind('plotselected', onSelected);
   196        $(eventHolder).unbind('mousemove', onMove);
   197        $(eventHolder).unbind('mouseout', onLeave);
   198        $(eventHolder).unbind('mouseleave', onLeave);
   199      }
   200  
   201      createDomElement();
   202  
   203      plot.hooks.bindEvents.push(bindEvents);
   204      plot.hooks.shutdown.push(shutdown);
   205    }
   206  
   207    $.plot.plugins.push({
   208      init,
   209      options,
   210      name: 'pyro-tooltip',
   211      version: '0.1',
   212    });
   213  })(jQuery);