1const currentHost = window.location.hostname.toLowerCase(); 2const currentPort = window.location.port; 3const isNlHost = currentHost === 'footballcritic.nl' || currentHost === 'www.footballcritic.nl' || currentPort === '8001'; 4 5function normalizeFcUrl(url) { 6 if (!url) return url; 7 8 url = url.replace('https://www.footballcritic.com/nl', 'https://www.footballcritic.nl'); 9 url = url.replace('https://footballcritic.com/nl', 'https://www.footballcritic.nl'); 10 11 if (currentHost === 'localhost' || currentHost === '127.0.0.1') { 12 const targetPort = isNlHost ? '8001' : '8000'; 13 url = url.replace(/https?:\/\/(www\.)?footballcritic\.(com|nl)/g, window.location.protocol + '//' + currentHost + ':' + targetPort); 14 return url; 15 } 16 17 if (isNlHost) { 18 url = url.replace('https://www.footballcritic.com', 'https://www.footballcritic.nl'); 19 url = url.replace('https://footballcritic.com', 'https://www.footballcritic.nl'); 20 } else { 21 url = url.replace('https://www.footballcritic.nl', 'https://www.footballcritic.com'); 22 url = url.replace('https://footballcritic.nl', 'https://www.footballcritic.com'); 23 } 24 25 return url; 26} 27 28// SEARCH - VISUAL INTERACTIONS 29$('#aa-search-input').focusin(function() { 30 $('#mobsearchVisual').show(); 31 $(this).addClass('bigger'); 32}); 33 34$('#mobsearchVisual .closeSub').click(function() { 35 $('#mobsearchVisual').hide(); 36}); 37 38$('#aa-search-input').on('input', function() { 39 var strL = $(this).val(); 40 if (strL.length > 0) { 41 $('#mobsearchVisual').hide(); 42 } 43}); 44 45$(document).mouseup(function(e) { 46 var containerVisSearch = $("#mobsearchVisual, #aa-search-input, .add-nav"); 47 if (!containerVisSearch.is(e.target) && containerVisSearch.has(e.target).length === 0) { 48 $("#mobsearchVisual").hide(); 49 $('#aa-search-input').removeClass('bigger'); 50 $(".add-nav").removeClass('active'); 51 $(".hasSubmenu").removeClass('on'); 52 } 53}); 54 55$('#aa-search-input, #bb-search-input').keyup(function(e) { 56 if (e.keyCode == 13) { 57 window.location = "/search?q=" + encodeURIComponent($(this).val()); 58 } 59}); 60 61$('#homeSearch').click(function() { 62 window.location = "/search?q=" + encodeURIComponent($("#bb-search-input").val()); 63}); 64 65function foreSearch() { 66 if ($('#homeSearch').length) { 67 $('#homeSearch').click(); 68 } else { 69 window.location = "/search?q=" + encodeURIComponent($("#aa-search-input").val()); 70 } 71} 72 73// TYPESENSE SEARCH CLIENT & SOURCE ADAPTER 74const TYPESENSE_HOST = 't63phscirf75198op-1.a1.typesense.net'; 75const TYPESENSE_SEARCH_KEY = 'ft6uQPuwlxXfg9y4oWMeHG4fr2cID8dm'; 76 77function typesenseSource(collection, queryBy, perPage) { 78 return function(query, callback) { 79 if (!query || query.trim().length === 0) { 80 callback([]); 81 return; 82 } 83 84 const url = 'https://' + TYPESENSE_HOST + '/collections/' + collection + '/documents/search?' + 85 'q=' + encodeURIComponent(query) + 86 '&query_by=' + encodeURIComponent(queryBy) + 87 '&per_page=' + perPage + 88 '&x-typesense-api-key=' + TYPESENSE_SEARCH_KEY; 89 90 fetch(url) 91 .then(function(res) { return res.json(); }) 92 .then(function(data) { 93 const hits = (data.hits || []).map(function(h) { 94 const doc = h.document || {}; 95 doc._highlightResult = { 96 name: { 97 value: (h.highlight && h.highlight.name && h.highlight.name.snippet) 98 ? h.highlight.name.snippet 99 : (doc.name || '') 100 } 101 }; 102 if (doc.team_name) { 103 doc._highlightResult.team_name = { 104 value: (h.highlight && h.highlight.team_name && h.highlight.team_name.snippet) 105 ? h.highlight.team_name.snippet 106 : doc.team_name 107 }; 108 } 109 return doc; 110 }); 111 112 callback(hits, { hits: hits, nbHits: data.found || 0 }); 113 }) 114 .catch(function(err) { 115 console.error('Typesense search error:', err); 116 callback([]); 117 }); 118 }; 119} 120 121// AUTOCOMPLETE INITIALIZATION 122$('#aa-search-input, #bb-search-input').autocomplete({ hint: false }, [ 123 // 1. TEAMS DATASET 124 { 125 source: typesenseSource('fc_teams', 'name,full_name', 6), 126 displayKey: 'title, description, link', 127 templates: { 128 header: function(data, response) { 129 var totalTmp = response ? response.nbHits : 0; 130 if (totalTmp > 99) totalTmp = "99+"; 131 var label = isNlHost ? 'Clubs (' + totalTmp + ')' : 'Teams (' + totalTmp + ')'; 132 var btnText = isNlHost ? 'Bekijk alles' : 'View all'; 133 return '<div class="aa-search-head"><span>' + label + '</span> <a onclick="foreSearch()" class="btn small rightside">' + btnText + '</a></div>'; 134 }, 135 suggestion: function(data) {
136 var plPic = (data.logo && data.logo !== "") ? data.logo : ("https://www.sportsbase.io/images/clubs/" + data.team_id + ".png"); 137 if (data.ranking == "0") { 138 data.ranking = ""; 139 data.ranking_class = ""; 140 } 141 142 if (isNlHost) { 143 data.team_url = normalizeFcUrl(data.team_url); 144 } 145 146 var highlightVal = (data._highlightResult && data._highlightResult.name) ? data._highlightResult.name.value : data.name; 147 var subVal = data.area_name ? data.area_name : ''; 148 var rankingBadge = ''; 149 if (data.ranking > 0) { 150 rankingBadge = '<span class="aa-badge ' + (data.ranking_class || '') + '"' + (data.ranking_color ? ' style="background-color:' + data.ranking_color + ' !important;"' : '') + '>' + data.ranking + '</span>'; 151 } 152 153 return '<div class="aa-item-row">' + 154 '<div class="aa-photo team"><img src="' + plPic + '" onerror="this.onerror=null;this.src=\'https://www.footballcritic.com/images/no_team.png\';" /></div>' + 155 '<div class="aa-info">' + 156 '<span class="aa-name">' + highlightVal + '</span>' + 157 (subVal ? '<span class="aa-sub">' + subVal + '</span>' : '') + 158 '</div>' + 159 rankingBadge + 160 '</div>'; 161 } 162 } 163 }, 164 165 // 2. COMPETITIONS DATASET 166 { 167 source: typesenseSource('fc_competitions', 'name', 6), 168 displayKey: 'title, description, link', 169 templates: { 170 header: function(data, response) { 171 var totalTmp = response ? response.nbHits : 0; 172 if (totalTmp > 99) totalTmp = "99+"; 173 var label = isNlHost ? 'Competities (' + totalTmp + ')' : 'Competitions (' + totalTmp + ')'; 174 var btnText = isNlHost ? 'Bekijk alles' : 'View all'; 175 return '<div class="aa-search-head"><span>' + label + '</span> <a onclick="foreSearch()" class="btn small rightside">' + btnText + '</a></div>'; 176 }, 177 suggestion: function(data) { 178 var cCode = (data.code || '').toLowerCase(); 179 if (isNlHost) { 180 data.seo_url = normalizeFcUrl(data.seo_url); 181 } 182 183 var highlightVal = (data._highlightResult && data._highlightResult.name) ? data._highlightResult.name.value : data.name; 184 var subVal = data.area_name ? data.area_name : ''; 185 186 return '<div class="aa-item-row">' + 187 '<div class="aa-photo comp"><i class="flag flag-' + cCode + '"></i></div>' + 188 '<div class="aa-info">' + 189 '<span class="aa-name">' + highlightVal + '</span>' + 190 (subVal ? '<span class="aa-sub">' + subVal + '</span>' : '') + 191 '</div>' + 192 '</div>'; 193 } 194 } 195 }, 196 197 // 3. PLAYERS DATASET 198 { 199 source: typesenseSource('fc_players', 'name,team_name', 8), 200 displayKey: 'title, description, link', 201 templates: { 202 header: function(data, response) { 203 var totalTmp = response ? response.nbHits : 0; 204 if (totalTmp > 99) totalTmp = "99+"; 205 var label = isNlHost ? 'Spelers (' + totalTmp + ')' : 'Players (' + totalTmp + ')'; 206 var btnText = isNlHost ? 'Bekijk alles' : 'View all'; 207 return '<div class="aa-search-head"><span>' + label + '</span> <a onclick="foreSearch()" class="btn small rightside">' + btnText + '</a></div>'; 208 }, 209 suggestion: function(data) { 210 var plPic = (data.picture && data.picture !== "") ? data.picture : "https://www.footballcritic.com/images/no_player4.png"; 211 212 if (isNlHost) { 213 data.people_url = normalizeFcUrl(data.people_url); 214 } 215 216 var playerName = (data._highlightResult && data._highlightResult.name) ? data._highlightResult.name.value : data.name; 217 var teamVal = (data._highlightResult && data._highlightResult.team_name) ? data._highlightResult.team_name.value : (data.team_name || ''); 218 219 var rankingBadge = ''; 220 if (data.ranking && data.ranking > 0) { 221 rankingBadge = '<span class="aa-badge ' + (data.ranking_class || '') + '"' + (data.ranking_color ? ' style="background-color:' + data.ranking_color + ' !important;"' : '') + '>' + data.ranking + '</span>'; 222 } else { 223 rankingBadge = '<span class="aa-badge na">-</span>'; 224 } 225 226 return '<div class="aa-item-row">' + 227 '<div class="aa-photo player"><img src="' + plPic + '" onerror="this.onerror=null;this.src=\'https://www.footballcritic.com/images/no_player4.png\';" /></div>' + 228 '<div class="aa-info">' + 229 '<span class="aa-name">' + playerName + '</span>' + 230 (teamVal ? '<span class="aa-sub">(' + teamVal + ')</span>' : '') + 231 '</div>' + 232 rankingBadge + 233 '</div>'; 234 } 235 } 236 } 237]).on("autocomplete:selected", function(event, suggestion, dataset) { 238 if ((dataset == 1) || (dataset == 5) || (dataset == 9)) { 239 location.href = suggestion.team_url; 240 } 241 if ((dataset == 2) || (dataset == 6) || (dataset == 10)) { 242 location.href = suggestion.seo_url; 243 } 244 if ((dataset == 3) || (dataset == 7) || (dataset == 11)) { 245 location.href = suggestion.people_url; 246 } 247});
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.