One way to make Roulette using Javascript - Part 4

One way to make Roulette using Javascript - Part 4

Finishing the game

·

20 min read

In part 3 we worked on setting bets and controlling the wheel. Today we're going to finish off the styling and add in some more functionality such as the ability to remove bets, change the bet value ... basically everything to make it a proper game of roulette. First things first, let's change the container style from

#container{
    display: flex;
    justify-content: center;
    align-items: center;
}

to

#container{
    display: flex;
    justify-content: center;
    background-color: #016D29;
    height: 470px;
    padding: 20px;
    color: #fff;
}

We've removed the align-items property which would have pushed the board down with the container, changed the background colour to a shade of green, stretched the container out to fill the board and changed the main colour to white. Now to change the betting board numbers colours to red and black. First, in the stylesheet we add in two more classes

.redNum{
    background-color: #E0080B;
}

.blackNum{
    background-color: #000;
}

Next, I created a global array for all the red numbers

let numRed = [1, 3, 5, 7, 9, 12, 14, 16, 18, 19, 21, 23, 25, 27, 30, 32, 34, 36];

Then, underneath the nbClass variable in the buildBettingBoard function, I checked to see if the numRed array contained the iteration numberBlocks was on, if it did then the class would be set to ' redNum', if it didn't another check was made to make sure the current iteration wasn't on "2 to 1", if it weren't then the class would be set to ' blackNum', else the class would stay empty

var colourClass = (redBlocks.includes(numberBlocks[i]))? ' redNum' : ((nbClass == 'number_block')? ' blackNum' : '');

Finally, I changed

numberBlock.setAttribute('class', nbClass);

to

numberBlock.setAttribute('class', nbClass + colourClass);

Now the board is starting to take shape. Next I'll change the red and black one to one bets at the bottom of the board to their respective background colour. So, on line 263, just under the "var d = i" line, we add the following

var colourClass = (otoBlocks[i] == 'RED')? ' redNum' : ((otoBlocks[i] == 'BLACK')? ' blackNum' : '');

then we change

otoBlock.setAttribute('class', 'oto_block');

to

otoBlock.setAttribute('class', 'oto_block' + colourClass);

Now, when the page is loaded, all the colours are in place. As of now, the wager has been set to 5 so now we're going to add in the ability to change the wager. We're going to add in some chips underneath the wheel with the values: 1, 5, 10 and 100.

So first, back to the javascript. Near the end of the buildBettingBoard function, underneath bettingBoard.append(otoBoard); first I created the chipDeck element

let chipDeck = document.createElement('div');
chipDeck.setAttribute('class', 'chipDeck');

Next, I set the values of each chip to an array

let chipValues = [1, 5, 10, 100, 'clear'];

I then iterated over the array

for(i = 0; i < chipValues.length; i++){}

Inside the iteration I first set cvi to i, which will be used in the click event

let cvi = i;

I then set the chip colour class to a variable depending on the value of the chip

let chipColour = (i == 0)? 'red' : ((i == 1)? 'blue' : ((i == 2)? 'orange' : ((i == 3)? 'gold' : 'clearBet')));

I then created the chip element and first set its class

let chip = document.createElement('div');
chip.setAttribute('class', 'cdChip ' + chipColour);

followed by the chip's click event which, if isn't the clear chip, is basically changing the wager variable set earlier to the value of the array's iteration

chip.onclick = function(){
    if(cvi !== 4){
        wager = parseInt(chip.childNodes[0].innerText);
    }
};

else it empties the bet and numberBet arrays and clears the chips from the table

else{
    bet = [];
    numbersBet = [];
    removeChips();
}

I then set the chip's text by creating a span so I can control the alignment and setting its innerText to the array's iteration

let chipSpan = document.createElement('span');
chipSpan.setAttribute('class', 'chipSpan');
chipSpan.innerText = chipValues[i];

and appended the chipSpan to the chip, the chip to the chipDeck and the chipDeck to the bettingBoard

