DEV Community

Cover image for One way to make Roulette using Javascript - Part 4
ozboware
ozboware

Posted on

One way to make Roulette using Javascript - Part 4

Wrapping up with style

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;
}
Enter fullscreen mode Exit fullscreen mode

to

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

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;
}
Enter fullscreen mode Exit fullscreen mode

Next, I created another global array for all the red coloured numbers

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

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' : '');
Enter fullscreen mode Exit fullscreen mode

Finally, I changed

numberBlock.setAttribute('class', nbClass);
Enter fullscreen mode Exit fullscreen mode

to

numberBlock.setAttribute('class', nbClass + colourClass);
Enter fullscreen mode Exit fullscreen mode

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' : '');
Enter fullscreen mode Exit fullscreen mode

then we change

otoBlock.setAttribute('class', 'oto_block');
Enter fullscreen mode Exit fullscreen mode

to

otoBlock.setAttribute('class', 'oto_block' + colourClass);
Enter fullscreen mode Exit fullscreen mode

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');
Enter fullscreen mode Exit fullscreen mode

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

let chipValues = [1, 5, 10, 100, 'clear'];
Enter fullscreen mode Exit fullscreen mode

I then iterated over the array

for(i = 0; i < chipValues.length; i++){}
Enter fullscreen mode Exit fullscreen mode

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

let cvi = i;
Enter fullscreen mode Exit fullscreen mode

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')));
Enter fullscreen mode Exit fullscreen mode

I then created the chip element and first set its class

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

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);
    }
};
Enter fullscreen mode Exit fullscreen mode

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

else{
    bet = [];
    numbersBet = [];
    removeChips();
}
Enter fullscreen mode Exit fullscreen mode

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];
Enter fullscreen mode Exit fullscreen mode

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);
Enter fullscreen mode Exit fullscreen mode

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%);
}
Enter fullscreen mode Exit fullscreen mode

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;
}
Enter fullscreen mode Exit fullscreen mode

then the chip's text

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

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
}
Enter fullscreen mode Exit fullscreen mode

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;
}
Enter fullscreen mode Exit fullscreen mode

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;
Enter fullscreen mode Exit fullscreen mode

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

let bankContainer = document.createElement('div');
bankContainer.setAttribute('class', 'bankContainer');
Enter fullscreen mode Exit fullscreen mode

then I created the bank element

let bank = document.createElement('div');
bank.setAttribute('class', 'bank');
Enter fullscreen mode Exit fullscreen mode

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") + '';
Enter fullscreen mode Exit fullscreen mode

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

bank.append(bankSpan);
bankContainer.append(bank);
Enter fullscreen mode Exit fullscreen mode

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);
Enter fullscreen mode Exit fullscreen mode

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;
}
Enter fullscreen mode Exit fullscreen mode

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;
Enter fullscreen mode Exit fullscreen mode

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") + '';
Enter fullscreen mode Exit fullscreen mode

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);
Enter fullscreen mode Exit fullscreen mode

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") + '';
Enter fullscreen mode Exit fullscreen mode

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');
Enter fullscreen mode Exit fullscreen mode

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');
Enter fullscreen mode Exit fullscreen mode

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;
};
Enter fullscreen mode Exit fullscreen mode

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

pnBlock.append(pnContent);  
bettingBoard.append(pnBlock);
Enter fullscreen mode Exit fullscreen mode

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;
}
Enter fullscreen mode Exit fullscreen mode

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;
}
Enter fullscreen mode Exit fullscreen mode

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');
Enter fullscreen mode Exit fullscreen mode

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

let pnContent = document.getElementById('pnContent');
Enter fullscreen mode Exit fullscreen mode

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;
Enter fullscreen mode Exit fullscreen mode

next I appended the pnSpan to the pnContent element

pnContent.append(pnSpan);
Enter fullscreen mode Exit fullscreen mode

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;
Enter fullscreen mode Exit fullscreen mode

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") + '';
Enter fullscreen mode Exit fullscreen mode

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") + '';
Enter fullscreen mode Exit fullscreen mode

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;
    }
}
Enter fullscreen mode Exit fullscreen mode

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 = [];
}
Enter fullscreen mode Exit fullscreen mode

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')){}
Enter fullscreen mode Exit fullscreen mode

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'));
Enter fullscreen mode Exit fullscreen mode

