PageSourceSearch

https://iot.ru/bitrix/templates/.default/components/bitrix/search.suggest.input/.default/script.js

js iot.ru collected 2026-10-02 07:12:33 UTC 12,503 bytes, 579 lines download raw bytes

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

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.