← Back to knowledge base |
  • Kentico Xperience 13

Load a site Javascript file after a Page builder is loaded in Kentico Xperience 13

In this post, I will provide you with code that loads a site JavaScript file after the Page Builder has loaded in Kentico Xperience 13.

Disclaimer

The solution in this article might initially seem a bit simplistic. However, while building a site on Xperience by Kentico—the successor to Xperience 13—I revisited the topic of JavaScript initialization and developed a more robust approach. The good news? The Page Builder in both products is quite similar, so you can easily adapt this solution for Xperience 13 as well!

The Problem

On my sites, I usually place a JavaScript file that handles all client-side logic right before the closing </body> tag. In Kentico Xperience 13, I would add this to the main _Layout.cshtml file.

    ...
    <script src="/Content/script.js" async asp-append-version="true"></script>
</body>
</html>

On the live site, this approach works well. Unfortunately, in the Page Builder, the script file gets loaded before the widgets. As a result, the script is not applied to the markup generated by the widgets. Additionally, the widgets load after the window.onload event, meaning there is no JavaScript event to listen for that allows you to dynamically add the script file.

I also asked Kentico support if there was a Kentico or .NET way to achieve this goal. They informed me that there isn't. So, I looked for a solution on my own.

The Solution

I ended up loading the JavaScript file using an interval to check for the existence of the .ktc-widget-zone element. Once the element is available, the script is added to the page. If a page does not contain widgets, the script is added after a certain number of interval runs.

Add this to your main layout file (i.e., _Layout.cshtml):

@if (Context.Kentico().PageBuilder().EditMode)
    {
        <script>
            window.addEventListener('load', function () {
                var ktcCounter = 0; // Interval counter for pages that do not have widget zones
                var interval = setInterval(function () { // Start interval with 200ms timer
                    var ktcElem = document.querySelector('.ktc-widget-zone'); // Try to get a widget zone element
                    if (ktcElem || ktcCounter > 10) { // If a widget zone is available or an interval counter exceeds a treshold
                        var body = document.querySelector('body');
                        var script = document.createElement('script'); // Create a script tag
                        script.type = 'text/javascript';
                        script.src = '/Content/script.js?v=' + (new Date()).getTime(); // Always get a fresh JS file
                        body.appendChild(script); // Add the script tag in the page
                        clearInterval(interval); // Stop the interval
                    }
                    ktcCounter++;
                }, 200);
            });
        </script>
    }
    else
    {
        <script src="~/Content/script.js" async></script>
    }


About the author

Milan Lund is a Freelance Web Developer with Kentico Expertise. He specializes in building and maintaining websites in Xperience by Kentico. Milan writes articles based on his project experiences to assist both his future self and other developers.

Find out more
Milan Lund