Adding additional play buttons

Couldn’t I just do this?

Here’s what it’s like when most of the scripting code is moved out.

<div id="playButton2" class="notClicked" style="width: 80px;background-color:black; height:44px;border: 3px solid #0059dd; cursor: pointer;" onclick="
var player = document.getElementById('player2');
var button = document.getElementById('playButton2');
playButton(player, button);
"
onmouseover="
var player = document.getElementById('player2');
var button = document.getElementById('playButton2');
showPause(player, button);
"
onmouseout="
var player = document.getElementById('player2');
var button = document.getElementById('playButton2');
showSpeaker(player, button);
">

There’s still some repetition there, which is next to be removed.

Here it is now with that repetition removed. The functions take care of the bulk of the work now, no matter which player is being used.

<div id="playButton1" data-player="player1" class="notClicked"
    style="width: 80px;background-color:black; height:44px;border: 3px solid #0059dd; cursor: pointer;"
    onclick="playButton(event)" onmouseover="showPause(event)" onmouseout="showSpeaker(event)">

To hell with it, let’s get rid of that data-player attribute as well. It was just temporary until a better solution was done, and in this case that solution is taking the last digit of the playButton id.

<div id="playButton1" class="notClicked" style="width: 80px;background-color:black;
    height:44px; border: 3px solid #0059dd; cursor: pointer;"
    onclick="playButton(event)" onmouseover="showPause(event)" onmouseout="showSpeaker(event)">
  	var player = document.getElementById("player" + button.id.slice(-1));

Like magic. https://jsfiddle.net/hk4dvj15/9/

That notClicked class can now be easily removed too, instead using a “clicked” class that the script can add.

Before:

  #playButton2.notClicked svg { fill: white; }
  #playButton2 svg { fill: #d7601e; }

After:

  #playButton2 svg { fill: white; }
  #playButton2.clicked svg { fill: #d7601e; }

And the scripting line is changed so that instead of removing a class, it adds class instead.

    // button.classList.remove('notClicked');
    button.classList.add('clicked');

That notClicked class can now be removed from all of the play buttons.

<div id="playButton2" style="width: 80px;background-color:black;
    height:44px; border: 3px solid #0059dd; cursor: pointer;"
    onclick="playButton(event)" onmouseover="showPause(event)" onmouseout="showSpeaker(event)">

I’ve also noticed that the class list contains a lot of duplicates.

  #playButton1 { display: inline-block; padding: 0; }
  #playButton2 { display: inline-block; padding: 0; }
  #playButton3 { display: inline-block; padding: 0; }
  #playButton1 svg { fill: white; }
  #playButton2 svg { fill: white; }
  #playButton3 svg { fill: white; }
  #playButton1.clicked svg { fill: #1ed760; }
  #playButton2.clicked svg { fill: #d7601e; }
  #playButton3.clicked svg { fill: #d71e95; }

I want to remove the identifier completely, replacing it with a class name, but dependency by the scripting to attach to the appropriate player, must also be dealt with.

The audio player can be put inside of the div, below the SVG elements. That way no identifier is needed to access the audio player.

<div id="playButton2" ...>
  <svg class="play" ...>...</svg>
  <svg class="pause" ...>...</svg>
  <svg class="speaker" ...>...</svg>
  <audio style="display:none;">
    <source src='http://hi5.1980s.fm/;' type='audio/mpeg' />
  </audio>
</div>

The script can now just look for the audio player inside of the playButton.

function playButton(event) {
  var button = getButton(event.target);
  var player = button.querySelector("audio");
  ...
}

Now that the reliance on the id value is gone, the classname duplication can be dealt with.

When having three play buttons, you will have noticed that it added some duplication. We can now easily remove duplication from the class names.

Here’s what the class names currently look like:

  #playButton1{ display: inline-block; padding: 0; }
  #playButton2{ display: inline-block; padding: 0; }
  #playButton3{ display: inline-block; padding: 0; }
  #playButton1svg { fill: white; }
  #playButton2svg { fill: white; }
  #playButton3svg { fill: white; }
  #playButton1.clicked svg { fill: #1ed760; }
  #playButton2.clicked svg { fill: #d7601e; }
  #playButton3.clicked svg { fill: #d71e95; }

The slow and proper way to do this is to first add a class name to the elements.

<div id="playButton1" class="playButton" ...>
<div id="playButton2" class="playButton" ...>
<div id="playButton3" class="playButton" ...>

