1jQuery(document).ready(function ($) { 2 // Adiciona os parâmetros na URL atual 3 function addParamsToCurrentUrl(params) { 4 // Obtém a URL atual 5 let currentUrl = new URL(window.location.href) 6 let searchParams = new URLSearchParams(currentUrl.search) 7 8 // Itera sobre os parâmetros e adiciona ou remove conforme necessário 9 Object.entries(params).forEach(([key, value]) => { 10 if (value !== undefined && value !== null) { 11 if (Array.isArray(value)) { 12 if (value.length > 0) { 13 // Converte arrays para strings separadas por vÃrgulas sem codificar as vÃrgulas 14 searchParams.set(key, value.join(",")) 15 } else { 16 // Remove o parâmetro se o array estiver vazio 17 searchParams.delete(key) 18 } 19 } else { 20 if (value !== "") { 21 // Define o novo valor do parâmetro 22 searchParams.set(key, value) 23 } else { 24 // Remove o parâmetro se o valor for uma string vazia 25 searchParams.delete(key) 26 } 27 } 28 } else { 29 // Remove o parâmetro se o valor for undefined ou null 30 searchParams.delete(key) 31 } 32 }) 33 34 // Converte searchParams em string, substituindo '%2C' por ',' 35 let searchString = searchParams.toString().replace(/%2C/g, ',') 36 37 // Atualiza a propriedade 'search' da URL com os novos parâmetros 38 currentUrl.search = '?' + searchString 39 40 // Atualiza a URL no navegador sem recarregar a página 41 window.history.pushState({}, "", currentUrl.toString()) 42 } 43 44 // Atribui valores do filtro furmulário com base nos query params 45 function setFormFieldsFromUrl() { 46 let urlParams = new URLSearchParams(window.location.search) 47 48 // Converte os parâmetros da URL em um objeto 49 let params = {} 50 for (let [key, value] of urlParams.entries()) { 51 params[key] = value 52 } 53 54 // Campo de busca 55 if (params.search_term) { 56 document.querySelector('input[name="search"]').value = params.search_term 57 } 58 59 // Categorias de produtos (Formato) 60 if (params.product_cats) { 61 let productCats = params.product_cats.split(',') 62 productCats.forEach(cat => { 63 let checkbox = document.querySelector(`input[type="checkbox"][name^="format-checkbox"][value="${cat}"]`) 64 if (checkbox) { 65 checkbox.checked = true 66 } 67 }) 68 } 69 70 // Tags de produtos (Temática) 71 if (params.product_tags) { 72 let productTags = params.product_tags.split(',') 73 productTags.forEach(tag => { 74 let checkbox = document.querySelector(`input[type="checkbox"][name^="thema-checkbox"][value="${tag}"]`) 75 if (checkbox) { 76 checkbox.checked = true 77 } 78 }) 79 } 80 81 // Recomendado para 82 if (params.recommendeds_for) { 83 let recommendedsFor = params.recommendeds_for.split(',') 84 recommendedsFor.forEach(rec => { 85 let checkbox = document.querySelector(`input[type="checkbox"][name^="recommended-for-checkbox"][value="${rec}"]`) 86 if (checkbox) { 87 checkbox.checked = true 88 } 89 }) 90 } 91 92 // Modalidade 93 if (params.modality) { 94 let modality = params.modality.toLowerCase() // 'all', 'online', 'presencial' 95 document.querySelectorAll('.filter-button').forEach(button => { 96 if (button.name === modality) { 97 button.classList.add('selected') 98 } else { 99 button.classList.remove('selected') 100 } 101 }) 102 } 103 104 // Cidade 105 if (params.city) { 106 let citySelect = document.querySelector('select[name="city"]'); 107 if (citySelect) { 108 citySelect.value = params.city 109 } 110 } 111 112 // Preço 113 if (params.price) { 114 let prices = params.price.split(',') 115 prices.forEach(priceValue => { 116 let checkbox = document.querySelector(`input[type="checkbox"][name^="price-"][value="${priceValue}"]`) 117 if (checkbox) { 118 checkbox.checked = true 119 } 120 }) 121 } 122 123 // Data 124 if (params.date) { 125 let dateValue = params.date 126 let radio = document.querySelector(`input[name="date"][value="${dateValue}"]`) 127 if (radio) { 128 radio.checked = true 129 } 130 if (dateValue === 'selected-data') { 131 document.getElementById("date-inputs").style.display = "grid" 132 } 133 } 134 135 // Data de inÃcio e fim 136 if (params.start_at) { 137 document.querySelector('input[name="start_at"]').value = params.start_at 138 } 139 if (params.end_at) { 140 document.querySelector('input[name="end_at"]').value = params.end_at 141 } 142 } 143 144 setFormFieldsFromUrl() 145 146 // Função de debounce 147 function debounce(func, wait, immediate) { 148 var timeout 149 return function () { 150 var context = this, 151 args = arguments 152 var later = function () { 153 timeout = null
154 if (!immediate) func.apply(context, args) 155 } 156 var callNow = immediate && !timeout 157 clearTimeout(timeout) 158 timeout = setTimeout(later, wait) 159 if (callNow) func.apply(context, args) 160 } 161 } 162 163 function getSettingsLoopWidget() { 164 // Pega os valores do settings decodificando o JSON 165 let settingsValue = $("#widget-settings").val() 166 let settings 167 try { 168 settings = JSON.parse(settingsValue) 169 } catch (e) { 170 console.error("Erro ao parsear as configurações do widget:", e) 171 const urlWithoutParams = window.location.origin + window.location.pathname 172 window.location.href = urlWithoutParams 173 return 174 } 175 return settings 176 } 177 178 $(document).on('click', '#ajax-pagination a', function (e) { 179 e.preventDefault() 180 const settings = getSettingsLoopWidget() 181 182 // Captura a URL completa do link clicado 183 const href = $(this).attr('href') 184 185 // Criar um objeto URL para extrair os parâmetros corretamente 186 const url = new URL(href, window.location.origin) // Garante que funciona mesmo com URLs relativas 187 const searchParams = new URLSearchParams(url.search) 188 189 // Pega dinamicamente o nome do parâmetro da paginação 190 const queryParamPaginationName = settings.query_param_pagination_name || 'list-page' 191 192 // Obtém o número da página corretamente 193 const page = searchParams.get(queryParamPaginationName) || 1 194 195 handleFormUpdate(e, page) 196 }) 197 198 // Add events in buttons when exists in view 199 const filterStoreForm = document.getElementById('filter-store-form') 200 const filterButtons = document.getElementById('filter-buttons') 201 const clearFilters = document.getElementById('clear-filters') 202 if (filterStoreForm) { 203 filterStoreForm.addEventListener('change', debounce(handleFormUpdate)) 204 filterStoreForm.addEventListener('input', debounce(handleFormUpdate)) 205 } 206 if (filterButtons) { 207 filterButtons.addEventListener('click', debounce(handleFormUpdate, 300, true)) 208 } 209 if (clearFilters) { 210 clearFilters.addEventListener('click', (event) => { 211 const newUrl = window.location.origin + window.location.pathname 212 window.history.replaceState({}, document.title, newUrl) 213 handleFormUpdate(event) 214 }) 215 } 216 217 async function handleFormUpdate(event, page = 1) { 218 event.preventDefault() 219 // Garantir que você está lidando com o formulário inteiro 220 const form = document.getElementById('filter-store-form') 221 // Capturar todos os valores do formulário 222 const data = Object.fromEntries(new FormData(form)) 223 224 if(data.date === 'selected-data' && !data.start_at && !data.end_at) return; 225 226 let city = data.city ? data.city : '' 227 let productCats = [] // Formato 228 let productTags = [] // Temática 229 let recommendedsFor = [] // Recomendado para 230 let price = [] // Preço 231 let date = '' 232 for (const key in data) { 233 if (Object.prototype.hasOwnProperty.call(data, key)) { 234 if(key.includes('format-checkbox')){ 235 productCats.push(data[key]) 236 continue 237 } 238 if(key.includes('thema-checkbox') ) { 239 productTags.push(data[key]) 240 continue 241 } 242 if(key.includes('recommended-for') ) { 243 recommendedsFor.push(data[key]) 244 continue 245 } 246 if(key.includes('price')) { 247 price.push(data[key]) 248 continue 249 } 250 if(key.includes('date')) { 251 if(data[key] !== 'all') 252 date = data[key] 253 continue 254 } 255 } 256 } 257 258 const urlParams = new URLSearchParams(window.location.search) 259 let modality = urlParams.get('modality') ? urlParams.get('modality') : '' 260 if(event.target.innerText) { 261 switch(event.target.innerText) { 262 case 'TODAS': 263 modality = 'ALL' 264 break 265 case 'ONLINE': 266 modality = 'ONLINE' 267 break 268 case 'PRESENCIAL': 269 modality = 'PRESENCIAL' 270 break 271 default: 272 break 273 } 274 } 275 276 let startAt = '' 277 let endAt = '' 278 if(data.start_at) 279 startAt = data.start_at 280 if(data.end_at) 281 endAt = data.end_at 282 283 let searchTerm = data.search 284 285 // Pega os valores do settings decodificando o JSON 286 const settings = getSettingsLoopWidget() 287 let select_template = settings.select_template 288 let postType = settings.post_type 289 let queryParamPaginationName = settings.query_param_pagination_name 290 let offset = settings.offset 291 let postQueryOrderby = settings.post_query_orderby 292 let postQueryOrder = settings.post_query_order 293 let columns = settings.columns 294 let rows = settings.rows 295 let postsPerPage = columns * rows 296 297 const dataPost = { 298 search_term: searchTerm, 299 product_cats: productCats, 300 product_tags: productTags, 301 recommendeds_for: recommendedsFor, 302 modality: modality, 303 city: city, 304 price: price, 305 date: date, 306 start_at: startAt, 307 end_at: endAt, 308 [queryParamPaginationName]: page === 1 ? undefined : page 309 } 310 311 // Executa a função com o objeto de parâmetros 312 addParamsToCurrentUrl(dataPost) 313 $.ajax({ 314 url: ajax_object.ajax_url, 315 type: "POST", 316 data: { 317 action: "filter_loop_grid_products", 318 current_url: window.location.href, 319 query_param_pagination_name: queryParamPaginationName, 320 post_type: postType, 321 offset: offset, 322 posts_per_page: postsPerPage, 323 post_query_orderby: postQueryOrderby, 324 post_query_order: postQueryOrder, 325 select_template, 326 ...dataPost 327 }, 328 beforeSend: function () { 329 const grid = $(".custom-loop-grid") 330 331 // Pega a altura e largura da div antes de limpar 332 var gridHeight = grid.outerHeight() 333 var gridWidth = grid.outerWidth() 334 335 // Define altura fixa para evitar que a div encolha 336 grid.css({ 337 "min-height": gridHeight + "px", 338 "display": "flex", 339 "align-items": "center", 340 "justify-content": "center", 341 "text-align": "center", 342 "position": "relative", 343 "width": gridWidth + "px" 344 }) 345 grid.html('<div class="loader-loop-item"></div>') 346 }, 347 success: function (response) { 348 if (response.success) { 349 $(".custom-loop-grid").html(response.data.content) 350 $(".custom-pagination").html(response.data.pagination) 351 } else { 352 $(".custom-loop-grid").html('<p>Nenhum resultado encontrado</p>') 353 $(".custom-pagination").html('') 354 } 355 }, 356 complete: function () { 357 // Remove o CSS extra quando o conteúdo for carregado 358 $(".custom-loop-grid").css({ 359 "min-height": "", 360 "display": "", 361 "align-items": "", 362 "justify-content": "", 363 "text-align": "", 364 "position": "", 365 "width": "" 366 }) 367 }, 368 error: function (xhr, status, error) { 369 console.error("Erro na requisição AJAX:", error) 370 console.log("Resposta recebida:", xhr.responseText) 371 }, 372 }) 373 } 374})
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.