npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

d3-gup

v1.0.1

Published

A small utility function that encapsulates the D3 General Update Pattern.

Downloads

11

Readme

d3-gup

release license

d3-gup is a functional and composable D3 plugin that codifies the General Update Pattern as described by Selection#data. It does not attempt to wrap D3 or provide abstractions to replace or conceal the existing D3 features. Instead it provides the facilities for composition of sets of functions to aid in the construction of components. d3-gup is aware of D3 transitions and takes the appropriate actions in response to them.

The following examples are reproductions of Mike Bostock's General Update Pattern examples. They are presented here so that you may compare how d3-gup relates to the conventional approach.

The globals below are used for each example.

var examples = [];
var alphabet = "abcdefghijklmnopqrstuvwxyz".split("");

function randomSample(data) {
  return d3.shuffle(data)
    .slice(0, Math.floor(Math.random() * data.length))
    .sort();
}

This example is a reproduction of General Update Pattern, I.

In this example we create a GUP factory that can be bound to data, which produces a GUP instance. A GUP instance can be called against a D3 selection, which preforms a data-join and executes a set of update functions.

The GUP factory is rebound to random letters of the alphabet and called at regular intervals in a D3 timer.

examples[0] = {
  tick() {
    examples[0].root.call(examples[0].gup(randomSample(alphabet)));
  },
  timer: d3.interval(() => examples[0].tick(), 1500),

The GUP instance is called on a D3 selection that contains a single g element inside a svg element.

  root: d3.select("svg#example-1")
    .attr("width", 450)
    .attr("height", 100)
    .append("g")
    .attr("transform", "translate(16 50)"),

This creates our GUP factory, ready to configure with our phase functions.

  gup: d3.gup()

select occurs prior to the data-join; here we select old text elements, if any.

    .select($ => $.selectAll("text"))

pre is applied to old elements; update class colours them blue.

    .pre($ => $.attr("class", "update"))

enter creates new elements as needed; enter class colours them green.

    .enter($ => $.append("text")
      .attr("class", "enter")
      .attr("dy", ".35em")
      .attr("x", (d, i) => i * 16))

post is applied to the merged set of new and old elements; here we lay them out in a line.

    .post($ => $.text(d => d))

exit is applied to elements that no longer have bound data; here we simply remove them.

The overall effect is that we see green letters when the list grows and only blue letters when the list shrinks. The association between individual letters and their colour is lost because no key function is specified whilst binding the data.

    .exit($ => $.remove())
};

This example is a reproduction of General Update Pattern, II.

In this example we provide the key function that was missing from the previous example.

As before, we setup a D3 timer to a g element but this time the identity function is passed as the key function when the data is bound to the GUP.

examples[1] = {
  tick() {
    examples[1].root.call(examples[1].gup(randomSample(alphabet), d => d));
  },
  timer: d3.interval(() => examples[1].tick(), 1500),

  root: d3.select("#example-2")
    .attr("width", 450)
    .attr("height", 100)
    .append("g")
    .attr("transform", "translate(16 50)"),

As before, we create our GUP and configure it. No change to select or pre either.

  gup: d3.gup()
    .select($ => $.selectAll("text"))
    .pre($ => $.attr("class", "update"))

enter is where the text content is applied since it will remain constant, by virtue of the key function.

    .enter($ => $.append("text")
      .attr("class", "enter")
      .attr("dy", ".35em")
      .text(d => d))

However, the elements will change position in the list (agian, thanks to the key function), thus post is where we set the horizontal position.

    .post($ => $.attr("x", (d, i) => i * 16))

No change to exit.

    .exit($ => $.remove())
};

This example is a reproduction of General Update Pattern, III.

In the previous example we provided the key function to communicate a sense of object constancy. This effect is completed with the addition of transitions.

As before, we setup a D3 timer to a g element.

examples[2] = {
  tick() {
    examples[2].root.call(examples[2].gup(randomSample(alphabet), d => d));
  },
  timer: d3.interval(() => examples[2].tick(), 1500),

  root: d3.select("#example-3")
    .attr("width", 450)
    .attr("height", 100)
    .append("g")
    .attr("transform", "translate(16 50)")

The g element is created the same way but now we introduce a transition.

    .transition()
      .duration(750),

As before, we create our GUP and configure it. We must now pay closer attention to the elements vertical and horizontal position so that it will be animated during the transition and also to the opacity to produce fade-in and fade-out effects.

  gup: d3.gup()
    .select($ => $.selectAll("text"))
    .pre($ => $.attr("class", "update"))
    .enter($ => $.append("text")
      .attr("class", "enter")
      .attr("dy", ".35em")
      .text(d => d)

Elements will begin positioned above the list and horizontally correct.

      .attr("y", -60)
      .attr("x", (d, i) => i * 16)
      .style("fill-opacity", 1e-6))

Elements final position will be in the list; existing elements will traval horizontally.

    .post($ => $.attr("x", (d, i) => i * 16)
      .attr("y", 0)
      .style("fill-opacity", 1))

Exiting elements will drop below the list and fade out and then removed when the transition completes.

    .exit($ => $.attr("class", "exit")
      .attr("y", 60)
      .style("fill-opacity", 1e-6)
      .remove())
};