PageSourceSearch

https://fontan.su/bitrix/templates/aspro-premier/js/conditional/search_title/search-title.js

js fontan.su collected 2026-10-08 20:43:02 UTC 13,727 bytes, 436 lines download raw bytes

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

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.