1/** 2 * @file 3 * Track search API via DB. 4 */ 5(function (Drupal, $) { 6 'use strict'; 7 8 /** 9 * @namespace 10 */ 11 Drupal.searchApiTracking = Drupal.searchApiTracking || {}; 12 Drupal.searchApiTracking.onceClass = 'onceSATrack'; 13 // Stops for this current session. For example after autocomplete to not track the submit. 14 Drupal.searchApiTrackingSTOP = false; 15 16 /** 17 * Drupal behavior. 18 */ 19 Drupal.behaviors.searchApiTracking = { 20 attach: function (context) { 21 22 const searchEmpty = document.querySelector(drupalSettings.search_api_tracking.search_empty_selector); 23 const selectorAutocomplete = drupalSettings.search_api_tracking.autocomplete_selector; 24 const searchForms = drupalSettings.search_api_tracking.search_form_selectors.split(','); 25 26 let firstForm; 27 for (let i = 0; i < searchForms.length; i++) { 28 const form = document.querySelector(searchForms[i]); 29 if (form) { 30 firstForm = form; 31 32 break; 33 } 34 } 35 36 if (firstForm) { 37 if (firstForm.classList.contains(Drupal.searchApiTracking.onceClass)) { 38 return false; 39 } 40 41 firstForm.classList.add(Drupal.searchApiTracking.onceClass); 42 43 // Did you mean. 44 // Autocomplete. 45 Drupal.behaviors.searchApiTracking.trackDidYouMean(); 46 47 // Autocomplete. 48 Drupal.behaviors.searchApiTracking.trackAutocomplete(searchForms, selectorAutocomplete); 49 50 // Empty. 51 Drupal.behaviors.searchApiTracking.trackEmptySearch(searchEmpty, firstForm); 52 53 // Form submit. 54 Drupal.behaviors.searchApiTracking.trackFormSubmit(searchForms); 55 } 56 }, 57 trackDidYouMean: function() { 58 const didyouMeanLink = document.querySelector(drupalSettings.search_api_tracking.did_you_mean_selector); 59 if (didyouMeanLink) { 60 didyouMeanLink.addEventListener('click', function(e) { 61 Drupal.behaviors.searchApiTracking.sendTracking('did_you_mean', e.target.innerHTML); 62 }); 63 } 64 }, 65 trackEmptySearch: function(searchEmpty, searchFieldPopup) { 66 if (searchEmpty) { 67 // Quite risky could be more efficient to also expose selector? 68 const inputSearchFormWithKeywords= searchFieldPopup.querySelector('input'); 69 Drupal.behaviors.searchApiTracking.sendTracking('empty', inputSearchFormWithKeywords.value); 70 } 71 }, 72 trackAutocomplete: function(searchForms, selectorAutoComplete) { 73 for (let i = 0; i < searchForms.length; i++) { 74 const searchForm = document.querySelector(searchForms[i]); 75 if (!searchForm) { 76 continue; 77 } 78 79 let searchField = searchForm.querySelector(selectorAutoComplete); 80 81 $(searchField).on('autocompleteselect', function(event, ui) { 82 Drupal.behaviors.searchApiTracking.trackAutocompleteSendValues(ui.item.value); 83 Drupal.searchApiTrackingSTOP = true; 84 }); 85 } 86 }, 87 trackAutocompleteSendValues: function(value) { 88 Drupal.behaviors.searchApiTracking.sendTracking('autocomplete', value); 89 }, 90 trackFormSubmit: function(searchForms) { 91 for (let i = 0; i < searchForms.length; i++) { 92 const searchForm = document.querySelector(searchForms[i]); 93 if (!searchForm) { 94 continue; 95 } 96 searchForm.addEventListener('submit', function(event) { 97 if (!Drupal.searchApiTrackingSTOP) { 98 Drupal.behaviors.searchApiTracking.sendTracking('submit', event.target.querySelector('input').value); 99 Drupal.searchApiTrackingSTOP = true; 100 } 101 }); 102 } 103 }, 104 sendTracking: function(type, searchedString) { 105 const sortBy = document.getElementById(drupalSettings.search_api_tracking.sort_by_selector); 106 const sortOrder = document.getElementById(drupalSettings.search_api_tracking.sort_order_selector); 107 108 let sortByValue = ''; 109 let sortOrderValue = ''; 110 111 if (sortBy) { 112 sortByValue = sortBy.value; 113 } 114 if (sortOrder) { 115 sortOrderValue = sortOrder.value; 116 } 117 118 let xhr = new XMLHttpRequest(); 119 xhr.open('POST', Drupal.url('tracking/search-api-tracking'), true); 120 xhr.setRequestHeader('Content-Type', 'application/json'); 121 xhr.send(JSON.stringify({ 122 'type': type, 123 'searchedString': searchedString, 124 'sortBy': sortByValue, 125 'sortOrder': sortOrderValue, 126 })); 127 } 128 }; 129 130})(Drupal, jQuery);
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.