HOW TO ADD TWO WIDGETS ON THE SAME PAGE

- Posted in Tutorials by

Today we're going to look at how to add the same widget several times on the same page.

Currently, widgets work with IDS, so it's impossible, for example, to display the standings widget twice on the same page with different parameters. If we do, only the 1st widget on the page will be updated and the other will have no content.

The idea of this tutorial is to get around this limitation so that we can display the same widget on a page as many times as we like.

Before we start, we'll need a valid API-KEY. If you don't have one, you can create a free account on the dashboard and retrieve your API-KEY in the dashboard's profile section.

The widget documentation is available here. We'll be doing the widget tutorial for API-FOOTBALL, but it will be functional for all sports.

As a reminder, widget operation is fairly straightforward: simply copy/paste the widget code, indicating the parameters and API-KEY, and include the widgets.js file.

So let's see how to display two standings widgets on the same page.

We'll start by creating an index.html file containing the following code :

<!-- index.html -->
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Widgets Tutorial</title>
    </head>
    <body>
    </body>
</html>

We'll try adding the widgets standings code for two competitions and the widgets.js script to our index.html file, and see what happens.

<!-- index.html -->
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Widgets Tutorial</title>
    </head>
    <body>

        <div id="wg-api-football-standings"
            data-host="v3.football.api-sports.io"
            data-key="YOUR_API_KEY_HERE"
            data-league="39"
            data-team=""
            data-season="2022"
            data-theme=""
            data-show-errors="false"
            data-show-logos="true"
            class="wg_loader">
        </div>

        <div id="wg-api-football-standings"
            data-host="v3.football.api-sports.io"
            data-key="YOUR_API_KEY_HERE"
            data-league="61"
            data-team=""
            data-season="2022"
            data-theme=""
            data-show-errors="false"
            data-show-logos="true"
            class="wg_loader">
        </div>

    </body>

    <script
        type="module"
        src="https://widgets.api-sports.io/2.0.3/widgets.js">
    </script>

</html>

So we have two standings widgets in our code:

  • One for competition 39 and season 2022 (England Premier League)
  • One for competition 61 and season 2022 (France Ligue 1)

If we launch the page index.html in the browser, we get this :

multiple-widgets-1.jpg

The first of the two widgets displays the requested information, but the second is still loading. It is therefore not possible to display the same widget twice in this way.

So how do ?

To do this, we'll use an Iframe in the index.html file to load the widget.

We'll create the file standings.html and insert the widget script :

<!-- standings.html -->
<div id="wg-api-football-standings"
    data-host="v3.football.api-sports.io"
    data-key="YOUR_API_KEY_HERE"
    data-league="39"
    data-team=""
    data-season="2022"
    data-theme=""
    data-show-errors="false"
    data-show-logos="true"
    class="wg_loader">
</div>

<script
    type="module"
    src="https://widgets.api-sports.io/2.0.3/widgets.js">
</script>

And we're going to modify the index.html file like this :

<!-- index.html -->
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <meta name="viewport"  content="width=device-width, initial-scale=1">
        <title>Widgets Tutorial</title>
    </head>

    <body>

        <iframe width="100%" src="standings.html" frameborder="0"></iframe>

    </body>

</html>

If we launch the index.html page, we'll get the standings.html page loaded in front of the iframe.

multiple-widgets-2.jpg

On the other hand, the display is not good because the size of the iframe is not adapted to the content of the standings.html page.

We therefore need to adjust the iframe's width and height.

For the width, it's easy enough to add the tag width="100%" in the iframe. (It can also be done via CSS)

Height is a little more complicated, as there's no "native" solution for adjusting the height of an iframe in relation to its content. So we're going to create a javascript function that will resize the height of the iframe when it's loaded in relation to its content.

So we're going to create a scripts.js file and put the following content in it :

function resizeIframe(obj) {

    setTimeout(() => {

        obj.style.height=(obj.contentWindow.document.body.scrollHeight+20)+'px';

    }, 500)
}

This function works as follows :

  • Get iframe content height obj.contentWindow.document.body.scrollHeight
  • Update iframe height relative to content and adding 20px obj.style.height=()

You'll notice that there's also a timeout before the function resizes the iframe. This is necessary because, as the widget is generated via the API response, it takes a few milliseconds for the widget to be fully displayed. We've set a default value of "500ms", but you can increase or decrease this value.

So we're going to modify our index.html file to add the modifications for resizing the iframe and add the scripts.js file.

<!-- index.html -->
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Widgets Tutorial</title>
    </head>

    <body>

        <iframe width="100%" src="standings.html" frameborder="0" onload="resizeIframe(this)"></iframe>

    </body>

    <script src="scripts.js"></script>

