Skip to content

Instantly share code, notes, and snippets.

@7iomka
Created February 4, 2017 11:48
Show Gist options
  • Save 7iomka/16673e3c176d1a2720e09d1b98c216b7 to your computer and use it in GitHub Desktop.
Save 7iomka/16673e3c176d1a2720e09d1b98c216b7 to your computer and use it in GitHub Desktop.
Yandex map list adress with click and focus
/* Start:"a:4:{s:4:"full";s:60:"https://kankan.ru/local/js/controllers/partials/yandex-map.js?148514742316146";s:6:"source";s:44:"/local/js/controllers/partials/yandex-map.js";s:3:"min";s:0:"";s:3:"map";s:0:"";}"*/
(function($, APP) {
'use strict';
/**
* Контроллер Яндекс Карты
**/
APP.Controls.YandexMap = can.Control.extend({
defaults: {
coords: [55.76, 37.64],
address: null,
map: '.js-map',
pinList: '.js-map-pin-list',
pinMapPointBtn: '.js-point-map',
toggleStarter: '.js-schedule-toggle-starter',
toggleBlock: '.js-schedule-button-toggle',
pinListItem: '.js-pin-list-item',
mapToggleItem: '.js-map-toggle-item',
mapToggle: '.js-map-toggle-list',
metroMap: '.js-map-metro',
metroStation: '.js-station'
}
}, {
init: function() {
ymaps.ready(function() {
this.initMap(this.options.coords);
}
.bind(this));
},
initMap: function(coords) {
var elementId = this.element.find(this.options.map).get(0);
this.metroInited = false;
if (typeof this.options.metro == "object" && typeof this.options.metro.SCHEME != 'undefined' && this.options.metro.SCHEME != 'undefined') {
this.options.metro.SCHEME = decodeURIComponent(this.options.metro.SCHEME);
this.initMapToggle();
} else {
this.removeMapToggle();
}
this.contactsMap = new ymaps.Map(elementId,{
center: coords,
zoom: 12,
controls: ['zoomControl', 'searchControl', 'trafficControl']
});
this.addPlacemark(this.options.points, this.contactsMap);
this.createPinList(this.options.points, this.contactsMap);
},
addPlacemark: function(points, map) {
if (points == undefined) {
return false;
}
var myCollection = new ymaps.GeoObjectCollection();
var self = this;
$.each(points, function(i, val) {
var myPlacemark = new ymaps.Placemark([val.LAT, val.LON],{
id: val.CODE,
name: val.NAME,
address: val.ADDRESS,
schedule: val.SCHEDULE,
lat: val.LAT,
lon: val.LON,
metro: val.METRO_STATION,
metroTrim: val.METRO_STATION_TRIM,
button: 'Выбрать метку'
},{
iconLayout: 'default#image',
iconImageHref: '/local/images/pin.png',
iconImageSize: [40, 52],
iconImageOffset: [-20, -52],
hasBalloon: false //balloonContentLayout: BalloonContentLayout
});
myCollection.add(myPlacemark);
myPlacemark.events.add('click', self.onClickListener.bind(self));
});
map.geoObjects.add(myCollection);
map.setBounds(myCollection.getBounds(), {
checkZoomRange: true
});
},
'{pinMapPointBtn} click': function($el) {
this.options.parent.selectPoint($el);
},
createSchedule: function(data) {
var days = {
1: 'Пн.',
2: 'Вт.',
3: 'Ср.',
4: 'Чт.',
5: 'Пт',
6: 'Сб.',
7: 'Вс.'
};
var result = [];
var iTmp = 0;
//debugger;
for (var i in days) {
if (i == 7) {
iTmp = 0;
} else {
iTmp = i;
}
if (data[iTmp] == undefined) {
//выходной
result[days[i]] = 'Выходной';
} else {
result[days[i]] = data[iTmp].Time;
}
}
return result;
},
onClickListener: function(e) {
var point = e.get('target');
//текущую иконку меняем на активную остальные на обычные
var pointId = point.properties.get('id');
if (pointId != undefined) {
var el = this.$pinList.find(this.options.pinListItem).filter('[data-id="' + pointId + '"]');
el.click();
this.$pinList.mCustomScrollbar("scrollTo", el);
}
},
createPinList: function(points, map) {
this.$pinList = this.element.find(this.options.pinList);
var resultItems = '';
var self = this;
this.contactsMap.geoObjects.get(0).each(function(val, i) {
var prop = val.properties.getAll();
var schedule = self.createSchedule(prop.schedule);
var scheduleResult = '';
for (var name in schedule) {
scheduleResult += '<div class="day-wrapper"><div class="day">' + name + '</div><div class="time">' + schedule[name] + '</div></div>';
}
prop.metroTrim = (typeof prop.metroTrim != "undefined" && prop.metroTrim != '') ? prop.metroTrim : null;
resultItems += '<div class="pin-list-item js-pin-list-item" data-geo-index="' + i + '" data-id="' + prop.id + '" data-metro="' + prop.metroTrim + '">' + '<div class="name js-schedule-toggle-starter"><span>' + prop.name + '</span><i class="name-arrow"></i></div>' + '<div class="address">' + prop.address + '</div>' + '<div class="schedule-button-toggle js-schedule-button-toggle">' + '<div class="schedule">' + scheduleResult + '</div>' + '<div class="button-wrapper"><button class="point-map-btn js-point-map"' + 'data-address="' + prop.address + '"' + 'data-id="' + prop.id + '"' + '>Заберу отсюда</button></div>' + '</div>' + '</div>'
});
this.$pinList.html(resultItems);
this.$pinList.mCustomScrollbar({
scrollbarPosition: 'outside',
scrollInertia: 0
});
if (this.options.selectedPoint != undefined && this.options.selectedPoint.val() != '') {
var el = this.$pinList.find(this.options.pinListItem).filter('[data-id="' + this.options.selectedPoint.val() + '"]');
if (el != undefined) {
el.click();
this.$pinList.mCustomScrollbar("scrollTo", el);
}
}
},
setDefaultIcon: function() {
var indexOld = this.$pinList.find(this.options.pinListItem).filter('.active').data('geo-index');
if (indexOld != undefined) {
var optionOld = {
iconImageHref: '/local/images/pin.png',
iconImageSize: [40, 52],
iconImageOffset: [-20, -52],
zIndex: 0
};
var point = this.contactsMap.geoObjects.get(0).get(indexOld);
point.options.set(optionOld);
}
},
'{pinListItem} click': function($el) {
this.setDefaultIcon();
this.$pinList.find(this.options.pinListItem).removeClass('active');
$el.addClass('active');
var point = this.contactsMap.geoObjects.get(0).get($el.data('geo-index'));
if (point != undefined) {
this.contactsMap.setCenter([point.properties.get('lat'), point.properties.get('lon')]);
point.options.set({
iconImageHref: '/local/images/pin-active.png',
iconImageSize: [57, 71],
iconImageOffset: [-28, -71],
zIndex: 999
});
}
},
initMapToggle: function() {
var toggleItem = '<a href="javascript:void(0);" class="js-map-toggle-item map-toggle-item toggle-icon-map active" data-type="map"><span>На карте</span></a><a href="javascript:void(0);" class="js-map-toggle-item map-toggle-item toggle-icon-metro" data-type="metro"><span>На карте метро</span></a>';
this.element.find(this.options.mapToggle).html(toggleItem);
},
removeMapToggle: function() {
this.element.find(this.options.mapToggle).html('');
},
'{mapToggleItem} click': function($el, ev) {
this.element.find(this.options.mapToggleItem).removeClass('active');
$el.addClass('active');
var type = $el.data('type');
switch (type) {
case 'metro':
//show metro map
this.initMetroMap();
this.showMetroMap();
this.showPointWithStation();
this.scrollToActive();
break;
case 'map':
this.clearPointStation();
this.hideMetroMap();
this.scrollToActive();
break;
}
},
'{metroStation} click': function($el, ev) {
this.clearPointStation();
this.showPointStation($el.data('station'));
},
initMetroMap: function() {
var metroMap = this.element.find(this.options.metroMap);
if (metroMap.hasClass('js-inited')) {
return false;
}
metroMap.addClass('show-metro');
this._renderMetroStation(metroMap, this.options.metro);
if (this.element.find('.js-map-inner svg').length) {
this.initScaleDragMap();
}
},
initScaleDragMap: function() {
if (this.metroInited) {
return false;
}
this.resetScale();
this.setZoom(1);
this.setPostion((this.map.width() - this.svgWidth * this.currentScale) / 2, (this.map.height() - this.svgHeight * this.currentScale) / 2);
interact('.js-mapsvg').draggable({
// enable inertial throwing
inertia: false,
// call this function on every dragmove event
onmove: this.dragMoveListener.bind(this),
// call this function on every dragend event
onend: function(event) {}
}).resizable({
preserveAspectRatio: true,
edges: {
left: true,
right: true,
bottom: true,
top: true
}
}).on('tap', function(event) {
$(event.target).closest('.js-station').click();
event.preventDefault();
});
this.metroInited = true;
},
resetScale: function() {
this.map = this.element.find(this.options.metroMap);
this.mapDrag = this.element.find('.js-mapsvg');
this.svg = this.element.find('.js-map-inner svg');
this.scaleElement = this.svg.find('#transform-wrapper');
this.svg.get(0).setAttribute('width', '100%');
this.svg.get(0).setAttribute('height', '100%');
this.svgWidth = this.scaleElement.get(0).getBBox().width;
this.svgHeight = this.scaleElement.get(0).getBBox().height;
var initScaleParam = this.svg.height() < this.svg.width() ? this.svgHeight : this.svgWidth;
var initScaleDiv = this.map.height() < this.map.width() ? this.map.height() : this.map.width();
if (initScaleParam > initScaleDiv) {
this.currentScale = initScaleDiv / (initScaleParam + 80);
} else {
this.currentScale = initScaleParam / (initScaleDiv + 80);
}
},
setZoom: function(scale) {
this.currentScale *= scale;
this.setPostion((this.map.width() - this.svgWidth * this.currentScale) / 2, (this.map.height() - this.svgHeight * this.currentScale) / 2);
var newMatrix = "scale(" + this.currentScale + ", " + this.currentScale + ")";
this.scaleElement.get(0).setAttributeNS(null, "transform", newMatrix);
},
dragMoveListener: function(event) {
var target = event.target;
this.setPostion((parseFloat(target.getAttribute('data-x')) || 0) + event.dx, (parseFloat(target.getAttribute('data-y')) || 0) + event.dy);
},
_renderMetroStation: function(obj, metro) {
//получить список станций у которых есть метро
obj.append('<div class="map-metro-inner js-map-inner">' + '<div class="js-mapsvg map-drag">' + metro.SCHEME + '</div>' + '<div class="zoom-button"><div class="button-plus button js-zoom-plus">+</div><div class="button-minis button js-zoom-minus">-</div></div>' + '</div>');
},
showMetroMap: function() {
this.element.find(this.options.metroMap).addClass('show-metro');
},
hideMetroMap: function() {
this.element.find(this.options.metroMap).removeClass('show-metro');
},
showPointWithStation: function() {
this.$pinList.find(this.options.pinListItem).filter('[data-metro="null"]').hide();
},
showPointStation: function(station) {
this.$pinList.find(this.options.pinListItem).filter('[data-metro!="' + station + '"]').hide();
},
clearPointStation: function() {
this.$pinList.find(this.options.pinListItem).show();
},
scrollToActive: function() {
var el = this.$pinList.find(this.options.pinListItem).filter('.active');
this.$pinList.mCustomScrollbar("scrollTo", el);
},
'.js-zoom-plus click': function() {
this.setZoom(1.25);
},
'.js-zoom-minus click': function() {
this.setZoom(0.8);
},
'{window} resize': function() {
if (typeof this.mapDrag != "undefined") {
setTimeout(function() {
this.resetScale();
this.setZoom(1);
this.setPostion((this.map.width() - this.scaleElement.get(0).getBBox().width * this.currentScale) / 2, (this.map.height() - this.scaleElement.get(0).getBBox().height * this.currentScale) / 2);
}
.bind(this), 100);
}
},
setPostion: function(dx, dy) {
var target = this.mapDrag.get(0)
, // keep the dragged position in the data-x/data-y attributes
x = dx
, y = dy;
// translate the element
target.style.webkitTransform = target.style.transform = 'translate(' + x + 'px, ' + y + 'px)';
// update the posiion attributes
target.setAttribute('data-x', x);
target.setAttribute('data-y', y);
}
});
})(jQuery, window.APP);
/* End */
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment