function JsSuggest(oHandler, sParams, sParser) { var t = this; t.oObj = oHandler; t.sParams = sParams; // Arrays for data if (sParser) { t.sExp = new RegExp("["+sParser+"]+", "i"); } else { t.sExp = new RegExp(","); } t.oLast = {"str":false, "arr":false}; t.oThis = {"str":false, "arr":false}; t.oEl = {"start":false, "end":false}; t.oUnfinedWords = {}; // Flags t.bReady = true; t.eFocus = true; // Array with results & it`s showing t.aDiv = null; t.oDiv = null; // Pointers t.oActive = null; t.oPointer = []; t.oPointer_default = []; t.oPointer_this = 'input_field'; t.oObj.onblur = function() { t.eFocus = false; }; t.oObj.onfocus = function() { if (!t.eFocus) { t.eFocus = true; setTimeout(function(){t.CheckModif('focus')}, 500); } }; t.oLast["arr"] = t.oObj.value.split(t.sExp); t.oLast["str"] = t.oLast["arr"].join(":"); setTimeout(function(){t.CheckModif('this')}, 500); this.CheckModif = function(__data) { var sThis = false, tmp = 0, bUnfined = false, word = "", cursor = {}; if (!t.eFocus) return; if (t.bReady && t.oObj.value.length > 0) { // Preparing input data t.oThis["arr"] = t.oObj.value.split(t.sExp); t.oThis["str"] = t.oThis["arr"].join(":"); // Getting modificated element if (t.oThis["str"] && (t.oThis["str"] != t.oLast["str"])) { cursor['position'] = TCJsUtils.getCursorPosition(t.oObj); if (cursor['position']['end'] > 0 && !t.sExp.test(t.oObj.value.substr(cursor['position']['end']-1, 1))) { cursor['arr'] = t.oObj.value.substr(0, cursor['position']['end']).split(t.sExp); sThis = t.oThis["arr"][cursor['arr'].length - 1]; t.oEl['start'] = cursor['position']['end'] - cursor['arr'][cursor['arr'].length - 1].length; t.oEl['end'] = t.oEl['start'] + sThis.length; t.oEl['content'] = sThis; t.oLast["arr"] = t.oThis["arr"]; t.oLast["str"] = t.oThis["str"]; } } if (sThis) { // Checking for UnfinedWords for (tmp = 2; tmp <= sThis.length; tmp++) { word = sThis.substr(0, tmp); if (t.oUnfinedWords[word] == '!fined') { bUnfined = true; break; } } if (!bUnfined) t.Send(sThis); } } setTimeout(function(){t.CheckModif('this')}, 500); }; t.Send = function(sSearch) { if (!sSearch) return false; var oError = []; t.bReady = false; if (BX('wait_container')) { BX('wait_container').innerHTML = BX.message('JS_CORE_LOADING'); BX.show(BX('wait_container')); } BX.ajax.post( '/bitrix/components/bitrix/search.suggest.input/search.php', {"search":sSearch, "params":t.sParams}, function(data) { var result = {}; t.bReady = true; try { eval("result = " + data + ";"); } catch(e) { oError['result_unval'] = e; } if (TCJsUtils.empty(result)) oError['result_empty'] = 'Empty result'; try { if (TCJsUtils.empty(oError) && (typeof result == 'object')) { if (!(result.length == 1 && result[0]['NAME'] == t.oEl['content'])) { t.Show(result); return; } } else { t.oUnfinedWords[t.oEl['content']] = '!fined'; } } catch(e) { oError['unknown_error'] = e; } if(BX('wait_container')) BX.hide(BX('wait_container')); } ); }; t.Show = function(result) { t.Destroy(); t.oDiv = document.body.appendChild(document.createElement("DIV")); t.oDiv.id = t.oObj.id+'_div'; t.oDiv.className = "search-popup"; t.oDiv.style.position = 'absolute'; t.aDiv = t.Print(result); var pos = TCJsUtils.GetRealPos(t.oObj); t.oDiv.style.width = parseInt(pos["width"]) + "px"; TCJsUtils.show(t.oDiv, pos["left"], pos["bottom"]); TCJsUtils.addEvent(document, "click", t.CheckMouse); TCJsUtils.addEvent(document, "keydown", t.CheckKeyword); }; t.Print = function(aArr) { var aEl = null; var aResult = {}; var iCnt = 0; var oDiv = null; var oSpan = null; var sPrefix = t.oDiv.id; for (var tmp_ in aArr) { if (aArr.hasOwnProperty(tmp_)) { // Math aEl = aArr[tmp_]; var aRes = { 'ID': (aEl['ID'] && aEl['ID'].length > 0) ? aEl['ID'] : iCnt++, 'GID': sPrefix + '_' + aRes['ID'], 'NAME': TCJsUtils.htmlspecialcharsEx(aEl['NAME']), 'CNT': aEl['CNT'] }; aResult[aRes['GID']] = aRes; t.oPointer.push(aRes['GID']); // Graph oDiv = t.oDiv.appendChild(document.createElement("DIV")); oDiv.id = aRes['GID']; oDiv.name = sPrefix + '_div'; oDiv.className = 'search-popup-row'; oDiv.onmouseover = function(){t.Init(); this.className='search-popup-row-active';}; oDiv.onmouseout = function(){t.Init(); this.className='search-popup-row';}; oDiv.onclick = function(){t.oActive = this.id}; oSpan = oDiv.appendChild(document.createElement("DIV")); oSpan.id = oDiv.id + '_NAME'; oSpan.className = "search-popup-el search-popup-el-cnt"; oSpan.innerHTML = aRes['CNT']; oSpan = oDiv.appendChild(document.createElement("DIV")); oSpan.id = oDiv.id + '_NAME'; oSpan.className = "search-popup-el search-popup-el-name"; oSpan.innerHTML = aRes['NAME']; } } t.oPointer.push('input_field'); t.oPointer_default = t.oPointer; return aResult; }; t.Destroy = function() { try { TCJsUtils.hide(t.oDiv); t.oDiv.parentNode.removeChild(t.oDiv); } catch(e) {} t.aDiv = []; t.oPointer = []; t.oPointer_default = []; t.oPointer_this = 'input_field'; t.bReady = true; t.eFocus = true; t.oActive = null; TCJsUtils.removeEvent(document, "click", t.CheckMouse); TCJsUtils.removeEvent(document, "keydown", t.CheckKeyword); }; t.Replace = function() { if (typeof t.oActive == 'string') { var tmp = t.aDiv[t.oActive]; var tmp1 = ''; if (typeof tmp == 'object') { var elEntities = document.createElement("span"); elEntities.innerHTML = tmp['NAME'].replace(/"/g, '"').replace(/&/g, '&'); tmp1 = elEntities.innerHTML; } //this preserves leading spaces var start = t.oEl['start']; while(start < t.oObj.value.length && t.oObj.value.substring(start, start+1) == " ") start++; t.oObj.value = t.oObj.value.substring(0, start) + tmp1.replace(/</g, '<').replace(/>/g, '>') + t.oObj.value.substr(t.oEl['end']); TCJsUtils.setCursorPosition(t.oObj, start + tmp1.length); } }; t.Init = function() { t.oActive = false; t.oPointer = t.oPointer_default; t.Clear(); t.oPointer_this = 'input_pointer'; }; t.Clear = function() { var oEl = t.oDiv.getElementsByTagName("div"); if (oEl.length > 0 && typeof oEl == 'object') { for (var ii in oEl) { if (oEl.hasOwnProperty(ii)) { var oE = oEl[ii]; if (oE && (typeof oE == 'object') && (oE.name == t.oDiv.id + '_div')) { oE.className = "search-popup-row"; } } } } }; t.CheckMouse = function() { t.Replace(); t.Destroy(); }; t.CheckKeyword = function(e) { if (!e) e = window.event; var oP = null; var oEl = null; if ((37 < e.keyCode && e.keyCode <41) || (e.keyCode == 13)) { t.Clear(); switch (e.keyCode) { case 38: oP = t.oPointer.pop(); if (t.oPointer_this == oP) { t.oPointer.unshift(oP); oP = t.oPointer.pop(); } if (oP != 'input_field') { t.oActive = oP; oEl = document.getElementById(oP); if (typeof oEl == 'object') { oEl.className = "search-popup-row-active"; } } t.oPointer.unshift(oP); break; case 40: oP = t.oPointer.shift(); if (t.oPointer_this == oP) { t.oPointer.push(oP); oP = t.oPointer.shift(); } if (oP != 'input_field') { t.oActive = oP; oEl = document.getElementById(oP); if (typeof oEl == 'object') { oEl.className = "search-popup-row-active"; } } t.oPointer.push(oP); break; case 39: t.Replace(); t.Destroy(); break; case 13: t.Replace(); t.Destroy(); break; } t.oPointer_this = oP; } else { t.Destroy(); } }; } var TCJsUtils = { arEvents: [], addEvent: function(el, evname, func) { if(el.attachEvent) // IE el.attachEvent("on" + evname, func); else if(el.addEventListener) // Gecko / W3C el.addEventListener(evname, func, false); else el["on" + evname] = func; this.arEvents[this.arEvents.length] = {'element': el, 'event': evname, 'fn': func}; }, removeEvent: function(el, evname, func) { if(el.detachEvent) // IE el.detachEvent("on" + evname, func); else if(el.removeEventListener) // Gecko / W3C el.removeEventListener(evname, func, false); else el["on" + evname] = null; }, getCursorPosition: function(oObj) { var result = {'start': 0, 'end': 0}; if (!oObj || (typeof oObj != 'object')) return result; try { if (document.selection != null && oObj.selectionStart == null) { oObj.focus(); var oRange = document.selection.createRange(); var oParent = oRange.parentElement(); var sBookmark = oRange.getBookmark(); var sContents = oObj.value; var sContents_ = oObj.value; var sMarker = '__' + Math.random() + '__'; while(sContents.indexOf(sMarker) != -1) { sMarker = '__' + Math.random() + '__'; } if (!oParent || oParent == null || (oParent.type != "textarea" && oParent.type != "text")) { return result; } oRange.text = sMarker + oRange.text + sMarker; sContents = oObj.value; result['start'] = sContents.indexOf(sMarker); sContents = sContents.replace(sMarker, ""); result['end'] = sContents.indexOf(sMarker); oObj.value = sContents_; oRange.moveToBookmark(sBookmark); oRange.select(); return result; } else { return { 'start': oObj.selectionStart, 'end': oObj.selectionEnd }; } } catch(e){} return result; }, setCursorPosition: function(oObj, iPosition) { if (typeof oObj != 'object') return false; oObj.focus(); try { if (document.selection != null && oObj.selectionStart == null) { var oRange = document.selection.createRange(); oRange.select(); } else { oObj.selectionStart = iPosition; oObj.selectionEnd = iPosition; } return true; } catch(e) { return false; } }, printArray: function (oObj, sParser, iLevel) { try { var result = ''; var space = ''; if (iLevel==undefined) iLevel = 0; if (!sParser) sParser = "\n"; for (var j = 0; j <= iLevel; j++) space += ' '; for (var i in oObj) { if (oObj.hasOwnProperty(i)) { if (typeof oObj[i] == 'object') result += space+i + " = {"+ sParser + TCJsUtils.printArray(oObj[i], sParser, iLevel+1) + ", " + sParser + "}" + sParser; else result += space+i + " = " + oObj[i] + "; " + sParser; } } return result; } catch(e) { } }, empty: function(oObj) { var result = true; if (oObj) { for (var i in oObj) { if (oObj.hasOwnProperty(i)) { result = false; break; } } } return result; }, show: function(oDiv, iLeft, iTop) { if (typeof oDiv != 'object') return; var zIndex = parseInt(oDiv.style.zIndex); if(zIndex <= 0 || isNaN(zIndex)) zIndex = 100; oDiv.style.zIndex = zIndex; oDiv.style.left = iLeft + "px"; oDiv.style.top = iTop + "px"; return oDiv; }, hide: function(oDiv) { if(oDiv) oDiv.style.display = 'none'; }, GetRealPos: function(el) { if(!el || !el.offsetParent) return false; var res = {}; var objParent = el.offsetParent; res["left"] = el.offsetLeft; res["top"] = el.offsetTop; while(objParent && objParent.tagName != "BODY") { res["left"] += objParent.offsetLeft; res["top"] += objParent.offsetTop; objParent = objParent.offsetParent; } res["right"]=res["left"] + el.offsetWidth; res["bottom"]=res["top"] + el.offsetHeight; res["width"]=el.offsetWidth; res["height"]=el.offsetHeight; return res; }, htmlspecialcharsEx: function(str) { return str.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;').replace(//g, '>').replace(/"/g, '"'); }, htmlspecialcharsback: function(str) { return str.replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/&/g, '&'); } };