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

Adds remove method to layer (#63). #103

Closed

Conversation

samselikoff
Copy link

First-pass implementation. Seems to work (I removed the .remove call in the bar chart example, and the bars were removed), but obviously I need to add some tests.

Not super familiar with Sinon. I tried to spy on the layer's remove method, but I couldn't get it working.

@@ -55,6 +55,10 @@ suite("d3.layer", function() {
dataBind: dataBind,
insert: insert
});
// this.layer.remove = sinon.spy();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You'll be hard-pressed to access the default internal remove method from the tests. That's okay, though, because (for the default implementation) what you really want to do is ensure that the element is removed from the document (not that any particular JavaScript function was invoked)

@jugglinmike
Copy link
Member

Thanks for putting this together, @samselikoff . I made a few comments in-line, but there's also one piece of functionality that's missing:

The remove function should be configurable. This will require a change in ['layer-extensions.js](https://github.com/misoproject/d3.chart/blob/27e2224fac8259cb9cf6a9f6857bd4b6ad2068a5/src/layer-extensions.js). Unlike dataBindandinsert, though, this function is optional, so you'll want to check options.removebefore attaching it to the locallayer` instance.

@@ -82,6 +82,12 @@ suite("d3.layer", function() {
this.layer.draw([]);
assert(this.insert.calledOn(this.dataBind.returnValues[0].enter.returnValues[0]));
});
test("invokes the provided `remove` method", function() {
this.layer.draw([1]);
assert.equal(this.layer.selectAll('g')[0].length, 1);
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a more elegant way to get this? this.layer.selectAll('g') will return a length-1 array even in after the elements have been removed, since it's the selection length rather than the length of the actual DOM elements.

@jugglinmike
Copy link
Member

You'll want to use d3's size method. You'll find the API documentation for that here

@samselikoff
Copy link
Author

Updated - sorry about the delay!

@samselikoff
Copy link
Author

Just saw your comment above - will add this.

@samselikoff
Copy link
Author

@jugglinmike ready for review

@@ -82,6 +82,12 @@ suite("d3.layer", function() {
this.layer.draw([]);
assert(this.insert.calledOn(this.dataBind.returnValues[0].enter.returnValues[0]));
});
test("invokes the provided `remove` method", function() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test description is a little inaccurate now since in this case, there is no provided remove method.

@jugglinmike
Copy link
Member

Thanks, @samselikoff. No worries about the delay: I know it can be tough to make time for this stuff!

@samselikoff
Copy link
Author

@jugglinmike I just checked if remove was called, but didn't know how to get the correct context.

@jugglinmike
Copy link
Member

We've stubbed the exit selection for just this reason. You can take a cue from this lifecycle event test for an idea on how to access it.

As it stands, this test demonstrates a bug in your implementation: the exit method should not be invoked if the selection is empty. You may remember identifying this in the other lifecycle events over in gh-69.

@samselikoff
Copy link
Author

Alright, I think I've got the context correct now.

I made sure exit wasn't called for an empty selection even if remove is provided, so I think I'm missing something about your second point. Are you talking about remove itself? It shouldn't be called if the exit selection is empty?

@jugglinmike
Copy link
Member

Hey @samselikoff!

I'm sorry for leaving you hanging in the review process. Regarding the last
change for this patch, I don't think I did a very good job explaining it in
words. Here's a code example that demonstrates what I had in mind:

diff --git a/src/layer.js b/src/layer.js
index f3b6823..b2a56ca 100644
--- a/src/layer.js
+++ b/src/layer.js
@@ -229,5 +229,7 @@ Layer.prototype.draw = function(data) {
        }
      }

-     this.remove.call(selection);
+     if (!selection.empty()) {
+       this.remove.call(selection);
+     }
 };
diff --git a/test/tests/layer.js b/test/tests/layer.js
index e0686ae..0bc033c 100644
--- a/test/tests/layer.js
+++ b/test/tests/layer.js
@@ -106,6 +106,12 @@ suite("d3.layer", function() {

          assert(this.remove.calledOn(exiting));
        });
+       test("does not invoke `remove` method when `exit` selection is empty", function() {
+         this.layerWithRemove.draw([1, 2, 3]);
+         this.layerWithRemove.draw([1, 2, 3]);
+
+         assert.equal(this.remove.callCount, 0)
+       });

        suite("event triggering", function() {
          test("invokes event handlers with the correct selection", function() {

besides that, there's just a trivial issue with white space to clean up (we're
using tabs in this project--I'll set us up with JSCS shortly so that this is
more obvious).

It's been quite a while since we worked on this, though, and I imagine your
interests have drifted. I'm more than happy to make these changes on top of
your patch and land it that way, but I wanted to give you an opportunity to
finalize this in the unlikely event that you're not completely exhasperated.

Let me know either way!

@samselikoff
Copy link
Author

I appreciate the follow-up - I'd need to spend some more time with this to re-familiarize myself and have a few other projects I'm focusing on now.

Again, I really appreciate your feedback!

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

Successfully merging this pull request may close these issues.

2 participants