chip.append(chipSpan);
chipDeck.append(chip);
bettingBoard.append(chipDeck);

Now, after the page has been refreshed, you may just see a line of numbers, so we have to add in some style. First we style the chipDeck

.chipDeck{
    position: absolute;
    margin-left: -383px;
    margin-top: -75px;
    width: 310px;
    height:39px;
    border: 1px solid;
    border-radius: 10px;
    box-shadow: inset -2px -4px rgb(0 0 0 / 20%);
}

This adds in a white block underneath the wheel. We can shape and position the chips within this boundary. First the chip

.cdChip{
    width: 27px;
    height: 27px;
    background-color: #fff;
    border: 5px solid;
    border-radius: 100%;
    display: inline-block;
    margin-left: 9px;
    color: #000;
    cursor: pointer;
}

then the chip's text

.cdChipSpan{
    display: inherit;
    position: relative;
    top: 5px;
    width: 26px;
    font-weight: bold;
    font-size: 14px;
    text-align: center;
}

Next I moved and styled the "spin" button because currently it's stuck up on the board. So I changed that style from

.spinBtn{
    position: relative;
    top: 253px;
    font-size:28px;
    cursor:pointer
}

to

.spinBtn{
    position: absolute;
    margin-top: 329px;
    margin-left: -392px;
    font-size: 15px;
    background-color: #ffec00;
    padding: 10px 5px;
    border-radius: 100%;
    color: #000;
    font-weight: bold;
    cursor: pointer;
}

Now I wanted to see how much was being bet so first I created a couple of global variables

let bankValue = 1000;
let currentBet = 0;

back in the buildBettingBoard function, I added in the bank container underneath the chipDeck

let bankContainer = document.createElement('div');
bankContainer.setAttribute('class', 'bankContainer');

then I created the bank element

let bank = document.createElement('div');
bank.setAttribute('class', 'bank');

followed by the bank's text which is wrapped in a span element

let bankSpan = document.createElement('div');
bankSpan.setAttribute('id', 'bankSpan');
bankSpan.innerText = '' + bankValue.toLocaleString("en-GB") + '';

then I appended the bankSpan element to the bank element and the bank to the bankContainer

bank.append(bankSpan);
bankContainer.append(bank);

I repeated the process with the bet value element

let bet = document.createElement('div');
bet.setAttribute('class', 'bet');
let betSpan = document.createElement('span');
betSpan.setAttribute('id', 'betSpan');
betSpan.innerText = '' + currentBet.toLocaleString("en-GB") + '';
bet.append(betSpan);
bankContainer.append(bet);

next I had to style the new elements

.bank, .bet{
    display: inline-block;
    width: calc(50% - 28px);
    background-color: #000;
    font-size: 18px;
    margin-left: 7px;
    padding: 5px;
    border: 4px solid silver;
    border-radius: 7px;
    text-align: right;
}

Now I had to make the bank work. For this I just need to minus the wager from the bankvalue and refresh the content of the element. For the bet, all I need do is plus the wager to the currentBet variable and refresh the content of the bet element. So, in the setBet function underneath bet.push(obj);, we add in the following

bankValue = bankValue - wager;
currentBet = currentBet + wager;

and underneath that I updated the elements to display the values

document.getElementById('bankSpan').innerText = '' + bankValue.toLocaleString("en-GB") + '';
document.getElementById('betSpan').innerText = '' + currentBet.toLocaleString("en-GB") + '';

Now when you play, you'll see the bank going down and the bet rising with each bet placed. It's all good until the wheel stops turning then we see it doesn't change. The bank doesn't go up with a win and bet doesn't reset to zero. So, back to the spin function. Right above the payout variable I changed the bankValue variable to include any winnings

bankValue = (bankValue + (bet[i].odds * bet[i].amt) + bet[i].amt);

then, outside the for loop and above bet = [];, I reset the currentBet variable to 0 and updated the bankSpan and betSpan elements.

