Pen Settings

HTML

CSS

CSS Base

Vendor Prefixing

Add External Stylesheets/Pens

Any URLs added here will be added as <link>s in order, and before the CSS in the editor. You can use the CSS from another Pen by using its URL and the proper URL extension.

+ add another resource

JavaScript

Babel includes JSX processing.

Add External Scripts/Pens

Any URL's added here will be added as <script>s in order, and run before the JavaScript in the editor. You can use the URL of any other Pen and it will include the JavaScript from that Pen.

+ add another resource

Packages

Add Packages

Search for and use JavaScript packages from npm here. By selecting a package, an import statement will be added to the top of the JavaScript editor for this package.

Behavior

Auto Save

If active, Pens will autosave every 30 seconds after being saved once.

Auto-Updating Preview

If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.

Format on Save

If enabled, your code will be formatted when you actively save your Pen. Note: your code becomes un-folded during formatting.

Editor Settings

Code Indentation

Want to change your Syntax Highlighting theme, Fonts and more?

Visit your global Editor Settings.

HTML

              
                <link href="https://fonts.googleapis.com/css2?family=Luckiest+Guy:wght@400&family=Lato:wght@400;500&display=swap" rel="stylesheet"> 

<header>
    <h1>
        Canto Bingo
    </h1>
    <div>
        Gossip Edition
    </div>
</header>

<section id="section">
    <label data-index="0" for="square-0">
        <input id="square-0" type="checkbox" onchange="removeCheckedSquare(this)" data-index="0">
        <span>0</span>
    </label>
    <label data-index="1" for="square-1">
        <input id="square-1" type="checkbox" onchange="removeCheckedSquare(this)" data-index="1">
        <span>1</span>
    </label>
    <label data-index="2" for="square-2">
        <input id="square-2" type="checkbox" onchange="removeCheckedSquare(this)" data-index="2">
        <span>2</span>
    </label>
    <label data-index="3" for="square-3">
        <input id="square-3" type="checkbox" onchange="removeCheckedSquare(this)" data-index="3">
        <span>3</span>
    </label>
    <label data-index="4" for="square-4">
        <input id="square-4" type="checkbox" onchange="removeCheckedSquare(this)" data-index="4">
        <span>4</span>
    </label>
    <label data-index="5" for="square-5">
        <input id="square-5" type="checkbox" onchange="removeCheckedSquare(this)" data-index="5">
        <span>5</span>
    </label>
    <label data-index="6" for="square-6">
        <input id="square-6" type="checkbox" onchange="removeCheckedSquare(this)" data-index="6">
        <span>6</span>
    </label>
    <label data-index="7" for="square-7">
        <input id="square-7" type="checkbox" onchange="removeCheckedSquare(this)" data-index="7">
        <span>7</span>
    </label>    
    <label data-index="8" for="square-8">
        <input id="square-8" type="checkbox" onchange="removeCheckedSquare(this)" data-index="8">
        <span>8</span>
    </label>
    <label data-index="9" for="square-9">
        <input id="square-9" type="checkbox" onchange="removeCheckedSquare(this)" data-index="9">
        <span>9</span>
    </label>
    <label data-index="10" for="square-10">
        <input id="square-10" type="checkbox" onchange="removeCheckedSquare(this)" data-index="10">
        <span>10</span>
    </label>
    <label data-index="11" for="square-11">
        <input id="square-11" type="checkbox" onchange="removeCheckedSquare(this)" data-index="11">
        <span>11</span>
    </label>    
    <label data-index="12" for="square-12">
        <input id="square-12" type="checkbox" onchange="removeCheckedSquare(this)" data-index="12">
        <span>12</span>
    </label>
    <label data-index="13" for="square-13">
        <input id="square-13" type="checkbox" onchange="removeCheckedSquare(this)" data-index="13">
        <span>13</span>
    </label>
    <label data-index="14" for="square-14">
        <input id="square-14" type="checkbox" onchange="removeCheckedSquare(this)" data-index="14">
        <span>14</span>
    </label>
    <label data-index="15" for="square-15">
        <input id="square-15" type="checkbox" onchange="removeCheckedSquare(this)" data-index="15">
        <span>15</span>
    </label>
    <label data-index="16" for="square-16">
        <input id="square-16" type="checkbox" onchange="removeCheckedSquare(this)" data-index="16">
        <span>16</span>
    </label>
    <label data-index="17" for="square-17">
        <input id="square-17" type="checkbox" onchange="removeCheckedSquare(this)" data-index="17">
        <span>17</span>
    </label>
    <label data-index="18" for="square-18">
        <input id="square-18" type="checkbox" onchange="removeCheckedSquare(this)" data-index="18">
        <span>18</span>
    </label>
    <label data-index="19" for="square-19">
        <input id="square-19" type="checkbox" onchange="removeCheckedSquare(this)" data-index="19">
        <span>19</span>
    </label>
    <label data-index="20" for="square-20">
        <input id="square-20" type="checkbox" onchange="removeCheckedSquare(this)" data-index="20">
        <span>20</span>
    </label>
    <label data-index="21" for="square-21">
        <input id="square-21" type="checkbox" onchange="removeCheckedSquare(this)" data-index="21">
        <span>21</span>
    </label>
    <label data-index="22" for="square-22">
        <input id="square-22" type="checkbox" onchange="removeCheckedSquare(this)" data-index="22">
        <span>22</span>
    </label>
    <label data-index="23" for="square-23">
        <input id="square-23" type="checkbox" onchange="removeCheckedSquare(this)" data-index="23">
        <span>23</span>
    </label>
    <label data-index="24" for="square-24">
        <input id="square-24" type="checkbox" onchange="removeCheckedSquare(this)" data-index="24">
        <span>24</span>
    </label>
