PageSourceSearch

https://xn--36-dlclanhp8agm.xn--p1acf/wp-content/themes/perevozki/js/search-address.js

js xn--36-dlclanhp8agm.xn--p1acf collected 2026-10-09 00:00:11 UTC 6,794 bytes, 250 lines download raw bytes

1// https://yandex.ru/blog/ymapsapi/1501
2function SearchAddress(map, form) {
3    this._model = new SearchAddress.Model(map);
4    this._formView = new SearchAddress.FormView(form);
5    this._mapView = new SearchAddress.MapView(map);
6
7    this._attachHandlers();
8}
9
10SearchAddress.prototype = {
11    constructor: SearchAddress,
12    _attachHandlers: function () {
13        this._formView.events
14            .on('searchrequest', $.proxy(this._onSearchRequest, this));
15    },
16    _detachHandlers: function () {
17        this._formView.events
18            .off();
19    },
20    _onSearchRequest: function (e) {
21        var promise = this._model.search(e.query);
22
23        this._mapView
24            .clear();
25
26        promise.then(
27            $.proxy(this._onSearchSuccess, this),
28            $.proxy(this._onSearchError, this)
29        );
30    },
31    _onSearchSuccess: function (result) {
32        if(this._model.getResult()) {
33            this._mapView
34                .render(result);
35        }
36        else {
37            this._formView
38                .showMessage("Ничего не найдено.");
39        }
40    },
41    _onSearchError: function (e) {
42        this._formView.showMessage(
43            this._model.getError()
44        );
45    },
46    getModel: function () {
47        return this._formModel;
48    }
49};
50
51SearchAddress.MapView = function (map) {
52    this._map = map;
53    this._point = null;
54};
55
56SearchAddress.MapView.prototype = {
57    constructor: SearchAddress.MapView,
58    render: function (results) {
59        var metaData = results.metaData.geocoder,
60            result = results.geoObjects.get(0),
61            balloonContent = '<p><small>по запросу:</small>&nbsp;<em>' + metaData.request + '</em></p>' +
62                '<p><small>найдено:</small>&nbsp;<strong>' + result.properties.get('text') + '</strong></p>';
63
64        this._point = new ymaps.Placemark(result.geometry.getCoordinates(), {
65            balloonContentBody: balloonContent
66        });
67
68        this._map.geoObjects
69            .add(this._point);
70
71        this._setMapBounds(result.properties.get('boundedBy'));
72
73        return this;
74    },
75    clear: function () {
76        if(this._point) {
77            this._map.geoObjects
78                .remove(this._point);
79            this._point = null;
80        }
81
82        return this;
83    },
84    getPoint: function () {
85        return this._point;
86    },
87    _setMapBounds: function (bounds) {
88        this._map.setBounds(bounds, {
89            checkZoomRange: true,
90            duration: 200,
91            callback: ymaps.util.bind(this._onSetMapBounds, this)
92        });
93    },
94    _onSetMapBounds: function () {
95        this._point.balloon
96            .open();
97    }
98};
99
100SearchAddress.FormView = function (form) {
101    this._form = form;
102    this._controls = form.find('.control-group');
103    this._message = form.find('.help-inline');
104    this._input = form.find('.search-query');
105
106    this.events = $({});
107
108    this._attachHandlers();
109};
110
111SearchAddress.FormView.prototype = {
112    constructor: SearchAddress.FormView,
113    _attachHandlers: function () {
114        // this._form
115            // .on('submit', $.proxy(this._onFormSubmit, this));
116        this._input
117            .on('keydown', $.proxy(this._onInputChange, this))
118            .typeahead({
119                source: $.proxy(this._dataSource, this),
120                items: this.getSuggestConfig().limit,
121                minLength: 3
122            });
123    },
124    _detachHandlers: function () {
125        this._form
126            .off("submit");
127        this._input
128            .off();
129    },
130    _onFormSubmit: function (e) {
131        e.preventDefault();
132
133        var value = this._input.val();
134
135        if(value) {
136            this.events.trigger($.Event('searchrequest', {
137                query: value
138            }));
139        }
140        else {
141            this.showMessage('Задан пустой поисковый запрос.');
142        }
143    },
144    _onInputChange: function (e) {
145        this.hideMessage();
146    },
147    showMessage: function (text) {
148        this._controls
149            .addClass('error');
150        this._message
151            .removeClass('invisible')
152            .text(text);
153    },
154    hideMessage: function () {
155        this._controls
156            .removeClass('error');
157        this._message
158            .addClass('invisible')
159            .text('');
160    },
161    _dataSource: function (query, callback) {
162        var config = this.getSuggestConfig(),
163            request = $.extend({ query: query }, config);
164
165        $.ajax({
166            url: config.url,
167            dataType: 'jsonp',
168            data: request,
169            context: this,
170            success: function (json) {
171                var results = [];
172
173                for(var i = 0, len = json.result.length; i < len; i++) {
174                    var result = json.result[i],
175                        parent = result.parents && result.parents[0];
176
177                    results.push(
178                        (parent && (parent.name + ' ' + parent.type + ', ') || '') +
179                        result.type + ' ' + result.name
180                    );
181                }
182
183                callback(results);
184            }
185        });
186    },
187    getSuggestConfig: function () {
188        return {
189            url: 'https://kladr-api.ru/api.php',
190            contentType: 'city',
191            withParent: 1,
192            limit: 5,
193            token: '52024d6c472d040824000221',
194            key: '6cf033712aa73a4a26db39d72ea02bb682c8e390'
195        };
196    }
197};
198
199SearchAddress.Model = function (map) {
200    this._map = map;
201    this._result = null;
202    this._error = null;
203};
204
205SearchAddress.Model.prototype = {
206    constructor: SearchAddress.Model,
207    search: function (request) {
208        var promise = ymaps.geocode(request, this.getDefaults());
209
210        this.clear();
211
212        promise.then(
213            $.proxy(this._onSearchSuccess, this),
214            $.proxy(this._onSearchFailed, this)
215        );
216
217        return promise;
218    },
219    clear: function () {
220        this._result = null;
221        this._error = null;
222    },
223    _onSearchSuccess: function (result) {
224        this._result = result.geoObjects.get(0);
225    },
226    _onSearchFailed: function (error) {
227        this._error = error;
228    },
229    getDefaults: function () {
230        return {
231            results: 1,
232            boundedBy: this._map.getBounds()
233        };
234    },
235    getResult: function () {
236        return this._result;
237    },
238    getError: function () {
239        return this._error;
240    }
241};
242
243$(document).ready(function(){
244        searchControl = new SearchAddress('', $('#route_form'));
245		
246		$('.add_waypoint').click(function() {
247			$('.waypoints > span:visible, .waypoints > input:visible').next('input').show();
248			if ($('.waypoints > input:hidden').length == 0) $(this).hide();
249		});
250});

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.