• We just upgraded the platform on which this website runs! Please inform @Jaxel of any issues.

Jaxel's 2018 Scoreboard

Jaxel

Administrator
In one of my tutorial videos, I showed off the scoreboard I had been using since 2018:


Since doing this tutorial video, I have actually created a new scoreboard that I use for my weekly tournaments. That means I am no longer using the 2018 scoreboard that I showed in my tutorials. Because of that, I've decided to release the code I used in my 2018 scoreboards to the public, for free. Keep in mind, that this code is not very clean. I created this scoreboard before this website even existed, so the code is a bit hackey because it was designed for the older (offline) version of Scoreboard Assistant. It also uses a third-party font called "Ubuntu Condensed" that you will have to download to your computer.

Package CSS:
Code:
:root
{
    --body-width: 1600px;
    --border-width: 4px;
    --slant-width: 30px;
    --flex-height: 50px;
    
    --event-width: 640px;
    --game-width: 320px;
    --match-width: 240px;
    --player-width: 610px;
    --score-width: 90px;
    
    --font-family: 'Ubuntu Condensed';
    --font-shadow: 1px 1px 0 var(--border-color), 1px -1px 0 var(--border-color),
                    -1px 1px 0 var(--border-color), -1px -1px 0 var(--border-color),
                    2px 2px 0 var(--border-color), 2px -2px 0 var(--border-color),
                    -2px 2px 0 var(--border-color), -2px -2px 0 var(--border-color);
    
    --font-xsmall: 20px;
    --font-small: 30px;
    --font-medium: 40px;
    --font-large: 50px;
    
    --fast-speed: 0.25s;
    --slow-speed: 0.50s;
    --xslow-speed: 1.00s;
}

body
{
    position: relative;
    margin: 0 auto;
    width: var(--body-width);
    color: var(--font-color);
    font-family: var(--font-family);
    font-weight: bold;
    text-align: center;
    overflow: hidden;
}

.xslow { transition: all var(--xslow-speed) ease-out; }
.slow { transition: all var(--slow-speed) ease-out; }
.fast { transition: all var(--fast-speed) ease-in; }

.colorB { background: var(--border-color); }
.color1 { background: var(--main-color1); }
.color2 { background: var(--main-color2); }
.color3 { background: var(--main-color3); }

.xsmall { font-size: var(--font-xsmall); text-transform: uppercase; }
.small { font-size: var(--font-small); text-transform: uppercase; }
.medium { font-size: var(--font-medium); text-transform: uppercase; }
.large { font-size: var(--font-large); text-transform: uppercase; }




.toprow.hidden { margin-top: calc(0px - var(--flex-height)); }
.toprow > div { border-bottom: var(--border-width) solid var(--border-color); }

.botrow { position: absolute; bottom: 0; left: 0; right: 0; }
.botrow.hidden { margin-bottom: calc(0px - var(--flex-height)); }
.botrow > div { border-top: var(--border-width) solid var(--border-color); }

.flexbox
{
    display: flex;
    height: var(--flex-height);
    justify-content: center;
}
.flexitem
{
    min-width: calc(var(--slant-width) + var(--border-width));
    position: relative;
}
.flexitem.hidden { width: 0 !important; }

.divider
{
    margin: 0 calc(0px - var(--slant-width));
    width: calc(var(--slant-width) + var(--border-width));
}

.topL { -webkit-clip-path: polygon(0% 0%, calc(100% - var(--slant-width)) 0%, 100% 100%, var(--slant-width) 100%); }
.topR { -webkit-clip-path: polygon(var(--slant-width) 0%, 100% 0%, calc(100% - var(--slant-width)) 100%, 0% 100%); }
.topC { -webkit-clip-path: polygon(0% 0%, 100% 0%, calc(100% - var(--slant-width)) 100%, var(--slant-width) 100%); }
.botL { -webkit-clip-path: polygon(var(--slant-width) 0%, 100% 0%, calc(100% - var(--slant-width)) 100%, 0% 100%); }
.botR { -webkit-clip-path: polygon(0% 0%, calc(100% - var(--slant-width)) 0%, 100% 100%, var(--slant-width) 100%); }
.botC { -webkit-clip-path: polygon(var(--slant-width) 0%, calc(100% - var(--slant-width)) 0%, 100% 100%, 0% 100%); }