currentBet = 0
document.getElementById('bankSpan').innerText = '' + bankValue.toLocaleString("en-GB") + '';
document.getElementById('betSpan').innerText = '' + currentBet.toLocaleString("en-GB") + '';

Okay, looking good so far. Next I wanted a bar to display the list of previous numbers drawn. Back in the buildBettingBoard function just above container.append(bettingBoard), I built in the previous numbers block

let pnBlock = document.createElement('div');
pnBlock.setAttribute('class', 'pnBlock');

Which is basically going to be just a white bordered rectangle, this was followed by the main pnContent block

let pnContent = document.createElement('div');
pnContent.setAttribute('id', 'pnContent');

I then set an on-wheel function to the pnContent so when you hover over the numbers and scroll, the content will scroll left and right. This was so I could keep the scrollbar hidden as it blocks off most of the content when it's displayed. Even using the webkit scrollbar styling doesn't work on every browser, so I thought this was the best for UX

pnContent.onwheel = function(e){
    e.preventDefault();
    pnContent.scrollLeft += e.deltaY;
};

Finally, I appended the pnContent to the pnBlock and the pnBlock to the bettingBoard.

pnBlock.append(pnContent);    
bettingBoard.append(pnBlock);

Now when you refresh the page ... nothing. Ah yes, we need to add in the style.

.pnBlock{
    position: absolute;
    border: 1px solid;
    width: 500px;
    height: 45px;
    margin-top: 10px;
    margin-left: -1px;
}

#pnContent{
    border: 4px solid #d5b714;
    width: 485px;
    height: 31px;
    position: relative;
    display: block;
    margin-left: 4px;
    margin-top: 3px;
    background-color: #fff;
    color: #000;
    overflow:hidden;
}

The numbers will be added in using span elements, one for red, one for green and one for black, so I styled those in now

.pnRed, .pnBlack, .pnGreen{
    position: relative;
    display: inline;
    padding:10px;
    font-size: 19px;
    top: 5px;
}

.pnRed{
    color: red;
}

.pnBlack{
    color: black;
}

.pnGreen{
    color: green;
}

Now we have to get the numbers showing after every spin, so we go back to the spin function. Right above bet = [], I created the pnClass variable. It checks to see if the winningSpin number is in the numRed array, if it is the style will be pnRed, if it's not and the number is zero then the style will be pnGreen, else it'll be pnBlack

let pnClass = (numRed.includes(winningSpin))? 'pnRed' : ((winningSpin == 0)? 'pnGreen' : 'pnBlack');

then I called on the pnContent element and set it to a variable

let pnContent = document.getElementById('pnContent');

then I created the pnSpan element, gave it the class we set out earlier and set its text to the winning number

let pnSpan = document.createElement('span');
pnSpan.setAttribute('class', pnClass);
pnSpan.innerText = winningSpin;

next I appended the pnSpan to the pnContent element

pnContent.append(pnSpan);

finally I scrolled the pnContent element to the end of the sequence so, as the content grows, it will display the end numbers

pnContent.scrollLeft = pnContent.scrollWidth;

and that is that for that function. Now give the wheel a spin 12 or 15 times to see it in action.

You may have noticed by now that when you clear the bets from the board, the bank and current bet values don't reset, so let's fix that first. Back to the buildBettingBoard function and the chipDeck, right above bet = []; in the click event, just add the following

bankValue = bankValue + currentBet;
currentBet = 0;
document.getElementById('bankSpan').innerText = '' + bankValue.toLocaleString("en-GB") + '';
document.getElementById('betSpan').innerText = '' + currentBet.toLocaleString("en-GB") + '';

The next thing to do is change the chips on the table. Currently they're just white dots plonked onto the table. We're going to alter them to show the value of the bet and change colour depending on how high the bet is.