</section>

<div id="winModal" class="modal">
    <h1>
        BINGO!
    </h1>
    <button onclick="resetGame()">
        Reset Game
    </button>
</div>

              
            
!

CSS

              
                $gridSquareSize: 100;
$gridFactor: 5;
$gridSquareSizePct: 100% / $gridFactor;
$spanBuffer: 8%;
$gridMasterMaxWidth: ($gridSquareSize * 1px) * $gridFactor;
$borderRadius: .4rem;

html {
    font-size: 62.5%;
}

body {
    font-size: 1rem;
    font-family: "Lato", sans-serif;
    padding-top: 1rem;
}

button {   
    background: #fff;
    border: .2rem solid #c52e2e;
    cursor: pointer;
    font-family: "Lato", serif;
    padding: 1rem 3.5rem;
    text-transform: uppercase;
    border-radius: .3rem;
    color: #c52e2e;
}

header {
    text-align: center;
}

h1 {
    $strokeCalc: 1 / 19 * 1em;
    $shadowCalc: 2 / 19 * 1em;
    font-family: "Luckiest Guy", sans-serif;
    margin: 0;
    display: inline-block;
    font-weight: normal;
    letter-spacing: -.04em;
    -webkit-text-stroke: $strokeCalc #fff;
    text-shadow: -$shadowCalc $shadowCalc #000;
    color: #c52e2e;
    line-height: .9;
    font-size: 12vw;
    
    + div {
        text-transform: uppercase;
        font-size: 3.5vw;
        letter-spacing: .15em;
    }
}

section {
    border-radius: $borderRadius;
    overflow: hidden;
    display: flex;
    margin: 2rem auto;
    flex-wrap: wrap;
    font-weight: 500;
    max-width: $gridMasterMaxWidth;
    line-height: 1;
}

label {
    border-radius: $borderRadius;
    border: .1rem solid;
    box-sizing: border-box;
    width: $gridSquareSizePct;
    padding-top: $gridSquareSizePct;
    text-align: center;
    position: relative;
    overflow: hidden;
    
    &:hover {
        cursor: pointer;
    }
}

