From 1f3bd945b8a3ad4f49cb97bb4e45c10a93e633aa Mon Sep 17 00:00:00 2001
From: Cee <cnell@usgs.gov>
Date: Sat, 25 May 2024 18:00:11 -0500
Subject: [PATCH] modularize tooltip

---
 src/components/BeeswarmChart.vue | 188 ++++++++++++++++---------------
 1 file changed, 98 insertions(+), 90 deletions(-)

diff --git a/src/components/BeeswarmChart.vue b/src/components/BeeswarmChart.vue
index 173c338..735d40c 100644
--- a/src/components/BeeswarmChart.vue
+++ b/src/components/BeeswarmChart.vue
@@ -181,96 +181,15 @@
     const forceManyBody = d3.forceManyBody().strength(1);
   
     const bubbles = svg
-      .selectAll('.bubble')
-      .data(data.value)
-      .enter()
-      .append('circle')
-      .attr('class', 'bubble')
-      .attr('r', d => radiusScale(d.evidence_val))
-      .style('fill', d => dimensionColors[d.dimension.replace(' ', '')])
-      .on('mouseover', function (event, d) {
-        const [x, y] = d3.pointer(event);
-        const tooltip = d3.select('#tooltip')
-
-        tooltip.html('')
-        tooltip.append('div')
-          .html(`<strong>${d.determinant}</strong><br>appeared in ${d.evidence_val} ${d.evidence_val === 1 ? 'study' : 'studies'}`);
-
-          // add stacked bar chart
-          const barData = [
-            { name: 'positive', value: d.pos_related_total, stroke: dimensionColors[d.dimension.replace(' ', '')], fill: dimensionColors[d.dimension.replace(' ', '')]  },
-            { name: 'negative', value: d.neg_related_total, stroke: dimensionColors[d.dimension.replace(' ', '')], fill: 'white'  },
-            { name: 'unknown', value: d.unk_direction_total, pattern: true, stroke: dimensionColors[d.dimension.replace(' ', '')], fill: 'white' }
-          ];
-
-          // Set dimensions for the bar chart
-          const barWidth = 130;
-          const barHeight = 10;
-
-          // Create an SVG element for the bar chart
-          const svgBar = tooltip.append('svg')
-            .attr('width', barWidth + 10)
-            .attr('height', barHeight + 10);
-
-            const defs = svgBar.append('defs');
-
-            const pattern = defs.append('pattern')
-            .attr('id', 'pattern-stripe')
-            .attr('patternUnits', 'userSpaceOnUse')
-            .attr('width', 8)  // Adjusted to make pattern larger
-            .attr('height', 8)
-
-          pattern.append('rect')
-            .attr('width', 8)
-            .attr('height', 8)
-            .attr('fill', 'white');
-
-          pattern.append('path')
-            .attr('d', 'M-2,2 l4,-4 M0,8 l8,-8 M6,10 l4,-4') // Adjusted path for thicker stripes
-            .attr('stroke', dimensionColors[d.dimension.replace(' ', '')])
-            .attr('stroke-width', 3);  // Thicker stripes
-
-          const g = svgBar.append('g')
-            .attr('transform', 'translate(8, 8)');
-
-          // Create a scale for the x-axis
-          const xBar = d3.scaleLinear()
-            .domain([0, d3.sum(barData, d => d.value)])
-            .range([0, barWidth]);
-
-          // Create groups for each bar segment
-          const barGroups = g.selectAll('g')
-            .data(barData)
-            .enter()
-            .append('g');
-
-          // Add the rectangles
-          barGroups.append('rect')
-            .attr('x', (d, i) => i > 0 ? xBar(d3.sum(barData.slice(0, i), d => d.value)) : 0)
-            .attr('y', 0)
-            .attr('width', d => xBar(d.value))
-            .attr('height', barHeight)
-            .style('fill', d => d.pattern ? 'url(#pattern-stripe)' : d.fill)
-            .style('stroke', d => d.stroke ? d.stroke : 'none');
-
-          // Position the tooltip
-          tooltip
-            .style('opacity', 1)
-            .attr('stroke', dimensionColors[d.dimension.replace(' ', '')])
-            .style('left', (x + 10) + 'px')
-            .style('top', (y - 28) + 'px');
-
-          // Highlight the circle
-          d3.select(this)
-            .attr('stroke', d => dimensionColors[d.dimension.replace(' ', '')])
-            .attr('stroke-width', 15);
-      })
-      .on('mouseout', function () {
-        d3.select('#tooltip').style('opacity', 0);
-        d3.select(this)
-          .attr('stroke', null)
-          .attr('stroke-width', null);
-      });
+    .selectAll('.bubble')
+    .data(data.value)
+    .enter()
+    .append('circle')
+    .attr('class', 'bubble')
+    .attr('r', d => radiusScale(d.evidence_val))
+    .style('fill', d => dimensionColors[d.dimension.replace(' ', '')])
+    .on('mouseover', handleMouseOver)
+    .on('mouseout', handleMouseOut);
   
     // Run simulation
     simulation = d3.forceSimulation()