Before we get onto the styling, first we should change the way the bet objects are placed in their array. Right now, every time we make a bet a new object is added to the array. This can get quite bulky and when searching through the bets to find the value, it could slow things down. Instead of a new object being created with each bet, we're going to check if the bet has already been placed first, if it has we'll update the value plus whatever the current wager value is, if not, then we'll add in the new object. So we go into the setBet function. First we move

bankValue = bankValue - wager;
currentBet = currentBet + wager;
document.getElementById('bankSpan').innerText = '' + bankValue.toLocaleString("en-GB") + '';
document.getElementById('betSpan').innerText = '' + currentBet.toLocaleString("en-GB") + '';

to the top of the function, then underneath that we add in the following

for(i = 0; i < bet.length; i++){
    if(bet[i].numbers == n && bet[i].type == t){
        bet[i].amt = bet[i].amt + wager;
        return;
    }
}

which iterates through the bet array and checks to see if the numbers and bet type have a match. If there's a match, the bet value for that object is updated and we call upon return to prevent the function from going any further and setting the bet again. Now, after doing this, I noticed some odd behaviour. Whenever I cleared the bets, the arrays weren't being cleared properly. Every time I placed a new bet the number and bet arrays filled back up to the original and added the new bet afterwards. The only way I could get around this was by creating a new function - clearBet and calling on that in the onclick event of the chipDeck

function clearBet(){
    bet = [];
    numbersBet = [];
}

Okay, so now it all seems to be functioning correctly. Next we have a similar problem with the chips being laid on the table. Every time there's a click, a brand new element is created, this can cause performance issues if many bets are placed, so let's make sure only one chip element is being placed per bet. That's pretty simple to do, in the setBet function where the chip is being created, wrap it in the following if statement

if(!e.querySelector('.chip')){}

That way, it will only create the chip if the element doesn't already exist. Now we're going to work some more on the chips in that if statement.

First we set the colour class

let chipColour = (wager < 5)? 'red' : ((wager < 10)? 'blue' : ((wager < 100)? 'orange' : 'gold'));

then we change the chip.setAttribute property

chip.setAttribute('class', 'chip ' + chipColour);

Then we create the chipSpan element and as it's going to be the first chip laid we only need to set the innerText to equal the wager

let chipSpan = document.createElement('span');
chipSpan.setAttribute('class', 'chipSpan');
chipSpan.innerText = wager;

Finally, we append the chipSpan to the chip

chip.append(chipSpan);

so the if statement should now look like this

if(!e.querySelector('.chip')){
    let chipColour = (wager < 5)? 'red' : ((wager < 10)? 'blue' : ((wager < 100)? 'orange' : 'gold'));
    let chip = document.createElement('div');
    chip.setAttribute('class', 'chip ' + chipColour);
    let chipSpan = document.createElement('span');
    chipSpan.setAttribute('class', 'chipSpan');
    chipSpan.innerText = wager;
    chip.append(chipSpan);
    e.append(chip);
}

next we go back to the following statement

for(i = 0; i < bet.length; i++){
    if(bet[i].numbers == n && bet[i].type == t){
        bet[i].amt = bet[i].amt + wager;
        return;
    }
}

just above the return, we add in the following

let chipColour = (bet[i].amt < 5)? 'red' : ((bet[i].amt < 10)? 'blue' : ((bet[i].amt < 100)? 'orange' : 'gold'));
e.querySelector('.chip').setAttribute('class', 'chip ' + chipColour);
let chipSpan = e.querySelector('.chipSpan');
chipSpan.innerText = bet[i].amt;

This is similar to adding the original chip except it's not checking for the wager, it's checking for the total bet, updating the chip span to tell us the bet amount and updating the colour of the chip depending on the amount bet.

Next, I wanted to see which chip was currently in use, I thought about changing the cursor to an image, but then I'd have to use an image but as I wanted to make this version using only code, I opted to raise and add a shadow for the selected chip when it was clicked. So back to the chipDeck in the buildBettingBoard function.

