1var Errors = { 2 'result_unval': 'Error in result', 3 'result_empty': 'Empty result', 4}; 5 6function JsTc(oHandler, sParams, sParser) // TC = TagCloud 7{ 8 var t = this; 9 10 t.oObj = typeof oHandler == 'object' ? oHandler : document.getElementById('TAGS'); 11 t.sParams = sParams; 12 // Arrays for data 13 if (sParser) 14 { 15 t.sExp = new RegExp('[' + sParser + ']+', 'i'); 16 } 17 else 18 { 19 t.sExp = new RegExp(','); 20 } 21 t.oLast = { 'str': false, 'arr': false }; 22 t.oThis = { 'str': false, 'arr': false }; 23 t.oEl = { 'start': false, 'end': false }; 24 t.oUnfinedWords = {}; 25 // Flags 26 t.bReady = true; 27 t.eFocus = true; 28 // Array with results & it`s showing 29 t.aDiv = null; 30 t.oDiv = null; 31 // Pointers 32 t.oActive = null; 33 t.oPointer = []; 34 t.oPointer_default = []; 35 t.oPointer_this = 'input_field'; 36 37 t.oObj.onblur = function() 38 { 39 t.eFocus = false; 40 }; 41 42 t.oObj.onfocus = function() 43 { 44 if (!t.eFocus) 45 { 46 t.eFocus = true; 47 setTimeout(function() { t.CheckModif('focus'); }, 500); 48 } 49 }; 50 51 t.oLast['arr'] = t.oObj.value.split(t.sExp); 52 t.oLast['str'] = t.oLast['arr'].join(':'); 53 54 setTimeout(function() { t.CheckModif('this'); }, 500); 55 56 this.CheckModif = function(__data) 57 { 58 var sThis = false; 59 var tmp = 0; 60 var bUnfined = false; 61 var word = ''; 62 var cursor = {}; 63 64 if (!t.eFocus) 65 { 66 return; 67 } 68 69 if (t.bReady && t.oObj.value.length > 0) 70 { 71 // Preparing input data 72 t.oThis['arr'] = t.oObj.value.split(t.sExp); 73 t.oThis['str'] = t.oThis['arr'].join(':'); 74 75 // Getting modificated element 76 if (t.oThis['str'] && (t.oThis['str'] != t.oLast['str'])) 77 { 78 cursor['position'] = TCJsUtils.getCursorPosition(t.oObj); 79 if (cursor['position']['end'] > 0 && !t.sExp.test(t.oObj.value.substr(cursor['position']['end'] - 1, 1))) 80 { 81 cursor['arr'] = t.oObj.value.substr(0, cursor['position']['end']).split(t.sExp); 82 sThis = t.oThis['arr'][cursor['arr'].length - 1]; 83 84 t.oEl['start'] = cursor['position']['end'] - cursor['arr'][cursor['arr'].length - 1].length; 85 t.oEl['end'] = t.oEl['start'] + sThis.length; 86 t.oEl['content'] = sThis; 87 88 t.oLast['arr'] = t.oThis['arr']; 89 t.oLast['str'] = t.oThis['str']; 90 } 91 } 92 93 if (sThis) 94 { 95 // Checking for UnfinedWords 96 for (tmp = 2; tmp <= sThis.length; tmp++) 97 { 98 word = sThis.substr(0, tmp); 99 if (t.oUnfinedWords[word] == '!fined') 100 { 101 bUnfined = true; 102 break; 103 } 104 } 105 106 if (!bUnfined) 107 { 108 t.Send(sThis); 109 } 110 } 111 } 112 setTimeout(function() { t.CheckModif('this'); }, 500); 113 }; 114 115 t.Send = function(sSearch) 116 { 117 if (!sSearch) 118 { 119 return; 120 } 121 122 var oError = []; 123 t.bReady = false; 124 if (BX('wait_container')) 125 { 126 BX('wait_container').innerHTML = BX.message('JS_CORE_LOADING'); 127 BX.show(BX('wait_container')); 128 } 129 BX.ajax.post( 130 '/bitrix/components/bitrix/search.tags.input/search.php', 131 { 132 'search': sSearch, 133 'params': t.sParams, 134 }, 135 function(data) 136 { 137 var result = {}; 138 t.bReady = true; 139 140 try 141 { 142 eval('result = ' + data + ';'); 143 } 144 catch (e) 145 { 146 oError['result_unval'] = e; 147 } 148 149 if (TCJsUtils.empty(result)) 150 { 151 oError['result_empty'] = Errors['result_empty']; 152 } 153 154 try 155 { 156 if (TCJsUtils.empty(oError) && (typeof result == 'object')) 157 { 158 if (!(result.length == 1 && result[0]['NAME'] == t.oEl['content'])) 159 { 160 t.Show(result); 161 162 return; 163 } 164 } 165 else 166 { 167 t.oUnfinedWords[t.oEl['content']] = '!fined'; 168 } 169 } 170 catch (e) 171 { 172 oError['unknown_error'] = e; 173 } 174 175 if (BX('wait_container')) 176 { 177 BX.hide(BX('wait_container')); 178 } 179 } 180 ); 181 }; 182 183 t.Show = function(result) 184 { 185 t.Destroy(); 186 t.oDiv = document.body.appendChild(document.createElement('DIV')); 187 t.oDiv.id = t.oObj.id + '_div'; 188 189 t.oDiv.className = 'search-popup'; 190 t.oDiv.style.position = 'absolute'; 191 192 t.aDiv = t.Print(result); 193 var pos = TCJsUtils.GetRealPos(t.oObj); 194 t.oDiv.style.width = parseInt(pos['width'], 10) + 'px'; 195 TCJsUtils.show(t.oDiv, pos['left'], pos['bottom']); 196 TCJsUtils.addEvent(document, 'click', t.CheckMouse); 197 TCJsUtils.addEvent(document, 'keydown', t.CheckKeyword); 198 }; 199 200 t.Print = function(aArr) 201 { 202 var aEl = null; 203 var aResult = []; 204 var aRes = []; 205 var iCnt = 0; 206 var oDiv = null; 207 var oSpan = null; 208 var sPrefix = t.oDiv.id; 209 210 for (var key in aArr) 211 { 212 // Math
213 if (aArr.hasOwnProperty(key)) 214 { 215 aEl = aArr[key]; 216 aRes = []; 217 aRes['ID'] = (aEl['ID'] && aEl['ID'].length > 0) ? aEl['ID'] : iCnt++; 218 aRes['GID'] = sPrefix + '_' + aRes['ID']; 219 aRes['NAME'] = TCJsUtils.htmlspecialcharsEx(aEl['NAME']); 220 aRes['~NAME'] = aEl['NAME']; 221 aRes['CNT'] = aEl['CNT']; 222 aResult[aRes['GID']] = aRes; 223 t.oPointer.push(aRes['GID']); 224 // Graph 225 oDiv = t.oDiv.appendChild(document.createElement('DIV')); 226 oDiv.id = aRes['GID']; 227 oDiv.name = sPrefix + '_div'; 228 229 oDiv.className = 'search-popup-row'; 230 231 oDiv.onmouseover = function() { 232 t.Init(); 233 this.className = 'search-popup-row-active'; 234 }; 235 236 oDiv.onmouseout = function() { 237 t.Init(); 238 this.className = 'search-popup-row'; 239 }; 240 241 oDiv.onclick = function(e) { 242 t.oActive = this.id; 243 t.Replace(); 244 t.Destroy(); 245 BX.PreventDefault(e); 246 }; 247 248 oSpan = oDiv.appendChild(document.createElement('DIV')); 249 oSpan.id = oDiv.id + '_NAME'; 250 oSpan.className = 'search-popup-el search-popup-el-cnt'; 251 oSpan.innerHTML = aRes['CNT']; 252 253 oSpan = oDiv.appendChild(document.createElement('DIV')); 254 oSpan.id = oDiv.id + '_NAME'; 255 oSpan.className = 'search-popup-el search-popup-el-name'; 256 oSpan.innerHTML = aRes['NAME']; 257 } 258 } 259 t.oPointer.push('input_field'); 260 t.oPointer_default = t.oPointer; 261 262 return aResult; 263 }; 264 265 t.Destroy = function() 266 { 267 try 268 { 269 TCJsUtils.hide(t.oDiv); 270 t.oDiv.parentNode.removeChild(t.oDiv); 271 } 272 catch 273 { 274 } 275 276 t.aDiv = []; 277 t.oPointer = []; 278 t.oPointer_default = []; 279 t.oPointer_this = 'input_field'; 280 t.bReady = true; 281 t.eFocus = true; 282 t.oActive = null; 283 284 TCJsUtils.removeEvent(document, 'click', t.CheckMouse); 285 TCJsUtils.removeEvent(document, 'keydown', t.CheckKeyword); 286 }; 287 288 t.Replace = function() 289 { 290 if (typeof t.oActive == 'string') 291 { 292 var tmp = t.aDiv[t.oActive]; 293 var tmp1 = ''; 294 if (typeof tmp == 'object') 295 { 296 var elEntities = document.createElement('textarea'); 297 elEntities.innerHTML = tmp['~NAME']; 298 tmp1 = elEntities.value; 299 } 300 // this preserves leading spaces 301 var start = t.oEl['start']; 302 while (start < t.oObj.value.length && t.oObj.value.substring(start, start + 1) == ' ') 303 { 304 start++; 305 } 306 307 t.oObj.value = t.oObj.value.substring(0, start) + tmp1 + t.oObj.value.substr(t.oEl['end']); 308 TCJsUtils.setCursorPosition(t.oObj, start + tmp1.length); 309 } 310 }; 311 312 t.Init = function() 313 { 314 t.oActive = false; 315 t.oPointer = t.oPointer_default; 316 t.Clear(); 317 t.oPointer_this = 'input_pointer'; 318 }; 319 320 t.Clear = function() 321 { 322 var oEl = t.oDiv.getElementsByTagName('div'); 323 if (oEl.length > 0 && typeof oEl == 'object') 324 { 325 for (var ii in oEl) 326 { 327 if (oEl.hasOwnProperty(ii)) 328 { 329 var oE = oEl[ii]; 330 if (oE && (typeof oE == 'object') && (oE.name == t.oDiv.id + '_div')) 331 { 332 oE.className = 'search-popup-row'; 333 } 334 } 335 } 336 } 337 }; 338 339 t.CheckMouse = function() 340 { 341 t.Replace(); 342 t.Destroy(); 343 }; 344 345 t.CheckKeyword = function(event) 346 { 347 var e = event || window.event; 348 var oP = null; 349 var oEl = null; 350 if ((e.keyCode > 37 && e.keyCode < 41) || (e.keyCode == 13)) 351 { 352 t.Clear(); 353 354 switch (e.keyCode) 355 { 356 case 38: 357 oP = t.oPointer.pop(); 358 if (t.oPointer_this == oP) 359 { 360 t.oPointer.unshift(oP); 361 oP = t.oPointer.pop(); 362 } 363 364 if (oP != 'input_field') 365 { 366 t.oActive = oP; 367 oEl = document.getElementById(oP); 368 if (typeof oEl == 'object') 369 { 370 oEl.className = 'search-popup-row-active'; 371 } 372 } 373 t.oPointer.unshift(oP); 374 break; 375 case 40: 376 oP = t.oPointer.shift(); 377 if (t.oPointer_this == oP) 378 { 379 t.oPointer.push(oP); 380 oP = t.oPointer.shift(); 381 } 382 383 if (oP != 'input_field') 384 { 385 t.oActive = oP; 386 oEl = document.getElementById(oP); 387 if (typeof oEl == 'object') 388 { 389 oEl.className = 'search-popup-row-active'; 390 } 391 } 392 t.oPointer.push(oP); 393 break; 394 case 39: 395 t.Replace(); 396 t.Destroy(); 397 break; 398 case 13: 399 t.Replace(); 400 t.Destroy(); 401 if (TCJsUtils.IsIE()) 402 { 403 e.returnValue = false;
404 e.cancelBubble = true; 405 } 406 else 407 { 408 e.preventDefault(); 409 e.stopPropagation(); 410 } 411 break; 412 default: 413 break; 414 } 415 t.oPointer_this = oP; 416 } 417 else 418 { 419 t.Destroy(); 420 } 421 } 422} 423 424var TCJsUtils = { 425 arEvents: [], 426 427 addEvent: function(el, evname, func) 428 { 429 if (el.attachEvent) 430 { // IE 431 el.attachEvent('on' + evname, func); 432 } 433 else if (el.addEventListener) 434 { // Gecko / W3C 435 el.addEventListener(evname, func, false); 436 } 437 else 438 { 439 el['on' + evname] = func; 440 } 441 this.arEvents[this.arEvents.length] = { 'element': el, 'event': evname, 'fn': func }; 442 }, 443 444 removeEvent: function(el, evname, func) 445 { 446 if (el.detachEvent) 447 { // IE 448 el.detachEvent('on' + evname, func); 449 } 450 else if (el.removeEventListener) 451 { // Gecko / W3C 452 el.removeEventListener(evname, func, false); 453 } 454 else 455 { 456 el['on' + evname] = null; 457 } 458 }, 459 460 getCursorPosition: function(oObj) 461 { 462 var result = {'start': 0, 'end': 0}; 463 if (!oObj || (typeof oObj != 'object')) 464 { 465 return result; 466 } 467 468 try 469 { 470 if (document.selection != null && oObj.selectionStart == null) 471 { 472 oObj.focus(); 473 var oRange = document.selection.createRange(); 474 var oParent = oRange.parentElement(); 475 var sBookmark = oRange.getBookmark(); 476 var sContents = oObj.value; 477 var sContentsSaved = oObj.value; 478 var sMarker = '__' + Math.random() + '__'; 479 480 while (sContents.indexOf(sMarker) != -1) 481 { 482 sMarker = '__' + Math.random() + '__'; 483 } 484 485 if (!oParent || oParent == null || (oParent.type != 'textarea' && oParent.type != 'text')) 486 { 487 return result; 488 } 489 490 oRange.text = sMarker + oRange.text + sMarker; 491 sContents = oObj.value; 492 result['start'] = sContents.indexOf(sMarker); 493 sContents = sContents.replace(sMarker, ''); 494 result['end'] = sContents.indexOf(sMarker); 495 oObj.value = sContentsSaved; 496 oRange.moveToBookmark(sBookmark); 497 oRange.select(); 498 499 return result; 500 } 501 502 return { 503 'start': oObj.selectionStart, 504 'end': oObj.selectionEnd, 505 }; 506 } 507 catch 508 { 509 return result; 510 } 511 }, 512 513 setCursorPosition: function(oObj, iPosition) 514 { 515 if (typeof oObj != 'object') 516 { 517 return false; 518 } 519 520 oObj.focus(); 521 522 try 523 { 524 if (document.selection != null && oObj.selectionStart == null) 525 { 526 var oRange = document.selection.createRange(); 527 oRange.select(); 528 } 529 else 530 { 531 oObj.selectionStart = iPosition; 532 oObj.selectionEnd = iPosition; 533 } 534 535 return true; 536 } 537 catch 538 { 539 return false; 540 } 541 }, 542 543 empty: function(oObj) 544 { 545 if (oObj) 546 { 547 for (var i in oObj) 548 { 549 if (oObj.hasOwnProperty(i)) 550 { 551 return false; 552 } 553 } 554 } 555 556 return true; 557 }, 558 559 show: function(oDiv, iLeft, iTop) 560 { 561 if (typeof oDiv != 'object') 562 { 563 return; 564 } 565 var zIndex = parseInt(oDiv.style.zIndex, 10); 566 if (zIndex <= 0 || isNaN(zIndex)) 567 { 568 zIndex = 2200; 569 } 570 oDiv.style.zIndex = zIndex; 571 oDiv.style.left = iLeft + 'px'; 572 oDiv.style.top = iTop + 'px'; 573 }, 574
575 hide: function(oDiv) 576 { 577 if (oDiv) 578 { 579 oDiv.style.display = 'none'; 580 } 581 }, 582 583 GetRealPos: function(el) 584 { 585 if (!el || !el.offsetParent) 586 { 587 return false; 588 } 589 590 var res = {}; 591 var objParent = el.offsetParent; 592 res['left'] = el.offsetLeft; 593 res['top'] = el.offsetTop; 594 while (objParent && objParent.tagName != 'BODY') 595 { 596 res['left'] += objParent.offsetLeft; 597 res['top'] += objParent.offsetTop; 598 objParent = objParent.offsetParent; 599 } 600 res['right'] = res['left'] + el.offsetWidth; 601 res['bottom'] = res['top'] + el.offsetHeight; 602 res['width'] = el.offsetWidth; 603 res['height'] = el.offsetHeight; 604 605 return res; 606 }, 607 608 IsIE: function() 609 { 610 return (document.attachEvent && !TCJsUtils.IsOpera()); 611 }, 612 613 IsOpera: function() 614 { 615 return (navigator.userAgent.toLowerCase().indexOf('opera') != -1); 616 }, 617 618 htmlspecialcharsEx: function(str) 619 { 620 return str 621 .replaceAll('&', '&amp;') 622 .replaceAll('<', '&lt;') 623 .replaceAll('>', '&gt;') 624 .replaceAll('"', '&quot;') 625 .replaceAll('<', '<') 626 .replaceAll('>', '>') 627 .replaceAll('"', '"') 628 ; 629 }, 630 631 htmlspecialcharsback: function(str) 632 { 633 return str 634 .replaceAll('<', '<') 635 .replaceAll('>', '>') 636 .replaceAll('";', '"') 637 .replaceAll('&', '&') 638 ; 639 }, 640};
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.