After doing that, we can add that class name to the declarations, and everything should still work.

  #playButton1.playButton { display: inline-block; padding: 0; }
  #playButton2.playButton { display: inline-block; padding: 0; }
  #playButton3.playButton { display: inline-block; padding: 0; }
  #playButton1.playButton svg { fill: white; }
  #playButton2.playButton svg { fill: white; }
  #playButton3.playButton svg { fill: white; }
  #playButton1.playButton.clicked svg { fill: #1ed760; }
  #playButton2.playButton.clicked svg { fill: #d7601e; }
  #playButton3.playButton.clicked svg { fill: #d71e95; }

Next, we can remove the id attributes from the class declarations

  .playButton { display: inline-block; padding: 0; }
  .playButton { display: inline-block; padding: 0; }
  .playButton { display: inline-block; padding: 0; }
  .playButton svg { fill: white; }
  .playButton svg { fill: white; }
  .playButton svg { fill: white; }
  .playButton.clicked svg { fill: #1ed760; }
  .playButton.clicked svg { fill: #d7601e; }
  .playButton.clicked svg { fill: #d71e95; }

The duplication here is now easily seen, and we can easily remove it.

  .playButton { display: inline-block; padding: 0; }
  .playButton svg { fill: white; }
  .playButton.clicked svg { fill: #1ed760; }
  .playButton.clicked svg { fill: #d7601e; }
  .playButton.clicked svg { fill: #d71e95; }

But oh no! All of the buttons now play with that last color. There are several options here.

  1. We could undo removing the unique identifier, and use both the id and the class
  2. We could use an extra class name on each button, such as blues, rock, indie
  3. We could use an nth-child selector so that we can target the 1st, 2nd, and 3rd matching elements

I like the second option out of those. Let’s get three different audio streams to experiment with.
1980s.fm is already there, the second can be classical, and the third can be movie scores.

    <source src='http://hi5.1980s.fm/;' type='audio/mpeg' />
    <source src='http://hi5.adagio.fm/;' type='audio/mpeg' />
    <source src='http://hi5.streamingsoundtracks.com/;' type='audio/mpeg' />

We can now give the playbuttons different class names, to represent each of these audio sources. The names can’t start with any numbers, so we’ll call the first one fm1980s instead.

<div class="playButton fm1980s" ...>
<div class="playButton adagio" ...>
<div class="playButton soundtracks" ...>

The class declarations can now be updated to make the colors properly work:

  .playButton { display: inline-block; padding: 0; }
  .playButton svg { fill: white; }
  .playButton.fm1980s.clicked svg { fill: #1ed760; }
  .playButton.adagio.clicked svg { fill: #d7601e; }
  .playButton.soundtracks.clicked svg { fill: #d71e95; }

And all of the colors now work for all of the different streaming sources.

2 Likes

Oh yes, and the centre margin between each play button is annoyingly doubled.

It’s now fixed by applying a negative margin.

  .playButton { display: inline-block; margin-left: -3px; padding: 0; }
2 Likes

Thank You!!!

I just learned a whole lot there.

If I wanted to do only one button in the middle, without the 2 squares on either side being clickable, how would I do that?

I was tring to figure that out.

Would this be right?

Would I be doing it right or, or am I missing stuff?

You don’t use negative margins, this ones does, how do I remove the negative margins?

<div style="width: 260px;height:44px;background-image: linear-gradient( to right,#000000 83px,#0059dd 83px, #0059dd 86px, #000000 86px, #000000 174px, #0059dd 174px, #0059dd 177px, #000000 177px );border: 3px solid #0059dd; cursor: default;"></div>


<div id="playButton2" style="margin:-32px 125px;width: 16px;height:14px; cursor: pointer;" onclick=" 
        var button = document.getElementById('playButton2');
        var player = document.getElementById('player2');
          document.querySelector('#playButton2 .initial').style.display='none';
          document.querySelector('#playButton2 .speaker').style.display='none';
          document.querySelector('#playButton2 .play').style.display='none';
        player.volume=1.0; if (player.paused) {
        document.querySelector('#playButton2 .pause').style.display='inline-block';
        document.querySelector('#playButton2 .play').style.display='none';
        player.play();
        } else {
        document.querySelector('#playButton2 .pause').style.display='none';
        document.querySelector('#playButton2 .play').style.display='inline-block';
        player.pause();
        }" onmouseover="
var player = document.getElementById('player2');
player.isPlaying = function () {
    return player.paused === false;
}
if  (player.isPlaying()) {
  document.querySelector('#playButton2 .speaker').style.display='none';
  document.querySelector('#playButton2 .pause').style.display='inline-block';
}"


onmouseout="
var player = document.getElementById('player2');
player.isPlaying = function () {
    return player.paused === false;
}
if  (player.isPlaying()) {
  document.querySelector('#playButton2 .pause').style.display='none';
  document.querySelector('#playButton2 .speaker').style.display='inline-block';
}">



 <svg class="initial" style="margin:0 2px;" width="12" height="14" viewBox="0 0 85 100"><path fill="white" d="M81 44.6c5 3 5 7.8 0 10.8L9 98.7c-5 3-9 .7-9-5V6.3c0-5.7 4-8 9-5l72 43.3z"></path></svg>

<svg class="pause" style="display:none  ;margin:0 3px; " width="10" height="14" viewBox="0 0 60 100"><path fill="#1ed760" d="M0 8c0-5 3-8 8-8s9 3 9 8v84c0 5-4 8-9 8s-8-3-8-8V8zm43 0c0-5 3-8 8-8s8 3 8 8v84c0 5-3 8-8 8s-8-3-8-8V8z"></path></svg>

<svg  class="speaker" style="display:none  ;margin:0 125px 0 0 ;" width="16" height="14" viewBox="0 0 16 14"><path d="M12.945.38l-.652.762c1.577 1.462 2.57 3.544 2.57 5.858 0 2.314-.994 4.396-2.57 5.858l.65.763c1.79-1.644 2.92-3.997 2.92-6.62S14.735 2.024 12.945.38zm-2.272 2.66l-.65.762c.826.815 1.34 1.947 1.34 3.198 0 1.25-.515 2.382-1.342 3.2l.652.762c1.04-1 1.69-2.404 1.69-3.96 0-1.558-.65-2.963-1.69-3.963zM0 4v6h2.804L8 13V1L2.804 4H0zm7-1.268v8.536L3.072 9H1V5h2.072L7 2.732z" fill="#1ed760" fill-rule="evenodd"></path></svg>

<svg class="play" style="display: none;margin:margin:0 2px;" width="12" height="14" viewBox="0 0 85 100"><path fill="#1ed760" d="M81 44.6c5 3 5 7.8 0 10.8L9 98.7c-5 3-9 .7-9-5V6.3c0-5.7 4-8 9-5l72 43.3z"></path></svg>

</div>

<audio id="player2" style="display:none;">
  <source src='http://hi5.1980s.fm/;' type='audio/mpeg'></source>
</audio>

wait, I would break them into 3 pieces, then add margin to them, right?


<div style="cursor:pointer;width: 89px; height:44px; border: 3px solid #0059dd;background-color:#00ffff;">
</div>

<div style="cursor:pointer;width: 88px; height:44px; border-top: 3px solid #0059dd;border-bottom: 3px solid #0059dd;background-color:#00ffff;">
</div>

<div style="cursor:pointer;width: 89px; height:44px; border: 3px solid #0059dd;background-color:#00ffff;">
</div>

Currently the play button, the thing that you click on to play/pause, is the whole black area’d playButton element.

Do you want all of it to trigger the onclick event? Or only the middle third?

Only the middle part:

<div style="cursor:default;width: 89px; height:44px; border: 3px solid #0059dd;background-color:#000000;">
</div>

<div style="margin: -50px 54px 0 95px;cursor:pointer;width: 88px; height:44px; border-top: 3px solid #0059dd;border-bottom: 3px solid #0059dd;background-color:#000000;">
</div>

<div style="margin: -50px 54px 85px 183px;cursor:default;width: 89px; height:44px; border: 3px solid #0059dd;background-color:#000000;">
</div>

Can I set that up only using just this?

<div id="playButton2" style="margin:-32px 125px;width: 16px;height:14px; cursor: pointer;" onclick=" 
        var button = document.getElementById('playButton2');
        var player = document.getElementById('player2');
          document.querySelector('#playButton2 .initial').style.display='none';
          document.querySelector('#playButton2 .speaker').style.display='none';
          document.querySelector('#playButton2 .play').style.display='none';
        player.volume=1.0; if (player.paused) {
        document.querySelector('#playButton2 .pause').style.display='inline-block';
        document.querySelector('#playButton2 .play').style.display='none';
        player.play();
        } else {
        document.querySelector('#playButton2 .pause').style.display='none';
        document.querySelector('#playButton2 .play').style.display='inline-block';
        player.pause();
        }" onmouseover="
var player = document.getElementById('player2');
player.isPlaying = function () {
    return player.paused === false;
}
if  (player.isPlaying()) {
  document.querySelector('#playButton2 .speaker').style.display='none';
  document.querySelector('#playButton2 .pause').style.display='inline-block';
}"


onmouseout="
var player = document.getElementById('player2');
player.isPlaying = function () {
    return player.paused === false;
}
if  (player.isPlaying()) {
  document.querySelector('#playButton2 .pause').style.display='none';
  document.querySelector('#playButton2 .speaker').style.display='inline-block';
}">



 <svg class="initial" style="margin:0 2px;" width="12" height="14" viewBox="0 0 85 100"><path fill="white" d="M81 44.6c5 3 5 7.8 0 10.8L9 98.7c-5 3-9 .7-9-5V6.3c0-5.7 4-8 9-5l72 43.3z"></path></svg>

<svg class="pause" style="display:none  ;margin:0 3px; " width="10" height="14" viewBox="0 0 60 100"><path fill="#1ed760" d="M0 8c0-5 3-8 8-8s9 3 9 8v84c0 5-4 8-9 8s-8-3-8-8V8zm43 0c0-5 3-8 8-8s8 3 8 8v84c0 5-3 8-8 8s-8-3-8-8V8z"></path></svg>

<svg  class="speaker" style="display:none  ;margin:0 125px 0 0 ;" width="16" height="14" viewBox="0 0 16 14"><path d="M12.945.38l-.652.762c1.577 1.462 2.57 3.544 2.57 5.858 0 2.314-.994 4.396-2.57 5.858l.65.763c1.79-1.644 2.92-3.997 2.92-6.62S14.735 2.024 12.945.38zm-2.272 2.66l-.65.762c.826.815 1.34 1.947 1.34 3.198 0 1.25-.515 2.382-1.342 3.2l.652.762c1.04-1 1.69-2.404 1.69-3.96 0-1.558-.65-2.963-1.69-3.963zM0 4v6h2.804L8 13V1L2.804 4H0zm7-1.268v8.536L3.072 9H1V5h2.072L7 2.732z" fill="#1ed760" fill-rule="evenodd"></path></svg>

<svg class="play" style="display: none;margin:margin:0 2px;" width="12" height="14" viewBox="0 0 85 100"><path fill="#1ed760" d="M81 44.6c5 3 5 7.8 0 10.8L9 98.7c-5 3-9 .7-9-5V6.3c0-5.7 4-8 9-5l72 43.3z"></path></svg>

</div>

<audio id="player2" style="display:none;">
  <source src='http://hi5.1980s.fm/;' type='audio/mpeg'></source>
</audio>

If it’s only the middle part that activates, then that middle part needs to be a separate section.

That can be easily done with the following structure:

<div class="playButton fm1980s">
  <div onclick="playButton(event)" onmouseover="showPause(event)" onmouseout="showSpeaker(event)">
    ...
  </div>
</div>

Where the outer div provides the background and border, and the inner div is the clickable button.

Here are the two styles used for it:

The margin helps to give vertical spacing between the three play buttons.
Inline-block prevents the button from taking the full width of the line.
The padding provides the spacing on either side of the inner button.

.playButton {
  margin: 0.5em;
  display: inline-block;
  padding: 0 80px;
  background-color: black;
  border: 3px solid #0059dd; }

Of the button itself (that being the inner div), it just needs a width and borders.

.playButton div {
  width: 80px;
   border-left: 3px solid #0059dd;
   border-right: 3px solid #0059dd;
   cursor: pointer;
}

I’ve just realised, that playButton isn’t a suitable name for the container outside of the button.
The one inside though is certainly a good candidate to be called, button.

<div class="playButton">
  <div class="button" ...>
     ...
  </div>
</div>
.playButton { ... }
  .playButton .button { ... }

Should the outer one be renamed to play, or to player?

<div class="player">
  <div class="button" ...>
     ...
  </div>
</div>
.player { ... }
.player .button { ... }

Does that seem better?

Can I do it like this if I only want to use 1.

<div style="width: 260px;height:44px;background-image: linear-gradient( to right,#000000 83px,#0059dd 83px, #0059dd 86px, #000000 86px, #000000 174px, #0059dd 174px, #0059dd 177px, #000000 177px );border: 3px solid #0059dd; cursor: default;"></div>


<div id="playButton2" style="margin:-47px 89px;width:88px;height:44px; cursor: pointer;background-color:;" onclick=" 
        var button = document.getElementById('playButton2');
        var player = document.getElementById('player2');
          document.querySelector('#playButton2 .initial').style.display='none';
          document.querySelector('#playButton2 .speaker').style.display='none';
          document.querySelector('#playButton2 .play').style.display='none';
        player.volume=1.0; if (player.paused) {
        document.querySelector('#playButton2 .pause').style.display='inline-block';
        document.querySelector('#playButton2 .play').style.display='none';
        player.play();
        } else {
        document.querySelector('#playButton2 .pause').style.display='none';
        document.querySelector('#playButton2 .play').style.display='inline-block';
        player.pause();
        }" onmouseover="
var player = document.getElementById('player2');
player.isPlaying = function () {
    return player.paused === false;
}
if  (player.isPlaying()) {
  document.querySelector('#playButton2 .speaker').style.display='none';
  document.querySelector('#playButton2 .pause').style.display='inline-block';
}"

onmouseout="
var player = document.getElementById('player2');
player.isPlaying = function () {
    return player.paused === false;
}
if  (player.isPlaying()) {
  document.querySelector('#playButton2 .pause').style.display='none';
  document.querySelector('#playButton2 .speaker').style.display='inline-block';
}">

 <svg class="initial" style="display:;margin:15px 38px;" width="12" height="14" viewBox="0 0 85 100"><path fill="white" d="M81 44.6c5 3 5 7.8 0 10.8L9 98.7c-5 3-9 .7-9-5V6.3c0-5.7 4-8 9-5l72 43.3z"></path></svg>

<svg class="pause" style="display:none  ;margin:15px 39px; " width="10" height="14" viewBox="0 0 60 100"><path fill="#1ed760" d="M0 8c0-5 3-8 8-8s9 3 9 8v84c0 5-4 8-9 8s-8-3-8-8V8zm43 0c0-5 3-8 8-8s8 3 8 8v84c0 5-3 8-8 8s-8-3-8-8V8z"></path></svg>

<svg  class="speaker" style="display:none;margin:15px 36px;" width="16" height="14" viewBox="0 0 16 14"><path d="M12.945.38l-.652.762c1.577 1.462 2.57 3.544 2.57 5.858 0 2.314-.994 4.396-2.57 5.858l.65.763c1.79-1.644 2.92-3.997 2.92-6.62S14.735 2.024 12.945.38zm-2.272 2.66l-.65.762c.826.815 1.34 1.947 1.34 3.198 0 1.25-.515 2.382-1.342 3.2l.652.762c1.04-1 1.69-2.404 1.69-3.96 0-1.558-.65-2.963-1.69-3.963zM0 4v6h2.804L8 13V1L2.804 4H0zm7-1.268v8.536L3.072 9H1V5h2.072L7 2.732z" fill="#1ed760" fill-rule="evenodd"></path></svg>

<svg class="play" style="display: none;margin:15px 38px;" width="12" height="14" viewBox="0 0 85 100"><path fill="#1ed760" d="M81 44.6c5 3 5 7.8 0 10.8L9 98.7c-5 3-9 .7-9-5V6.3c0-5.7 4-8 9-5l72 43.3z"></path></svg>

</div>

<audio id="player2" style="display:none;">
  <source src='http://hi5.1980s.fm/;' type='audio/mpeg'></source>

</audio>

Of course you can. Earlier you were asking about using multiple players, which resulted in a lot of duplication, remember?
I was taking you through how to remove that annoying duplication.

To get rid of this: “margin-left: -3px; padding: 0;
.playButton { display: inline-block; margin-left: -3px; padding: 0; }

You can add this instead:

border-bottom: 3px solid #0059dd;border-bottom: 3px solid #0059dd; border-left: 3px solid #0059dd;border-top: 3px solid #0059dd;

border-bottom: 3px solid #0059dd;border-bottom: 3px solid #0059dd; border-right: 3px solid #0059dd;border-top: 3px solid #0059dd;

or you can leave the border off on the right and left side of the middle block, and add them to the far left and right blocks.

That negative margin isn’t needed when you only have one.

What it did, was to fix a problem when you have a left and right border together. If they’re both 3px then you end up with a 6px border.

By making one of them a negative margin, it overlaps the other border fixing the problem.

When you have only the one player, there’s no need for that negative margin, so just ditch it.

1 Like