1(function () { 2 'use strict'; 3 4 // Ãberprüfung ob jQuery verfügbar ist 5 if (typeof jQuery === 'undefined') { 6 console.warn('affiliate-toolkit-search: jQuery is not loaded'); 7 return; 8 } 9 10 var $j = jQuery.noConflict(); 11 12 // Utility-Funktionen 13 var Utils = { 14 isValidString: function (str) { 15 return typeof str === 'string' && str.trim() !== ''; 16 }, 17 18 isValidNumber: function (num) { 19 return typeof num === 'number' && !isNaN(num) && isFinite(num); 20 }, 21 22 parseFloat: function (value, defaultValue) { 23 var parsed = parseFloat(value); 24 return this.isValidNumber(parsed) ? parsed : (defaultValue || 0); 25 }, 26 27 sanitizeHtml: function (html) { 28 var div = document.createElement('div'); 29 div.textContent = html; 30 return div.innerHTML; 31 } 32 }; 33 34 // Format-Funktionen 35 function formatRepo(value) { 36 if (!value) return ''; 37 if (value.loading) return Utils.sanitizeHtml(value.text || ''); 38 if (value.id === '') return "None"; 39 40 var imageUrl = Utils.sanitizeHtml(value.imageurl || ''); 41 var title = Utils.sanitizeHtml(value.title || ''); 42 43 return '<div class="atkp-select-option"><div class="atkp-select-image"><img src="' + imageUrl + '" /></div><div class="atkp-select-title">' + title + '</div></div><div class="atkp-clearfix"></div>'; 44 } 45 46 function formatRepoSelection(repo) { 47 if (!repo) return ''; 48 49 try { 50 var placeholder = $j(repo).parent().parent().parent().attr('placeholder'); 51 } catch (e) { 52 console.warn('affiliate-toolkit-search: Error getting placeholder', e); 53 } 54 55 if (repo.id === '') return repo.text || ''; 56 return repo.text || repo.title || ''; 57 } 58 59 // Live Search Handler 60 function initLiveSearch($element) { 61 var shopid = $element.attr("shopid"); 62 var filter = $element.attr("filter"); 63 var template = $element.attr("template"); 64 var endpointurl = $element.attr('endpointurl'); 65 var elementcss = $element.attr('elementcss'); 66 var containercss = $element.attr('containercss'); 67 var limit = $element.attr('limit'); 68 var init = $element.attr('init'); 69 70 if (init === "1") return; 71 if (!Utils.isValidString(endpointurl)) { 72 console.error('affiliate-toolkit-search: No endpoint URL provided'); 73 return; 74 } 75 76 $element.addClass('atkp-spinloader'); 77 $j('.atkp-livesearch-searching').show(); 78 79 var requestData = { 80 action: 'atkp_live_search_render', 81 shopid: shopid || '', 82 filter: filter || '', 83 template: template || '', 84 elementcss: elementcss || '', 85 containercss: containercss || '', 86 limit: limit || 10 87 }; 88 89 $j.ajax({ 90 url: endpointurl, 91 type: 'POST', 92 data: requestData, 93 dataType: 'json', 94 timeout: 30000, 95 success: function (data) { 96 if (!data || typeof data !== 'object') { 97 $element.html('Invalid response format'); 98 return; 99 } 100 101 switch (data.status) { 102 case 'okay': 103 if (Utils.isValidString(data.html)) { 104 $element.html(data.html); 105 } 106 break; 107 case 'noresultfound': 108 $j('.atkp-livesearch-noresult').show(); 109 break; 110 case 'searchtermrequired': 111 $j('.atkp-livesearch-searchtermrequired').show(); 112 break; 113 case 'error': 114 var errorMsg = Utils.sanitizeHtml(data.error || 'Unknown error'); 115 var message = Utils.sanitizeHtml(data.message || ''); 116 $element.html(errorMsg + (message ? '<br />' + message : '')); 117 break; 118 default: 119 $element.html('Unknown error on loading'); 120 console.warn('affiliate-toolkit-search: Unknown status', data.status); 121 break; 122 } 123 }, 124 error: function (xhr, status, error) { 125 console.error('affiliate-toolkit-search: Request failed', status, error); 126 $element.html('Error loading content. Please try again later.'); 127 }, 128 complete: function () { 129 $element.removeClass('atkp-spinloader'); 130 $j('.atkp-livesearch-searching').hide(); 131 } 132 }); 133 } 134 135 // Select Control Initialisierung 136 function initSelectControl($element) { 137 if ($element.data('select2atkp')) return; 138 if (typeof $element.select2atkp !== 'function') { 139 console.warn('affiliate-toolkit-search: select2atkp is not available'); 140 return; 141 } 142 143 var placeholder = $element.attr('placeholder') || ''; 144 145 try { 146 $element.select2atkp({ 147 placeholder: placeholder, 148 dropdownAutoWidth: true 149 }); 150 } catch (e) { 151 console.error('affiliate-toolkit-search: Error initializing select2', e); 152 } 153 } 154 155 // Product Select Control Initialisierung 156 function initProductSelectControl($element) { 157 if ($element.data('select2atkp')) return; 158 if (typeof $element.select2atkp !== 'function') { 159 console.warn('affiliate-toolkit-search: select2atkp is not available'); 160 return; 161 } 162 163 var placeholder = $element.attr('placeholder') || ''; 164 var searchnounce = $element.attr('searchnounce') || ''; 165 var endpointurl = $element.attr('endpointurl'); 166 var inputtooshort = $element.attr('inputtooshort') || 'Please enter 3 or more characters'; 167 168 if (!Utils.isValidString(endpointurl)) { 169 console.error('affiliate-toolkit-search: No endpoint URL provided for product select'); 170 return; 171 } 172 173 try { 174 $element.select2atkp({ 175 placeholder: placeholder, 176 dropdownAutoWidth: true, 177 allowClear: true, 178 language: { 179 inputTooShort: function () { 180 return inputtooshort; 181 } 182 }, 183 ajax: { 184 type: "POST", 185 url: endpointurl, 186 dataType: 'json', 187 delay: 250, 188 timeout: 30000, 189 data: function (params) { 190 return { 191 action: "atkp_frontend_search_products", 192 type: "atkp_product", 193 request_nonce: searchnounce, 194 keyword: params.term || '' 195 }; 196 }, 197 processResults: function (data, params) { 198 if (!Array.isArray(data)) { 199 console.warn('affiliate-toolkit-search: Invalid data format'); 200 return {results: [], pagination: {more: false}}; 201 } 202 203 if (data.length > 0 && typeof data[0].error !== 'undefined') { 204 console.error('affiliate-toolkit-search:', data[0].error, data[0].message); 205 } 206 207 params.page = params.page || 1; 208 209 return { 210 results: data, 211 pagination: {more: false} 212 }; 213 }, 214 error: function (xhr, status, error) { 215 console.error('affiliate-toolkit-search: Product search failed', status, error); 216 }, 217 cache: true 218 }, 219 escapeMarkup: function (markup) { 220 return markup; 221 }, 222 minimumInputLength: 3, 223 templateResult: formatRepo, 224 templateSelection: formatRepoSelection 225 }); 226 } catch (e) { 227 console.error('affiliate-toolkit-search: Error initializing product select', e); 228 } 229 } 230 231 // Range Slider Initialisierung 232 function initRangeSlider(element) { 233 if (!element || typeof atkpnoUiSlider === 'undefined') { 234 console.warn('affiliate-toolkit-search: noUiSlider is not available'); 235 return; 236 } 237 238 var $element = $j(element); 239 var minname = $element.attr('minname'); 240 var maxname = $element.attr('maxname'); 241 242 if (!minname || !maxname) { 243 console.warn('affiliate-toolkit-search: Missing min/max name attributes'); 244 return; 245 } 246
247 var $minInput = $j('#' + minname, element); 248 var $maxInput = $j('#' + maxname, element); 249 250 if ($minInput.length === 0 || $maxInput.length === 0) { 251 console.warn('affiliate-toolkit-search: Min/max inputs not found'); 252 return; 253 } 254 255 var minpriceval = Utils.parseFloat($minInput.val()); 256 var maxpriceval = Utils.parseFloat($maxInput.val()); 257 var minprice = Utils.parseFloat($minInput.attr('defaultvalue')); 258 var maxprice = Utils.parseFloat($maxInput.attr('defaultvalue')); 259 260 minprice = Math.floor((minprice + 1) / 10) * 10; 261 maxprice = Math.ceil((maxprice + 1) / 10) * 10; 262 minpriceval = Math.floor(minpriceval / 10) * 10; 263 maxpriceval = Math.ceil(maxpriceval / 10) * 10; 264 265 try { 266 atkpnoUiSlider.create(element, { 267 start: [minpriceval, maxpriceval], 268 connect: true, 269 step: 10, 270 tooltips: false, 271 behaviour: 'tap-drag', 272 range: { 273 'min': minprice, 274 'max': maxprice 275 } 276 }); 277 278 element.atkpnoUiSlider.on('update', function (values, handle) { 279 if (!Array.isArray(values) || values.length < 2) return; 280 281 $minInput.val(values[0]); 282 $maxInput.val(values[1]); 283 284 var $minParent = $minInput.parent().parent(); 285 var $maxParent = $maxInput.parent().parent(); 286 287 $j('.minprice-display', $minParent).html(Math.trunc(values[0])); 288 $j('.maxprice-display', $maxParent).html(Math.trunc(values[1])); 289 }); 290 } catch (e) { 291 console.error('affiliate-toolkit-search: Error initializing range slider', e); 292 } 293 } 294 295 // Initialisierung 296 $j(document).ready(function () { 297 try { 298 $j(".atkp-livesearch").each(function (i, obj) { 299 initLiveSearch($j(obj)); 300 }); 301 302 $j('.atkp-selectcontrol').each(function (i, obj) { 303 initSelectControl($j(obj)); 304 }); 305 306 $j('.atkp-product-selectcontrol').each(function (i, obj) { 307 initProductSelectControl($j(obj)); 308 }); 309 310 $j('.atkp-rangeslider').each(function (i, obj) { 311 initRangeSlider(obj); 312 }); 313 } catch (e) { 314 console.error('affiliate-toolkit-search: Initialization error', e); 315 } 316 }); 317 318})();
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.