0

I have a paragraph content builder that has a countdown element. Moreover, this element, like other types of paragraphs, can be added an unlimited number of times. This means that the script must be called several times.

The script of the reverse report (https://github.com/PButcher/flipdown#flipdown ) is connected as a library on all pages. In the template of the required paragraph type, I have the following code:

    {% block paragraph %}
        {% block content %}
                <div class="row my-5 pb-0 pb-lg-5">
                        <div class="col-12 d-flex justify-content-center">
                                <div id="flipdown" class="flipdown mb-5"></div>
                                <script>
                                        var myDate = (new Date().getTime() / 1000) + ({{ content.field_timer_date.value|date('U')|format_date('unix') }} * 2) + 1;
                                        new FlipDown(myDate, "flipdown", {
                                                headings: ["Дней", "Часов", "Минут", "Секунд"],
                                                theme: "blue",
                                        }).start();
                                </script>
                        </div>                 
                </div> 
        {% endblock %}
{% endblock paragraph %}

The date in Unix format is inserted as needed, without any wrapper, but the script does not work with the error "Uncaught ReferenceError: FlipDown is not defined"

I usually do all initialization through custom.js, where I have everything wrapped up as needed in Drupal.behaviors. But what if I need a piece of script in the template, as in this example? I have not found a solution for Drupal 10.

2
  • 1
    It’s not defined because libraries are loaded at the very end of the body (as they should be), after your code executes. That’s also where you need to move your JS code. It should itself be a library, with a dependency on the library which defines the plugin. That will ensure the correct load order. You can use template preprocess hooks to attach data to drupalSettings in PHP, and pick them up again in JS, for example HTML IDs to invoke the plugin, if that’s what it needs. If it supports targeting with a class, even easier
    – Clive
    Commented Jul 31 at 15:30
  • ^ that should be the posted answer.
    – mona lisa
    Commented Jul 31 at 15:36

1 Answer 1

1

JS scripts are placed at the end of the <body /> (which is best/standard practice), so the FlipDown class doesn't exist when you're trying to use it. You're also not waiting for the DOM to be ready, but even if you did, there's no guarantee the external script would be loaded by then. In fact for an uncached page load over a remote network, it's likely not to be.

But what if I need a piece of script in the template

While there are some general edge cases where that might really be needed, in your case it's not. There's no reason you can't just leave some hints in the markup, and target appropriate elements from a script somewhere else. It's made even easier by the fact that you already have a natural identifier to use - the paragraph ID.

So your markup becomes:

<div class="row my-5 pb-0 pb-lg-5">
  <div class="col-12 d-flex justify-content-center">
    <div 
      id="flipdown-{{ paragraph.id() }}" 
      data-timer-date="{{ content.field_timer_date.value|date('U')|format_date('unix') }}" 
      class="flipdown mb-5"></div>
  </div>
</div>

And the behaviour, which must be in a library which either includes the external script directly, or depends on another library which includes it, is simple:

once('my-behaviour', '.flipdown[id][data-timer-date]', context).forEach(container => {
  const myDate = (new Date().getTime() / 1000) + (parseInt(container.getAttribute('data-timer-date')) * 2) + 1
  new FlipDown(myDate, container.id, {
    headings: ["Дней", "Часов", "Минут", "Секунд"],
    theme: "blue",
  }).start();
})

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.