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