Bowl a Strike explainer

The aim of this puzzle: Make the ball roll and knock down all the pins.
Walkthrough of the solution: You see that in the bowlBall function of the starter code has a .transition() with nothing after it – it should at least have an .attr(), and specifically, 'cy' should go to zero so that the ball moves toward the top of the screen and toward the pins. The other part to add to this command is changing the duration. Without .duration() the transition will default to 250ms – set the duration to 2000ms by attaching .duration(2000) to the .transition(). Finally, the bowlBall should be complete, but it won’t do anything until it gets called into action, and you want it to run when you tap on the ball – this is the time to use .on('click',...)! You want bowlBall to run when you click on the ball, so the command looks like: ball.on('click', bowlBall); Remember you can read the .on('click',...) command backwards to make sure you have each part in the right place.
Sample code solution:
(Tap below to reveal)

function bowlBall(){
  ball.transition()
    .duration(2000)
    .attr('cy', 0);
  knockPins();
}

ball.on('click', bowlBall);

JavaScript Concepts: Code Block (function), Identifiers, Member Expression
D3 Concepts: .transition(), .duration(), .attr(‘cy’,), .on(‘click’,)
Additional Code: There is hidden code that runs before the puzzle’s code that sets the SVG Shapes attributes, and creates the function knockPins.

1 Like

The ball will move automatically although I haven’t click on the ball yet

1 Like

Hello,
Can you please paste your code? So we can analyze it to see where there might be an issue? Based upon the code sample it should be triggered once a click event happens which basically means either a mouse or finger press of the ball object. I hope that helps :slight_smile:

Thanks,
Ahsen

1 Like

I have find the mistake that I have made. Thanks!

1 Like

Hello all ,

I have a stupid question to ask. I wrote the same code and passed, but I was wondering why my pins disappeared after my ball already ran to the top… Looked not natural enough lol thanks!

The knockPins function is defined in some additional code that runs right before your code runs. It simply removes each pin after a simple time delay. These delay times could be adjusted to give a more natural look – making the outer pins remove slower than the center line pins.

function knockPins(){
    pin1.transition().delay(750).remove();

    pin2.transition().delay(800).remove();
    pin3.transition().delay(800).remove();

    pin4.transition().delay(850).remove();
    pin5.transition().delay(850).remove();
    pin6.transition().delay(850).remove();

    pin7.transition().delay(900).remove();
    pin8.transition().delay(900).remove();
    pin9.transition().delay(900).remove();
    pin10.transition().delay(900).remove();
}

–Frankie

1 Like

I made the same mistake, it was that i typed bowlball after click, but i chose the blue one instead of the green one… Which is the difference btw both? First attempt the green one was greyed out, that lead me to choose the blue one instead

When you declare a function like function bowlBall(), 2 buttons are created:

  • Function Call: bowlBall(), colored blue and has parentheses at the end
  • Function Identifier: bowlBall, colored grey and does not have parentheses

The function call means, “run this function now”.
You can think of the bowlBall identifier as a shortcut to all the code that comes after function bowlBall. It is like a variable that stores all the code from the function definition including what parameters it uses.

When you put ball.on('click',...) in your code, it takes the function you place in the ... and combines it with some code that can detect a “click” or “tap” and attaches that code to the ball. You want to use the function identifier inside of .on('click', bowlBall) because that references all the code that defines the function. If you do .on('click', bowlBall()), the bowlBall function will run immediately while attaching the “on click” event listener.

–Frankie

2 Likes

Really good explanation, thanks! So, if we use listeners, like .on(‘click’), we always have to use function identifier in it to prevent immediate execution?

Yes. Although, there could be times when you want your function to run right away. For example:

function bowlBall(){
  return function contents(){
    ball.transition().duration(2000).attr('cy', 0);
    knockPins();
  }
}
ball.on('click', bowlBall());

I stuck the meat of the bowlBall function into a new arrow function called contents. Calling bowlBall() now basically transforms it into the function definition for contents. This would give you the same behavior as the normal solution. This is a messier way to do this puzzle, but there are scenarios when it makes sense for a function to return another function.

–Frankie

1 Like

Hi why can’t I pass this one… I checked answer tho

This seems to be a bug that was also reported here. We’re trying to figure out how to reproduce this issue. If you remember the steps you took to get this error, it would help us a lot. To fix the problem for now, you’ll have to use the reset button.

–Frankie

1 Like

What is the difference between
ball.transition().duaratiton(2000).attr(“cy”, 0) and
ball.transition().attr(“cy”, 0).duration(2000) ?

I tried both and they produce similar results. Is there norm for order for these in JavaScript or D3.js?

You’re correct; those two examples will produce the same result, and both are readable. I would suggest keeping the order the same throughout your code, but there’s no standard order.

–Frankie

Hello, I’m stuck! Here’s my code, which is as close as I can get to the code provided in help

The .on('click',...) should be attached to a shape – the shape you click on to trigger the function. You’ll want to change bowlBall.on(...) to ball.on(...).

–Frankie

can u tell me whats wrong?

The .duration() is a property of a .transition(); it doesn’t make sense to have it on its own. You can think of ball.transition() as “attaching a transition to the ball”. Then you attach an attr to the transition to tell it what it should be animating. To change how long the animation (transition) takes, you want to apply a duration to it. If you move the .duration(2000) to be attached to the .transition() it will work. You can also attach the .duration(2000) to the attr since the attr is also connected to the transition.

–Frankie

I am having the same issue, I’m glad it’s not me… hehehe!