Getting audio players to play their respective streams out of their element


#1487

The next issue to deal with is a CSS problem, where .playButtone.activated causes the display to mess up.

That can be fixed by removing the absolute part of the style declaration, setting the width and height, and removing the border.

.playButtone.activated {
  /* position: absolute; */
  left: 0;
  top: 0;
  right: 0;
  bottom: 0;
  /* margin: auto;
  width: 44px;
  height: 44px; */
  width: 266px;
  height: 174px;
  cursor: pointer;
  /* border: 3px solid #0059dd; */
  fill: #aaff00;
}

And the fix can be seen in the code at https://jsfiddle.net/pmw57/tavcvcu6/390/

There seems to be one problem remaining, and that is that the play button cannot be clicked on. The link behind the play button gets activated instead.


#1488

The CSS for .playe has given the play button a z-index of -1

Commenting out that line results in the player working.
https://jsfiddle.net/pmw57/tavcvcu6/394/


#1489

I have a question about a different version of this code.

This line:
var playButton = document.querySelector(".playButtone");

Why is it:
.playButtone
https://jsfiddle.net/k9zo184L/

  document.querySelector(".linkse").classList.add("inactive");
  var playButton = document.querySelector(".playButtone");
  playButton.addEventListener("click", initialOverlayClickHandler);
}());

And not:
.linkse
https://jsfiddle.net/k9zo184L/1/

  document.querySelector(".linkse").classList.add("inactive");
  var playButton = document.querySelector(".linkse");
  playButton.addEventListener("click", initialOverlayClickHandler);
}());

#1490

One final refactoring improvement is to move the classname changes into the init code.

The test code is now much simpler:

  var button = document.querySelector(".playButtone");
  var links = button.querySelector(".linkse");
  afterEach(function() {
    app.buttone.init(button);
  });

because we've moved the rest of the intializing work into the init function instead:

  function init(button) {
    var initial = button.querySelector(".initiale");
    var links = button.querySelector(".linkse");
    show(initial);
    links.classList.add("inactive");
    hide(getPlay(button));
    button.removeEventListener("click", playButtonClickHandler);
    button.addEventListener("click", initialOverlayClickHandler);
  }

In fact, because we have a hideInitialOverlay() function, we really should make good use of a showInitialOverlay() function too.

The last piece of the puzzle is to have initialClickOverlay() do all of the good and correct work instead.

Using the hideInitialOverlay() function as a base to work from, we can have showInitialOverlay() do the opposite of that instead, and add to it what's needed to get the play button properly hidden too.

  function showInitialOverlay(button) {
    var links = button.querySelector(".linkse");
    var initial = button.querySelector(".initiale");
    links.classList.add("inactive");
    show(initial);
    hide(getPlay(button));
    button.classList.remove("activated");
  }

The hideInitialOverlay() function can then be the opposite of the showInitialOverlay() function:

  function hideInitialOverlay(button) {
    var links = button.querySelector(".linkse");
    var initial = button.querySelector(".initiale");
    links.classList.remove("inactive");
    hide(initial);
    show(getPlay(button));
    button.classList.add("activated");
  }

and we can call the showInitialOverlay() function from the init() function:

  function init(button) {
    showInitialOverlay(button);
    button.removeEventListener("click", playButtonClickHandler);
    button.addEventListener("click", initialOverlayClickHandler);
  }

All of our code continues to work, and the tests are all still in the green, so job done.

Here's the updated code: https://jsfiddle.net/pmw57/tavcvcu6/397/


#1491

Can you answer that for me, I was curious about it.
#1489


#1492

It doesn't have to be either of those, it could be only the initial element instead that the event is assigned to. That looks like a good refactoring task to do.

I'll take a look at it now.


#1493

By god you are being bloody pushy today - I'm getting to it FFS.


#1494

I'm not, I didn't think you saw it, that's all.


#1495

Thank you for this, I'm going to do some testing on it.


#1496

When the initial overlay handler is on the intiial element instead of the button, there is a problem.

  function init(button) {
    var initial = button.querySelector(".initiale");
    showInitialOverlay(button);
    button.removeEventListener("click", playButtonClickHandler);
    initial.addEventListener("click", initialOverlayClickHandler);
  }

The problem is that clicking on the initial image, causes the button to start playing immediately, and one of the tests fails. This test here:

  it("shows links when initial is clicked", function() {
    expect(links.classList.contains("inactive")).toBe(true);
    button.click();
    expect(links.classList.contains("inactive")).toBe(false);
  });