input {
    position: absolute;
    left: -10000em;
    
    + span {
        display: none!important; // remove important when debugging
        margin-top: -60px;
    }
    
    ~ span {
        position: absolute;
        top: $spanBuffer;
        bottom: $spanBuffer;
        left: $spanBuffer;
        right: $spanBuffer;
        display: flex;
        justify-content: center;
        align-items: center;
        font-size: 4vw;
    }
    
    &:checked, &:disabled {
       ~ span {    
           cursor: default;
           
           &::before {
               cursor: default;
               content: "";
               background: gainsboro;
               position: absolute;
               left: -$spanBuffer;
               right: -$spanBuffer;
               top: -$spanBuffer;
               bottom: -$spanBuffer;
               z-index: -1;
           }
        }
    }
}

.modal {
    background: rgba(255,255,255,.8);
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    top: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    display: none;
    flex-direction: column;
    
    &.u-flex {
        display: flex;
        
        h1 {
            animation: scale-bounce1 450ms ease-out forwards;
        }
    }
    
    h1 {
        margin-bottom: .5em;
        transform: scale3d(0,0,0);
    }
}

@media (min-width: ($gridSquareSize * $gridFactor) / 16 * 1em) {
    h1 {
        font-size: 50px;
        -webkit-text-stroke: .2rem #fff;
        text-shadow: -.3rem .3rem #000;
        
        + div {
            font-size: 10px;
        }
    }
    
    input {
        ~ span {
            font-size: 20px;
        }
    }
}


@keyframes scale-bounce1 {
    50% {
        transform: scale3d(2,2,2);
    }
    100% {
        transform: scale3d(1.5,1.5,1.5);
    }
}


// asfasd
              
            
!

JS

              
                var sectionEl = document.getElementById('section');
var gridFactor = 5;
var centerSquareIndex = gridFactor * gridFactor / 2 - 0.5;
var masterArray = new Array();
var masterArrayOfWinningArrays = new Array();
var winningCombosCount = gridFactor * 2 + 2;
var freeText = 'FREE';
var squarePhrases = [
    "ai yah",
    "baht poh",
    "chaw see",
    "chee seen",
    "dai lo",
    "deem shurn",
    "gik say",
    "gwai lo",
    "jong gwai",
    "lau hey",
    "loh meng",
    "mm gun yew",
    "mm gwan ngo see",
    "mm sahm mm say",
    "mm teng wah",
    "mo bahn faht",
    "mo soh way",
    "nau",
    "ngau",
    "say la",
    "shurn la",
    "sik see",
    "sun ging",
    "tahm sum",
    "yow mo gow choy",
    "yum gung",
];

function pushFreeText() {
    masterArray.push(freeText);
}

// get the number of squares to set up subarrays of winning rows
var sectionEl = document.getElementById('section');
var squares = sectionEl.querySelectorAll('label');
for (d = 0; d < squares.length; d++) {
    if (d == centerSquareIndex) {
        pushFreeText();
    } else {
        masterArray.push(d);    
    }
    //console.log(masterArray);
}

// get index values to set up subarrays of winning columns
for (n = 0; n < gridFactor; n++) {
    for (m = 0; m < gridFactor; m++) {
        var columnValue = gridFactor * m + n;
        if (columnValue == centerSquareIndex) {
            pushFreeText();
        } else {
            masterArray.push(columnValue);
        }
    }
}

// get index values to set up subarrays of winning diagonals
for (m = 1; m <= gridFactor; m++) {
    var diagonalValue = gridFactor * m - m;
    if (diagonalValue == centerSquareIndex) {
        pushFreeText();
    } else {
        masterArray.push(diagonalValue);       
    }
}

for (m = 0; m < gridFactor; m++) {
    var diagonalValue = gridFactor * m + m;
    if (diagonalValue == centerSquareIndex) {
        pushFreeText();
    } else {
        masterArray.push(diagonalValue);       
    }
}

