PageSourceSearch

https://www.propellers.ru/bitrix/components/bitrix/search.suggest.…/.default/script.js?174375032412206

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