1(function (Drupal) { 2 'use strict'; 3 4 /** 5 * The current step of the form. 6 * 7 * @type {null|number} 8 */ 9 Drupal.webformDataLayerCurrentStep = null; 10 11 /** 12 * Performs data layer pushes on webform interactions. 13 * 14 * @type {Drupal~behavior} 15 * 16 * @prop {Drupal~behaviorAttach} attach 17 * Attaches behavior for performing data layer pushes on webform 18 * interactions. 19 */ 20 Drupal.behaviors.webformDataLayer = { 21 attach: function (context) { 22 // The attach behavior is called on main page load as well as on AJAX 23 // requests. AJAX requests might be triggered because of AJAX elements on 24 // the page or as well when the webform supports AJAX for the steps. On 25 // the first load of the webform we will get a Document object and when 26 // AJAX is enabled for the webform steps we will be getting a form 27 // element. We are only interessted in those two scenarios and do not care 28 // about the other elements going through the attach behaviors while 29 // interracting with the form. 30 let form; 31 if (context instanceof Document) { 32 // Address the webform specifically as on the page might be multiple 33 // forms. 34 form = context.querySelector('form.webform-submission-form'); 35 } 36 // On AJAX requests the form is passed, and we check that it is a webform, 37 // but check only if the current page has changed since we want only to 38 // cover the case where AJAX has been enabled for the webform steps and 39 // the previous if-condition that is checking if the context is a Document 40 // will be triggered for each step only on multistep forms without AJAX. 41 // We want to ignore all other AJAX events since we do not want to fire 42 // the "started" event whenever AJAX is used on a step e.g. if there is a 43 // file upload field then the whole form will be passed to the attach 44 // behavior whenever the file upload is used. 45 else if (context.tagName === 'FORM' && context.classList.contains('webform-submission-form') && (Drupal.webformDataLayerCurrentStep !== context.dataset.currentPage)) { 46 form = context; 47 } 48 // We are not interessted in any other scenarios. 49 else { 50 return; 51 } 52 53 // 54 Drupal.webformDataLayerCurrentStep = form.dataset.currentPage; 55 56 var started = false; 57 "click change".split(" ").forEach(function(eventType){ 58 form.addEventListener(eventType, function() { 59 // We need to keep a state since we are binding two event listeners 60 // and the once option will remove the event listener only for the 61 // event type that has been triggered. However, as we have two event 62 // types on which we are registering the event listener it will 63 // probably be fired twice before unbound from both of them. We could 64 // also use only a state variable without the once option, but then 65 // the event will be fired unnecessary on every click and change. 66 if (!started) { 67 started = true; 68 Drupal.webformDataLayerPush(form, 'started'); 69 } 70 },{once : true}); 71 }); 72 73 // AJAX enabled webforms will have a next instead of a submit button. 74 const nextButton = form.querySelector('input.webform-button--next[type="submit"]'); 75 if (nextButton) { 76 nextButton.addEventListener('click', function() { 77 if (form.checkValidity()) { 78 // On a multistep form if the user goes back to the previous step, 79 // but immediately clicks the next button the successful event might 80 // be triggered before the started event. In order to prevent this 81 // we make sure to trigger first the started event and then the 82 // successful event by deactivating the click handler for the 83 // started event. 84 if (!started) { 85 started = true; 86 Drupal.webformDataLayerPush(form, 'started'); 87 } 88 Drupal.webformDataLayerPush(form, 'successful'); 89 } 90 }); 91 } 92 93 // AJAX enabled webforms will have the submit button only on the last 94 // step. 95 const submitButton = form.querySelector('input.webform-button--submit[type="submit"]'); 96 if (submitButton) { 97 submitButton.addEventListener('click', function() { 98 if (form.checkValidity()) { 99 // On a multistep form if the user goes back to the previous step, 100 // but immediately clicks the next button the successful event might 101 // be triggered before the started event. In order to prevent this 102 // we make sure to trigger first the started event and then the 103 // successful event by deactivating the click handler for the 104 // started event. 105 if (!started) { 106 started = true; 107 Drupal.webformDataLayerPush(form, 'started'); 108 } 109 Drupal.webformDataLayerPush(form, 'successful'); 110 } 111 }); 112 } 113 } 114 }; 115 116 /** 117 * Helper function to submit a data layer push. 118 * 119 * @param {HTMLElement} form 120 * The form element. 121 * @param {string} status 122 * The status to submit to the data layer: 123 * - "started" on first interaction with the webform. 124 * - "successful" on form submission. 125 */ 126 Drupal.webformDataLayerPush = function(form, status) { 127 window.dataLayer = window.dataLayer || []; 128 window.dataLayer.push({ 129 'event': 'webform', 130 'title': form.dataset.title, 131 'step': form.dataset.currentPage, 132 'totalSteps': form.dataset.totalPages, 133 'status': status 134 }); 135 }; 136})(Drupal);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.