1function JCTitleSearch(arParams) 2{ 3 var _this = this; 4 5 this.arParams = { 6 'AJAX_PAGE': BX.util.htmlspecialcharsback(arParams.AJAX_PAGE), 7 'CONTAINER_ID': arParams.CONTAINER_ID, 8 'INPUT_ID': arParams.INPUT_ID, 9 'MIN_QUERY_LEN': parseInt(arParams.MIN_QUERY_LEN, 10), 10 }; 11 12 if (arParams.WAIT_IMAGE) 13 { 14 this.arParams.WAIT_IMAGE = arParams.WAIT_IMAGE; 15 } 16 17 if (this.arParams.MIN_QUERY_LEN <= 0) 18 { 19 this.arParams.MIN_QUERY_LEN = 1; 20 } 21 22 this.cache = []; 23 this.cache_key = null; 24 25 this.startText = ''; 26 this.running = false; 27 this.runningCall = false; 28 this.currentRow = -1; 29 this.RESULT = null; 30 this.CONTAINER = null; 31 this.INPUT = null; 32 this.WAIT = null; 33 34 this.ShowResult = function(result) 35 { 36 if (BX.type.isString(result)) 37 { 38 _this.RESULT.innerHTML = result; 39 } 40 41 _this.RESULT.style.display = _this.RESULT.innerHTML === '' ? 'none' : 'block'; 42 var pos = _this.adjustResultNode(); 43 44 // adjust left column to be an outline 45 var resultPosition = null; 46 var th = null; 47 var tbl = BX.findChild(_this.RESULT, { 'tag': 'table', 'class': 'title-search-result' }, true); 48 if (tbl) 49 { 50 th = BX.findChild(tbl, { 'tag': 'th' }, true); 51 } 52 53 if (th) 54 { 55 var tablePosition = BX.pos(tbl); 56 tablePosition.width = tablePosition.right - tablePosition.left; 57 58 var tableHeaderPosition = BX.pos(th); 59 tableHeaderPosition.width = tableHeaderPosition.right - tableHeaderPosition.left; 60 th.style.width = tableHeaderPosition.width + 'px'; 61 62 _this.RESULT.style.width = (pos.width + tableHeaderPosition.width) + 'px'; 63 64 // Move table to left by width of the first column 65 _this.RESULT.style.left = (pos.left - tableHeaderPosition.width - 1) + 'px'; 66 67 // Shrink table when it's too wide 68 if ((tablePosition.width - tableHeaderPosition.width) > pos.width) 69 { 70 _this.RESULT.style.width = (pos.width + tableHeaderPosition.width - 1) + 'px'; 71 } 72 73 // Check if table is too wide and shrink result div to it's width 74 tablePosition = BX.pos(tbl); 75 resultPosition = BX.pos(_this.RESULT); 76 if (resultPosition.right > tablePosition.right) 77 { 78 _this.RESULT.style.width = (tablePosition.right - tablePosition.left) + 'px'; 79 } 80 } 81 82 var fade = false;
83 if (tbl) 84 { 85 fade = BX.findChild(_this.RESULT, { 'class': 'title-search-fader' }, true); 86 } 87 88 if (fade && th) 89 { 90 resultPosition = BX.pos(_this.RESULT); 91 fade.style.left = (resultPosition.right - resultPosition.left - 18) + 'px'; 92 fade.style.width = 18 + 'px'; 93 fade.style.top = 0 + 'px'; 94 fade.style.height = (resultPosition.bottom - resultPosition.top) + 'px'; 95 fade.style.display = 'block'; 96 } 97 }; 98 99 this.onKeyPress = function(keyCode) 100 { 101 var tbl = BX.findChild(_this.RESULT, { 'tag': 'table', 'class': 'title-search-result' }, true); 102 if (!tbl) 103 { 104 return false; 105 } 106 107 var i = 0; 108 var cnt = tbl.rows.length; 109 110 switch (keyCode) 111 { 112 case 27: // escape key - close search div 113 _this.RESULT.style.display = 'none'; 114 _this.currentRow = -1; 115 _this.UnSelectAll(); 116 117 return true; 118 case 40: // down key - navigate down on search results 119 if (_this.RESULT.style.display == 'none') 120 { 121 _this.RESULT.style.display = 'block'; 122 } 123 124 var first = -1; 125 for (i = 0; i < cnt; i++) 126 { 127 if (!BX.findChild(tbl.rows[i], { 'class': 'title-search-separator' }, true)) 128 { 129 if (first == -1) 130 { 131 first = i; 132 } 133 134 if (_this.currentRow < i) 135 { 136 _this.currentRow = i; 137 break; 138 } 139 else if (tbl.rows[i].className == 'title-search-selected') 140 { 141 tbl.rows[i].className = ''; 142 } 143 } 144 } 145 146 if (i == cnt && _this.currentRow != i) 147 { 148 _this.currentRow = first; 149 } 150 151 tbl.rows[_this.currentRow].className = 'title-search-selected'; 152 153 return true; 154 case 38: // up key - navigate up on search results 155 if (_this.RESULT.style.display == 'none') 156 { 157 _this.RESULT.style.display = 'block'; 158 } 159 160 var last = -1; 161 for (i = cnt - 1; i >= 0; i--) 162 { 163 if (!BX.findChild(tbl.rows[i], { 'class': 'title-search-separator' }, true)) 164 { 165 if (last == -1) 166 { 167 last = i; 168 } 169 170 if (_this.currentRow > i) 171 { 172 _this.currentRow = i; 173 break; 174 } 175 else if (tbl.rows[i].className == 'title-search-selected') 176 { 177 tbl.rows[i].className = ''; 178 } 179 } 180 } 181 182 if (i < 0 && _this.currentRow != i) 183 { 184 _this.currentRow = last; 185 } 186 187 tbl.rows[_this.currentRow].className = 'title-search-selected'; 188 189 return true; 190 case 13: // enter key - choose current search result 191 if (_this.RESULT.style.display == 'block') 192 { 193 for (i = 0; i < cnt; i++) 194 { 195 if ( 196 _this.currentRow == i 197 && !BX.findChild(tbl.rows[i], { 'class': 'title-search-separator' }, true) 198 ) 199 { 200 var a = BX.findChild(tbl.rows[i], { 'tag': 'a' }, true); 201 if (a) 202 { 203 window.location = a.href; 204 205 return true; 206 } 207 } 208 } 209 } 210 211 return false; 212 default: 213 break; 214 } 215 216 return false; 217 }; 218 219 this.onTimeout = function() 220 { 221 _this.onChange(function() { 222 setTimeout(_this.onTimeout, 500); 223 }); 224 }; 225 226 this.onChange = function(callback) 227 { 228 if (_this.running) 229 { 230 _this.runningCall = true; 231 232 return; 233 } 234 _this.running = true; 235 236 if (_this.INPUT.value != _this.oldValue && _this.INPUT.value != _this.startText) 237 { 238 _this.oldValue = _this.INPUT.value; 239 if (_this.INPUT.value.length >= _this.arParams.MIN_QUERY_LEN) 240 { 241 _this.cache_key = _this.arParams.INPUT_ID + '|' + _this.INPUT.value; 242 if (_this.cache[_this.cache_key] == null) 243 { 244 if (_this.WAIT) 245 { 246 var pos = BX.pos(_this.INPUT); 247 var height = (pos.bottom - pos.top) - 2; 248 _this.WAIT.style.top = (pos.top + 1) + 'px'; 249 _this.WAIT.style.height = height + 'px'; 250 _this.WAIT.style.width = height + 'px'; 251 _this.WAIT.style.left = (pos.right - height + 2) + 'px'; 252 _this.WAIT.style.display = 'block'; 253 } 254 255 BX.ajax.post( 256 _this.arParams.AJAX_PAGE, 257 { 258 'ajax_call': 'y', 259 'INPUT_ID': _this.arParams.INPUT_ID, 260 'q': _this.INPUT.value, 261 'l': _this.arParams.MIN_QUERY_LEN, 262 }, 263 function(result) 264 { 265 _this.cache[_this.cache_key] = result; 266 _this.ShowResult(result); 267 _this.currentRow = -1; 268 _this.EnableMouseEvents(); 269 if (_this.WAIT) 270 { 271 _this.WAIT.style.display = 'none'; 272 } 273 274 if (!!callback) 275 { 276 callback(); 277 } 278 279 _this.running = false;
280 if (_this.runningCall) 281 { 282 _this.runningCall = false; 283 _this.onChange(); 284 } 285 } 286 ); 287 288 return; 289 } 290 291 _this.ShowResult(_this.cache[_this.cache_key]); 292 _this.currentRow = -1; 293 _this.EnableMouseEvents(); 294 } 295 else 296 { 297 _this.RESULT.style.display = 'none'; 298 _this.currentRow = -1; 299 _this.UnSelectAll(); 300 } 301 } 302 303 if (!!callback) 304 { 305 callback(); 306 } 307 _this.running = false; 308 }; 309 310 this.onScroll = function () 311 { 312 if (BX.type.isElementNode(_this.RESULT) 313 && _this.RESULT.style.display !== 'none' 314 && _this.RESULT.innerHTML !== '' 315 ) 316 { 317 _this.adjustResultNode(); 318 } 319 }; 320 321 this.UnSelectAll = function() 322 { 323 var tbl = BX.findChild(_this.RESULT, { 'tag': 'table', 'class': 'title-search-result' }, true); 324 if (tbl) 325 { 326 var cnt = tbl.rows.length; 327 for (var i = 0; i < cnt; i++) 328 { 329 tbl.rows[i].className = ''; 330 } 331 } 332 }; 333 334 this.EnableMouseEvents = function() 335 { 336 var tbl = BX.findChild(_this.RESULT, { 'tag': 'table', 'class': 'title-search-result' }, true); 337 if (tbl) 338 { 339 var cnt = tbl.rows.length; 340 for (var i = 0; i < cnt; i++) 341 { 342 if (!BX.findChild(tbl.rows[i], { 'class': 'title-search-separator' }, true)) 343 { 344 tbl.rows[i].id = 'row_' + i; 345 tbl.rows[i].onmouseover = function (e) { 346 if (_this.currentRow != this.id.substr(4)) 347 { 348 _this.UnSelectAll(); 349 this.className = 'title-search-selected'; 350 _this.currentRow = this.id.substr(4); 351 } 352 }; 353 354 tbl.rows[i].onmouseout = function (e) { 355 this.className = ''; 356 _this.currentRow = -1; 357 }; 358 } 359 } 360 } 361 }; 362 363 this.onFocusLost = function(hide) 364 { 365 setTimeout(function() { _this.RESULT.style.display = 'none'; }, 250); 366 }; 367 368 this.onFocusGain = function() 369 { 370 if (_this.RESULT.innerHTML.length > 0) 371 { 372 _this.ShowResult(); 373 } 374 }; 375 376 this.onKeyDown = function(e) 377 { 378 if (!e) 379 { 380 e = window.event; 381 } 382 383 if (_this.RESULT.style.display == 'block' && _this.onKeyPress(e.keyCode)) 384 { 385 return BX.PreventDefault(e); 386 } 387 }; 388 389 this.adjustResultNode = function() 390 { 391 if (!(BX.type.isElementNode(_this.RESULT) 392 && BX.type.isElementNode(_this.CONTAINER)) 393 ) 394 { 395 return { top: 0, right: 0, bottom: 0, left: 0, width: 0, height: 0 }; 396 } 397 398 var pos = BX.pos(_this.CONTAINER); 399 400 _this.RESULT.style.position = 'absolute'; 401 _this.RESULT.style.top = (pos.bottom + 2) + 'px'; 402 _this.RESULT.style.left = pos.left + 'px'; 403 _this.RESULT.style.width = pos.width + 'px'; 404 405 return pos; 406 }; 407 408 this.onContainerLayoutChange = function() 409 { 410 if (BX.type.isElementNode(_this.RESULT) 411 && _this.RESULT.style.display !== 'none' 412 && _this.RESULT.innerHTML !== '' 413 ) 414 { 415 _this.adjustResultNode(); 416 } 417 }; 418 419 this.Init = function() 420 { 421 this.CONTAINER = document.getElementById(this.arParams.CONTAINER_ID); 422 BX.addCustomEvent(this.CONTAINER, 'OnNodeLayoutChange', this.onContainerLayoutChange); 423 424 this.RESULT = document.body.appendChild(document.createElement("DIV")); 425 this.RESULT.className = 'title-search-result'; 426 this.INPUT = document.getElementById(this.arParams.INPUT_ID); 427 this.startText = this.INPUT.value; 428 this.oldValue = this.INPUT.value; 429 BX.bind(this.INPUT, 'focus', function() { _this.onFocusGain(); }); 430 BX.bind(this.INPUT, 'blur', function() { _this.onFocusLost(); }); 431 this.INPUT.onkeydown = this.onKeyDown; 432 433 if (this.arParams.WAIT_IMAGE) 434 { 435 this.WAIT = document.body.appendChild(document.createElement('DIV')); 436 this.WAIT.style.backgroundImage = "url('" + this.arParams.WAIT_IMAGE + "')"; 437 if (!BX.browser.IsIE()) 438 { 439 this.WAIT.style.backgroundRepeat = 'none'; 440 } 441 this.WAIT.style.display = 'none'; 442 this.WAIT.style.position = 'absolute'; 443 this.WAIT.style.zIndex = '1100'; 444 } 445 446 BX.bind(this.INPUT, 'bxchange', function() {_this.onChange()}); 447 448 var fixedParent = BX.findParent(this.CONTAINER, BX.is_fixed); 449 if (BX.type.isElementNode(fixedParent)) 450 { 451 BX.bind(window, 'scroll', BX.throttle(this.onScroll, 100, this)); 452 } 453 }; 454 455 BX.ready(function() { _this.Init(arParams); }); 456}
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.