In the chip onclick function, right under if(cvi !== 4){, I set the cdChipActive elements to a variable

let cdChipActive = document.getElementsByClassName('cdChipActive');
```javascript

then iterated over them and removed the class name from the element

```javascript
for(i = 0; i < cdChipActive.length; i++){
    cdChipActive[i].classList.remove('cdChipActive');
}

I then set the currently clicked element's class name to a variable

let curClass = this.getAttribute('class');

and, if the current class doesn't contain the cdChipActive class, set the new class for the element

if(!curClass.includes('cdChipActive')){
    this.setAttribute('class', curClass + ' cdChipActive');
}

then I slightly altered the chipColour variable to start the game with the 5 chip being set to active

let chipColour = (i == 0)? 'red' : ((i == 1)? 'blue cdChipActive' : ((i == 2)? 'orange' : ((i == 3)? 'gold' : 'clearBet')));

finally, I styled and positioned the element that is currently active

.cdChipActive{
    position: relative;
    top: -4px;
    box-shadow: 0 4px rgb(0 0 0 / 20%);
}

Now each token raises when you click it so you know what you're betting. The next problem I wanted to work on was setting a game over function. Currently the game just keeps on going infinitely, running the bank into the negative. We want it to stop when the bank and the bet reach 0.

First we need to make sure the bet can't exceed whatever's remaining in the bank, so we go back to the setBet function. Right at the top of the function I checked to see if the bankValue was lower than the wager, if it was I changed the wager to equal bankValue

wager = (bankValue < wager)? bankValue : wager;

Now, once the bank hits zero, no more bets can be placed ... except for bets of zero. To stop this, we wrap the rest of the setBet function in the following

if(wager > 0){}

So now the game stops as soon as the bank and bet hit zero. Now we need an option to start the game again. For this, I created a new function

function gameOver(){}

Inside that function I made a notification element

let notification = document.createElement('div');
notification.setAttribute('id', 'notification');

I then created the notification span with the "bankrupt" message and added it to the notification element

let nSpan = document.createElement('span');
nSpan.setAttribute('class', 'nSpan');
nSpan.innerText = 'Bankrupt';
notification.append(nSpan);

next, I created the "play again button" which will call on the resetGame function and added it to the notification element

let nBtn = document.createElement('div');
nBtn.setAttribute('class', 'nBtn');
nBtn.innerText = 'Play again';    
nBtn.onclick = function(){
    resetGame();
};
notification.append(nBtn);

I then added the notification element to the beginning of the container element

container.prepend(notification);

Next I created the resetGame function which is just resetting the main variables, removing the notification and replacing the board

function resetGame(){
    bankValue = 1000;
    currentBet = 0;
    wager = 5;
    bet = [];
    numbersBet = [];
    previousNumbers = [];
    document.getElementById('betting_board').remove();
    document.getElementById('notification').remove();
    buildBettingBoard();
}

Now we want the gameOver notification to show when the bank and the bet hits zero. It's no good showing it as soon as the bank hits zero while there's an active bet, so for this we go back into the spin function, right at the end of the timeout function, under removeChips(); we add the following

if(bankValue == 0 && currentBet == 0){
    gameOver();
}

finally we style the elements

#notification{
    position: absolute;
    width: 500px;
    height: 318px;
    background-color: #ad0205;
    z-index: 10;
    border: 8px solid #d3b201;
    border-radius: 12px;
    transition: 1s;
}

.nSpan{
    display: block;
    position: relative;
    top: 105px;
    font-size: 53px;
    text-align: center;
}

.nBtn{
    display: block;
    position: relative;
    top: 116px;
    left: 25%;
    width: 45%;
    padding: 10px;
    font-size: 32px;
    text-align: center;
    background-color: green;
    border-radius: 15px;
    box-shadow: 3px 4px rgb(0 0 0 / 25%);
    cursor: pointer;
    transition: .5s;
}

.nBtn:active{
    top: 118px;
    left: calc(25% + 2px);
    box-shadow: 1px 2px rgb(0 0 0 / 25%);
}