@@ -332,11 +251,100 @@
     .style('fill', d => activeCategories.includes(d.dimension.replace(' ', '')) ? dimensionColors[d.dimension.replace(' ', '')] : 'rgba(250, 250, 250, 0.93)')
     .attr('cx', d => d.x)  // Use existing x position
     .attr('cy', d => d.y)
+    .on('mouseover', handleMouseOver)
+    .on('mouseout', handleMouseOut)
     .merge(bubbles);
 
   // Ensure all bubbles are handled correctly
   bubbles.exit().remove();
 }
+
+//tooltip
+function handleMouseOver(event, d) {
+  const [x, y] = d3.pointer(event, svg.node());
+  const tooltip = d3.select('#tooltip');
+
+  tooltip.html('')
+    .append('div')
+    .html(`<strong>${d.determinant}</strong><br>appeared in ${d.evidence_val} ${d.evidence_val === 1 ? 'study' : 'studies'}`);
+
+  // Add stacked bar chart
+  const barData = [
+    { name: 'positive', value: d.pos_related_total, stroke: dimensionColors[d.dimension.replace(' ', '')], fill: dimensionColors[d.dimension.replace(' ', '')] },
+    { name: 'negative', value: d.neg_related_total, stroke: dimensionColors[d.dimension.replace(' ', '')], fill: 'white' },
+    { name: 'unknown', value: d.unk_direction_total, pattern: true, stroke: dimensionColors[d.dimension.replace(' ', '')], fill: 'white' }
+  ];
+
+  // Set dimensions for the bar chart
+  const barWidth = 130;
+  const barHeight = 10;
+
+  // Create an SVG element for the bar chart
+  const svgBar = tooltip.append('svg')
+    .attr('width', barWidth + 10)
+    .attr('height', barHeight + 10);
+
+  const defs = svgBar.append('defs');
+
+  const pattern = defs.append('pattern')
+    .attr('id', 'pattern-stripe')
+    .attr('patternUnits', 'userSpaceOnUse')
+    .attr('width', 8)  // Adjusted to make pattern larger
+    .attr('height', 8);
+
+  pattern.append('rect')
+    .attr('width', 8)
+    .attr('height', 8)
+    .attr('fill', 'white');
+
+  pattern.append('path')
+    .attr('d', 'M-2,2 l4,-4 M0,8 l8,-8 M6,10 l4,-4') // Adjusted path for thicker stripes
+    .attr('stroke', dimensionColors[d.dimension.replace(' ', '')])
+    .attr('stroke-width', 3);  // Thicker stripes
+
+  const g = svgBar.append('g')
+    .attr('transform', 'translate(8, 8)');
+
+  // Create a scale for the x-axis
+  const xBar = d3.scaleLinear()
+    .domain([0, d3.sum(barData, d => d.value)])
+    .range([0, barWidth]);
+
+  // Create groups for each bar segment
+  const barGroups = g.selectAll('g')
+    .data(barData)
+    .enter()
+    .append('g');
+
+  // Add the rectangles
+  barGroups.append('rect')
+    .attr('x', (d, i) => i > 0 ? xBar(d3.sum(barData.slice(0, i), d => d.value)) : 0)
+    .attr('y', 0)
+    .attr('width', d => xBar(d.value))
+    .attr('height', barHeight)
+    .style('fill', d => d.pattern ? 'url(#pattern-stripe)' : d.fill)
+    .style('stroke', d => d.stroke ? d.stroke : 'none');
+
+  // Position the tooltip
+  tooltip
+    .style('opacity', 1)
+    .style('left', (x + 10) + 'px')
+    .style('top', (y - 28) + 'px');
+
+  // Highlight the circle
+  d3.select(this)
+    .attr('stroke', dimensionColors[d.dimension.replace(' ', '')])
+    .attr('stroke-width', 8);
+}
+
+function handleMouseOut() {
+  d3.select('#tooltip').style('opacity', 0);
+  d3.select(this)
+    .attr('stroke', null)
+    .attr('stroke-width', null);
+}
+
+
   </script>
   
   <style scoped lang="scss">
-- 
GitLab