bracketryjs
Visualize a knockout tournament in the browser
Inject your markup

You can replace match element or some of its parts using several handy options.


import { createBracket } from 'bracketry'

const options = {

    getRoundTitleElement: (roundData, roundIndex) => { /* ...return an Element for round title */ },

    getMatchElement: (roundIndex, matchOrder) => { /* ...return an Element for a whole match OR null */ },
    
    getEntryStatusHTML: (entryStatus, context) => { /* ...return an HTML string for contestant's entryStatus */ },

    getNationalityHTML: (player, context) => { /* ...return an HTML string for player's nationality */ },

    getPlayerTitleHTML: (player, context) => { /* ...return an HTML string for player's title */ },
    
    getScoresHTML: (side, match) => { /* ...return an HTML string for side's scores */ },

    getMatchTopHTML: (match) => { /* ...return an HTML string to be rendered above a match */ },

    getMatchBottomHTML: (match) => { /* ...return an HTML string to be rendered underneath a match */ },
}

createBracket(your_data, your_wrapper, options)




getRoundTitleElement()
Parameters
Return value

    HTMLElement that will be inserted into the round titles bar instead of default title

getRoundTitleElement will be called for each round specified in your data (which was passed to createBracket). getRoundTitleElement will be called with a data of a given round as the first parameter. Although by design a Round has only a "name" property, you are not limited to that. All extra properties of a Round object (e.g., "prize money" or whatever) will persist. Mind the roundTitlesVerticalPadding option. This padding is not discarded by your Element but will be drawn around your Element.





getMatchElement()
Parameters
Return value

    HTMLElement that will replace the default match layout. Or null, if you want to prevent rendering a match at a given roundIndex and matchOrder

Please set explicit width and height to images and other asynchronously loaded content within your custom match element.

To prevent a given match from rendering return null from getMatchElement.

{
    getMatchElement: (roundIndex, matchOrder) => {
        const el = document.createElement('div')
        el.style.display = "flex"
        el.style.alignItems = "center"
        el.style.fontSize = "50px"
        el.innerHTML = `
            ${roundIndex}
            ${matchOrder}
             
            <img style="width: 150px" src="matches.jpg">
        `
        return el
    }
}






getNationalityHTML()
Parameters
Return value

    HTML string or just a string of text that will be injected into the nationality field.

If getNationalityHTML option is not provided (or if it fails to return a string), then "nationality" column will be filled with a bare string from contestants[id].players[i].nationality (if such property will be found). In most cases it won't look nice and will lead to a subtle horizontal misalignment within a match. So it's highly recommended to provide getNationalityHTML and return an HTML string where root element has an explicit width (equal for all players). Feel free to use getNationalityHTML to display any info you want. Think of it as just a way to populate "the second column on the left". There you can render a player's photo or whatever. If you want to prevent nationality from rendering, return an empty string from getNationalityHTML. In such case the corresponding element will not be visible even if "nationality" is provided in Players's data.

Flags

getNationalityHTML is where you can inject nationality flags. But it's your job to provide flag images and valid links to them.

{
    getNationalityHTML: player => {
        return `<img style="width: 40px;" src="your-flags-url/${player.nationality}">`
    }
}




getEntryStatusHTML()
Parameters
Return value

    HTML string or just a string of text that will be injected into the entry status field.

If getEntryStatusHTML option is not provided (or if it fails to return a string), then the corresponding column (first on the left) will be filled with a bare string from contestants[id].entryStatus (if such property will be found). In most cases it won't look nice and will lead to a subtle horizontal misalignment within a match. So it's highly recommended to provide getEntryStatusHTML and return an HTML string where root element has an explicit width (equal for all players).

{
    getEntryStatusHTML: entryStatus => {
        return `<div style="width: 24px">${entryStatus}<div>`
    }
}

Feel free to use getEntryStatusHTML to display any info you want. Think of it as just a way to populate "the first column on the left". If you want to prevent entry status from rendering, return an empty string from getEntryStatusHTML. In such case the corresponding element will not be visible even if "entryStatus" was provided in Contestant's data.





getPlayerTitleHTML()
Parameters
Return value

    HTML string or just a string of text that will be injected into the player title field.

Mind that getPlayerTitleHTML is NOT called (and bare Player.title is NOT rendered either) IF a given Side has a 'title' property getPlayerTitleHTML is the recommended way to turn your players' titles into links.

{
    getPlayerTitleHTML: player => {
        // let's say you provided an extra property "link_to_profile" to your players' data
        return `<a href="${player.link_to_profile}">${player.title}</a>`
    }
}




getScoresHTML()
Parameters
Return value

    HTML string or just a string of text which will be injected into the "scores" section of match layout.

getScoresHTML is called for each side of a match separately. The output string is used to render scores of a single side of a match, not both sides.





getMatchTopHTML()
Parameters
Return value

    HTML string or just a string of text which will be rendered above a match

Make sure that you have enough vertical space between the matches. Use matchMinVerticalGap option for that.





getMatchBottomHTML()
Parameters
Return value

    HTML string or just a string of text which will be rendered underneath a match

Make sure that you have enough vertical space between the matches. Use matchMinVerticalGap option for that.






All options listed here are not updatable. It means they can only be passed to createBracket but not to applyNewOptions lifecycle method.