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