1//Function for limiting the selection to one checkbox within each group 2function limitSelectionToOne(groupClass) { 3 const checkboxes = document.querySelectorAll(groupClass); 4 5 checkboxes.forEach(checkbox => { 6 checkbox.addEventListener('change', () => { 7 if (checkbox.checked) { 8 // Deactivates all other checkboxes within the same group 9 checkboxes.forEach(otherCheckbox => { 10 if (otherCheckbox !== checkbox) { 11 otherCheckbox.checked = false; 12 } 13 }); 14 } 15 }); 16 }); 17} 18 19limitSelectionToOne('.audienceCheckbox'); 20limitSelectionToOne('.categoryCheckbox'); 21 22let currentPage = 1; 23const itemsPerPage = 10; 24let filteredJobs = []; 25const minKeywordLength = 3; 26let keyword = ''; 27function ajaxHandler(url, method, data) { 28 data = data || {}; 29 return new Promise((resolve, reject) => { 30 let xhr = new XMLHttpRequest(); 31 xhr.open(method, url, true); 32 xhr.setRequestHeader('Content-Type', 'application/json'); 33 xhr.setRequestHeader('Accept', 'application/json'); // Explizit JSON akzeptieren 34 35 xhr.onreadystatechange = function () { 36 if (xhr.readyState === XMLHttpRequest.DONE) { 37 if (xhr.status === 200) { 38 try { 39 let responseData = JSON.parse(xhr.responseText); 40 resolve(responseData); 41 } catch (e) { 42 console.error('Error parsing the JSON response:', e); 43 reject('Error parsing the response'); 44 } 45 } else { 46 reject('Error: ' + xhr.status); 47 } 48 } 49 }; 50 51 xhr.onerror = function () { 52 reject('Network error'); 53 }; 54 55 xhr.send(JSON.stringify(data)); 56 }); 57} 58 59function handleSelectionOnChange() { 60 return async function () { 61 const url = document.querySelector(`.job-list-container`).getAttribute('data-url'); 62 63 const checkboxes = document.querySelectorAll('.job-filter .select-options-container input[type="checkbox"]'); 64 65 // Array for saving the selected IDs 66 let selectedAudienceIds = []; 67 let selectedCategoryIds = []; 68 69 // Iterate over the checkboxes and collect the selected IDs 70 checkboxes.forEach(checkbox => { 71 if (checkbox.checked) { 72 if (checkbox.classList.contains('audienceCheckbox')) { 73 selectedAudienceIds.push(checkbox.value); 74 } else if (checkbox.classList.contains('categoryCheckbox')) { 75 selectedCategoryIds.push(checkbox.value); 76 } 77 } 78 }); 79 80 let data = { 81 selectedAudienceIds: selectedAudienceIds, 82 selectedCategoryIds: selectedCategoryIds, 83 keyword: keyword.length >= minKeywordLength ? keyword : null, 84 }; 85 try { 86 const result = await ajaxHandler(url, 'POST', data); 87 if (result.status === 200) { 88 filteredJobs = result.jobs; 89 currentPage = 1; 90 updateJobListView(result.categories); 91 if (data.keyword === null) { 92 updateCounts(result.allJobs, selectedAudienceIds, selectedCategoryIds); 93 } else { 94 updateCounts(filteredJobs, selectedAudienceIds, selectedCategoryIds); 95 } 96 97 const resultsSpan = document.querySelector('.job-results'); 98 if (resultsSpan) { 99 resultsSpan.textContent = filteredJobs.length; 100 } 101 } else { 102 console.log('Error when processing the enquiry.'); 103 } 104 } catch (error) { 105 console.error('Error:', error); 106 } 107 }; 108} 109 110// Event-Listener für das Suchfeld 111const searchInputElement = document.getElementById('job-search-input'); 112 113if (searchInputElement) { 114 searchInputElement.addEventListener('input', async function (event) { 115 keyword = event.target.value.trim(); 116 if (keyword.length >= minKeywordLength) { 117 handleSelectionOnChange()(); 118 } else if (keyword === '') { 119 handleSelectionOnChange()(); 120 } 121 }); 122} 123 124function updateJobListView(categories) { 125 const jobListView = document.getElementById('job-list-view'); 126 127 if (!jobListView) { 128 return; 129 } 130 131 // Delete actual content 132 try { 133 jobListView.innerHTML = ''; 134 } catch (error) { 135 console.error('Failed to clear job list view:', error); 136 return; 137 } 138 139 const startIndex = (currentPage - 1) * itemsPerPage; 140 const endIndex = startIndex + itemsPerPage; 141 const jobsToDisplay = filteredJobs.slice(startIndex, endIndex); 142 143 // Generate new content based on the filtered jobs 144 jobsToDisplay.forEach(job => { 145 const jobItem = document.createElement('a'); 146 const jobCategoryElements = job.jobCategories 147 .map(categoryId => categories[categoryId]?.title || categoryId) 148 .join(', '); 149 const formattedDate = formatDate(job.jobStartDate); 150 const detailUrl = job.detailUrl; 151 152 jobItem.classList.add('job-item'); 153 jobItem.href = detailUrl; 154 jobItem.innerHTML = ` 155 <div class="job-info"> 156 <div class="fontsize-28-32 color-primary-base no-space-bottom job-info-headline">${job.externalPostingName}</div> 157 <div class="d-flex space-xs-top-10 job-list-info flex-wrap gap-10"> 158 <div class="job-postingtime space-xs-right-40 d-flex justify-content-center">
159 <i class="job-info-icon icon icon-calendar color-primary-base d-flex justify-content-center space-xs-right-10"></i> 160 <span class="job-info-text">${formattedDate}</span> 161 </div> 162 <div class="job-catogry space-xs-right-40 d-flex justify-content-center"> 163 <i class="job-info-icon icon icon-list color-primary-base d-flex justify-content-center space-xs-right-10"></i> 164 <span class="job-info-text">${jobCategoryElements}</span> 165 </div> 166 <div class="job-location d-flex justify-content-center"> 167 <i class="job-info-icon icon icon-location color-primary-base d-flex justify-content-center space-xs-right-10"></i> 168 <span class="job-info-text">${job.geo_city}</span> 169 </div> 170 </div> 171 </div> 172 173 174 <div class="job-info-arrow"><i class="icon icon-arrow-right"></i></div> 175 `; 176 jobListView.appendChild(jobItem); 177 }); 178 // Update Pagination 179 updatePagination(categories); 180} 181 182function updateCounts(jobsArray, selectedAudienceIds, selectedCategoryIds) { 183 // Initialize the counters 184 const {categoryCounts, audienceCounts} = initializeCounts(); 185 186 jobsArray.forEach(job => { 187 const matchesSelectedCategory = selectedCategoryIds.length === 0 || job.jobCategories.some(cat => selectedCategoryIds.includes(cat)); 188 const matchesSelectedAudience = selectedAudienceIds.length === 0 || job.audiences.some(aud => selectedAudienceIds.includes(aud)); 189 190 // Update job categories if target group filter is selected or empty 191 if (matchesSelectedAudience) { 192 job.jobCategories.forEach(categoryId => { 193 if (categoryCounts[categoryId] !== undefined) { 194 categoryCounts[categoryId]++; 195 } 196 }); 197 } 198 199 // Update target groups if job category filter is selected or empty 200 if (matchesSelectedCategory) { 201 job.audiences.forEach(audienceId => { 202 if (audienceCounts[audienceId] !== undefined) { 203 audienceCounts[audienceId]++; 204 } 205 }); 206 } 207 }); 208 209 // Update counts for categories and disable checkboxes if count is 0 210 Object.keys(categoryCounts).forEach(categoryId => { 211 const countElement = document.querySelector(`#${CSS.escape(categoryId)} + label .count`); 212 const checkbox = document.querySelector(`#${CSS.escape(categoryId)}`); 213 214 if (countElement) { 215 countElement.textContent = categoryCounts[categoryId]; 216 217 if (categoryCounts[categoryId] === 0) { 218 // Disable the checkbox and apply 'disabled' style if count is 0 219 checkbox.disabled = true; 220 checkbox.parentElement.classList.add('disabled'); 221 } else { 222 // Enable checkbox and remove 'disabled' style if count is greater than 0 223 checkbox.disabled = false; 224 checkbox.parentElement.classList.remove('disabled'); 225 } 226 } 227 }); 228 229 // Update counts for audiences and disable checkboxes if count is 0 230 Object.keys(audienceCounts).forEach(audienceId => { 231 const countElement = document.querySelector(`#${CSS.escape(audienceId)} + label .count`); 232 const checkbox = document.querySelector(`#${CSS.escape(audienceId)}`); 233 234 if (countElement) { 235 countElement.textContent = audienceCounts[audienceId]; 236 237 if (audienceCounts[audienceId] === 0) { 238 // Disable the checkbox and apply 'disabled' style if count is 0 239 checkbox.disabled = true; 240 checkbox.parentElement.classList.add('disabled'); 241 } else { 242 // Enable checkbox and remove 'disabled' style if count is greater than 0 243 checkbox.disabled = false; 244 checkbox.parentElement.classList.remove('disabled'); 245 } 246 } 247 }); 248} 249 250function initializeCounts() { 251 const categoryCounts = {}; 252 const audienceCounts = {}; 253 254 // Count job categories 255 const categoryCheckboxes = document.querySelectorAll('.categoryCheckbox');
256 categoryCheckboxes.forEach(checkbox => { 257 const categoryId = checkbox.value; 258 categoryCounts[categoryId] = 0; // Initialize the counter 259 }); 260 261 // Count target groups 262 const audienceCheckboxes = document.querySelectorAll('.audienceCheckbox'); 263 audienceCheckboxes.forEach(checkbox => { 264 const audienceId = checkbox.value; 265 audienceCounts[audienceId] = 0; // Initialize the counter 266 }); 267 268 return {categoryCounts, audienceCounts}; 269} 270 271function formatDate(timestamp) { 272 const date = new Date(timestamp); 273 274 const day = String(date.getDate()).padStart(2, '0'); 275 const month = String(date.getMonth() + 1).padStart(2, '0'); 276 const year = String(date.getFullYear()).slice(-2); 277 278 return `${day}.${month}.${year}`; 279} 280 281function updatePagination(categories) { 282 const paginationContainer = document.getElementById('pagination-container'); 283 284 // Ãberprüfung: Wenn keine Jobs vorhanden sind, verstecken Sie das Pagination-Element 285 if (filteredJobs.length === 0) { 286 paginationContainer.style.display = 'none'; 287 return; 288 } else { 289 paginationContainer.style.display = 'flex'; 290 } 291 292 paginationContainer.innerHTML = ''; 293 294 const totalPages = Math.ceil(filteredJobs.length / itemsPerPage); 295 296 // Prev arrow button 297 const prevButton = document.createElement('button'); 298 prevButton.classList.add('pagination-arrow', 'prev-button', 'pagination-button'); 299 prevButton.innerHTML = '<i class="icon icon-arrow-left"></i>'; 300 if (currentPage > 1) { 301 prevButton.onclick = function () { 302 currentPage--; 303 updateJobListView(categories); 304 }; 305 } else { 306 prevButton.disabled = true; 307 prevButton.classList.add('disabled'); 308 } 309 paginationContainer.appendChild(prevButton); 310 311 // Pagenumbers 312 for (let i = 1; i <= totalPages; i++) { 313 const pageButton = document.createElement('button'); 314 pageButton.textContent = i; 315 pageButton.classList.add('pagination-button'); 316 pageButton.onclick = function () { 317 currentPage = i; 318 updateJobListView(categories); 319 }; 320 321 if (i === currentPage) { 322 pageButton.classList.add('active'); 323 } 324 325 paginationContainer.appendChild(pageButton); 326 } 327 328 // Next arrow button 329 const nextButton = document.createElement('button'); 330 nextButton.classList.add('pagination-arrow', 'next-button', 'pagination-button'); 331 nextButton.innerHTML = '<i class="icon icon-arrow-right"></i>'; 332 if (currentPage < totalPages) { 333 nextButton.onclick = function () { 334 currentPage++; 335 updateJobListView(categories); 336 }; 337 } else { 338 nextButton.disabled = true; 339 nextButton.classList.add('disabled'); 340 } 341 paginationContainer.appendChild(nextButton); 342} 343 344 345document.addEventListener('DOMContentLoaded', function () { 346 const checkboxes = document.querySelectorAll('.job-filter .select-options-container input[type="checkbox"]'); 347 348 checkboxes.forEach(checkbox => { 349 checkbox.addEventListener('change', handleSelectionOnChange()); 350 }); 351 // Direct call of handleSelectionOnChange() on page request 352 handleSelectionOnChange()(); 353}); 354 355 356 357
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.