Álvaro Franz
Álvaro Franz

Reputation: 801

Include script only once

I am building some twig modules that require specific javascript to work.

A javascript file is an asset that can be included as follows:

<script src="{{ asset('what/ever/hello.js') }}">

All cool so far, but knowing that:

If I add the script to the module twig file, and if the module is used multiple times, it will result in my page containing multiple calls to the same script.

How can I approach this case?

Upvotes: 0

Views: 570

Answers (1)

DarkBee
DarkBee

Reputation: 15608

You can work with an extension to keep track of the scripts you want included,

<?php
    class Project_Twig_Extension extends \Twig\Extension\AbstractExtension {
        protected $scripts = [];

        public function getFunctions() {
            return [
                new \Twig\TwigFunction('get_scripts', [ $this, 'getScripts']),
                new \Twig\TwigFunction('add_script', [ $this, 'addScript']),
            ];
        }

        public function getScripts() {
            return $this->scripts;
        }

        public function addScripts($script) {
            if (!in_array($script, $this->getScripts()) $this->scripts[] = $script;
        }
    }

Just some mock-up modules

{% do add_script('modules/module_a.js') %}
<h1>Module A</h1>
{% do add_script('modules/module_b.js') %}
<h1>Module B</h1>

Just a simple base template

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8" />
    </head>
    <body>
        {% block content %}
        {% endblock %}

        {% for script in get_scripts() %}
            <script src="{{ asset(script) }}"></script>
        {% endfor %}
    </body>
</html>

Just a simple child template

{% extends "base.html" %}
{% block content %}
    {% incude "modules/module_a.html" %}
    {% incude "modules/module_b.html" %}
    {% incude "modules/module_a.html" %}
    {% incude "modules/module_b.html" %}
{% endblock %}

This would output something like

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8" />
    </head>
    <body>
        <h1>Module A</h1>
        <h1>Module B</h1>
        <h1>Module A</h1>
        <h1>Module B</h1>

        <script src="js/modules/module_a.js"></script>
        <script src="js/modules/module_b.js"></script>
    </body>
</html>

Upvotes: 1

Related Questions