then we change the chip.setAttribute property

chip.setAttribute('class', 'chip ' + chipColour);
Enter fullscreen mode Exit fullscreen mode

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;
Enter fullscreen mode Exit fullscreen mode

Finally, we append the chipSpan to the chip

chip.append(chipSpan);
Enter fullscreen mode Exit fullscreen mode

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);
}
Enter fullscreen mode Exit fullscreen mode

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;
    }
}
Enter fullscreen mode Exit fullscreen mode

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;
Enter fullscreen mode Exit fullscreen mode

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');
Enter fullscreen mode Exit fullscreen mode


javascript

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

for(i = 0; i < cdChipActive.length; i++){
    cdChipActive[i].classList.remove('cdChipActive');
}
Enter fullscreen mode Exit fullscreen mode

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

let curClass = this.getAttribute('class');
Enter fullscreen mode Exit fullscreen mode

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');
}
Enter fullscreen mode Exit fullscreen mode

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')));
Enter fullscreen mode Exit fullscreen mode

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%);
}
Enter fullscreen mode Exit fullscreen mode

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;
Enter fullscreen mode Exit fullscreen mode

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){}
Enter fullscreen mode Exit fullscreen mode

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(){}
Enter fullscreen mode Exit fullscreen mode

Inside that function I made a notification element

let notification = document.createElement('div');
notification.setAttribute('id', 'notification');
Enter fullscreen mode Exit fullscreen mode

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);
Enter fullscreen mode Exit fullscreen mode

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);
Enter fullscreen mode Exit fullscreen mode

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

container.prepend(notification);
Enter fullscreen mode Exit fullscreen mode

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();
}
Enter fullscreen mode Exit fullscreen mode

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();
}
Enter fullscreen mode Exit fullscreen mode

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%);
}
Enter fullscreen mode Exit fullscreen mode

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(){};
Enter fullscreen mode Exit fullscreen mode

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

let notification = document.createElement('div');
notification.setAttribute('id', 'notification');
Enter fullscreen mode Exit fullscreen mode

we'll add to that the content block

let nSpan = document.createElement('div');
nSpan.setAttribute('class', 'nSpan');
Enter fullscreen mode Exit fullscreen mode

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);
Enter fullscreen mode Exit fullscreen mode

a message element stating "win"

let nsTxt = document.createElement('span');
nsTxt.innerText = ' Win';
nSpan.append(nsTxt);
Enter fullscreen mode Exit fullscreen mode

along with a breakdown element for the payout

let nsWin = document.createElement('div');
nsWin.setAttribute('class', 'nsWin');
Enter fullscreen mode Exit fullscreen mode

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);
Enter fullscreen mode Exit fullscreen mode

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

notification.append(nSpan);
container.prepend(notification);
Enter fullscreen mode Exit fullscreen mode

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);
Enter fullscreen mode Exit fullscreen mode

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

transition: 1s;
Enter fullscreen mode Exit fullscreen mode

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;
}
Enter fullscreen mode Exit fullscreen mode

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(){}
Enter fullscreen mode Exit fullscreen mode

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

wager = (wager == 0)? 100 : wager;
Enter fullscreen mode Exit fullscreen mode

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){}
}
Enter fullscreen mode Exit fullscreen mode

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

if(bet[i].amt != 0){}
Enter fullscreen mode Exit fullscreen mode

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;
Enter fullscreen mode Exit fullscreen mode

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") + '';
Enter fullscreen mode Exit fullscreen mode

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

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

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;
}
Enter fullscreen mode Exit fullscreen mode

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;
                }
            }
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

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);
    }
};
Enter fullscreen mode Exit fullscreen mode

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;
Enter fullscreen mode Exit fullscreen mode

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

lastWager = wager;
Enter fullscreen mode Exit fullscreen mode

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

wager = lastWager;
Enter fullscreen mode Exit fullscreen mode

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);
}
Enter fullscreen mode Exit fullscreen mode

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();
}
Enter fullscreen mode Exit fullscreen mode

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

Discussion (1)