function redraw_axis()

in src/parallel/parallel.tsx [312:425]


    function redraw_axis() {
      // Extract the list of numerical dimensions and create a scale for each.
      me.xscale.domain(me.state.dimensions);

      // Add a group element for each dimension.
      function create_drag_beh() {
        return d3.drag().on("start", function(d: string) {
          me.setState({
            dragging: {
              col: d,
              pos: me.xscale(d),
              origin: me.xscale(d),
              dragging: false
            }
          });
          d3.select(me.foreground_ref.current).style("opacity", "0.35");
        })
        .on("drag", function(d: string) {
          const eventdx = d3.event.dx;
          const brushEl = d3.select(this).select("." + style.brush);
          me.setState(function(prevState, _) { return {
            dragging: {
              col: d,
              pos: Math.min(me.w, Math.max(0, prevState.dragging.pos + eventdx)),
              origin: prevState.dragging.origin,
              dragging: true
            }
          };}, function() {
            // Feedback for axis deletion if dropped
            if (me.state.dragging.pos < 12 || me.state.dragging.pos > me.w-12) {
              brushEl.style('fill', 'red');
            } else {
              brushEl.style('fill', null);
            }
          });

          var new_dimensions = Array.from(me.state.dimensions);
          new_dimensions.sort(function(a, b) { return me.position(a) - me.position(b); });
          if (!new_dimensions.every(function(val, idx) { return val == me.state.dimensions[idx]; })) {
            me.setState({dimensions: new_dimensions});
          }
          me.dimensions_dom.attr("transform", function(d) { return "translate(" + me.position(d) + ")"; });
          redrawAllForeignObjectsIfSafari();
        })
        .on("end", function(d: string) {
          if (!me.state.dragging.dragging) {
            // no movement, invert axis
            var extent = invert_axis(d);
          } else {
            // reorder axes
            var drag: any = d3.select(this);
            if (!IS_SAFARI) {
              drag = drag.transition();
            }
            drag.attr("transform", "translate(" + me.xscale(d) + ")");
            var extents = brush_extends();
            extent = extents[d];
          }

          // remove axis if dragged all the way left
          if (me.state.dragging.pos < 12 || me.state.dragging.pos > me.w-12) {
            me.remove_axis(d);
          } else {
            me.setState({order: Array.from(me.state.dimensions)});
          }

          me.update_ticks(d, extent);

          // rerender
          d3.select(me.foreground_ref.current).style("opacity", null);
          me.setState({dragging: null});
        });
      }
      if (me.dimensions_dom) {
        me.dimensions_dom.remove();
      }
      me.dimensions_dom = d3.select(me.svgg_ref.current).selectAll<SVGGElement, string>(".dimension")
          // reverse the order so that the tooltips appear on top of the axis ticks
          .data(me.state.dimensions.reverse())
        .enter().append<SVGGElement>("svg:g")
          .attr("class", "dimension")
          .attr("transform", function(d) { return "translate(" + me.xscale(d) + ")"; })
          //@ts-ignore
          .call(create_drag_beh());

      // Add an axis and title.
      me.dimensions_dom.append("svg:g")
          .attr("class", style.axis)
          .attr("transform", "translate(0,0)")
          .each(function(d) { console.assert(me.yscale[d], d, me.yscale, this); d3.select(this).call(me.axis.scale(me.yscale[d])); })
        .append(function(dim) { return foCreateAxisLabel(me.props.params_def[dim], me.props.context_menu_ref, "Drag to move, right click for options"); })
          .attr("y", -20)
          .attr("text-anchor", "left")
          .classed("pplot-label", true)
          .classed(style.pplotLabel, true);
      me.dimensions_dom.selectAll(".label-name").style("font-size", "20px");
      me.dimensions_dom.selectAll(".pplot-label").each(function(this: SVGForeignObjectElement, d: string) {
        foDynamicSizeFitContent(this, [-me.xscale(d) + 5, -me.xscale(d) + me.state.width - 5]);
      }).attr("x", 0).style("width", "1px");
      me.updateAxisTitlesAnglesAndFontSize();
      // Add and store a brush for each axis.
      me.dimensions_dom.append("svg:g")
          .classed(style.brush, true)
          .classed("pplot-brush", true)
          .each(function(d) { d3.select(this).call(me.d3brush); })
        .selectAll("rect")
          .style("visibility", null)
          .append("title")
            .text("Drag up or down to brush along this axis");

      me.dimensions_dom.selectAll(".extent")
          .append("title")
            .text("Drag or resize this filter");
    };