PageSourceSearch

https://voenchast.ru/bitrix/components/bitrix/search.tags.input/templates/.default/script.js

js voenchast.ru collected 2026-10-09 22:41:47 UTC 12,799 bytes, 640 lines download raw bytes

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;', '&amp;amp;')
622			.replaceAll('&lt;', '&amp;lt;')
623			.replaceAll('&gt;', '&amp;gt;')
624			.replaceAll('&quot;', '&amp;quot;')
625			.replaceAll('<', '&lt;')
626			.replaceAll('>', '&gt;')
627			.replaceAll('"', '&quot;')
628		;
629	},
630
631	htmlspecialcharsback: function(str)
632	{
633		return str
634			.replaceAll('&lt;', '<')
635			.replaceAll('&gt;', '>')
636			.replaceAll('&quot;;', '"')
637			.replaceAll('&amp;', '&')
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.