Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Programatically set brush #6

Open
vinayakkulkarni opened this issue Sep 23, 2021 · 2 comments
Open

Programatically set brush #6

vinayakkulkarni opened this issue Sep 23, 2021 · 2 comments

Comments

@vinayakkulkarni
Copy link

Hey @bumbeishvili, Thanks for the plugin!

  1. Is there a way I could like to programatically set the brush instead of manually setting it via clicking on the slider?
  2. Is there a way I can disable the ability to remove the brush, like, I want to ensure that the brush is always on the slider.

I am trying different ways to update the index.js file, but due to lack of comments & my understanding of d3, it's a bit difficult to find a solution/hack/workaround as of now.

@bumbeishvili
Copy link
Owner

bumbeishvili commented Sep 23, 2021

Hello @vinayakkulkarni

Is there a way I could like to programmatically set the brush instead of manually setting it via clicking on the slider?

No, there is not

Is there a way I can disable the ability to remove the brush,, I want to ensure that the brush is always on the slider.

No, unfortunately

This project is a quick solution to one of the problems I've faced and I thought I'd just open source it. If you don't know d3 it will be very hard/time-consuming to modify it, but for people with d3.js knowledge, it will be easier

If you want to customize it, I'd suggest finding another d3 brush-based solution, so first, you can customize it and then you can style it as you want

@creynolds-icr
Copy link

Note for @vinayakkulkarni (and anyone interested) - I needed to figure this out also, so I have found the proper calls necessary. To programmatically set the d3 brush you need to first move the brush, then kick off the events that are called with mouse down/up/etc. With prior d3 you could directly call d3 events (there's reference to doing it this way somewhere on the Internet), but now you need to use a callback.

I'm sure I could do some things better here, but here's a starting point for what works for me so far:

  1. Add a dispatchme to the attrs object
    dispatchme: null,

  2. Create a method that can be called from external to data-driven-range-slider. I added some checks to adjust the selection if it's fully outside of the extent. As you can see there's two things I don't like. One, how I am getting the extent - shouldn't be diving into the object like this but I couldn't find a proper getter to call. Two, I was unable to figure out how to directly stim the attrs.brush event so I made a new dispatch of "all"

  setSliderRange(start, end) {
    const attrs = this.getChartState();

    if (! "brush" in attrs) {
      return "The time slider chart is not yet populated";
    }

    // TODO: There must be a function call to get the current extent of the chart and/or brush!
    const maxExtent = attrs.brush._groups[0][0].__brush.extent[1][0];
    let startDateTime = attrs.scaleTime(new Date(start));
    let endDateTime = attrs.scaleTime(new Date(end));

    // Check for fully out of range and bail if so
    if (endDateTime < 0) {
      return "The desired date range is prior to any available data";
    }
    if (startDateTime > maxExtent) {
      return "The desired date range is after any available data";
    }

    // If partially out of range, set selection to extent bounds and carry on
    if (startDateTime < 0) {
      startDateTime = 0;
    }
    if (endDateTime > maxExtent) {
      endDateTime = maxExtent;
    }

    attrs.brush.call(d3.brushX().move, [startDateTime, endDateTime]);

    // Unable to get direct dispatch call of existing .on callbacks, such as the below line:
    // attrs.brush.dispatch("start", ...)
    // attrs.brush.node().dispatchEvent(new CustomEvent("start"))

    // Instead. use a separately created Dispatch to stim the d3 brush callbacks
    attrs.dispatchme.call("all");
  }
  1. Add new code within render() to configure the new dispatch. This calls all the necessary brush start/brushed/ended with expected parameters
    // Setup dispatch to stim callbacks from outside
    var dispatchme = d3.dispatch("all");
    dispatchme.on("all", function() {
      const sel = d3.brushSelection(attrs.brush.node());
      if (!sel) {
        return;
      }
      brushStarted(
        {
          selection: [sel[0]],
          programmatic: true,
        }
      );
      brushed(
        {
          sourceEvent: {
            type: "mousemove"
          },
          selection: sel
        },
        "brush"
      );
      brushEnded(
        {
          sourceEvent: {
            type: "mouseup"
          },
          selection: sel
        }
      );
    })
    attrs.dispatchme = dispatchme;
  1. From external, call setSliderRange() with a string start and end date/timestamp. Check for err string return if you'd like to see how data-driven-range-slider thought how things went

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants