1function JCTitleSearchAG(arParams) 2{ 3 var _this = this; 4 5 if(!arParams.POPUP_HISTORY){ 6 arParams.POPUP_HISTORY = 'N'; 7 } 8 9 this.arParams = { 10 'AJAX_PAGE': arParams.AJAX_PAGE, 11 'CONTAINER_ID': arParams.CONTAINER_ID, 12 'INPUT_ID': arParams.INPUT_ID, 13 'POPUP_HISTORY': arParams.POPUP_HISTORY, 14 'POPUP_HISTORY_TITLE': arParams.POPUP_HISTORY_TITLE, 15 'PAGE': arParams.PAGE, 16 'MIN_QUERY_LEN': parseInt(arParams.MIN_QUERY_LEN) 17 }; 18 if(arParams.WAIT_IMAGE) 19 this.arParams.WAIT_IMAGE = arParams.WAIT_IMAGE; 20 21 this.elements = { 22 'clear': null, 23 'preloader': null, 24 }; 25 26 if(arParams.PRELODER_ID){ 27 this.elements.preloader = BX(arParams.PRELODER_ID); 28 } 29 if(arParams.CLEAR_ID){ 30 this.elements.clear = BX(arParams.CLEAR_ID); 31 } 32 if(arParams.VOICE_ID){ 33 this.elements.voice = BX(arParams.VOICE_ID); 34 } 35 36 if(arParams.MIN_QUERY_LEN <= 0) 37 arParams.MIN_QUERY_LEN = 1; 38 39 this.cache = []; 40 this.cache_key = null; 41 42 this.startText = ''; 43 this.running = false; 44 45 this.currentRow = -1; 46 this.RESULT = null; 47 this.CONTAINER = null; 48 this.INPUT = null; 49 this.WAIT = null; 50 51 this.ShowResult = function(result) 52 { 53 if(BX.type.isString(result)) 54 { 55 _this.RESULT.innerHTML = result; 56 } 57 58 _this.RESULT.style.display = _this.RESULT.innerHTML !== '' ? 'block' : 'none'; 59 var pos = _this.adjustResultNode(); 60 61 //adjust left column to be an outline 62 var res_pos; 63 var th; 64 var tbl = BX.findChild(_this.RESULT, {'tag':'table','class':'title-search-result'}, true); 65 if(tbl) 66 { 67 th = BX.findChild(tbl, {'tag':'th'}, true); 68 } 69 70 if(th) 71 { 72 var tbl_pos = BX.pos(tbl); 73 tbl_pos.width = tbl_pos.right - tbl_pos.left; 74 75 var th_pos = BX.pos(th); 76 th_pos.width = th_pos.right - th_pos.left; 77 th.style.width = th_pos.width + 'px'; 78 79 _this.RESULT.style.width = (pos.width + th_pos.width) + 'px'; 80 81 //Move table to left by width of the first column 82 _this.RESULT.style.left = (pos.left - th_pos.width - 1)+ 'px'; 83 84 //Shrink table when it's too wide 85 if((tbl_pos.width - th_pos.width) > pos.width) 86 _this.RESULT.style.width = (pos.width + th_pos.width -1) + 'px'; 87 88 //Check if table is too wide and shrink result div to it's width 89 tbl_pos = BX.pos(tbl); 90 res_pos = BX.pos(_this.RESULT); 91 if(res_pos.right > tbl_pos.right) 92 { 93 _this.RESULT.style.width = (tbl_pos.right - tbl_pos.left) + 'px'; 94 } 95 } 96 97 var fade; 98 if(tbl) fade = BX.findChild(_this.RESULT, {'class':'title-search-fader'}, true); 99 if(fade && th) 100 { 101 res_pos = BX.pos(_this.RESULT); 102 fade.style.left = (res_pos.right - res_pos.left - 18) + 'px'; 103 fade.style.width = 18 + 'px'; 104 fade.style.top = 0 + 'px'; 105 fade.style.height = (res_pos.bottom - res_pos.top) + 'px'; 106 fade.style.display = 'block'; 107 } 108 }; 109 110 this.onKeyPress = function(keyCode) 111 { 112 var tbl = BX.findChild(_this.RESULT, {'tag':'table','class':'title-search-result'}, true); 113 if(!tbl) 114 return false; 115 116 var i; 117 var cnt = tbl.rows.length; 118 119 switch (keyCode) 120 { 121 case 27: // escape key - close search div 122 _this.RESULT.style.display = 'none'; 123 _this.currentRow = -1; 124 _this.UnSelectAll(); 125 return true; 126 127 case 40: // down key - navigate down on search results 128 if(_this.RESULT.style.display == 'none') 129 _this.RESULT.style.display = 'block'; 130 131 var first = -1; 132 for(i = 0; i < cnt; i++) 133 { 134 if(!BX.findChild(tbl.rows[i], {'class':'title-search-separator'}, true)) 135 { 136 if(first == -1) 137 first = i; 138 139 if(_this.currentRow < i) 140 { 141 _this.currentRow = i; 142 break; 143 } 144 else if(tbl.rows[i].className == 'title-search-selected') 145 { 146 tbl.rows[i].className = ''; 147 } 148 } 149 } 150 151 if(i == cnt && _this.currentRow != i) 152 _this.currentRow = first; 153 154 tbl.rows[_this.currentRow].className = 'title-search-selected'; 155 return true; 156 157 case 38: // up key - navigate up on search results 158 if(_this.RESULT.style.display == 'none') 159 _this.RESULT.style.display = 'block'; 160 161 var last = -1; 162 for(i = cnt-1; i >= 0; i--) 163 { 164 if(!BX.findChild(tbl.rows[i], {'class':'title-search-separator'}, true)) 165 { 166 if(last == -1) 167 last = i; 168 169 if(_this.currentRow > i) 170 { 171 _this.currentRow = i; 172 break; 173 } 174 else if(tbl.rows[i].className == 'title-search-selected') 175 { 176 tbl.rows[i].className = ''; 177 } 178 } 179 } 180 181 if(i < 0 && _this.currentRow != i) 182 _this.currentRow = last; 183 184 tbl.rows[_this.currentRow].className = 'title-search-selected'; 185 return true; 186 187 case 13: // enter key - choose current search result 188 if(_this.RESULT.style.display == 'block') 189 { 190 for(i = 0; i < cnt; i++) 191 { 192 if(_this.currentRow == i) 193 { 194 if(!BX.findChild(tbl.rows[i], {'class':'title-search-separator'}, true)) 195 { 196 var a = BX.findChild(tbl.rows[i], {'tag':'a'}, true); 197 if(a) 198 { 199 window.location = a.href; 200 return true; 201 } 202 } 203 } 204 } 205 } 206 return false;
207 } 208 209 return false; 210 }; 211 212 this.onTimeout = function() 213 { 214 _this.onChange(function(){ 215 setTimeout(_this.onTimeout, 500); 216 }); 217 }; 218 219 this.onChange = function(callback) 220 { 221 if (_this.running) 222 return; 223 224 _this.checkButtonsVisible(); 225 226 _this.running = true; 227 228 if(_this.INPUT.value != _this.oldValue && _this.INPUT.value != _this.startText) 229 { 230 _this.oldValue = _this.INPUT.value; 231 if(_this.INPUT.value.length >= _this.arParams.MIN_QUERY_LEN) 232 { 233 _this.cache_key = _this.arParams.INPUT_ID + '|' + _this.INPUT.value; 234 if(_this.cache[_this.cache_key] == null) 235 { 236 if(_this.WAIT) 237 { 238 var pos = BX.pos(_this.INPUT); 239 var height = (pos.bottom - pos.top)-2; 240 _this.WAIT.style.top = (pos.top+1) + 'px'; 241 _this.WAIT.style.height = height + 'px'; 242 _this.WAIT.style.width = height + 'px'; 243 _this.WAIT.style.left = (pos.right - height + 2) + 'px'; 244 _this.WAIT.style.display = 'block'; 245 } 246 247 if(_this.elements.preloader){ 248 BX.show(_this.elements.preloader); 249 } 250 251 // console.log('ajax call ' + _this.INPUT.value); 252 253 BX.ajax.post( 254 _this.arParams.AJAX_PAGE, 255 { 256 'ajax_call':'y', 257 'INPUT_ID':_this.arParams.INPUT_ID, 258 'q':_this.INPUT.value, 259 'l':_this.arParams.MIN_QUERY_LEN 260 }, 261 function(result) 262 { 263 _this.cache[_this.cache_key] = result; 264 _this.ShowResult(result); 265 _this.currentRow = -1; 266 _this.EnableMouseEvents(); 267 if(_this.WAIT) 268 _this.WAIT.style.display = 'none'; 269 270 if(_this.elements.preloader){ 271 BX.hide(_this.elements.preloader); 272 } 273 274 if (!!callback) 275 callback(); 276 _this.running = false; 277 278 if(_this.INPUT.value != _this.oldValue) 279 { 280 _this.onChange(); 281 } 282 } 283 ); 284 return; 285 } 286 else 287 { 288 _this.ShowResult(_this.cache[_this.cache_key]); 289 _this.currentRow = -1; 290 _this.EnableMouseEvents(); 291 } 292 } 293 else 294 { 295 _this.RESULT.style.display = 'none'; 296 _this.currentRow = -1; 297 _this.UnSelectAll(); 298 } 299 } 300 if (!!callback) 301 callback(); 302 _this.running = false; 303 }; 304 305 this.onScroll = function () 306 { 307 if(BX.type.isElementNode(_this.RESULT) 308 && _this.RESULT.style.display !== "none" 309 && _this.RESULT.innerHTML !== '' 310 ) 311 { 312 _this.adjustResultNode(); 313 } 314 }; 315 316 this.UnSelectAll = function() 317 { 318 var tbl = BX.findChild(_this.RESULT, {'tag':'table','class':'title-search-result'}, true); 319 if(tbl) 320 { 321 var cnt = tbl.rows.length; 322 for(var i = 0; i < cnt; i++) 323 tbl.rows[i].className = ''; 324 } 325 }; 326 327 this.EnableMouseEvents = function() 328 { 329 var tbl = BX.findChild(_this.RESULT, {'tag':'table','class':'title-search-result'}, true); 330 if(tbl) 331 { 332 var cnt = tbl.rows.length; 333 for(var i = 0; i < cnt; i++) 334 if(!BX.findChild(tbl.rows[i], {'class':'title-search-separator'}, true)) 335 { 336 tbl.rows[i].id = 'row_' + i; 337 tbl.rows[i].onmouseover = function (e) { 338 if(_this.currentRow != this.id.substr(4)) 339 { 340 _this.UnSelectAll(); 341 this.className = 'title-search-selected'; 342 _this.currentRow = this.id.substr(4); 343 } 344 }; 345 tbl.rows[i].onmouseout = function (e) { 346 this.className = ''; 347 _this.currentRow = -1; 348 }; 349 } 350 } 351 }; 352 353 this.onFocusLost = function(hide) 354 { 355 setTimeout(function(){_this.RESULT.style.display = 'none';}, 250); 356 }; 357 358 this.onFocusGain = function() 359 { 360 if(_this.RESULT.innerHTML.length && _this.INPUT.value.length >= _this.arParams.MIN_QUERY_LEN) 361 _this.ShowResult(); 362 else if(_this.arParams.POPUP_HISTORY == 'Y'){ 363 _this.ShowResult(_this.getHistoryHtml()); 364 } 365 }; 366 367 this.onKeyDown = function(e) 368 { 369 if(!e) 370 e = window.event; 371 372 if (_this.RESULT.style.display == 'block') 373 { 374 if(_this.onKeyPress(e.keyCode)) 375 return BX.PreventDefault(e); 376 } 377 }; 378 379 this.adjustResultNode = function() 380 { 381 if(!(BX.type.isElementNode(_this.RESULT) 382 && BX.type.isElementNode(_this.CONTAINER)) 383 ) 384 { 385 return { top: 0, right: 0, bottom: 0, left: 0, width: 0, height: 0 }; 386 } 387 388 var pos = BX.pos(_this.CONTAINER); 389 390 _this.RESULT.style.position = 'absolute'; 391 _this.RESULT.style.top = (pos.bottom + 2) + 'px'; 392 _this.RESULT.style.left = pos.left + 'px'; 393 _this.RESULT.style.width = pos.width + 'px'; 394 395 return pos; 396 }; 397 398 this._onContainerLayoutChange = function() 399 { 400 if(BX.type.isElementNode(_this.RESULT) 401 && _this.RESULT.style.display !== "none" 402 && _this.RESULT.innerHTML !== '' 403 ) 404 { 405 _this.adjustResultNode(); 406 } 407 }; 408 409 // voice input 410 this.initVoiceInput = function(){ 411 if(_this.elements.voice){ 412 window.SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition; 413 if (window.SpeechRecognition) { 414 _this.elements.voice.classList.add('voice-show'); 415 416 _this.voiceRecorderActive = 0; 417 418 _this.voiceRecorder = new SpeechRecognition(); 419 _this.voiceRecorder.interimResults = true; 420 _this.voiceRecorder.lang = 'ru-RU'; 421 422 _this.voiceRecorder.addEventListener("start", function(){ 423 _this.voiceRecorderActive = 1; 424 _this.elements.voice.classList.add('active'); 425 }); 426 427 _this.voiceRecorder.addEventListener("end", function(){ 428 _this.voiceRecorderActive = 0; 429 _this.elements.voice.classList.remove('active'); 430 }); 431 432 _this.voiceRecorder.addEventListener("result", function(e){ 433 _this.INPUT.value = e.results[0][0].transcript; 434 if(e.results[0].isFinal){ 435 _this.onChange(); 436 } 437 }); 438 439 _this.voiceRecorder.addEventListener("error", function(e){ 440 _this.voiceRecorderActive = 0; 441 _this.elements.voice.classList.remove('active'); 442 443 // e.error == 'no-speech' 444 }); 445 446 _this.elements.voice.addEventListener('click', function(){ 447 if(!_this.voiceRecorderActive){ 448 _this.voiceRecorder.start(); 449 }else{ 450 _this.voiceRecorder.stop(); 451 } 452 }); 453 } 454 } 455 }; 456 457 // clear 458 this.initClear = function(){ 459 if(this.elements.clear){ 460 this.elements.clear.addEventListener('click', function(){ 461 _this.INPUT.value = ''; 462 _this.onChange(); 463 }); 464 } 465 }; 466 this.checkButtonsVisible = function(){ 467 if(_this.elements.clear){ 468 if(_this.INPUT.value){ 469 _this.elements.clear.style.display = 'block'; 470 }else{ 471 _this.elements.clear.style.display = 'none'; 472 } 473 } 474 475 if(_this.elements.voice && window.SpeechRecognition){ 476 if(_this.INPUT.value){ 477 _this.elements.voice.style.display = 'none'; 478 }else{ 479 _this.elements.voice.style.display = 'block'; 480 } 481 } 482 }; 483 484 // history 485 this.getCookie = function(name) { 486 const value = `; ${document.cookie}`; 487 const parts = value.split(`; ${name}=`); 488 if (parts.length === 2) return parts.pop().split(';').shift(); 489 }; 490 491 this.getHistoryHtml = function(){ 492 var html = '', history = _this.getCookie('BITRIX_SM_AG_SMSE_H'); 493 494 if(history){ 495 history = decodeURI(history).replace('+', ' '); 496 497 var arHistory = history.split('|'); 498 if(arHistory.length){ 499 html = html + '<div class="bx_smart_searche bx_searche"><div class="bx-searchtitle-popup-history">'; 500 html = html + '<div class="bx-searchtitle-popup-history-title">'+_this.arParams.POPUP_HISTORY_TITLE+'</div>';
501 arHistory.reverse().forEach(function(item){ 502 item = decodeURIComponent(item); 503 504 html = html + '<div class="bx-searchtitle-popup-history-item"><a class="js_search_href" href="'+_this.arParams.PAGE+'?q='+item+'">'+item+'</a></div>'; 505 }); 506 html = html + '</div></div>'; 507 } 508 } 509 510 return html; 511 }; 512 513 // init 514 this.Init = function() 515 { 516 this.CONTAINER = document.getElementById(this.arParams.CONTAINER_ID); 517 BX.addCustomEvent(this.CONTAINER, "OnNodeLayoutChange", this._onContainerLayoutChange); 518 519 this.RESULT = document.body.appendChild(document.createElement("DIV")); 520 this.RESULT.className = 'title-search-result'; 521 522 this.INPUT = document.getElementById(this.arParams.INPUT_ID); 523 BX.bind(this.INPUT, 'focus', function() {_this.onFocusGain()}); 524 BX.bind(this.INPUT, 'blur', function(e) { 525 if(!!e.relatedTarget){ 526 if(!BX.hasClass(BX(e.relatedTarget), 'js_search_href')){ 527 _this.onFocusLost(); 528 } 529 }else{ 530 _this.onFocusLost(); 531 } 532 }); 533 this.INPUT.onkeydown = this.onKeyDown; 534 535 this.startText = this.oldValue = this.INPUT.value; 536 537 if(this.arParams.WAIT_IMAGE) 538 { 539 this.WAIT = document.body.appendChild(document.createElement("DIV")); 540 this.WAIT.style.backgroundImage = "url('" + this.arParams.WAIT_IMAGE + "')"; 541 if(!BX.browser.IsIE()) 542 this.WAIT.style.backgroundRepeat = 'none'; 543 this.WAIT.style.display = 'none'; 544 this.WAIT.style.position = 'absolute'; 545 this.WAIT.style.zIndex = '1100'; 546 } 547 548 BX.bind(this.INPUT, 'bxchange', function() {_this.onChange()}); 549 BX.bind(this.INPUT, 'paste', function(e) {setTimeout(function(){_this.onChange();}, 200);}); 550 551 this.initClear(); 552 this.initVoiceInput(); 553 554 /* var fixedParent = BX.findParent(this.CONTAINER, BX.is_fixed); 555 if(BX.type.isElementNode(fixedParent)){ 556 BX.bind(window, 'scroll', BX.throttle(this.onScroll, 100, this)); 557 } */ 558 559 BX.bind(window, 'scroll', BX.throttle(this.onScroll, 100, this)); 560 BX.bind(window, 'resize', BX.throttle(this.onScroll, 100, this)); 561 }; 562 BX.ready(function (){_this.Init(arParams)}); 563}
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.