It's clicking on the button, and we've moved the event to the initial element instead, so let's get that initial element dealt with.

The proper way is to leave the vars for button/links/initial unassigned, and before each test to assign them.
That way, we are better protected from the impact of any other tests that might cause changes to occur.

  var button;
  var links;
  var initial;
  beforeEach(function () {
    button = document.querySelector(".playButtone");
    links = button.querySelector(".linkse");
    initial = button.querySelector(".initiale");
  });

We can now easily use that initial variable in our test:

    // button.click();
    initial.click();

The test passes, but it has a bad effect on the button. The pause button is shown and the music plays when the testing is done. That's not how we want things to be.

The init() code needs to hide the pause button, and make sure that the audio is paused too.

    showInitialOverlay(button);
    hide(getPlay(button));
    hide(getPause(button));
    pauseAudio(player);

That's better. The init code is now more appropriately doing its job.

The question remains though, why after setting the initial overlay clickhandler on initial instead of the button, is the button playing immediately after we click on the initial image?

I think that it has something to do with the play/pause buttons being hidden to start with, and remember that we had a similar problem with other code, that was fixed by updating the isPlaying() function.

It's time for another test, from what we have at https://jsfiddle.net/pmw57/tavcvcu6/401/


Getting initial to work at the top of the code?
#1497

I thought you were looking at this:
#1489

I didn't know you were still working on the other code.

You said, "so job done," so I took that to mean you were done with the code


#1498

Here's that test, it's a simple one:

  it("isn't playing when the button is initialized", function () {
    app.buttone.init(button);
    expect(app.buttone.isPlaying(button)).toBe(false);
  });

That test fails, because isPlaying() isn't a function. Let's add it to the list of things being returned from the playbutton code:

  return {
    upTo,
    init
  };

And now the test is failing because it expects true to be false. https://jsfiddle.net/pmw57/tavcvcu6/402/

This is a good place to be, for it has confirmed out suspicions about what's wrong with the code, and makes it easy for us to investigate the problem.


#1499

issue:
When you click inbetween the boxes, the button goes on and off when it shouldn't.
It should only change when you click on the playbutton.
https://jsfiddle.net/pmw57/tavcvcu6/402/


#1500

I'll investigate that after getting the current issue resolved. There will be a delay of a few hours after having resolved it though.


#1501

The issue was occuring because when initial is clicked, after the click event is handled by the initial click handler, the event bubbles up to parent elements, where the playbutton click event then becomes triggered.

This can be stopped by having the initial click handler stop propogation of the click event, so that it doesn't bubble up to its parents.

  function initialOverlayClickHandler(evt) {
    event.stopPropagation();

With that fix in place, , the initial click event is assigned to the initial element as you requested, and the play button is properly paused as it should be when you click on the initial image.

The code that has this fix in place it at https://jsfiddle.net/pmw57/tavcvcu6/404/

The next thing to do, is to have the play/pause only doing so when they are clicked, and not when between the links are clicked.

That I'll come back to investigating, in about 3 hours from now.


#1502

I shouldn't break protocol and need to have a test in place, to help confirm that we fixed the problem.

In this case, the test is to check that when the initial image is clicked, that the button shouldn't be playing.

  it("doesn't play when the initial image is clicked", function () {
    expect(app.buttone.isPlaying(button)).toBe(false);
    initial.click();
    expect(app.buttone.isPlaying(button)).toBe(false);
  });

Before the propagation fix, the above test properly fails, to tell us that the problem still exists.
https://jsfiddle.net/pmw57/tavcvcu6/405/

After putting the stopPropagation fix in place, we end up with the following code that works well and has tests in place to help warn us about any regressions to previously unwanted situations.

https://jsfiddle.net/pmw57/tavcvcu6/406/

That is the proper use of tests. Create a failing test, the write code to make the failing test pass, after which any refactoring can occur to further improve the code, using those tests as a safety net to help ensure that everything continues to work.


#1503

Red/green/refactor is the heartbeat of test-driven development.

source: http://www.happyprog.com/pulse/


#1504

With the updated code from https://jsfiddle.net/pmw57/tavcvcu6/406/ we can add a test for the behaviour that we want to occur.

It doesn't go on and off when I click between the boxes.

That was nice and easy. Job's done.


#1505

Click on the red border, that's not supposed to happen. It should be unclickable:


#1506

The CSS and/or the HTML SVG values controls the size of the play button.