PageSourceSearch

https://e-boreal.ru/js/shops_map.js

js e-boreal.ru collected 2026-10-05 00:27:27 UTC 28,981 bytes, 787 lines download raw bytes

1$(document).ready(function() {
2	if ($('.shops_map').size() > 0) {
3		shops_map.init();
4	}
5});
6
7var shops_map = {
8	markers: [],
9	visibles: 0,
10	userAction: true,
11	init: function() {
12		shops_map.resize();
13		$(window).resize(function() {
14			shops_map.resize();
15		});
16		shops_map.fill_arrays();
17		ymaps.ready(function() {
18			shops_map.ymap_init($('.shops_map_container'));
19		});
20	},
21	resize: function() {
22		var h = Math.min(Math.max(window.innerHeight - $('.shops_map_wrap').offset().top - 10, 450), 770);
23		shops_map.scrollHeight = h * 0.87;
24		$('.shops_map_container').height(h);
25		$('.shops_map_wrap .scroll:visible').each(function() {
26			shops_map.scroll_init($(this));
27		});
28	},
29	ymap_init: function(container) {
30		var center_zoom = shops_map.get_center_zoom();
31		shops_map.map = new ymaps.Map(
32			container.attr('id'),
33			{
34				center: center_zoom.center,
35				zoom: center_zoom.zoom,
36				behaviors: ['default'],
37				controls: ['typeSelector', 'fullscreenControl', 'zoomControl']
38			},
39			{
40				searchControlProvider: 'yandex#search'
41			}
42		);
43		shops_map.map.behaviors.disable('scrollZoom');
44		shops_map.map.events.add('click', function(e) {
45			shops_map.map.balloon.close();
46			$('.balloon .close').click();
47		});
48		shops_map.map.events.add('boundschange', function(e) {
49			if (!shops_map.userAction) {
50				if (e.get('newZoom') != e.get('oldZoom')) {
51					shops_map.set_markers(null, null, true);
52				}
53			}
54			shops_map.userAction = false;
55		});
56		if (typeof(add_map_points) != 'undefined') {
57			shops_map.fill_data();
58		}
59		$(document).on('click', '.shops_map_cities .item', function() {
60			shops_map.userAction = true;
61			shops_map.remove_route();
62			var cityID = $(this).text();
63			var data = shops_map.data[cityID];
64			if (data.shops_count == 1) {
65				shops_map.show_info(cityID, Object.keys(data.shops)[0]);
66			}
67			else {
68				shops_map.show_info(cityID);
69			}
70		});
71		$(document).on('click', '.shops_map_shops .shop', function() {
72			if ($(this).hasClass('visible')) {
73				shops_map.userAction = true;
74				shops_map.remove_route();
75				var cityID = $(this).attr('data-city');
76				var data = shops_map.data[cityID];
77				if (data.shops_count == 1) {
78					shops_map.show_info(shops_map.cityID, Object.keys(data.shops)[0]);
79				}
80				else {
81					var ind = $('.shops_map_shops .shop').index($(this));
82					var marker = shops_map.markers[ind];
83					shops_map.map.setCenter(marker.geometry.getCoordinates(), shops_map.map.getZoom(), {
84						useMapMargin: true
85					});
86					marker.balloon.open();
87				}
88			}
89		});
90		$(document).on('click', '.shops_map_wrap .collapse_lnk, .shops_map_wrap .layer .title', function() {
91			$(this).closest('.layer').toggleClass('collapsed');
92			shops_map.scroll_init($(this).closest('.layer').find('.scroll'));
93		});
94		$(document).on('click', '.shops_map_shops .back_lnk', function() {
95			shops_map.userAction = true;
96			shops_map.remove_route();
97			shops_map.show_info(null);
98		});
99		$(document).on('click', '.shops_map_shop .back_lnk', function() {
100			shops_map.userAction = true;
101			shops_map.remove_route();
102			var data = shops_map.data[shops_map.cityID];
103			if (data.shops_count == 1) {
104				shops_map.show_info(null);
105			}
106			else {
107				shops_map.show_info(shops_map.cityID);
108			}
109		});
110		$(document).on('click', '.shops_map_shop .but_print', function() {
111			shops_map.print_shop();
112		});
113		$(document).on('click', '.shops_map_shop .route_icon', function() {
114			shops_map.user_position();
115		});
116		$(document).on('focus', '.shops_map_shop .route input[name=address]', function() {
117			$('.shops_map_shop .route_msg').html('');
118		});
119		$(document).on('submit', '.shops_map_shop .route', function(e) {
120			e.preventDefault();
121			shops_map.create_route();
122			return false;
123		});
124		$('.shops_map_wrap .scroll').bind('scroll mousewheel DOMMouseScroll', function(e) {
125			e.stopPropagation();
126			var scroll = $(this);
127			var h = scroll.outerHeight() - scroll.find('.scroll_content').outerHeight();
128			e.delta = null;
129			if (e.originalEvent) {
130				if (e.originalEvent.wheelDelta) e.delta = e.originalEvent.wheelDelta / -40;
131				if (e.originalEvent.deltaY) e.delta = e.originalEvent.deltaY;
132				if (e.originalEvent.detail) e.delta = e.originalEvent.detail;
133			}
134			if ($(this).find('.jspPane').position().top <= h && e.delta > 0 || $(this).find('.jspPane').position().top == 0 && e.delta <= 0) {
135				e.preventDefault();
136				return false;
137			}
138		});
139
140		if (shops_map.cityID != null && typeof(shops_map.cityID) != 'undefined') {
141			var data = shops_map.data[shops_map.cityID];
142			if (data.shops_count == 1) {
143				shops_map.show_info(shops_map.cityID, Object.keys(data.shops)[0]);
144			}
145		}
146		else {
147			shops_map.show_info(shops_map.cityID, shops_map.shopID);
148		}
149	},
150	get_center_zoom: function() {
151		var markers = [], xmin = 9999, xmax = -9999, ymin = 9999, ymax = -9999, c = 0, a = 0;
152		for (var i in shops_map.data) {
153			for (var j in shops_map.data[i].shops) {
154				if (shops_map.cityID != null && typeof(shops_map.cityID) != 'undefined' && i == shops_map.cityID || shops_map.cityID == null || typeof(shops_map.cityID) == 'undefined') {
155					var coords = shops_map.data[i].shops[j].coords.split(',');
156					coords = [parseFloat(coords[0]), parseFloat(coords[1])];
157					if (coords[0] > ymax) {
158						ymax = coords[0];
159					}
160					if (coords[0] < ymin) {
161						ymin = coords[0];
162					}
163					if (coords[1] > xmax) {
164						xmax = coords[1];
165					}
166					if (coords[1] < xmin) {
167						xmin = coords[1];
168					}
169					c ++;
170				}
171				a ++;
172			}
173		}
174		var z = 16, o = 0;
175		if (c == 2) {
176			z = 12;
177		}
178		else if (c > 2 && c < 15) {
179			z = 10;
180		}
181		else if (c >= 15) {
182			z = 3;
183		}
184		var ox = c < a ? 274 / Math.pow(2, z) : 0;
185		var oy = c == a ? 36 / Math.pow(2, z) : 0;
186		return {'center': c > 1 ? [(ymax + ymin) / 2 + oy, (xmax + xmin) / 2 - ox] : [ymin + oy, xmin - ox], 'zoom': z};
187	},
188	fill_arrays: function() {
189		shops_map.data = {};
190		if (typeof(add_map_points) != 'undefined') {
191			for (var i in add_map_points) {
192				var city = add_map_points[i].cityname;
193				if (city) {
194					if (typeof(shops_map.data[city]) == 'undefined') {
195						shops_map.data[city] = {};
196						shops_map.data[city].shops = {};
197						shops_map.data[city].shops_count = 0;
198					}
199					shops_map.data[city].shops[i] = add_map_points[i];
200					if (!add_map_points[i].name) {
201						shops_map.data[city].shops[i].name = 'Ìàãàçèí «Òðèàë-Ñïîðò»';
202					}
203					if (!add_map_points[i].dealer_url) {
204						shops_map.data[city].shops[i].dealer_url = 'http://trial-sport.ru';
205					}
206					shops_map.data[city].shops_count ++;
207				}
208			}
209		}
210		if (typeof(add_map_points2) != 'undefined') {
211			for (var i in add_map_points2) {
212				var city = add_map_points2[i].cityname;
213				if (city) {
214					if (typeof(shops_map.data[city]) == 'undefined') {
215						shops_map.data[city] = {};
216						shops_map.data[city].shops = {};
217						shops_map.data[city].shops_count = 0;
218					}
219					shops_map.data[city].shops[i] = add_map_points2[i];
220					shops_map.data[city].shops_count ++;
221				}
222			}
223		}
224		shops_map.data = sort_object(shops_map.data);
225		$('.shops_map_data .scroll_content').html('');
226		var html = '<div class="hiddable">';
227		for (var i in shops_map.data) {
228			html += '<div class="item">' + i + '</div>';
229		}
230		html += '</div>';
231		$('.shops_map_cities .scroll_content').html(html);
232	},
233	fill_item: function(cityID, shopID) {
234		var data = shops_map.data[cityID].shops[shopID]
235		var balloonLayout = ymaps.templateLayoutFactory.createClass(
236			'<div class="balloon">' +
237				'<div class="close"></div>' +
238				'<div class="arrow"></div>' +
239				'$[[options.contentLayout observeSize minWidth=300 maxWidth=300 maxHeight=350]]' +
240			'</div>', {
241			build: function () {
242				this.constructor.superclass.build.call(this);
243				this._$element = $('.balloon', this.getParentElement());
244				this.applyElementOffset();
245				this._$element.find('.close').on('click', $.proxy(this.onCloseClick, this));
246				this._$element.find('.but').on('click', $.proxy(this.onButtonMoreClick, this));
247			},
248			clear: function () {
249				this._$element.find('.close').off('click');
250				this.constructor.superclass.clear.call(this);
251			},
252			onSublayoutSizeChange: function () {
253				balloonLayout.superclass.onSublayoutSizeChange.apply(this, arguments);
254				if(!this._isElement(this._$element)) {
255					return;
256				}
257				this.applyElementOffset();
258				this.events.fire('shapechange');
259			},
260			applyElementOffset: function () {
261				this._$element.css({
262					left: -(this._$element[0].offsetWidth / 2),
263					top: -(this._$element[0].offsetHeight + this._$element.find('.arrow')[0].offsetHeight)
264				});
265			},
266			getShape: function () {
267				if(!this._isElement(this._$element)) {
268					return balloonLayout.superclass.getShape.call(this);
269				}
270				var position = this._$element.position();
271				return new ymaps.shape.Rectangle(new ymaps.geometry.pixel.Rectangle([
272					[position.left, position.top], [
273						position.left + this._$element[0].offsetWidth,
274						position.top + this._$element[0].offsetHeight + this._$element.find('.arrow')[0].offsetHeight
275					]
276				]));
277			},
278			_isElement: function (element) {
279				return element && element[0] && element.find('.arrow')[0];
280			},
281			onCloseClick: function (e) {
282				e.preventDefault();
283				this.events.fire('userclose');
284			},
285			onButtonMoreClick: function (e) {
286				e.preventDefault();
287				if (!$('.shops_map_shop').is(':visible') || $('.shops_map_shop .shop').attr('data-shop') != this._$element.find('.buttons').attr('data-shop')) {
288					shops_map.userAction = true;
289					shops_map.show_info(this._$element.find('.buttons').attr('data-city'), this._$element.find('.buttons').attr('data-shop'));
290				}
291			}
292		});
293		var balloonContentLayout = ymaps.templateLayoutFactory.createClass(
294			'$[properties.balloonContent]'
295		);
296		var balloonContent = shops_map.short_shop_content(cityID, shopID, true);
297		var marker = new ymaps.Placemark(
298			data.coords.split(','),
299			{
300				balloonContent: balloonContent
301			},
302			{
303				id: shopID,
304				city: cityID,
305				iconLayout: 'default#image',
306				iconImageHref: 'img/shops_map_point.png',
307				iconImageSize: [34, 51],
308				iconImageOffset: [-14, -51],
309				balloonShadow: false,
310				balloonLayout: balloonLayout,
311				balloonContentLayout: balloonContentLayout,
312				hideIconOnBalloonOpen: false,
313				balloonOffset: [3, -42],
314				visible: true
315			}
316		);
317		shops_map.markers.push(marker);
318		return shops_map.short_shop_content(cityID, shopID, false);
319	},
320	fill_data: function() {
321		shops_map.markers = [];
322		$('.shops_map_shops .scroll_content').html('');
323		var html = '<div class="hiddable">';
324		for (var i in shops_map.data) {
325			for (var j in shops_map.data[i].shops) {
326				html += shops_map.fill_item(i, j);
327			}
328		}
329		html += '<div align="center"><a href="javascript:void(0)" class="back_lnk">ìàãàçèíû â äðóãèõ ãîðîäàõ</a></div>';
330		html += '</div>';
331		$('.shops_map_shops .scroll_content').html(html);
332	},
333	create_group: function() {
334		shops_map.group = new ymaps.GeoObjectCollection({}, {});
335		shops_map.map.geoObjects.add(shops_map.group);
336	},
337	set_markers: function(cityID, shopID, bounds) {
338		if (!shops_map.group) {
339			shops_map.create_group();
340		}
341		var markers = [];
342		if (cityID != null && typeof(cityID) != 'undefined') {
343			shops_map.group.removeAll();
344			for (var i = 0; i < shops_map.markers.length; i ++) {
345				if ((shops_map.markers[i].options.get('city') == cityID) && (shopID != null && typeof(shopID) != 'undefined' && shops_map.markers[i].options.get('id') == shopID || shopID == null || typeof(shopID) == 'undefined')) {
346					markers.push(shops_map.markers[i]);
347					shops_map.group.add(shops_map.markers[i]);
348				}
349			}
350			if (markers.length == 1) {
351				shops_map.map.setCenter(markers[0].geometry.getCoordinates(), 16, {
352					useMapMargin: true
353				});
354			}
355			else {
356				shops_map.set_bounds();
357			}
358		}
359		else if (bounds) {
360			var searchMarkers = ymaps.geoQuery(shops_map.markers).searchInside(shops_map.map);
361			var cities = [], shops = [];
362			searchMarkers.each(function(m) {
363				cities.push(m.options.get('city'));
364				shops_map.cityID = null;
365				if (shops_map.shopID == null) {
366					shops.push(m.options.get('id'));
367				}
368				else if (m.options.get('id') != shops_map.shopID) {
369					shops.push(m.options.get('id'));
370					shops_map.shopID = null;
371				}
372			});
373			if (shops_map.visibles != searchMarkers.getLength()) {
374				shops_map.group.removeAll();
375				if (cities.length == 1) {
376					shops_map.cityID = cities[0];
377				}
378				else if (cities.length > 1 && cities.filter(uniqueVal).length == 1) {
379					shops_map.cityID = cities.filter(uniqueVal)[0];
380				}
381				if (shops.length == 1) {
382					shops_map.shopID = shops[0];
383				}
384				if (shops_map.cityID) {
385					for (var i = 0; i < shops_map.markers.length; i ++) {
386						if (shops_map.markers[i].options.get('city') == shops_map.cityID) {
387							markers.push(shops_map.markers[i]);
388							shops_map.group.add(shops_map.markers[i]);
389						}
390					}
391					shops_map.show_layers(shops_map.cityID, shops_map.shopID);
392				}
393				else {
394					markers = shops_map.markers;
395					for (var i = 0; i < shops_map.markers.length; i ++) {
396						shops_map.group.add(shops_map.markers[i]);
397					}
398					shops_map.show_layers(shops_map.cityID, shops_map.shopID);
399				}
400			}
401		}
402		else {
403			markers = shops_map.markers;
404			if (shops_map.visibles != markers.length) {
405				shops_map.group.removeAll();
406				for (var i = 0; i < shops_map.markers.length; i ++) {
407					shops_map.group.add(shops_map.markers[i]);
408				}
409				var center_zoom = shops_map.get_center_zoom();
410				shops_map.map.setCenter(center_zoom.center);
411				shops_map.map.setZoom(center_zoom.zoom);
412
413			}
414		}
415		shops_map.visibles = markers.length;
416	},
417	set_margins: function() {
418		var margins = [30, 30, 30, 360];
419		shops_map.map.margin.setDefaultMargin(margins);
420	},
421	set_bounds: function() {
422		shops_map.map.setBounds(
423			shops_map.group.getBounds(),
424			{
425				checkZoomRange: true,
426				useMapMargin: true
427			}
428		);
429	},
430	show_info: function(cityID, shopID) {
431		shops_map.cityID = cityID;
432		shops_map.shopID = shopID;
433		$('.shops_map_wrap .layer').addClass('collapsed').hide();
434		shops_map.set_margins();
435		shops_map.set_markers(cityID, shopID, false);
436		shops_map.show_layers(cityID, shopID);
437	},
438	show_layers: function(cityID, shopID) {
439		if (cityID != null && typeof(cityID) != 'undefined' && shopID != null && typeof(shopID) != 'undefined') {
440			var block = $('.shops_map_shop');
441			var data = shops_map.data[cityID];
442			block.find('.title').html(data.shops[shopID].name ? data.shops[shopID].name : ('Ìàãàçèíû â ã. ' + cityID));
443			block.find('.scroll_content').html(shops_map.full_shop_content(cityID, shopID));
444		}
445		else if (cityID != null && typeof(cityID) != 'undefined') {
446			var block = $('.shops_map_shops');
447			block.find('.title').html('Ìàãàçèíû â ã. ' + cityID);
448			block.find('.shop').each(function() {
449				$(this).removeClass('first').toggleClass('visible', $(this).attr('data-city') == cityID);
450			});
451			block.find('.shop.visible:first').addClass('first');
452		}
453		else {
454			var block = $('.shops_map_cities');
455		}
456		$('.shops_map_wrap').toggleClass('shops_map_one', block.hasClass('shops_map_shop'));
457		$('.shops_map_wrap .layer').addClass('collapsed').hide();
458		block.toggleClass('collapsed', block.hasClass('shops_map_cities')).show();
459		shops_map.scroll_init(block.find('.scroll'));
460	},
461	short_shop_content: function(cityID, shopID, isBalloon) {
462		var shop = shops_map.data[cityID].shops[shopID];
463		var shopContent = '<div class="' + (isBalloon ? '' : 'item ') + 'shop" data-city="' + cityID + '" data-shop="' + shopID + '">';
464		if (shop.name) {
465			if (isBalloon) {
466				shopContent += '<div class="title">' + shop.name + '</div>';
467			}
468			else {
469				shopContent += '<div class="block">';
470				shopContent += '<div class="info name"><i><img src="img/shops_map_sprite.png"></i>' + shop.name + '</div>';
471				shopContent += '</div>';
472			}
473		}
474		if (isBalloon) {
475			shopContent += '<div class="block"><big>' + cityID + '</big></div>';
476		}
477		if (shop.metro) {
478			shopContent += '<div class="block">';
479			for (var i = 0; i < shop.metro.length; i ++) {
480				shopContent += '<div class="info metro"><i><img src="img/shops_map_sprite.png"></i>' + shop.metro[i] + '</div>';
481			}
482			shopContent += '</div>';
483		}
484		if (shop.addr) {
485			shopContent += '<div class="block">';
486			shopContent += '<div class="info address"><i><img src="img/shops_map_sprite.png"></i>' + shop.addr + '</div>';
487			shopContent += '</div>';
488		}
489		if (shop.phone) {
490			shopContent += '<div class="block">';
491			shopContent += '<div class="info phone"><i><img src="img/shops_map_sprite.png"></i>';
492			for (var i = 0; i < shop.phone.length; i ++) {
493				shopContent += (i > 0 ? '<br>' : '') + shop.phone[i][0] + (shop.phone[i][1] != '' ? (' <small>/ ' + shop.phone[i][1] + ' /</small>') : '');
494			}
495			shopContent += '</div>';
496			shopContent += '</div>';
497		}
498		if (shop.time) {
499			shopContent += '<div class="block">';
500			shopContent += '<div class="info time"><i><img src="img/shops_map_sprite.png"></i>';
501			for (var i = 0; i < shop.time.length; i ++) {
502				shopContent += (i > 0 ? '<br>' : '') + shop.time[i];
503			}
504			shopContent += '</div>';
505			shopContent += '</div>';
506		}
507		if (isBalloon) {
508			if (shop.dealer_url) {
509				shopContent += '<div class="block">';
510				shopContent += '<div class="info url"><i><img src="img/shops_map_sprite.png"></i><a href="' + shop.dealer_url + '" target="_blank">' + shop.dealer_url + '</a></div>';
511				shopContent += '</div>';
512			}
513		}
514		shopContent += '</div>';
515		if (isBalloon) {
516			shopContent += '<div class="buttons" data-city="' + cityID + '" data-shop="' + shopID + '">';
517			shopContent += '<a href="javascript:void(0)" class="but">ïîäðîáíåå</a>';
518			shopContent += '</div>';
519		}
520		return shopContent;
521	},
522	full_shop_content: function(cityID, shopID) {
523		var shop = shops_map.data[cityID].shops[shopID];
524		var shopContent = '<div class="item shop" data-city="' + cityID + '" data-shop="' + shopID + '" data-print="1">';
525		shopContent += '<div class="block"><big>' + cityID + '</big></div>';
526		if (shop.metro) {
527			shopContent += '<div class="block">';
528			for (var i = 0; i < shop.metro.length; i ++) {
529				shopContent += '<div class="info metro"><i><img src="img/shops_map_sprite.png"></i>' + shop.metro[i] + '</div>';
530			}
531			shopContent += '</div>';
532		}
533		if (shop.addr) {
534			shopContent += '<div class="block">';
535			shopContent += '<div class="info address"><i><img src="img/shops_map_sprite.png"></i>' + shop.addr + '</div>';
536			shopContent += '</div>';
537		}
538		if (shop.phone) {
539			shopContent += '<div class="block">';
540			shopContent += '<div class="info phone"><i><img src="img/shops_map_sprite.png"></i>';
541			for (var i = 0; i < shop.phone.length; i ++) {
542				shopContent += (i > 0 ? '<br>' : '') + '<a href="tel:' + shop.phone[i][0] + '">' + shop.phone[i][0] + '</a>' + (shop.phone[i][1] != '' ? (' <small>/ ' + shop.phone[i][1] + ' /</small>') : '');
543			}
544			shopContent += '</div>';
545			shopContent += '</div>';
546		}
547		if (shop.time) {
548			shopContent += '<div class="block">';
549			shopContent += '<div class="info time"><i><img src="img/shops_map_sprite.png"></i>';
550			for (var i = 0; i < shop.time.length; i ++) {
551				shopContent += (i > 0 ? '<br>' : '') + shop.time[i];
552			}
553			shopContent += '</div>';
554			shopContent += '</div>';
555		}
556		if (shop.dealer_url) {
557			shopContent += '<div class="block">';
558			shopContent += '<div class="info url"><i><img src="img/shops_map_sprite.png"></i><a href="' + shop.dealer_url + '" target="_blank">' + shop.dealer_url + '</a></div>';
559			shopContent += '</div>';
560		}
561		if (shop.email) {
562			shopContent += '<div class="block">';
563			shopContent += '<div class="info email"><i><img src="img/shops_map_sprite.png"></i><a href="mailto:' + shop.email + '">' + shop.email + '</a></div>';
564			shopContent += '</div>';
565		}
566		shopContent += '</div>';
567		if (shop.credit == '1' || shop.service == '1' || shop.delivery == '1' || shop.bike == '1' || shop.cards == '1') {
568			shopContent += '<div class="item hiddable" data-print="1">';
569			shopContent += '<div class="block">';
570			if (shop.credit == '1') {
571				shopContent += '<div class="info info_half credit"><i><img src="img/shops_map_sprite.png"></i>Òîâàðû â êðåäèò</div>';
572			}
573			if (shop.service == '1') {
574				shopContent += '<div class="info info_half service"><i><img src="img/shops_map_sprite.png"></i>Ìàñòåðñêàÿ</div>';
575			}
576			if (shop.delivery == '1') {
577				shopContent += '<div class="info info_half delivery"><i><img src="img/shops_map_sprite.png"></i>Äîñòàâêà</div>';
578			}
579			if (shop.bike == '1') {
580				shopContent += '<div class="info info_half bike"><i><img src="img/shops_map_sprite.png"></i>Âåëîïàðêîâêà</div>';
581			}
582			if (shop.cards == '1') {
583				shopContent += '<div class="info info_half cards"><i><img src="img/shops_map_sprite.png"></i><table cellpadding="0" cellspacing="0"><tr><td><span class="card_icon card_icon_visa"><img src="img/shops_map_sprite.png"></span></td><td>
583<span class="card_icon card_icon_mc"><img src="img/shops_map_sprite.png"></span></td></tr></table></div>';
584			}
585			shopContent += '</div>';
586			shopContent += '</div>';
587		}
588		shopContent += '<div class="item hiddable">';
589		shopContent += '<div class="block">';
590		shopContent += '<div class="b5">Ïðîëîæèòü ìàðøðóò</div>';
591		shopContent += '<form class="route">';
592		shopContent += '<table cellpadding="0" cellspacing="0" width="100%"><tr>';
593		shopContent += '<td width="40"><a href="javascript:void(0)" class="route_icon" title="Îïðåäåëèòü òåêóùåå ìåñòîïîëîæåíèå"></a></td>';
594		shopContent += '<td><span class="route_input"><input type="text" name="address" value="" placeholder="Ââåäèòå àäðåñ"><span class="route_but"><input type="submit" value=" "></span></span></td>';
595		shopContent += '</tr></table>';
596		shopContent += '<div class="route_msg"></div>';
597		shopContent += '</form>';
598		shopContent += '</div>';
599		shopContent += '</div>';
600		shopContent += '<div class="item last hiddable">';
601		if (shop.info) {
602			shopContent += '<div class="block_grey b25" data-print="1">' + shop.info + '</div>';
603		}
604		shopContent += '<div class="but but_print b25"><span>ðàñïå÷àòàòü</span></div>';
605		var data = shops_map.data[shops_map.cityID];
606		var lnk_txt = data.shops_count == 1 ? 'ìàãàçèíû â äðóãèõ ãîðîäàõ' : 'âñå ìàãàçèíû';
607		shopContent += '<div align="center"><a href="javascript:void(0)" class="back_lnk">' + lnk_txt + '</a></div>';
608		shopContent += '</div>';
609		return shopContent;
610	},
611	user_position: function() {
612		$('.shops_map_shop .route_msg').html('');
613		ymaps.geolocation.get({
614			provider: 'auto',
615			mapStateAutoApply: true
616		}).then(
617			function(result) {
618				var coords = result.geoObjects.position;
619				$('.shops_map_shop .route_msg').html('');
620				$('.shops_map_shop .route input[name=address]').val(coords);
621				shops_map.create_route();
622			},
623			function() {
624				$('.shops_map_shop .route_msg').html('Íå óäàëîñü îïðåäåëèòü òåêóùåå ìåñòîïîëîæåíèå. Ââåäèòå àäðåñ.');
625			}
626		);
627	},
628	remove_route: function() {
629		if (shops_map.route) {
630			shops_map.map.geoObjects.remove(shops_map.route);
631		}
632	},
633	create_route: function() {
634		shops_map.userAction = true;
635		shops_map.remove_route();
636		$('.shops_map_shop .route_msg').html('');
637		if ($('.shops_map_shop .route input[name=address]').val() != '') {
638			var balloonLayout = ymaps.templateLayoutFactory.createClass(
639				'<div class="balloon balloon_route">' +
640					'<div class="close"></div>' +
641					'<div class="arrow"></div>' +
642					'<div class="shop">' +
643						'<div class="block">{{ properties.distance.text }}, {{ properties.duration.text }}</div>' +
644					'</div>' +
645				'</div>', {
646				build: function () {
647					this.constructor.superclass.build.call(this);
648					this._$element = $('.balloon', this.getParentElement());
649					this.applyElementOffset();
650					this._$element.find('.close').on('click', $.proxy(this.onCloseClick, this));
651				},
652				clear: function () {
653					this._$element.find('.close').off('click');
654					this.constructor.superclass.clear.call(this);
655				},
656				onSublayoutSizeChange: function () {
657					balloonLayout.superclass.onSublayoutSizeChange.apply(this, arguments);
658					if(!this._isElement(this._$element)) {
659						return;
660					}
661					this.applyElementOffset();
662					this.events.fire('shapechange');
663				},
664				applyElementOffset: function () {
665					this._$element.css({
666						left: -(this._$element[0].offsetWidth / 2),
667						top: -(this._$element[0].offsetHeight + this._$element.find('.arrow')[0].offsetHeight)
668					});
669				},
670				getShape: function () {
671					if(!this._isElement(this._$element)) {
672						return balloonLayout.superclass.getShape.call(this);
673					}
674					var position = this._$element.position();
675					return new ymaps.shape.Rectangle(new ymaps.geometry.pixel.Rectangle([
676						[position.left, position.top], [
677							position.left + this._$element[0].offsetWidth,
678							position.top + this._$element[0].offsetHeight + this._$element.find('.arrow')[0].offsetHeight
679						]
680					]));
681				},
682				_isElement: function (element) {
683					return element && element[0] && element.find('.arrow')[0];
684				},
685				onCloseClick: function (e) {
686					e.preventDefault();
687					this.events.fire('userclose');
688				}
689			});
690			shops_map.route = new ymaps.multiRouter.MultiRoute({
691				referencePoints: [
692					$('.shops_map_shop .route input[name=address]').val(),
693					shops_map.data[shops_map.cityID].shops[shops_map.shopID].coords.split(',')
694				],
695				params: {
696					routingMode: 'auto'
697				}
698			}, {
699				useMapMargin: true,
700				boundsAutoApply: true,
701				wayPointStartIconLayout: 'default#image',
702				wayPointStartIconImageHref: 'img/shops_map_origin.png',
703				wayPointStartIconImageSize: [30, 34],
704				wayPointStartIconImageOffset: [-15, -34],
705				wayPointFinishVisible: false,
706				routeStrokeWidth: 2,
707				routeStrokeColor: '0043aeff',
708				routeActiveStrokeWidth: 5,
709				routeActiveStrokeColor: '0043aeff',
710				balloonLayout: balloonLayout,
711				balloonPanelMaxMapArea: 0,
712				balloonOffset: [-3, -25]
713			});
714			shops_map.map.geoObjects.add(shops_map.route);
715		}
716		else {
717			$('.shops_map_shop .route_msg').html('Ââåäèòå àäðåñ èëè îïðåäåëèòå òåêóùåå ìåñòîïîëîæåíèå.');
718		}
719	},
720	scroll_init: function(scroll) {
721		scroll.removeData('jsp').removeAttr('style').removeClass('jspScrollable').html('<div class="scroll_content">' + scroll.find('.scroll_content').html() + '</div>').css({'max-height': (shops_map.scrollHeight - scroll.closest('.layer').find('.title').outerHeight()) + 'px'});
722		scroll.jScrollPane({
723			verticalGutter: 30,
724			scrollbarWidth: 5,
725			mouseWheelSpeed: 50
726		});
727		scroll.find('.jspHorizontalBar').remove();
728		scroll.toggleClass('jspScrollable', scroll.find('.jspVerticalBar').size() == 1);
729	},
730	print_shop: function() {
731		var shop = shops_map.data[shops_map.cityID].shops[shops_map.shopID];
732		var c = shop.coords.split(',');
733		var z = 16;
734		var url = 'http://static-maps.yandex.ru/1.x/?ll='+c[1]+','+c[0]+'&z='+z+'&pt='+c[1]+','+c[0]+',pm2lbl&l=map&size=580,310';
735		var head = '';
736		head += '<link href="css/shops_map.css" rel="stylesheet" type="text/css" media="all" />';
737		head += '<style type="text/css">body { margin: 0; }</style>';
738		var content = '<html><head>' + head + '</head><body>';
739		content += '<div class="shops_map_wrap printable">';
740		content += '<div class="shops_map_shop">';
741		$('.shops_map_shop [data-print]').each(function() {
742			content += '<div class="item">' + $(this).html() + '</div>';
743		});
744		content += '</div>';
745		content += '<div class="shops_map"><img src="' + url + '" /></div>';
746		content += '</div>';
747		content += '</div>';
748		content += '</body></html>';
749		var prwin = window.open('', 'printWin', 'width=940,height=640,toolbar=no,Scrollbars=1');
750		if (typeof prwin == 'object') {
751			prwin.focus();
752			prwin.document.open();
753			prwin.document.write(content);
754			prwin.document.close();
755			img_load(url, function() { prwin.print(); })
756		}
757	}
758};
759
760function uniqueVal(value, index, self) { 
761	return self.indexOf(value) === index;
762}
763
764function sort_object(obj) {
765	var vals = new Array(), res = {};
766	for (var i in obj) {
767		vals.push(i);
768	}
769	vals = vals.sort();
770	for (var i in vals) {
771		res[vals[i]] = obj[vals[i]];
772	}
773	return res;
774}
775
776function img_load(src, callback) {
777	var image = document.createElement('img');
778	image.src = src;
779	if (image.width != 0) {
780		callback();
781	}
782	else {
783		$(image).load(function() {
784			callback();
785		});
786	}
787}

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.