PageSourceSearch

https://portalidea.com.br/assets/js/home-concursos.js

js portalidea.com.br collected 2026-09-24 12:22:58 UTC 4,003 bytes, 157 lines download raw bytes

1document.addEventListener('DOMContentLoaded', function() {
2  const form = document.querySelector('[data-contest-city-form]');
3  const input = form ? form.querySelector('[data-contest-city-input]') : null;
4  const cityIdInput = form ? form.querySelector('[data-contest-city-id]') : null;
5  const cityLabelInput = form ? form.querySelector('[data-contest-city-label]') : null;
6  const results = form ? form.querySelector('[data-contest-city-results]') : null;
7  const feedback = document.querySelector('[data-contest-city-feedback]');
8  const findBaseUrl = 'https://find.portalidea.top/';
9  let debounceTimer = null;
10  let activeRequest = null;
11  let selectedCity = null;
12
13  if (!form || !input || !cityIdInput || !cityLabelInput || !results || !feedback) {
14    return;
15  }
16
17  function buildCityLabel(city) {
18    return city.city + ' — ' + city.state;
19  }
20
21  function setFeedback(message) {
22    feedback.textContent = message;
23    feedback.hidden = !message;
24  }
25
26  function clearSelectedCity() {
27    selectedCity = null;
28    cityIdInput.value = '';
29    cityLabelInput.value = '';
30  }
31
32  function closeResults() {
33    results.innerHTML = '';
34    results.hidden = true;
35  }
36
37  function selectCity(city) {
38    const label = buildCityLabel(city);
39
40    selectedCity = {
41      id: city.id,
42      label: label
43    };
44
45    input.value = label;
46    cityIdInput.value = city.id;
47    cityLabelInput.value = label;
48    setFeedback('');
49    closeResults();
50  }
51
52  function renderResults(cities) {
53    results.innerHTML = '';
54
55    if (!cities.length) {
56      closeResults();
57      setFeedback('Nenhuma cidade encontrada.');
58      return;
59    }
60
61    cities.forEach(function(city) {
62      const item = document.createElement('li');
63      const button = document.createElement('button');
64      const cityName = document.createElement('strong');
65
66      button.type = 'button';
67      cityName.textContent = city.city;
68      button.appendChild(cityName);
69      button.appendChild(document.createTextNode(' — ' + city.state));
70      button.addEventListener('click', function() {
71        selectCity(city);
72      });
73
74      item.appendChild(button);
75      results.appendChild(item);
76    });
77
78    results.hidden = false;
79    setFeedback('');
80  }
81
82  function fetchCities(term) {
83    const url = new URL('/api/locations', findBaseUrl);
84
85    url.searchParams.set('q', term);
86    url.searchParams.set('limit', '8');
87
88    if (activeRequest) {
89      activeRequest.abort();
90    }
91
92    activeRequest = new AbortController();
93    setFeedback('Buscando cidades...');
94
95    fetch(url.toString(), {
96      signal: activeRequest.signal
97    })
98      .then(function(response) {
99        if (!response.ok) {
100          throw new Error('Falha ao buscar cidades.');
101        }
102
103        return response.json();
104      })
105      .then(function(data) {
106        renderResults(Array.isArray(data.results) ? data.results : []);
107      })
108      .catch(function(error) {
109        if (error.name === 'AbortError') {
110          return;
111        }
112
113        closeResults();
114        setFeedback('Não foi possível buscar as cidades agora.');
115      });
116  }
117
118  input.addEventListener('input', function() {
119    const term = input.value.trim();
120
121    clearSelectedCity();
122    clearTimeout(debounceTimer);
123
124    if (term.length < 2) {
125      closeResults();
126      setFeedback('');
127      return;
128    }
129
130    debounceTimer = setTimeout(function() {
131      fetchCities(term);
132    }, 250);
133  });
134
135  document.addEventListener('click', function(event) {
136    if (!form.contains(event.target)) {
137      closeResults();
138    }
139  });
140
141  form.addEventListener('submit', function(event) {
142    event.preventDefault();
143
144    if (!selectedCity || !selectedCity.id) {
145      setFeedback('Selecione uma cidade da lista para pesquisar.');
146      input.focus();
147      return;
148    }
149
150    const url = new URL(findBaseUrl);
151
152    url.searchParams.set('city', selectedCity.id);
153    url.searchParams.set('city_label', selectedCity.label);
154
155    window.open(url.toString(), '_blank', 'noopener');
156  });
157});

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.