Improve documentation about Drupal.eu_cookie_compliance event listener implementation

Created on 15 September 2023, over 1 year ago
Updated 22 October 2023, about 1 year ago

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
🐛 Bug report
Status

Fixed

Version

1.0

Component

Documentation

Created by

🇫🇷France goz

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

  • Issue created by @goz
  • Status changed to Needs review about 1 year ago
  • 🇫🇷France goz

    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
    
  • Status changed to Closed: works as designed about 1 year ago
  • 🇳🇴Norway svenryen

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

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

  • Status changed to Needs work about 1 year ago
  • 🇫🇷France goz

    I'd like to reopen for documentation improvements.

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

  • 🇫🇷France goz

    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 opened merge request.
  • Status changed to Needs review about 1 year ago
  • 🇳🇴Norway svenryen

    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?

  • 🇫🇷France goz

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

  • 🇳🇴Norway svenryen

    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....
  • Status changed to Fixed about 1 year ago
  • 🇳🇴Norway svenryen

    Merged. Thanks for contributing!

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

Production build 0.71.5 2024