Problem/Motivation

Implementing event listener on Drupal.eu_cookie_compliance generate error in console Uncaught TypeError: Drupal.eu_cookie_compliance is not a function

Steps to reproduce

I'm currently in 10.1.3, and previously in 9.5.x.. Everything worked with 9.5.x.

I have custom code to interact with matomo :

var _paq = _paq || [];
(function($, Drupal, drupalSettings, _paq) {
    Drupal.behaviors.customMatomo = {
        attach: function(context, settings) {
          Drupal.eu_cookie_compliance('postPreferencesLoad', function(){
            if (Drupal.eu_cookie_compliance.hasAgreed('audience')) {
              _paq.push(['setConsentGiven']);
              _paq.push(['setCookieConsentGiven']);
            }
          });
        }
    };
})(jQuery, Drupal, drupalSettings, _paq);

Library is defined as :

custom_module.matomo:
  js:
    js/matomo.js: {}
  dependencies:
    - matomo/matomo
    - eu_cookie_compliance/eu_cookie_compliance

For information, i previously used advagg module (and submodules) in 9.5.x but remove it from 10.1.x.
I now use Standard Drupal JS aggregation, but enabling or disabling js preprocess does not change anything.

The following error is only displayed in specific cases :

Uncaught TypeError: Drupal.eu_cookie_compliance is not a function
    attach https://domain.name/modules/custom/custom_module/js/matomo.js?s0zcs9:5
    attachBehaviors https://domain.name/core/misc/drupal.js?v=10.1.3:166
    attachBehaviors https://domain.name/core/misc/drupal.js?v=10.1.3:162
    <anonymous> https://domain.name/core/modules/big_pipe/js/big_pipe.js?v=10.1.3:118
    <anonymous> https://domain.name/core/modules/big_pipe/js/big_pipe.js?v=10.1.3:138
  1. I'm anonymous, no error
  2. I'm logged in (admin or no special user), error is displayed
  3. I'm logged in with big_pipe uninstalled, no error
Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

GoZ created an issue. See original summary.

goz’s picture

Component: Code » Documentation
Status: Active » Needs review

I finally find out how to make it works.

I think it works "as designed", but documentation should be updated.

Event should be defined out of behaviors. Thinking about it, this should never be in behaviors, because it has to be called only once at page load, no need to reattach something with behaviors.

var _paq = _paq || [];
(function($, Drupal, drupalSettings, _paq) {
  Drupal.eu_cookie_compliance('postPreferencesLoad', function(){
    if (Drupal.eu_cookie_compliance.hasAgreed('audience')) {
      _paq.push(['setConsentGiven']);
      _paq.push(['setCookieConsentGiven']);
    }
  });
})(jQuery, Drupal, drupalSettings, _paq);

And we need to call this javascript with defer option so it will be called after eu_cookie_compliance.js script.

custom_module.matomo:
  js:
    js/matomo.js: { attributes: { defer: true } }
  dependencies:
    - matomo/matomo
    - eu_cookie_compliance/eu_cookie_compliance
svenryen’s picture

Status: Needs review » Closed (works as designed)

I'm closing this one, as it seems you got it sorted out.

Let me know if you'd like to reopen the issue.

goz’s picture

Status: Closed (works as designed) » Needs work

I'd like to reopen for documentation improvements.

I'll work on it this week during the Drupal Con Lille.

goz’s picture

Issue tags: +DrupalCon Lille 2023

In Readme, in the "Main file" section, we can read :

Drupal.eu_cookie_compliance = Drupal.eu_cookie_compliance || function () {
   (Drupal.eu_cookie_compliance.queue = Drupal.eu_cookie_compliance.queue || [])
   .push(arguments)
};
<code>
This ensures that a script from another module (which either should not use
`defer`, or should be placed AFTER the main script in the HTML) will be able
to access the Events from the main script and perform actions.
</cite>

Except that adding the code of the "Second file" section :

<code>
var postPreferencesLoadHandler = function(response) {
   console.log(response);
   window.cookieResponse = response;
};
Drupal.eu_cookie_compliance('postPreferencesLoad', postPreferencesLoadHandler);

Will display the error :

Uncaught TypeError: Drupal.eu_cookie_compliance is not a function

After adding "defer" attribute to script, error no more display and code is called as expected.
But i don't think putting the script in defer is the better solution.

Looking at https://git.drupalcode.org/project/eu_cookie_compliance_gtm/-/blob/2.x/j..., i can see Drupal.eu_cookie_compliance is defined before using it in our custom script. Adding same piece of code make it works without having to definer script as defered.

  // Sep up the namespace as a function to store list of arguments in a queue.
  Drupal.eu_cookie_compliance = Drupal.eu_cookie_compliance || function() {
    (Drupal.eu_cookie_compliance.queue = Drupal.eu_cookie_compliance.queue || []).push(arguments)
  };

In "Second file" section, i think we should add the following informations :

To use Drupal.eu_cookie_compliance in you custom code, don't forget to instanciate it putting this code in top of your script :

  // Sep up the namespace as a function to store list of arguments in a queue.
  Drupal.eu_cookie_compliance = Drupal.eu_cookie_compliance || function() {
    (Drupal.eu_cookie_compliance.queue = Drupal.eu_cookie_compliance.queue || []).push(arguments)
  }; 
<code>

And we can take advantage to add the recommended <code>(function(Drupal) {})(Drupal)

syntax on the example.

Example: reading the cookie preferences after submission + save it
somewhere else for later use
```
(function(Drupal) {
// Sep up the namespace as a function to store list of arguments in a queue.
Drupal.eu_cookie_compliance = Drupal.eu_cookie_compliance || function() {
(Drupal.eu_cookie_compliance.queue = Drupal.eu_cookie_compliance.queue || []).push(arguments)
};

var postPreferencesLoadHandler = function(response) {
console.log(response);
window.cookieResponse = response;
};
Drupal.eu_cookie_compliance('postPreferencesLoad', postPreferencesLoadHandler);
})(Drupal);
```

Warning: As this type of code only needs to be called once, it shouldn't be necessary to add it as a Drupal.behavior.

goz’s picture

Title: Implementing event listener on Drupal.eu_cookie_compliance generate error in console since 10.1.x » Improve documentation about Drupal.eu_cookie_compliance event listener implementation
goz’s picture

Status: Needs work » Needs review
svenryen’s picture

Thanks. I'll take a look. Are you done with your task, or do you plan to further work on this during sprints at DrupalCon Lille?

goz’s picture

I'm done now, but open to discuss about changes if needed.

svenryen’s picture

All right. I'll merge this later this week. Thanks for the contribution!

  • svenryen committed d2786628 on 8.x-1.x authored by GoZ
    Issue #3387537 by GoZ, svenryen: Improve documentation about Drupal....
svenryen’s picture

Status: Needs review » Fixed

Merged. Thanks for contributing!

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.