As we have a notification for game over, we may as well make the win look a bit more attractive while we're at it. I'll start by adding a new function called win

function win(){};

in that function we'll begin by adding the notification element

let notification = document.createElement('div');
notification.setAttribute('id', 'notification');

we'll add to that the content block

let nSpan = document.createElement('div');
nSpan.setAttribute('class', 'nSpan');

which includes an element for the winning number and its colour

let nsnumber = document.createElement('span');
nsnumber.setAttribute('class', 'nsnumber');
nsnumber.style.cssText = (numRed.includes(winningSpin))? 'color:red' : 'color:black';
nsnumber.innerText = winningSpin;
nSpan.append(nsnumber);

a message element stating "win"

let nsTxt = document.createElement('span');
nsTxt.innerText = ' Win';
nSpan.append(nsTxt);

along with a breakdown element for the payout

let nsWin = document.createElement('div');
nsWin.setAttribute('class', 'nsWin');

which includes the payout broken down into blocks of total bet, total win and payout

let nsWinBlock = document.createElement('div');
nsWinBlock.setAttribute('class', 'nsWinBlock');
nsWinBlock.innerText = 'Bet: ' + betTotal;
nSpan.append(nsWinBlock);
nsWin.append(nsWinBlock);
nsWinBlock = document.createElement('div');
nsWinBlock.setAttribute('class', 'nsWinBlock');
nsWinBlock.innerText = 'Win: ' + winValue;
nSpan.append(nsWinBlock);
nsWin.append(nsWinBlock);
nsWinBlock = document.createElement('div');
nsWinBlock.setAttribute('class', 'nsWinBlock');
nsWinBlock.innerText = 'Payout: ' + (winValue + betTotal);
nsWin.append(nsWinBlock);
nSpan.append(nsWin);

I then appended the nSpan to the notification element and prepended notification to the container

notification.append(nSpan);
container.prepend(notification);

This was followed by setting 2 timeouts. 1 was set 3 seconds after the notification was shown, the other after 4 seconds. The first set the opacity of the notification to 0. This was followed by the removal of the element.

setTimeout(function(){
    notification.style.cssText = 'opacity:0';
}, 3000);
setTimeout(function(){
    notification.remove();
}, 4000);

I then added in a transition to the notification element in the stylesheet

transition: 1s;

along with the styling for the newly added blocks

.nsWin{
    position:absolute;
    left: 4px;
}

.nsWinBlock{
    display: inline-block;
    font-size: 21px;
    border-right: 1px solid;
    border-left: 1px solid;
    padding-left: 40px;
    padding-right: 40px;
}

Combined, this gives a fadeout effect to the winning notification element. Now place a bet on black and red or any guranteed win and give it a spin.

Next, I wanted the ability to remove accidental bets from the table. I opted to take advantage of the right click here, which when activated will remove the wager from the bet clicked. Time to create one last function

function removeBet(){}

inside that function I made sure the wager wasn't on 0

wager = (wager == 0)? 100 : wager;

I then looped over the bet objects and checked for a number and type match

for(i = 0; i < bet.length; i++){
    if(bet[i].numbers == n && bet[i].type == t){}
}

On finding a match we then make sure the current bet amount isn't 0

if(bet[i].amt != 0){}

if not, we set the wager again by checking if the current bet amount is greater than the wager. If it is then the wager stays the same, if it's lower then the wager is set to whatever the bet is

wager = (bet[i].amt > wager)? wager : bet[i].amt;

Next I lowered the bet amount in the object by the wager, changed the bankValue plus the wager, changed the betValue minus the wager and refreshed the bank/bet elements to display the difference

bet[i].amt = bet[i].amt - wager;
bankValue = bankValue + wager;
currentBet = currentBet - wager;
document.getElementById('bankSpan').innerText = '' + bankValue.toLocaleString("en-GB") + '';
document.getElementById('betSpan').innerText = '' + currentBet.toLocaleString("en-GB") + '';