//console.log(masterArray);

// generate a subarray for each winning combo
for (s = 1; s <= winningCombosCount; s++) {
    var firstSliceIndex = gridFactor * (s - 1);
    var secondSliceIndex = gridFactor * s;
    masterArrayOfWinningArrays.push(masterArray.slice(firstSliceIndex, secondSliceIndex));
}

//console.log(masterArrayOfWinningArrays);

// randomize square phrases and populate them in each square
// using the Fisher-Yates algorithm
  for (let i = squarePhrases.length - 1; i > 0; i--) {
    const j = Math.floor(Math.random() * (i + 1));
    const temp = squarePhrases[i];
    squarePhrases[i] = squarePhrases[j];
    squarePhrases[j] = temp;
  }

//console.log(squarePhrases);

var allLabelEls = document.querySelectorAll('label');

for (v = 0; v < allLabelEls.length; v++) {
    var squareValue = squarePhrases[v];
    //console.log(squareValue);
    var spanEl = document.createElement('span');
    
    if (v == centerSquareIndex) {
        var currentInputEl = allLabelEls[v].firstElementChild; // refactor
        //console.log(allLabelEls[v]);
        //console.log(currentInputEl);
        spanEl.append(freeText);
        allLabelEls[v].append(spanEl);
        currentInputEl.disabled = true;
    } else {
        spanEl.append(squareValue);
        allLabelEls[v].append(spanEl);        
    }

    //console.log(spanEl);
    //console.log(allLabelEls[v]);
}

//console.log(allLabelEls);

// find FREE in the winning combos and mark them
for (var y = masterArrayOfWinningArrays.length - 1; y >= 0; y--) {
    for (x = masterArrayOfWinningArrays[y].length - 1; x >= 0; x--) {
        if (masterArrayOfWinningArrays[y].[x] === freeText) {
            masterArrayOfWinningArrays[y].splice(x + 1, 0, 'marked');
        }
    }
}

//console.log(masterArrayOfWinningArrays);

function removeCheckedSquare(inputEl) {
    var modal = document.getElementById('winModal');
    var selectedNumber = inputEl.getAttribute("data-index");
    //console.log(selectedNumber);
    
    // mark the selected number in its array so we can keep track of it
    if (inputEl.checked) {        
        for (var c = masterArrayOfWinningArrays.length - 1; c >= 0; c--) {
            for (a = masterArrayOfWinningArrays[c].length - 1; a >= 0; a--) {
                if (masterArrayOfWinningArrays[c].[a] === +selectedNumber) {
                   masterArrayOfWinningArrays[c].splice(a + 1, 0, 'marked');
                }
            }
            //console.log(masterArrayOfWinningArrays[c]);
        }
    } else {
        // if user unselects a square, remove the marker added earlier
        for (var c = masterArrayOfWinningArrays.length - 1; c >= 0; c--) {
            for (a = masterArrayOfWinningArrays[c].length - 1; a >= 0; a--) {
                if (masterArrayOfWinningArrays[c].[a] === +selectedNumber) {
                   masterArrayOfWinningArrays[c].splice(a + 1, 1);
                }
            }
            //console.log(masterArrayOfWinningArrays[c]);
        }
    }
 
    // display bingo modal when user wins
    for (w = 0; w < masterArrayOfWinningArrays.length; w++) {
        if (masterArrayOfWinningArrays[w].length === gridFactor * 2) {            
            modal.classList.add('u-flex');
        }
    }
}

function resetGame() {
    // use these lines if you want to clear the board when user wins
    // var allCheckedInputs = document.querySelectorAll('input');
    // for (h = 0; h < allCheckedInputs.length; h++) {
    //     if (allCheckedInputs[h].checked) {
    //         allCheckedInputs[h].checked = false;
    //     }
    // }
    history.go(0);
}


              
            
!
999px

Console