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

selection.draggable API: callback fires for every datapoint, not for the region #3911

Closed
utrack opened this issue Oct 31, 2024 · 2 comments
Closed

Comments

@utrack
Copy link

utrack commented Oct 31, 2024

Hi there! Not sure if it's a bug or a question, but here goes :)

Versions:

        <script src="https://d3js.org/d3.v6.js"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/billboard.js/3.14.0/billboard.min.js"></script>
        <link href="https://cdnjs.cloudflare.com/ajax/libs/billboard.js/3.14.0/theme/dark.min.css" rel="stylesheet"/>

I've set up my chart like this:

        var chart = bb.generate({

            data: {
                columns: [
                    ["Bucket Count", ...initCols.values],
                ],
                type: "bar",
                selection: {
                    draggable: true,
                    enabled: true,
                    grouped: true,
                    multiple: true,
                },
                onselected: function(d, element) {
                    console.log(d);
                    console.log(element);
                }
            },
            bar: {
               width: {
                ratio: 0.5
               }
            },
            axis: {
                x: {
                    type: "category",
                    categories: initCols.tickNames,
                    tick: {
                        format: (d) => initCols.tickLabels[d],
                    }
                }
            },
            tooltip: {
                format: {
                    title: function(d) {
                        return initCols.tickNames[d];
                    },
                    value: function(value, ratio, id) {
                        return value + ' player(s)';
                    }
                }
            },
            bindto: bindTo
        });

Now, since I set up multiple: true, I expect onselected to fire only once - when the drag area is let go.

However, right now I get an event for every data point I select when the drag area crosses it; and there's no way to know when the dragging actually stopped.

How do I set up the listeners correctly? Is it a bug?

@utrack
Copy link
Author

utrack commented Nov 1, 2024

Update: I've tried to use zoom for my case but it doesn't really work since onzoom* are called recursively if I update the data via chart.load({columns:...}).

My usecase is to basically run some code for the zoomed-in portion of the graph, and put the new data into the chart.

@netil
Copy link
Member

netil commented Nov 15, 2024

Hi @utrack.

My usecase is to basically run some code for the zoomed-in portion of the graph, and put the new data into the chart.

"selection" and "zoom" is totally different interaction.
Based on the last comment, if I understood correctly, you want some sort of these actions.

    1. drag some area
    1. when drag finishes(mouseup event)
    1. run some code based on the dragged selected data

If so, currently billboad.js doesn't provide some event for "dragend", but you can implement as follows.

	data: {
		...,
		onselected: function(d, element) {
			this.selectionList.push(d);
		}
	},
	onafterinit() {
		const node = this.internal.$el.main.select(".bb-chart").node();
		this.selectionList = [];
		
		new MutationObserver((mutationList, observer) => {
			mutationList.forEach((mutation) => {
				if (mutation.type === "childList") {
					if (!node.querySelector(".bb-dragarea")) {
						// (1) do something with selection list
						console.log(this.selectionList);

						// (2) clear selection list for next selection
						this.selectionList.length = 0;
					}
				}
			});
		}).observe(node, {
			childList: true
		});
	}
}

You can add the code you want to run, after the // (1) do something with selection list comment.
By accessing this.selectionList value, will get selected data list.

checkout the working exmple:

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

No branches or pull requests

2 participants