PageSourceSearch

https://spasstower.ru/local/js/controllers/partial/search-panel.js?17164858005318

js spasstower.ru collected 2026-10-02 04:44:47 UTC 5,318 bytes, 157 lines download raw bytes

1(function($, APP) {
2    'use strict';
3    
4    /**
5     * Панель поиска, десктопная версия
6     **/
7    APP.Controls.Partial.SearchPanel = can.Control.extend({
8        defaults: {
9            events: {
10                searchPanelOpen: 'searchPanelOpen',
11                searchPanelClose: 'searchPanelClose'
12            }
13        }
14    }, {
15
16        loading: false,
17        prevSearch: '',
18        scrollInited: false,
19    
20        init: function() {
21            this.$input = this.element.find('.js-search-input');
22            this.$resultsWrapper = this.element.find('.js-results-wrapper');
23            this.$results = this.element.find('.js-results');
24            this.$allResults = this.$resultsWrapper.find('.js-all-results');
25            this.$noResults = this.$resultsWrapper.find('.js-no-results');
26            this.prevSearch = this.$input.val();
27        },
28
29        '{window} {events.searchPanelOpen}': function() {
30            this.element.addClass('opened');
31
32            if (this.element.hasClass('search-giant-panel')) {
33
34                this.$input.focus();
35
36                if (APP.Helper.isIe() !== false) {
37                    setTimeout(function () {
38                        this.$input.focus();
39                    }.bind(this), 100);
40                }
41            }
42        },
43
44        '{window} click': function($el, ev) {
45            var $target = $(ev.target);
46
47            if (!$target.hasClass('js-results-wrapper') && $target.closest('.js-results-wrapper').length == 0) {
48                this.$resultsWrapper.removeClass('visible');
49            }
50        },
51
52        '{window} {events.searchPanelClose}': function() {
53            this.element.removeClass('opened');
54            this.$resultsWrapper.removeClass('visible');
55        },
56
57        '{window} resize': function() {
58            if (this.$resultsWrapper.hasClass('visible') && this.scrollInited) {
59                this.element.find('.js-m-scroll').mCustomScrollbar('update');
60            }
61        },
62
63        '.back-shadow click': function() {
64            this.element.removeClass('opened');
65            this.$resultsWrapper.removeClass('visible');
66        },
67
68        '.js-close-panel click': function() {
69            this.element.removeClass('opened');
70            this.$resultsWrapper.removeClass('visible');
71        },
72
73        '.js-search-input keyup': function($el, ev) {
74            if (ev.which == 27) {
75                this.prevSearch = this.$input.val();
76                this.$resultsWrapper.removeClass('visible');
77            }
78        },
79
80        '.js-search-input keydown': APP.Helper.debounce(function() {
81            this.loadAutocomplete();
82        }, 500),
83
84        '.button-submit click': function() {
85            this.element.find('.js-form').submit();
86        },
87
88        loadAutocomplete: function() {
89            var text = this.$input.val();
90            if (text.length < 3) return;
91
92            if (this.loading) return false;
93            if (text == this.prevSearch) return false;
94
95            this.prevSearch = text;
96            this.loading = true;
97            this.$resultsWrapper.removeClass('visible');
98
99            $.ajax({
100                url: APP.searchUrl,
101                data: {
102                    query: text
103                },
104                dataType: 'json',
105                method: 'post',
106                success: function(result) {
107                    if (!result || !result.success) return;
108
109                    this.loading = false;
110                    this.showResults(result);
111                }.bind(this),
112                error: function() {
113                    this.loading = false;
114                    this.showResults({});
115                }.bind(this)
116            });
117        },
118
119        showResults: function(data) {
120            var $container = this.$results;
121            if (this.scrollInited) $container = this.$results.find('.mCSB_container');
122            $container.html('');
123
124            this.$resultsWrapper.addClass('visible');
125            if (!data.types || data.types == 0) {
126                this.$allResults.hide();
127                this.$noResults.show().find('.js-query').html(this.prevSearch);
128
129            } else {
130
131                for (var type in data.results) {
132                    if (type == 'other') continue; // Выводим их последними
133                    if (!data.results.hasOwnProperty(type)) continue;
134                    $container.append(can.view.render('searchAutocompleteTypeResult', {data: data.results[type]}));
135                }
136                if (data.results.other) {
137                    $container.append(can.view.render('searchAutocompleteTypeResult', {data: data.results.other}));
138                }
139
140                if (this.scrollInited) {
141                    this.element.find('.js-m-scroll').mCustomScrollbar('update');
142                } else {
143                    this.element.find('.js-m-scroll').mCustomScrollbar({
144                        scrollbarPosition: 'outside',
145                        scrollInertia: 0,
146                        axis: 'y'
147                    });
148                }
149                this.scrollInited = true;
150
151                this.$noResults.hide();
152                this.$allResults.attr('href', data.all).show();
153            }
154        }
155    });
156
157})(jQuery, window.APP);

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.