PageSourceSearch

https://www.marimedia.ru/bitrix/components/bitrix/search.title/script.js

js marimedia.ru collected 2026-09-24 20:47:36 UTC 10,542 bytes, 455 lines download raw bytes

1function JCTitleSearch(arParams)
2{
3	var _this = this;
4
5	this.arParams = {
6		'AJAX_PAGE': arParams.AJAX_PAGE,
7		'CONTAINER_ID': arParams.CONTAINER_ID,
8		'INPUT_ID': arParams.INPUT_ID,
9		'MIN_QUERY_LEN': parseInt(arParams.MIN_QUERY_LEN, 10),
10	};
11	if (arParams.WAIT_IMAGE)
12	{
13		this.arParams.WAIT_IMAGE = arParams.WAIT_IMAGE;
14	}
15
16	if (this.arParams.MIN_QUERY_LEN <= 0)
17	{
18		this.arParams.MIN_QUERY_LEN = 1;
19	}
20
21	this.cache = [];
22	this.cache_key = null;
23
24	this.startText = '';
25	this.running = false;
26	this.runningCall = false;
27	this.currentRow = -1;
28	this.RESULT = null;
29	this.CONTAINER = null;
30	this.INPUT = null;
31	this.WAIT = null;
32
33	this.ShowResult = function(result)
34	{
35		if (BX.type.isString(result))
36		{
37			_this.RESULT.innerHTML = result;
38		}
39
40		_this.RESULT.style.display = _this.RESULT.innerHTML === '' ? 'none' : 'block';
41		var pos = _this.adjustResultNode();
42
43		// adjust left column to be an outline
44		var resultPosition = null;
45		var th = null;
46		var tbl = BX.findChild(_this.RESULT, { 'tag': 'table', 'class': 'title-search-result' }, true);
47		if (tbl)
48		{
49			th = BX.findChild(tbl, { 'tag': 'th' }, true);
50		}
51
52		if (th)
53		{
54			var tablePosition = BX.pos(tbl);
55			tablePosition.width = tablePosition.right - tablePosition.left;
56
57			var tableHeaderPosition = BX.pos(th);
58			tableHeaderPosition.width = tableHeaderPosition.right - tableHeaderPosition.left;
59			th.style.width = tableHeaderPosition.width + 'px';
60
61			_this.RESULT.style.width = (pos.width + tableHeaderPosition.width) + 'px';
62
63			// Move table to left by width of the first column
64			_this.RESULT.style.left = (pos.left - tableHeaderPosition.width - 1) + 'px';
65
66			// Shrink table when it's too wide
67			if ((tablePosition.width - tableHeaderPosition.width) > pos.width)
68			{
69				_this.RESULT.style.width = (pos.width + tableHeaderPosition.width - 1) + 'px';
70			}
71
72			// Check if table is too wide and shrink result div to it's width
73			tablePosition = BX.pos(tbl);
74			resultPosition = BX.pos(_this.RESULT);
75			if (resultPosition.right > tablePosition.right)
76			{
77				_this.RESULT.style.width = (tablePosition.right - tablePosition.left) + 'px';
78			}
79		}
80
81		var fade = false;
82		if (tbl)
83		{
84			fade = BX.findChild(_this.RESULT, { 'class': 'title-search-fader' }, true);
85		}
86
87		if (fade && th)
88		{
89			resultPosition = BX.pos(_this.RESULT);
90			fade.style.left = (resultPosition.right - resultPosition.left - 18) + 'px';
91			fade.style.width = 18 + 'px';
92			fade.style.top = 0 + 'px';
93			fade.style.height = (resultPosition.bottom - resultPosition.top) + 'px';
94			fade.style.display = 'block';
95		}
96	};
97
98	this.onKeyPress = function(keyCode)
99	{
100		var tbl = BX.findChild(_this.RESULT, { 'tag': 'table', 'class': 'title-search-result' }, true);
101		if (!tbl)
102		{
103			return false;
104		}
105
106		var i = 0;
107		var cnt = tbl.rows.length;
108
109		switch (keyCode)
110		{
111			case 27: // escape key - close search div
112				_this.RESULT.style.display = 'none';
113				_this.currentRow = -1;
114				_this.UnSelectAll();
115
116				return true;
117			case 40: // down key - navigate down on search results
118				if (_this.RESULT.style.display == 'none')
119				{
120					_this.RESULT.style.display = 'block';
121				}
122
123				var first = -1;
124				for (i = 0; i < cnt; i++)
125				{
126					if (!BX.findChild(tbl.rows[i], { 'class': 'title-search-separator' }, true))
127					{
128						if (first == -1)
129						{
130							first = i;
131						}
132
133						if (_this.currentRow < i)
134						{
135							_this.currentRow = i;
136							break;
137						}
138						else if (tbl.rows[i].className == 'title-search-selected')
139						{
140							tbl.rows[i].className = '';
141						}
142					}
143				}
144
145				if (i == cnt && _this.currentRow != i)
146				{
147					_this.currentRow = first;
148				}
149
150				tbl.rows[_this.currentRow].className = 'title-search-selected';
151
152				return true;
153			case 38: // up key - navigate up on search results
154				if (_this.RESULT.style.display == 'none')
155				{
156					_this.RESULT.style.display = 'block';
157				}
158
159				var last = -1;
160				for (i = cnt - 1; i >= 0; i--)
161				{
162					if (!BX.findChild(tbl.rows[i], { 'class': 'title-search-separator' }, true))
163					{
164						if (last == -1)
165						{
166							last = i;
167						}
168
169						if (_this.currentRow > i)
170						{
171							_this.currentRow = i;
172							break;
173						}
174						else if (tbl.rows[i].className == 'title-search-selected')
175						{
176							tbl.rows[i].className = '';
177						}
178					}
179				}
180
181				if (i < 0 && _this.currentRow != i)
182				{
183					_this.currentRow = last;
184				}
185
186				tbl.rows[_this.currentRow].className = 'title-search-selected';
187
188				return true;
189			case 13: // enter key - choose current search result
190				if (_this.RESULT.style.display == 'block')
191				{
192					for (i = 0; i < cnt; i++)
193					{
194						if (
195							_this.currentRow == i
196							&& !BX.findChild(tbl.rows[i], { 'class': 'title-search-separator' }, true)
197						)
198						{
199							var a = BX.findChild(tbl.rows[i], { 'tag': 'a' }, true);
200							if (a)
201							{
202								window.location = a.href;
203
204								return true;
205							}
206						}
207					}
208				}
209
210				return false;
211			default:
212				break;
213		}
214
215		return false;
216	};
217
218	this.onTimeout = function()
219	{
220		_this.onChange(function() {
221			setTimeout(_this.onTimeout, 500);
222		});
223	};
224
225	this.onChange = function(callback)
226	{
227		if (_this.running)
228		{
229			_this.runningCall = true;
230
231			return;
232		}
233		_this.running = true;
234
235		if (_this.INPUT.value != _this.oldValue && _this.INPUT.value != _this.startText)
236		{
237			_this.oldValue = _this.INPUT.value;
238			if (_this.INPUT.value.length >= _this.arParams.MIN_QUERY_LEN)
239			{
240				_this.cache_key = _this.arParams.INPUT_ID + '|' + _this.INPUT.value;
241				if (_this.cache[_this.cache_key] == null)
242				{
243					if (_this.WAIT)
244					{
245						var pos = BX.pos(_this.INPUT);
246						var height = (pos.bottom - pos.top) - 2;
247						_this.WAIT.style.top = (pos.top + 1) + 'px';
248						_this.WAIT.style.height = height + 'px';
249						_this.WAIT.style.width = height + 'px';
250						_this.WAIT.style.left = (pos.right - height + 2) + 'px';
251						_this.WAIT.style.display = 'block';
252					}
253
254					BX.ajax.post(
255						_this.arParams.AJAX_PAGE,
256						{
257							'ajax_call': 'y',
258							'INPUT_ID': _this.arParams.INPUT_ID,
259							'q': _this.INPUT.value,
260							'l': _this.arParams.MIN_QUERY_LEN,
261						},
262						function(result)
263						{
264							_this.cache[_this.cache_key] = result;
265							_this.ShowResult(result);
266							_this.currentRow = -1;
267							_this.EnableMouseEvents();
268							if (_this.WAIT)
269							{
270								_this.WAIT.style.display = 'none';
271							}
272
273							if (!!callback)
274							{
275								callback();
276							}
277
278							_this.running = false;
279							if (_this.runningCall)
280							{
281								_this.runningCall = false;
282								_this.onChange();
283							}
284						}
285					);
286
287					return;
288				}
289
290				_this.ShowResult(_this.cache[_this.cache_key]);
291				_this.currentRow = -1;
292				_this.EnableMouseEvents();
293			}
294			else
295			{
296				_this.RESULT.style.display = 'none';
297				_this.currentRow = -1;
298				_this.UnSelectAll();
299			}
300		}
301
302		if (!!callback)
303		{
304			callback();
305		}
306		_this.running = false;
307	};
308
309	this.onScroll = function ()
310	{
311		if (BX.type.isElementNode(_this.RESULT)
312			&& _this.RESULT.style.display !== 'none'
313			&& _this.RESULT.innerHTML !== ''
314		)
315		{
316			_this.adjustResultNode();
317		}
318	};
319
320	this.UnSelectAll = function()
321	{
322		var tbl = BX.findChild(_this.RESULT, { 'tag': 'table', 'class': 'title-search-result' }, true);
323		if (tbl)
324		{
325			var cnt = tbl.rows.length;
326			for (var i = 0; i < cnt; i++)
327			{
328				tbl.rows[i].className = '';
329			}
330		}
331	};
332
333	this.EnableMouseEvents = function()
334	{
335		var tbl = BX.findChild(_this.RESULT, { 'tag': 'table', 'class': 'title-search-result' }, true);
336		if (tbl)
337		{
338			var cnt = tbl.rows.length;
339			for (var i = 0; i < cnt; i++)
340			{
341				if (!BX.findChild(tbl.rows[i], { 'class': 'title-search-separator' }, true))
342				{
343					tbl.rows[i].id = 'row_' + i;
344					tbl.rows[i].onmouseover = function (e) {
345						if (_this.currentRow != this.id.substr(4))
346						{
347							_this.UnSelectAll();
348							this.className = 'title-search-selected';
349							_this.currentRow = this.id.substr(4);
350						}
351					};
352
353					tbl.rows[i].onmouseout = function (e) {
354						this.className = '';
355						_this.currentRow = -1;
356					};
357				}
358			}
359		}
360	};
361
362	this.onFocusLost = function(hide)
363	{
364		setTimeout(function() { _this.RESULT.style.display = 'none'; }, 250);
365	};
366
367	this.onFocusGain = function()
368	{
369		if (_this.RESULT.innerHTML.length > 0)
370		{
371			_this.ShowResult();
372		}
373	};
374
375	this.onKeyDown = function(e)
376	{
377		if (!e)
378		{
379			e = window.event;
380		}
381
382		if (_this.RESULT.style.display == 'block' && _this.onKeyPress(e.keyCode))
383		{
384			return BX.PreventDefault(e);
385		}
386	};
387
388	this.adjustResultNode = function()
389	{
390		if (!(BX.type.isElementNode(_this.RESULT)
391			&& BX.type.isElementNode(_this.CONTAINER))
392		)
393		{
394			return { top: 0, right: 0, bottom: 0, left: 0, width: 0, height: 0 };
395		}
396
397		var pos = BX.pos(_this.CONTAINER);
398
399		_this.RESULT.style.position = 'absolute';
400		_this.RESULT.style.top = (pos.bottom + 2) + 'px';
401		_this.RESULT.style.left = pos.left + 'px';
402		_this.RESULT.style.width = pos.width + 'px';
403
404		return pos;
405	};
406
407	this.onContainerLayoutChange = function()
408	{
409		if (BX.type.isElementNode(_this.RESULT)
410			&& _this.RESULT.style.display !== 'none'
411			&& _this.RESULT.innerHTML !== ''
412		)
413		{
414			_this.adjustResultNode();
415		}
416	};
417
418	this.Init = function()
419	{
420		this.CONTAINER = document.getElementById(this.arParams.CONTAINER_ID);
421		BX.addCustomEvent(this.CONTAINER, 'OnNodeLayoutChange', this.onContainerLayoutChange);
422
423		this.RESULT = document.body.appendChild(document.createElement("DIV"));
424		this.RESULT.className = 'title-search-result';
425		this.INPUT = document.getElementById(this.arParams.INPUT_ID);
426		this.startText = this.INPUT.value;
427		this.oldValue = this.INPUT.value;
428		BX.bind(this.INPUT, 'focus', function() { _this.onFocusGain(); });
429		BX.bind(this.INPUT, 'blur', function() { _this.onFocusLost(); });
430		this.INPUT.onkeydown = this.onKeyDown;
431
432		if (this.arParams.WAIT_IMAGE)
433		{
434			this.WAIT = document.body.appendChild(document.createElement('DIV'));
435			this.WAIT.style.backgroundImage = "url('" + this.arParams.WAIT_IMAGE + "')";
436			if (!BX.browser.IsIE())
437			{
438				this.WAIT.style.backgroundRepeat = 'none';
439			}
440			this.WAIT.style.display = 'none';
441			this.WAIT.style.position = 'absolute';
442			this.WAIT.style.zIndex = '1100';
443		}
444
445		BX.bind(this.INPUT, 'bxchange', function() {_this.onChange()});
446
447		var fixedParent = BX.findParent(this.CONTAINER, BX.is_fixed);
448		if (BX.type.isElementNode(fixedParent))
449		{
450			BX.bind(window, 'scroll', BX.throttle(this.onScroll, 100, this));
451		}
452	};
453
454	BX.ready(function() { _this.Init(arParams); });
455}

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.