</html>

Now let's launch our index.html page in our browser

multiple-widgets-3.jpg

As we can see, the widget is well displayed in both width and height.

All we have to do is load the second widget into a new iframe, and we'll have two identical widgets on the same page.

But we're not going to create several html pages for the same widget, we're going to modify the standings.html page so that we can pass it the parameters it needs.

The idea is to call the standings.html page via the iframe, passing it the league and season parameters. Our standings.html page then needs to retrieve the values from the url and add them to the widget code.

So we're going to add a function to our scripts.js file that will collect the parameters passed via the url

function get_parameter(param) {

    var vars = {};

    window.location.href.replace( location.hash, '' ).replace(/[?&]+([^=&]+)=?([^&]*)?/gi,
        function( m, key, value ) {

            vars[key] = value !==  undefined  ? value :  '';
        }
    );

    if ( param ) {

        return vars[param] ? vars[param] :  null;
    }
    return vars;
}

We will also modify the contents of the standings.html file as follows :

<!-- standings.html -->
<div id="wg-api-football-standings"
    data-host="v3.football.api-sports.io"
    data-key="YOUR_API_KEY_HERE"
    data-league=""
    data-team=""
    data-season=""
    data-theme=""
    data-show-errors="false"
    data-show-logos="true"
    class="wg_loader">
</div>

<script src="scripts.js"></script>

<script>
    let standings = document.getElementById('wg-api-football-standings')
    let league = get_parameter('league')
    let season = get_parameter('season')
    standings.setAttribute('data-league', league)
    standings.setAttribute('data-season', season)
</script>

<script
    type="module"
    src="https://widgets.api-sports.io/2.0.3/widgets.js">
</script>

We have also removed the values of the data-league and data-season fields as they will be automatically filled by our javascript code.

We've added our scripts.js file and also added the following code :

let standings = document.getElementById('wg-api-football-standings')
let league = get_parameter('league')
let season = get_parameter('season')
standings.setAttribute('data-league', league)
standings.setAttribute('data-season', season)

The get_parameter function retrieves the parameters passed via the url and inserts them into the widget code.

We will now test the code by adding two iframes and passing them different parameters. Modify the index.html file as follows

<!-- index.html -->
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Widgets Tutorial</title>
    </head>

    <body>

        <iframe width="100%" src="standings.html?league=39&season=2022" frameborder="0" onload="resizeIframe(this)"></iframe>

        <iframe width="100%" src="standings.html?league=61&season=2022" frameborder="0" onload="resizeIframe(this)"></iframe>

    </body>

    <script src="scripts.js"></script>

</html>

If you launch the page in your browser, you should see the two widgets like this :

multiple-widgets-4.jpg

Here is the complete code for each file, which you can adapt and improve to suit your needs.

index.html

<!-- index.html -->
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Widgets Tutorial</title>
    </head>

    <body>

        <iframe width="100%" src="standings.html?league=39&season=2022" frameborder="0" onload="resizeIframe(this)"></iframe>

        <iframe width="100%" src="standings.html?league=61&season=2022" frameborder="0" onload="resizeIframe(this)"></iframe>

    </body>

    <script src="scripts.js"></script>

</html>

standings.html

<!-- standings.html -->
<div id="wg-api-football-standings"
    data-host="v3.football.api-sports.io"
    data-key="YOUR_API_KEY_HERE"
    data-league=""
    data-team=""
    data-season=""
    data-theme=""
    data-show-errors="false"
    data-show-logos="true"
    class="wg_loader">
</div>

<script src="scripts.js"></script>

<script>
    let standings = document.getElementById('wg-api-football-standings')
    let league = get_parameter('league')
    let season = get_parameter('season')
    standings.setAttribute('data-league', league)
    standings.setAttribute('data-season', season)
</script>

<script
    type="module"
    src="https://widgets.api-sports.io/2.0.3/widgets.js">
</script>

scripts.js

// scripts.js
function resizeIframe(obj) {

    setTimeout(() => {

        obj.style.height=(obj.contentWindow.document.body.scrollHeight+20)+'px';

    }, 500)
}

function get_parameter(param) {

    var vars = {};

    window.location.href.replace( location.hash, '' ).replace(/[?&]+([^=&]+)=?([^&]*)?/gi,
        function( m, key, value ) {

            vars[key] = value !==  undefined  ? value :  '';
        }
    );

    if ( param ) {

        return vars[param] ? vars[param] :  null;
    }
    return vars;
}