PluginProbe ʕ •ᴥ•ʔ
Advanced Ads – Ad Manager & AdSense / 2.0.24
Advanced Ads – Ad Manager & AdSense v2.0.24
2.0.24 2.0.23 2.0.22 2.0.21 1.38.0 1.39.0 1.39.1 1.39.2 1.39.3 1.39.4 1.4.0 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 1.4.7 1.4.8 1.4.9 1.40.0 1.40.1 1.40.2 1.41.0 1.42.0 1.42.1 1.42.2 1.43.0 1.44.0 1.44.1 1.45.0 1.45.1 1.46.0 1.47.0 1.47.1 1.47.2 1.47.3 1.47.4 1.47.5 1.48.0 1.48.1 1.49.0 1.5.0 1.5.0.1 1.5.1 1.5.2 1.5.2.1 1.5.4 1.5.4.1 1.5.5 1.50.0 1.51.0 1.51.1 1.51.2 1.51.3 1.52.0 1.52.1 1.52.2 1.52.3 1.52.4 1.53.0 1.53.1 1.53.2 1.54.0 1.54.1 1.55.0 1.56.0 1.56.1 1.56.2 1.56.3 1.56.4 1.6 1.6.1 1.6.10 1.6.10.1 1.6.10.2 1.6.11 1.6.11.1 1.6.12 1.6.13 1.6.14 1.6.15 1.6.16 1.6.17 1.6.17.1 1.6.17.2 1.6.2 1.6.2.1 1.6.3 1.6.4 1.6.4.1 1.6.5 1.6.6 1.6.6.1 1.6.7 1.6.7.1 1.6.8 1.6.8.1 1.6.8.2 1.6.8.3 1.6.9 1.6.9.1 1.6.9.2 1.6.9.3 1.6.9.4 1.7 1.7.0.1 1.7.0.2 1.7.0.3 1.7.1 1.7.1.1 1.7.1.2 1.7.1.3 1.7.1.4 1.7.1.5 1.7.10 trunk 1.7.11 1.0.1 1.7.12 1.0.2 1.7.13 1.0.3 1.7.14 1.1.0 1.7.15 1.1.1 1.7.16 1.1.2 1.7.17 1.1.3 1.7.18 1.10 1.7.19 1.10.1 1.7.2 1.10.10 1.7.2.1 1.10.11 1.7.20 1.10.12 1.7.21 1.10.2 1.7.22 1.10.3 1.7.23 1.10.4 1.7.24 1.10.5 1.7.25 1.10.6 1.7.3 1.10.7 1.7.4 1.10.8 1.7.4.1 1.10.9 1.7.4.2 1.11 1.7.4.3 1.11.1 1.7.4.4 1.11.2 1.7.4.5 1.12 1.7.5 1.13 1.7.5.1 1.13.1 1.7.6 1.13.2 1.7.7 1.13.3 1.7.8 1.13.4 1.7.9 1.13.5 1.7.9.1 1.13.6 1.7.9.2 1.13.7 1.7.9.3 1.13.8 1.8 1.14 1.8.1 1.14.1 1.8.10 1.14.10 1.8.11 1.14.11 1.8.12 1.14.2 1.8.13 1.14.3 1.8.14 1.14.4 1.8.15 1.14.5 1.8.16 1.14.6 1.8.17 1.14.7 1.8.18 1.14.8 1.8.19 1.14.9 1.8.2 1.15 1.8.20 1.16 1.8.21 1.16.1 1.8.22 1.17 1.8.23 1.17.1 1.8.24 1.17.10 1.8.25 1.17.10-rc.1 1.8.26 1.17.11 1.8.27 1.17.12 1.8.28 1.17.12-rc.1 1.8.29 1.17.2 1.8.3 1.17.3 1.8.30 1.17.4 1.8.4 1.17.5 1.8.5 1.17.6 1.8.6 1.17.7 1.8.7 1.17.8 1.8.8 1.17.9 1.8.9 1.17.9-beta.1 1.9 1.18.0 2.0.0 1.19.0 2.0.1 1.19.1 2.0.10 1.2 2.0.11 1.2.1 2.0.12 1.2.2 2.0.13 1.2.3 2.0.14 1.2.4 2.0.15 1.2.5 2.0.16 1.2.6 2.0.17 1.2.7 2.0.18 1.20.0 2.0.19 1.20.0-rc.1 2.0.2 1.20.0-rc.2 2.0.20 1.20.1 2.0.3 1.20.2 2.0.4 1.20.3 2.0.5 1.21.0 2.0.6 1.21.1 2.0.7 1.22.0 2.0.8 1.22.1 2.0.9 1.22.2 1.23.0 1.23.1 1.23.2 1.24.0 1.24.1 1.24.2 1.25.0 1.25.1 1.26.0 1.27.0 1.28.0 1.29.0 1.29.1 1.3 1.3.1 1.3.10 1.3.11 1.3.12 1.3.13 1.3.14 1.3.15 1.3.16 1.3.17 1.3.18 1.3.2 1.3.3 1.3.4 1.3.5 1.3.6 1.3.7 1.3.8 1.3.9 1.30.0 1.30.1 1.30.2 1.30.2-rc.1 1.30.3 1.30.4 1.30.4-rc.1 1.30.5 1.31.0 1.31.1 1.32.0 1.32.0-rc.1 1.33.0 1.33.1 1.33.2 1.34.0 1.35.0 1.35.1 1.36.0 1.36.1 1.36.2 1.36.3 1.37.0 1.37.1 1.37.2
advanced-ads / src / admin / screen-support / autocomplete.js
advanced-ads / src / admin / screen-support Last commit date
autocomplete.js 3 months ago submit-ticket.js 3 months ago support.css 3 months ago support.js 3 months ago
autocomplete.js
179 lines
1 // Debounce function to limit the rate of API calls
2 const debounce = ( func, delay ) => {
3 let timeoutId;
4 return ( ...args ) => {
5 if ( timeoutId ) {
6 clearTimeout( timeoutId );
7 }
8 timeoutId = setTimeout( () => {
9 func( ...args );
10 }, delay );
11 };
12 };
13
14 export function searchCombobox(
15 inputId,
16 suggestionsListId,
17 endpoint,
18 formatSuggestion,
19 onSelect
20 ) {
21 const input = document.getElementById( inputId );
22 const suggestionsList = document.getElementById( suggestionsListId );
23 let selectedSuggestionIndex = -1;
24
25 // fetch users from API
26 const fetchData = async ( search ) => {
27 try {
28 const response = await fetch(
29 endpoint.replace( '{{search}}', search )
30 );
31 return await response.json();
32 } catch ( error ) {
33 console.error( 'Error fetching:', error );
34 return [];
35 }
36 };
37
38 // Render suggestions in the dropdown
39 const renderSuggestions = ( suggestions ) => {
40 // clear previous suggestions
41 clearSuggestions();
42 // set aria-expanded attribute
43 input.setAttribute( 'aria-expanded', 'true' );
44 suggestionsList.style.display = 'block';
45
46 // Show "No results found" message if no suggestions
47 if ( suggestions.length === 0 ) {
48 const li = document.createElement( 'li' );
49 li.textContent = 'No results found';
50 li.classList.add( 'no-results' );
51 suggestionsList.appendChild( li );
52 return;
53 }
54
55 // iterate over suggestions and create list items
56 // for each suggestion, create a list item and append it to the suggestions list
57 suggestions.forEach( ( suggestion, index ) => {
58 const li = document.createElement( 'li' );
59 li.id = `suggestion-${ index }`;
60 li.setAttribute( 'role', 'option' );
61 li.innerHTML = formatSuggestion( suggestion );
62 li.dataset.index = index;
63
64 // add event listener for suggestion click
65 // when a suggestion is clicked, set the input value to the suggestion name
66 li.addEventListener( 'click', () => {
67 onSelect( suggestion, input );
68 clearSuggestions();
69 } );
70
71 // append the list item to the suggestions list
72 suggestionsList.appendChild( li );
73 } );
74 };
75
76 // clear suggestions
77 const clearSuggestions = () => {
78 suggestionsList.innerHTML = '';
79 selectedSuggestionIndex = -1;
80 // set aria-expanded attribute
81 input.setAttribute( 'aria-expanded', 'false' );
82 suggestionsList.style.display = '';
83 // remove aria-activedescendant attribute
84 input.removeAttribute( 'aria-activedescendant' );
85 };
86
87 // Update the selected suggestion
88 // Highlight the selected suggestion
89 const updateSelectedSuggestion = () => {
90 const suggestions = suggestionsList.querySelectorAll(
91 'li:not(.no-results)'
92 );
93 // find the currently selected suggestion and highlight it
94 suggestions.forEach( ( li, index ) => {
95 if ( index === selectedSuggestionIndex ) {
96 // add selected class
97 li.classList.add( 'selected' );
98 // scroll the selected suggestion into view
99 li.scrollIntoView( { block: 'nearest' } );
100 // set aria-activedescendant attribute
101 input.setAttribute( 'aria-activedescendant', li.id );
102 } else {
103 // remove selected class
104 li.classList.remove( 'selected' );
105 }
106 } );
107 };
108
109 // Handle input event
110 const handleInput = async ( e ) => {
111 // Get the input value
112 const query = e.target.value.toLowerCase();
113
114 // Clear suggestions if input is empty
115 if ( query.length < 1 ) {
116 clearSuggestions();
117 return;
118 }
119
120 const data = await fetchData( query );
121 renderSuggestions( data );
122 };
123
124 // add debounce to input event
125 input.addEventListener( 'input', debounce( handleInput, 300 ) );
126 // Handle keyboard navigation
127 input.addEventListener( 'keydown', ( e ) => {
128 // get the current suggestions
129 const suggestions = suggestionsList.querySelectorAll(
130 'li:not(.no-results)'
131 );
132 // check if there are any suggestions and if the suggestions list is open
133 if (
134 suggestions.length === 0 ||
135 input.getAttribute( 'aria-expanded' ) === 'false'
136 ) {
137 return;
138 }
139
140 // Handle arrow key down navigation and move down the suggestions
141 if ( e.key === 'ArrowDown' ) {
142 e.preventDefault();
143 selectedSuggestionIndex =
144 ( selectedSuggestionIndex + 1 ) % suggestions.length;
145 updateSelectedSuggestion();
146
147 // Handle arrow key up navigation and move up the suggestions
148 } else if ( e.key === 'ArrowUp' ) {
149 e.preventDefault();
150 selectedSuggestionIndex =
151 ( selectedSuggestionIndex - 1 + suggestions.length ) %
152 suggestions.length;
153 updateSelectedSuggestion();
154
155 // Handle enter key and select the suggestion
156 } else if ( e.key === 'Enter' ) {
157 e.preventDefault();
158 if ( selectedSuggestionIndex > -1 ) {
159 suggestions[ selectedSuggestionIndex ].click();
160 }
161 // Handle escape key and close the suggestions
162 } else if ( e.key === 'Escape' ) {
163 input.value = '';
164 clearSuggestions();
165 }
166 } );
167
168 // Close suggestions when Escape is pressed anywhere in the document
169 document.addEventListener( 'keydown', ( e ) => {
170 if (
171 e.key === 'Escape' &&
172 input.getAttribute( 'aria-expanded' ) === 'true'
173 ) {
174 input.value = '';
175 clearSuggestions();
176 }
177 } );
178 }
179