next I hid the chip if the current bet is on 0

if(bet[i].amt == 0){
    e.querySelector('.chip').style.cssText = 'display:none';
}

and updated the chip colour/figure if the bet is greater than zero

else{
    let chipColour = (bet[i].amt < 5)? 'red' : ((bet[i].amt < 10)? 'blue' : ((bet[i].amt < 100)? 'orange' : 'gold'));
    e.querySelector('.chip').setAttribute('class', 'chip ' + chipColour);
    let chipSpan = e.querySelector('.chipSpan');
    chipSpan.innerText = bet[i].amt;
}

The full function

function removeBet(e, n, t, o){
    wager = (wager == 0)? 100 : wager;
    for(i = 0; i < bet.length; i++){
        if(bet[i].numbers == n && bet[i].type == t){
            if(bet[i].amt != 0){
                wager = (bet[i].amt > wager)? wager : bet[i].amt;
                bet[i].amt = bet[i].amt - wager;
                bankValue = bankValue + wager;
                currentBet = currentBet - wager;
                document.getElementById('bankSpan').innerText = '' + bankValue.toLocaleString("en-GB") + '';
                document.getElementById('betSpan').innerText = '' + currentBet.toLocaleString("en-GB") + '';
                if(bet[i].amt == 0){
                    e.querySelector('.chip').style.cssText = 'display:none';
                }else{
                    let chipColour = (bet[i].amt < 5)? 'red' : ((bet[i].amt < 10)? 'blue' : ((bet[i].amt < 100)? 'orange' : 'gold'));
                    e.querySelector('.chip').setAttribute('class', 'chip ' + chipColour);
                    let chipSpan = e.querySelector('.chipSpan');
                    chipSpan.innerText = bet[i].amt;
                }
            }
        }
    }
}

The next step was to go through all of the betting points again and adding the right click event to call on the removeBet function. For instance:

numberBlock.oncontextmenu = function(e){
    e.preventDefault();
    if(numberBlocks[a] != '2 to 1'){
        removeBet(this, ''+numberBlocks[a]+'', 'inside_whole', 35);
    }else{
        num = (a == 12)? '3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36' : ((a == 25)? '2, 5, 8, 11, 14, 17, 20, 23, 26, 29, 32, 35' : '1, 4, 7, 10, 13, 16, 19, 22, 25, 28, 31, 34');
        removeBet(this, num, 'outside_column', 2);
    }
};

Next problem to fix was resetting the wager to the last bet amount after the bank was pushed to zero during a bet and the bet was won. Currently, the wager sticks on zero. To change this I created another global variable

let lastWager = 0;

then, at the top of the setBet function set the lastWager to equal the current wager

lastWager = wager;

then, at the end of the spin function set the wager back to equal the lastWager

wager = lastWager;

Now the bet won't be set to zero on a win. Finally, now that all of the testing is out of the way, I only wanted to spin the wheel if the bet was higher than 0 so I removed the button from the table by taking it out of the buildBettingBoard function and placing it in the setBet function, after if(wager > 0), wrapped in a statement checking if it doesn't already exist so it isn't added to the table multiple times

if(!container.querySelector('.spinBtn')){
    let spinBtn = document.createElement('div');
    spinBtn.setAttribute('class', 'spinBtn');
    spinBtn.innerText = 'spin';
    spinBtn.onclick = function(){
        this.remove();
        spin();
    };
    container.append(spinBtn);
}

and in the removeBet function, I checked to see if the bet value equalled zero, and removed the spin button if it did

if(currentBet == 0 && container.querySelector('.spinBtn')){
    document.getElementsByClassName('spinBtn')[0].remove();
}

And that's it. There are a couple of betting points missing (0-1, 0-2, 0-3), you could include a rebet function, add in some sound, animations, images and even a menu. But for the sake of this entry that's all there is to it. One way to make roulette using Javascript. I hope someone found it of some use.

You can play the game and see the full code on codePen here

Or you can download it from Github here