tags { color: #999999; }
text
{
    line-height: calc(var(--flex-height) - var(--border-width));
    overflow: hidden;
    text-overflow: ellipsis;
    text-shadow: var(--font-shadow);
    white-space: nowrap;
}
text.hidden { opacity: 0 !important; padding: 0 !important; }




.xsmall icon { margin-bottom: -4px; height: 22px; width: 22px; }
.small icon { margin-bottom: -5px; height: 32px; width: 32px; }
.medium icon { margin-bottom: -2px; height: 32px; width: 32px; }
.large icon { margin-bottom: -3px; height: 46px; width: 46px; }
icon { display: inline-block; background-position: center; background-size: 100%; }

icon.i8WR { background-image: url('http://data.8wr.io/sba/1/icons/8WR.png'); }
icon.iCHL { background-image: url('http://data.8wr.io/sba/1/icons/CHL.png'); }
icon.iINS { background-image: url('http://data.8wr.io/sba/1/icons/INS.png'); }
icon.iFB { background-image: url('http://data.8wr.io/sba/1/icons/FB.png'); }
icon.iSGG { background-image: url('http://data.8wr.io/sba/1/icons/SGG.png'); }
icon.iTW { background-image: url('http://data.8wr.io/sba/1/icons/TW.png'); }
icon.iTWC { background-image: url('http://data.8wr.io/sba/1/icons/TWC.png'); }
icon.iYT { background-image: url('http://data.8wr.io/sba/1/icons/YT.png'); }

team.t8WR { background-image: url('http://data.8wr.io/sba/1/teams/8WR.png'); }
team.tCLG { background-image: url('http://data.8wr.io/sba/1/teams/CLG.png'); }
team.tFOX { background-image: url('http://data.8wr.io/sba/1/teams/FOX.png'); }
team.tNRG { background-image: url('http://data.8wr.io/sba/1/teams/NRG.png'); }
team.tTSM { background-image: url('http://data.8wr.io/sba/1/teams/TSM.png'); }

Package JS:
Code:
document.addEventListener("DOMContentLoaded", function()
{
    var styles = getComputedStyle(document.documentElement);
    
    inSpeed = String(styles.getPropertyValue('--slow-speed')).trim();
    inSpeed = inSpeed.replace('s', '');
    inSpeed = inSpeed * 1000;
    outSpeed = inSpeed / 2;
});

function parseText(txt)
{
    if (txt == null || txt == '') { return ''; }
    txt = txt.trim();
    
    txt = txt.replace(/</g, "&lt;").replace(/>/g, "&gt;");
    txt = txt.replace(/\&/g, "&amp;").replace(/\s/g, "&nbsp;");
    
    var regex = /\{\{([\w\.]+?)\}\}/g;
    var match = regex.exec(txt);
    
    while (match != null)
    {
        match[1] = match[1].replace('.', ' ');
        txt = txt.replace(match[0], "<icon class=\"i"+match[1]+"\"></icon>");
        match = regex.exec(txt);
    }
    
    return txt.trim();
}

function elemsHide(elem)
{
    return function (next)
    {
        $(elem).addClass('fast hidden');
        next();
    };
}

function elemsShow(elem)
{
    return function (next)
    {
        $(elem).removeClass('fast hidden');
        next();
    };
}

function elemsUpdate()
{
    return function (next)
    {
        for (var prop in newData)
        {
            $('#'+prop+' text').html(newData[prop]);
        }
        next();
    };
}

Page HTML:
Code:
<div class="flexbox botrow hidden slow">
    <div class="flexitem botL colorB divider"></div>

    <div class="flexitem botC color2 xsmall game" id="gg">
        <text>&nbsp;</text>
    </div>

    <div class="flexitem botR colorB divider"></div>
</div>

<div class="flexbox toprow hidden slow">
    <div class="flexitem topL colorB divider"></div>

    <div class="flexitem topL color3 medium score score1 slow hidden" id="s1">
        <text class="slow hidden">&nbsp;</text>
    </div>

    <div class="flexitem topL colorB divider"></div>

    <div class="flexitem topL color2 medium player player1 xslow hidden" id="p1">
        <text class="slow hidden">&nbsp;</text>
        <team class="slow hidden"></team>
    </div>

    <div class="flexitem topL colorB divider"></div>

    <div class="flexitem topC color1 xsmall round" id="rr">
        <text>&nbsp;</text>
    </div>

    <div class="flexitem topR colorB divider"></div>

    <div class="flexitem topR color2 medium player player2 xslow hidden" id="p2">
        <text class="slow hidden">&nbsp;</text>
        <team class="slow hidden"></team>
    </div>

    <div class="flexitem topR colorB divider"></div>

    <div class="flexitem topR color3 medium score score2 slow hidden" id="s2">
        <text class="slow hidden">&nbsp;</text>
    </div>

    <div class="flexitem topR colorB divider"></div>
</div>

Page CSS:
Code:
.game
{
    min-width: calc(var(--slant-width) * 2);
    width: var(--game-width);
}

.round
{
    min-width: calc(var(--slant-width) * 2);
    width: var(--match-width);
}

.player { width: var(--player-width); }
.player1 { text-align: right; }
.player2 { text-align: left; }
.player text { padding: 0 calc(var(--slant-width) + 10px); }

.score { width: var(--score-width); }
.score text { padding: 0 var(--slant-width); }

.player team
{
    position: absolute;
    top: 0;
    
    height: var(--flex-height);
    width: 150px;
}
.player1 team { left: 30px; }
.player2 team { right: 30px; }

Page JS:
Code:
var versus_1 = docData['versus_1'].split('||');
    versus_2 = docData['versus_2'].split('||');
    round_1 = docData['round_1'].split('||');
    game_1 = docData['game_1'].split('||');

newData = {
    't1': {},
    't2': {},
    'p1': parseText(versus_1[0]),
    'p2': parseText(versus_2[0]),
    's1': docData['versus_1s'],
    's2': docData['versus_2s'],
    'rr': parseText(round_1[1]),
    'gg': parseText(game_1[1]),
};

if (versus_1[1] != undefined)
{
    newData['p1'] = '<tags>' + parseText(versus_1[1]) + '</tags> ' + newData['p1'];
    newData['t1'] = parseText(versus_1[1]).split('&nbsp;');
}

if (versus_2[1] != undefined)
{
    newData['p2'] = '<tags>' + parseText(versus_2[1]) + '</tags> ' + newData['p2'];
    newData['t2'] = parseText(versus_2[1]).split('&nbsp;');
}

if ($('#gg text').html() != newData['gg'])
{
    $('.game')
        .queue(elemsHide('.botrow')).delay(outSpeed)
        .queue(elemsUpdate()).delay(inSpeed * 4)
        .queue(elemsShow('.botrow')).delay(inSpeed);
}

if ($('#rr text').html() != newData['rr'])
{
    $('body')
        .queue(elemsHide('.score text')).delay(outSpeed)
        .queue(elemsHide('.score')).delay(outSpeed)
        .queue(elemsHide('.player text')).delay(outSpeed)
        .queue(elemsHide('.player')).delay(outSpeed)
        .queue(elemsHide('.toprow')).delay(outSpeed)
        .queue(elemsUpdate()).queue(teamsUpdate()).delay(inSpeed * 2)
        .queue(elemsShow('.toprow')).delay(inSpeed * 2)
        .queue(elemsShow('.player')).delay(inSpeed * 2)
        .queue(elemsShow('.player text')).delay(inSpeed)
        .queue(elemsShow('.score')).delay(inSpeed)
        .queue(elemsShow('.score text')).delay(inSpeed);
}
else if ($('#p1 text').html() != newData['p1'] || $('#p2 text').html() != newData['p2'])
{
    $('body')
        .queue(elemsHide('.score text')).delay(outSpeed)
        .queue(elemsHide('.score')).delay(outSpeed)
        .queue(elemsHide('.player text')).delay(outSpeed)
        .queue(elemsHide('.player')).delay(outSpeed)
        .queue(elemsUpdate()).queue(teamsUpdate()).delay(inSpeed * 2)
        .queue(elemsShow('.player')).delay(inSpeed * 2)
        .queue(elemsShow('.player text')).delay(inSpeed)
        .queue(elemsShow('.score')).delay(inSpeed)
        .queue(elemsShow('.score text')).delay(inSpeed);
}
else if ($('#s1 text').html() != newData['s1'] || $('#s2 text').html() != newData['s2'])
{
    $('body')
        .queue(elemsHide('.score text')).delay(outSpeed)
        .queue(elemsHide('.score')).delay(outSpeed)
        .queue(elemsUpdate()).delay(inSpeed * 4)
        .queue(elemsShow('.score')).delay(inSpeed)
        .queue(elemsShow('.score text')).delay(inSpeed);
}

function teamsUpdate()
{
    return function (next)
    {
        var int1, int2, cnt1 = 0, cnt2 = 0;
    
        clearInterval(int1);
        $('#p1 team').removeClass().addClass('t'+newData.t1[0]);

        if (newData.t1.length > 1)
        {
            int1 = setInterval(function()
            {
                cnt1 = (cnt1 >= newData.t1.length-1) ? 0 : (cnt1+1);
                $('#p1 team').removeClass().addClass('xslow t'+newData.t1[cnt1]);
            }, 15000);
        }

        clearInterval(int2);
        $('#p2 team').removeClass().addClass('t'+newData.t2[0]);

        if (newData.t2.length > 1)
        {
            int2 = setInterval(function()
            {
                cnt2 = (cnt2 >= newData.t2.length-1) ? 0 : (cnt2+1);
                $('#p2 team').removeClass().addClass('xslow t'+newData.t2[cnt2]);
            }, 15000);
        }
        
        next();
    };
}

And if you're interested in what my 2019 scoreboard looks like:

 

Raiser

New member
I'm not a coder, but I'm trying...
I popped this code into all the editors and renamed my stuff to match your titles and identifiers, but nothing is populating.
Is there something I'm missing that's breaking it?
 

Raiser

New member
I figured the pictures wouldn't show up, but I could cut those out.

Console does show this error

js:69 Uncaught TypeError: Cannot read property 'split' of undefined
at fireExec (js:69)
at c.snapshot (firebase.js?_v=12838d63:92)
at Object.i [as next] (jquery-3.3.1.min.js?_v=12838d63:2)
at next (database.ts:1071)
at async_observer.ts:51
 

Raiser

New member
Here is where it's breaking down at.

var versus_1 = docData['versus_1'].split('||');
versus_2 = docData['versus_2'].split('||');
round_1 = docData['round_1'].split('||');

game_1 = docData['game_1'].split('||');

I guess I need to use the "||" somewhere for it to populate?
I can't stress enough that I don't know what I'm doing haha
 

RealestFrenchy

New member
I'm encountering the same error here, and also am not very good with HTML or any of the other coding languages used here.
Where exactly should we name our variables,
 

Jaxel

Administrator
Variable names are these:

Scoreboard Assistant.png

By default, this scoreboard is looking for these very specific variable names... unless you change the code for it to look for something else.
 

RealestFrenchy

New member
I have those exact variables under that name, however I'm still getting that error.
I've been messing with the code a lot to try to see if I can get it to work.

When I delete the split and all the array portions it runs, however doesn't display the actual text for versus, while correctly displaying the Game and Round.

I thought it had to do with the variable being called player in the CSS/HTML and versus in the js/variables, but I'm honestly clueless


Edit: JK LMAO turns out I misspelled versus in the unique key and didn't realize it
 
Last edited:

Carniverous

New member
Noticed your CSS and JS both have Teams functions and formatting, but I don't see that addition in the video. Can you post a picture of what the full package panel looks like with some info about adding your teams functionality? Is this done through a named dropped down list?

** Question revoked, I got it... That is why the || split in the player name. Second param becomes the team that is uses to populate the team graphic.

Ok.. I've got team... but what about Icon? Is it used?
 
Last edited:

Jaxel

Administrator
The teams are done through a variation of this: